summaryrefslogtreecommitdiff
path: root/linux-core/drm_bufs.c
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2005-06-14 22:34:11 +0000
committerIan Romanick <idr@us.ibm.com>2005-06-14 22:34:11 +0000
commit72cfc797b51e59ecf8a2787c6a176838241cc94b (patch)
tree87ade354c97e962a29b3d1fc8b620972754092eb /linux-core/drm_bufs.c
parent3585bdf7d81a92c729bb5bcbc7cfca6048d640ce (diff)
Adds support for PCI cards to MGA DRM
This patch adds serveral new ioctls and a new query to get_param query to support PCI MGA cards. Two ioctls were added to implement interrupt based waiting. With this change, the client-side driver no longer needs to map the primary DMA region or the MMIO region. Previously, end-of-frame waiting was done by busy waiting in the client-side driver until one of the MMIO registers (the current DMA pointer) matched a pointer to the end of primary DMA space. By using interrupts, the busy waiting and the extra mappings are removed. A third ioctl was added to bootstrap DMA. This ioctl, which is used by the X-server, moves a *LOT* of code from the X-server into the kernel. This allows the kernel to do whatever needs to be done to setup DMA buffers. The entire process and the locations of the buffers are hidden from user-mode. Additionally, a get_param query was added to differentiate between G4x0 cards and G550 cards. A gap was left in the numbering sequence so that, if needed, G450 cards could be distinguished from G400 cards. According to Ville Syrjälä, the G4x0 cards and the G550 cards handle anisotropic filtering differently. This seems the most compatible way to let the client-side driver know which card it's own. Doing this very small change now eliminates the need to bump the DRM minor version twice. http://marc.theaimsgroup.com/?l=dri-devel&m=106625815319773&w=2 A number of ioctl handlers in linux-core were also modified so that they could be called in-kernel. In these cases, the in-kernel callable version kept the existing name (e.g., drm_agp_acquire) and the ioctl handler added _ioctl to the name (e.g., drm_agp_acquire_ioctl). This patch also replaces the drm_agp_do_release function with drm_agp_release. drm_agp_release (drm_core_agp_release in the previous patch) is very similar to drm_agp_do_release, and I saw no reason to have both. This commit *breaks the build* on BSD. Eric said that he would make the required updates to the BSD side soon. Xorg bug: 3259 Reviewed by: Eric Anholt
Diffstat (limited to 'linux-core/drm_bufs.c')
-rw-r--r--linux-core/drm_bufs.c89
1 files changed, 63 insertions, 26 deletions
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index 50182160..b54aaeb8 100644
--- a/linux-core/drm_bufs.c
+++ b/linux-core/drm_bufs.c
@@ -122,27 +122,23 @@ EXPORT_SYMBOL(drm_initmap);
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel.
*/
-int drm_addmap(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+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)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
drm_map_t *map;
- drm_map_t __user *argp = (void __user *)arg;
drm_map_list_t *list;
drm_dma_handle_t *dmah;
- if (!(filp->f_mode & 3))
- return -EACCES; /* Require read/write */
map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
if (!map)
return -ENOMEM;
- if (copy_from_user(map, argp, sizeof(*map))) {
- drm_free(map, sizeof(*map), DRM_MEM_MAPS);
- return -EFAULT;
- }
+ map->offset = offset;
+ map->size = size;
+ map->flags = flags;
+ map->type = type;
/* Only allow shared memory to be removable since we only keep enough
* book keeping information about shared memory to allow for removal
@@ -289,11 +285,40 @@ int drm_addmap(struct inode *inode, struct file *filp,
list_add(&list->head, &dev->maplist->head);
up(&dev->struct_sem);
found_it:
- 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;
- if (map->type != _DRM_SHM) {
+ }
+
+ 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;
+ if (map_ptr->type != _DRM_SHM) {
if (copy_to_user(&argp->handle,
- &map->offset, sizeof(map->offset)))
+ &map_ptr->offset, sizeof(map_ptr->offset)))
return -EFAULT;
}
return 0;
@@ -313,23 +338,16 @@ 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
* being on use.
*
- * \sa addmap().
+ * \sa drm_addmap
*/
-int drm_rmmap(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_rmmap(drm_device_t *dev, void *handle)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
struct list_head *list;
drm_map_list_t *r_list = NULL;
drm_vma_entry_t *pt, *prev;
drm_map_t *map;
- drm_map_t request;
int found_maps = 0;
- if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
- return -EFAULT;
- }
down(&dev->struct_sem);
list = &dev->maplist->head;
@@ -337,7 +355,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->handle == handle &&
r_list->map->flags & _DRM_REMOVABLE)
break;
}
@@ -389,6 +407,22 @@ int drm_rmmap(struct inode *inode, struct file *filp,
up(&dev->struct_sem);
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.
@@ -444,7 +478,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
* reallocates the buffer list of the same size order to accommodate the new
* buffers.
*/
-static int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
{
drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry;
@@ -596,9 +630,10 @@ static int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_agp);
#endif /* __OS_HAS_AGP */
-static int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
{
drm_device_dma_t *dma = dev->dma;
int count;
@@ -814,6 +849,7 @@ static int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_pci);
static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
{
@@ -1127,6 +1163,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_fb);
/**