Merged ati-pcigart-1-0-0
authorKevin E Martin <kem@kem.org>
Thu, 5 Apr 2001 22:16:12 +0000 (22:16 +0000)
committerKevin E Martin <kem@kem.org>
Thu, 5 Apr 2001 22:16:12 +0000 (22:16 +0000)
42 files changed:
libdrm/xf86drm.c
linux-core/ati_pcigart.c [new file with mode: 0644]
linux-core/drmP.h
linux-core/drm_agpsupport.c
linux-core/drm_bufs.c
linux-core/drm_drv.c
linux-core/drm_fops.c
linux-core/drm_init.c
linux-core/drm_ioctl.c
linux-core/drm_memory.h
linux-core/drm_scatter.c [new file with mode: 0644]
linux-core/drm_vm.c
linux-core/r128_drv.c
linux-core/radeon_drv.c
linux/Makefile.linux
linux/ati_pcigart.h [new file with mode: 0644]
linux/drm.h
linux/drmP.h
linux/drm_agpsupport.h
linux/drm_bufs.h
linux/drm_drv.h
linux/drm_fops.h
linux/drm_init.h
linux/drm_ioctl.h
linux/drm_memory.h
linux/drm_scatter.h [new file with mode: 0644]
linux/drm_vm.h
linux/mga_drm.h
linux/r128.h
linux/r128_cce.c
linux/r128_drm.h
linux/r128_drv.c
linux/r128_drv.h
linux/r128_state.c
linux/radeon.h
linux/radeon_cp.c
linux/radeon_drm.h
linux/radeon_drv.c
linux/radeon_drv.h
linux/radeon_state.c
shared-core/drm.h
shared/drm.h

index 8267588..bb719ed 100644 (file)
@@ -67,11 +67,6 @@ extern int xf86RemoveSIGIOHandler(int fd);
 # endif
 #endif
 
-#ifdef __alpha__
-extern unsigned long _bus_base(void);
-#define BUS_BASE _bus_base()
-#endif
-
 /* Not all systems have MAP_FAILED defined */
 #ifndef MAP_FAILED
 #define MAP_FAILED ((void *)-1)
@@ -490,11 +485,6 @@ int drmAddMap(int fd,
     drm_map_t map;
 
     map.offset  = offset;
-#ifdef __alpha__
-    /* Make sure we add the bus_base to all but shm */
-    if (type != DRM_SHM)
-       map.offset += BUS_BASE;
-#endif
     map.size    = size;
     map.handle  = 0;
     map.type    = type;
@@ -998,6 +988,28 @@ unsigned int drmAgpDeviceId(int fd)
     return i.id_device;
 }
 
+int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
+{
+    drm_scatter_gather_t sg;
+
+    *handle = 0;
+    sg.size   = size;
+    sg.handle = 0;
+    if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
+    *handle = sg.handle;
+    return 0;
+}
+
+int drmScatterGatherFree(int fd, unsigned long handle)
+{
+    drm_scatter_gather_t sg;
+
+    sg.size   = 0;
+    sg.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
+    return 0;
+}
+
 int drmError(int err, const char *label)
 {
     switch (err) {
diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c
new file mode 100644 (file)
index 0000000..93c5148
--- /dev/null
@@ -0,0 +1,138 @@
+/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
+ * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#if PAGE_SIZE == 8192
+# define ATI_PCIGART_TABLE_ORDER       2
+# define ATI_PCIGART_TABLE_PAGES       (1 << 2)
+#elif PAGE_SIZE == 4096
+# define ATI_PCIGART_TABLE_ORDER       3
+# define ATI_PCIGART_TABLE_PAGES       (1 << 3)
+#elif
+# error - PAGE_SIZE not 8K or 4K
+#endif
+
+# define ATI_MAX_PCIGART_PAGES         8192    /* 32 MB aperture, 4K pages */
+# define ATI_PCIGART_PAGE_SIZE         4096    /* PCI GART page size */
+
+static unsigned long DRM(ati_alloc_pcigart_table)( void )
+{
+       unsigned long address;
+       struct page *page;
+       int i;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
+       if ( address == 0UL ) {
+               return 0;
+       }
+
+       page = virt_to_page( address );
+
+       for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+               atomic_inc( &page->count );
+               SetPageReserved( page );
+       }
+
+       DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
+       return address;
+}
+
+static void DRM(ati_free_pcigart_table)( unsigned long address )
+{
+       struct page *page;
+       int i;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       if ( !address ) return;
+
+       page = virt_to_page( address );
+
+       for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+               atomic_dec( &page->count );
+               ClearPageReserved( page );
+       }
+
+       free_pages( address, ATI_PCIGART_TABLE_ORDER );
+}
+
+unsigned long DRM(ati_pcigart_init)( drm_device_t *dev )
+{
+       drm_sg_mem_t *entry = dev->sg;
+       unsigned long address;
+       unsigned long pages;
+       u32 *pci_gart, page_base;
+       int i, j;
+
+       if ( !entry ) {
+               DRM_ERROR( "no scatter/gather memory!\n" );
+               return 0;
+       }
+
+       address = DRM(ati_alloc_pcigart_table)();
+       if ( !address ) {
+               DRM_ERROR( "cannot allocate PCI GART page!\n" );
+               return 0;
+       }
+
+       pci_gart = (u32 *)address;
+
+       pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
+               ? entry->pages : ATI_MAX_PCIGART_PAGES;
+
+       memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
+
+       for ( i = 0 ; i < pages ; i++ ) {
+               page_base = virt_to_bus( entry->pagelist[i]->virtual );
+               for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+                       *pci_gart++ = cpu_to_le32( page_base );
+                       page_base += ATI_PCIGART_PAGE_SIZE;
+               }
+       }
+
+#if __i386__
+       asm volatile ( "wbinvd" ::: "memory" );
+#else
+       mb();
+#endif
+
+       return address;
+}
+
+int DRM(ati_pcigart_cleanup)( unsigned long address )
+{
+
+       if ( address ) {
+               DRM(ati_free_pcigart_table)( address );
+       }
+
+       return 0;
+}
index 274e318..085d1cb 100644 (file)
@@ -53,7 +53,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>    /* For (un)lock_kernel */
 #include <linux/mm.h>
-#ifdef __alpha__
+#if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h> /* For pte_wrprotect */
 #endif
 #include <asm/io.h>
 #define DRM_MEM_BOUNDAGP  17
 #define DRM_MEM_CTXBITMAP 18
 #define DRM_MEM_STUB      19
+#define DRM_MEM_SGLISTS   20
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
@@ -199,7 +200,7 @@ __cmpxchg_u32(volatile int *m, int old, int new)
        unsigned long prev, cmp;
 
        __asm__ __volatile__(
-       "1:     ldl_l %0,%2\n"
+       "1:     ldl_l %0,%5\n"
        "       cmpeq %0,%3,%1\n"
        "       beq %1,2f\n"
        "       mov %4,%1\n"
@@ -210,7 +211,8 @@ __cmpxchg_u32(volatile int *m, int old, int new)
        "3:     br 1b\n"
        ".previous"
        : "=&r"(prev), "=&r"(cmp), "=m"(*m)
-       : "r"((long) old), "r"(new), "m"(*m));
+       : "r"((long) old), "r"(new), "m"(*m)
+       : "memory" );
 
        return prev;
 }
@@ -221,7 +223,7 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
        unsigned long prev, cmp;
 
        __asm__ __volatile__(
-       "1:     ldq_l %0,%2\n"
+       "1:     ldq_l %0,%5\n"
        "       cmpeq %0,%3,%1\n"
        "       beq %1,2f\n"
        "       mov %4,%1\n"
@@ -232,7 +234,8 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
        "3:     br 1b\n"
        ".previous"
        : "=&r"(prev), "=&r"(cmp), "=m"(*m)
-       : "r"((long) old), "r"(new), "m"(*m));
+       : "r"((long) old), "r"(new), "m"(*m)
+       : "memory" );
 
        return prev;
 }
@@ -284,12 +287,43 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
        return old;
 }
 
+#elif defined(__powerpc__)
+extern void __cmpxchg_called_with_bad_pointer(void);
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                      unsigned long new, int size)
+{
+       unsigned long prev;
+
+       switch (size) {
+       case 4:
+               __asm__ __volatile__(
+                       "sync;"
+                       "0:    lwarx %0,0,%1 ;"
+                       "      cmpl 0,%0,%3;"
+                       "      bne 1f;"
+                       "      stwcx. %2,0,%1;"
+                       "      bne- 0b;"
+                       "1:    "
+                       "sync;"
+                       : "=&r"(prev)
+                       : "r"(ptr), "r"(new), "r"(old)
+                       : "cr0", "memory");
+               return prev;
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#endif /* i386, powerpc & alpha */
+
+#ifndef __alpha__
 #define cmpxchg(ptr,o,n)                                               \
   ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),             \
                                 (unsigned long)(n),sizeof(*(ptr))))
-#endif /* i386 & alpha */
 #endif
 
+#endif /* !__HAVE_ARCH_CMPXCHG */
+
                                /* Macros to make printk easier */
 #define DRM_ERROR(fmt, arg...) \
        printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
@@ -547,7 +581,8 @@ typedef struct drm_device_dma {
        unsigned long     *pagelist;
        unsigned long     byte_count;
        enum {
-               _DRM_DMA_USE_AGP = 0x01
+               _DRM_DMA_USE_AGP = 0x01,
+               _DRM_DMA_USE_SG  = 0x02
        } flags;
 
                                /* DMA support */
@@ -579,6 +614,13 @@ typedef struct drm_agp_head {
 } drm_agp_head_t;
 #endif
 
+typedef struct drm_sg_mem {
+       unsigned long   handle;
+       void            *virtual;
+       int             pages;
+       struct page     **pagelist;
+} drm_sg_mem_t;
+
 typedef struct drm_sigdata {
        int           context;
        drm_hw_lock_t *lock;
@@ -667,6 +709,10 @@ typedef struct drm_device {
 #if __REALLY_HAVE_AGP
        drm_agp_head_t    *agp;
 #endif
+#ifdef __alpha__
+       struct pci_controler *hose;
+#endif
+       drm_sg_mem_t      *sg;  /* Scatter gather memory */
        unsigned long     *ctx_bitmap;
        void              *dev_private;
        drm_sigdata_t     sigdata; /* For block_all_signals */
@@ -718,6 +764,9 @@ extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
                                        unsigned long address,
                                        int write_access);
+extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                                      unsigned long address,
+                                      int write_access);
 #else
                                /* Return type changed in 2.3.23 */
 extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
@@ -729,6 +778,9 @@ extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
                                       unsigned long address,
                                       int write_access);
+extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                                     unsigned long address,
+                                     int write_access);
 #endif
 extern void         DRM(vm_open)(struct vm_area_struct *vma);
 extern void         DRM(vm_close)(struct vm_area_struct *vma);
@@ -947,5 +999,16 @@ extern int            DRM(proc_cleanup)(int minor,
                                        struct proc_dir_entry *root,
                                        struct proc_dir_entry *dev_root);
 
+                               /* 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);
+
+                               /* ATI PCIGART support (ati_pcigart.h) */
+extern unsigned long  DRM(ati_pcigart_init)(drm_device_t *dev);
+extern int            DRM(ati_pcigart_cleanup)(unsigned long address);
+
 #endif /* __KERNEL__ */
 #endif
index dfd0d8f..9b056c7 100644 (file)
@@ -52,7 +52,8 @@ int DRM(agp_info)(struct inode *inode, struct file *filp,
        agp_kern_info    *kern;
        drm_agp_info_t   info;
 
-       if (!dev->agp->acquired || !drm_agp->copy_info) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
+               return -EINVAL;
 
        kern                   = &dev->agp->agp_info;
        info.agp_version_major = kern->version.major;
@@ -77,7 +78,8 @@ int DRM(agp_acquire)(struct inode *inode, struct file *filp,
        drm_device_t     *dev    = priv->dev;
        int              retcode;
 
-       if (!dev->agp|| dev->agp->acquired || !drm_agp->acquire) return -EINVAL;
+       if (!dev->agp || dev->agp->acquired || !drm_agp->acquire)
+               return -EINVAL;
        if ((retcode = drm_agp->acquire())) return retcode;
        dev->agp->acquired = 1;
        return 0;
@@ -89,7 +91,8 @@ int DRM(agp_release)(struct inode *inode, struct file *filp,
        drm_file_t       *priv   = filp->private_data;
        drm_device_t     *dev    = priv->dev;
 
-       if (!dev->agp->acquired || !drm_agp->release) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->release)
+               return -EINVAL;
        drm_agp->release();
        dev->agp->acquired = 0;
        return 0;
@@ -108,7 +111,8 @@ int DRM(agp_enable)(struct inode *inode, struct file *filp,
        drm_device_t     *dev    = priv->dev;
        drm_agp_mode_t   mode;
 
-       if (!dev->agp->acquired || !drm_agp->enable) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->enable)
+               return -EINVAL;
 
        if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
                return -EFAULT;
@@ -131,7 +135,7 @@ int DRM(agp_alloc)(struct inode *inode, struct file *filp,
        unsigned long    pages;
        u32              type;
 
-       if (!dev->agp->acquired) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired) return -EINVAL;
        if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
@@ -188,7 +192,7 @@ int DRM(agp_unbind)(struct inode *inode, struct file *filp,
        drm_agp_binding_t request;
        drm_agp_mem_t     *entry;
 
-       if (!dev->agp->acquired) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired) return -EINVAL;
        if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
@@ -207,7 +211,8 @@ int DRM(agp_bind)(struct inode *inode, struct file *filp,
        int               retcode;
        int               page;
 
-       if (!dev->agp->acquired || !drm_agp->bind_memory) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory)
+               return -EINVAL;
        if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
@@ -229,7 +234,7 @@ int DRM(agp_free)(struct inode *inode, struct file *filp,
        drm_agp_buffer_t request;
        drm_agp_mem_t    *entry;
 
-       if (!dev->agp->acquired) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired) return -EINVAL;
        if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
index b111104..16af7bd 100644 (file)
 #define __HAVE_PCI_DMA         0
 #endif
 
+#ifndef __HAVE_SG
+#define __HAVE_SG              0
+#endif
+
 #ifndef DRIVER_BUF_PRIV_T
 #define DRIVER_BUF_PRIV_T              u32
 #endif
@@ -103,13 +107,16 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
        switch ( map->type ) {
        case _DRM_REGISTERS:
        case _DRM_FRAME_BUFFER:
-#ifndef __sparc__
+#if !defined(__sparc__) && !defined(__alpha__)
                if ( map->offset + map->size < map->offset ||
                     map->offset < virt_to_phys(high_memory) ) {
                        DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
                        return -EINVAL;
                }
 #endif
+#ifdef __alpha__
+               map->offset += dev->hose->mem_space->start;
+#endif
 #if __REALLY_HAVE_MTRR
                if ( map->type == _DRM_FRAME_BUFFER ||
                     (map->flags & _DRM_WRITE_COMBINING) ) {
@@ -135,10 +142,21 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
                break;
 #if __REALLY_HAVE_AGP
        case _DRM_AGP:
+#ifdef __alpha__
+               map->offset += dev->hose->mem_space->start;
+#endif
                map->offset = map->offset + dev->agp->base;
                map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
                break;
 #endif
+       case _DRM_SCATTER_GATHER:
+               if (!dev->sg) {
+                       DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EINVAL;
+               }
+               map->offset = map->offset + dev->sg->handle;
+               break;
+
        default:
                DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
                return -EINVAL;
@@ -237,6 +255,7 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
                        vfree(map->handle);
                        break;
                case _DRM_AGP:
+               case _DRM_SCATTER_GATHER:
                        break;
                }
                DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -565,6 +584,159 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 }
 #endif /* __HAVE_PCI_DMA */
 
+#ifdef __HAVE_SG
+int DRM(addbufs_sg)( 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;
+
+       if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
+                            sizeof(request) ) )
+               return -EFAULT;
+
+       count = request.count;
+       order = DRM(order)( request.size );
+       size = 1 << order;
+
+       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;
+       agp_offset = request.agp_start;
+
+       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 );
+
+       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 */
+       }
+
+       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;
+
+       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;
+
+               buf->offset  = (dma->byte_count + offset);
+               buf->bus_address = agp_offset + offset;
+               buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+               buf->next    = NULL;
+               buf->waiting = 0;
+               buf->pending = 0;
+               init_waitqueue_head( &buf->dma_wait );
+               buf->pid     = 0;
+
+               buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
+               buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+                                              DRM_MEM_BUFS );
+               memset( buf->dev_private, 0, buf->dev_priv_size );
+
+#if __HAVE_DMA_HISTOGRAM
+               buf->time_queued = 0;
+               buf->time_dispatched = 0;
+               buf->time_completed = 0;
+               buf->time_freed = 0;
+#endif
+               DRM_DEBUG( "buffer %d @ %p\n",
+                          entry->buf_count, buf->address );
+
+               offset += alignment;
+               entry->buf_count++;
+               byte_count += PAGE_SIZE << page_order;
+       }
+
+       DRM_DEBUG( "byte_count: %d\n", byte_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 = 0 ; i < entry->buf_count ; i++ ) {
+               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+       }
+
+       dma->buf_count += entry->buf_count;
+       dma->byte_count += byte_count;
+
+       DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+       DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+#if __HAVE_DMA_FREELIST
+       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] );
+       }
+#endif
+       up( &dev->struct_sem );
+
+       request.count = entry->buf_count;
+       request.size = size;
+
+       if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
+               return -EFAULT;
+
+       dma->flags = _DRM_DMA_USE_SG;
+
+       atomic_dec( &dev->buf_alloc );
+       return 0;
+}
+#endif /* __HAVE_SG */
+
 int DRM(addbufs)( struct inode *inode, struct file *filp,
                  unsigned int cmd, unsigned long arg )
 {
@@ -579,6 +751,11 @@ int DRM(addbufs)( struct inode *inode, struct file *filp,
                return DRM(addbufs_agp)( inode, filp, cmd, arg );
        else
 #endif
+#if __HAVE_SG
+       if ( request.flags & _DRM_SG_BUFFER )
+               return DRM(addbufs_sg)( inode, filp, cmd, arg );
+       else
+#endif
 #if __HAVE_PCI_DMA
                return DRM(addbufs_pci)( inode, filp, cmd, arg );
 #else
@@ -760,7 +937,8 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
                return -EFAULT;
 
        if ( request.count >= dma->buf_count ) {
-               if ( __HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP) ) {
+               if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
+                    (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
                        drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
 
                        if ( !map ) {
index 7447ca6..3791d7a 100644 (file)
@@ -81,6 +81,9 @@
 #ifndef __HAVE_COUNTERS
 #define __HAVE_COUNTERS                        0
 #endif
+#ifndef __HAVE_SG
+#define __HAVE_SG                      0
+#endif
 
 #ifndef DRIVER_PREINIT
 #define DRIVER_PREINIT()
@@ -178,6 +181,11 @@ static drm_ioctl_desc_t              DRM(ioctls)[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  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 },
+#endif
+
        DRIVER_IOCTLS
 };
 
@@ -415,6 +423,12 @@ static int DRM(takedown)( drm_device_t *dev )
                                 * handled in the AGP/GART driver.
                                 */
                                break;
+                       case _DRM_SCATTER_GATHER:
+                               if(dev->sg) {
+                                       DRM(sg_cleanup)(dev->sg);
+                                       dev->sg = NULL;
+                               }
+                               break;
                        }
                        DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
                }
index dd57476..75752b3 100644 (file)
@@ -70,6 +70,21 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
        }
        up(&dev->struct_sem);
 
+#ifdef __alpha__
+       /*
+        * Default the hose
+        */
+       if (!dev->hose) {
+               struct pci_dev *pci_dev;
+               pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+               if (pci_dev) dev->hose = pci_dev->sysdata;
+               if (!dev->hose) {
+                       struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+                       if (b) dev->hose = b->sysdata;
+               }
+       }
+#endif
+
        return 0;
 }
 
index 9ae9841..d9d8e3a 100644 (file)
 #define __NO_VERSION__
 #include "drmP.h"
 
+#if 0
+int DRM(flags) = DRM_FLAG_DEBUG;
+#else
 int DRM(flags) = 0;
+#endif
 
 /* drm_parse_option parses a single option.  See description for
  * drm_parse_options for details.
index 2fba6b0..1cc8f31 100644 (file)
@@ -95,6 +95,27 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
                                  DRM_MEM_DRIVER);
        sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
 
+#ifdef __alpha__
+       do {
+               struct pci_dev *pci_dev;
+                int b, d, f;
+                char *p;
+                for(p = dev->unique; p && *p && *p != ':'; p++);
+                if (!p || !*p) break;
+                b = (int)simple_strtoul(p+1, &p, 10);
+                if (*p != ':') break;
+                d = (int)simple_strtoul(p+1, &p, 10);
+                if (*p != ':') break;
+                f = (int)simple_strtoul(p+1, &p, 10);
+                if (*p) break;
+                pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
+                if (pci_dev)
+                        dev->hose = pci_dev->sysdata;
+        } while(0);
+#endif
+
        return 0;
 }
 
index 1763d9b..498937d 100644 (file)
@@ -63,6 +63,7 @@ static drm_mem_stats_t          DRM(mem_stats)[]   = {
        [DRM_MEM_MAPPINGS]  = { "mappings" },
        [DRM_MEM_BUFLISTS]  = { "buflists" },
        [DRM_MEM_AGPLISTS]  = { "agplist"  },
+       [DRM_MEM_SGLISTS]   = { "sglist"   },
        [DRM_MEM_TOTALAGP]  = { "totalagp" },
        [DRM_MEM_BOUNDAGP]  = { "boundagp" },
        [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c
new file mode 100644 (file)
index 0000000..a037107
--- /dev/null
@@ -0,0 +1,218 @@
+/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
+ * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/vmalloc.h>
+#include "drmP.h"
+
+#define DEBUG_SCATTER 0
+
+void DRM(sg_cleanup)( drm_sg_mem_t *entry )
+{
+       struct page *page;
+       int i;
+
+       for ( i = 0 ; i < entry->pages ; i++ ) {
+               page = entry->pagelist[i];
+               if ( page )
+                       ClearPageReserved( page );
+       }
+
+       vfree( entry->virtual );
+
+       DRM(free)( entry->pagelist,
+                 entry->pages * sizeof(*entry->pagelist),
+                 DRM_MEM_PAGES );
+       DRM(free)( entry,
+                 sizeof(*entry),
+                 DRM_MEM_SGLISTS );
+}
+
+int DRM(sg_alloc)( 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;
+       unsigned long pages, i, j;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       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;
+
+       memset( entry, 0, sizeof(*entry) );
+
+       pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+       DRM_DEBUG( "sg size=%ld pages=%ld\n", request.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;
+       }
+
+       entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
+       if ( !entry->virtual ) {
+               DRM(free)( entry->pagelist,
+                         entry->pages * sizeof(*entry->pagelist),
+                         DRM_MEM_PAGES );
+               DRM(free)( entry,
+                         sizeof(*entry),
+                         DRM_MEM_SGLISTS );
+               return -ENOMEM;
+       }
+
+       /* This also forces the mapping of COW pages, so our page list
+        * will be valid.  Please don't remove it...
+        */
+       memset( entry->virtual, 0, pages << PAGE_SHIFT );
+
+       entry->handle = (unsigned long)entry->virtual;
+
+       DRM_DEBUG( "sg alloc handle  = %08lx\n", entry->handle );
+       DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
+
+       for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
+               pgd = pgd_offset_k( i );
+               if ( !pgd_present( *pgd ) )
+                       goto failed;
+
+               pmd = pmd_offset( pgd, i );
+               if ( !pmd_present( *pmd ) )
+                       goto failed;
+
+               pte = pte_offset( pmd, i );
+               if ( !pte_present( *pte ) )
+                       goto failed;
+
+               entry->pagelist[j] = pte_page( *pte );
+
+               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.
+        */
+       {
+       int error = 0;
+
+       for ( i = 0 ; i < pages ; i++ ) {
+               unsigned long *tmp;
+
+               tmp = (unsigned long *)entry->pagelist[i]->virtual;
+               for ( j = 0 ;
+                     j < PAGE_SIZE / sizeof(unsigned long) ;
+                     j++, tmp++ ) {
+                       *tmp = 0xcafebabe;
+               }
+               tmp = (unsigned long *)((u8 *)entry->virtual +
+                                       (PAGE_SIZE * i));
+               for( j = 0 ;
+                    j < PAGE_SIZE / sizeof(unsigned long) ;
+                    j++, tmp++ ) {
+                       if ( *tmp != 0xcafebabe && error == 0 ) {
+                               error = 1;
+                               DRM_ERROR( "Scatter allocation error, "
+                                          "pagelist does not match "
+                                          "virtual mapping\n" );
+                       }
+               }
+               tmp = (unsigned long *)entry->pagelist[i]->virtual;
+               for(j = 0 ;
+                   j < PAGE_SIZE / sizeof(unsigned long) ;
+                   j++, tmp++) {
+                       *tmp = 0;
+               }
+       }
+       if (error == 0)
+               DRM_ERROR( "Scatter allocation matches pagelist\n" );
+       }
+#endif
+
+       return 0;
+
+ failed:
+       DRM(sg_cleanup)( entry );
+       return -ENOMEM;
+}
+
+int DRM(sg_free)( 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;
+
+       if ( copy_from_user( &request,
+                            (drm_scatter_gather_t *)arg,
+                            sizeof(request) ) )
+               return -EFAULT;
+
+       entry = dev->sg;
+       dev->sg = NULL;
+
+       if ( !entry || entry->handle != request.handle )
+               return -EINVAL;
+
+       DRM_DEBUG( "sg free virtual  = %p\n", entry->virtual );
+
+       DRM(sg_cleanup)( entry );
+
+       return 0;
+}
index fb51926..771c11b 100644 (file)
@@ -50,6 +50,12 @@ struct vm_operations_struct   drm_vm_dma_ops = {
        close:   DRM(vm_close),
 };
 
+struct vm_operations_struct   drm_vm_sg_ops = {
+       nopage:  DRM(vm_sg_nopage),
+       open:    DRM(vm_open),
+       close:   DRM(vm_close),
+};
+
 #if LINUX_VERSION_CODE < 0x020317
 unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
                             unsigned long address,
@@ -93,7 +99,7 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
        offset   = address - vma->vm_start;
        i = (unsigned long)map->handle + offset;
        /* We have to walk page tables here because we need large SAREA's, and
-        * they need to be virtually contigious in kernel space.
+        * they need to be virtually contiguous in kernel space.
         */
        pgd = pgd_offset_k( i );
        if( !pgd_present( *pgd ) ) return NOPAGE_OOM;
@@ -187,6 +193,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
                                vfree(map->handle);
                                break;
                        case _DRM_AGP:
+                       case _DRM_SCATTER_GATHER:
                                break;
                        }
                        DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -230,6 +237,48 @@ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 #endif
 }
 
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                               unsigned long address,
+                               int write_access)
+#else
+                               /* Return type changed in 2.3.23 */
+struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                              unsigned long address,
+                              int write_access)
+#endif
+{
+#if LINUX_VERSION_CODE >= 0x020300
+       drm_map_t        *map    = (drm_map_t *)vma->vm_private_data;
+#else
+       drm_map_t        *map    = (drm_map_t *)vma->vm_pte;
+#endif
+       drm_file_t *priv = vma->vm_file->private_data;
+       drm_device_t *dev = priv->dev;
+       drm_sg_mem_t *entry = dev->sg;
+       unsigned long offset;
+       unsigned long map_offset;
+       unsigned long page_offset;
+       struct page *page;
+
+       if (!entry)                return NOPAGE_SIGBUS; /* Error */
+       if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+       if (!entry->pagelist)      return NOPAGE_OOM ;  /* Nothing allocated */
+
+
+       offset = address - vma->vm_start;
+       map_offset = map->offset - dev->sg->handle;
+       page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
+       page = entry->pagelist[page_offset];
+       atomic_inc(&page->count);                       /* Dec. by kernel */
+
+#if LINUX_VERSION_CODE < 0x020317
+       return (unsigned long)virt_to_phys(page->virtual);
+#else
+       return page;
+#endif
+}
+
 void DRM(vm_open)(struct vm_area_struct *vma)
 {
        drm_file_t      *priv   = vma->vm_file->private_data;
@@ -322,6 +371,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
        drm_device_t    *dev    = priv->dev;
        drm_map_t       *map    = NULL;
        drm_map_list_t  *r_list;
+       unsigned long   offset  = 0;
        struct list_head *list;
 
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
@@ -374,19 +424,26 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
                        }
 #elif defined(__ia64__)
                        if (map->type != _DRM_AGP)
-                               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+                               vma->vm_page_prot =
+                                       pgprot_writecombine(vma->vm_page_prot);
+#elif defined(__powerpc__)
+                       pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
 #endif
                        vma->vm_flags |= VM_IO; /* not in core dump */
                }
+#ifdef __alpha__
+                offset = dev->hose->dense_mem_base -
+                        dev->hose->mem_space->start;
+#endif
                if (remap_page_range(vma->vm_start,
-                                    VM_OFFSET(vma),
+                                    VM_OFFSET(vma) + offset,
                                     vma->vm_end - vma->vm_start,
                                     vma->vm_page_prot))
                                return -EAGAIN;
                DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
                          " offset = 0x%lx\n",
                          map->type,
-                         vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+                         vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
                vma->vm_ops = &drm_vm_ops;
                break;
        case _DRM_SHM:
@@ -400,6 +457,15 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
                                   DRM_KERNEL advisory is supported. */
                vma->vm_flags |= VM_LOCKED;
                break;
+       case _DRM_SCATTER_GATHER:
+               vma->vm_ops = &drm_vm_sg_ops;
+#if LINUX_VERSION_CODE >= 0x020300
+               vma->vm_private_data = (void *)map;
+#else
+               vma->vm_pte = (unsigned long)map;
+#endif
+                vma->vm_flags |= VM_LOCKED;
+                break;
        default:
                return -EINVAL; /* This should never happen. */
        }
index daae0f8..584cb29 100644 (file)
 #include "r128.h"
 #include "drmP.h"
 #include "r128_drv.h"
+#include "ati_pcigart.h"
 
 #define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
 
 #define DRIVER_NAME            "r128"
 #define DRIVER_DESC            "ATI Rage 128"
-#define DRIVER_DATE            "20010308"
+#define DRIVER_DATE            "20010405"
 
 #define DRIVER_MAJOR           2
 #define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      5
+#define DRIVER_PATCHLEVEL      6
 
 #define DRIVER_IOCTLS                                                      \
    [DRM_IOCTL_NR(DRM_IOCTL_DMA)]             = { r128_cce_buffers,  1, 0 }, \
@@ -88,3 +89,4 @@
 #include "drm_proc.h"
 #include "drm_vm.h"
 #include "drm_stub.h"
+#include "drm_scatter.h"
index b022c3b..d763266 100644 (file)
 #include "radeon.h"
 #include "drmP.h"
 #include "radeon_drv.h"
+#include "ati_pcigart.h"
 
 #define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
 
 #define DRIVER_NAME            "radeon"
 #define DRIVER_DESC            "ATI Radeon"
-#define DRIVER_DATE            "20010402"
+#define DRIVER_DATE            "20010405"
 
 #define DRIVER_MAJOR           1
 #define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      0
+#define DRIVER_PATCHLEVEL      1
 
 #define DRIVER_IOCTLS                                                       \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
@@ -85,3 +86,4 @@
 #include "drm_proc.h"
 #include "drm_vm.h"
 #include "drm_stub.h"
+#include "drm_scatter.h"
index 470c25b..702fca0 100644 (file)
@@ -47,7 +47,7 @@
 
 # **** End of SMP/MODVERSIONS detection
 
-MODS =         gamma.o tdfx.o
+MODS =         gamma.o tdfx.o r128.o radeon.o
 LIBS =
 
 DRMTEMPLATES = drm_auth.h drm_bufs.h drm_context.h drm_dma.h drm_drawable.h \
@@ -61,6 +61,13 @@ GAMMAHEADERS =       gamma_drv.h $(DRMHEADERS) $(DRMTEMPLATES)
 TDFXOBJS =     tdfx_drv.o
 TDFXHEADERS =  tdfx.h $(DRMHEADERS)
 
+R128OBJS =     r128_drv.o r128_cce.o r128_state.o
+R128HEADERS =  r128.h r128_drv.h r128_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
+
+RADEONOBJS =   radeon_drv.o radeon_cp.o radeon_state.o
+RADEONHEADERS =        radeon.h radeon_drv.h radeon_drm.h $(DRMHEADERS) \
+               $(DRMTEMPLATES)
+
 INC =          /usr/include
 
 CFLAGS =       -O2 $(WARNINGS)
@@ -132,7 +139,7 @@ ifeq ($(AGP),1)
 MODCFLAGS += -DCONFIG_AGP -DCONFIG_AGP_MODULE
 DRMTEMPLATES += drm_agpsupport.h
 DRMHEADERS += agpsupport-pre24.h
-MODS += mga.o r128.o radeon.o
+MODS += mga.o
 ifeq ($(MACHINE),i386)
 MODS += i810.o
 endif
@@ -140,19 +147,16 @@ ifeq ($(MACHINE),i686)
 MODS += i810.o
 endif
 
-
 MGAOBJS =      mga_drv.o mga_dma.o mga_state.o mga_warp.o
 MGAHEADERS =   mga.h mga_drv.h mga_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
 
 I810OBJS =     i810_drv.o i810_dma.o
 I810HEADERS =  i810.h i810_drv.h i810_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
 
-R128OBJS =     r128_drv.o r128_cce.o r128_state.o
-R128HEADERS =  r128.h r128_drv.h r128_drm.h $(DRMHEADERS) $(DRMTEMPLATES)
+endif
 
-RADEONOBJS =   radeon_drv.o radeon_cp.o radeon_state.o
-RADEONHEADERS =        radeon.h radeon_drv.h radeon_drm.h $(DRMHEADERS) \
-               $(DRMTEMPLATES)
+ifeq ($(MACHINE),alpha)
+MODCFLAGS+=      -ffixed-8 -mno-fp-regs -mcpu=ev56 -Wa,-mev6 
 endif
 
 ifeq ($(SIS),1)
@@ -218,26 +222,27 @@ tdfx.o: $(TDFXOBJS) $(LIBS)
 sis.o: $(SISOBJS) $(LIBS)
        $(LD) -r $^ -o $@
 
-ifeq ($(AGP),1)
-mga_drv.o: mga_drv.c
+r128_drv.o: r128_drv.c
        $(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
-mga.o: $(MGAOBJS)
+r128.o: $(R128OBJS) $(LIBS)
        $(LD) -r $^ -o $@
 
-i810_drv.o: i810_drv.c
+radeon_drv.o: radeon_drv.c
        $(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
-i810.o: $(I810OBJS) $(LIBS)
+radeon.o: $(RADEONOBJS) $(LIBS)
        $(LD) -r $^ -o $@
 
-r128_drv.o: r128_drv.c
+ifeq ($(AGP),1)
+mga_drv.o: mga_drv.c
        $(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
-r128.o: $(R128OBJS) $(LIBS)
+mga.o: $(MGAOBJS)
        $(LD) -r $^ -o $@
 
-radeon_drv.o: radeon_drv.c
+i810_drv.o: i810_drv.c
        $(CC) $(MODCFLAGS) -DEXPORT_SYMTAB -I$(TREE) -c $< -o $@
-radeon.o: $(RADEONOBJS) $(LIBS)
+i810.o: $(I810OBJS) $(LIBS)
        $(LD) -r $^ -o $@
+
 endif
 
 .PHONY: ChangeLog
diff --git a/linux/ati_pcigart.h b/linux/ati_pcigart.h
new file mode 100644 (file)
index 0000000..93c5148
--- /dev/null
@@ -0,0 +1,138 @@
+/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
+ * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#if PAGE_SIZE == 8192
+# define ATI_PCIGART_TABLE_ORDER       2
+# define ATI_PCIGART_TABLE_PAGES       (1 << 2)
+#elif PAGE_SIZE == 4096
+# define ATI_PCIGART_TABLE_ORDER       3
+# define ATI_PCIGART_TABLE_PAGES       (1 << 3)
+#elif
+# error - PAGE_SIZE not 8K or 4K
+#endif
+
+# define ATI_MAX_PCIGART_PAGES         8192    /* 32 MB aperture, 4K pages */
+# define ATI_PCIGART_PAGE_SIZE         4096    /* PCI GART page size */
+
+static unsigned long DRM(ati_alloc_pcigart_table)( void )
+{
+       unsigned long address;
+       struct page *page;
+       int i;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
+       if ( address == 0UL ) {
+               return 0;
+       }
+
+       page = virt_to_page( address );
+
+       for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+               atomic_inc( &page->count );
+               SetPageReserved( page );
+       }
+
+       DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
+       return address;
+}
+
+static void DRM(ati_free_pcigart_table)( unsigned long address )
+{
+       struct page *page;
+       int i;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       if ( !address ) return;
+
+       page = virt_to_page( address );
+
+       for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+               atomic_dec( &page->count );
+               ClearPageReserved( page );
+       }
+
+       free_pages( address, ATI_PCIGART_TABLE_ORDER );
+}
+
+unsigned long DRM(ati_pcigart_init)( drm_device_t *dev )
+{
+       drm_sg_mem_t *entry = dev->sg;
+       unsigned long address;
+       unsigned long pages;
+       u32 *pci_gart, page_base;
+       int i, j;
+
+       if ( !entry ) {
+               DRM_ERROR( "no scatter/gather memory!\n" );
+               return 0;
+       }
+
+       address = DRM(ati_alloc_pcigart_table)();
+       if ( !address ) {
+               DRM_ERROR( "cannot allocate PCI GART page!\n" );
+               return 0;
+       }
+
+       pci_gart = (u32 *)address;
+
+       pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
+               ? entry->pages : ATI_MAX_PCIGART_PAGES;
+
+       memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
+
+       for ( i = 0 ; i < pages ; i++ ) {
+               page_base = virt_to_bus( entry->pagelist[i]->virtual );
+               for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+                       *pci_gart++ = cpu_to_le32( page_base );
+                       page_base += ATI_PCIGART_PAGE_SIZE;
+               }
+       }
+
+#if __i386__
+       asm volatile ( "wbinvd" ::: "memory" );
+#else
+       mb();
+#endif
+
+       return address;
+}
+
+int DRM(ati_pcigart_cleanup)( unsigned long address )
+{
+
+       if ( address ) {
+               DRM(ati_free_pcigart_table)( address );
+       }
+
+       return 0;
+}
index f1abaab..3def97f 100644 (file)
@@ -126,10 +126,11 @@ typedef struct drm_control {
 } drm_control_t;
 
 typedef enum drm_map_type {
-       _DRM_FRAME_BUFFER = 0,    /* WC (no caching), no core dump          */
-       _DRM_REGISTERS    = 1,    /* no caching, no core dump               */
-       _DRM_SHM          = 2,    /* shared, cached                         */
-       _DRM_AGP          = 3     /* AGP/GART                               */
+       _DRM_FRAME_BUFFER   = 0,  /* WC (no caching), no core dump          */
+       _DRM_REGISTERS      = 1,  /* no caching, no core dump               */
+       _DRM_SHM            = 2,  /* shared, cached                         */
+       _DRM_AGP            = 3,  /* AGP/GART                               */
+       _DRM_SCATTER_GATHER = 4   /* Scatter/gather memory for PCI DMA      */
 } drm_map_type_t;
 
 typedef enum drm_map_flags {
@@ -238,7 +239,8 @@ typedef struct drm_buf_desc {
        int           high_mark; /* High water mark                          */
        enum {
                _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA  */
-               _DRM_AGP_BUFFER = 0x02  /* Buffer is in agp space            */
+               _DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space            */
+               _DRM_SG_BUFFER  = 0x04  /* Scatter/gather memory buffer      */
        }             flags;
        unsigned long agp_start; /* Start address of where the agp buffers
                                  * are in the agp aperture */
@@ -344,6 +346,11 @@ typedef struct drm_agp_info {
        unsigned short id_device;
 } drm_agp_info_t;
 
+typedef struct drm_scatter_gather {
+       unsigned long size;     /* In bytes -- will round to page boundary */
+       unsigned long handle;   /* Used for mapping / unmapping */
+} drm_scatter_gather_t;
+
 #define DRM_IOCTL_BASE                 'd'
 #define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
 #define DRM_IOR(nr,size)               _IOR(DRM_IOCTL_BASE,nr,size)
@@ -399,6 +406,9 @@ typedef struct drm_agp_info {
 #define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, drm_agp_binding_t)
 #define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, drm_agp_binding_t)
 
+#define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, drm_scatter_gather_t)
+
 /* MGA specific ioctls */
 #define DRM_IOCTL_MGA_INIT             DRM_IOW( 0x40, drm_mga_init_t)
 #define DRM_IOCTL_MGA_FLUSH            DRM_IOW( 0x41, drm_lock_t)
index 274e318..085d1cb 100644 (file)
@@ -53,7 +53,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>    /* For (un)lock_kernel */
 #include <linux/mm.h>
-#ifdef __alpha__
+#if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h> /* For pte_wrprotect */
 #endif
 #include <asm/io.h>
 #define DRM_MEM_BOUNDAGP  17
 #define DRM_MEM_CTXBITMAP 18
 #define DRM_MEM_STUB      19
+#define DRM_MEM_SGLISTS   20
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
@@ -199,7 +200,7 @@ __cmpxchg_u32(volatile int *m, int old, int new)
        unsigned long prev, cmp;
 
        __asm__ __volatile__(
-       "1:     ldl_l %0,%2\n"
+       "1:     ldl_l %0,%5\n"
        "       cmpeq %0,%3,%1\n"
        "       beq %1,2f\n"
        "       mov %4,%1\n"
@@ -210,7 +211,8 @@ __cmpxchg_u32(volatile int *m, int old, int new)
        "3:     br 1b\n"
        ".previous"
        : "=&r"(prev), "=&r"(cmp), "=m"(*m)
-       : "r"((long) old), "r"(new), "m"(*m));
+       : "r"((long) old), "r"(new), "m"(*m)
+       : "memory" );
 
        return prev;
 }
@@ -221,7 +223,7 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
        unsigned long prev, cmp;
 
        __asm__ __volatile__(
-       "1:     ldq_l %0,%2\n"
+       "1:     ldq_l %0,%5\n"
        "       cmpeq %0,%3,%1\n"
        "       beq %1,2f\n"
        "       mov %4,%1\n"
@@ -232,7 +234,8 @@ __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
        "3:     br 1b\n"
        ".previous"
        : "=&r"(prev), "=&r"(cmp), "=m"(*m)
-       : "r"((long) old), "r"(new), "m"(*m));
+       : "r"((long) old), "r"(new), "m"(*m)
+       : "memory" );
 
        return prev;
 }
@@ -284,12 +287,43 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
        return old;
 }
 
+#elif defined(__powerpc__)
+extern void __cmpxchg_called_with_bad_pointer(void);
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                      unsigned long new, int size)
+{
+       unsigned long prev;
+
+       switch (size) {
+       case 4:
+               __asm__ __volatile__(
+                       "sync;"
+                       "0:    lwarx %0,0,%1 ;"
+                       "      cmpl 0,%0,%3;"
+                       "      bne 1f;"
+                       "      stwcx. %2,0,%1;"
+                       "      bne- 0b;"
+                       "1:    "
+                       "sync;"
+                       : "=&r"(prev)
+                       : "r"(ptr), "r"(new), "r"(old)
+                       : "cr0", "memory");
+               return prev;
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#endif /* i386, powerpc & alpha */
+
+#ifndef __alpha__
 #define cmpxchg(ptr,o,n)                                               \
   ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),             \
                                 (unsigned long)(n),sizeof(*(ptr))))
-#endif /* i386 & alpha */
 #endif
 
+#endif /* !__HAVE_ARCH_CMPXCHG */
+
                                /* Macros to make printk easier */
 #define DRM_ERROR(fmt, arg...) \
        printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
@@ -547,7 +581,8 @@ typedef struct drm_device_dma {
        unsigned long     *pagelist;
        unsigned long     byte_count;
        enum {
-               _DRM_DMA_USE_AGP = 0x01
+               _DRM_DMA_USE_AGP = 0x01,
+               _DRM_DMA_USE_SG  = 0x02
        } flags;
 
                                /* DMA support */
@@ -579,6 +614,13 @@ typedef struct drm_agp_head {
 } drm_agp_head_t;
 #endif
 
+typedef struct drm_sg_mem {
+       unsigned long   handle;
+       void            *virtual;
+       int             pages;
+       struct page     **pagelist;
+} drm_sg_mem_t;
+
 typedef struct drm_sigdata {
        int           context;
        drm_hw_lock_t *lock;
@@ -667,6 +709,10 @@ typedef struct drm_device {
 #if __REALLY_HAVE_AGP
        drm_agp_head_t    *agp;
 #endif
+#ifdef __alpha__
+       struct pci_controler *hose;
+#endif
+       drm_sg_mem_t      *sg;  /* Scatter gather memory */
        unsigned long     *ctx_bitmap;
        void              *dev_private;
        drm_sigdata_t     sigdata; /* For block_all_signals */
@@ -718,6 +764,9 @@ extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
                                        unsigned long address,
                                        int write_access);
+extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                                      unsigned long address,
+                                      int write_access);
 #else
                                /* Return type changed in 2.3.23 */
 extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
@@ -729,6 +778,9 @@ extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
                                       unsigned long address,
                                       int write_access);
+extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                                     unsigned long address,
+                                     int write_access);
 #endif
 extern void         DRM(vm_open)(struct vm_area_struct *vma);
 extern void         DRM(vm_close)(struct vm_area_struct *vma);
@@ -947,5 +999,16 @@ extern int            DRM(proc_cleanup)(int minor,
                                        struct proc_dir_entry *root,
                                        struct proc_dir_entry *dev_root);
 
+                               /* 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);
+
+                               /* ATI PCIGART support (ati_pcigart.h) */
+extern unsigned long  DRM(ati_pcigart_init)(drm_device_t *dev);
+extern int            DRM(ati_pcigart_cleanup)(unsigned long address);
+
 #endif /* __KERNEL__ */
 #endif
index dfd0d8f..9b056c7 100644 (file)
@@ -52,7 +52,8 @@ int DRM(agp_info)(struct inode *inode, struct file *filp,
        agp_kern_info    *kern;
        drm_agp_info_t   info;
 
-       if (!dev->agp->acquired || !drm_agp->copy_info) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
+               return -EINVAL;
 
        kern                   = &dev->agp->agp_info;
        info.agp_version_major = kern->version.major;
@@ -77,7 +78,8 @@ int DRM(agp_acquire)(struct inode *inode, struct file *filp,
        drm_device_t     *dev    = priv->dev;
        int              retcode;
 
-       if (!dev->agp|| dev->agp->acquired || !drm_agp->acquire) return -EINVAL;
+       if (!dev->agp || dev->agp->acquired || !drm_agp->acquire)
+               return -EINVAL;
        if ((retcode = drm_agp->acquire())) return retcode;
        dev->agp->acquired = 1;
        return 0;
@@ -89,7 +91,8 @@ int DRM(agp_release)(struct inode *inode, struct file *filp,
        drm_file_t       *priv   = filp->private_data;
        drm_device_t     *dev    = priv->dev;
 
-       if (!dev->agp->acquired || !drm_agp->release) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->release)
+               return -EINVAL;
        drm_agp->release();
        dev->agp->acquired = 0;
        return 0;
@@ -108,7 +111,8 @@ int DRM(agp_enable)(struct inode *inode, struct file *filp,
        drm_device_t     *dev    = priv->dev;
        drm_agp_mode_t   mode;
 
-       if (!dev->agp->acquired || !drm_agp->enable) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->enable)
+               return -EINVAL;
 
        if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
                return -EFAULT;
@@ -131,7 +135,7 @@ int DRM(agp_alloc)(struct inode *inode, struct file *filp,
        unsigned long    pages;
        u32              type;
 
-       if (!dev->agp->acquired) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired) return -EINVAL;
        if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
@@ -188,7 +192,7 @@ int DRM(agp_unbind)(struct inode *inode, struct file *filp,
        drm_agp_binding_t request;
        drm_agp_mem_t     *entry;
 
-       if (!dev->agp->acquired) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired) return -EINVAL;
        if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
@@ -207,7 +211,8 @@ int DRM(agp_bind)(struct inode *inode, struct file *filp,
        int               retcode;
        int               page;
 
-       if (!dev->agp->acquired || !drm_agp->bind_memory) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory)
+               return -EINVAL;
        if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
@@ -229,7 +234,7 @@ int DRM(agp_free)(struct inode *inode, struct file *filp,
        drm_agp_buffer_t request;
        drm_agp_mem_t    *entry;
 
-       if (!dev->agp->acquired) return -EINVAL;
+       if (!dev->agp || !dev->agp->acquired) return -EINVAL;
        if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
                return -EFAULT;
        if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
index b111104..16af7bd 100644 (file)
 #define __HAVE_PCI_DMA         0
 #endif
 
+#ifndef __HAVE_SG
+#define __HAVE_SG              0
+#endif
+
 #ifndef DRIVER_BUF_PRIV_T
 #define DRIVER_BUF_PRIV_T              u32
 #endif
@@ -103,13 +107,16 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
        switch ( map->type ) {
        case _DRM_REGISTERS:
        case _DRM_FRAME_BUFFER:
-#ifndef __sparc__
+#if !defined(__sparc__) && !defined(__alpha__)
                if ( map->offset + map->size < map->offset ||
                     map->offset < virt_to_phys(high_memory) ) {
                        DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
                        return -EINVAL;
                }
 #endif
+#ifdef __alpha__
+               map->offset += dev->hose->mem_space->start;
+#endif
 #if __REALLY_HAVE_MTRR
                if ( map->type == _DRM_FRAME_BUFFER ||
                     (map->flags & _DRM_WRITE_COMBINING) ) {
@@ -135,10 +142,21 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
                break;
 #if __REALLY_HAVE_AGP
        case _DRM_AGP:
+#ifdef __alpha__
+               map->offset += dev->hose->mem_space->start;
+#endif
                map->offset = map->offset + dev->agp->base;
                map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
                break;
 #endif
+       case _DRM_SCATTER_GATHER:
+               if (!dev->sg) {
+                       DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EINVAL;
+               }
+               map->offset = map->offset + dev->sg->handle;
+               break;
+
        default:
                DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
                return -EINVAL;
@@ -237,6 +255,7 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
                        vfree(map->handle);
                        break;
                case _DRM_AGP:
+               case _DRM_SCATTER_GATHER:
                        break;
                }
                DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -565,6 +584,159 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 }
 #endif /* __HAVE_PCI_DMA */
 
+#ifdef __HAVE_SG
+int DRM(addbufs_sg)( 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;
+
+       if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
+                            sizeof(request) ) )
+               return -EFAULT;
+
+       count = request.count;
+       order = DRM(order)( request.size );
+       size = 1 << order;
+
+       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;
+       agp_offset = request.agp_start;
+
+       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 );
+
+       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 */
+       }
+
+       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;
+
+       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;
+
+               buf->offset  = (dma->byte_count + offset);
+               buf->bus_address = agp_offset + offset;
+               buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+               buf->next    = NULL;
+               buf->waiting = 0;
+               buf->pending = 0;
+               init_waitqueue_head( &buf->dma_wait );
+               buf->pid     = 0;
+
+               buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
+               buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+                                              DRM_MEM_BUFS );
+               memset( buf->dev_private, 0, buf->dev_priv_size );
+
+#if __HAVE_DMA_HISTOGRAM
+               buf->time_queued = 0;
+               buf->time_dispatched = 0;
+               buf->time_completed = 0;
+               buf->time_freed = 0;
+#endif
+               DRM_DEBUG( "buffer %d @ %p\n",
+                          entry->buf_count, buf->address );
+
+               offset += alignment;
+               entry->buf_count++;
+               byte_count += PAGE_SIZE << page_order;
+       }
+
+       DRM_DEBUG( "byte_count: %d\n", byte_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 = 0 ; i < entry->buf_count ; i++ ) {
+               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+       }
+
+       dma->buf_count += entry->buf_count;
+       dma->byte_count += byte_count;
+
+       DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+       DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+#if __HAVE_DMA_FREELIST
+       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] );
+       }
+#endif
+       up( &dev->struct_sem );
+
+       request.count = entry->buf_count;
+       request.size = size;
+
+       if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
+               return -EFAULT;
+
+       dma->flags = _DRM_DMA_USE_SG;
+
+       atomic_dec( &dev->buf_alloc );
+       return 0;
+}
+#endif /* __HAVE_SG */
+
 int DRM(addbufs)( struct inode *inode, struct file *filp,
                  unsigned int cmd, unsigned long arg )
 {
@@ -579,6 +751,11 @@ int DRM(addbufs)( struct inode *inode, struct file *filp,
                return DRM(addbufs_agp)( inode, filp, cmd, arg );
        else
 #endif
+#if __HAVE_SG
+       if ( request.flags & _DRM_SG_BUFFER )
+               return DRM(addbufs_sg)( inode, filp, cmd, arg );
+       else
+#endif
 #if __HAVE_PCI_DMA
                return DRM(addbufs_pci)( inode, filp, cmd, arg );
 #else
@@ -760,7 +937,8 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
                return -EFAULT;
 
        if ( request.count >= dma->buf_count ) {
-               if ( __HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP) ) {
+               if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
+                    (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
                        drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
 
                        if ( !map ) {
index 7447ca6..3791d7a 100644 (file)
@@ -81,6 +81,9 @@
 #ifndef __HAVE_COUNTERS
 #define __HAVE_COUNTERS                        0
 #endif
+#ifndef __HAVE_SG
+#define __HAVE_SG                      0
+#endif
 
 #ifndef DRIVER_PREINIT
 #define DRIVER_PREINIT()
@@ -178,6 +181,11 @@ static drm_ioctl_desc_t              DRM(ioctls)[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  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 },
+#endif
+
        DRIVER_IOCTLS
 };
 
@@ -415,6 +423,12 @@ static int DRM(takedown)( drm_device_t *dev )
                                 * handled in the AGP/GART driver.
                                 */
                                break;
+                       case _DRM_SCATTER_GATHER:
+                               if(dev->sg) {
+                                       DRM(sg_cleanup)(dev->sg);
+                                       dev->sg = NULL;
+                               }
+                               break;
                        }
                        DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
                }
index dd57476..75752b3 100644 (file)
@@ -70,6 +70,21 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
        }
        up(&dev->struct_sem);
 
+#ifdef __alpha__
+       /*
+        * Default the hose
+        */
+       if (!dev->hose) {
+               struct pci_dev *pci_dev;
+               pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+               if (pci_dev) dev->hose = pci_dev->sysdata;
+               if (!dev->hose) {
+                       struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+                       if (b) dev->hose = b->sysdata;
+               }
+       }
+#endif
+
        return 0;
 }
 
index 9ae9841..d9d8e3a 100644 (file)
 #define __NO_VERSION__
 #include "drmP.h"
 
+#if 0
+int DRM(flags) = DRM_FLAG_DEBUG;
+#else
 int DRM(flags) = 0;
+#endif
 
 /* drm_parse_option parses a single option.  See description for
  * drm_parse_options for details.
index 2fba6b0..1cc8f31 100644 (file)
@@ -95,6 +95,27 @@ int DRM(setunique)(struct inode *inode, struct file *filp,
                                  DRM_MEM_DRIVER);
        sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
 
+#ifdef __alpha__
+       do {
+               struct pci_dev *pci_dev;
+                int b, d, f;
+                char *p;
+                for(p = dev->unique; p && *p && *p != ':'; p++);
+                if (!p || !*p) break;
+                b = (int)simple_strtoul(p+1, &p, 10);
+                if (*p != ':') break;
+                d = (int)simple_strtoul(p+1, &p, 10);
+                if (*p != ':') break;
+                f = (int)simple_strtoul(p+1, &p, 10);
+                if (*p) break;
+                pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
+                if (pci_dev)
+                        dev->hose = pci_dev->sysdata;
+        } while(0);
+#endif
+
        return 0;
 }
 
index 1763d9b..498937d 100644 (file)
@@ -63,6 +63,7 @@ static drm_mem_stats_t          DRM(mem_stats)[]   = {
        [DRM_MEM_MAPPINGS]  = { "mappings" },
        [DRM_MEM_BUFLISTS]  = { "buflists" },
        [DRM_MEM_AGPLISTS]  = { "agplist"  },
+       [DRM_MEM_SGLISTS]   = { "sglist"   },
        [DRM_MEM_TOTALAGP]  = { "totalagp" },
        [DRM_MEM_BOUNDAGP]  = { "boundagp" },
        [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
diff --git a/linux/drm_scatter.h b/linux/drm_scatter.h
new file mode 100644 (file)
index 0000000..a037107
--- /dev/null
@@ -0,0 +1,218 @@
+/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
+ * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/vmalloc.h>
+#include "drmP.h"
+
+#define DEBUG_SCATTER 0
+
+void DRM(sg_cleanup)( drm_sg_mem_t *entry )
+{
+       struct page *page;
+       int i;
+
+       for ( i = 0 ; i < entry->pages ; i++ ) {
+               page = entry->pagelist[i];
+               if ( page )
+                       ClearPageReserved( page );
+       }
+
+       vfree( entry->virtual );
+
+       DRM(free)( entry->pagelist,
+                 entry->pages * sizeof(*entry->pagelist),
+                 DRM_MEM_PAGES );
+       DRM(free)( entry,
+                 sizeof(*entry),
+                 DRM_MEM_SGLISTS );
+}
+
+int DRM(sg_alloc)( 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;
+       unsigned long pages, i, j;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       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;
+
+       memset( entry, 0, sizeof(*entry) );
+
+       pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+       DRM_DEBUG( "sg size=%ld pages=%ld\n", request.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;
+       }
+
+       entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
+       if ( !entry->virtual ) {
+               DRM(free)( entry->pagelist,
+                         entry->pages * sizeof(*entry->pagelist),
+                         DRM_MEM_PAGES );
+               DRM(free)( entry,
+                         sizeof(*entry),
+                         DRM_MEM_SGLISTS );
+               return -ENOMEM;
+       }
+
+       /* This also forces the mapping of COW pages, so our page list
+        * will be valid.  Please don't remove it...
+        */
+       memset( entry->virtual, 0, pages << PAGE_SHIFT );
+
+       entry->handle = (unsigned long)entry->virtual;
+
+       DRM_DEBUG( "sg alloc handle  = %08lx\n", entry->handle );
+       DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
+
+       for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
+               pgd = pgd_offset_k( i );
+               if ( !pgd_present( *pgd ) )
+                       goto failed;
+
+               pmd = pmd_offset( pgd, i );
+               if ( !pmd_present( *pmd ) )
+                       goto failed;
+
+               pte = pte_offset( pmd, i );
+               if ( !pte_present( *pte ) )
+                       goto failed;
+
+               entry->pagelist[j] = pte_page( *pte );
+
+               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.
+        */
+       {
+       int error = 0;
+
+       for ( i = 0 ; i < pages ; i++ ) {
+               unsigned long *tmp;
+
+               tmp = (unsigned long *)entry->pagelist[i]->virtual;
+               for ( j = 0 ;
+                     j < PAGE_SIZE / sizeof(unsigned long) ;
+                     j++, tmp++ ) {
+                       *tmp = 0xcafebabe;
+               }
+               tmp = (unsigned long *)((u8 *)entry->virtual +
+                                       (PAGE_SIZE * i));
+               for( j = 0 ;
+                    j < PAGE_SIZE / sizeof(unsigned long) ;
+                    j++, tmp++ ) {
+                       if ( *tmp != 0xcafebabe && error == 0 ) {
+                               error = 1;
+                               DRM_ERROR( "Scatter allocation error, "
+                                          "pagelist does not match "
+                                          "virtual mapping\n" );
+                       }
+               }
+               tmp = (unsigned long *)entry->pagelist[i]->virtual;
+               for(j = 0 ;
+                   j < PAGE_SIZE / sizeof(unsigned long) ;
+                   j++, tmp++) {
+                       *tmp = 0;
+               }
+       }
+       if (error == 0)
+               DRM_ERROR( "Scatter allocation matches pagelist\n" );
+       }
+#endif
+
+       return 0;
+
+ failed:
+       DRM(sg_cleanup)( entry );
+       return -ENOMEM;
+}
+
+int DRM(sg_free)( 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;
+
+       if ( copy_from_user( &request,
+                            (drm_scatter_gather_t *)arg,
+                            sizeof(request) ) )
+               return -EFAULT;
+
+       entry = dev->sg;
+       dev->sg = NULL;
+
+       if ( !entry || entry->handle != request.handle )
+               return -EINVAL;
+
+       DRM_DEBUG( "sg free virtual  = %p\n", entry->virtual );
+
+       DRM(sg_cleanup)( entry );
+
+       return 0;
+}
index fb51926..771c11b 100644 (file)
@@ -50,6 +50,12 @@ struct vm_operations_struct   drm_vm_dma_ops = {
        close:   DRM(vm_close),
 };
 
+struct vm_operations_struct   drm_vm_sg_ops = {
+       nopage:  DRM(vm_sg_nopage),
+       open:    DRM(vm_open),
+       close:   DRM(vm_close),
+};
+
 #if LINUX_VERSION_CODE < 0x020317
 unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
                             unsigned long address,
@@ -93,7 +99,7 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
        offset   = address - vma->vm_start;
        i = (unsigned long)map->handle + offset;
        /* We have to walk page tables here because we need large SAREA's, and
-        * they need to be virtually contigious in kernel space.
+        * they need to be virtually contiguous in kernel space.
         */
        pgd = pgd_offset_k( i );
        if( !pgd_present( *pgd ) ) return NOPAGE_OOM;
@@ -187,6 +193,7 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
                                vfree(map->handle);
                                break;
                        case _DRM_AGP:
+                       case _DRM_SCATTER_GATHER:
                                break;
                        }
                        DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -230,6 +237,48 @@ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 #endif
 }
 
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                               unsigned long address,
+                               int write_access)
+#else
+                               /* Return type changed in 2.3.23 */
+struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+                              unsigned long address,
+                              int write_access)
+#endif
+{
+#if LINUX_VERSION_CODE >= 0x020300
+       drm_map_t        *map    = (drm_map_t *)vma->vm_private_data;
+#else
+       drm_map_t        *map    = (drm_map_t *)vma->vm_pte;
+#endif
+       drm_file_t *priv = vma->vm_file->private_data;
+       drm_device_t *dev = priv->dev;
+       drm_sg_mem_t *entry = dev->sg;
+       unsigned long offset;
+       unsigned long map_offset;
+       unsigned long page_offset;
+       struct page *page;
+
+       if (!entry)                return NOPAGE_SIGBUS; /* Error */
+       if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+       if (!entry->pagelist)      return NOPAGE_OOM ;  /* Nothing allocated */
+
+
+       offset = address - vma->vm_start;
+       map_offset = map->offset - dev->sg->handle;
+       page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
+       page = entry->pagelist[page_offset];
+       atomic_inc(&page->count);                       /* Dec. by kernel */
+
+#if LINUX_VERSION_CODE < 0x020317
+       return (unsigned long)virt_to_phys(page->virtual);
+#else
+       return page;
+#endif
+}
+
 void DRM(vm_open)(struct vm_area_struct *vma)
 {
        drm_file_t      *priv   = vma->vm_file->private_data;
@@ -322,6 +371,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
        drm_device_t    *dev    = priv->dev;
        drm_map_t       *map    = NULL;
        drm_map_list_t  *r_list;
+       unsigned long   offset  = 0;
        struct list_head *list;
 
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
@@ -374,19 +424,26 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
                        }
 #elif defined(__ia64__)
                        if (map->type != _DRM_AGP)
-                               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+                               vma->vm_page_prot =
+                                       pgprot_writecombine(vma->vm_page_prot);
+#elif defined(__powerpc__)
+                       pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
 #endif
                        vma->vm_flags |= VM_IO; /* not in core dump */
                }
+#ifdef __alpha__
+                offset = dev->hose->dense_mem_base -
+                        dev->hose->mem_space->start;
+#endif
                if (remap_page_range(vma->vm_start,
-                                    VM_OFFSET(vma),
+                                    VM_OFFSET(vma) + offset,
                                     vma->vm_end - vma->vm_start,
                                     vma->vm_page_prot))
                                return -EAGAIN;
                DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
                          " offset = 0x%lx\n",
                          map->type,
-                         vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+                         vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
                vma->vm_ops = &drm_vm_ops;
                break;
        case _DRM_SHM:
@@ -400,6 +457,15 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
                                   DRM_KERNEL advisory is supported. */
                vma->vm_flags |= VM_LOCKED;
                break;
+       case _DRM_SCATTER_GATHER:
+               vma->vm_ops = &drm_vm_sg_ops;
+#if LINUX_VERSION_CODE >= 0x020300
+               vma->vm_private_data = (void *)map;
+#else
+               vma->vm_pte = (unsigned long)map;
+#endif
+                vma->vm_flags |= VM_LOCKED;
+                break;
        default:
                return -EINVAL; /* This should never happen. */
        }
index 066b4e4..4af2ca2 100644 (file)
@@ -237,7 +237,7 @@ typedef struct drm_mga_init {
                MGA_CLEANUP_DMA = 0x02
        } func;
 
-       int sarea_priv_offset;
+       unsigned long sarea_priv_offset;
 
        int chipset;
        int sgram;
@@ -254,12 +254,12 @@ typedef struct drm_mga_init {
        unsigned int texture_offset[MGA_NR_TEX_HEAPS];
        unsigned int texture_size[MGA_NR_TEX_HEAPS];
 
-       unsigned int fb_offset;
-       unsigned int mmio_offset;
-       unsigned int status_offset;
-       unsigned int warp_offset;
-       unsigned int primary_offset;
-       unsigned int buffers_offset;
+       unsigned long fb_offset;
+       unsigned long mmio_offset;
+       unsigned long status_offset;
+       unsigned long warp_offset;
+       unsigned long primary_offset;
+       unsigned long buffers_offset;
 } drm_mga_init_t;
 
 typedef struct drm_mga_fullscreen {
index 83e002a..926b4bf 100644 (file)
 /* General customization:
  */
 #define __HAVE_AGP             1
-#define __MUST_HAVE_AGP                1
+#define __MUST_HAVE_AGP                0
 #define __HAVE_MTRR            1
 #define __HAVE_CTX_BITMAP      1
+#define __HAVE_SG              1
+#define __HAVE_PCI_DMA         1
 
 /* Driver customization:
  */
index c0e20c2..1ced05f 100644 (file)
@@ -178,6 +178,8 @@ static void r128_cce_load_microcode( drm_r128_private_t *dev_priv )
 {
        int i;
 
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
        r128_do_wait_for_idle( dev_priv );
 
        R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
@@ -208,7 +210,7 @@ int r128_do_cce_idle( drm_r128_private_t *dev_priv )
        int i;
 
        for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-               if ( *dev_priv->ring.head == dev_priv->ring.tail ) {
+               if ( GET_RING_HEAD( &dev_priv->ring ) == dev_priv->ring.tail ) {
                        int pm4stat = R128_READ( R128_PM4_STAT );
                        if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
                               dev_priv->cce_fifo_size ) &&
@@ -249,7 +251,7 @@ static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
 {
        R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
        R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
-       *dev_priv->ring.head = 0;
+       SET_RING_HEAD( &dev_priv->ring, 0 );
        dev_priv->ring.tail = 0;
 }
 
@@ -312,19 +314,43 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev )
        u32 ring_start;
        u32 tmp;
 
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
        /* The manual (p. 2) says this address is in "VM space".  This
         * means it's an offset from the start of AGP space.
         */
-       ring_start = dev_priv->cce_ring->offset - dev->agp->base;
+#if __REALLY_HAVE_AGP
+       if ( !dev_priv->is_pci )
+               ring_start = dev_priv->cce_ring->offset - dev->agp->base;
+       else
+#endif
+               ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
+
        R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
 
        R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
        R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
 
        /* DL_RPTR_ADDR is a physical address in AGP space. */
-       *dev_priv->ring.head = 0;
-       R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-                   dev_priv->ring_rptr->offset );
+       SET_RING_HEAD( &dev_priv->ring, 0 );
+
+       if ( !dev_priv->is_pci ) {
+               R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
+                           dev_priv->ring_rptr->offset );
+       } else {
+               drm_sg_mem_t *entry = dev->sg;
+               unsigned long tmp_ofs, page_ofs;
+
+               tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+               page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+               R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
+                           virt_to_bus(entry->pagelist[page_ofs]->virtual));
+
+               DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+                          virt_to_bus(entry->pagelist[page_ofs]->virtual),
+                          entry->handle + tmp_ofs );
+       }
 
        /* Set watermark control */
        R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
@@ -346,6 +372,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
        drm_r128_private_t *dev_priv;
        struct list_head *list;
 
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
        dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
        if ( dev_priv == NULL )
                return -ENOMEM;
@@ -355,11 +383,9 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 
        dev_priv->is_pci = init->is_pci;
 
-       /* GH: We don't support PCI cards until PCI GART is implemented.
-        * Fail here so we can remove all checks for PCI cards around
-        * the CCE ring code.
-        */
-       if ( dev_priv->is_pci ) {
+       if ( dev_priv->is_pci && !dev->sg ) {
+               DRM_DEBUG( "PCI GART memory not allocated!\n" );
+               DRM_ERROR( "PCI GART memory not allocated!\n" );
                DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
                dev->dev_private = NULL;
                return -EINVAL;
@@ -368,6 +394,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
        dev_priv->usec_timeout = init->usec_timeout;
        if ( dev_priv->usec_timeout < 1 ||
             dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
+               DRM_DEBUG( "TIMEOUT problem!\n" );
                DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
                dev->dev_private = NULL;
                return -EINVAL;
@@ -387,6 +414,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
             ( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
             ( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
             ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
+               DRM_DEBUG( "Bad cce_mode!\n" );
                DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
                dev->dev_private = NULL;
                return -EINVAL;
@@ -476,9 +504,24 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
                (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
                                     init->sarea_priv_offset);
 
-       DRM_IOREMAP( dev_priv->cce_ring );
-       DRM_IOREMAP( dev_priv->ring_rptr );
-       DRM_IOREMAP( dev_priv->buffers );
+       if ( !dev_priv->is_pci ) {
+               DRM_IOREMAP( dev_priv->cce_ring );
+               DRM_IOREMAP( dev_priv->ring_rptr );
+               DRM_IOREMAP( dev_priv->buffers );
+       } else {
+               dev_priv->cce_ring->handle =
+                       (void *)dev_priv->cce_ring->offset;
+               dev_priv->ring_rptr->handle =
+                       (void *)dev_priv->ring_rptr->offset;
+               dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+       }
+
+#if __REALLY_HAVE_AGP
+       if ( !dev_priv->is_pci )
+               dev_priv->cce_buffers_offset = dev->agp->base;
+       else
+#endif
+               dev_priv->cce_buffers_offset = dev->sg->handle;
 
        dev_priv->ring.head = ((__volatile__ u32 *)
                               dev_priv->ring_rptr->handle);
@@ -501,6 +544,20 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
        R128_WRITE( R128_LAST_DISPATCH_REG,
                    dev_priv->sarea_priv->last_dispatch );
 
+       if ( dev_priv->is_pci ) {
+               dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev );
+               if ( !dev_priv->phys_pci_gart ) {
+                       DRM_DEBUG( "failed to init PCI GART!\n" );
+                       DRM_ERROR( "failed to init PCI GART!\n" );
+                       DRM(free)( dev_priv, sizeof(*dev_priv),
+                                  DRM_MEM_DRIVER );
+                       dev->dev_private = NULL;
+                       return -EINVAL;
+               }
+               R128_WRITE( R128_PCI_GART_PAGE,
+                           virt_to_bus( (void *)dev_priv->phys_pci_gart ) );
+       }
+
        r128_cce_init_ring_buffer( dev );
        r128_cce_load_microcode( dev_priv );
        r128_do_engine_reset( dev );
@@ -513,9 +570,11 @@ int r128_do_cleanup_cce( drm_device_t *dev )
        if ( dev->dev_private ) {
                drm_r128_private_t *dev_priv = dev->dev_private;
 
-               DRM_IOREMAPFREE( dev_priv->cce_ring );
-               DRM_IOREMAPFREE( dev_priv->ring_rptr );
-               DRM_IOREMAPFREE( dev_priv->buffers );
+               if ( !dev_priv->is_pci ) {
+                       DRM_IOREMAPFREE( dev_priv->cce_ring );
+                       DRM_IOREMAPFREE( dev_priv->ring_rptr );
+                       DRM_IOREMAPFREE( dev_priv->buffers );
+               }
 
                DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
                           DRM_MEM_DRIVER );
@@ -532,6 +591,8 @@ int r128_cce_init( struct inode *inode, struct file *filp,
         drm_device_t *dev = priv->dev;
        drm_r128_init_t init;
 
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
        if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) )
                return -EFAULT;
 
index 86aba17..fc1261e 100644 (file)
@@ -175,7 +175,7 @@ typedef struct drm_r128_init {
                R128_INIT_CCE    = 0x01,
                R128_CLEANUP_CCE = 0x02
        } func;
-       int sarea_priv_offset;
+       unsigned long sarea_priv_offset;
        int is_pci;
        int cce_mode;
        int cce_secure;
@@ -189,12 +189,12 @@ typedef struct drm_r128_init {
        unsigned int depth_offset, depth_pitch;
        unsigned int span_offset;
 
-       unsigned int fb_offset;
-       unsigned int mmio_offset;
-       unsigned int ring_offset;
-       unsigned int ring_rptr_offset;
-       unsigned int buffers_offset;
-       unsigned int agp_textures_offset;
+       unsigned long fb_offset;
+       unsigned long mmio_offset;
+       unsigned long ring_offset;
+       unsigned long ring_rptr_offset;
+       unsigned long buffers_offset;
+       unsigned long agp_textures_offset;
 } drm_r128_init_t;
 
 typedef struct drm_r128_cce_stop {
index daae0f8..584cb29 100644 (file)
 #include "r128.h"
 #include "drmP.h"
 #include "r128_drv.h"
+#include "ati_pcigart.h"
 
 #define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
 
 #define DRIVER_NAME            "r128"
 #define DRIVER_DESC            "ATI Rage 128"
-#define DRIVER_DATE            "20010308"
+#define DRIVER_DATE            "20010405"
 
 #define DRIVER_MAJOR           2
 #define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      5
+#define DRIVER_PATCHLEVEL      6
 
 #define DRIVER_IOCTLS                                                      \
    [DRM_IOCTL_NR(DRM_IOCTL_DMA)]             = { r128_cce_buffers,  1, 0 }, \
@@ -88,3 +89,4 @@
 #include "drm_proc.h"
 #include "drm_vm.h"
 #include "drm_stub.h"
+#include "drm_scatter.h"
index 6216b9a..fbc6922 100644 (file)
  *    Rickard E. (Rik) Faith <faith@valinux.com>
  *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
+ *    Michel Dänzer <daenzerm@student.ethz.ch>
  */
 
 #ifndef __R128_DRV_H__
 #define __R128_DRV_H__
 
+#define GET_RING_HEAD( ring )          le32_to_cpu( *(ring)->head )
+#define SET_RING_HEAD( ring, val )     *(ring)->head = cpu_to_le32( val )
+
 typedef struct drm_r128_freelist {
        unsigned int age;
        drm_buf_t *buf;
@@ -67,6 +71,8 @@ typedef struct drm_r128_private {
 
        int usec_timeout;
        int is_pci;
+       unsigned long phys_pci_gart;
+       unsigned long cce_buffers_offset;
 
        atomic_t idle_count;
 
@@ -134,7 +140,7 @@ extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
 static inline void
 r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
 {
-       ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32);
+       ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32);
        if ( ring->space <= 0 )
                ring->space += ring->size;
 }
@@ -248,6 +254,7 @@ extern int r128_cce_indirect( struct inode *inode, struct file *filp,
 #      define R128_PC_FLUSH_ALL                0x00ff
 #      define R128_PC_BUSY                     (1 << 31)
 
+#define R128_PCI_GART_PAGE             0x017c
 #define R128_PRIM_TEX_CNTL_C           0x1cb0
 
 #define R128_SCALE_3D_CNTL             0x1a00
@@ -365,7 +372,7 @@ extern int r128_cce_indirect( struct inode *inode, struct file *filp,
 
 #define R128_LAST_FRAME_REG            R128_GUI_SCRATCH_REG0
 #define R128_LAST_DISPATCH_REG         R128_GUI_SCRATCH_REG1
-#define R128_MAX_VB_AGE                        0xffffffff
+#define R128_MAX_VB_AGE                        0x7fffffff
 #define R128_MAX_VB_VERTS              (0xffff)
 
 #define R128_RING_HIGH_MARK            128
@@ -373,17 +380,36 @@ extern int r128_cce_indirect( struct inode *inode, struct file *filp,
 #define R128_PERFORMANCE_BOXES         0
 
 
-#define R128_BASE(reg)         ((u32)(dev_priv->mmio->handle))
+#define R128_BASE(reg)         ((unsigned long)(dev_priv->mmio->handle))
 #define R128_ADDR(reg)         (R128_BASE( reg ) + reg)
 
 #define R128_DEREF(reg)                *(volatile u32 *)R128_ADDR( reg )
-#define R128_READ(reg)         R128_DEREF( reg )
-#define R128_WRITE(reg,val)    do { R128_DEREF( reg ) = val; } while (0)
+#ifdef __alpha__
+#define R128_READ(reg)         (_R128_READ((u32 *)R128_ADDR(reg)))
+static inline u32 _R128_READ(u32 *addr) {
+       mb();
+       return *(volatile u32 *)addr;
+}
+#define R128_WRITE(reg,val)    \
+       do { wmb(); R128_DEREF(reg) = val; } while (0)
+#else
+#define R128_READ(reg)         le32_to_cpu( R128_DEREF( reg ) )
+#define R128_WRITE(reg,val)    do { R128_DEREF( reg ) = cpu_to_le32( val ); } while (0)
+#endif
 
 #define R128_DEREF8(reg)       *(volatile u8 *)R128_ADDR( reg )
+#ifdef __alpha__
+#define R128_READ8(reg)                _R128_READ8((u8 *)R128_ADDR(reg))
+static inline u8 _R128_READ8(u8 *addr) {
+       mb();
+       return *(volatile u8 *)addr;
+}
+#define R128_WRITE8(reg,val)   \
+       do { wmb(); R128_DEREF8(reg) = val; } while (0)
+#else
 #define R128_READ8(reg)                R128_DEREF8( reg )
 #define R128_WRITE8(reg,val)   do { R128_DEREF8( reg ) = val; } while (0)
-
+#endif
 
 #define R128_WRITE_PLL(addr,val)                                              \
 do {                                                                          \
@@ -485,7 +511,7 @@ do {                                                                        \
 
 #define ADVANCE_RING() do {                                            \
        if ( R128_VERBOSE ) {                                           \
-               DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n",     \
+               DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",     \
                          write, dev_priv->ring.tail );                 \
        }                                                               \
        if ( R128_BROKEN_CCE && write < 32 ) {                          \
@@ -503,7 +529,7 @@ do {                                                                        \
                DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",            \
                           (unsigned int)(x), write );                  \
        }                                                               \
-       ring[write++] = (x);                                            \
+       ring[write++] = cpu_to_le32( x );                               \
        write &= tail_mask;                                             \
 } while (0)
 
index 9fc6b48..7eafd72 100644 (file)
@@ -660,7 +660,7 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev,
                        u32 *data = (u32 *)
                                ((char *)dev_priv->buffers->handle
                                 + buf->offset + start);
-                       data[dwords++] = R128_CCE_PACKET2;
+                       data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
                }
 
                buf_priv->dispatched = 1;
@@ -704,7 +704,7 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
        drm_r128_buf_priv_t *buf_priv = buf->dev_private;
        drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int format = sarea_priv->vc_format;
-       int offset = dev_priv->buffers->offset - dev->agp->base;
+       int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
        int prim = buf_priv->prim;
        u32 *data;
        int dwords;
@@ -727,16 +727,21 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
                data = (u32 *)((char *)dev_priv->buffers->handle
                               + buf->offset + start);
 
-               data[0] = CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+               data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
+                                                   dwords-2 ) );
 
-               data[1] = offset;
-               data[2] = R128_MAX_VB_VERTS;
-               data[3] = format;
-               data[4] = (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
-                          (count << 16));
+               data[1] = cpu_to_le32( offset );
+               data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
+               data[3] = cpu_to_le32( format );
+               data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
+                                       (count << 16)) );
 
                if ( count & 0x1 ) {
+#ifdef __LITTLE_ENDIAN
                        data[dwords-1] &= 0x0000ffff;
+#else
+                       data[dwords-1] &= 0xffff0000;
+#endif
                }
 
                do {
@@ -842,23 +847,23 @@ static int r128_cce_dispatch_blit( drm_device_t *dev,
 
        data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
 
-       data[0] = CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 );
-       data[1] = (R128_GMC_DST_PITCH_OFFSET_CNTL |
-                  R128_GMC_BRUSH_NONE |
-                  (blit->format << 8) |
-                  R128_GMC_SRC_DATATYPE_COLOR |
-                  R128_ROP3_S |
-                  R128_DP_SRC_SOURCE_HOST_DATA |
-                  R128_GMC_CLR_CMP_CNTL_DIS |
-                  R128_GMC_AUX_CLIP_DIS |
-                  R128_GMC_WR_MSK_DIS);
-
-       data[2] = (blit->pitch << 21) | (blit->offset >> 5);
-       data[3] = 0xffffffff;
-       data[4] = 0xffffffff;
-       data[5] = (blit->y << 16) | blit->x;
-       data[6] = (blit->height << 16) | blit->width;
-       data[7] = dwords;
+       data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
+       data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
+                               R128_GMC_BRUSH_NONE |
+                               (blit->format << 8) |
+                               R128_GMC_SRC_DATATYPE_COLOR |
+                               R128_ROP3_S |
+                               R128_DP_SRC_SOURCE_HOST_DATA |
+                               R128_GMC_CLR_CMP_CNTL_DIS |
+                               R128_GMC_AUX_CLIP_DIS |
+                               R128_GMC_WR_MSK_DIS) );
+
+       data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
+       data[3] = cpu_to_le32( 0xffffffff );
+       data[4] = cpu_to_le32( 0xffffffff );
+       data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
+       data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
+       data[7] = cpu_to_le32( dwords );
 
        buf->used = (dwords + 8) * sizeof(u32);
 
@@ -1299,8 +1304,8 @@ int r128_cce_vertex( struct inode *inode, struct file *filp,
 
        LOCK_TEST_WITH_RETURN( dev );
 
-       if ( !dev_priv || dev_priv->is_pci ) {
-               DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
                return -EINVAL;
        }
 
@@ -1362,8 +1367,8 @@ int r128_cce_indices( struct inode *inode, struct file *filp,
 
        LOCK_TEST_WITH_RETURN( dev );
 
-       if ( !dev_priv || dev_priv->is_pci ) {
-               DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
                return -EINVAL;
        }
 
index db238b1..0fdeb82 100644 (file)
 /* General customization:
  */
 #define __HAVE_AGP             1
-#define __MUST_HAVE_AGP                1
+#define __MUST_HAVE_AGP                0
 #define __HAVE_MTRR            1
 #define __HAVE_CTX_BITMAP      1
+#define __HAVE_SG              1
+#define __HAVE_PCI_DMA         1
 
 /* Driver customization:
  */
index 5d662bc..c255a3e 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Kevin E. Martin <martin@valinux.com>
- *   Gareth Hughes <gareth@valinux.com>
- *
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #define __NO_VERSION__
+#include "radeon.h"
 #include "drmP.h"
 #include "radeon_drv.h"
 
@@ -300,26 +300,6 @@ static u32 radeon_cp_microcode[][2] = {
 };
 
 
-#define DO_IOREMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
-
-#define DO_IOREMAPFREE(_m)                                             \
-       do {                                                            \
-               if ((_m)->handle && (_m)->size)                         \
-                       drm_ioremapfree((_m)->handle, (_m)->size);      \
-       } while (0)
-
-#define DO_FIND_MAP(_m, _o)                                            \
-       do {                                                            \
-               int _i;                                                 \
-               for (_i = 0; _i < dev->map_count; _i++) {               \
-                       if (dev->maplist[_i]->offset == _o) {           \
-                               _m = dev->maplist[_i];                  \
-                               break;                                  \
-                       }                                               \
-               }                                                       \
-       } while (0)
-
-
 int RADEON_READ_PLL(drm_device_t *dev, int addr)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -338,6 +318,16 @@ static void radeon_status( drm_radeon_private_t *dev_priv )
                (unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
        printk( "CP_RB_WTPR = 0x%08x\n",
                (unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
+       printk( "AIC_CNTL = 0x%08x\n",
+               (unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
+       printk( "AIC_STAT = 0x%08x\n",
+               (unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
+       printk( "AIC_PT_BASE = 0x%08x\n",
+               (unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
+       printk( "TLB_ADDR = 0x%08x\n",
+               (unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
+       printk( "TLB_DATA = 0x%08x\n",
+               (unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
 }
 #endif
 
@@ -421,6 +411,7 @@ static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
 static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
 {
        int i;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 
        radeon_do_wait_for_idle( dev_priv );
 
@@ -439,6 +430,7 @@ static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
  */
 static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
 {
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 #if 0
        u32 tmp;
 
@@ -452,6 +444,7 @@ static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
 int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
 {
        RING_LOCALS;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 
        BEGIN_RING( 6 );
 
@@ -469,6 +462,7 @@ int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
 static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
 {
        RING_LOCALS;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 
        radeon_do_wait_for_idle( dev_priv );
 
@@ -492,6 +486,7 @@ static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
 static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
 {
        u32 cur_read_ptr;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 
        cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
        RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
@@ -505,6 +500,8 @@ static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
  */
 static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
 {
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
        RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
 
        dev_priv->cp_running = 0;
@@ -571,18 +568,29 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev )
        drm_radeon_private_t *dev_priv = dev->dev_private;
        u32 ring_start, cur_read_ptr;
        u32 tmp;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 
        /* Initialize the memory controller */
        RADEON_WRITE( RADEON_MC_FB_LOCATION,
                      (dev_priv->agp_vm_start - 1) & 0xffff0000 );
-       RADEON_WRITE( RADEON_MC_AGP_LOCATION,
-                     (((dev_priv->agp_vm_start - 1 +
-                        dev_priv->agp_size) & 0xffff0000) |
-                      (dev_priv->agp_vm_start >> 16)) );
 
-       ring_start = (dev_priv->cp_ring->offset
-                     - dev->agp->base
-                     + dev_priv->agp_vm_start);
+       if ( !dev_priv->is_pci ) {
+               RADEON_WRITE( RADEON_MC_AGP_LOCATION,
+                             (((dev_priv->agp_vm_start - 1 +
+                                dev_priv->agp_size) & 0xffff0000) |
+                              (dev_priv->agp_vm_start >> 16)) );
+       }
+
+#if __REALLY_HAVE_AGP
+       if ( !dev_priv->is_pci )
+               ring_start = (dev_priv->cp_ring->offset
+                             - dev->agp->base
+                             + dev_priv->agp_vm_start);
+       else
+#endif
+               ring_start = (dev_priv->cp_ring->offset
+                             - dev->sg->handle
+                             + dev_priv->agp_vm_start);
 
        RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
 
@@ -595,17 +603,29 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev )
        *dev_priv->ring.head = cur_read_ptr;
        dev_priv->ring.tail = cur_read_ptr;
 
-       RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset );
+       if ( !dev_priv->is_pci ) {
+               RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+                             dev_priv->ring_rptr->offset );
+       } else {
+               drm_sg_mem_t *entry = dev->sg;
+               unsigned long tmp_ofs, page_ofs;
+
+               tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+               page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+               RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+                             virt_to_bus(entry->pagelist[page_ofs]->virtual));
+
+               DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+                          virt_to_bus(entry->pagelist[page_ofs]->virtual),
+                          entry->handle + tmp_ofs );
+       }
 
        /* Set ring buffer size */
        RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
 
        radeon_do_wait_for_idle( dev_priv );
 
-       /* Turn off PCI GART */
-       tmp = RADEON_READ( RADEON_AIC_CNTL ) & ~RADEON_PCIGART_TRANSLATE_EN;
-       RADEON_WRITE( RADEON_AIC_CNTL, tmp );
-
        /* Turn on bus mastering */
        tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
        RADEON_WRITE( RADEON_BUS_CNTL, tmp );
@@ -621,9 +641,11 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev )
 static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 {
        drm_radeon_private_t *dev_priv;
-        int i;
+       struct list_head *list;
+       u32 tmp;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       dev_priv = drm_alloc( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
+       dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
        if ( dev_priv == NULL )
                return -ENOMEM;
        dev->dev_private = (void *)dev_priv;
@@ -632,12 +654,21 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 
        dev_priv->is_pci = init->is_pci;
 
-       /* We don't support PCI cards until PCI GART is implemented.
-        * Fail here so we can remove all checks for PCI cards around
-        * the CP ring code.
+#if 1
+       /* PCI support is not 100% working, so we disable it here.
         */
        if ( dev_priv->is_pci ) {
-               drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+               DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
+               DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+               dev->dev_private = NULL;
+               return -EINVAL;
+       }
+#endif
+
+       if ( dev_priv->is_pci && !dev->sg ) {
+               DRM_DEBUG( "PCI GART memory not allocated!\n" );
+               DRM_ERROR( "PCI GART memory not allocated!\n" );
+               DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
                dev->dev_private = NULL;
                return -EINVAL;
        }
@@ -645,7 +676,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
        dev_priv->usec_timeout = init->usec_timeout;
        if ( dev_priv->usec_timeout < 1 ||
             dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
-               drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+               DRM_DEBUG( "TIMEOUT problem!\n" );
+               DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
                dev->dev_private = NULL;
                return -EINVAL;
        }
@@ -662,7 +694,8 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
         */
        if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
             ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
-               drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
+               DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
+               DRM(free)( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
                dev->dev_private = NULL;
                return -EINVAL;
        }
@@ -722,55 +755,78 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
                                         RADEON_BFACE_SOLID |
                                         RADEON_FFACE_SOLID |
                                         RADEON_FLAT_SHADE_VTX_LAST |
-
                                         RADEON_DIFFUSE_SHADE_FLAT |
                                         RADEON_ALPHA_SHADE_FLAT |
                                         RADEON_SPECULAR_SHADE_FLAT |
                                         RADEON_FOG_SHADE_FLAT |
-
                                         RADEON_VTX_PIX_CENTER_OGL |
                                         RADEON_ROUND_MODE_TRUNC |
                                         RADEON_ROUND_PREC_8TH_PIX);
 
-       /* FIXME: We want multiple shared areas, including one shared
-        * only by the X Server and kernel module.
-        */
-       for ( i = 0 ; i < dev->map_count ; i++ ) {
-               if ( dev->maplist[i]->type == _DRM_SHM ) {
-                       dev_priv->sarea = dev->maplist[i];
-                       break;
-               }
-       }
-
-       DO_FIND_MAP( dev_priv->fb, init->fb_offset );
-       DO_FIND_MAP( dev_priv->mmio, init->mmio_offset );
-       DO_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
-       DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
-       DO_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+       list_for_each(list, &dev->maplist->head) {
+               drm_map_list_t *r_list = (drm_map_list_t *)list;
+               if( r_list->map &&
+                   r_list->map->type == _DRM_SHM &&
+                   r_list->map->flags & _DRM_CONTAINS_LOCK ) {
+                       dev_priv->sarea = r_list->map;
+                       break;
+               }
+       }
+
+       DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+       DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+       DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
+       DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+       DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
 
        if ( !dev_priv->is_pci ) {
-               DO_FIND_MAP( dev_priv->agp_textures,
-                            init->agp_textures_offset );
+               DRM_FIND_MAP( dev_priv->agp_textures,
+                             init->agp_textures_offset );
        }
 
        dev_priv->sarea_priv =
                (drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
                                       init->sarea_priv_offset);
 
-       DO_IOREMAP( dev_priv->cp_ring );
-       DO_IOREMAP( dev_priv->ring_rptr );
-       DO_IOREMAP( dev_priv->buffers );
-#if 0
        if ( !dev_priv->is_pci ) {
-               DO_IOREMAP( dev_priv->agp_textures );
+               DRM_IOREMAP( dev_priv->cp_ring );
+               DRM_IOREMAP( dev_priv->ring_rptr );
+               DRM_IOREMAP( dev_priv->buffers );
+       } else {
+               dev_priv->cp_ring->handle =
+                       (void *)dev_priv->cp_ring->offset;
+               dev_priv->ring_rptr->handle =
+                       (void *)dev_priv->ring_rptr->offset;
+               dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+
+               DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
+                          dev_priv->cp_ring->handle );
+               DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
+                          dev_priv->ring_rptr->handle );
+               DRM_DEBUG( "dev_priv->buffers->handle %p\n",
+                          dev_priv->buffers->handle );
        }
-#endif
+
 
        dev_priv->agp_size = init->agp_size;
        dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
-       dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
-                                       - dev->agp->base
-                                       + dev_priv->agp_vm_start);
+#if __REALLY_HAVE_AGP
+       if ( !dev_priv->is_pci )
+               dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+                                               - dev->agp->base
+                                               + dev_priv->agp_vm_start);
+       else
+#endif
+               dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+                                               - dev->sg->handle
+                                               + dev_priv->agp_vm_start);
+
+       DRM_DEBUG( "dev_priv->agp_size %d\n",
+                  dev_priv->agp_size );
+       DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
+                  dev_priv->agp_vm_start );
+       DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
+                  dev_priv->agp_buffers_offset );
 
        dev_priv->ring.head = ((__volatile__ u32 *)
                               dev_priv->ring_rptr->handle);
@@ -779,11 +835,13 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
        dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
                              + init->ring_size / sizeof(u32));
        dev_priv->ring.size = init->ring_size;
-       dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
+       dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
 
        dev_priv->ring.tail_mask =
                (dev_priv->ring.size / sizeof(u32)) - 1;
 
+       dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
+
 #if 0
        /* Initialize the scratch register pointer.  This will cause
         * the scratch register values to be written out to memory
@@ -812,6 +870,44 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
        RADEON_WRITE( RADEON_LAST_CLEAR_REG,
                      dev_priv->sarea_priv->last_clear );
 
+       if ( dev_priv->is_pci ) {
+               dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev );
+               if ( !dev_priv->phys_pci_gart ) {
+                       DRM_DEBUG( "failed to init PCI GART!\n" );
+                       DRM_ERROR( "failed to init PCI GART!\n" );
+                       DRM(free)( dev_priv, sizeof(*dev_priv),
+                                  DRM_MEM_DRIVER );
+                       dev->dev_private = NULL;
+                       return -EINVAL;
+               }
+               /* Turn on PCI GART
+                */
+               tmp = RADEON_READ( RADEON_AIC_CNTL )
+                     | RADEON_PCIGART_TRANSLATE_EN;
+               RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+
+               /* set PCI GART page-table base address
+                */
+               RADEON_WRITE( RADEON_AIC_PT_BASE,
+                             virt_to_bus( (void *)dev_priv->phys_pci_gart ) );
+
+               /* set address range for PCI address translate
+                */
+               RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
+               RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
+                                                 + dev_priv->agp_size - 1);
+
+               /* Turn off AGP aperture -- is this required for PCIGART?
+                */
+               RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0 );
+       } else {
+               /* Turn off PCI GART
+                */
+               tmp = RADEON_READ( RADEON_AIC_CNTL )
+                     & ~RADEON_PCIGART_TRANSLATE_EN;
+               RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+       }
+
        radeon_cp_load_microcode( dev_priv );
        radeon_cp_init_ring_buffer( dev );
        radeon_do_engine_reset( dev );
@@ -823,22 +919,21 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
        return 0;
 }
 
-static int radeon_do_cleanup_cp( drm_device_t *dev )
+int radeon_do_cleanup_cp( drm_device_t *dev )
 {
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
        if ( dev->dev_private ) {
                drm_radeon_private_t *dev_priv = dev->dev_private;
 
-               DO_IOREMAPFREE( dev_priv->cp_ring );
-               DO_IOREMAPFREE( dev_priv->ring_rptr );
-               DO_IOREMAPFREE( dev_priv->buffers );
-#if 0
                if ( !dev_priv->is_pci ) {
-                       DO_IOREMAPFREE( dev_priv->agp_textures );
+                       DRM_IOREMAPFREE( dev_priv->cp_ring );
+                       DRM_IOREMAPFREE( dev_priv->ring_rptr );
+                       DRM_IOREMAPFREE( dev_priv->buffers );
                }
-#endif
 
-               drm_free( dev->dev_private, sizeof(drm_radeon_private_t),
-                         DRM_MEM_DRIVER );
+               DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
+                          DRM_MEM_DRIVER );
                dev->dev_private = NULL;
        }
 
@@ -873,11 +968,8 @@ int radeon_cp_start( struct inode *inode, struct file *filp,
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
+
        if ( dev_priv->cp_running ) {
                DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
                return 0;
@@ -906,11 +998,7 @@ int radeon_cp_stop( struct inode *inode, struct file *filp,
        int ret;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
 
        if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) )
                return -EFAULT;
@@ -952,11 +1040,8 @@ int radeon_cp_reset( struct inode *inode, struct file *filp,
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
+
        if ( !dev_priv ) {
                DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
                return -EINVAL;
@@ -978,11 +1063,7 @@ int radeon_cp_idle( struct inode *inode, struct file *filp,
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
 
        return radeon_do_cp_idle( dev_priv );
 }
@@ -994,11 +1075,7 @@ int radeon_engine_reset( struct inode *inode, struct file *filp,
         drm_device_t *dev = priv->dev;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
 
        return radeon_do_engine_reset( dev );
 }
@@ -1048,11 +1125,7 @@ int radeon_fullscreen( struct inode *inode, struct file *filp,
         drm_device_t *dev = priv->dev;
        drm_radeon_fullscreen_t fs;
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
 
        if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
                             sizeof(fs) ) )
@@ -1085,8 +1158,8 @@ static int radeon_freelist_init( drm_device_t *dev )
        drm_radeon_freelist_t *entry;
        int i;
 
-       dev_priv->head = drm_alloc( sizeof(drm_radeon_freelist_t),
-                                   DRM_MEM_DRIVER );
+       dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t),
+                                    DRM_MEM_DRIVER );
        if ( dev_priv->head == NULL )
                return -ENOMEM;
 
@@ -1097,8 +1170,8 @@ static int radeon_freelist_init( drm_device_t *dev )
                buf = dma->buflist[i];
                buf_priv = buf->dev_private;
 
-               entry = drm_alloc( sizeof(drm_radeon_freelist_t),
-                                  DRM_MEM_DRIVER );
+               entry = DRM(alloc)( sizeof(drm_radeon_freelist_t),
+                                   DRM_MEM_DRIVER );
                if ( !entry ) return -ENOMEM;
 
                entry->age = RADEON_BUFFER_FREE;
@@ -1218,32 +1291,20 @@ int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n )
        int i;
 
        for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-               ring->space = *ring->head - ring->tail;
-               if ( ring->space <= 0 )
-                       ring->space += ring->size;
-
-               if ( ring->space >= n )
+               radeon_update_ring_snapshot( ring );
+               if ( ring->space > n )
                        return 0;
-
                udelay( 1 );
        }
 
        /* FIXME: This return value is ignored in the BEGIN_RING macro! */
+#if RADEON_FIFO_DEBUG
+       radeon_status( dev_priv );
        DRM_ERROR( "failed!\n" );
+#endif
        return -EBUSY;
 }
 
-void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
-
-       ring->space = *ring->head - ring->tail;
-       if ( ring->space == 0 )
-               atomic_inc( &dev_priv->idle_count );
-       if ( ring->space <= 0 )
-               ring->space += ring->size;
-}
-
 static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
 {
        int i;
@@ -1276,14 +1337,10 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp,
        int ret = 0;
        drm_dma_t d;
 
-       if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) )
-               return -EFAULT;
+       LOCK_TEST_WITH_RETURN( dev );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
+               return -EFAULT;
 
        /* Please don't send us buffers.
         */
@@ -1307,7 +1364,7 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp,
                ret = radeon_cp_get_buffers( dev, &d );
        }
 
-       if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) )
+       if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
                return -EFAULT;
 
        return ret;
index c5f9f66..4ae387f 100644 (file)
@@ -26,7 +26,6 @@
  * Authors:
  *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *
  */
 
 #ifndef __RADEON_DRM_H__
@@ -74,7 +73,7 @@
 
 /* Vertex/indirect buffer size
  */
-#define RADEON_BUFFER_SIZE             16384
+#define RADEON_BUFFER_SIZE             65536
 
 /* Byte offsets for indirect buffer data
  */
@@ -237,7 +236,7 @@ typedef struct drm_radeon_init {
                RADEON_INIT_CP    = 0x01,
                RADEON_CLEANUP_CP = 0x02
        } func;
-       int sarea_priv_offset;
+       unsigned long sarea_priv_offset;
        int is_pci;
        int cp_mode;
        int agp_size;
@@ -250,12 +249,12 @@ typedef struct drm_radeon_init {
        unsigned int depth_bpp;
        unsigned int depth_offset, depth_pitch;
 
-       unsigned int fb_offset;
-       unsigned int mmio_offset;
-       unsigned int ring_offset;
-       unsigned int ring_rptr_offset;
-       unsigned int buffers_offset;
-       unsigned int agp_textures_offset;
+       unsigned long fb_offset;
+       unsigned long mmio_offset;
+       unsigned long ring_offset;
+       unsigned long ring_rptr_offset;
+       unsigned long buffers_offset;
+       unsigned long agp_textures_offset;
 } drm_radeon_init_t;
 
 typedef struct drm_radeon_cp_stop {
@@ -276,15 +275,18 @@ typedef struct drm_radeon_fullscreen {
 #define CLEAR_Y2       3
 #define CLEAR_DEPTH    4
 
+typedef union drm_radeon_clear_rect {
+       float f[5];
+       unsigned int ui[5];
+} drm_radeon_clear_rect_t;
+
 typedef struct drm_radeon_clear {
        unsigned int flags;
-       int x, y, w, h;
        unsigned int clear_color;
        unsigned int clear_depth;
-       union {
-               float f[5];
-               unsigned int ui[5];
-       } rect;
+       unsigned int color_mask;
+       unsigned int depth_mask;
+       drm_radeon_clear_rect_t *depth_boxes;
 } drm_radeon_clear_t;
 
 typedef struct drm_radeon_vertex {
@@ -302,14 +304,20 @@ typedef struct drm_radeon_indices {
        int discard;                    /* Client finished with buffer? */
 } drm_radeon_indices_t;
 
-typedef struct drm_radeon_blit {
-       int idx;
-       int pitch;
+typedef struct drm_radeon_tex_image {
+       unsigned int x, y;              /* Blit coordinates */
+       unsigned int width, height;
+       const void *data;
+} drm_radeon_tex_image_t;
+
+typedef struct drm_radeon_texture {
        int offset;
+       int pitch;
        int format;
-       unsigned short x, y;
-       unsigned short width, height;
-} drm_radeon_blit_t;
+       int width;                      /* Texture image coordinates */
+       int height;
+       drm_radeon_tex_image_t *image;
+} drm_radeon_texture_t;
 
 typedef struct drm_radeon_stipple {
        unsigned int *mask;
index b022c3b..d763266 100644 (file)
 #include "radeon.h"
 #include "drmP.h"
 #include "radeon_drv.h"
+#include "ati_pcigart.h"
 
 #define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
 
 #define DRIVER_NAME            "radeon"
 #define DRIVER_DESC            "ATI Radeon"
-#define DRIVER_DATE            "20010402"
+#define DRIVER_DATE            "20010405"
 
 #define DRIVER_MAJOR           1
 #define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      0
+#define DRIVER_PATCHLEVEL      1
 
 #define DRIVER_IOCTLS                                                       \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
@@ -85,3 +86,4 @@
 #include "drm_proc.h"
 #include "drm_vm.h"
 #include "drm_stub.h"
+#include "drm_scatter.h"
index 06b5419..2493584 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Rickard E. (Rik) Faith <faith@valinux.com>
- *   Kevin E. Martin <martin@valinux.com>
- *   Gareth Hughes <gareth@valinux.com>
- *
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #ifndef __RADEON_DRV_H__
@@ -50,6 +48,8 @@ typedef struct drm_radeon_ring_buffer {
        u32 tail;
        u32 tail_mask;
        int space;
+
+       int high_mark;
 } drm_radeon_ring_buffer_t;
 
 typedef struct drm_radeon_depth_clear_t {
@@ -64,7 +64,7 @@ typedef struct drm_radeon_private {
 
        int agp_size;
        u32 agp_vm_start;
-       u32 agp_buffers_offset;
+       unsigned long agp_buffers_offset;
 
        int cp_mode;
        int cp_running;
@@ -83,6 +83,7 @@ typedef struct drm_radeon_private {
 
        int usec_timeout;
        int is_pci;
+       unsigned long phys_pci_gart;
 
        atomic_t idle_count;
 
@@ -91,13 +92,13 @@ typedef struct drm_radeon_private {
        u32 crtc_offset;
        u32 crtc_offset_cntl;
 
-       unsigned int color_fmt;
+       u32 color_fmt;
        unsigned int front_offset;
        unsigned int front_pitch;
        unsigned int back_offset;
        unsigned int back_pitch;
 
-       unsigned int depth_fmt;
+       u32 depth_fmt;
        unsigned int depth_offset;
        unsigned int depth_pitch;
 
@@ -124,18 +125,6 @@ typedef struct drm_radeon_buf_priv {
        drm_radeon_freelist_t *list_entry;
 } drm_radeon_buf_priv_t;
 
-                               /* radeon_drv.c */
-extern int  radeon_version( struct inode *inode, struct file *filp,
-                           unsigned int cmd, unsigned long arg );
-extern int  radeon_open( struct inode *inode, struct file *filp );
-extern int  radeon_release( struct inode *inode, struct file *filp );
-extern int  radeon_ioctl( struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg );
-extern int  radeon_lock( struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg );
-extern int  radeon_unlock( struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg );
-
                                /* radeon_cp.c */
 extern int radeon_cp_init( struct inode *inode, struct file *filp,
                           unsigned int cmd, unsigned long arg );
@@ -158,9 +147,17 @@ extern void radeon_freelist_reset( drm_device_t *dev );
 extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
 
 extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
-extern void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv );
+
+static inline void
+radeon_update_ring_snapshot( drm_radeon_ring_buffer_t *ring )
+{
+       ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32);
+       if ( ring->space <= 0 )
+               ring->space += ring->size;
+}
 
 extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
+extern int radeon_do_cleanup_cp( drm_device_t *dev );
 extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
 
                                /* radeon_state.c */
@@ -172,38 +169,13 @@ extern int radeon_cp_vertex( struct inode *inode, struct file *filp,
                             unsigned int cmd, unsigned long arg );
 extern int radeon_cp_indices( struct inode *inode, struct file *filp,
                              unsigned int cmd, unsigned long arg );
-extern int radeon_cp_blit( struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg );
+extern int radeon_cp_texture( struct inode *inode, struct file *filp,
+                             unsigned int cmd, unsigned long arg );
 extern int radeon_cp_stipple( struct inode *inode, struct file *filp,
                              unsigned int cmd, unsigned long arg );
 extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
                               unsigned int cmd, unsigned long arg );
 
-                               /* radeon_bufs.c */
-extern int radeon_addbufs(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int radeon_mapbufs(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-
-                               /* radeon_context.c */
-extern int  radeon_resctx(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int  radeon_addctx(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int  radeon_modctx(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int  radeon_getctx(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int  radeon_switchctx(struct inode *inode, struct file *filp,
-                            unsigned int cmd, unsigned long arg);
-extern int  radeon_newctx(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int  radeon_rmctx(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
-
-extern int  radeon_context_switch(drm_device_t *dev, int old, int new);
-extern int  radeon_context_switch_complete(drm_device_t *dev, int new);
-
 
 /* Register definitions, register access macros and drmAddMap constants
  * for Radeon kernel driver.
@@ -462,6 +434,12 @@ extern int  radeon_context_switch_complete(drm_device_t *dev, int new);
 
 #define RADEON_AIC_CNTL                        0x01d0
 #      define RADEON_PCIGART_TRANSLATE_EN      (1 << 0)
+#define RADEON_AIC_STAT                        0x01d4
+#define RADEON_AIC_PT_BASE             0x01d8
+#define RADEON_AIC_LO_ADDR             0x01dc
+#define RADEON_AIC_HI_ADDR             0x01e0
+#define RADEON_AIC_TLB_ADDR            0x01e4
+#define RADEON_AIC_TLB_DATA            0x01e8
 
 /* CP command packets */
 #define RADEON_CP_PACKET0              0x00000000
@@ -514,14 +492,14 @@ extern int  radeon_context_switch_complete(drm_device_t *dev, int new);
 #define RADEON_COLOR_FORMAT_RGB8       9
 #define RADEON_COLOR_FORMAT_ARGB4444   15
 
-#define RADEON_TXF_8BPP_I              0
-#define RADEON_TXF_16BPP_AI88          1
-#define RADEON_TXF_8BPP_RGB332         2
-#define RADEON_TXF_16BPP_ARGB1555      3
-#define RADEON_TXF_16BPP_RGB565                4
-#define RADEON_TXF_16BPP_ARGB4444      5
-#define RADEON_TXF_32BPP_ARGB8888      6
-#define RADEON_TXF_32BPP_RGBA8888      7
+#define RADEON_TXFORMAT_I8             0
+#define RADEON_TXFORMAT_AI88           1
+#define RADEON_TXFORMAT_RGB332         2
+#define RADEON_TXFORMAT_ARGB1555       3
+#define RADEON_TXFORMAT_RGB565         4
+#define RADEON_TXFORMAT_ARGB4444       5
+#define RADEON_TXFORMAT_ARGB8888       6
+#define RADEON_TXFORMAT_RGBA8888       7
 
 /* Constants */
 #define RADEON_MAX_USEC_TIMEOUT                100000  /* 100 ms */
@@ -534,27 +512,51 @@ extern int  radeon_context_switch_complete(drm_device_t *dev, int new);
 #define RADEON_MAX_VB_AGE              0x7fffffff
 #define RADEON_MAX_VB_VERTS            (0xffff)
 
+#define RADEON_RING_HIGH_MARK          128
 
-#define RADEON_BASE(reg)       ((u32)(dev_priv->mmio->handle))
-#define RADEON_ADDR(reg)       (RADEON_BASE(reg) + reg)
 
-#define RADEON_DEREF(reg)      *(__volatile__ u32 *)RADEON_ADDR(reg)
-#define RADEON_READ(reg)       RADEON_DEREF(reg)
-#define RADEON_WRITE(reg,val)  do { RADEON_DEREF(reg) = val; } while (0)
+#define RADEON_BASE(reg)       ((unsigned long)(dev_priv->mmio->handle))
+#define RADEON_ADDR(reg)       (RADEON_BASE( reg ) + reg)
 
-#define RADEON_DEREF8(reg)     *(__volatile__ u8 *)RADEON_ADDR(reg)
-#define RADEON_READ8(reg)      RADEON_DEREF8(reg)
-#define RADEON_WRITE8(reg,val) do { RADEON_DEREF8(reg) = val; } while (0)
+#define RADEON_DEREF(reg)      *(volatile u32 *)RADEON_ADDR( reg )
+#ifdef __alpha__
+#define RADEON_READ(reg)       (_RADEON_READ((u32 *)RADEON_ADDR( reg )))
+static inline u32 _RADEON_READ(u32 *addr) {
+       mb();
+       return *(volatile u32 *)addr;
+}
+#define RADEON_WRITE(reg,val) do {                                     \
+       wmb();
+       RADEON_DEREF(reg) = val;
+} while (0)
+#else
+#define RADEON_READ(reg)       RADEON_DEREF( reg )
+#define RADEON_WRITE(reg, val) do { RADEON_DEREF( reg ) = val; } while (0)
+#endif
 
-#define RADEON_WRITE_PLL(addr,val)                                            \
-do {                                                                          \
-       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX,                                \
-                     ((addr) & 0x1f) | RADEON_PLL_WR_EN);                    \
-       RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val));                          \
+#define RADEON_DEREF8(reg)     *(volatile u8 *)RADEON_ADDR( reg )
+#ifdef __alpha__
+#define RADEON_READ8(reg)      _RADEON_READ8((u8 *)RADEON_ADDR( reg ))
+static inline u8 _RADEON_READ8(u8 *addr) {
+       mb();
+       return *(volatile u8 *)addr;
+}
+#define RADEON_WRITE8(reg,val) do {                                    \
+       wmb();
+       RADEON_DEREF8( reg ) = val;
 } while (0)
+#else
+#define RADEON_READ8(reg)      RADEON_DEREF8( reg )
+#define RADEON_WRITE8(reg, val)        do { RADEON_DEREF8( reg ) = val; } while (0)
+#endif
 
-extern int RADEON_READ_PLL(drm_device_t *dev, int addr);
+#define RADEON_WRITE_PLL( addr, val ) do {                             \
+       RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX,                         \
+                      ((addr) & 0x1f) | RADEON_PLL_WR_EN );            \
+       RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) );                  \
+} while (0)
 
+extern int RADEON_READ_PLL( drm_device_t *dev, int addr );
 
 
 #define CP_PACKET0( reg, n )                                           \
@@ -573,54 +575,46 @@ extern int RADEON_READ_PLL(drm_device_t *dev, int addr);
  * Engine control helper macros
  */
 
-#define RADEON_WAIT_UNTIL_2D_IDLE()                                    \
-do {                                                                   \
+#define RADEON_WAIT_UNTIL_2D_IDLE() do {                               \
        OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
        OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |                           \
                   RADEON_WAIT_HOST_IDLECLEAN) );                       \
 } while (0)
 
-#define RADEON_WAIT_UNTIL_3D_IDLE()                                    \
-do {                                                                   \
+#define RADEON_WAIT_UNTIL_3D_IDLE() do {                               \
        OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
        OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |                           \
                   RADEON_WAIT_HOST_IDLECLEAN) );                       \
 } while (0)
 
-#define RADEON_WAIT_UNTIL_IDLE()                                       \
-do {                                                                   \
+#define RADEON_WAIT_UNTIL_IDLE() do {                                  \
        OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
        OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |                           \
                   RADEON_WAIT_3D_IDLECLEAN |                           \
                   RADEON_WAIT_HOST_IDLECLEAN) );                       \
 } while (0)
 
-#define RADEON_WAIT_UNTIL_PAGE_FLIPPED()                               \
-do {                                                                   \
+#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do {                          \
        OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
        OUT_RING( RADEON_WAIT_CRTC_PFLIP );                             \
 } while (0)
 
-#define RADEON_FLUSH_CACHE()                                           \
-do {                                                                   \
+#define RADEON_FLUSH_CACHE() do {                                      \
        OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );      \
        OUT_RING( RADEON_RB2D_DC_FLUSH );                               \
 } while (0)
 
-#define RADEON_PURGE_CACHE()                                           \
-do {                                                                   \
+#define RADEON_PURGE_CACHE() do {                                      \
        OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );      \
        OUT_RING( RADEON_RB2D_DC_FLUSH_ALL );                           \
 } while (0)
 
-#define RADEON_FLUSH_ZCACHE()                                          \
-do {                                                                   \
+#define RADEON_FLUSH_ZCACHE() do {                                     \
        OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );        \
        OUT_RING( RADEON_RB3D_ZC_FLUSH );                               \
 } while (0)
 
-#define RADEON_PURGE_ZCACHE()                                          \
-do {                                                                   \
+#define RADEON_PURGE_ZCACHE() do {                                     \
        OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );        \
        OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL );                           \
 } while (0)
@@ -630,7 +624,33 @@ do {                                                                       \
  * Misc helper macros
  */
 
-#define VB_AGE_CHECK_WITH_RET( dev_priv )                              \
+#define LOCK_TEST_WITH_RETURN( dev )                                   \
+do {                                                                   \
+       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||           \
+            dev->lock.pid != current->pid ) {                          \
+               DRM_ERROR( "%s called without lock held\n",             \
+                          __FUNCTION__ );                              \
+               return -EINVAL;                                         \
+       }                                                               \
+} while (0)
+
+#define RING_SPACE_TEST_WITH_RETURN( dev_priv )                                \
+do {                                                                   \
+       drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i;        \
+       if ( ring->space < ring->high_mark ) {                          \
+               for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {      \
+                       radeon_update_ring_snapshot( ring );            \
+                       if ( ring->space >= ring->high_mark )           \
+                               goto __ring_space_done;                 \
+                       udelay( 1 );                                    \
+               }                                                       \
+               DRM_ERROR( "ring space check failed!\n" );              \
+               return -EBUSY;                                          \
+       }                                                               \
+ __ring_space_done:                                                    \
+} while (0)
+
+#define VB_AGE_TEST_WITH_RETURN( dev_priv )                            \
 do {                                                                   \
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;          \
        if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {         \
@@ -641,20 +661,17 @@ do {                                                                      \
        }                                                               \
 } while (0)
 
-#define RADEON_DISPATCH_AGE( age )                                     \
-do {                                                                   \
+#define RADEON_DISPATCH_AGE( age ) do {                                        \
        OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) );          \
        OUT_RING( age );                                                \
 } while (0)
 
-#define RADEON_FRAME_AGE( age )                                                \
-do {                                                                   \
+#define RADEON_FRAME_AGE( age ) do {                                   \
        OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) );             \
        OUT_RING( age );                                                \
 } while (0)
 
-#define RADEON_CLEAR_AGE( age )                                                \
-do {                                                                   \
+#define RADEON_CLEAR_AGE( age ) do {                                   \
        OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) );             \
        OUT_RING( age );                                                \
 } while (0)
@@ -676,7 +693,7 @@ do {                                                                        \
                DRM_INFO( "BEGIN_RING( %d ) in %s\n",                   \
                           n, __FUNCTION__ );                           \
        }                                                               \
-       if ( dev_priv->ring.space < (n) * sizeof(u32) ) {               \
+       if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {              \
                radeon_wait_ring( dev_priv, (n) * sizeof(u32) );        \
        }                                                               \
        dev_priv->ring.space -= (n) * sizeof(u32);                      \
@@ -687,7 +704,7 @@ do {                                                                        \
 
 #define ADVANCE_RING() do {                                            \
        if ( RADEON_VERBOSE ) {                                         \
-               DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n",     \
+               DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",     \
                          write, dev_priv->ring.tail );                 \
        }                                                               \
        radeon_flush_write_combine();                                   \
index 7bfefb2..0a20924 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *
+ *    Kevin E. Martin <martin@valinux.com>
  */
 
 #define __NO_VERSION__
+#include "radeon.h"
 #include "drmP.h"
 #include "radeon_drv.h"
 #include "drm.h"
@@ -486,7 +486,8 @@ static void radeon_print_dirty( const char *msg, unsigned int flags )
 }
 
 static void radeon_cp_dispatch_clear( drm_device_t *dev,
-                                     drm_radeon_clear_t *clear )
+                                     drm_radeon_clear_t *clear,
+                                     drm_radeon_clear_rect_t *depth_boxes )
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -497,8 +498,6 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
        RING_LOCALS;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       radeon_update_ring_snapshot( dev_priv );
-
        if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
                unsigned int tmp = flags;
 
@@ -525,7 +524,7 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
                        RADEON_WAIT_UNTIL_3D_IDLE();
 
                        OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
-                       OUT_RING( sarea_priv->context_state.rb3d_planemask );
+                       OUT_RING( clear->color_mask );
 
                        ADVANCE_RING();
 
@@ -609,17 +608,17 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
                                   RADEON_VTX_FMT_RADEON_MODE |
                                   (3 << RADEON_NUM_VERTICES_SHIFT)) );
 
-                       OUT_RING( clear->rect.ui[CLEAR_X1] );
-                       OUT_RING( clear->rect.ui[CLEAR_Y1] );
-                       OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
 
-                       OUT_RING( clear->rect.ui[CLEAR_X1] );
-                       OUT_RING( clear->rect.ui[CLEAR_Y2] );
-                       OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
 
-                       OUT_RING( clear->rect.ui[CLEAR_X2] );
-                       OUT_RING( clear->rect.ui[CLEAR_Y2] );
-                       OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+                       OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
 
                        ADVANCE_RING();
 
@@ -655,8 +654,6 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
        RING_LOCALS;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       radeon_update_ring_snapshot( dev_priv );
-
 #if RADEON_PERFORMANCE_BOXES
        /* Do some trivial performance monitoring...
         */
@@ -724,8 +721,6 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
        RING_LOCALS;
        DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
 
-       radeon_update_ring_snapshot( dev_priv );
-
 #if RADEON_PERFORMANCE_BOXES
        /* Do some trivial performance monitoring...
         */
@@ -776,9 +771,7 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev,
        RING_LOCALS;
        DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
 
-       radeon_update_ring_snapshot( dev_priv );
-
-       if ( 1 )
+       if ( 0 )
                radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
 
        if ( buf->used ) {
@@ -844,8 +837,6 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
        DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
                   buf->idx, start, end );
 
-       radeon_update_ring_snapshot( dev_priv );
-
        if ( start != end ) {
                int offset = (dev_priv->agp_buffers_offset
                              + buf->offset + start);
@@ -908,8 +899,6 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
        RING_LOCALS;
        DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
 
-       radeon_update_ring_snapshot( dev_priv );
-
        if ( 0 )
                radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
 
@@ -971,50 +960,67 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
        sarea_priv->nbox = 0;
 }
 
-static int radeon_cp_dispatch_blit( drm_device_t *dev,
-                                   drm_radeon_blit_t *blit )
+#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
+
+static int radeon_cp_dispatch_texture( drm_device_t *dev,
+                                      drm_radeon_texture_t *tex,
+                                      drm_radeon_tex_image_t *image )
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
        drm_buf_t *buf;
        drm_radeon_buf_priv_t *buf_priv;
        u32 format;
-       u32 *data;
-       int dword_shift, dwords;
+       u32 *buffer;
+       u8 *data;
+       int size, dwords, tex_width, blit_width;
+       u32 y, height;
+       int ret = 0, i;
        RING_LOCALS;
-       DRM_DEBUG( "blit: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
-                  blit->offset >> 10, blit->pitch, blit->format,
-                  blit->x, blit->y, blit->width, blit->height );
 
-       radeon_update_ring_snapshot( dev_priv );
+       /* FIXME: Be smarter about this...
+        */
+       buf = radeon_freelist_get( dev );
+       if ( !buf ) return -EAGAIN;
+
+       DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+                  tex->offset >> 10, tex->pitch, tex->format,
+                  image->x, image->y, image->width, image->height );
+
+       buf_priv = buf->dev_private;
 
        /* The compiler won't optimize away a division by a variable,
         * even if the only legal values are powers of two.  Thus, we'll
         * use a shift instead.
         */
-       switch ( blit->format ) {
-       case RADEON_TXF_32BPP_ARGB8888:
-       case RADEON_TXF_32BPP_RGBA8888:
+       switch ( tex->format ) {
+       case RADEON_TXFORMAT_ARGB8888:
+       case RADEON_TXFORMAT_RGBA8888:
                format = RADEON_COLOR_FORMAT_ARGB8888;
-               dword_shift = 0;
+               tex_width = tex->width * 4;
+               blit_width = image->width * 4;
                break;
-       case RADEON_TXF_16BPP_AI88:
-       case RADEON_TXF_16BPP_ARGB1555:
-       case RADEON_TXF_16BPP_RGB565:
-       case RADEON_TXF_16BPP_ARGB4444:
+       case RADEON_TXFORMAT_AI88:
+       case RADEON_TXFORMAT_ARGB1555:
+       case RADEON_TXFORMAT_RGB565:
+       case RADEON_TXFORMAT_ARGB4444:
                format = RADEON_COLOR_FORMAT_RGB565;
-               dword_shift = 1;
+               tex_width = tex->width * 2;
+               blit_width = image->width * 2;
                break;
-       case RADEON_TXF_8BPP_I:
-       case RADEON_TXF_8BPP_RGB332:
+       case RADEON_TXFORMAT_I8:
+       case RADEON_TXFORMAT_RGB332:
                format = RADEON_COLOR_FORMAT_CI8;
-               dword_shift = 2;
+               tex_width = tex->width * 1;
+               blit_width = image->width * 1;
                break;
        default:
-               DRM_ERROR( "invalid blit format %d\n", blit->format );
+               DRM_ERROR( "invalid texture format %d\n", tex->format );
                return -EINVAL;
        }
 
+       DRM_DEBUG( "   tex=%dx%d  blit=%d\n",
+                  tex_width, tex->height, blit_width );
+
        /* Flush the pixel cache.  This ensures no pixel data gets mixed
         * up with the texture data from the host data blit, otherwise
         * part of the texture image may be corrupted.
@@ -1026,46 +1032,88 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev,
 
        ADVANCE_RING();
 
-       /* Dispatch the indirect buffer.
+       /* Make a copy of the parameters in case we have to update them
+        * for a multi-pass texture blit.
         */
-       buf = dma->buflist[blit->idx];
-       buf_priv = buf->dev_private;
+       y = image->y;
+       height = image->height;
+       data = (u8 *)image->data;
 
-       if ( buf->pid != current->pid ) {
-               DRM_ERROR( "process %d using buffer owned by %d\n",
-                          current->pid, buf->pid );
-               return -EINVAL;
-       }
-       if ( buf->pending ) {
-               DRM_ERROR( "sending pending buffer %d\n", blit->idx );
-               return -EINVAL;
-       }
+       size = height * blit_width;
 
-       buf_priv->discard = 1;
+       if ( size > RADEON_MAX_TEXTURE_SIZE ) {
+               /* Texture image is too large, do a multipass upload */
+               ret = -EAGAIN;
 
-       dwords = (blit->width * blit->height) >> dword_shift;
-       if ( !dwords ) dwords = 1;
+               /* Adjust the blit size to fit the indirect buffer */
+               height = RADEON_MAX_TEXTURE_SIZE / blit_width;
+               size = height * blit_width;
 
-       data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+               /* Update the input parameters for next time */
+               image->y += height;
+               image->height -= height;
+               image->data = (char *)image->data + size;
 
-       data[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
-       data[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-                  RADEON_GMC_BRUSH_NONE |
-                  (format << 8) |
-                  RADEON_GMC_SRC_DATATYPE_COLOR |
-                  RADEON_ROP3_S |
-                  RADEON_DP_SRC_SOURCE_HOST_DATA |
-                  RADEON_GMC_CLR_CMP_CNTL_DIS |
-                  RADEON_GMC_WR_MSK_DIS);
+               if ( copy_to_user( tex->image, image, sizeof(*image) ) ) {
+                       DRM_ERROR( "EFAULT on tex->image\n" );
+                       return -EFAULT;
+               }
+       } else if ( size < 4 ) {
+               size = 4;
+       }
 
-       data[2] = (blit->pitch << 22) | (blit->offset >> 10);
-       data[3] = 0xffffffff;
-       data[4] = 0xffffffff;
-       data[5] = (blit->y << 16) | blit->x;
-       data[6] = (blit->height << 16) | blit->width;
-       data[7] = dwords;
+       dwords = size / 4;
 
+       /* Dispatch the indirect buffer.
+        */
+       buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+
+       buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
+       buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+                    RADEON_GMC_BRUSH_NONE |
+                    (format << 8) |
+                    RADEON_GMC_SRC_DATATYPE_COLOR |
+                    RADEON_ROP3_S |
+                    RADEON_DP_SRC_SOURCE_HOST_DATA |
+                    RADEON_GMC_CLR_CMP_CNTL_DIS |
+                    RADEON_GMC_WR_MSK_DIS);
+
+       buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
+       buffer[3] = 0xffffffff;
+       buffer[4] = 0xffffffff;
+       buffer[5] = (y << 16) | image->x;
+       buffer[6] = (height << 16) | image->width;
+       buffer[7] = dwords;
+
+       buffer += 8;
+
+       if ( tex_width >= 32 ) {
+               /* Texture image width is larger than the minimum, so we
+                * can upload it directly.
+                */
+               if ( copy_from_user( buffer, data, dwords * sizeof(u32) ) ) {
+                       DRM_ERROR( "EFAULT on data, %d dwords\n", dwords );
+                       return -EFAULT;
+               }
+       } else {
+               /* Texture image width is less than the minimum, so we
+                * need to pad out each image scanline to the minimum
+                * width.
+                */
+               for ( i = 0 ; i < tex->height ; i++ ) {
+                       if ( copy_from_user( buffer, data, tex_width ) ) {
+                               DRM_ERROR( "EFAULT on pad, %d bytes\n",
+                                          tex_width );
+                               return -EFAULT;
+                       }
+                       buffer += 8;
+                       data += tex_width;
+               }
+       }
+
+       buf->pid = current->pid;
        buf->used = (dwords + 8) * sizeof(u32);
+       buf_priv->discard = 1;
 
        radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
 
@@ -1080,7 +1128,7 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev,
 
        ADVANCE_RING();
 
-       return 0;
+       return ret;
 }
 
 static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
@@ -1090,8 +1138,6 @@ static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
        RING_LOCALS;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       radeon_update_ring_snapshot( dev_priv );
-
        BEGIN_RING( 35 );
 
        OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
@@ -1118,22 +1164,25 @@ int radeon_cp_clear( struct inode *inode, struct file *filp,
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_radeon_clear_t clear;
+       drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
 
-       if ( copy_from_user( &clear, (drm_radeon_clear_t *) arg,
+       if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg,
                             sizeof(clear) ) )
                return -EFAULT;
 
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
        if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
                sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-       radeon_cp_dispatch_clear( dev, &clear );
+       if ( copy_from_user( &depth_boxes, clear.depth_boxes,
+                            sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
+               return -EFAULT;
+
+       radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
 
        return 0;
 }
@@ -1147,11 +1196,9 @@ int radeon_cp_swap( struct inode *inode, struct file *filp,
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
+
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
        if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
                sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
@@ -1178,13 +1225,10 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
        drm_radeon_buf_priv_t *buf_priv;
        drm_radeon_vertex_t vertex;
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
-       if ( !dev_priv || dev_priv->is_pci ) {
-               DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+       LOCK_TEST_WITH_RETURN( dev );
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
                return -EINVAL;
        }
 
@@ -1207,7 +1251,8 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       VB_AGE_CHECK_WITH_RET( dev_priv );
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
 
        buf = dma->buflist[vertex.idx];
        buf_priv = buf->dev_private;
@@ -1243,13 +1288,10 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
        drm_radeon_indices_t elts;
        int count;
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
-       if ( !dev_priv || dev_priv->is_pci ) {
-               DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+       LOCK_TEST_WITH_RETURN( dev );
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
                return -EINVAL;
        }
 
@@ -1272,7 +1314,8 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       VB_AGE_CHECK_WITH_RET( dev_priv );
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
 
        buf = dma->buflist[elts.idx];
        buf_priv = buf->dev_private;
@@ -1308,37 +1351,34 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
        return 0;
 }
 
-int radeon_cp_blit( struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg )
+int radeon_cp_texture( 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_radeon_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_radeon_blit_t blit;
+       drm_radeon_texture_t tex;
+       drm_radeon_tex_image_t image;
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
 
-       if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg,
-                            sizeof(blit) ) )
+       if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) )
                return -EFAULT;
 
-       DRM_DEBUG( "%s: pid=%d index=%d\n",
-                  __FUNCTION__, current->pid, blit.idx );
-
-       if ( blit.idx < 0 || blit.idx > dma->buf_count ) {
-               DRM_ERROR( "sending %d buffers (of %d max)\n",
-                          blit.idx, dma->buf_count );
+       if ( tex.image == NULL ) {
+               DRM_ERROR( "null texture image!\n" );
                return -EINVAL;
        }
 
-       VB_AGE_CHECK_WITH_RET( dev_priv );
+       if ( copy_from_user( &image,
+                            (drm_radeon_tex_image_t *)tex.image,
+                            sizeof(image) ) )
+               return -EFAULT;
+
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
 
-       return radeon_cp_dispatch_blit( dev, &blit );
+       return radeon_cp_dispatch_texture( dev, &tex, &image );
 }
 
 int radeon_cp_stipple( struct inode *inode, struct file *filp,
@@ -1346,23 +1386,21 @@ int radeon_cp_stipple( struct inode *inode, struct file *filp,
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_stipple_t stipple;
        u32 mask[32];
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
+       LOCK_TEST_WITH_RETURN( dev );
 
        if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
                             sizeof(stipple) ) )
                return -EFAULT;
 
-       if ( copy_from_user( &mask, stipple.mask,
-                            32 * sizeof(u32) ) )
+       if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) )
                return -EFAULT;
 
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
        radeon_cp_dispatch_stipple( dev, mask );
 
        return 0;
@@ -1380,13 +1418,10 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
        drm_radeon_indirect_t indirect;
        RING_LOCALS;
 
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-            dev->lock.pid != current->pid ) {
-               DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );
-               return -EINVAL;
-       }
-       if ( !dev_priv || dev_priv->is_pci ) {
-               DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+       LOCK_TEST_WITH_RETURN( dev );
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
                return -EINVAL;
        }
 
@@ -1423,7 +1458,8 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       VB_AGE_CHECK_WITH_RET( dev_priv );
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
 
        buf->used = indirect.end;
        buf_priv->discard = indirect.discard;
index f1abaab..3def97f 100644 (file)
@@ -126,10 +126,11 @@ typedef struct drm_control {
 } drm_control_t;
 
 typedef enum drm_map_type {
-       _DRM_FRAME_BUFFER = 0,    /* WC (no caching), no core dump          */
-       _DRM_REGISTERS    = 1,    /* no caching, no core dump               */
-       _DRM_SHM          = 2,    /* shared, cached                         */
-       _DRM_AGP          = 3     /* AGP/GART                               */
+       _DRM_FRAME_BUFFER   = 0,  /* WC (no caching), no core dump          */
+       _DRM_REGISTERS      = 1,  /* no caching, no core dump               */
+       _DRM_SHM            = 2,  /* shared, cached                         */
+       _DRM_AGP            = 3,  /* AGP/GART                               */
+       _DRM_SCATTER_GATHER = 4   /* Scatter/gather memory for PCI DMA      */
 } drm_map_type_t;
 
 typedef enum drm_map_flags {
@@ -238,7 +239,8 @@ typedef struct drm_buf_desc {
        int           high_mark; /* High water mark                          */
        enum {
                _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA  */
-               _DRM_AGP_BUFFER = 0x02  /* Buffer is in agp space            */
+               _DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space            */
+               _DRM_SG_BUFFER  = 0x04  /* Scatter/gather memory buffer      */
        }             flags;
        unsigned long agp_start; /* Start address of where the agp buffers
                                  * are in the agp aperture */
@@ -344,6 +346,11 @@ typedef struct drm_agp_info {
        unsigned short id_device;
 } drm_agp_info_t;
 
+typedef struct drm_scatter_gather {
+       unsigned long size;     /* In bytes -- will round to page boundary */
+       unsigned long handle;   /* Used for mapping / unmapping */
+} drm_scatter_gather_t;
+
 #define DRM_IOCTL_BASE                 'd'
 #define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
 #define DRM_IOR(nr,size)               _IOR(DRM_IOCTL_BASE,nr,size)
@@ -399,6 +406,9 @@ typedef struct drm_agp_info {
 #define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, drm_agp_binding_t)
 #define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, drm_agp_binding_t)
 
+#define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, drm_scatter_gather_t)
+
 /* MGA specific ioctls */
 #define DRM_IOCTL_MGA_INIT             DRM_IOW( 0x40, drm_mga_init_t)
 #define DRM_IOCTL_MGA_FLUSH            DRM_IOW( 0x41, drm_lock_t)
index f1abaab..3def97f 100644 (file)
@@ -126,10 +126,11 @@ typedef struct drm_control {
 } drm_control_t;
 
 typedef enum drm_map_type {
-       _DRM_FRAME_BUFFER = 0,    /* WC (no caching), no core dump          */
-       _DRM_REGISTERS    = 1,    /* no caching, no core dump               */
-       _DRM_SHM          = 2,    /* shared, cached                         */
-       _DRM_AGP          = 3     /* AGP/GART                               */
+       _DRM_FRAME_BUFFER   = 0,  /* WC (no caching), no core dump          */
+       _DRM_REGISTERS      = 1,  /* no caching, no core dump               */
+       _DRM_SHM            = 2,  /* shared, cached                         */
+       _DRM_AGP            = 3,  /* AGP/GART                               */
+       _DRM_SCATTER_GATHER = 4   /* Scatter/gather memory for PCI DMA      */
 } drm_map_type_t;
 
 typedef enum drm_map_flags {
@@ -238,7 +239,8 @@ typedef struct drm_buf_desc {
        int           high_mark; /* High water mark                          */
        enum {
                _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA  */
-               _DRM_AGP_BUFFER = 0x02  /* Buffer is in agp space            */
+               _DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space            */
+               _DRM_SG_BUFFER  = 0x04  /* Scatter/gather memory buffer      */
        }             flags;
        unsigned long agp_start; /* Start address of where the agp buffers
                                  * are in the agp aperture */
@@ -344,6 +346,11 @@ typedef struct drm_agp_info {
        unsigned short id_device;
 } drm_agp_info_t;
 
+typedef struct drm_scatter_gather {
+       unsigned long size;     /* In bytes -- will round to page boundary */
+       unsigned long handle;   /* Used for mapping / unmapping */
+} drm_scatter_gather_t;
+
 #define DRM_IOCTL_BASE                 'd'
 #define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
 #define DRM_IOR(nr,size)               _IOR(DRM_IOCTL_BASE,nr,size)
@@ -399,6 +406,9 @@ typedef struct drm_agp_info {
 #define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, drm_agp_binding_t)
 #define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, drm_agp_binding_t)
 
+#define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, drm_scatter_gather_t)
+
 /* MGA specific ioctls */
 #define DRM_IOCTL_MGA_INIT             DRM_IOW( 0x40, drm_mga_init_t)
 #define DRM_IOCTL_MGA_FLUSH            DRM_IOW( 0x41, drm_lock_t)