提交 8678887e 编写于 作者: L Linus Torvalds
......@@ -19,6 +19,11 @@ radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
ffb-objs := ffb_drv.o ffb_context.o
sis-objs := sis_drv.o sis_ds.o sis_mm.o
ifeq ($(CONFIG_COMPAT),y)
drm-objs += drm_ioc32.o
radeon-objs += radeon_ioc32.o
endif
obj-$(CONFIG_DRM) += drm.o
obj-$(CONFIG_DRM_GAMMA) += gamma.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
......
......@@ -316,6 +316,9 @@ do { \
typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
unsigned long arg);
typedef struct drm_ioctl_desc {
drm_ioctl_t *func;
int auth_needed;
......@@ -775,6 +778,8 @@ extern int drm_version(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern long drm_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_takedown(drm_device_t * dev);
/* Device support (drm_fops.h) */
......
......@@ -60,6 +60,15 @@ int drm_order( unsigned long size )
}
EXPORT_SYMBOL(drm_order);
#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.
*/
static unsigned int map32_handle = 0x10000000;
#endif
/**
* Ioctl to specify a range of memory that is available for mapping by a non-root process.
*
......@@ -187,16 +196,18 @@ int drm_addmap( struct inode *inode, struct file *filp,
down(&dev->struct_sem);
list_add(&list->head, &dev->maplist->head);
#ifdef CONFIG_COMPAT
/* Assign a 32-bit handle for _DRM_SHM mappings */
/* We do it here so that dev->struct_sem protects the increment */
if (map->type == _DRM_SHM)
map->offset = map32_handle += PAGE_SIZE;
#endif
up(&dev->struct_sem);
if ( copy_to_user( argp, map, sizeof(*map) ) )
return -EFAULT;
if ( map->type != _DRM_SHM ) {
if ( copy_to_user( &argp->handle,
&map->offset,
sizeof(map->offset) ) )
if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))
return -EFAULT;
}
return 0;
}
......@@ -240,7 +251,7 @@ int drm_rmmap(struct inode *inode, struct file *filp,
r_list = list_entry(list, drm_map_list_t, head);
if(r_list->map &&
r_list->map->handle == request.handle &&
r_list->map->offset == (unsigned long) request.handle &&
r_list->map->flags & _DRM_REMOVABLE) break;
}
......
......@@ -225,7 +225,7 @@ 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 = (void *) map->offset;
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return 0;
......@@ -261,8 +261,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->map->offset == (unsigned long) request.handle)
goto found;
}
bad:
......
此差异已折叠。
......@@ -101,6 +101,9 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
#ifdef CONFIG_COMPAT
.compat_ioctl = radeon_compat_ioctl,
#endif
},
.pci_driver = {
.name = DRIVER_NAME,
......
......@@ -317,6 +317,9 @@ extern int radeon_preinit( struct drm_device *dev, unsigned long flags );
extern int radeon_postinit( struct drm_device *dev, unsigned long flags );
extern int radeon_postcleanup( struct drm_device *dev );
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
/* Flags for stats.boxes
*/
#define RADEON_BOX_DMA_IDLE 0x1
......
/**
* \file radeon_ioc32.c
*
* 32-bit ioctl compatibility routines for the Radeon DRM.
*
* \author Paul Mackerras <paulus@samba.org>
*
* Copyright (C) Paul Mackerras 2005
* 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
* THE AUTHOR 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 <linux/compat.h>
#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
typedef struct drm_radeon_init32 {
int func;
u32 sarea_priv_offset;
int is_pci;
int cp_mode;
int gart_size;
int ring_size;
int usec_timeout;
unsigned int fb_bpp;
unsigned int front_offset, front_pitch;
unsigned int back_offset, back_pitch;
unsigned int depth_bpp;
unsigned int depth_offset, depth_pitch;
u32 fb_offset;
u32 mmio_offset;
u32 ring_offset;
u32 ring_rptr_offset;
u32 buffers_offset;
u32 gart_textures_offset;
} drm_radeon_init32_t;
static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_init32_t init32;
drm_radeon_init_t __user *init;
if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
return -EFAULT;
init = compat_alloc_user_space(sizeof(*init));
if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
|| __put_user(init32.func, &init->func)
|| __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
|| __put_user(init32.is_pci, &init->is_pci)
|| __put_user(init32.cp_mode, &init->cp_mode)
|| __put_user(init32.gart_size, &init->gart_size)
|| __put_user(init32.ring_size, &init->ring_size)
|| __put_user(init32.usec_timeout, &init->usec_timeout)
|| __put_user(init32.fb_bpp, &init->fb_bpp)
|| __put_user(init32.front_offset, &init->front_offset)
|| __put_user(init32.front_pitch, &init->front_pitch)
|| __put_user(init32.back_offset, &init->back_offset)
|| __put_user(init32.back_pitch, &init->back_pitch)
|| __put_user(init32.depth_bpp, &init->depth_bpp)
|| __put_user(init32.depth_offset, &init->depth_offset)
|| __put_user(init32.depth_pitch, &init->depth_pitch)
|| __put_user(init32.fb_offset, &init->fb_offset)
|| __put_user(init32.mmio_offset, &init->mmio_offset)
|| __put_user(init32.ring_offset, &init->ring_offset)
|| __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
|| __put_user(init32.buffers_offset, &init->buffers_offset)
|| __put_user(init32.gart_textures_offset,
&init->gart_textures_offset))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);
}
typedef struct drm_radeon_clear32 {
unsigned int flags;
unsigned int clear_color;
unsigned int clear_depth;
unsigned int color_mask;
unsigned int depth_mask; /* misnamed field: should be stencil */
u32 depth_boxes;
} drm_radeon_clear32_t;
static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_clear32_t clr32;
drm_radeon_clear_t __user *clr;
if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))
return -EFAULT;
clr = compat_alloc_user_space(sizeof(*clr));
if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))
|| __put_user(clr32.flags, &clr->flags)
|| __put_user(clr32.clear_color, &clr->clear_color)
|| __put_user(clr32.clear_depth, &clr->clear_depth)
|| __put_user(clr32.color_mask, &clr->color_mask)
|| __put_user(clr32.depth_mask, &clr->depth_mask)
|| __put_user((void __user *)(unsigned long)clr32.depth_boxes,
&clr->depth_boxes))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);
}
typedef struct drm_radeon_stipple32 {
u32 mask;
} drm_radeon_stipple32_t;
static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_stipple32_t __user *argp = (void __user *) arg;
drm_radeon_stipple_t __user *request;
u32 mask;
if (get_user(mask, &argp->mask))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
|| __put_user((unsigned int __user *)(unsigned long) mask,
&request->mask))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);
}
typedef struct drm_radeon_tex_image32 {
unsigned int x, y; /* Blit coordinates */
unsigned int width, height;
u32 data;
} drm_radeon_tex_image32_t;
typedef struct drm_radeon_texture32 {
unsigned int offset;
int pitch;
int format;
int width; /* Texture image coordinates */
int height;
u32 image;
} drm_radeon_texture32_t;
static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_texture32_t req32;
drm_radeon_texture_t __user *request;
drm_radeon_tex_image32_t img32;
drm_radeon_tex_image_t __user *image;
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
return -EFAULT;
if (req32.image == 0)
return -EINVAL;
if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,
sizeof(img32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));
if (!access_ok(VERIFY_WRITE, request,
sizeof(*request) + sizeof(*image)))
return -EFAULT;
image = (drm_radeon_tex_image_t __user *) (request + 1);
if (__put_user(req32.offset, &request->offset)
|| __put_user(req32.pitch, &request->pitch)
|| __put_user(req32.format, &request->format)
|| __put_user(req32.width, &request->width)
|| __put_user(req32.height, &request->height)
|| __put_user(image, &request->image)
|| __put_user(img32.x, &image->x)
|| __put_user(img32.y, &image->y)
|| __put_user(img32.width, &image->width)
|| __put_user(img32.height, &image->height)
|| __put_user((const void __user *)(unsigned long)img32.data,
&image->data))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);
}
typedef struct drm_radeon_vertex2_32 {
int idx; /* Index of vertex buffer */
int discard; /* Client finished with buffer? */
int nr_states;
u32 state;
int nr_prims;
u32 prim;
} drm_radeon_vertex2_32_t;
static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_vertex2_32_t req32;
drm_radeon_vertex2_t __user *request;
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
|| __put_user(req32.idx, &request->idx)
|| __put_user(req32.discard, &request->discard)
|| __put_user(req32.nr_states, &request->nr_states)
|| __put_user((void __user *)(unsigned long)req32.state,
&request->state)
|| __put_user(req32.nr_prims, &request->nr_prims)
|| __put_user((void __user *)(unsigned long)req32.prim,
&request->prim))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);
}
typedef struct drm_radeon_cmd_buffer32 {
int bufsz;
u32 buf;
int nbox;
u32 boxes;
} drm_radeon_cmd_buffer32_t;
static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_cmd_buffer32_t req32;
drm_radeon_cmd_buffer_t __user *request;
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
|| __put_user(req32.bufsz, &request->bufsz)
|| __put_user((void __user *)(unsigned long)req32.buf,
&request->buf)
|| __put_user(req32.nbox, &request->nbox)
|| __put_user((void __user *)(unsigned long)req32.boxes,
&request->boxes))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);
}
typedef struct drm_radeon_getparam32 {
int param;
u32 value;
} drm_radeon_getparam32_t;
static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_getparam32_t req32;
drm_radeon_getparam_t __user *request;
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
|| __put_user(req32.param, &request->param)
|| __put_user((void __user *)(unsigned long)req32.value,
&request->value))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);
}
typedef struct drm_radeon_mem_alloc32 {
int region;
int alignment;
int size;
u32 region_offset; /* offset from start of fb or GART */
} drm_radeon_mem_alloc32_t;
static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_mem_alloc32_t req32;
drm_radeon_mem_alloc_t __user *request;
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
|| __put_user(req32.region, &request->region)
|| __put_user(req32.alignment, &request->alignment)
|| __put_user(req32.size, &request->size)
|| __put_user((int __user *)(unsigned long)req32.region_offset,
&request->region_offset))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);
}
typedef struct drm_radeon_irq_emit32 {
u32 irq_seq;
} drm_radeon_irq_emit32_t;
static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
unsigned long arg)
{
drm_radeon_irq_emit32_t req32;
drm_radeon_irq_emit_t __user *request;
if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
return -EFAULT;
request = compat_alloc_user_space(sizeof(*request));
if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
|| __put_user((int __user *)(unsigned long)req32.irq_seq,
&request->irq_seq))
return -EFAULT;
return drm_ioctl(file->f_dentry->d_inode, file,
DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
}
drm_ioctl_compat_t *radeon_compat_ioctls[] = {
[DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
[DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
[DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,
[DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,
[DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
[DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
[DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
[DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
[DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
};
/**
* Called whenever a 32-bit process running under a 64-bit kernel
* performs an ioctl on /dev/dri/card<n>.
*
* \param filp file pointer.
* \param cmd command.
* \param arg user argument.
* \return zero on success or negative number on failure.
*/
long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
unsigned int nr = DRM_IOCTL_NR(cmd);
drm_ioctl_compat_t *fn = NULL;
int ret;
if (nr < DRM_COMMAND_BASE)
return drm_compat_ioctl(filp, cmd, arg);
if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
lock_kernel(); /* XXX for now */
if (fn != NULL)
ret = (*fn)(filp, cmd, arg);
else
ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
unlock_kernel();
return ret;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册