You can see attached the changes made done so far (patch relative to
current HEAD). It's actually very little but I want to be sure we're all
aiming on the same direction.

Basically these are the new semantics: for all API entries which are
interesting from within a DRM kernel module (such as
PCI/AGP/scatter-gather memory allocation) there are two versions:
 - an internal version, which does little or no booking of the memory
   allocated (is up to the kernel driver to release all its privatly
   allocated stuff when user program exits)
 - an external (*_ioctl names) which calls the one aboves but keep
   tracks of everything to prevent leaking memory.

This mean that a driver from now on has the choice whether to setup the
AGP/PCI/SG DMA memory from the DDX or from the DRM. Of course, my
personal choice goes to do all the memory allocations within the DRM, to
avoid so many data structure duplication, leaving to X/fbdev the
MMIO/framebuffer setup. Note that who uses the DMA memory on the end is
a completely seperate issue - everybody can use everything as long as
premission to do so is given. 

One issue I haven't decided yet is the memory mapping. A driver which
setups the DMA in X (as all current drivers do) the memory mapping is
processed as follows: 1. X allocates memory (via drmAGP* for AGP) 2. X
adds a mapping for that memory in the kernel, anc receives a hanlde for
that mapping.  3. Client receives the handle in screen initialization.
4. Client requests the memory to be mapped with that handle.

For a driver which setups its memory from within the DRM I don't see
much point in going through the same process, and the DRM simply would
map the necessary stuff (such as vertex buffers, and texture area) - as
is currently done with drmMapBufs, and give the virtual addresses, in
single IOCTL.

Comments are welcome.

I would also like to now whether the APIs in drm_pci.h would pose any
difficulty for other OS's.

Regards,

José Fonseca
? .drmP.h.swp
? .drm_agpsupport.h.swp
? .drm_bufs.h.swp
? .drm_drv.h.swp
? .drm_pci.h.swp
? .radeon_cp.c.swp
? drm_pci.h
? drm_sarea.h
? mga.h
? mga_dma.c
? mga_drm.h
? mga_drv.h
? mga_irq.c
? mga_state.c
? mga_ucode.h
? mga_warp.c
? r128.h
? r128_cce.c
? r128_drm.h
? r128_drv.h
? r128_irq.c
? r128_state.c
? radeon.h
? radeon_cp.c
? radeon_drm.h
? radeon_drv.h
? radeon_irq.c
? radeon_mem.c
? radeon_state.c
Index: drm.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h,v
retrieving revision 1.41
diff -u -r1.41 drm.h
--- drm.h       12 Dec 2002 22:20:30 -0000      1.41
+++ drm.h       26 Feb 2003 21:25:31 -0000
@@ -408,6 +408,16 @@
        unsigned long handle;   /* Used for mapping / unmapping */
 } drm_scatter_gather_t;
 
+/**
+ * \brief PCI consistent memory block, for DMA.
+ *
+ * \warning Not stable.
+ */
+typedef struct drm_pci_mem_ioctl {
+       unsigned long   size;           /**< \brief size */
+       unsigned long   busaddr;        /**< \brief associated bus address */
+} drm_pci_mem_ioctl_t;
+
 #define DRM_IOCTL_BASE                 'd'
 #define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
 #define DRM_IOR(nr,type)               _IOR(DRM_IOCTL_BASE,nr,type)
Index: drmP.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v
retrieving revision 1.57
diff -u -r1.57 drmP.h
--- drmP.h      21 Feb 2003 23:23:07 -0000      1.57
+++ drmP.h      26 Feb 2003 21:25:34 -0000
@@ -477,6 +477,16 @@
        wait_queue_head_t waiting;      /* Processes waiting on free bufs  */
 } drm_device_dma_t;
 
+/**
+ * \brief PCI consistent memory block, for DMA.
+ */
+typedef struct drm_pci_mem {
+       struct list_head        list;           /**< \brief Linux list */
+       size_t                  size;           /**< \brief size */
+       void                    *cpuaddr;       /**< \brief kernel virtual address */
+       dma_addr_t              busaddr;        /**< \brief associated bus address */
+} drm_pci_mem_t;
+
 #if __REALLY_HAVE_AGP
 typedef struct drm_agp_mem {
        unsigned long      handle;
@@ -629,6 +639,8 @@
        void              *dev_private;
        drm_sigdata_t     sigdata; /* For block_all_signals */
        sigset_t          sigmask;
+
+       struct list_head  pci_mem;      /**< \brief PCI consistent memory */
 } drm_device_t;
 
 
@@ -792,9 +804,9 @@
 
                                /* Buffer management support (drm_bufs.h) */
 extern int          DRM(order)( unsigned long size );
-extern int          DRM(addmap)( struct inode *inode, struct file *filp,
+extern int          DRM(addmap_ioctl)( struct inode *inode, struct file *filp,
                                  unsigned int cmd, unsigned long arg );
-extern int          DRM(rmmap)( struct inode *inode, struct file *filp,
+extern int          DRM(rmmap_ioctl)( struct inode *inode, struct file *filp,
                                 unsigned int cmd, unsigned long arg );
 #if __HAVE_DMA
 extern int          DRM(addbufs)( struct inode *inode, struct file *filp,
@@ -867,23 +879,23 @@
                                /* AGP/GART support (drm_agpsupport.h) */
 extern drm_agp_head_t *DRM(agp_init)(void);
 extern void           DRM(agp_uninit)(void);
-extern int            DRM(agp_acquire)(struct inode *inode, struct file *filp,
-                                      unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_acquire_ioctl)(struct inode *inode, struct file *filp,
+                                            unsigned int cmd, unsigned long arg);
 extern void           DRM(agp_do_release)(void);
-extern int            DRM(agp_release)(struct inode *inode, struct file *filp,
-                                      unsigned int cmd, unsigned long arg);
-extern int            DRM(agp_enable)(struct inode *inode, struct file *filp,
-                                     unsigned int cmd, unsigned long arg);
-extern int            DRM(agp_info)(struct inode *inode, struct file *filp,
-                                   unsigned int cmd, unsigned long arg);
-extern int            DRM(agp_alloc)(struct inode *inode, struct file *filp,
-                                    unsigned int cmd, unsigned long arg);
-extern int            DRM(agp_free)(struct inode *inode, struct file *filp,
-                                   unsigned int cmd, unsigned long arg);
-extern int            DRM(agp_unbind)(struct inode *inode, struct file *filp,
-                                     unsigned int cmd, unsigned long arg);
-extern int            DRM(agp_bind)(struct inode *inode, struct file *filp,
-                                   unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_release_ioctl)(struct inode *inode, struct file *filp,
+                                            unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_enable_ioctl)(struct inode *inode, struct file *filp,
+                                           unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_info_ioctl)(struct inode *inode, struct file *filp,
+                                         unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_alloc_ioctl)(struct inode *inode, struct file *filp,
+                                          unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_free_ioctl)(struct inode *inode, struct file *filp,
+                                         unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_unbind_ioctl)(struct inode *inode, struct file *filp,
+                                           unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_bind_ioctl)(struct inode *inode, struct file *filp,
+                                         unsigned int cmd, unsigned long arg);
 extern agp_memory     *DRM(agp_allocate_memory)(size_t pages, u32 type);
 extern int            DRM(agp_free_memory)(agp_memory *handle);
 extern int            DRM(agp_bind_memory)(agp_memory *handle, off_t start);
@@ -907,11 +919,12 @@
 
 #if __HAVE_SG
                                /* Scatter Gather Support (drm_scatter.h) */
-extern void           DRM(sg_cleanup)(drm_sg_mem_t *entry);
-extern int            DRM(sg_alloc)(struct inode *inode, struct file *filp,
-                                   unsigned int cmd, unsigned long arg);
-extern int            DRM(sg_free)(struct inode *inode, struct file *filp,
-                                  unsigned int cmd, unsigned long arg);
+extern drm_sg_mem_t   *DRM(sg_alloc)(unsigned long size);
+extern void           DRM(sg_free)(drm_sg_mem_t *entry);
+extern int            DRM(sg_alloc_ioctl)(struct inode *inode, struct file *filp,
+                                         unsigned int cmd, unsigned long arg);
+extern int            DRM(sg_free_ioctl)(struct inode *inode, struct file *filp,
+                                        unsigned int cmd, unsigned long arg);
 #endif
 
                                /* ATI PCIGART support (ati_pcigart.h) */
Index: drm_agpsupport.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_agpsupport.h,v
retrieving revision 1.10
diff -u -r1.10 drm_agpsupport.h
--- drm_agpsupport.h    11 Dec 2002 13:40:27 -0000      1.10
+++ drm_agpsupport.h    26 Feb 2003 21:25:36 -0000
@@ -40,8 +40,8 @@
 
 static const drm_agp_t *drm_agp = NULL;
 
-int DRM(agp_info)(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+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->dev;
@@ -67,8 +67,8 @@
        return 0;
 }
 
-int DRM(agp_acquire)(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+int DRM(agp_acquire_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->dev;
@@ -81,8 +81,8 @@
        return 0;
 }
 
-int DRM(agp_release)(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+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->dev;
@@ -100,8 +100,8 @@
        if (drm_agp->release) drm_agp->release();
 }
 
-int DRM(agp_enable)(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg)
+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->dev;
@@ -120,8 +120,8 @@
        return 0;
 }
 
-int DRM(agp_alloc)(struct inode *inode, struct file *filp,
-                  unsigned int cmd, unsigned long arg)
+int DRM(agp_alloc_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->dev;
@@ -180,8 +180,8 @@
        return NULL;
 }
 
-int DRM(agp_unbind)(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg)
+int DRM(agp_unbind_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->dev;
@@ -197,8 +197,8 @@
        return DRM(unbind_agp)(entry->memory);
 }
 
-int DRM(agp_bind)(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int DRM(agp_bind_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->dev;
@@ -222,8 +222,8 @@
        return 0;
 }
 
-int DRM(agp_free)(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int DRM(agp_free_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->dev;
Index: drm_bufs.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_bufs.h,v
retrieving revision 1.15
diff -u -r1.15 drm_bufs.h
--- drm_bufs.h  21 Sep 2002 23:18:54 -0000      1.15
+++ drm_bufs.h  26 Feb 2003 21:25:39 -0000
@@ -68,8 +68,8 @@
        return order;
 }
 
-int DRM(addmap)( struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg )
+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->dev;
@@ -191,8 +191,8 @@
  * isn't in use.
  */
 
-int DRM(rmmap)(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+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->dev;
Index: drm_drv.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h,v
retrieving revision 1.24
diff -u -r1.24 drm_drv.h
--- drm_drv.h   25 Sep 2002 17:18:19 -0000      1.24
+++ drm_drv.h   26 Feb 2003 21:25:39 -0000
@@ -171,8 +171,8 @@
        [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { DRM(unblock),     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_RM_MAP)]        = { DRM(rmmap),       1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { DRM(addmap_ioctl),      1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { DRM(rmmap_ioctl),       1, 0 },
 
 #if __HAVE_CTX_BITMAP
        [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
@@ -207,19 +207,19 @@
 #endif
 
 #if __REALLY_HAVE_AGP
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { DRM(agp_acquire), 1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { DRM(agp_release), 1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { DRM(agp_enable),  1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { DRM(agp_info),    1, 0 },
-       [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_BIND)]      = { DRM(agp_bind),    1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  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_ioctl), 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_ioctl),    1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { DRM(agp_alloc_ioctl),   1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { DRM(agp_free_ioctl),    1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { DRM(agp_bind_ioctl),    1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind_ioctl),  1, 1 },
 #endif
 
 #if __HAVE_SG
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { DRM(sg_alloc),    1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { DRM(sg_alloc_ioctl),    1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free_ioctl),     1, 1 },
 #endif
 
 #if __HAVE_VBL_IRQ
@@ -460,7 +460,7 @@
                                 */
 #if __HAVE_SG
                                if(dev->sg) {
-                                       DRM(sg_cleanup)(dev->sg);
+                                       DRM(sg_free)(dev->sg);
                                        dev->sg = NULL;
                                }
 #endif
Index: drm_scatter.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_scatter.h,v
retrieving revision 1.9
diff -u -r1.9 drm_scatter.h
--- drm_scatter.h       16 May 2002 23:47:15 -0000      1.9
+++ drm_scatter.h       26 Feb 2003 21:25:39 -0000
@@ -34,7 +34,7 @@
 
 #define DEBUG_SCATTER 0
 
-void DRM(sg_cleanup)( drm_sg_mem_t *entry )
+void DRM(sg_free)( drm_sg_mem_t *entry )
 {
        struct page *page;
        int i;
@@ -58,40 +58,28 @@
                   DRM_MEM_SGLISTS );
 }
 
-int DRM(sg_alloc)( struct inode *inode, struct file *filp,
-                  unsigned int cmd, unsigned long arg )
+drm_sg_mem_t * DRM(sg_alloc)( unsigned long size )
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->dev;
-       drm_scatter_gather_t request;
        drm_sg_mem_t *entry;
        unsigned long pages, i, j;
 
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( dev->sg )
-               return -EINVAL;
-
-       if ( copy_from_user( &request,
-                            (drm_scatter_gather_t *)arg,
-                            sizeof(request) ) )
-               return -EFAULT;
-
        entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
        if ( !entry )
-               return -ENOMEM;
+               return NULL;
 
        memset( entry, 0, sizeof(*entry) );
 
-       pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
-       DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
+       pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+       DRM_DEBUG( "sg size=%ld pages=%ld\n", size, pages );
 
        entry->pages = pages;
        entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
                                     DRM_MEM_PAGES );
        if ( !entry->pagelist ) {
                DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
-               return -ENOMEM;
+               return NULL;
        }
 
        memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
@@ -105,7 +93,7 @@
                DRM(free)( entry,
                           sizeof(*entry),
                           DRM_MEM_SGLISTS );
-               return -ENOMEM;
+               return NULL;
        }
        memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
 
@@ -120,7 +108,7 @@
                DRM(free)( entry,
                           sizeof(*entry),
                           DRM_MEM_SGLISTS );
-               return -ENOMEM;
+               return NULL;
        }
 
        /* This also forces the mapping of COW pages, so our page list
@@ -140,17 +128,6 @@
                SetPageReserved(entry->pagelist[j]);
        }
 
-       request.handle = entry->handle;
-
-       if ( copy_to_user( (drm_scatter_gather_t *)arg,
-                          &request,
-                          sizeof(request) ) ) {
-               DRM(sg_cleanup)( entry );
-               return -EFAULT;
-       }
-
-       dev->sg = entry;
-
 #if DEBUG_SCATTER
        /* Verify that each page points to its virtual address, and vice
         * versa.
@@ -191,14 +168,50 @@
        }
 #endif
 
-       return 0;
+       return entry;
 
  failed:
-       DRM(sg_cleanup)( entry );
-       return -ENOMEM;
+       DRM(sg_free)( entry );
+       return NULL;
+}
+
+int DRM(sg_alloc_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->dev;
+       drm_scatter_gather_t request;
+       drm_sg_mem_t *entry;
+
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       if ( dev->sg )
+               return -EINVAL;
+
+       if ( copy_from_user( &request,
+                            (drm_scatter_gather_t *)arg,
+                            sizeof(request) ) )
+               return -EFAULT;
+
+       entry = DRM(sg_alloc)( request.size  );
+       if ( !entry )
+               return -ENOMEM;
+
+       request.handle = entry->handle;
+
+       if ( copy_to_user( (drm_scatter_gather_t *)arg,
+                          &request,
+                          sizeof(request) ) ) {
+               DRM(sg_free)( entry );
+               return -EFAULT;
+       }
+
+       dev->sg = entry;
+
+       return 0;
 }
 
-int DRM(sg_free)( struct inode *inode, struct file *filp,
+int DRM(sg_free_ioctl)( struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg )
 {
        drm_file_t *priv = filp->private_data;
@@ -219,7 +232,7 @@
 
        DRM_DEBUG( "sg free virtual  = %p\n", entry->virtual );
 
-       DRM(sg_cleanup)( entry );
+       DRM(sg_free)( entry );
 
        return 0;
 }
Index: radeon_drv.c
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c,v
retrieving revision 1.17
diff -u -r1.17 radeon_drv.c
--- radeon_drv.c        5 Jul 2002 08:31:10 -0000       1.17
+++ radeon_drv.c        26 Feb 2003 21:25:39 -0000
@@ -51,3 +51,4 @@
 #include "drm_vm.h"
 #include "drm_stub.h"
 #include "drm_scatter.h"
+#include "drm_pci.h"
/**
 * \file drm_pci.h
 * \brief ioctl's to manage PCI memory
 * 
 * \author José Fonseca <[EMAIL PROTECTED]>
 */

/*
 * Copyright 2003 José Fonseca.
 * 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.
 */

#define __NO_VERSION__
#include <linux/pci.h>
#include "drmP.h"

/**********************************************************************/
/* \name PCI memory */
/[EMAIL PROTECTED]/

/**
 * \brief Allocate a PCI consistent memory block, for DMA.
 */
void * DRM(pci_alloc)( drm_device_t *dev, size_t size, dma_addr_t *busaddr )
{
        return pci_alloc_consistent( dev->pdev, size, busaddr );
}

/**
 * \brief Free a PCI consistent memory block.
 */
void DRM(pci_free)( drm_device_t *dev, size_t size, void *cpuaddr, dma_addr_t busaddr )
{
        DRM_DEBUG( "%s\n", __FUNCTION__ );

        pci_free_consistent( dev->pdev, size, cpuaddr, busaddr );
}

/[EMAIL PROTECTED]/


/**********************************************************************/
/* \name PCI memory pool */
/[EMAIL PROTECTED]/

/**
 * \brief Create a pool of PCI consistent memory blocks, for DMA.
 *
 * \return a handle on success, or NULL on failure.
 * 
 * \note This is a minimalistic wrapper around Linux's pci_pool_create()
 * function to ease porting to other OS's. More functionality can be exposed
 * later if actually required by the drivers.
 */
void *DRM(pci_pool_create)( drm_device_t *dev, size_t size, size_t align )
{
        DRM_DEBUG( "%s\n", __FUNCTION__ );

        return pci_pool_create( "DRM", dev->pdev, size, align, 0, 0);
}

/**
 * \brief Destroy a pool of PCI consistent memory blocks.
 */
void DRM(pci_pool_destroy)( drm_device_t *dev, void *entry )
{
        DRM_DEBUG( "%s\n", __FUNCTION__ );

        pci_pool_destroy( (struct pci_pool *)entry );
}

/**
 * \brief Allocate a block from a PCI consistent memory block pool.
 *
 * \return the virtual address of a block on success, or NULL on failure. 
 */
void *DRM(pci_pool_alloc)( void *entry, dma_addr_t *busaddr )
{
        DRM_DEBUG( "%s\n", __FUNCTION__ );

        return pci_pool_alloc( (struct pci_pool *)entry, 0, busaddr );
}

/**
 * \brief Free a block back into a PCI consistent memory block pool.
 */
void DRM(pci_pool_free)( void *entry, void *cpuaddr, dma_addr_t busaddr )
{
        DRM_DEBUG( "%s\n", __FUNCTION__ );

        pci_pool_free( (struct pci_pool *)entry, cpuaddr, busaddr );
}

/[EMAIL PROTECTED]/


/**********************************************************************/
/* \name Ioctl's
 *
 * \todo Implement the remaining ioctl's.
 * \todo Book keep all allocated memory to recover it when the client dies.
 * \todo Map these buffers.
 *
 * \warning These interfaces aren't stable yet.
 */
/[EMAIL PROTECTED]/

int DRM(pci_alloc_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->dev;
        drm_pci_mem_ioctl_t request;
        drm_pci_mem_t *entry;

        DRM_DEBUG( "%s\n", __FUNCTION__ );

        if ( copy_from_user( &request,
                             (drm_pci_mem_ioctl_t *)arg,
                             sizeof(request) ) )
                return -EFAULT;

        entry = DRM(alloc)( sizeof(*entry), DRM_MEM_DRIVER );
        if ( !entry )
                return -ENOMEM;

        memset( entry, 0, sizeof(*entry) );

        entry->cpuaddr = DRM(pci_alloc)( dev, request.size, 
                                         &entry->busaddr );
        
        if ( !entry->cpuaddr ) {
                DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER );
                return -ENOMEM;
        }

        entry->size = request.size;
        request.busaddr = entry->busaddr;

        if ( copy_to_user( (drm_pci_mem_ioctl_t *)arg,
                           &request,
                           sizeof(request) ) ) {
                DRM(pci_free)( dev, entry->size, entry->cpuaddr, entry->busaddr );
                DRM(free)( entry, sizeof(*entry), DRM_MEM_DRIVER );
                return -EFAULT;
        }

        list_add( (struct list_head *)entry, &dev->pci_mem );
        
        return 0;
}

int DRM(pci_free_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->dev;
        drm_pci_mem_ioctl_t request;
        struct list_head *ptr;
        drm_pci_mem_t *entry;

        DRM_DEBUG( "%s\n", __FUNCTION__ );

        if ( copy_from_user( &request,
                             (drm_pci_mem_ioctl_t *)arg,
                             sizeof(request) ) )
                return -EFAULT;

        list_for_each(ptr, &dev->pci_mem)
        {
                entry = list_entry(ptr, drm_pci_mem_t, list);
                if( entry->busaddr == request.busaddr ) {
                        list_del(ptr);
                        DRM(pci_free)( dev, entry->size, entry->cpuaddr, 
entry->busaddr );
                        return 0;
                }
        }

        return -EFAULT;
}
/[EMAIL PROTECTED]/

Reply via email to