Merged mga branch with trunk
[platform/upstream/libdrm.git] / linux / mga_bufs.c
index 34f1112..3ce428b 100644 (file)
 #define __NO_VERSION__
 #include "drmP.h"
 #include "mga_drv.h"
-#include "mga_dma.h"
 #include "linux/un.h"
 
 
 int mga_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
                    unsigned long arg)
 {
-   drm_file_t *priv = filp->private_data;
-   drm_device_t *dev = priv->dev;
-   drm_device_dma_t *dma = dev->dma;
-   drm_buf_desc_t request;
-   drm_buf_entry_t *entry;
-   drm_buf_t *buf;
-   unsigned long offset;
-   unsigned long agp_offset;
-   int count;
-   int order;
-   int size;
-   int alignment;
-   int page_order;
-   int total;
-   int byte_count;
-   int i;
-
-   if (!dma) return -EINVAL;
-
-   copy_from_user_ret(&request,
-                     (drm_buf_desc_t *)arg,
-                     sizeof(request),
-                     -EFAULT);
-
-   count = request.count;
-   order = drm_order(request.size);
-   size        = 1 << order;
-   agp_offset = request.agp_start;
-   alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
-   page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-   total = PAGE_SIZE << page_order;
-   byte_count = 0;
-
-   DRM_DEBUG("count: %d\n", count);
-   DRM_DEBUG("order: %d\n", order);
-   DRM_DEBUG("size: %d\n", size);
-   DRM_DEBUG("agp_offset: %d\n", agp_offset);
-   DRM_DEBUG("alignment: %d\n", alignment);
-   DRM_DEBUG("page_order: %d\n", page_order);
-   DRM_DEBUG("total: %d\n", total);
-   DRM_DEBUG("byte_count: %d\n", byte_count);
-
-   if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-   if (dev->queue_count) return -EBUSY; /* Not while in use */
-   spin_lock(&dev->count_lock);
-   if (dev->buf_use) {
-      spin_unlock(&dev->count_lock);
-      return -EBUSY;
-   }
-   atomic_inc(&dev->buf_alloc);
-   spin_unlock(&dev->count_lock);
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->dev;
+       drm_device_dma_t *dma = dev->dma;
+       drm_buf_desc_t request;
+       drm_buf_entry_t *entry;
+       drm_buf_t *buf;
+       unsigned long offset;
+       unsigned long agp_offset;
+       int count;
+       int order;
+       int size;
+       int alignment;
+       int page_order;
+       int total;
+       int byte_count;
+       int i;
+
+       if (!dma) return -EINVAL;
+
+       copy_from_user_ret(&request,
+                          (drm_buf_desc_t *)arg,
+                          sizeof(request),
+                          -EFAULT);
+
+       count = request.count;
+       order = drm_order(request.size);
+       size    = 1 << order;
+       agp_offset = request.agp_start;
+       alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
+       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+       total = PAGE_SIZE << page_order;
+       byte_count = 0;
+
+       DRM_DEBUG("count: %d\n", count);
+       DRM_DEBUG("order: %d\n", order);
+       DRM_DEBUG("size: %d\n", size);
+       DRM_DEBUG("agp_offset: %ld\n", agp_offset);
+       DRM_DEBUG("alignment: %d\n", alignment);
+       DRM_DEBUG("page_order: %d\n", page_order);
+       DRM_DEBUG("total: %d\n", total);
+       DRM_DEBUG("byte_count: %d\n", byte_count);
+
+       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
+       if (dev->queue_count) return -EBUSY; /* Not while in use */
+       spin_lock(&dev->count_lock);
+       if (dev->buf_use) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       atomic_inc(&dev->buf_alloc);
+       spin_unlock(&dev->count_lock);
    
-   down(&dev->struct_sem);
-   entry = &dma->bufs[order];
-   if (entry->buf_count) {
-      up(&dev->struct_sem);
-      atomic_dec(&dev->buf_alloc);
-      return -ENOMEM; /* May only call once for each order */
-   }
+       down(&dev->struct_sem);
+       entry = &dma->bufs[order];
+       if (entry->buf_count) {
+               up(&dev->struct_sem);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM; /* May only call once for each order */
+       }
    
-   entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-                             DRM_MEM_BUFS);
-   if (!entry->buflist) {
-      up(&dev->struct_sem);
-      atomic_dec(&dev->buf_alloc);
-      return -ENOMEM;
-   }
-   memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+                                  DRM_MEM_BUFS);
+       if (!entry->buflist) {
+               up(&dev->struct_sem);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
    
-   entry->buf_size   = size;
-   entry->page_order = page_order;
-   offset = 0;
+       entry->buf_size   = size;
+       entry->page_order = page_order;
+       offset = 0;
 
    
-   while(entry->buf_count < count) {
-      buf = &entry->buflist[entry->buf_count];
-      buf->idx = dma->buf_count + entry->buf_count;
-      buf->total = alignment;
-      buf->order = order;
-      buf->used = 0;
-
-      DRM_DEBUG("offset : %d\n", offset);
-
-      buf->offset = offset; /* Hrm */
-      buf->bus_address = dev->agp->base + agp_offset + offset;
-      buf->address = (void *)(agp_offset + offset + dev->agp->base);
-      buf->next = NULL;
-      buf->waiting = 0;
-      buf->pending = 0;
-      init_waitqueue_head(&buf->dma_wait);
-      buf->pid = 0;
-
-      buf->dev_private = drm_alloc(sizeof(drm_mga_buf_priv_t), DRM_MEM_BUFS);
-      buf->dev_priv_size = sizeof(drm_mga_buf_priv_t);
+       while(entry->buf_count < count) {
+               buf = &entry->buflist[entry->buf_count];
+               buf->idx = dma->buf_count + entry->buf_count;
+               buf->total = alignment;
+               buf->order = order;
+               buf->used = 0;
+
+               DRM_DEBUG("offset : %ld\n", offset);
+
+               buf->offset = offset; /* Hrm */
+               buf->bus_address = dev->agp->base + agp_offset + offset;
+               buf->address = (void *)(agp_offset + offset + dev->agp->base);
+               buf->next = NULL;
+               buf->waiting = 0;
+               buf->pending = 0;
+               init_waitqueue_head(&buf->dma_wait);
+               buf->pid = 0;
+
+               buf->dev_private = drm_alloc(sizeof(drm_mga_buf_priv_t), DRM_MEM_BUFS);
+               buf->dev_priv_size = sizeof(drm_mga_buf_priv_t);
 
 #if DRM_DMA_HISTOGRAM
-      buf->time_queued = 0;
-      buf->time_dispatched = 0;
-      buf->time_completed = 0;
-      buf->time_freed = 0;
+               buf->time_queued = 0;
+               buf->time_dispatched = 0;
+               buf->time_completed = 0;
+               buf->time_freed = 0;
 #endif
-      offset = offset + alignment;
-      entry->buf_count++;
-      byte_count += PAGE_SIZE << page_order;
+               offset = offset + alignment;
+               entry->buf_count++;
+               byte_count += PAGE_SIZE << page_order;
       
-      DRM_DEBUG("buffer %d @ %p\n",
-            entry->buf_count, buf->address);
-   }
+               DRM_DEBUG("buffer %d @ %p\n",
+                         entry->buf_count, buf->address);
+       }
    
-   dma->buflist = drm_realloc(dma->buflist,
-                             dma->buf_count * sizeof(*dma->buflist),
-                             (dma->buf_count + entry->buf_count)
-                             * sizeof(*dma->buflist),
-                             DRM_MEM_BUFS);
-   for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
-     dma->buflist[i] = &entry->buflist[i - dma->buf_count];
+       dma->buflist = drm_realloc(dma->buflist,
+                                  dma->buf_count * sizeof(*dma->buflist),
+                                  (dma->buf_count + entry->buf_count)
+                                  * sizeof(*dma->buflist),
+                                  DRM_MEM_BUFS);
+       for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
+               dma->buflist[i] = &entry->buflist[i - dma->buf_count];
    
-   dma->buf_count  += entry->buf_count;
+       dma->buf_count  += entry->buf_count;
 
-   DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
 
-   dma->byte_count += byte_count;
+       dma->byte_count += byte_count;
 
-   DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
 
-   drm_freelist_create(&entry->freelist, entry->buf_count);
-   for (i = 0; i < entry->buf_count; i++) {
-      drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
-   }
+       drm_freelist_create(&entry->freelist, entry->buf_count);
+       for (i = 0; i < entry->buf_count; i++) {
+               drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
+       }
    
-   up(&dev->struct_sem);
+       up(&dev->struct_sem);
    
-   request.count = entry->buf_count;
-   request.size  = size;
+       request.count = entry->buf_count;
+       request.size  = size;
    
-   copy_to_user_ret((drm_buf_desc_t *)arg,
-                   &request,
-                   sizeof(request),
-                   -EFAULT);
+       copy_to_user_ret((drm_buf_desc_t *)arg,
+                        &request,
+                        sizeof(request),
+                        -EFAULT);
    
-   atomic_dec(&dev->buf_alloc);
+       atomic_dec(&dev->buf_alloc);
 
-   DRM_DEBUG("count: %d\n", count);
-   DRM_DEBUG("order: %d\n", order);
-   DRM_DEBUG("size: %d\n", size);
-   DRM_DEBUG("agp_offset: %d\n", agp_offset);
-   DRM_DEBUG("alignment: %d\n", alignment);
-   DRM_DEBUG("page_order: %d\n", page_order);
-   DRM_DEBUG("total: %d\n", total);
-   DRM_DEBUG("byte_count: %d\n", byte_count);
+       DRM_DEBUG("count: %d\n", count);
+       DRM_DEBUG("order: %d\n", order);
+       DRM_DEBUG("size: %d\n", size);
+       DRM_DEBUG("agp_offset: %ld\n", agp_offset);
+       DRM_DEBUG("alignment: %d\n", alignment);
+       DRM_DEBUG("page_order: %d\n", page_order);
+       DRM_DEBUG("total: %d\n", total);
+       DRM_DEBUG("byte_count: %d\n", byte_count);
 
-   dma->flags = _DRM_DMA_USE_AGP;
+       dma->flags = _DRM_DMA_USE_AGP;
 
-   DRM_DEBUG("dma->flags : %lx\n", dma->flags);
+       DRM_DEBUG("dma->flags : %x\n", dma->flags);
 
-   return 0;
+       return 0;
 }
 
 int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -362,17 +361,17 @@ int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
 int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
                unsigned long arg)
 {
-   drm_buf_desc_t       request;
+       drm_buf_desc_t   request;
 
-   copy_from_user_ret(&request,
-                     (drm_buf_desc_t *)arg,
-                     sizeof(request),
-                     -EFAULT);
+       copy_from_user_ret(&request,
+                          (drm_buf_desc_t *)arg,
+                          sizeof(request),
+                          -EFAULT);
 
-   if(request.flags & _DRM_AGP_BUFFER)
-     return mga_addbufs_agp(inode, filp, cmd, arg);
-   else
-     return mga_addbufs_pci(inode, filp, cmd, arg);
+       if(request.flags & _DRM_AGP_BUFFER)
+               return mga_addbufs_agp(inode, filp, cmd, arg);
+       else
+               return mga_addbufs_pci(inode, filp, cmd, arg);
 }
 
 int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -546,7 +545,7 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
        spin_lock(&dev->count_lock);
        if (atomic_read(&dev->buf_alloc)) {
                spin_unlock(&dev->count_lock);
-          DRM_DEBUG("Buzy\n");
+               DRM_DEBUG("Busy\n");
                return -EBUSY;
        }
        ++dev->buf_use;         /* Can't allocate more after this call */
@@ -558,79 +557,84 @@ int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
                           -EFAULT);
 
        DRM_DEBUG("mga_mapbufs\n");
-       DRM_DEBUG("dma->flags : %lx\n", dma->flags);
+       DRM_DEBUG("dma->flags : %x\n", dma->flags);
    
-   if (request.count >= dma->buf_count) {
-      if(dma->flags & _DRM_DMA_USE_AGP) {
-        drm_mga_private_t *dev_priv = dev->dev_private;
-        drm_map_t *map = NULL;
+       if (request.count >= dma->buf_count) {
+               if(dma->flags & _DRM_DMA_USE_AGP) {
+                       drm_mga_private_t *dev_priv = dev->dev_private;
+                       drm_map_t *map = NULL;
         
-        map = dev->maplist[dev_priv->buffer_map_idx];
-        if (!map) {
-           DRM_DEBUG("map is null\n");
-           retcode = -EINVAL;
-           goto done;
-        }
-
-        DRM_DEBUG("map->offset : %lx\n", map->offset);
-        DRM_DEBUG("map->size : %lx\n", map->size);
-        DRM_DEBUG("map->type : %d\n", map->type);
-        DRM_DEBUG("map->flags : %x\n", map->flags);
-        DRM_DEBUG("map->handle : %lx\n", map->handle);
-        DRM_DEBUG("map->mtrr : %d\n", map->mtrr);
-
-        virtual = do_mmap(filp, 0, map->size, PROT_READ|PROT_WRITE,
-                          MAP_SHARED, (unsigned long)map->offset);
-      } else {
-             virtual = do_mmap(filp, 0, dma->byte_count,
-                               PROT_READ|PROT_WRITE, MAP_SHARED, 0);
-      }
-      if (virtual > -1024UL) {
-        /* Real error */
-        DRM_DEBUG("mmap error\n");
-        retcode = (signed long)virtual;
-        goto done;
-      }
-      request.virtual = (void *)virtual;
+                       map = dev->maplist[dev_priv->buffer_map_idx];
+                       if (!map) {
+                               DRM_DEBUG("map is null\n");
+                               retcode = -EINVAL;
+                               goto done;
+                       }
+
+                       DRM_DEBUG("map->offset : %lx\n", map->offset);
+                       DRM_DEBUG("map->size : %lx\n", map->size);
+                       DRM_DEBUG("map->type : %d\n", map->type);
+                       DRM_DEBUG("map->flags : %x\n", map->flags);
+                       DRM_DEBUG("map->handle : %p\n", map->handle);
+                       DRM_DEBUG("map->mtrr : %d\n", map->mtrr);
+                       down(&current->mm->mmap_sem);
+                       virtual = do_mmap(filp, 0, map->size, 
+                                         PROT_READ|PROT_WRITE,
+                                         MAP_SHARED, 
+                                         (unsigned long)map->offset);
+                       up(&current->mm->mmap_sem);
+               } else {
+                       down(&current->mm->mmap_sem);
+                       virtual = do_mmap(filp, 0, dma->byte_count,
+                                         PROT_READ|PROT_WRITE, MAP_SHARED, 0);
+                       up(&current->mm->mmap_sem);
+               }
+               if (virtual > -1024UL) {
+                       /* Real error */
+                       DRM_DEBUG("mmap error\n");
+                       retcode = (signed long)virtual;
+                       goto done;
+               }
+               request.virtual = (void *)virtual;
       
-      for (i = 0; i < dma->buf_count; i++) {
-        if (copy_to_user(&request.list[i].idx,
-                         &dma->buflist[i]->idx,
-                         sizeof(request.list[0].idx))) {
-           retcode = -EFAULT;
-           goto done;
-        }
-        if (copy_to_user(&request.list[i].total,
-                         &dma->buflist[i]->total,
-                         sizeof(request.list[0].total))) {
-           retcode = -EFAULT;
-           goto done;
-        }
-        if (copy_to_user(&request.list[i].used,
-                         &zero,
-                         sizeof(zero))) {
-           retcode = -EFAULT;
-           goto done;
-        }
-        address = virtual + dma->buflist[i]->offset;
-        if (copy_to_user(&request.list[i].address,
-                         &address,
-                         sizeof(address))) {
-           retcode = -EFAULT;
-           goto done;
-        }
-      }
-   }
  done:
-   request.count = dma->buf_count;
-   DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
+               for (i = 0; i < dma->buf_count; i++) {
+                       if (copy_to_user(&request.list[i].idx,
+                                        &dma->buflist[i]->idx,
+                                        sizeof(request.list[0].idx))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+                       if (copy_to_user(&request.list[i].total,
+                                        &dma->buflist[i]->total,
+                                        sizeof(request.list[0].total))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+                       if (copy_to_user(&request.list[i].used,
+                                        &zero,
+                                        sizeof(zero))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+                       address = virtual + dma->buflist[i]->offset;
+                       if (copy_to_user(&request.list[i].address,
+                                        &address,
+                                        sizeof(address))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+               }
+       }
+ done:
+       request.count = dma->buf_count;
+       DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
    
-   copy_to_user_ret((drm_buf_map_t *)arg,
-                   &request,
-                   sizeof(request),
-                   -EFAULT);
+       copy_to_user_ret((drm_buf_map_t *)arg,
+                        &request,
+                        sizeof(request),
+                        -EFAULT);
 
-   DRM_DEBUG("retcode : %d\n", retcode);
+       DRM_DEBUG("retcode : %d\n", retcode);
 
-   return retcode;
+       return retcode;
 }