OSDN Git Service

Import of XFree86 4.0.99.3
authorDavid Dawes <dawes@xfree86.org>
Tue, 1 May 2001 17:07:59 +0000 (17:07 +0000)
committerDavid Dawes <dawes@xfree86.org>
Tue, 1 May 2001 17:07:59 +0000 (17:07 +0000)
16 files changed:
linux-core/drm_agpsupport.c
linux-core/drm_bufs.c
linux-core/drm_fops.c
linux-core/drm_init.c
linux-core/drm_ioctl.c
linux-core/drm_memory.h
linux-core/drm_vm.c
linux/drm_agpsupport.h
linux/drm_bufs.h
linux/drm_fops.h
linux/drm_init.h
linux/drm_ioctl.h
linux/drm_memory.h
linux/drm_vm.h
linux/r128.h
linux/radeon.h

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 63cfb0d..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 ) {
@@ -768,18 +946,34 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
                                goto done;
                        }
 
+#if LINUX_VERSION_CODE <= 0x020402
                        down( &current->mm->mmap_sem );
+#else
+                       down_write( &current->mm->mmap_sem );
+#endif
                        virtual = do_mmap( filp, 0, map->size,
                                           PROT_READ | PROT_WRITE,
                                           MAP_SHARED,
                                           (unsigned long)map->offset );
+#if LINUX_VERSION_CODE <= 0x020402
                        up( &current->mm->mmap_sem );
+#else
+                       up_write( &current->mm->mmap_sem );
+#endif
                } else {
+#if LINUX_VERSION_CODE <= 0x020402
                        down( &current->mm->mmap_sem );
+#else
+                       down_write( &current->mm->mmap_sem );
+#endif
                        virtual = do_mmap( filp, 0, dma->byte_count,
                                           PROT_READ | PROT_WRITE,
                                           MAP_SHARED, 0 );
+#if LINUX_VERSION_CODE <= 0x020402
                        up( &current->mm->mmap_sem );
+#else
+                       up_write( &current->mm->mmap_sem );
+#endif
                }
                if ( virtual > -1024UL ) {
                        /* Real error */
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"},
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 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 63cfb0d..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 ) {
@@ -768,18 +946,34 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
                                goto done;
                        }
 
+#if LINUX_VERSION_CODE <= 0x020402
                        down( &current->mm->mmap_sem );
+#else
+                       down_write( &current->mm->mmap_sem );
+#endif
                        virtual = do_mmap( filp, 0, map->size,
                                           PROT_READ | PROT_WRITE,
                                           MAP_SHARED,
                                           (unsigned long)map->offset );
+#if LINUX_VERSION_CODE <= 0x020402
                        up( &current->mm->mmap_sem );
+#else
+                       up_write( &current->mm->mmap_sem );
+#endif
                } else {
+#if LINUX_VERSION_CODE <= 0x020402
                        down( &current->mm->mmap_sem );
+#else
+                       down_write( &current->mm->mmap_sem );
+#endif
                        virtual = do_mmap( filp, 0, dma->byte_count,
                                           PROT_READ | PROT_WRITE,
                                           MAP_SHARED, 0 );
+#if LINUX_VERSION_CODE <= 0x020402
                        up( &current->mm->mmap_sem );
+#else
+                       up_write( &current->mm->mmap_sem );
+#endif
                }
                if ( virtual > -1024UL ) {
                        /* Real error */
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"},
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 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 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:
  */