summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h27
-rw-r--r--linux-core/drm_bufs.c80
-rw-r--r--linux-core/drm_context.c15
-rw-r--r--linux-core/drm_ioctl.c2
-rw-r--r--linux-core/drm_proc.c6
-rw-r--r--linux-core/drm_scatter.c11
-rw-r--r--linux-core/drm_vm.c22
-rw-r--r--linux-core/i810_dma.c1
-rw-r--r--linux-core/i830_dma.c1
-rw-r--r--linux-core/mga_ioc32.c68
10 files changed, 178 insertions, 55 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 2b4dbcf6..4f677471 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -100,12 +100,13 @@
#define DRIVER_USE_MTRR 0x4
#define DRIVER_PCI_DMA 0x8
#define DRIVER_SG 0x10
-#define DRIVER_FB_DMA 0x20
-#define DRIVER_HAVE_DMA 0x40
-#define DRIVER_HAVE_IRQ 0x80
-#define DRIVER_IRQ_SHARED 0x100
-#define DRIVER_IRQ_VBL 0x200
-#define DRIVER_DMA_QUEUE 0x400
+#define DRIVER_HAVE_DMA 0x20
+#define DRIVER_HAVE_IRQ 0x40
+#define DRIVER_IRQ_SHARED 0x80
+#define DRIVER_IRQ_VBL 0x100
+#define DRIVER_DMA_QUEUE 0x200
+#define DRIVER_FB_DMA 0x400
+
/*@}*/
@@ -499,6 +500,7 @@ typedef struct drm_dma_handle {
typedef struct drm_map_list {
struct list_head head; /**< list head */
drm_map_t *map; /**< mapping */
+ unsigned int user_token;
} drm_map_list_t;
typedef drm_map_t drm_local_map_t;
@@ -729,6 +731,7 @@ typedef struct drm_device {
struct drm_driver *driver;
drm_local_map_t *agp_buffer_map;
+ unsigned int agp_buffer_token;
drm_head_t primary; /**< primary screen head */
} drm_device_t;
@@ -1019,16 +1022,12 @@ static __inline__ void drm_core_ioremapfree(struct drm_map *map,
}
static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
- unsigned long offset)
+ unsigned int token)
{
- struct list_head *_list;
- list_for_each(_list, &dev->maplist->head) {
- drm_map_list_t *_entry =
- list_entry(_list, drm_map_list_t, head);
- if (_entry->map && _entry->map->offset == offset) {
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head, head)
+ if (_entry->user_token == token)
return _entry->map;
- }
- }
return NULL;
}
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index 416d7d8c..bad02f2d 100644
--- a/linux-core/drm_bufs.c
+++ b/linux-core/drm_bufs.c
@@ -56,8 +56,7 @@ static drm_local_map_t *drm_find_matching_map(drm_device_t *dev,
list_for_each(list, &dev->maplist->head) {
drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
if (entry->map && map->type == entry->map->type &&
- ((entry->map->offset == map->offset) ||
- (map->type == _DRM_SHM))) {
+ entry->map->offset == map->offset) {
return entry->map;
}
}
@@ -65,13 +64,42 @@ static drm_local_map_t *drm_find_matching_map(drm_device_t *dev,
return NULL;
}
-#ifdef CONFIG_COMPAT
+
/*
- * Used to allocate 32-bit handles for _DRM_SHM regions
- * The 0x10000000 value is chosen to be out of the way of
- * FB/register and GART physical addresses.
+ * Used to allocate 32-bit handles for mappings.
*/
-static unsigned int map32_handle = 0x10000000;
+#define START_RANGE 0x10000000
+#define END_RANGE 0x40000000
+
+#ifdef _LP64
+static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev)
+{
+ static unsigned int map32_handle = START_RANGE;
+ unsigned int hash;
+
+ if (lhandle & 0xffffffff00000000) {
+ hash = map32_handle;
+ map32_handle += PAGE_SIZE;
+ if (map32_handle > END_RANGE)
+ map32_handle = START_RANGE;
+ } else
+ hash = lhandle;
+
+ while (1) {
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head,head) {
+ if (_entry->user_token == hash)
+ break;
+ }
+ if (&_entry->head == &dev->maplist->head)
+ return hash;
+
+ hash += PAGE_SIZE;
+ map32_handle += PAGE_SIZE;
+ }
+}
+#else
+# define HandleID(x,dev) (unsigned int)(x)
#endif
/**
@@ -228,7 +256,7 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
}
- map->offset += dev->sg->handle;
+ map->offset += (unsigned long)dev->sg->virtual;
break;
case _DRM_CONSISTENT: {
/* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G.
@@ -260,13 +288,11 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
down(&dev->struct_sem);
list_add(&list->head, &dev->maplist->head);
-#ifdef CONFIG_COMPAT
- /* Assign a 32-bit handle for _DRM_SHM mappings */
+ /* Assign a 32-bit handle */
/* We do it here so that dev->struct_sem protects the increment */
- if (map->type == _DRM_SHM)
- map->offset = map32_handle += PAGE_SIZE;
-#endif
-
+ list->user_token = HandleID(map->type==_DRM_SHM
+ ? (unsigned long)map->handle
+ : map->offset, dev);
up(&dev->struct_sem);
*map_ptr = map;
@@ -283,6 +309,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
drm_map_t *map_ptr;
drm_map_t __user *argp = (void __user *)arg;
int err;
+ unsigned long handle = 0;
if (!(filp->f_mode & 3))
return -EACCES; /* Require read/write */
@@ -301,13 +328,20 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
return err;
}
- if (copy_to_user(argp, map_ptr, sizeof(*map_ptr)))
- return -EFAULT;
- if (map_ptr->type != _DRM_SHM) {
- if (copy_to_user(&argp->handle,
- &map_ptr->offset, sizeof(map_ptr->offset)))
+ {
+ drm_map_list_t *_entry;
+ list_for_each_entry(_entry, &dev->maplist->head, head) {
+ if (_entry->map == map_ptr)
+ handle = _entry->user_token;
+ }
+ if (!handle)
return -EFAULT;
}
+
+ if (copy_to_user(argp, map_ptr, sizeof(*map_ptr)))
+ return -EFAULT;
+ if (put_user(handle, &argp->handle))
+ return -EFAULT;
return 0;
}
@@ -422,7 +456,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
if (r_list->map &&
- r_list->map->handle == request.handle &&
+ r_list->user_token == (unsigned long) request.handle &&
r_list->map->flags & _DRM_REMOVABLE) {
map = r_list->map;
break;
@@ -991,7 +1025,8 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
buf->offset = (dma->byte_count + offset);
buf->bus_address = agp_offset + offset;
- buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+ buf->address = (void *)(agp_offset + offset
+ + (unsigned long)dev->sg->virtual);
buf->next = NULL;
buf->waiting = 0;
buf->pending = 0;
@@ -1517,6 +1552,7 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
|| (drm_core_check_feature(dev, DRIVER_FB_DMA)
&& (dma->flags & _DRM_DMA_USE_FB))) {
drm_map_t *map = dev->agp_buffer_map;
+ unsigned long token = dev->agp_buffer_token;
if (!map) {
retcode = -EINVAL;
@@ -1530,7 +1566,7 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
virtual = do_mmap(filp, 0, map->size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
- (unsigned long)map->offset);
+ token);
#if LINUX_VERSION_CODE <= 0x020402
up(&current->mm->mmap_sem);
#else
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c
index baa8437d..5947c8e6 100644
--- a/linux-core/drm_context.c
+++ b/linux-core/drm_context.c
@@ -217,6 +217,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
drm_ctx_priv_map_t __user *argp = (void __user *)arg;
drm_ctx_priv_map_t request;
drm_map_t *map;
+ drm_map_list_t *_entry;
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
@@ -231,7 +232,16 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
map = dev->context_sareas[request.ctx_id];
up(&dev->struct_sem);
- request.handle = map->handle;
+ request.handle = 0;
+ list_for_each_entry(_entry, &dev->maplist->head,head) {
+ if (_entry->map == map) {
+ request.handle = (void *)(unsigned long)_entry->user_token;
+ break;
+ }
+ }
+ if (request.handle == 0)
+ return -EINVAL;
+
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return 0;
@@ -266,7 +276,8 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
down(&dev->struct_sem);
list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
- if (r_list->map && r_list->map->handle == request.handle)
+ if (r_list->map
+ && r_list->user_token == (unsigned long) request.handle)
goto found;
}
bad:
diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c
index eac89ea6..e0998d53 100644
--- a/linux-core/drm_ioctl.c
+++ b/linux-core/drm_ioctl.c
@@ -211,7 +211,7 @@ int drm_getmap(struct inode *inode, struct file *filp,
map.size = r_list->map->size;
map.type = r_list->map->type;
map.flags = r_list->map->flags;
- map.handle = r_list->map->handle;
+ map.handle = (void *)(unsigned long) r_list->user_token;
map.mtrr = r_list->map->mtrr;
up(&dev->struct_sem);
diff --git a/linux-core/drm_proc.c b/linux-core/drm_proc.c
index 94aea2b7..3e2b3ba0 100644
--- a/linux-core/drm_proc.c
+++ b/linux-core/drm_proc.c
@@ -238,11 +238,13 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
type = "??";
else
type = types[map->type];
- DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
+ DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ",
i,
map->offset,
map->size,
- type, map->flags, (unsigned long)map->handle);
+ type, map->flags,
+ r_list->user_token);
+
if (map->mtrr < 0) {
DRM_PROC_PRINT("none\n");
} else {
diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c
index 342e7572..1647303d 100644
--- a/linux-core/drm_scatter.c
+++ b/linux-core/drm_scatter.c
@@ -58,6 +58,12 @@ void drm_sg_cleanup(drm_sg_mem_t * entry)
drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
}
+#ifdef _LP64
+# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
+#else
+# define ScatterHandle(x) (unsigned int)(x)
+#endif
+
int drm_sg_alloc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -125,12 +131,13 @@ int drm_sg_alloc(struct inode *inode, struct file *filp,
*/
memset(entry->virtual, 0, pages << PAGE_SHIFT);
- entry->handle = (unsigned long)entry->virtual;
+ entry->handle = ScatterHandle((unsigned long)entry->virtual);
DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
DRM_DEBUG("sg alloc virtual = %p\n", entry->virtual);
- for (i = entry->handle, j = 0; j < pages; i += PAGE_SIZE, j++) {
+ for (i = (unsigned long)entry->virtual, j = 0; j < pages;
+ i += PAGE_SIZE, j++) {
entry->pagelist[j] = vmalloc_to_page((void *)i);
if (!entry->pagelist[j])
goto failed;
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index 227dc663..b253991f 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -75,13 +75,13 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
map = r_list->map;
if (!map)
continue;
- if (map->offset == VM_OFFSET(vma))
+ if (r_list->user_token == VM_OFFSET(vma))
break;
}
if (map && map->type == _DRM_AGP) {
unsigned long offset = address - vma->vm_start;
- unsigned long baddr = VM_OFFSET(vma) + offset;
+ unsigned long baddr = map->offset + offset;
struct drm_agp_mem *agpmem;
struct page *page;
@@ -319,7 +319,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
return NOPAGE_OOM; /* Nothing allocated */
offset = address - vma->vm_start;
- map_offset = map->offset - dev->sg->handle;
+ 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);
@@ -586,14 +586,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
for performance, even if the list was a
bit longer. */
list_for_each(list, &dev->maplist->head) {
- unsigned long off;
r_list = list_entry(list, drm_map_list_t, head);
map = r_list->map;
if (!map)
continue;
- off = dev->driver->get_map_ofs(map);
- if (off == VM_OFFSET(vma))
+ if (r_list->user_token == VM_OFFSET(vma))
break;
}
@@ -636,7 +634,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
/* fall through to _DRM_FRAME_BUFFER... */
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
- if (VM_OFFSET(vma) >= __pa(high_memory)) {
+ if (map->offset >= __pa(high_memory)) {
#if defined(__i386__) || defined(__x86_64__)
if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
@@ -659,13 +657,13 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
#endif
offset = dev->driver->get_reg_ofs(dev);
#ifdef __sparc__
- if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
- VM_OFFSET(vma) + offset,
+ if (io_remap_pfn_range(vma, vma->vm_start,
+ (map->offset + offset) >>PAGE_SHIFT,
vma->vm_end - vma->vm_start,
- vma->vm_page_prot, 0))
+ vma->vm_page_prot))
#else
if (remap_pfn_range(vma, vma->vm_start,
- (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
+ (map->offset + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
#endif
@@ -673,7 +671,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
" offset = 0x%lx\n",
map->type,
- vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
+ vma->vm_start, vma->vm_end, map->offset + offset);
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_SHM:
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 9e0634a5..2f0484ee 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -373,6 +373,7 @@ static int i810_dma_initialize(drm_device_t * dev,
DRM_ERROR("can not find mmio map!\n");
return -EINVAL;
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if (!dev->agp_buffer_map) {
dev->dev_private = (void *)dev_priv;
diff --git a/linux-core/i830_dma.c b/linux-core/i830_dma.c
index 1c44f70d..022cecf3 100644
--- a/linux-core/i830_dma.c
+++ b/linux-core/i830_dma.c
@@ -366,6 +366,7 @@ static int i830_dma_initialize(drm_device_t * dev,
DRM_ERROR("can not find mmio map!\n");
return -EINVAL;
}
+ dev->agp_buffer_token = init->buffers_offset;
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if (!dev->agp_buffer_map) {
dev->dev_private = (void *)dev_priv;
diff --git a/linux-core/mga_ioc32.c b/linux-core/mga_ioc32.c
index bc745cfa..5775cd63 100644
--- a/linux-core/mga_ioc32.c
+++ b/linux-core/mga_ioc32.c
@@ -1,3 +1,4 @@
+
/**
* \file mga_ioc32.c
*
@@ -129,9 +130,76 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd,
DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
}
+typedef struct drm_mga_drm_bootstrap32 {
+ u32 texture_handle;
+ u32 texture_size;
+ u32 primary_size;
+ u32 secondary_bin_count;
+ u32 secondary_bin_size;
+ u32 agp_mode;
+ u8 agp_size;
+} drm_mga_dma_bootstrap32_t;
+
+static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_mga_dma_bootstrap32_t dma_bootstrap32;
+ drm_mga_dma_bootstrap_t __user *dma_bootstrap;
+ int err;
+
+ if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
+ sizeof(dma_bootstrap32)))
+ return -EFAULT;
+
+ dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
+ if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
+ || __put_user(dma_bootstrap32.texture_handle,
+ &dma_bootstrap->texture_handle)
+ || __put_user(dma_bootstrap32.texture_size,
+ &dma_bootstrap->texture_size)
+ || __put_user(dma_bootstrap32.primary_size,
+ &dma_bootstrap->primary_size)
+ || __put_user(dma_bootstrap32.secondary_bin_count,
+ &dma_bootstrap->secondary_bin_count)
+ || __put_user(dma_bootstrap32.secondary_bin_size,
+ &dma_bootstrap->secondary_bin_size)
+ || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
+ || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+ (unsigned long)dma_bootstrap);
+ if (err)
+ return err;
+
+ if (__get_user(dma_bootstrap32.texture_handle,
+ &dma_bootstrap->texture_handle)
+ || __get_user(dma_bootstrap32.texture_size,
+ &dma_bootstrap->texture_size)
+ || __get_user(dma_bootstrap32.primary_size,
+ &dma_bootstrap->primary_size)
+ || __get_user(dma_bootstrap32.secondary_bin_count,
+ &dma_bootstrap->secondary_bin_count)
+ || __get_user(dma_bootstrap32.secondary_bin_size,
+ &dma_bootstrap->secondary_bin_size)
+ || __get_user(dma_bootstrap32.agp_mode,
+ &dma_bootstrap->agp_mode)
+ || __get_user(dma_bootstrap32.agp_size,
+ &dma_bootstrap->agp_size))
+ return -EFAULT;
+
+ if (copy_to_user((void __user *)arg, &dma_bootstrap32,
+ sizeof(dma_bootstrap32)))
+ return -EFAULT;
+
+ return 0;
+}
+
drm_ioctl_compat_t *mga_compat_ioctls[] = {
[DRM_MGA_INIT] = compat_mga_init,
[DRM_MGA_GETPARAM] = compat_mga_getparam,
+ [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
};
/**