diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/Makefile.kernel | 2 | ||||
| -rw-r--r-- | linux-core/ati_pcigart.c | 20 | ||||
| -rw-r--r-- | linux-core/drm_compat.c | 1 | ||||
| -rw-r--r-- | linux-core/drm_compat.h | 19 | ||||
| -rw-r--r-- | linux-core/drm_fops.c | 7 | ||||
| -rw-r--r-- | linux-core/drm_irq.c | 2 | ||||
| -rw-r--r-- | linux-core/drm_lock.c | 35 | ||||
| -rw-r--r-- | linux-core/drm_vm.c | 143 | ||||
| -rw-r--r-- | linux-core/drm_vm_nopage_compat.c | 267 | ||||
| -rw-r--r-- | linux-core/i915_drv.c | 8 | ||||
| l--------- | linux-core/radeon_microcode.h | 1 | 
11 files changed, 388 insertions, 117 deletions
| diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 82132ff4..82d200b3 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -14,7 +14,7 @@ drm-objs    := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \  		drm_memory_debug.o ati_pcigart.o drm_sman.o \  		drm_hashtab.o drm_memrange.o drm_object.o drm_compat.o \  	        drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock.o \ -		drm_regman.o drm_gem.o +		drm_regman.o drm_vm_nopage_compat.o drm_gem.o  tdfx-objs   := tdfx_drv.o  r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o  mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c index beaa4424..09251ac3 100644 --- a/linux-core/ati_pcigart.c +++ b/linux-core/ati_pcigart.c @@ -34,6 +34,11 @@  #include "drmP.h"  # define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */ +# define ATI_PCIGART_PAGE_MASK		(~(ATI_PCIGART_PAGE_SIZE-1)) + +#define ATI_PCIE_WRITE 0x4 +#define ATI_PCIE_READ 0x8 +  static int drm_ati_alloc_pcigart_table(struct drm_device *dev,  				       struct drm_ati_pcigart_info *gart_info)  { @@ -103,6 +108,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga  	dma_addr_t bus_address = 0;  	int i, j, ret = 0;  	int max_pages; +	dma_addr_t entry_addr;  	if (!entry) {  		DRM_ERROR("no scatter/gather memory!\n"); @@ -148,23 +154,27 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga  			bus_address = 0;  			goto done;  		} -		page_base = (u32) entry->busaddr[i]; +		entry_addr = entry->busaddr[i];  		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { +			page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;  			switch(gart_info->gart_reg_if) {  			case DRM_ATI_GART_IGP: -				*pci_gart = cpu_to_le32((page_base) | 0xc); +				page_base |= (upper_32_bits(entry_addr) & 0xff) << 4; +				page_base |= 0xc;  				break;  			case DRM_ATI_GART_PCIE: -				*pci_gart = cpu_to_le32((page_base >> 8) | 0xc); +				page_base >>= 8; +				page_base |= (upper_32_bits(entry_addr) & 0xff) << 24; +				page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;  				break;  			default:  			case DRM_ATI_GART_PCI: -				*pci_gart = cpu_to_le32(page_base);  				break;  			} +			*pci_gart = cpu_to_le32(page_base);  			pci_gart++; -			page_base += ATI_PCIGART_PAGE_SIZE; +			entry_addr += ATI_PCIGART_PAGE_SIZE;  		}  	} diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index 23e5028a..3d082e7e 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -758,3 +758,4 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,  EXPORT_SYMBOL(kmap_atomic_prot_pfn);  #endif + diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h index 3b1287e1..30834f33 100644 --- a/linux-core/drm_compat.h +++ b/linux-core/drm_compat.h @@ -343,4 +343,23 @@ extern void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,  #define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : (1ULL<<(n)) - 1)  #endif +#ifndef VM_CAN_NONLINEAR +#define DRM_VM_NOPAGE 1 +#endif + +#ifdef DRM_VM_NOPAGE + +extern struct page *drm_vm_nopage(struct vm_area_struct *vma, +				  unsigned long address, int *type); + +extern struct page *drm_vm_shm_nopage(struct vm_area_struct *vma, +				      unsigned long address, int *type); + +extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma, +				      unsigned long address, int *type); + +extern struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, +				     unsigned long address, int *type); +#endif +  #endif diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index c42bfaab..ec521101 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -376,7 +376,6 @@ int drm_release(struct inode *inode, struct file *filp)  	struct drm_file *file_priv = filp->private_data;  	struct drm_device *dev = file_priv->minor->dev;  	int retcode = 0; -	unsigned long irqflags;  	lock_kernel(); @@ -407,11 +406,9 @@ int drm_release(struct inode *inode, struct file *filp)  			 */  			do{ -				spin_lock_irqsave(&dev->lock.spinlock, -						  irqflags); +				spin_lock_bh(&dev->lock.spinlock);  				locked = dev->lock.idle_has_lock; -				spin_unlock_irqrestore(&dev->lock.spinlock, -						       irqflags); +				spin_unlock_bh(&dev->lock.spinlock);  				if (locked)  					break;  				schedule(); diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index 592ea2ad..8f27d7f3 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -437,7 +437,7 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,  	int crtc, ret = 0;  	u32 new; -	crtc = modeset->arg; +	crtc = modeset->crtc;  	if (crtc >= dev->num_crtcs) {  		ret = -EINVAL;  		goto out; diff --git a/linux-core/drm_lock.c b/linux-core/drm_lock.c index ad7c1679..58c5f08d 100644 --- a/linux-core/drm_lock.c +++ b/linux-core/drm_lock.c @@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  	DECLARE_WAITQUEUE(entry, current);  	struct drm_lock *lock = data;  	int ret = 0; -	unsigned long irqflags;  	++file_priv->lock_count; @@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  			return -EINVAL;  	add_wait_queue(&dev->lock.lock_queue, &entry); -	spin_lock_irqsave(&dev->lock.spinlock, irqflags); +	spin_lock_bh(&dev->lock.spinlock);  	dev->lock.user_waiters++; -	spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); +	spin_unlock_bh(&dev->lock.spinlock);  	for (;;) {  		__set_current_state(TASK_INTERRUPTIBLE);  		if (!dev->lock.hw_lock) { @@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  			break;  		}  	} -	spin_lock_irqsave(&dev->lock.spinlock, irqflags); +	spin_lock_bh(&dev->lock.spinlock);  	dev->lock.user_waiters--; -	spin_unlock_irqrestore(&dev->lock.spinlock, irqflags); +	spin_unlock_bh(&dev->lock.spinlock);  	__set_current_state(TASK_RUNNING);  	remove_wait_queue(&dev->lock.lock_queue, &entry); @@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data,  {  	unsigned int old, new, prev;  	volatile unsigned int *lock = &lock_data->hw_lock->lock; -	unsigned long irqflags; -	spin_lock_irqsave(&lock_data->spinlock, irqflags); +	spin_lock_bh(&lock_data->spinlock);  	do {  		old = *lock;  		if (old & _DRM_LOCK_HELD) @@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,  		}  		prev = cmpxchg(lock, old, new);  	} while (prev != old); -	spin_unlock_irqrestore(&lock_data->spinlock, irqflags); +	spin_unlock_bh(&lock_data->spinlock);  	/* Warn on recursive locking of user contexts. */  	if (_DRM_LOCKING_CONTEXT(old) == context && _DRM_LOCK_IS_HELD(old)) { @@ -269,16 +267,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)  {  	unsigned int old, new, prev;  	volatile unsigned int *lock = &lock_data->hw_lock->lock; -	unsigned long irqflags; -	spin_lock_irqsave(&lock_data->spinlock, irqflags); +	spin_lock_bh(&lock_data->spinlock);  	if (lock_data->kernel_waiters != 0) {  		drm_lock_transfer(lock_data, 0);  		lock_data->idle_has_lock = 1; -		spin_unlock_irqrestore(&lock_data->spinlock, irqflags); +		spin_unlock_bh(&lock_data->spinlock);  		return 1;  	} -	spin_unlock_irqrestore(&lock_data->spinlock, irqflags); +	spin_unlock_bh(&lock_data->spinlock);  	do {  		old = *lock; @@ -342,20 +339,19 @@ static int drm_notifier(void *priv)  void drm_idlelock_take(struct drm_lock_data *lock_data)  {  	int ret = 0; -	unsigned long irqflags; -	spin_lock_irqsave(&lock_data->spinlock, irqflags); +	spin_lock_bh(&lock_data->spinlock);  	lock_data->kernel_waiters++;  	if (!lock_data->idle_has_lock) { -		spin_unlock_irqrestore(&lock_data->spinlock, irqflags); +		spin_unlock_bh(&lock_data->spinlock);  		ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); -		spin_lock_irqsave(&lock_data->spinlock, irqflags); +		spin_lock_bh(&lock_data->spinlock);  		if (ret == 1)  			lock_data->idle_has_lock = 1;  	} -	spin_unlock_irqrestore(&lock_data->spinlock, irqflags); +	spin_unlock_bh(&lock_data->spinlock);  }  EXPORT_SYMBOL(drm_idlelock_take); @@ -363,9 +359,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)  {  	unsigned int old, prev;  	volatile unsigned int *lock = &lock_data->hw_lock->lock; -	unsigned long irqflags; -	spin_lock_irqsave(&lock_data->spinlock, irqflags); +	spin_lock_bh(&lock_data->spinlock);  	if (--lock_data->kernel_waiters == 0) {  		if (lock_data->idle_has_lock) {  			do { @@ -376,7 +371,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)  			lock_data->idle_has_lock = 0;  		}  	} -	spin_unlock_irqrestore(&lock_data->spinlock, irqflags); +	spin_unlock_bh(&lock_data->spinlock);  }  EXPORT_SYMBOL(drm_idlelock_release); diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index cabfb8f4..6618c0ae 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -81,8 +81,9 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)  	return tmp;  } +#ifndef DRM_VM_NOPAGE  /** - * \c nopage method for AGP virtual memory. + * \c fault method for AGP virtual memory.   *   * \param vma virtual memory area.   * \param address access address. @@ -92,8 +93,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)   * map, get the page, increment the use count and return it.   */  #if __OS_HAS_AGP -static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, -						unsigned long address) +static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  {  	struct drm_file *priv = vma->vm_file->private_data;  	struct drm_device *dev = priv->minor->dev; @@ -105,19 +105,24 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,  	 * Find the right map  	 */  	if (!drm_core_has_AGP(dev)) -		goto vm_nopage_error; +		goto vm_fault_error;  	if (!dev->agp || !dev->agp->cant_use_aperture) -		goto vm_nopage_error; +		goto vm_fault_error;  	if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) -		goto vm_nopage_error; +		goto vm_fault_error;  	r_list = drm_hash_entry(hash, struct drm_map_list, hash);  	map = r_list->map;  	if (map && map->type == _DRM_AGP) { -		unsigned long offset = address - vma->vm_start; +		/* +		 * Using vm_pgoff as a selector forces us to use this unusual +		 * addressing scheme. +		 */ +		unsigned long offset = (unsigned long)vmf->virtual_address - +								vma->vm_start;  		unsigned long baddr = map->offset + offset;  		struct drm_agp_mem *agpmem;  		struct page *page; @@ -139,7 +144,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,  		}  		if (!agpmem) -			goto vm_nopage_error; +			goto vm_fault_error;  		/*  		 * Get the page, inc the use count, and return it @@ -147,25 +152,21 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,  		offset = (baddr - agpmem->bound) >> PAGE_SHIFT;  		page = virt_to_page(__va(agpmem->memory->memory[offset]));  		get_page(page); +		vmf->page = page; -#if 0 -		/* page_count() not defined everywhere */  		DRM_DEBUG  		    ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",  		     baddr, __va(agpmem->memory->memory[offset]), offset,  		     page_count(page)); -#endif - -		return page; +		return 0;  	} -      vm_nopage_error: -	return NOPAGE_SIGBUS;	/* Disallow mremap */ +vm_fault_error: +	return VM_FAULT_SIGBUS;	/* Disallow mremap */  }  #else				/* __OS_HAS_AGP */ -static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, -						unsigned long address) +static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  { -	return NOPAGE_SIGBUS; +	return VM_FAULT_SIGBUS;  }  #endif				/* __OS_HAS_AGP */ @@ -179,29 +180,28 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,   * Get the mapping, find the real physical page to map, get the page, and   * return it.   */ -static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, -						    unsigned long address) +static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  {  	struct drm_map *map = (struct drm_map *) vma->vm_private_data;  	unsigned long offset;  	unsigned long i;  	struct page *page; -	if (address > vma->vm_end) -		return NOPAGE_SIGBUS;	/* Disallow mremap */  	if (!map) -		return NOPAGE_SIGBUS;	/* Nothing allocated */ +		return VM_FAULT_SIGBUS;	/* Nothing allocated */ -	offset = address - vma->vm_start; +	offset = (unsigned long)vmf->virtual_address - vma->vm_start;  	i = (unsigned long)map->handle + offset;  	page = vmalloc_to_page((void *)i);  	if (!page) -		return NOPAGE_SIGBUS; +		return VM_FAULT_SIGBUS;  	get_page(page); +	vmf->page = page; -	DRM_DEBUG("0x%lx\n", address); -	return page; +	DRM_DEBUG("shm_fault 0x%lx\n", offset); +	return 0;  } +#endif  /**   * \c close method for shared virtual memory. @@ -283,8 +283,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)  	mutex_unlock(&dev->struct_mutex);  } +#ifndef DRM_VM_NOPAGE  /** - * \c nopage method for DMA virtual memory. + * \c fault method for DMA virtual memory.   *   * \param vma virtual memory area.   * \param address access address. @@ -292,8 +293,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)   *   * Determine the page number from the page offset and get it from drm_device_dma::pagelist.   */ -static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, -						    unsigned long address) +static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  {  	struct drm_file *priv = vma->vm_file->private_data;  	struct drm_device *dev = priv->minor->dev; @@ -303,24 +303,23 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,  	struct page *page;  	if (!dma) -		return NOPAGE_SIGBUS;	/* Error */ -	if (address > vma->vm_end) -		return NOPAGE_SIGBUS;	/* Disallow mremap */ +		return VM_FAULT_SIGBUS;	/* Error */  	if (!dma->pagelist) -		return NOPAGE_SIGBUS;	/* Nothing allocated */ +		return VM_FAULT_SIGBUS;	/* Nothing allocated */ -	offset = address - vma->vm_start;	/* vm_[pg]off[set] should be 0 */ -	page_nr = offset >> PAGE_SHIFT; +	offset = (unsigned long)vmf->virtual_address - vma->vm_start;	/* vm_[pg]off[set] should be 0 */ +	page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */  	page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));  	get_page(page); +	vmf->page = page; -	DRM_DEBUG("0x%lx (page %lu)\n", address, page_nr); -	return page; +	DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr); +	return 0;  }  /** - * \c nopage method for scatter-gather virtual memory. + * \c fault method for scatter-gather virtual memory.   *   * \param vma virtual memory area.   * \param address access address. @@ -328,8 +327,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,   *   * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.   */ -static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, -						   unsigned long address) +static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  {  	struct drm_map *map = (struct drm_map *) vma->vm_private_data;  	struct drm_file *priv = vma->vm_file->private_data; @@ -340,80 +338,62 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,  	unsigned long page_offset;  	struct page *page; -	DRM_DEBUG("\n");  	if (!entry) -		return NOPAGE_SIGBUS;	/* Error */ -	if (address > vma->vm_end) -		return NOPAGE_SIGBUS;	/* Disallow mremap */ +		return VM_FAULT_SIGBUS;	/* Error */  	if (!entry->pagelist) -		return NOPAGE_SIGBUS;	/* Nothing allocated */ +		return VM_FAULT_SIGBUS;	/* Nothing allocated */ -	offset = address - vma->vm_start; +	offset = (unsigned long)vmf->virtual_address - vma->vm_start;  	map_offset = map->offset - (unsigned long)dev->sg->virtual;  	page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);  	page = entry->pagelist[page_offset];  	get_page(page); +	vmf->page = page; -	return page; -} - -static struct page *drm_vm_nopage(struct vm_area_struct *vma, -				  unsigned long address, int *type) -{ -	if (type) -		*type = VM_FAULT_MINOR; -	return drm_do_vm_nopage(vma, address); -} - -static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma, -				      unsigned long address, int *type) -{ -	if (type) -		*type = VM_FAULT_MINOR; -	return drm_do_vm_shm_nopage(vma, address); -} - -static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma, -				      unsigned long address, int *type) -{ -	if (type) -		*type = VM_FAULT_MINOR; -	return drm_do_vm_dma_nopage(vma, address); -} - -static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, -				     unsigned long address, int *type) -{ -	if (type) -		*type = VM_FAULT_MINOR; -	return drm_do_vm_sg_nopage(vma, address); +	return 0;  } - +#endif  /** AGP virtual memory operations */  static struct vm_operations_struct drm_vm_ops = { +#ifdef DRM_VM_NOPAGE  	.nopage = drm_vm_nopage, +#else +	.fault = drm_do_vm_fault, +#endif  	.open = drm_vm_open,  	.close = drm_vm_close,  };  /** Shared virtual memory operations */  static struct vm_operations_struct drm_vm_shm_ops = { +#ifdef DRM_VM_NOPAGE  	.nopage = drm_vm_shm_nopage, +#else +	.fault = drm_do_vm_shm_fault, +#endif  	.open = drm_vm_open,  	.close = drm_vm_shm_close,  };  /** DMA virtual memory operations */  static struct vm_operations_struct drm_vm_dma_ops = { +#ifdef DRM_VM_NOPAGE  	.nopage = drm_vm_dma_nopage, +#else +	.fault = drm_do_vm_dma_fault, +#endif  	.open = drm_vm_open,  	.close = drm_vm_close,  };  /** Scatter-gather virtual memory operations */  static struct vm_operations_struct drm_vm_sg_ops = { +#ifdef DRM_VM_NOPAGE  	.nopage = drm_vm_sg_nopage, +#else +	.fault = drm_do_vm_sg_fault, +#endif  	.open = drm_vm_open,  	.close = drm_vm_close,  }; @@ -751,6 +731,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma,  	err = drm_bo_wait(bo, 0, 1, 0, 1);  	if (err) {  		ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; +		bo->priv_flags &= ~_DRM_BO_FLAG_UNLOCKED;  		goto out_unlock;  	} diff --git a/linux-core/drm_vm_nopage_compat.c b/linux-core/drm_vm_nopage_compat.c new file mode 100644 index 00000000..be8d6c1c --- /dev/null +++ b/linux-core/drm_vm_nopage_compat.c @@ -0,0 +1,267 @@ +/** + * \file drm_vm.c + * Memory mapping for DRM + * + * \author Rickard E. (Rik) Faith <faith@valinux.com> + * \author Gareth Hughes <gareth@valinux.com> + */ + +/* + * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" + +#ifdef DRM_VM_NOPAGE +/** + * \c nopage method for AGP virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \return pointer to the page structure. + * + * Find the right map and if it's AGP memory find the real physical page to + * map, get the page, increment the use count and return it. + */ +#if __OS_HAS_AGP +static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, +						unsigned long address) +{ +	struct drm_file *priv = vma->vm_file->private_data; +	struct drm_device *dev = priv->minor->dev; +	struct drm_map *map = NULL; +	struct drm_map_list *r_list; +	struct drm_hash_item *hash; + +	/* +	 * Find the right map +	 */ +	if (!drm_core_has_AGP(dev)) +		goto vm_nopage_error; + +	if (!dev->agp || !dev->agp->cant_use_aperture) +		goto vm_nopage_error; + +	if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) +		goto vm_nopage_error; + +	r_list = drm_hash_entry(hash, struct drm_map_list, hash); +	map = r_list->map; + +	if (map && map->type == _DRM_AGP) { +		unsigned long offset = address - vma->vm_start; +		unsigned long baddr = map->offset + offset; +		struct drm_agp_mem *agpmem; +		struct page *page; + +#ifdef __alpha__ +		/* +		 * Adjust to a bus-relative address +		 */ +		baddr -= dev->hose->mem_space->start; +#endif + +		/* +		 * It's AGP memory - find the real physical page to map +		 */ +		list_for_each_entry(agpmem, &dev->agp->memory, head) { +			if (agpmem->bound <= baddr && +			    agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) +				break; +		} + +		if (!agpmem) +			goto vm_nopage_error; + +		/* +		 * Get the page, inc the use count, and return it +		 */ +		offset = (baddr - agpmem->bound) >> PAGE_SHIFT; +		page = virt_to_page(__va(agpmem->memory->memory[offset])); +		get_page(page); + +#if 0 +		/* page_count() not defined everywhere */ +		DRM_DEBUG +		    ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", +		     baddr, __va(agpmem->memory->memory[offset]), offset, +		     page_count(page)); +#endif + +		return page; +	} +      vm_nopage_error: +	return NOPAGE_SIGBUS;	/* Disallow mremap */ +} +#else				/* __OS_HAS_AGP */ +static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, +						unsigned long address) +{ +	return NOPAGE_SIGBUS; +} +#endif				/* __OS_HAS_AGP */ + +/** + * \c nopage method for shared virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \return pointer to the page structure. + * + * Get the mapping, find the real physical page to map, get the page, and + * return it. + */ +static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, +						    unsigned long address) +{ +	struct drm_map *map = (struct drm_map *) vma->vm_private_data; +	unsigned long offset; +	unsigned long i; +	struct page *page; + +	if (address > vma->vm_end) +		return NOPAGE_SIGBUS;	/* Disallow mremap */ +	if (!map) +		return NOPAGE_SIGBUS;	/* Nothing allocated */ + +	offset = address - vma->vm_start; +	i = (unsigned long)map->handle + offset; +	page = vmalloc_to_page((void *)i); +	if (!page) +		return NOPAGE_SIGBUS; +	get_page(page); + +	DRM_DEBUG("0x%lx\n", address); +	return page; +} + +/** + * \c nopage method for DMA virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \return pointer to the page structure. + * + * Determine the page number from the page offset and get it from drm_device_dma::pagelist. + */ +static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, +						    unsigned long address) +{ +	struct drm_file *priv = vma->vm_file->private_data; +	struct drm_device *dev = priv->minor->dev; +	struct drm_device_dma *dma = dev->dma; +	unsigned long offset; +	unsigned long page_nr; +	struct page *page; + +	if (!dma) +		return NOPAGE_SIGBUS;	/* Error */ +	if (address > vma->vm_end) +		return NOPAGE_SIGBUS;	/* Disallow mremap */ +	if (!dma->pagelist) +		return NOPAGE_SIGBUS;	/* Nothing allocated */ + +	offset = address - vma->vm_start;	/* vm_[pg]off[set] should be 0 */ +	page_nr = offset >> PAGE_SHIFT; +	page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK)))); + +	get_page(page); + +	DRM_DEBUG("0x%lx (page %lu)\n", address, page_nr); +	return page; +} + +/** + * \c nopage method for scatter-gather virtual memory. + * + * \param vma virtual memory area. + * \param address access address. + * \return pointer to the page structure. + * + * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. + */ +static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, +						   unsigned long address) +{ +	struct drm_map *map = (struct drm_map *) vma->vm_private_data; +	struct drm_file *priv = vma->vm_file->private_data; +	struct drm_device *dev = priv->minor->dev; +	struct drm_sg_mem *entry = dev->sg; +	unsigned long offset; +	unsigned long map_offset; +	unsigned long page_offset; +	struct page *page; + +	DRM_DEBUG("\n"); +	if (!entry) +		return NOPAGE_SIGBUS;	/* Error */ +	if (address > vma->vm_end) +		return NOPAGE_SIGBUS;	/* Disallow mremap */ +	if (!entry->pagelist) +		return NOPAGE_SIGBUS;	/* Nothing allocated */ + +	offset = address - vma->vm_start; +	map_offset = map->offset - (unsigned long)dev->sg->virtual; +	page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); +	page = entry->pagelist[page_offset]; +	get_page(page); + +	return page; +} + + +struct page *drm_vm_nopage(struct vm_area_struct *vma, +			   unsigned long address, int *type) +{ +	if (type) +		*type = VM_FAULT_MINOR; +	return drm_do_vm_nopage(vma, address); +} + +struct page *drm_vm_shm_nopage(struct vm_area_struct *vma, +			       unsigned long address, int *type) +{ +	if (type) +		*type = VM_FAULT_MINOR; +	return drm_do_vm_shm_nopage(vma, address); +} + +struct page *drm_vm_dma_nopage(struct vm_area_struct *vma, +			       unsigned long address, int *type) +{ +	if (type) +		*type = VM_FAULT_MINOR; +	return drm_do_vm_dma_nopage(vma, address); +} + +struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, +			      unsigned long address, int *type) +{ +	if (type) +		*type = VM_FAULT_MINOR; +	return drm_do_vm_sg_nopage(vma, address); +} +#endif diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index a50ee53c..3f246a08 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -172,7 +172,7 @@ static void i915_save_vga(struct drm_device *dev)  	i915_write_indexed(cr_index, cr_data, 0x11,  			   i915_read_indexed(cr_index, cr_data, 0x11) &  			   (~0x80)); -	for (i = 0; i < 0x24; i++) +	for (i = 0; i <= 0x24; i++)  		dev_priv->saveCR[i] =  			i915_read_indexed(cr_index, cr_data, i);  	/* Make sure we don't turn off CR group 0 writes */ @@ -181,7 +181,7 @@ static void i915_save_vga(struct drm_device *dev)  	/* Attribute controller registers */  	inb(st01);  	dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX); -	for (i = 0; i < 20; i++) +	for (i = 0; i <= 0x14; i++)  		dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);  	inb(st01);  	outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX); @@ -231,7 +231,7 @@ static void i915_restore_vga(struct drm_device *dev)  	/* CRT controller regs */  	/* Enable CR group 0 writes */  	i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]); -	for (i = 0; i < 0x24; i++) +	for (i = 0; i <= 0x24; i++)  		i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);  	/* Graphics controller regs */ @@ -248,7 +248,7 @@ static void i915_restore_vga(struct drm_device *dev)  	/* Attribute controller registers */  	inb(st01); /* switch back to index mode */ -	for (i = 0; i < 20; i++) +	for (i = 0; i <= 0x14; i++)  		i915_write_ar(st01, i, dev_priv->saveAR[i], 0);  	inb(st01); /* switch back to index mode */  	outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX); diff --git a/linux-core/radeon_microcode.h b/linux-core/radeon_microcode.h new file mode 120000 index 00000000..709fff30 --- /dev/null +++ b/linux-core/radeon_microcode.h @@ -0,0 +1 @@ +../shared-core/radeon_microcode.h
\ No newline at end of file | 
