aboutsummaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/Makefile.kernel2
-rw-r--r--linux-core/ati_pcigart.c20
-rw-r--r--linux-core/drm_compat.c1
-rw-r--r--linux-core/drm_compat.h19
-rw-r--r--linux-core/drm_fops.c7
-rw-r--r--linux-core/drm_irq.c2
-rw-r--r--linux-core/drm_lock.c35
-rw-r--r--linux-core/drm_vm.c143
-rw-r--r--linux-core/drm_vm_nopage_compat.c267
-rw-r--r--linux-core/i915_drv.c8
l---------linux-core/radeon_microcode.h1
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