Commit 7ab98401 authored by Dave Airlie's avatar Dave Airlie Committed by Dave Airlie

drm: update some function so a driver can call them

This patch splits some ioctl functions so that they can be called
in-kernel by a DRM driver. The driver will use them later.

From: Ian Romanick <idr@us.ibm.com>
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent 9c8da5eb
...@@ -889,11 +889,16 @@ extern int drm_lock_free(drm_device_t *dev, ...@@ -889,11 +889,16 @@ extern int drm_lock_free(drm_device_t *dev,
unsigned int context); unsigned int context);
/* Buffer management support (drm_bufs.h) */ /* Buffer management support (drm_bufs.h) */
extern int drm_addmap(drm_device_t *dev, unsigned int offset,
unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_map_t **map_ptr);
extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_rmmap(drm_device_t *dev, void *handle);
extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_order( unsigned long size ); extern int drm_order( unsigned long size );
extern int drm_addmap( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
extern int drm_rmmap( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
extern int drm_addbufs( struct inode *inode, struct file *filp, extern int drm_addbufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg ); unsigned int cmd, unsigned long arg );
extern int drm_infobufs( struct inode *inode, struct file *filp, extern int drm_infobufs( struct inode *inode, struct file *filp,
...@@ -927,14 +932,17 @@ extern void drm_vbl_send_signals( drm_device_t *dev ); ...@@ -927,14 +932,17 @@ extern void drm_vbl_send_signals( drm_device_t *dev );
/* AGP/GART support (drm_agpsupport.h) */ /* AGP/GART support (drm_agpsupport.h) */
extern drm_agp_head_t *drm_agp_init(drm_device_t *dev); extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
extern int drm_agp_acquire(struct inode *inode, struct file *filp, extern int drm_agp_acquire(drm_device_t * dev);
extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern void drm_agp_do_release(drm_device_t *dev); extern int drm_agp_release(drm_device_t *dev);
extern int drm_agp_release(struct inode *inode, struct file *filp, extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_agp_enable(struct inode *inode, struct file *filp, extern int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode);
extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_agp_info(struct inode *inode, struct file *filp, extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info);
extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_agp_alloc(struct inode *inode, struct file *filp, extern int drm_agp_alloc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#if __OS_HAS_AGP #if __OS_HAS_AGP
/** /**
* AGP information ioctl. * Get AGP information.
* *
* \param inode device inode. * \param inode device inode.
* \param filp file pointer. * \param filp file pointer.
...@@ -48,51 +48,56 @@ ...@@ -48,51 +48,56 @@
* Verifies the AGP device has been initialized and acquired and fills in the * Verifies the AGP device has been initialized and acquired and fills in the
* drm_agp_info structure with the information in drm_agp_head::agp_info. * drm_agp_info structure with the information in drm_agp_head::agp_info.
*/ */
int drm_agp_info(struct inode *inode, struct file *filp, int drm_agp_info(drm_device_t *dev, drm_agp_info_t *info)
unsigned int cmd, unsigned long arg)
{ {
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
DRM_AGP_KERN *kern; DRM_AGP_KERN *kern;
drm_agp_info_t info;
if (!dev->agp || !dev->agp->acquired) if (!dev->agp || !dev->agp->acquired)
return -EINVAL; return -EINVAL;
kern = &dev->agp->agp_info; kern = &dev->agp->agp_info;
info.agp_version_major = kern->version.major; info->agp_version_major = kern->version.major;
info.agp_version_minor = kern->version.minor; info->agp_version_minor = kern->version.minor;
info.mode = kern->mode; info->mode = kern->mode;
info.aperture_base = kern->aper_base; info->aperture_base = kern->aper_base;
info.aperture_size = kern->aper_size * 1024 * 1024; info->aperture_size = kern->aper_size * 1024 * 1024;
info.memory_allowed = kern->max_memory << PAGE_SHIFT; info->memory_allowed = kern->max_memory << PAGE_SHIFT;
info.memory_used = kern->current_memory << PAGE_SHIFT; info->memory_used = kern->current_memory << PAGE_SHIFT;
info.id_vendor = kern->device->vendor; info->id_vendor = kern->device->vendor;
info.id_device = kern->device->device; info->id_device = kern->device->device;
if (copy_to_user((drm_agp_info_t __user *)arg, &info, sizeof(info))) return 0;
}
EXPORT_SYMBOL(drm_agp_info);
int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_info_t info;
int err;
err = drm_agp_info(dev, &info);
if (err)
return err;
if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
/** /**
* Acquire the AGP device (ioctl). * Acquire the AGP device.
* *
* \param inode device inode. * \param dev DRM device that is to acquire AGP
* \param filp file pointer.
* \param cmd command.
* \param arg user argument.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
* *
* Verifies the AGP device hasn't been acquired before and calls * Verifies the AGP device hasn't been acquired before and calls
* agp_acquire(). * \c agp_backend_acquire.
*/ */
int drm_agp_acquire(struct inode *inode, struct file *filp, int drm_agp_acquire(drm_device_t *dev)
unsigned int cmd, unsigned long arg)
{ {
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
if (!dev->agp) if (!dev->agp)
return -ENODEV; return -ENODEV;
if (dev->agp->acquired) if (dev->agp->acquired)
...@@ -102,9 +107,10 @@ int drm_agp_acquire(struct inode *inode, struct file *filp, ...@@ -102,9 +107,10 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
dev->agp->acquired = 1; dev->agp->acquired = 1;
return 0; return 0;
} }
EXPORT_SYMBOL(drm_agp_acquire);
/** /**
* Release the AGP device (ioctl). * Acquire the AGP device (ioctl).
* *
* \param inode device inode. * \param inode device inode.
* \param filp file pointer. * \param filp file pointer.
...@@ -112,63 +118,80 @@ int drm_agp_acquire(struct inode *inode, struct file *filp, ...@@ -112,63 +118,80 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
* \param arg user argument. * \param arg user argument.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
* *
* Verifies the AGP device has been acquired and calls agp_backend_release(). * Verifies the AGP device hasn't been acquired before and calls
* \c agp_backend_acquire.
*/ */
int drm_agp_release(struct inode *inode, struct file *filp, int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
agp_backend_release(dev->agp->bridge);
dev->agp->acquired = 0;
return 0;
return drm_agp_acquire( (drm_device_t *) priv->head->dev );
} }
/** /**
* Release the AGP device. * Release the AGP device.
* *
* Calls agp_backend_release(). * \param dev DRM device that is to release AGP
* \return zero on success or a negative number on failure.
*
* Verifies the AGP device has been acquired and calls \c agp_backend_release.
*/ */
void drm_agp_do_release(drm_device_t *dev) int drm_agp_release(drm_device_t *dev)
{ {
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
agp_backend_release(dev->agp->bridge); agp_backend_release(dev->agp->bridge);
dev->agp->acquired = 0;
return 0;
}
EXPORT_SYMBOL(drm_agp_release);
int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
return drm_agp_release(dev);
} }
/** /**
* Enable the AGP bus. * Enable the AGP bus.
* *
* \param inode device inode. * \param dev DRM device that has previously acquired AGP.
* \param filp file pointer. * \param mode Requested AGP mode.
* \param cmd command.
* \param arg pointer to a drm_agp_mode structure.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
* *
* Verifies the AGP device has been acquired but not enabled, and calls * Verifies the AGP device has been acquired but not enabled, and calls
* agp_enable(). * \c agp_enable.
*/ */
int drm_agp_enable(struct inode *inode, struct file *filp, int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
unsigned int cmd, unsigned long arg)
{ {
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_mode_t mode;
if (!dev->agp || !dev->agp->acquired) if (!dev->agp || !dev->agp->acquired)
return -EINVAL; return -EINVAL;
if (copy_from_user(&mode, (drm_agp_mode_t __user *)arg, sizeof(mode)))
return -EFAULT;
dev->agp->mode = mode.mode; dev->agp->mode = mode.mode;
agp_enable(dev->agp->bridge, mode.mode); agp_enable(dev->agp->bridge, mode.mode);
dev->agp->base = dev->agp->agp_info.aper_base; dev->agp->base = dev->agp->agp_info.aper_base;
dev->agp->enabled = 1; dev->agp->enabled = 1;
return 0; return 0;
} }
EXPORT_SYMBOL(drm_agp_enable);
int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_agp_mode_t mode;
if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
return -EFAULT;
return drm_agp_enable(dev, mode);
}
/** /**
* Allocate AGP memory. * Allocate AGP memory.
......
...@@ -82,26 +82,22 @@ static unsigned int map32_handle = 0x10000000; ...@@ -82,26 +82,22 @@ static unsigned int map32_handle = 0x10000000;
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel. * applicable and if supported by the kernel.
*/ */
int drm_addmap( struct inode *inode, struct file *filp, int drm_addmap(drm_device_t * dev, unsigned int offset,
unsigned int cmd, unsigned long arg ) unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_local_map_t ** map_ptr)
{ {
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_map_t *map; drm_map_t *map;
drm_map_t __user *argp = (void __user *)arg;
drm_map_list_t *list; drm_map_list_t *list;
drm_dma_handle_t *dmah; drm_dma_handle_t *dmah;
if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
map = drm_alloc( sizeof(*map), DRM_MEM_MAPS ); map = drm_alloc( sizeof(*map), DRM_MEM_MAPS );
if ( !map ) if ( !map )
return -ENOMEM; return -ENOMEM;
if ( copy_from_user( map, argp, sizeof(*map) ) ) { map->offset = offset;
drm_free( map, sizeof(*map), DRM_MEM_MAPS ); map->size = size;
return -EFAULT; map->flags = flags;
} map->type = type;
/* Only allow shared memory to be removable since we only keep enough /* Only allow shared memory to be removable since we only keep enough
* book keeping information about shared memory to allow for removal * book keeping information about shared memory to allow for removal
...@@ -218,10 +214,42 @@ int drm_addmap( struct inode *inode, struct file *filp, ...@@ -218,10 +214,42 @@ int drm_addmap( struct inode *inode, struct file *filp,
#endif #endif
up(&dev->struct_sem); up(&dev->struct_sem);
if ( copy_to_user( argp, map, sizeof(*map) ) ) *map_ptr = map;
return 0;
}
EXPORT_SYMBOL(drm_addmap);
int drm_addmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_map_t map;
drm_map_t *map_ptr;
drm_map_t __user *argp = (void __user *)arg;
int err;
if (!(filp->f_mode & 3))
return -EACCES; /* Require read/write */
if (copy_from_user(& map, argp, sizeof(map))) {
return -EFAULT;
}
err = drm_addmap( dev, map.offset, map.size, map.type, map.flags,
&map_ptr );
if (err) {
return err;
}
if (copy_to_user(argp, map_ptr, sizeof(*map_ptr)))
return -EFAULT; return -EFAULT;
if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset))) if (map_ptr->type != _DRM_SHM) {
if (copy_to_user(&argp->handle, &map_ptr->offset,
sizeof(map_ptr->offset)))
return -EFAULT; return -EFAULT;
}
return 0; return 0;
} }
...@@ -240,32 +268,23 @@ int drm_addmap( struct inode *inode, struct file *filp, ...@@ -240,32 +268,23 @@ int drm_addmap( struct inode *inode, struct file *filp,
* its being used, and free any associate resource (such as MTRR's) if it's not * its being used, and free any associate resource (such as MTRR's) if it's not
* being on use. * being on use.
* *
* \sa addmap(). * \sa drm_addmap
*/ */
int drm_rmmap(struct inode *inode, struct file *filp, int drm_rmmap(drm_device_t *dev, void *handle)
unsigned int cmd, unsigned long arg)
{ {
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
struct list_head *list; struct list_head *list;
drm_map_list_t *r_list = NULL; drm_map_list_t *r_list = NULL;
drm_vma_entry_t *pt, *prev; drm_vma_entry_t *pt, *prev;
drm_map_t *map; drm_map_t *map;
drm_map_t request;
int found_maps = 0; int found_maps = 0;
if (copy_from_user(&request, (drm_map_t __user *)arg,
sizeof(request))) {
return -EFAULT;
}
down(&dev->struct_sem); down(&dev->struct_sem);
list = &dev->maplist->head; list = &dev->maplist->head;
list_for_each(list, &dev->maplist->head) { list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head); r_list = list_entry(list, drm_map_list_t, head);
if(r_list->map && if(r_list->map &&
r_list->map->offset == (unsigned long) request.handle && r_list->map->handle == handle &&
r_list->map->flags & _DRM_REMOVABLE) break; r_list->map->flags & _DRM_REMOVABLE) break;
} }
...@@ -319,6 +338,21 @@ int drm_rmmap(struct inode *inode, struct file *filp, ...@@ -319,6 +338,21 @@ int drm_rmmap(struct inode *inode, struct file *filp,
up(&dev->struct_sem); up(&dev->struct_sem);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_rmmap);
int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
drm_map_t request;
if (copy_from_user(&request, (drm_map_t __user *)arg, sizeof(request))) {
return -EFAULT;
}
return drm_rmmap(dev, request.handle);
}
/** /**
* Cleanup after an error on one of the addbufs() functions. * Cleanup after an error on one of the addbufs() functions.
......
...@@ -70,8 +70,8 @@ static drm_ioctl_desc_t drm_ioctls[] = { ...@@ -70,8 +70,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_noop, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap_ioctl,1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = { drm_rmmap_ioctl, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
...@@ -102,10 +102,10 @@ static drm_ioctl_desc_t drm_ioctls[] = { ...@@ -102,10 +102,10 @@ static drm_ioctl_desc_t drm_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = { drm_control, 1, 1 },
#if __OS_HAS_AGP #if __OS_HAS_AGP
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire_ioctl, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release_ioctl, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable_ioctl, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info_ioctl, 1, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
...@@ -178,7 +178,8 @@ int drm_takedown( drm_device_t *dev ) ...@@ -178,7 +178,8 @@ int drm_takedown( drm_device_t *dev )
} }
dev->agp->memory = NULL; dev->agp->memory = NULL;
if ( dev->agp->acquired ) drm_agp_do_release(dev); if (dev->agp->acquired)
drm_agp_release(dev);
dev->agp->acquired = 0; dev->agp->acquired = 0;
dev->agp->enabled = 0; dev->agp->enabled = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment