]> git.neil.brown.name Git - history.git/commitdiff
Merge DRI CVS tree into standard kernel
authorLinus Torvalds <torvalds@home.transmeta.com>
Fri, 24 May 2002 03:48:57 +0000 (20:48 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Fri, 24 May 2002 03:48:57 +0000 (20:48 -0700)
46 files changed:
drivers/char/drm/Config.in
drivers/char/drm/Makefile
drivers/char/drm/drm.h
drivers/char/drm/drmP.h
drivers/char/drm/drm_agpsupport.h
drivers/char/drm/drm_auth.h
drivers/char/drm/drm_bufs.h
drivers/char/drm/drm_context.h
drivers/char/drm/drm_dma.h
drivers/char/drm/drm_drv.h
drivers/char/drm/drm_fops.h
drivers/char/drm/drm_lists.h
drivers/char/drm/drm_memory.h
drivers/char/drm/drm_scatter.h
drivers/char/drm/drm_stub.h
drivers/char/drm/drm_vm.h
drivers/char/drm/gamma.h
drivers/char/drm/gamma_dma.c
drivers/char/drm/gamma_drm.h [new file with mode: 0644]
drivers/char/drm/gamma_drv.c
drivers/char/drm/gamma_drv.h
drivers/char/drm/i810.h
drivers/char/drm/i810_dma.c
drivers/char/drm/i810_drm.h
drivers/char/drm/i810_drv.c
drivers/char/drm/i810_drv.h
drivers/char/drm/i830.h [new file with mode: 0644]
drivers/char/drm/i830_dma.c [new file with mode: 0644]
drivers/char/drm/i830_drm.h [new file with mode: 0644]
drivers/char/drm/i830_drv.c [new file with mode: 0644]
drivers/char/drm/i830_drv.h [new file with mode: 0644]
drivers/char/drm/mga_state.c
drivers/char/drm/r128_drv.c
drivers/char/drm/r128_state.c
drivers/char/drm/radeon_cp.c
drivers/char/drm/radeon_drm.h
drivers/char/drm/radeon_drv.c
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_state.c
drivers/char/drm/sis.h [new file with mode: 0644]
drivers/char/drm/sis_drm.h [new file with mode: 0644]
drivers/char/drm/sis_drv.c [new file with mode: 0644]
drivers/char/drm/sis_drv.h [new file with mode: 0644]
drivers/char/drm/sis_ds.c [new file with mode: 0644]
drivers/char/drm/sis_ds.h [new file with mode: 0644]
drivers/char/drm/sis_mm.c [new file with mode: 0644]

index 4936c6b3f0e59cfafeab02615bc4c5bbab61e212..5cc13e84d9ca742e1d4715a9dfa0d0304052471e 100644 (file)
@@ -1,5 +1,5 @@
 #
-# drm device configuration
+# Drm device configuration
 #
 # This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
@@ -12,5 +12,6 @@ if [ "$CONFIG_DRM" != "n" ]; then
     tristate '  ATI Rage 128' CONFIG_DRM_R128
     dep_tristate '  ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
     dep_tristate '  Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
+    dep_tristate '  Intel 830M' CONFIG_DRM_I830 $CONFIG_AGP
     dep_tristate '  Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
 fi
index a0ffc1152fe0aa57996c359937cbae3549c646bd..5b000a45ca7107e6043450d87bcd0f35b776d9e9 100644 (file)
@@ -9,6 +9,7 @@ tdfx-objs   := tdfx_drv.o
 r128-objs   := r128_drv.o r128_cce.o r128_state.o
 mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o
 i810-objs   := i810_drv.o i810_dma.o
+i830-objs   := i830_drv.o i830_dma.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o
 ffb-objs    := ffb_drv.o ffb_context.o
 
@@ -18,6 +19,7 @@ obj-$(CONFIG_DRM_R128)        += r128.o
 obj-$(CONFIG_DRM_RADEON)+= radeon.o
 obj-$(CONFIG_DRM_MGA)  += mga.o
 obj-$(CONFIG_DRM_I810) += i810.o
+obj-$(CONFIG_DRM_I830) += i830.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
 
 include $(TOPDIR)/Rules.make
index ac9f407a7e25843ffb878c4b3e7987c82b9e6aaf..c6316a0a97926172b692e70d982d982cc02b6454 100644 (file)
@@ -104,9 +104,9 @@ typedef struct drm_tex_region {
 #include "i810_drm.h"
 #include "r128_drm.h"
 #include "radeon_drm.h"
-#ifdef CONFIG_DRM_SIS
 #include "sis_drm.h"
-#endif
+#include "i830_drm.h"
+#include "gamma_drm.h"
 
 typedef struct drm_version {
        int    version_major;     /* Major version                          */
@@ -449,6 +449,12 @@ typedef struct drm_scatter_gather {
 #define DRM_IOCTL_I810_SWAP            DRM_IO(  0x46)
 #define DRM_IOCTL_I810_COPY            DRM_IOW( 0x47, drm_i810_copy_t)
 #define DRM_IOCTL_I810_DOCOPY          DRM_IO(  0x48)
+#define DRM_IOCTL_I810_OV0INFO         DRM_IOR( 0x49, drm_i810_overlay_t)
+#define DRM_IOCTL_I810_FSTATUS         DRM_IO ( 0x4a)
+#define DRM_IOCTL_I810_OV0FLIP         DRM_IO ( 0x4b)
+#define DRM_IOCTL_I810_MC              DRM_IOW( 0x4c, drm_i810_mc_t)
+#define DRM_IOCTL_I810_RSTATUS         DRM_IO ( 0x4d )
+
 
 /* Rage 128 specific ioctls */
 #define DRM_IOCTL_R128_INIT            DRM_IOW( 0x40, drm_r128_init_t)
@@ -466,6 +472,7 @@ typedef struct drm_scatter_gather {
 #define DRM_IOCTL_R128_STIPPLE         DRM_IOW( 0x4d, drm_r128_stipple_t)
 #define DRM_IOCTL_R128_INDIRECT                DRM_IOWR(0x4f, drm_r128_indirect_t)
 #define DRM_IOCTL_R128_FULLSCREEN      DRM_IOW( 0x50, drm_r128_fullscreen_t)
+#define DRM_IOCTL_R128_CLEAR2          DRM_IOW( 0x51, drm_r128_clear2_t)
 
 /* Radeon specific ioctls */
 #define DRM_IOCTL_RADEON_CP_INIT       DRM_IOW( 0x40, drm_radeon_init_t)
@@ -482,8 +489,15 @@ typedef struct drm_scatter_gather {
 #define DRM_IOCTL_RADEON_STIPPLE       DRM_IOW( 0x4c, drm_radeon_stipple_t)
 #define DRM_IOCTL_RADEON_INDIRECT      DRM_IOWR(0x4d, drm_radeon_indirect_t)
 #define DRM_IOCTL_RADEON_TEXTURE       DRM_IOWR(0x4e, drm_radeon_texture_t)
+#define DRM_IOCTL_RADEON_VERTEX2       DRM_IOW( 0x4f, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_CMDBUF        DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
+#define DRM_IOCTL_RADEON_GETPARAM      DRM_IOWR(0x51, drm_radeon_getparam_t)
+#define DRM_IOCTL_RADEON_FLIP          DRM_IO(  0x52)
+
+/* Gamma specific ioctls */
+#define DRM_IOCTL_GAMMA_INIT           DRM_IOW( 0x40, drm_gamma_init_t)
+#define DRM_IOCTL_GAMMA_COPY           DRM_IOW( 0x41, drm_gamma_copy_t)
 
-#ifdef CONFIG_DRM_SIS
 /* SiS specific ioctls */
 #define SIS_IOCTL_FB_ALLOC             DRM_IOWR(0x44, drm_sis_mem_t)
 #define SIS_IOCTL_FB_FREE              DRM_IOW( 0x45, drm_sis_mem_t)
@@ -493,6 +507,16 @@ typedef struct drm_scatter_gather {
 #define SIS_IOCTL_FLIP                 DRM_IOW( 0x48, drm_sis_flip_t)
 #define SIS_IOCTL_FLIP_INIT            DRM_IO(  0x49)
 #define SIS_IOCTL_FLIP_FINAL           DRM_IO(  0x50)
-#endif
+
+/* I830 specific ioctls */
+#define DRM_IOCTL_I830_INIT            DRM_IOW( 0x40, drm_i830_init_t)
+#define DRM_IOCTL_I830_VERTEX          DRM_IOW( 0x41, drm_i830_vertex_t)
+#define DRM_IOCTL_I830_CLEAR           DRM_IOW( 0x42, drm_i830_clear_t)
+#define DRM_IOCTL_I830_FLUSH           DRM_IO ( 0x43)
+#define DRM_IOCTL_I830_GETAGE          DRM_IO ( 0x44)
+#define DRM_IOCTL_I830_GETBUF          DRM_IOWR(0x45, drm_i830_dma_t)
+#define DRM_IOCTL_I830_SWAP            DRM_IO ( 0x46)
+#define DRM_IOCTL_I830_COPY            DRM_IOW( 0x47, drm_i830_copy_t)
+#define DRM_IOCTL_I830_DOCOPY          DRM_IO ( 0x48)
 
 #endif
index 780942105b040eb5d617f12c2fdb6d4f85b76261..6f9665f1b161641bf103b6e3e51da775ffea80e2 100644 (file)
 #include <linux/types.h>
 #include <linux/agp_backend.h>
 #endif
-#if LINUX_VERSION_CODE >= 0x020100 /* KERNEL_VERSION(2,1,0) */
 #include <linux/tqueue.h>
 #include <linux/poll.h>
-#endif
-#if LINUX_VERSION_CODE < 0x020400
-#include "compat-pre24.h"
-#endif
 #include <asm/pgalloc.h>
 #include "drm.h"
 
-/* page_to_bus for earlier kernels, not optimal in all cases */
-#ifndef page_to_bus
-#define page_to_bus(page)      ((unsigned int)(virt_to_bus(page_address(page))))
-#endif
-
-/* We just use virt_to_bus for pci_map_single on older kernels */
-#if LINUX_VERSION_CODE < 0x020400
-#define pci_map_single(hwdev, ptr, size, direction)    virt_to_bus(ptr)
-#define pci_unmap_single(hwdev, dma_addr, size, direction)
-#endif
-
 /* DRM template customization defaults
  */
 #ifndef __HAVE_AGP
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
                                /* Backward compatibility section */
-                               /* _PAGE_WT changed to _PAGE_PWT in 2.2.6 */
-#ifndef _PAGE_PWT
-#define _PAGE_PWT _PAGE_WT
-#endif
-                               /* Wait queue declarations changed in 2.3.1 */
-#ifndef DECLARE_WAITQUEUE
-#define DECLARE_WAITQUEUE(w,c) struct wait_queue w = { c, NULL }
-typedef struct wait_queue *wait_queue_head_t;
-#define init_waitqueue_head(q) *q = NULL;
-#endif
-
-                               /* _PAGE_4M changed to _PAGE_PSE in 2.3.23 */
-#ifndef _PAGE_PSE
-#define _PAGE_PSE _PAGE_4M
+#ifndef minor
+#define minor(x) MINOR((x))
 #endif
 
-                               /* vm_offset changed to vm_pgoff in 2.3.25 */
-#if LINUX_VERSION_CODE < 0x020319
-#define VM_OFFSET(vma) ((vma)->vm_offset)
-#else
-#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(x) 
 #endif
 
-                               /* *_nopage return values defined in 2.3.26 */
-#ifndef NOPAGE_SIGBUS
-#define NOPAGE_SIGBUS 0
-#endif
-#ifndef NOPAGE_OOM
-#define NOPAGE_OOM 0
+#ifndef preempt_disable
+#define preempt_disable()
+#define preempt_enable()
 #endif
 
-                               /* module_init/module_exit added in 2.3.13 */
-#ifndef module_init
-#define module_init(x)  int init_module(void) { return x(); }
-#endif
-#ifndef module_exit
-#define module_exit(x)  void cleanup_module(void) { x(); }
+#ifndef pte_offset_map 
+#define pte_offset_map pte_offset
+#define pte_unmap(pte)
 #endif
 
-                               /* Generic cmpxchg added in 2.3.x */
-#ifndef __HAVE_ARCH_CMPXCHG
-                               /* Include this here so that driver can be
-                                   used with older kernels. */
-#if defined(__alpha__)
-static __inline__ unsigned long
-__cmpxchg_u32(volatile int *m, int old, int new)
+#if LINUX_VERSION_CODE < 0x020500
+static inline struct page * vmalloc_to_page(void * vmalloc_addr)
 {
-       unsigned long prev, cmp;
-
-       __asm__ __volatile__(
-       "1:     ldl_l %0,%5\n"
-       "       cmpeq %0,%3,%1\n"
-       "       beq %1,2f\n"
-       "       mov %4,%1\n"
-       "       stl_c %1,%2\n"
-       "       beq %1,3f\n"
-       "2:     mb\n"
-       ".subsection 2\n"
-       "3:     br 1b\n"
-       ".previous"
-       : "=&r"(prev), "=&r"(cmp), "=m"(*m)
-       : "r"((long) old), "r"(new), "m"(*m)
-       : "memory" );
-
-       return prev;
-}
-
-static __inline__ unsigned long
-__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
-{
-       unsigned long prev, cmp;
-
-       __asm__ __volatile__(
-       "1:     ldq_l %0,%5\n"
-       "       cmpeq %0,%3,%1\n"
-       "       beq %1,2f\n"
-       "       mov %4,%1\n"
-       "       stq_c %1,%2\n"
-       "       beq %1,3f\n"
-       "2:     mb\n"
-       ".subsection 2\n"
-       "3:     br 1b\n"
-       ".previous"
-       : "=&r"(prev), "=&r"(cmp), "=m"(*m)
-       : "r"((long) old), "r"(new), "m"(*m)
-       : "memory" );
-
-       return prev;
-}
-
-static __inline__ unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-       switch (size) {
-               case 4:
-                       return __cmpxchg_u32(ptr, old, new);
-               case 8:
-                       return __cmpxchg_u64(ptr, old, new);
+       unsigned long addr = (unsigned long) vmalloc_addr;
+       struct page *page = NULL;
+       pgd_t *pgd = pgd_offset_k(addr);
+       pmd_t *pmd;
+       pte_t *ptep, pte;
+  
+       if (!pgd_none(*pgd)) {
+               pmd = pmd_offset(pgd, addr);
+               if (!pmd_none(*pmd)) {
+                       preempt_disable();
+                       ptep = pte_offset_map(pmd, addr);
+                       pte = *ptep;
+                       if (pte_present(pte))
+                               page = pte_page(pte);
+                       pte_unmap(ptep);
+                       preempt_enable();
+               }
        }
-       return old;
+       return page;
 }
-#define cmpxchg(ptr,o,n)                                                \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-#elif __i386__
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-                                     unsigned long new, int size)
-{
-       unsigned long prev;
-       switch (size) {
-       case 1:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-                                    : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 2:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-                                    : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       case 4:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-                                    : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
-                                    : "memory");
-               return prev;
-       }
-       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 */
+#endif
 
-#ifndef __alpha__
-#define cmpxchg(ptr,o,n)                                               \
-  ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),             \
-                                (unsigned long)(n),sizeof(*(ptr))))
+#if LINUX_VERSION_CODE < 0x020500
+#define DRM_RPR_ARG(vma)
+#else
+#define DRM_RPR_ARG(vma) vma,
 #endif
 
-#endif /* !__HAVE_ARCH_CMPXCHG */
+
+#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
 
                                /* Macros to make printk easier */
 #define DRM_ERROR(fmt, arg...) \
@@ -369,6 +231,9 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 #define DRM_IOREMAP(map)                                               \
        (map)->handle = DRM(ioremap)( (map)->offset, (map)->size )
 
+#define DRM_IOREMAP_NOCACHE(map)                                       \
+       (map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size)
+
 #define DRM_IOREMAPFREE(map)                                           \
        do {                                                            \
                if ( (map)->handle && (map)->size )                     \
@@ -778,34 +643,18 @@ extern unsigned int  DRM(poll)(struct file *filp,
                               struct poll_table_struct *wait);
 
                                /* Mapping support (drm_vm.h) */
-#if LINUX_VERSION_CODE < 0x020317
-extern unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
-                                   unsigned long address,
-                                   int unused);
-extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-                                       unsigned long address,
-                                       int unused);
-extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-                                       unsigned long address,
-                                       int unused);
-extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-                                      unsigned long address,
-                                      int unused);
-#else
-                               /* Return type changed in 2.3.23 */
 extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
                                   unsigned long address,
-                                  int unused);
+                                  int write_access);
 extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
                                       unsigned long address,
-                                      int unused);
+                                      int write_access);
 extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
                                       unsigned long address,
-                                      int unused);
+                                      int write_access);
 extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
                                      unsigned long address,
-                                     int unused);
-#endif
+                                     int write_access);
 extern void         DRM(vm_open)(struct vm_area_struct *vma);
 extern void         DRM(vm_close)(struct vm_area_struct *vma);
 extern void         DRM(vm_shm_close)(struct vm_area_struct *vma);
@@ -827,6 +676,7 @@ extern unsigned long DRM(alloc_pages)(int order, int area);
 extern void         DRM(free_pages)(unsigned long address, int order,
                                     int area);
 extern void         *DRM(ioremap)(unsigned long offset, unsigned long size);
+extern void         *DRM(ioremap_nocache)(unsigned long offset, unsigned long size);
 extern void         DRM(ioremapfree)(void *pt, unsigned long size);
 
 #if __REALLY_HAVE_AGP
index 2751a5175fa460f6b1002f89f528daeebb6f2729..363c3a54add42b657a3e8f546a3823223200eef6 100644 (file)
 
 #if __REALLY_HAVE_AGP
 
-#if LINUX_VERSION_CODE < 0x020400
-#include "agpsupport-pre24.h"
-#else
 #define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
 #define DRM_AGP_PUT inter_module_put("drm_agp")
-#endif
 
 static const drm_agp_t *drm_agp = NULL;
 
@@ -271,24 +267,24 @@ drm_agp_head_t *DRM(agp_init)(void)
                case INTEL_GX:          head->chipset = "Intel 440GX";   break;
                case INTEL_I810:        head->chipset = "Intel i810";    break;
 
-#if LINUX_VERSION_CODE >= 0x020400
                case INTEL_I815:        head->chipset = "Intel i815";    break;
+#if LINUX_VERSION_CODE >= 0x020415
                case INTEL_I820:        head->chipset = "Intel i820";    break;
+#endif
                case INTEL_I840:        head->chipset = "Intel i840";    break;
+#if LINUX_VERSION_CODE >= 0x020415
                case INTEL_I845:        head->chipset = "Intel i845";    break;
-               case INTEL_I850:        head->chipset = "Intel i850";    break;
 #endif
+               case INTEL_I850:        head->chipset = "Intel i850";    break;
 
                case VIA_GENERIC:       head->chipset = "VIA";           break;
                case VIA_VP3:           head->chipset = "VIA VP3";       break;
                case VIA_MVP3:          head->chipset = "VIA MVP3";      break;
-#if LINUX_VERSION_CODE >= 0x020400
                case VIA_MVP4:          head->chipset = "VIA MVP4";      break;
                case VIA_APOLLO_KX133:  head->chipset = "VIA Apollo KX133";
                        break;
                case VIA_APOLLO_KT133:  head->chipset = "VIA Apollo KT133";
                        break;
-#endif
 
                case VIA_APOLLO_PRO:    head->chipset = "VIA Apollo Pro";
                        break;
index 2636e617996c61ae97fc0d59ab5ddc3f105a9cea..8fce6dfcac4ed87b691d492041ea90102f666fb6 100644 (file)
@@ -64,6 +64,7 @@ int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
        hash         = DRM(hash_magic)(magic);
        entry        = DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC);
        if (!entry) return -ENOMEM;
+       memset(entry, 0, sizeof(*entry));
        entry->magic = magic;
        entry->priv  = priv;
        entry->next  = NULL;
index ec5dd543a96e0c5dbb3dd25d039fbd8c52a66835..3ff3527f61720c7b3f802ce7915a3bb7f34bbe36 100644 (file)
@@ -229,11 +229,7 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
        DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
 
        for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
-#if LINUX_VERSION_CODE >= 0x020300
                if (pt->vma->vm_private_data == map) found_maps++;
-#else
-               if (pt->vma->vm_pte == map) found_maps++;
-#endif
        }
 
        if(!found_maps) {
index 33d6112e33e4771b0a41bf08ab3d953af114e2b4..e155946dcf765607093acca2cefbcd170dea1dd2 100644 (file)
  * Authors:
  *    Rickard E. (Rik) Faith <faith@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
+ * ChangeLog:
+ *  2001-11-16 Torsten Duwe <duwe@caldera.de>
+ *             added context constructor/destructor hooks,
+ *             needed by SiS driver's memory management.
  */
 
 #define __NO_VERSION__
@@ -316,6 +320,10 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
                                /* Should this return -EBUSY instead? */
                return -ENOMEM;
        }
+#ifdef DRIVER_CTX_CTOR
+       if ( ctx.handle != DRM_KERNEL_CONTEXT )
+               DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
+#endif
 
        if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
                return -EFAULT;
@@ -390,6 +398,9 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
                priv->remove_auth_on_close = 1;
        }
        if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
+#ifdef DRIVER_CTX_DTOR
+               DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */
+#endif
                DRM(ctxbitmap_free)( dev, ctx.handle );
        }
 
index 85fa147231ee0caa339348a268b60f809a57eed7..dce376f6cad29bd3275b7eeb53a9a7120d032a3d 100644 (file)
@@ -598,6 +598,25 @@ int DRM(control)( struct inode *inode, struct file *filp,
        }
 }
 
+#else
+
+int DRM(control)( struct inode *inode, struct file *filp,
+                 unsigned int cmd, unsigned long arg )
+{
+       drm_control_t ctl;
+
+       if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
+               return -EFAULT;
+
+       switch ( ctl.func ) {
+       case DRM_INST_HANDLER:
+       case DRM_UNINST_HANDLER:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
 #endif /* __HAVE_DMA_IRQ */
 
 #endif /* __HAVE_DMA */
index c7a9a45adf729765d58e43c4591dc1b6fcc6f2d5..b124c4225f67a254227af8384eda5b485d306421 100644 (file)
 #define DRIVER_IOCTLS
 #endif
 #ifndef DRIVER_FOPS
-#if LINUX_VERSION_CODE >= 0x020400
 #define DRIVER_FOPS                            \
 static struct file_operations  DRM(fops) = {   \
        owner:   THIS_MODULE,                   \
@@ -126,19 +125,6 @@ static struct file_operations      DRM(fops) = {   \
        fasync:  DRM(fasync),                   \
        poll:    DRM(poll),                     \
 }
-#else
-#define DRIVER_FOPS                            \
-static struct file_operations  DRM(fops) = {   \
-       open:    DRM(open),                     \
-       flush:   DRM(flush),                    \
-       release: DRM(release),                  \
-       ioctl:   DRM(ioctl),                    \
-       mmap:    DRM(mmap),                     \
-       read:    DRM(read),                     \
-       fasync:  DRM(fasync),                   \
-       poll:    DRM(poll),                     \
-}
-#endif
 #endif
 
 
@@ -201,10 +187,8 @@ static drm_ioctl_desc_t              DRM(ioctls)[] = {
 
        /* The DRM_IOCTL_DMA ioctl should be defined by the driver.
         */
-#if __HAVE_DMA_IRQ
        [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
 #endif
-#endif
 
 #if __REALLY_HAVE_AGP
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { DRM(agp_acquire), 1, 1 },
@@ -732,9 +716,6 @@ int DRM(open)( struct inode *inode, struct file *filp )
 
        retcode = DRM(open_helper)( inode, filp, dev );
        if ( !retcode ) {
-#if LINUX_VERSION_CODE < 0x020333
-               MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
                atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
                spin_lock( &dev->count_lock );
                if ( !dev->open_count++ ) {
@@ -853,9 +834,6 @@ int DRM(release)( struct inode *inode, struct file *filp )
         * End inline drm_release
         */
 
-#if LINUX_VERSION_CODE < 0x020333
-       MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
        atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
        spin_lock( &dev->count_lock );
        if ( !--dev->open_count ) {
index ec88ad27eb6cd4c60e3d168bd286fa3a0822503c..3d4bffa524c82ab43c910bf5b0e57f8616a5dc38 100644 (file)
@@ -191,24 +191,8 @@ int DRM(write_string)(drm_device_t *dev, const char *s)
                send -= count;
        }
 
-#if LINUX_VERSION_CODE < 0x020315 && !defined(KILLFASYNCHASTHREEPARAMETERS)
-       /* The extra parameter to kill_fasync was added in 2.3.21, and is
-           _not_ present in _stock_ 2.2.14 and 2.2.15.  However, some
-           distributions patch 2.2.x kernels to add this parameter.  The
-           Makefile.linux attempts to detect this addition and defines
-           KILLFASYNCHASTHREEPARAMETERS if three parameters are found. */
-       if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO);
-#else
-
-                               /* Parameter added in 2.3.21. */
-#if LINUX_VERSION_CODE < 0x020400
-       if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN);
-#else
-                               /* Type of first parameter changed in
-                                   Linux 2.4.0-test2... */
        if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
-#endif
-#endif
+
        DRM_DEBUG("waking\n");
        wake_up_interruptible(&dev->buf_readers);
        return 0;
index 3ad487fdaae48c1f1edfd1cbf403d0c6462b6be5..5cd8cd47bcb11fe3c03c7a9447c914f89e4d01fd 100644 (file)
@@ -42,7 +42,7 @@ int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
                                    DRM_MEM_BUFLISTS);
 
        if(!bl->bufs) return -ENOMEM;
-
+       memset(bl->bufs, 0, sizeof(*bl->bufs));
        bl->count      = count;
        bl->rp         = bl->bufs;
        bl->wp         = bl->bufs;
index 498937d4caa3fecfb684c753cd9ba7d2c0f8e0de..22aab7f49b7c29c60cf3183cd37334c572363c38 100644 (file)
@@ -85,12 +85,7 @@ void DRM(mem_init)(void)
        }
 
        si_meminfo(&si);
-#if LINUX_VERSION_CODE < 0x020317
-                               /* Changed to page count in 2.3.23 */
-       DRM(ram_available) = si.totalram >> PAGE_SHIFT;
-#else
        DRM(ram_available) = si.totalram;
-#endif
        DRM(ram_used)      = 0;
 }
 
@@ -257,12 +252,7 @@ unsigned long DRM(alloc_pages)(int order, int area)
        for (addr = address, sz = bytes;
             sz > 0;
             addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-#if LINUX_VERSION_CODE >= 0x020400
-                               /* Argument type changed in 2.4.0-test6/pre8 */
                mem_map_reserve(virt_to_page(addr));
-#else
-               mem_map_reserve(MAP_NR(addr));
-#endif
        }
 
        return address;
@@ -283,12 +273,7 @@ void DRM(free_pages)(unsigned long address, int order, int area)
                for (addr = address, sz = bytes;
                     sz > 0;
                     addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-#if LINUX_VERSION_CODE >= 0x020400
-                               /* Argument type changed in 2.4.0-test6/pre8 */
                        mem_map_unreserve(virt_to_page(addr));
-#else
-                       mem_map_unreserve(MAP_NR(addr));
-#endif
                }
                free_pages(address, order);
        }
@@ -329,6 +314,29 @@ void *DRM(ioremap)(unsigned long offset, unsigned long size)
        return pt;
 }
 
+void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size)
+{
+       void *pt;
+
+       if (!size) {
+               DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+                             "Mapping 0 bytes at 0x%08lx\n", offset);
+               return NULL;
+       }
+
+       if (!(pt = ioremap_nocache(offset, size))) {
+               spin_lock(&DRM(mem_lock));
+               ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
+               spin_unlock(&DRM(mem_lock));
+               return NULL;
+       }
+       spin_lock(&DRM(mem_lock));
+       ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
+       DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
+       spin_unlock(&DRM(mem_lock));
+       return pt;
+}
+
 void DRM(ioremapfree)(void *pt, unsigned long size)
 {
        int alloc_count;
index c151d2b04a4b0c809b89a2467af03020232e3bc8..1aedb4037d9bb6ce8547e2f0efdd698cf49b19a3 100644 (file)
@@ -94,6 +94,8 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
                return -ENOMEM;
        }
 
+       memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
+
        entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr),
                                     DRM_MEM_PAGES );
        if ( !entry->busaddr ) {
index d37a017829bd11076e06fe9869db1c8e86b737bf..b1e7892351fe5ecd1a0d96fe5436e739e0abe98e 100644 (file)
 #define __NO_VERSION__
 #include "drmP.h"
 
-#if LINUX_VERSION_CODE < 0x020400
-#include "stubsupport-pre24.h"
-#endif
-
 #define DRM_STUB_MAXCARDS 16   /* Enough for one machine */
 
 static struct drm_stub_list {
@@ -70,9 +66,7 @@ static int DRM(stub_open)(struct inode *inode, struct file *filp)
 }
 
 static struct file_operations DRM(stub_fops) = {
-#if LINUX_VERSION_CODE >= 0x020400
        owner:   THIS_MODULE,
-#endif
        open:    DRM(stub_open)
 };
 
index 83d13c41503c89ec221f2f167e642f7cb954b112..c07c9affc92ee093f02d0a52e467cdc2bdd6d1cc 100644 (file)
@@ -56,16 +56,9 @@ struct vm_operations_struct   DRM(vm_sg_ops) = {
        close:   DRM(vm_close),
 };
 
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
-                            unsigned long address,
-                            int unused)
-#else
-                               /* Return type changed in 2.3.23 */
 struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
                            unsigned long address,
-                           int unused)
-#endif
+                           int write_access)
 {
 #if __REALLY_HAVE_AGP
        drm_file_t *priv  = vma->vm_file->private_data;
@@ -122,11 +115,7 @@ struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
                DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n",
                          baddr, __va(agpmem->memory->memory[offset]), offset);
 
-#if LINUX_VERSION_CODE < 0x020317
-               return page_address(page);
-#else
                return page;
-#endif
         }
 vm_nopage_error:
 #endif /* __REALLY_HAVE_AGP */
@@ -134,22 +123,11 @@ vm_nopage_error:
        return NOPAGE_SIGBUS;           /* Disallow mremap */
 }
 
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-                                unsigned long address,
-                                int unused)
-#else
-                               /* Return type changed in 2.3.23 */
 struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
                                unsigned long address,
-                               int unused)
-#endif
+                               int write_access)
 {
-#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
        unsigned long    offset;
        unsigned long    i;
        struct page      *page;
@@ -165,11 +143,7 @@ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
        get_page(page);
 
        DRM_DEBUG("shm_nopage 0x%lx\n", address);
-#if LINUX_VERSION_CODE < 0x020317
-       return page_address(page);
-#else
        return page;
-#endif
 }
 
 /* Special close routine which deletes map information if we are the last
@@ -188,25 +162,14 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-#if LINUX_VERSION_CODE < 0x020333
-       MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
        atomic_dec(&dev->vma_count);
 
-#if LINUX_VERSION_CODE >= 0x020300
        map = vma->vm_private_data;
-#else
-       map = vma->vm_pte;
-#endif
 
        down(&dev->struct_sem);
        for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
                next = pt->next;
-#if LINUX_VERSION_CODE >= 0x020300
                if (pt->vma->vm_private_data == map) found_maps++;
-#else
-               if (pt->vma->vm_pte == map) found_maps++;
-#endif
                if (pt->vma == vma) {
                        if (prev) {
                                prev->next = pt->next;
@@ -259,16 +222,9 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
        up(&dev->struct_sem);
 }
 
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-                                unsigned long address,
-                                int unused)
-#else
-                               /* Return type changed in 2.3.23 */
 struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
                                unsigned long address,
-                               int unused)
-#endif
+                               int write_access)
 {
        drm_file_t       *priv   = vma->vm_file->private_data;
        drm_device_t     *dev    = priv->dev;
@@ -288,30 +244,15 @@ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 
        get_page(page);
 
-       DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); 
-#if LINUX_VERSION_CODE < 0x020317
-       return page_address(page);
-#else
+       DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr);
        return page;
-#endif
 }
 
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-                               unsigned long address,
-                               int unused)
-#else
-                               /* Return type changed in 2.3.23 */
 struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
                               unsigned long address,
-                              int unused)
-#endif
+                              int write_access)
 {
-#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;
@@ -331,11 +272,7 @@ struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
        page = entry->pagelist[page_offset];
        get_page(page);
 
-#if LINUX_VERSION_CODE < 0x020317
-       return page_address(page);
-#else
        return page;
-#endif
 }
 
 void DRM(vm_open)(struct vm_area_struct *vma)
@@ -347,10 +284,6 @@ void DRM(vm_open)(struct vm_area_struct *vma)
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
        atomic_inc(&dev->vma_count);
-#if LINUX_VERSION_CODE < 0x020333
-                               /* The map can exist after the fd is closed. */
-       MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
 
        vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS);
        if (vma_entry) {
@@ -371,9 +304,6 @@ void DRM(vm_close)(struct vm_area_struct *vma)
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-#if LINUX_VERSION_CODE < 0x020333
-       MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
        atomic_dec(&dev->vma_count);
 
        down(&dev->struct_sem);
@@ -412,13 +342,13 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
        unlock_kernel();
 
        vma->vm_ops   = &DRM(vm_dma_ops);
-       vma->vm_flags |= VM_RESERVED; /* Don't swap */
 
-#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
-                               /* In Linux 2.2.3 and above, this is
-                                  handled in do_mmap() in mm/mmap.c. */
-       ++filp->f_count;
+#if LINUX_VERSION_CODE <= 0x020414
+       vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+#else
+       vma->vm_flags |= VM_RESERVED; /* Don't swap */
 #endif
+
        vma->vm_file  =  filp;  /* Needed for drm_vm_open() */
        DRM(vm_open)(vma);
        return 0;
@@ -521,12 +451,12 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
                }
                offset = DRIVER_GET_REG_OFS();
 #ifdef __sparc__
-               if (io_remap_page_range(vma, vma->vm_start,
+               if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
                                        VM_OFFSET(vma) + offset,
                                        vma->vm_end - vma->vm_start,
                                        vma->vm_page_prot, 0))
 #else
-               if (remap_page_range(vma, vma->vm_start,
+               if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
                                     VM_OFFSET(vma) + offset,
                                     vma->vm_end - vma->vm_start,
                                     vma->vm_page_prot))
@@ -540,34 +470,33 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
                break;
        case _DRM_SHM:
                vma->vm_ops = &DRM(vm_shm_ops);
-#if LINUX_VERSION_CODE >= 0x020300
                vma->vm_private_data = (void *)map;
-#else
-               vma->vm_pte = (unsigned long)map;
-#endif
                                /* Don't let this area swap.  Change when
                                   DRM_KERNEL advisory is supported. */
+#if LINUX_VERSION_CODE <= 0x020414
+               vma->vm_flags |= VM_LOCKED;
+#else
                vma->vm_flags |= VM_RESERVED;
+#endif
                break;
        case _DRM_SCATTER_GATHER:
                vma->vm_ops = &DRM(vm_sg_ops);
-#if LINUX_VERSION_CODE >= 0x020300
                vma->vm_private_data = (void *)map;
+#if LINUX_VERSION_CODE <= 0x020414
+               vma->vm_flags |= VM_LOCKED;
 #else
-               vma->vm_pte = (unsigned long)map;
+               vma->vm_flags |= VM_RESERVED;
 #endif
-                vma->vm_flags |= VM_RESERVED;
                 break;
        default:
                return -EINVAL; /* This should never happen. */
        }
+#if LINUX_VERSION_CODE <= 0x020414
+       vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+#else
        vma->vm_flags |= VM_RESERVED; /* Don't swap */
-
-#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
-                               /* In Linux 2.2.3 and above, this is
-                                  handled in do_mmap() in mm/mmap.c. */
-       ++filp->f_count;
 #endif
+
        vma->vm_file  =  filp;  /* Needed for drm_vm_open() */
        DRM(vm_open)(vma);
        return 0;
index 232ed018b361704e1e89a060a3070c1ee44a18ab..a38c3c28bfa77c55344ea387c51b0e462f010341 100644 (file)
@@ -41,6 +41,8 @@
 /* DMA customization:
  */
 #define __HAVE_DMA                     1
+#define __HAVE_AGP                     1
+#define __MUST_HAVE_AGP                        0
 #define __HAVE_OLD_DMA                 1
 #define __HAVE_PCI_DMA                 1
 
 #define __HAVE_DMA_QUIESCENT           1
 #define DRIVER_DMA_QUIESCENT() do {                                    \
        /* FIXME ! */                                                   \
-       gamma_dma_quiescent_dual(dev);                                  \
+       gamma_dma_quiescent_single(dev);                                        \
        return 0;                                                       \
 } while (0)
 
 #define __HAVE_DMA_IRQ                 1
 #define __HAVE_DMA_IRQ_BH              1
+
+#if 1
 #define DRIVER_PREINSTALL() do {                                       \
        drm_gamma_private_t *dev_priv =                                 \
                                (drm_gamma_private_t *)dev->dev_private;\
-       GAMMA_WRITE( GAMMA_GCOMMANDMODE,        0x00000000 );           \
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);                       \
+       GAMMA_WRITE( GAMMA_GCOMMANDMODE,        0x00000004 );           \
        GAMMA_WRITE( GAMMA_GDMACONTROL,         0x00000000 );           \
 } while (0)
-
 #define DRIVER_POSTINSTALL() do {                                      \
        drm_gamma_private_t *dev_priv =                                 \
                                (drm_gamma_private_t *)dev->dev_private;\
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);                       \
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);                       \
        GAMMA_WRITE( GAMMA_GINTENABLE,          0x00002001 );           \
        GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000008 );           \
        GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00039090 );           \
 } while (0)
+#else
+#define DRIVER_POSTINSTALL() do {                                      \
+       drm_gamma_private_t *dev_priv =                                 \
+                               (drm_gamma_private_t *)dev->dev_private;\
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);                       \
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);                       \
+       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00002000 );           \
+       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000004 );           \
+} while (0)
+
+#define DRIVER_PREINSTALL() do {                                       \
+       drm_gamma_private_t *dev_priv =                                 \
+                               (drm_gamma_private_t *)dev->dev_private;\
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);                       \
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);                       \
+       GAMMA_WRITE( GAMMA_GCOMMANDMODE,        GAMMA_QUEUED_DMA_MODE );\
+       GAMMA_WRITE( GAMMA_GDMACONTROL,         0x00000000 );\
+} while (0)
+#endif
 
 #define DRIVER_UNINSTALL() do {                                                \
        drm_gamma_private_t *dev_priv =                                 \
                                (drm_gamma_private_t *)dev->dev_private;\
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);                       \
+       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);                       \
        GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00000000 );           \
        GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000000 );           \
        GAMMA_WRITE( GAMMA_GINTENABLE,          0x00000000 );           \
 } while (0)
 
+#define DRIVER_AGP_BUFFERS_MAP( dev )                                  \
+       ((drm_gamma_private_t *)((dev)->dev_private))->buffers
+
 #endif /* __GAMMA_H__ */
index 7510e2b5742b86e22f66f46ada8ee158f8fa97c4..094f51d6574efb4193d57a6c758332cb90b0248d 100644 (file)
 #include <linux/interrupt.h>   /* For task queue support */
 #include <linux/delay.h>
 
-
 static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
                                      unsigned long length)
 {
        drm_gamma_private_t *dev_priv =
-               (drm_gamma_private_t *)dev->dev_private;
-
-       GAMMA_WRITE(GAMMA_DMAADDRESS, virt_to_phys((void *)address));
-       while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
-               ;
+                               (drm_gamma_private_t *)dev->dev_private;
+       mb();
+       while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       GAMMA_WRITE(GAMMA_DMAADDRESS, address);
+       while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4);
        GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
 }
 
 void gamma_dma_quiescent_single(drm_device_t *dev)
 {
        drm_gamma_private_t *dev_priv =
-               (drm_gamma_private_t *)dev->dev_private;
+                               (drm_gamma_private_t *)dev->dev_private;
+       while (GAMMA_READ(GAMMA_DMACOUNT));
 
-       while (GAMMA_READ(GAMMA_DMACOUNT))
-               ;
-       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-               ;
+       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
 
        GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
        GAMMA_WRITE(GAMMA_SYNC, 0);
@@ -72,56 +69,50 @@ void gamma_dma_quiescent_single(drm_device_t *dev)
 void gamma_dma_quiescent_dual(drm_device_t *dev)
 {
        drm_gamma_private_t *dev_priv =
-               (drm_gamma_private_t *)dev->dev_private;
+                               (drm_gamma_private_t *)dev->dev_private;
+       while (GAMMA_READ(GAMMA_DMACOUNT));
 
-       while (GAMMA_READ(GAMMA_DMACOUNT))
-               ;
-       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-               ;
+       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
 
        GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
-
        GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
        GAMMA_WRITE(GAMMA_SYNC, 0);
 
-                               /* Read from first MX */
+       /* Read from first MX */
        do {
-               while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
-                       ;
+               while (!GAMMA_READ(GAMMA_OUTFIFOWORDS));
        } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
 
-                               /* Read from second MX */
+       /* Read from second MX */
        do {
-               while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
-                       ;
+               while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000));
        } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
 }
 
 void gamma_dma_ready(drm_device_t *dev)
 {
        drm_gamma_private_t *dev_priv =
-               (drm_gamma_private_t *)dev->dev_private;
-
-       while (GAMMA_READ(GAMMA_DMACOUNT))
-               ;
+                               (drm_gamma_private_t *)dev->dev_private;
+       while (GAMMA_READ(GAMMA_DMACOUNT));
 }
 
 static inline int gamma_dma_is_ready(drm_device_t *dev)
 {
        drm_gamma_private_t *dev_priv =
-               (drm_gamma_private_t *)dev->dev_private;
-
-       return !GAMMA_READ(GAMMA_DMACOUNT);
+                               (drm_gamma_private_t *)dev->dev_private;
+       return(!GAMMA_READ(GAMMA_DMACOUNT));
 }
 
 void gamma_dma_service(int irq, void *device, struct pt_regs *regs)
 {
-       drm_device_t        *dev      = (drm_device_t *)device;
-       drm_device_dma_t    *dma      = dev->dma;
+       drm_device_t     *dev = (drm_device_t *)device;
+       drm_device_dma_t *dma = dev->dma;
        drm_gamma_private_t *dev_priv =
-               (drm_gamma_private_t *)dev->dev_private;
+                               (drm_gamma_private_t *)dev->dev_private;
 
        atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
+
+       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
        GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
        GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
        GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
@@ -165,7 +156,9 @@ static int gamma_do_dma(drm_device_t *dev, int locked)
        }
 
        buf     = dma->next_buffer;
-       address = (unsigned long)buf->address;
+       /* WE NOW ARE ON LOGICAL PAGES!! - using page table setup in dma_init */
+       /* So we pass the buffer index value into the physical page offset */
+       address = buf->idx << 12;
        length  = buf->used;
 
        DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
@@ -232,6 +225,9 @@ static int gamma_do_dma(drm_device_t *dev, int locked)
        buf->time_dispatched = get_cycles();
 #endif
 
+       /* WE NOW ARE ON LOGICAL PAGES!!! - overriding address */
+       address = buf->idx << 12;
+
        gamma_dma_dispatch(dev, address, length);
        gamma_free_buffer(dev, dma->this_buffer);
        dma->this_buffer = buf;
@@ -582,3 +578,255 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
 
        return retcode;
 }
+
+/* =============================================================
+ * DMA initialization, cleanup
+ */
+
+static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
+{
+       drm_gamma_private_t *dev_priv;
+       drm_device_dma_t    *dma = dev->dma;
+       drm_buf_t           *buf;
+       int i;
+       struct list_head    *list;
+       unsigned int        *pgt;
+
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t),
+                                                       DRM_MEM_DRIVER );
+       if ( !dev_priv )
+               return -ENOMEM;
+
+       dev->dev_private = (void *)dev_priv;
+
+       memset( dev_priv, 0, sizeof(drm_gamma_private_t) );
+
+       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->mmio0, init->mmio0 );
+       DRM_FIND_MAP( dev_priv->mmio1, init->mmio1 );
+       DRM_FIND_MAP( dev_priv->mmio2, init->mmio2 );
+       DRM_FIND_MAP( dev_priv->mmio3, init->mmio3 );
+
+       dev_priv->sarea_priv = (drm_gamma_sarea_t *)
+               ((u8 *)dev_priv->sarea->handle +
+                init->sarea_priv_offset);
+
+       if (init->pcimode) {
+               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+               pgt = buf->address;
+
+               for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
+                       buf = dma->buflist[i];
+                       *pgt = virt_to_phys((void*)buf->address) | 0x07;
+                       pgt++;
+               }
+
+               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+       } else {
+               DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+
+               DRM_IOREMAP( dev_priv->buffers );
+
+               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+               pgt = buf->address;
+
+               for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
+                       buf = dma->buflist[i];
+                       *pgt = (unsigned int)buf->address + 0x07;
+                       pgt++;
+               }
+
+               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+
+               while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1);
+               GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe);
+       }
+       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+       GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) );
+       GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 );
+
+       return 0;
+}
+
+int gamma_do_cleanup_dma( drm_device_t *dev )
+{
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       if ( dev->dev_private ) {
+               drm_gamma_private_t *dev_priv = dev->dev_private;
+
+               DRM_IOREMAPFREE( dev_priv->buffers );
+
+               DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
+                          DRM_MEM_DRIVER );
+               dev->dev_private = NULL;
+       }
+
+       return 0;
+}
+
+int gamma_dma_init( 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_gamma_init_t init;
+
+       if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) )
+               return -EFAULT;
+
+       switch ( init.func ) {
+       case GAMMA_INIT_DMA:
+               return gamma_do_init_dma( dev, &init );
+       case GAMMA_CLEANUP_DMA:
+               return gamma_do_cleanup_dma( dev );
+       }
+
+       return -EINVAL;
+}
+
+static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy )
+{
+       drm_device_dma_t    *dma = dev->dma;
+       unsigned int        *screenbuf;
+
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       /* We've DRM_RESTRICTED this DMA buffer */
+
+       screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address;
+
+#if 0
+       *buffer++ = 0x180;      /* Tag (FilterMode) */
+       *buffer++ = 0x200;      /* Allow FBColor through */
+       *buffer++ = 0x53B;      /* Tag */
+       *buffer++ = copy->Pitch;
+       *buffer++ = 0x53A;      /* Tag */
+       *buffer++ = copy->SrcAddress;
+       *buffer++ = 0x539;      /* Tag */
+       *buffer++ = copy->WidthHeight; /* Initiates transfer */
+       *buffer++ = 0x53C;      /* Tag - DMAOutputAddress */
+       *buffer++ = virt_to_phys((void*)screenbuf);
+       *buffer++ = 0x53D;      /* Tag - DMAOutputCount */
+       *buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/
+
+       /* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */
+       /* Now put it back to the screen */
+
+       *buffer++ = 0x180;      /* Tag (FilterMode) */
+       *buffer++ = 0x400;      /* Allow Sync through */
+       *buffer++ = 0x538;      /* Tag - DMARectangleReadTarget */
+       *buffer++ = 0x155;      /* FBSourceData | count */
+       *buffer++ = 0x537;      /* Tag */
+       *buffer++ = copy->Pitch;
+       *buffer++ = 0x536;      /* Tag */
+       *buffer++ = copy->DstAddress;
+       *buffer++ = 0x535;      /* Tag */
+       *buffer++ = copy->WidthHeight; /* Initiates transfer */
+       *buffer++ = 0x530;      /* Tag - DMAAddr */
+       *buffer++ = virt_to_phys((void*)screenbuf);
+       *buffer++ = 0x531;
+       *buffer++ = copy->Count; /* initiates DMA transfer of color data */
+#endif
+
+       /* need to dispatch it now */
+
+       return 0;
+}
+
+int gamma_dma_copy( 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_gamma_copy_t copy;
+
+       if ( copy_from_user( &copy, (drm_gamma_copy_t *)arg, sizeof(copy) ) )
+               return -EFAULT;
+
+       return gamma_do_copy_dma( dev, &copy );
+}
+
+/* =============================================================
+ * Per Context SAREA Support
+ */
+
+int gamma_getsareactx(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_ctx_priv_map_t request;
+       drm_map_t *map;
+
+       if (copy_from_user(&request,
+                          (drm_ctx_priv_map_t *)arg,
+                          sizeof(request)))
+               return -EFAULT;
+
+       down(&dev->struct_sem);
+       if ((int)request.ctx_id >= dev->max_context) {
+               up(&dev->struct_sem);
+               return -EINVAL;
+       }
+
+       map = dev->context_sareas[request.ctx_id];
+       up(&dev->struct_sem);
+
+       request.handle = map->handle;
+       if (copy_to_user((drm_ctx_priv_map_t *)arg, &request, sizeof(request)))
+               return -EFAULT;
+       return 0;
+}
+
+int gamma_setsareactx(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_ctx_priv_map_t request;
+       drm_map_t *map = NULL;
+       drm_map_list_t *r_list;
+       struct list_head *list;
+
+       if (copy_from_user(&request,
+                          (drm_ctx_priv_map_t *)arg,
+                          sizeof(request)))
+               return -EFAULT;
+
+       down(&dev->struct_sem);
+       r_list = NULL;
+       list_for_each(list, &dev->maplist->head) {
+               r_list = (drm_map_list_t *)list;
+               if(r_list->map &&
+                  r_list->map->handle == request.handle) break;
+       }
+       if (list == &(dev->maplist->head)) {
+               up(&dev->struct_sem);
+               return -EINVAL;
+       }
+       map = r_list->map;
+       up(&dev->struct_sem);
+
+       if (!map) return -EINVAL;
+
+       down(&dev->struct_sem);
+       if ((int)request.ctx_id >= dev->max_context) {
+               up(&dev->struct_sem);
+               return -EINVAL;
+       }
+       dev->context_sareas[request.ctx_id] = map;
+       up(&dev->struct_sem);
+       return 0;
+}
diff --git a/drivers/char/drm/gamma_drm.h b/drivers/char/drm/gamma_drm.h
new file mode 100644 (file)
index 0000000..d06763a
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _GAMMA_DRM_H_
+#define _GAMMA_DRM_H_
+
+typedef struct _drm_gamma_tex_region {
+       unsigned char next, prev; /* indices to form a circular LRU  */
+       unsigned char in_use;   /* owned by a client, or free? */
+       int age;                /* tracked by clients to update local LRU's */
+} drm_gamma_tex_region_t;
+
+typedef struct {
+       unsigned int    GDeltaMode;
+       unsigned int    GDepthMode;
+       unsigned int    GGeometryMode;
+       unsigned int    GTransformMode;
+} drm_gamma_context_regs_t;
+
+typedef struct _drm_gamma_sarea {
+       drm_gamma_context_regs_t context_state;
+
+       unsigned int dirty;
+
+
+       /* Maintain an LRU of contiguous regions of texture space.  If
+        * you think you own a region of texture memory, and it has an
+        * age different to the one you set, then you are mistaken and
+        * it has been stolen by another client.  If global texAge
+        * hasn't changed, there is no need to walk the list.
+        *
+        * These regions can be used as a proxy for the fine-grained
+        * texture information of other clients - by maintaining them
+        * in the same lru which is used to age their own textures,
+        * clients have an approximate lru for the whole of global
+        * texture space, and can make informed decisions as to which
+        * areas to kick out.  There is no need to choose whether to
+        * kick out your own texture or someone else's - simply eject
+        * them all in LRU order.  
+        */
+   
+#define GAMMA_NR_TEX_REGIONS 64
+       drm_gamma_tex_region_t texList[GAMMA_NR_TEX_REGIONS+1]; 
+                               /* Last elt is sentinal */
+        int texAge;            /* last time texture was uploaded */
+        int last_enqueue;      /* last time a buffer was enqueued */
+       int last_dispatch;      /* age of the most recently dispatched buffer */
+       int last_quiescent;     /*  */
+       int ctxOwner;           /* last context to upload state */
+
+       int vertex_prim;
+} drm_gamma_sarea_t;
+
+typedef struct drm_gamma_copy {
+       unsigned int    DMAOutputAddress;
+       unsigned int    DMAOutputCount;
+       unsigned int    DMAReadGLINTSource;
+       unsigned int    DMARectangleWriteAddress;
+       unsigned int    DMARectangleWriteLinePitch;
+       unsigned int    DMARectangleWrite;
+       unsigned int    DMARectangleReadAddress;
+       unsigned int    DMARectangleReadLinePitch;
+       unsigned int    DMARectangleRead;
+       unsigned int    DMARectangleReadTarget;
+} drm_gamma_copy_t;
+
+typedef struct drm_gamma_init {
+       enum {
+               GAMMA_INIT_DMA    = 0x01,
+               GAMMA_CLEANUP_DMA = 0x02
+       } func;
+
+       int sarea_priv_offset;
+       int pcimode;
+       unsigned int mmio0;
+       unsigned int mmio1;
+       unsigned int mmio2;
+       unsigned int mmio3;
+       unsigned int buffers_offset;
+} drm_gamma_init_t;
+
+#endif /* _GAMMA_DRM_H_ */
index c05465c5dad95fede92ac458d3f75675bae5be02..58cea2412cc13333a0d247896f7297940d187cc1 100644 (file)
 
 #define DRIVER_NAME            "gamma"
 #define DRIVER_DESC            "3DLabs gamma"
-#define DRIVER_DATE            "20010216"
+#define DRIVER_DATE            "20010624"
 
-#define DRIVER_MAJOR           1
+#define DRIVER_MAJOR           2
 #define DRIVER_MINOR           0
 #define DRIVER_PATCHLEVEL      0
 
 #define DRIVER_IOCTLS                                                    \
-       [DRM_IOCTL_NR(DRM_IOCTL_DMA)]        = { gamma_dma,       1, 0 }
+       [DRM_IOCTL_NR(DRM_IOCTL_DMA)]        = { gamma_dma,       1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_GAMMA_INIT)] = { gamma_dma_init,  1, 1 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_GAMMA_COPY)] = { gamma_dma_copy,  1, 1 }
 
+#define IOCTL_TABLE_NAME       DRM(ioctls)
+#define IOCTL_FUNC_NAME        DRM(ioctl)
 
 #define __HAVE_COUNTERS                5
 #define __HAVE_COUNTER6                _DRM_STAT_IRQ
@@ -57,6 +61,7 @@
 
 
 #include "drm_auth.h"
+#include "drm_agpsupport.h"
 #include "drm_bufs.h"
 #include "drm_context.h"
 #include "drm_dma.h"
@@ -82,7 +87,6 @@ static int __init gamma_options( char *str )
 __setup( DRIVER_NAME "=", gamma_options );
 #endif
 
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
index 68b520700ac6006db655e894a1917ebb6f5d1ed0..e7d0c89603a1562defd011a680377613a3b9837b 100644 (file)
@@ -32,8 +32,9 @@
 #ifndef _GAMMA_DRV_H_
 #define _GAMMA_DRV_H_
 
-
 typedef struct drm_gamma_private {
+       drm_gamma_sarea_t *sarea_priv;
+       drm_map_t *sarea;
        drm_map_t *buffers;
        drm_map_t *mmio0;
        drm_map_t *mmio1;
@@ -51,6 +52,11 @@ do {                                                                 \
        }                                                               \
 } while (0)
 
+                               /* gamma_dma.c */
+extern int gamma_dma_init( struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg );
+extern int gamma_dma_copy( struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg );
 
 extern void gamma_dma_ready(drm_device_t *dev);
 extern void gamma_dma_quiescent_single(drm_device_t *dev);
@@ -63,6 +69,7 @@ extern int  gamma_dma(struct inode *inode, struct file *filp,
 extern int  gamma_find_devices(void);
 extern int  gamma_found(void);
 
+#define GLINT_DRI_BUF_COUNT 256
 
 #define GAMMA_OFF(reg)                                            \
        ((reg < 0x1000)                                            \
@@ -78,7 +85,6 @@ extern int  gamma_found(void);
                           ((reg < 0x10000)  ? dev_priv->mmio1->handle :     \
                            ((reg < 0x11000) ? dev_priv->mmio2->handle :     \
                                               dev_priv->mmio3->handle))))
-       
 #define GAMMA_ADDR(reg)         (GAMMA_BASE(reg) + GAMMA_OFF(reg))
 #define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
 #define GAMMA_READ(reg)         GAMMA_DEREF(reg)
@@ -91,9 +97,11 @@ extern int  gamma_found(void);
 #define GAMMA_FILTERMODE       0x8c00
 #define GAMMA_GCOMMANDINTFLAGS 0x0c50
 #define GAMMA_GCOMMANDMODE     0x0c40
+#define                GAMMA_QUEUED_DMA_MODE           1<<1
 #define GAMMA_GCOMMANDSTATUS   0x0c60
 #define GAMMA_GDELAYTIMER      0x0c38
 #define GAMMA_GDMACONTROL      0x0060
+#define        GAMMA_USE_AGP                   1<<1
 #define GAMMA_GINTENABLE       0x0808
 #define GAMMA_GINTFLAGS               0x0810
 #define GAMMA_INFIFOSPACE      0x0018
@@ -101,5 +109,12 @@ extern int  gamma_found(void);
 #define GAMMA_OUTPUTFIFO       0x2000
 #define GAMMA_SYNC            0x8c40
 #define GAMMA_SYNC_TAG        0x0188
+#define GAMMA_PAGETABLEADDR    0x0C00
+#define GAMMA_PAGETABLELENGTH  0x0C08
+
+#define GAMMA_PASSTHROUGH      0x1FE
+#define GAMMA_DMAADDRTAG       0x530
+#define GAMMA_DMACOUNTTAG      0x531
+#define GAMMA_COMMANDINTTAG    0x532
 
 #endif
index a5152bc0ac5e3481633e263ffdee7a5a93c5cffe..64309f59a9f2882017888c55a64f45173cf790b9 100644 (file)
        i810_dma_quiescent( dev );                                      \
 } while (0)
 
-#define __HAVE_DMA_IRQ         1
-#define __HAVE_DMA_IRQ_BH      1
-#define __HAVE_SHARED_IRQ       1
-#define DRIVER_PREINSTALL() do {                                       \
-       drm_i810_private_t *dev_priv =                                  \
-               (drm_i810_private_t *)dev->dev_private;                 \
-       u16 tmp;                                                        \
-       tmp = I810_READ16( I810REG_HWSTAM );                            \
-       tmp = tmp & 0x6000;                                             \
-       I810_WRITE16( I810REG_HWSTAM, tmp );                            \
-                                                                       \
-       tmp = I810_READ16( I810REG_INT_MASK_R );                        \
-       tmp = tmp & 0x6000;             /* Unmask interrupts */         \
-       I810_WRITE16( I810REG_INT_MASK_R, tmp );                        \
-       tmp = I810_READ16( I810REG_INT_ENABLE_R );                      \
-       tmp = tmp & 0x6000;             /* Disable all interrupts */    \
-       I810_WRITE16( I810REG_INT_ENABLE_R, tmp );                      \
-} while (0)
-
-#define DRIVER_POSTINSTALL() do {                                      \
-       drm_i810_private_t *dev_priv =                                  \
-               (drm_i810_private_t *)dev->dev_private;                 \
-       u16 tmp;                                                        \
-       tmp = I810_READ16( I810REG_INT_ENABLE_R );                      \
-       tmp = tmp & 0x6000;                                             \
-       tmp = tmp | 0x0003;     /* Enable bp & user interrupts */       \
-       I810_WRITE16( I810REG_INT_ENABLE_R, tmp );                      \
-} while (0)
-
-#define DRIVER_UNINSTALL() do {                                                \
-       drm_i810_private_t *dev_priv =                                  \
-               (drm_i810_private_t *)dev->dev_private;                 \
-       u16 tmp;                                                        \
-       if ( dev_priv ) {                                               \
-               tmp = I810_READ16( I810REG_INT_IDENTITY_R );            \
-               tmp = tmp & ~(0x6000);  /* Clear all interrupts */      \
-               if ( tmp != 0 )                                         \
-                       I810_WRITE16( I810REG_INT_IDENTITY_R, tmp );    \
-                                                                       \
-               tmp = I810_READ16( I810REG_INT_ENABLE_R );              \
-               tmp = tmp & 0x6000;     /* Disable all interrupts */    \
-               I810_WRITE16( I810REG_INT_ENABLE_R, tmp );              \
-       }                                                               \
-} while (0)
+/* Don't need an irq any more.  The template code will make sure that
+ * a noop stub is generated for compatibility.
+ */
+#define __HAVE_DMA_IRQ         0
 
 /* Buffer customization:
  */
index 968cf384c88fc0b6d051fd0c9353193622e56af4..9dc1e45fa325e47ab0194d16cca5a0663a719a45 100644 (file)
@@ -26,7 +26,7 @@
  *
  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
  *         Jeff Hartmann <jhartmann@valinux.com>
- *          Keith Whitwell <keithw@valinux.com>
+ *          Keith Whitwell <keith_whitwell@yahoo.com>
  *
  */
 
 #include "i810_drv.h"
 #include <linux/interrupt.h>   /* For task queue support */
 
-/* in case we don't have a 2.3.99-pre6 kernel or later: */
-#ifndef VM_DONTCOPY
-#define VM_DONTCOPY 0
-#endif
-
 #define I810_BUF_FREE          2
 #define I810_BUF_CLIENT                1
 #define I810_BUF_HARDWARE              0
 
 #define RING_LOCALS    unsigned int outring, ringmask; volatile char *virt;
 
-#define BEGIN_LP_RING(n) do {                          \
-       if (I810_VERBOSE)                               \
-               DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",  \
-                         n, __FUNCTION__);             \
-       if (dev_priv->ring.space < n*4)                 \
-               i810_wait_ring(dev, n*4);               \
-       dev_priv->ring.space -= n*4;                    \
-       outring = dev_priv->ring.tail;                  \
-       ringmask = dev_priv->ring.tail_mask;            \
-       virt = dev_priv->ring.virtual_start;            \
+#define BEGIN_LP_RING(n) do {                                          \
+       if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \
+       if (dev_priv->ring.space < n*4)                                 \
+               i810_wait_ring(dev, n*4);                               \
+       dev_priv->ring.space -= n*4;                                    \
+       outring = dev_priv->ring.tail;                                  \
+       ringmask = dev_priv->ring.tail_mask;                            \
+       virt = dev_priv->ring.virtual_start;                            \
 } while (0)
 
-#define ADVANCE_LP_RING() do {                                 \
-       if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");       \
-       dev_priv->ring.tail = outring;                          \
-       I810_WRITE(LP_RING + RING_TAIL, outring);               \
+#define ADVANCE_LP_RING() do {                         \
+       if (0) DRM_DEBUG("ADVANCE_LP_RING\n");                  \
+       dev_priv->ring.tail = outring;                  \
+       I810_WRITE(LP_RING + RING_TAIL, outring);       \
 } while(0)
 
-#define OUT_RING(n) do {                                               \
-       if (I810_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
-       *(volatile unsigned int *)(virt + outring) = n;                 \
-       outring += 4;                                                   \
-       outring &= ringmask;                                            \
+#define OUT_RING(n) do {                               \
+       if (0) DRM_DEBUG("   OUT_RING %x\n", (int)(n)); \
+       *(volatile unsigned int *)(virt + outring) = n; \
+       outring += 4;                                   \
+       outring &= ringmask;                            \
 } while (0)
 
 static inline void i810_print_status_page(drm_device_t *dev)
@@ -86,6 +79,7 @@ static inline void i810_print_status_page(drm_device_t *dev)
        DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
        DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
        DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
+       DRM_DEBUG(  "hw_status: Last Render: %x\n", temp[4]);
        DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
        for(i = 6; i < dma->buf_count + 6; i++) {
                DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
@@ -163,7 +157,7 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
        buf_priv->currently_mapped = I810_BUF_MAPPED;
        unlock_kernel();
 
-       if (remap_page_range(vma, vma->vm_start,
+       if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
                             VM_OFFSET(vma),
                             vma->vm_end - vma->vm_start,
                             vma->vm_page_prot)) return -EAGAIN;
@@ -181,36 +175,31 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
 
        if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
 
-       if(VM_DONTCOPY != 0) {
 #if LINUX_VERSION_CODE <= 0x020402
-               down( &current->mm->mmap_sem );
+       down( &current->mm->mmap_sem );
 #else
-               down_write( &current->mm->mmap_sem );
+       down_write( &current->mm->mmap_sem );
 #endif
-               old_fops = filp->f_op;
-               filp->f_op = &i810_buffer_fops;
-               dev_priv->mmap_buffer = buf;
-               buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
-                                                   PROT_READ|PROT_WRITE,
-                                                   MAP_SHARED,
-                                                   buf->bus_address);
-               dev_priv->mmap_buffer = NULL;
-               filp->f_op = old_fops;
-               if ((unsigned long)buf_priv->virtual > -1024UL) {
-                       /* Real error */
-                       DRM_DEBUG("mmap error\n");
-                       retcode = (signed int)buf_priv->virtual;
-                       buf_priv->virtual = 0;
-               }
+       old_fops = filp->f_op;
+       filp->f_op = &i810_buffer_fops;
+       dev_priv->mmap_buffer = buf;
+       buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
+                                           PROT_READ|PROT_WRITE,
+                                           MAP_SHARED,
+                                           buf->bus_address);
+       dev_priv->mmap_buffer = NULL;
+       filp->f_op = old_fops;
+       if ((unsigned long)buf_priv->virtual > -1024UL) {
+               /* Real error */
+               DRM_DEBUG("mmap error\n");
+               retcode = (signed int)buf_priv->virtual;
+               buf_priv->virtual = 0;
+       }
 #if LINUX_VERSION_CODE <= 0x020402
-               up( &current->mm->mmap_sem );
+       up( &current->mm->mmap_sem );
 #else
-               up_write( &current->mm->mmap_sem );
+       up_write( &current->mm->mmap_sem );
 #endif
-       } else {
-               buf_priv->virtual = buf_priv->kernel_virtual;
-               buf_priv->currently_mapped = I810_BUF_MAPPED;
-       }
        return retcode;
 }
 
@@ -219,28 +208,21 @@ static int i810_unmap_buffer(drm_buf_t *buf)
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
        int retcode = 0;
 
-       if(VM_DONTCOPY != 0) {
-               if(buf_priv->currently_mapped != I810_BUF_MAPPED)
-                       return -EINVAL;
+       if(buf_priv->currently_mapped != I810_BUF_MAPPED)
+               return -EINVAL;
 #if LINUX_VERSION_CODE <= 0x020402
-               down( &current->mm->mmap_sem );
+       down( &current->mm->mmap_sem );
 #else
-               down_write( &current->mm->mmap_sem );
-#endif
-#if LINUX_VERSION_CODE < 0x020399
-               retcode = do_munmap((unsigned long)buf_priv->virtual,
-                                   (size_t) buf->total);
-#else
-               retcode = do_munmap(current->mm,
-                                   (unsigned long)buf_priv->virtual,
-                                   (size_t) buf->total);
+       down_write( &current->mm->mmap_sem );
 #endif
+       retcode = do_munmap(current->mm,
+                           (unsigned long)buf_priv->virtual,
+                           (size_t) buf->total);
 #if LINUX_VERSION_CODE <= 0x020402
-               up( &current->mm->mmap_sem );
+       up( &current->mm->mmap_sem );
 #else
-               up_write( &current->mm->mmap_sem );
+       up_write( &current->mm->mmap_sem );
 #endif
-       }
        buf_priv->currently_mapped = I810_BUF_UNMAPPED;
        buf_priv->virtual = 0;
 
@@ -286,18 +268,28 @@ static unsigned long i810_alloc_page(drm_device_t *dev)
        if(address == 0UL)
                return 0;
 
+#if LINUX_VERSION_CODE < 0x020500
+       atomic_inc(&virt_to_page(address)->count);
+       set_bit(PG_locked, &virt_to_page(address)->flags);
+#else
        get_page(virt_to_page(address));
        SetPageLocked(virt_to_page(address));
-
+#endif
        return address;
 }
 
 static void i810_free_page(drm_device_t *dev, unsigned long page)
 {
        if (page) {
+#if LINUX_VERSION_CODE < 0x020500
+               atomic_dec(&virt_to_page(page)->count);
+               clear_bit(PG_locked, &virt_to_page(page)->flags);
+               wake_up(&virt_to_page(page)->wait);
+#else
                struct page *p = virt_to_page(page);
                put_page(p);
                unlock_page(p);
+#endif
                free_page(page);
        }
 }
@@ -358,8 +350,7 @@ static int i810_wait_ring(drm_device_t *dev, int n)
                        DRM_ERROR("lockup\n");
                        goto out_wait_ring;
                }
-
-               for (i = 0 ; i < 2000 ; i++) ;
+               udelay(1);
        }
 
 out_wait_ring:
@@ -447,9 +438,6 @@ static int i810_dma_initialize(drm_device_t *dev,
                ((u8 *)dev_priv->sarea_map->handle +
                 init->sarea_priv_offset);
 
-       atomic_set(&dev_priv->flush_done, 0);
-       init_waitqueue_head(&dev_priv->flush_queue);
-
        dev_priv->ring.Start = init->ring_start;
        dev_priv->ring.End = init->ring_end;
        dev_priv->ring.Size = init->ring_size;
@@ -474,6 +462,9 @@ static int i810_dma_initialize(drm_device_t *dev,
        dev_priv->back_offset = init->back_offset;
        dev_priv->depth_offset = init->depth_offset;
 
+       dev_priv->overlay_offset = init->overlay_offset;
+       dev_priv->overlay_physical = init->overlay_physical;
+
        dev_priv->front_di1 = init->front_offset | init->pitch_bits;
        dev_priv->back_di1 = init->back_offset | init->pitch_bits;
        dev_priv->zi1 = init->depth_offset | init->pitch_bits;
@@ -539,16 +530,12 @@ int i810_dma_init(struct inode *inode, struct file *filp,
 
 /* Most efficient way to verify state for the i810 is as it is
  * emitted.  Non-conformant state is silently dropped.
- *
- * Use 'volatile' & local var tmp to force the emitted values to be
- * identical to the verified ones.
  */
 static void i810EmitContextVerified( drm_device_t *dev,
-                                    volatile unsigned int *code )
+                                    unsigned int *code )
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        int i, j = 0;
-       unsigned int tmp;
        RING_LOCALS;
 
        BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
@@ -560,14 +547,13 @@ static void i810EmitContextVerified( drm_device_t *dev,
        OUT_RING( code[I810_CTXREG_ST1] );
 
        for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
-               tmp = code[i];
-
-               if ((tmp & (7<<29)) == (3<<29) &&
-                   (tmp & (0x1f<<24)) < (0x1d<<24))
+               if ((code[i] & (7<<29)) == (3<<29) &&
+                   (code[i] & (0x1f<<24)) < (0x1d<<24))
                {
-                       OUT_RING( tmp );
+                       OUT_RING( code[i] );
                        j++;
                }
+               else printk("constext state dropped!!!\n");
        }
 
        if (j & 1)
@@ -581,7 +567,6 @@ static void i810EmitTexVerified( drm_device_t *dev,
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        int i, j = 0;
-       unsigned int tmp;
        RING_LOCALS;
 
        BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
@@ -592,14 +577,14 @@ static void i810EmitTexVerified( drm_device_t *dev,
        OUT_RING( code[I810_TEXREG_MI3] );
 
        for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
-               tmp = code[i];
 
-               if ((tmp & (7<<29)) == (3<<29) &&
-                   (tmp & (0x1f<<24)) < (0x1d<<24))
+               if ((code[i] & (7<<29)) == (3<<29) &&
+                   (code[i] & (0x1f<<24)) < (0x1d<<24))
                {
-                       OUT_RING( tmp );
+                       OUT_RING( code[i] );
                        j++;
                }
+               else printk("texture state dropped!!!\n");
        }
 
        if (j & 1)
@@ -624,9 +609,9 @@ static void i810EmitDestVerified( drm_device_t *dev,
        if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
                OUT_RING( CMD_OP_DESTBUFFER_INFO );
                OUT_RING( tmp );
-       } else
-          DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
-                    tmp, dev_priv->front_di1, dev_priv->back_di1);
+       } 
+       else
+          printk("buffer state dropped\n");
 
        /* invarient:
         */
@@ -711,7 +696,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
                        continue;
 
                if ( flags & I810_FRONT ) {
-                       DRM_DEBUG("clear front\n");
                        BEGIN_LP_RING( 6 );
                        OUT_RING( BR00_BITBLT_CLIENT |
                                  BR00_OP_COLOR_BLT | 0x3 );
@@ -724,7 +708,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
                }
 
                if ( flags & I810_BACK ) {
-                       DRM_DEBUG("clear back\n");
                        BEGIN_LP_RING( 6 );
                        OUT_RING( BR00_BITBLT_CLIENT |
                                  BR00_OP_COLOR_BLT | 0x3 );
@@ -737,7 +720,6 @@ static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
                }
 
                if ( flags & I810_DEPTH ) {
-                       DRM_DEBUG("clear depth\n");
                        BEGIN_LP_RING( 6 );
                        OUT_RING( BR00_BITBLT_CLIENT |
                                  BR00_OP_COLOR_BLT | 0x3 );
@@ -763,8 +745,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev )
        int i;
        RING_LOCALS;
 
-       DRM_DEBUG("swapbuffers\n");
-
        i810_kernel_lost_context(dev);
 
        if (nbox > I810_NR_SAREA_CLIPRECTS)
@@ -783,10 +763,6 @@ static void i810_dma_dispatch_swap( drm_device_t *dev )
                    pbox->y2 > dev_priv->h)
                        continue;
 
-               DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
-                         pbox[i].x1, pbox[i].y1,
-                         pbox[i].x2, pbox[i].y2);
-
                BEGIN_LP_RING( 6 );
                OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
                OUT_RING( pitch | (0xCC << 16));
@@ -811,7 +787,7 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
        int nbox = sarea_priv->nbox;
        unsigned long address = (unsigned long)buf->bus_address;
        unsigned long start = address - dev->agp->base;
-       int i = 0, u;
+       int i = 0;
        RING_LOCALS;
 
        i810_kernel_lost_context(dev);
@@ -819,33 +795,16 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
        if (nbox > I810_NR_SAREA_CLIPRECTS)
                nbox = I810_NR_SAREA_CLIPRECTS;
 
-       if (discard) {
-               u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
-                           I810_BUF_HARDWARE);
-               if(u != I810_BUF_CLIENT) {
-                       DRM_DEBUG("xxxx 2\n");
-               }
-       }
-
        if (used > 4*1024)
                used = 0;
 
        if (sarea_priv->dirty)
           i810EmitState( dev );
 
-       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
-                 address, used, nbox);
-
-       dev_priv->counter++;
-       DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);
-       DRM_DEBUG(  "i810_dma_dispatch\n");
-       DRM_DEBUG(  "start : %lx\n", start);
-       DRM_DEBUG(  "used : %d\n", used);
-       DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
-
        if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
-               *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
-                                            sarea_priv->vertex_prim |
+               unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
+
+               *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | prim | 
                                             ((used/4)-2));
 
                if (used & 4) {
@@ -878,154 +837,62 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
                } while (++i < nbox);
        }
 
-       BEGIN_LP_RING(10);
-       OUT_RING( CMD_STORE_DWORD_IDX );
-       OUT_RING( 20 );
-       OUT_RING( dev_priv->counter );
-       OUT_RING( 0 );
-
        if (discard) {
+               dev_priv->counter++;
+
+               (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+                              I810_BUF_HARDWARE);
+
+               BEGIN_LP_RING(8);
+               OUT_RING( CMD_STORE_DWORD_IDX );
+               OUT_RING( 20 );
+               OUT_RING( dev_priv->counter );
                OUT_RING( CMD_STORE_DWORD_IDX );
                OUT_RING( buf_priv->my_use_idx );
                OUT_RING( I810_BUF_FREE );
+               OUT_RING( CMD_REPORT_HEAD );
                OUT_RING( 0 );
+               ADVANCE_LP_RING();
        }
-
-       OUT_RING( CMD_REPORT_HEAD );
-       OUT_RING( 0 );
-       ADVANCE_LP_RING();
-}
-
-
-/* Interrupts are only for flushing */
-void i810_dma_service(int irq, void *device, struct pt_regs *regs)
-{
-       drm_device_t     *dev = (drm_device_t *)device;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-       u16 temp;
-
-       atomic_inc(&dev->counts[_DRM_STAT_IRQ]);
-       temp = I810_READ16(I810REG_INT_IDENTITY_R);
-       temp = temp & ~(0x6000);
-       if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R,
-                                  temp); /* Clear all interrupts */
-       else
-          return;
-
-       queue_task(&dev->tq, &tq_immediate);
-       mark_bh(IMMEDIATE_BH);
-}
-
-void i810_dma_immediate_bh(void *device)
-{
-       drm_device_t *dev = (drm_device_t *) device;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-
-       atomic_set(&dev_priv->flush_done, 1);
-       wake_up_interruptible(&dev_priv->flush_queue);
 }
 
-static inline void i810_dma_emit_flush(drm_device_t *dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       i810_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(2);
-       OUT_RING( CMD_REPORT_HEAD );
-       OUT_RING( GFX_OP_USER_INTERRUPT );
-       ADVANCE_LP_RING();
-
-/*     i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
-/*             atomic_set(&dev_priv->flush_done, 1); */
-/*             wake_up_interruptible(&dev_priv->flush_queue); */
-}
 
-static inline void i810_dma_quiescent_emit(drm_device_t *dev)
+void i810_dma_quiescent(drm_device_t *dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
 
+/*     printk("%s\n", __FUNCTION__); */
+
        i810_kernel_lost_context(dev);
 
        BEGIN_LP_RING(4);
        OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
        OUT_RING( CMD_REPORT_HEAD );
        OUT_RING( 0 );
-       OUT_RING( GFX_OP_USER_INTERRUPT );
+       OUT_RING( 0 );
        ADVANCE_LP_RING();
 
-/*     i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
-/*             atomic_set(&dev_priv->flush_done, 1); */
-/*             wake_up_interruptible(&dev_priv->flush_queue); */
-}
-
-void i810_dma_quiescent(drm_device_t *dev)
-{
-       DECLARE_WAITQUEUE(entry, current);
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-       unsigned long end;
-
-       if(dev_priv == NULL) {
-               return;
-       }
-       atomic_set(&dev_priv->flush_done, 0);
-       add_wait_queue(&dev_priv->flush_queue, &entry);
-       end = jiffies + (HZ*3);
-
-       for (;;) {
-               current->state = TASK_INTERRUPTIBLE;
-               i810_dma_quiescent_emit(dev);
-               if (atomic_read(&dev_priv->flush_done) == 1) break;
-               if((signed)(end - jiffies) <= 0) {
-                       DRM_ERROR("lockup\n");
-                       break;
-               }
-               schedule_timeout(HZ*3);
-               if (signal_pending(current)) {
-                       break;
-               }
-       }
-
-       current->state = TASK_RUNNING;
-       remove_wait_queue(&dev_priv->flush_queue, &entry);
-
-       return;
+       i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 }
 
 static int i810_flush_queue(drm_device_t *dev)
 {
-       DECLARE_WAITQUEUE(entry, current);
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       drm_i810_private_t *dev_priv = dev->dev_private;
        drm_device_dma_t *dma = dev->dma;
-       unsigned long end;
        int i, ret = 0;
+       RING_LOCALS;
+       
+/*     printk("%s\n", __FUNCTION__); */
 
-       if(dev_priv == NULL) {
-               return 0;
-       }
-       atomic_set(&dev_priv->flush_done, 0);
-       add_wait_queue(&dev_priv->flush_queue, &entry);
-       end = jiffies + (HZ*3);
-       for (;;) {
-               current->state = TASK_INTERRUPTIBLE;
-               i810_dma_emit_flush(dev);
-               if (atomic_read(&dev_priv->flush_done) == 1) break;
-               if((signed)(end - jiffies) <= 0) {
-                       DRM_ERROR("lockup\n");
-                       break;
-               }
-               schedule_timeout(HZ*3);
-               if (signal_pending(current)) {
-                       ret = -EINTR; /* Can't restart */
-                       break;
-               }
-       }
+       i810_kernel_lost_context(dev);
 
-       current->state = TASK_RUNNING;
-       remove_wait_queue(&dev_priv->flush_queue, &entry);
+       BEGIN_LP_RING(2);
+       OUT_RING( CMD_REPORT_HEAD );
+       OUT_RING( 0 );
+       ADVANCE_LP_RING();
 
+       i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 
        for (i = 0; i < dma->buf_count; i++) {
                drm_buf_t *buf = dma->buflist[ i ];
@@ -1037,7 +904,7 @@ static int i810_flush_queue(drm_device_t *dev)
                if (used == I810_BUF_HARDWARE)
                        DRM_DEBUG("reclaimed from HARDWARE\n");
                if (used == I810_BUF_CLIENT)
-                       DRM_DEBUG("still on client HARDWARE\n");
+                       DRM_DEBUG("still on client\n");
        }
 
        return ret;
@@ -1077,7 +944,6 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp,
        drm_file_t        *priv   = filp->private_data;
        drm_device_t      *dev    = priv->dev;
 
-       DRM_DEBUG("i810_flush_ioctl\n");
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
                DRM_ERROR("i810_flush_ioctl called without lock held\n");
                return -EINVAL;
@@ -1108,9 +974,6 @@ int i810_dma_vertex(struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
-                 vertex.idx, vertex.used, vertex.discard);
-
        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
 
        i810_dma_dispatch_vertex( dev,
@@ -1159,8 +1022,6 @@ int i810_swap_bufs(struct inode *inode, struct file *filp,
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
 
-       DRM_DEBUG("i810_swap_bufs\n");
-
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
                DRM_ERROR("i810_swap_buf called without lock held\n");
                return -EINVAL;
@@ -1196,7 +1057,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
                                        dev_priv->sarea_priv;
 
-       DRM_DEBUG("getbuf\n");
        if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
                return -EFAULT;
 
@@ -1209,9 +1069,6 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
 
        retcode = i810_dma_get_buffer(dev, &d, filp);
 
-       DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
-                 current->pid, retcode, d.granted);
-
        if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
                return -EFAULT;
        sarea_priv->last_dispatch = (int) hw_status[5];
@@ -1219,46 +1076,171 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
        return retcode;
 }
 
-int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd,
+int i810_copybuf(struct inode *inode,
+                struct file *filp, 
+                unsigned int cmd,
+                unsigned long arg)
+{
+       /* Never copy - 2.4.x doesn't need it */
+       return 0;
+}
+
+int i810_docopy(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_i810_copy_t   d;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
-       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-                                       dev_priv->sarea_priv;
-       drm_buf_t *buf;
-       drm_i810_buf_priv_t *buf_priv;
+       /* Never copy - 2.4.x doesn't need it */
+       return 0;
+}
+
+static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
+               unsigned int last_render)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned long address = (unsigned long)buf->bus_address;
+       unsigned long start = address - dev->agp->base;
+       int u;
+       RING_LOCALS;
+
+       i810_kernel_lost_context(dev);
+
+       u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+               I810_BUF_HARDWARE);
+       if(u != I810_BUF_CLIENT) {
+               DRM_DEBUG("MC found buffer that isn't mine!\n");
+       }
+
+       if (used > 4*1024)
+               used = 0;
+
+       sarea_priv->dirty = 0x7f;
+
+       DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n",
+               address, used);
+
+       dev_priv->counter++;
+       DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
+       DRM_DEBUG("i810_dma_dispatch_mc\n");
+       DRM_DEBUG("start : %lx\n", start);
+       DRM_DEBUG("used : %d\n", used);
+       DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
+
+       if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+               if (used & 4) {
+                       *(u32 *)((u32)buf_priv->virtual + used) = 0;
+                       used += 4;
+               }
+
+               i810_unmap_buffer(buf);
+       }
+       BEGIN_LP_RING(4);
+       OUT_RING( CMD_OP_BATCH_BUFFER );
+       OUT_RING( start | BB1_PROTECTED );
+       OUT_RING( start + used - 4 );
+       OUT_RING( 0 );
+       ADVANCE_LP_RING();
+
+
+       BEGIN_LP_RING(8);
+       OUT_RING( CMD_STORE_DWORD_IDX );
+       OUT_RING( buf_priv->my_use_idx );
+       OUT_RING( I810_BUF_FREE );
+       OUT_RING( 0 );
+
+       OUT_RING( CMD_STORE_DWORD_IDX );
+       OUT_RING( 16 );
+       OUT_RING( last_render );
+       OUT_RING( 0 );
+       ADVANCE_LP_RING();
+}
+
+int i810_dma_mc(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+               dev_priv->sarea_priv;
+       drm_i810_mc_t mc;
+
+       if (copy_from_user(&mc, (drm_i810_mc_t *)arg, sizeof(mc)))
+               return -EFAULT;
+
 
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-               DRM_ERROR("i810_dma called without lock held\n");
+               DRM_ERROR("i810_dma_mc called without lock held\n");
                return -EINVAL;
        }
 
-       if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d)))
-               return -EFAULT;
+       i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
+               mc.last_render );
 
-        if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL;
-       buf = dma->buflist[ d.idx ];
-       buf_priv = buf->dev_private;
-       if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM;
+       atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);
+       atomic_inc(&dev->counts[_DRM_STAT_DMA]);
+       sarea_priv->last_enqueue = dev_priv->counter-1;
+       sarea_priv->last_dispatch = (int) hw_status[5];
 
-       if(d.used < 0 || d.used > buf->total) return -EINVAL;
+       return 0;
+}
 
-       if (copy_from_user(buf_priv->virtual, d.address, d.used))
-               return -EFAULT;
+int i810_rstatus(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 
-       sarea_priv->last_dispatch = (int) hw_status[5];
+       return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
+}
 
+int i810_ov0_info(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       drm_i810_overlay_t data;
+
+       data.offset = dev_priv->overlay_offset;
+       data.physical = dev_priv->overlay_physical;
+       copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data));
        return 0;
 }
 
-int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
-               unsigned long arg)
+int i810_fstatus(struct inode *inode, struct file *filp,
+               unsigned int cmd, unsigned long arg)
 {
-       if(VM_DONTCOPY == 0) return 1;
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->dev;
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i810_fstatus called without lock held\n");
+               return -EINVAL;
+       }
+       return I810_READ(0x30008);
+}
+
+int i810_ov0_flip(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i810_ov0_flip called without lock held\n");
+               return -EINVAL;
+       }
+
+       //Tell the overlay to update
+       I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000);
+
        return 0;
 }
+
+
index 5d47adda2c63c702a092d9e22d1b64dead6e2cdf..bff616375b457d1ef06e3ceee325c5f4cbaae8ce 100644 (file)
@@ -88,6 +88,8 @@
 #define I810_TEXREG_MCS  7     /* GFX_OP_MAP_COORD_SETS ??? */
 #define I810_TEX_SETUP_SIZE 8
 
+/* Flags for clear ioctl
+ */
 #define I810_FRONT   0x1
 #define I810_BACK    0x2
 #define I810_DEPTH   0x4
@@ -112,6 +114,8 @@ typedef struct _drm_i810_init {
        unsigned int front_offset;
        unsigned int back_offset;
        unsigned int depth_offset;
+       unsigned int overlay_offset;
+       unsigned int overlay_physical;
        unsigned int w;
        unsigned int h;
        unsigned int pitch;
@@ -189,6 +193,17 @@ typedef struct _drm_i810_copy_t {
        void *address;          /* Address to copy from */
 } drm_i810_copy_t;
 
+#define PR_TRIANGLES         (0x0<<18)
+#define PR_TRISTRIP_0        (0x1<<18)
+#define PR_TRISTRIP_1        (0x2<<18)
+#define PR_TRIFAN            (0x3<<18)
+#define PR_POLYGON           (0x4<<18)
+#define PR_LINES             (0x5<<18)
+#define PR_LINESTRIP         (0x6<<18)
+#define PR_RECTS             (0x7<<18)
+#define PR_MASK              (0x7<<18)
+
+
 typedef struct drm_i810_dma {
        void *virtual;
        int request_idx;
@@ -196,4 +211,18 @@ typedef struct drm_i810_dma {
        int granted;
 } drm_i810_dma_t;
 
+typedef struct _drm_i810_overlay_t {
+       unsigned int offset;    /* Address of the Overlay Regs */
+       unsigned int physical;
+} drm_i810_overlay_t;
+
+typedef struct _drm_i810_mc {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       int num_blocks;         /* number of GFXBlocks */
+       int *length;            /* List of lengths for GFXBlocks (FUTURE)*/
+       unsigned int last_render; /* Last Render Request */
+} drm_i810_mc_t;
+
+
 #endif /* _I810_DRM_H_ */
index a228cb466193ad53924d79907b2f4d1dda8c5bbf..f792e37818bd609dd88046209839af5081043159 100644 (file)
 
 #define DRIVER_NAME            "i810"
 #define DRIVER_DESC            "Intel i810"
-#define DRIVER_DATE            "20010616"
+#define DRIVER_DATE            "20020211"
 
+/* Interface history
+ *
+ * 1.1   - XFree86 4.1
+ * 1.2   - XvMC interfaces
+ *       - XFree86 4.2
+ * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
+ *       - Remove requirement for interrupt (leave stubs again)
+ */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      0
+#define DRIVER_MINOR           2
+#define DRIVER_PATCHLEVEL      1
 
 #define DRIVER_IOCTLS                                                      \
        [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)]   = { i810_dma_init,    1, 1 }, \
        [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf,      1, 0 }, \
        [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)]   = { i810_swap_bufs,   1, 0 }, \
        [DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)]   = { i810_copybuf,     1, 0 }, \
-       [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy,      1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy,      1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0INFO)] = { i810_ov0_info,   1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus,    1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip,   1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_MC)]      = { i810_dma_mc,     1, 1 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }
 
 
 #define __HAVE_COUNTERS         4
index e1b17148e9412837cd2952f093a9eb12fbf0259c..99165cf81e569d9937f5b70bfd28224f6a035111 100644 (file)
@@ -64,8 +64,6 @@ typedef struct drm_i810_private {
        unsigned long hw_status_page;
        unsigned long counter;
 
-       atomic_t flush_done;
-       wait_queue_head_t flush_queue;  /* Processes waiting until flush    */
        drm_buf_t *mmap_buffer;
 
 
@@ -73,8 +71,11 @@ typedef struct drm_i810_private {
 
        int back_offset;
        int depth_offset;
+       int overlay_offset;
+       int overlay_physical;
        int w, h;
        int pitch;
+
 } drm_i810_private_t;
 
                                /* i810_dma.c */
@@ -89,15 +90,29 @@ extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid);
 extern int  i810_getage(struct inode *inode, struct file *filp,
                        unsigned int cmd, unsigned long arg);
 extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
+
+/* Obsolete:
+ */
 extern int i810_copybuf(struct inode *inode, struct file *filp,
                        unsigned int cmd, unsigned long arg);
+/* Obsolete:
+ */
 extern int i810_docopy(struct inode *inode, struct file *filp,
                       unsigned int cmd, unsigned long arg);
 
-extern void i810_dma_quiescent(drm_device_t *dev);
+extern int i810_rstatus(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
+extern int i810_ov0_info(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
+extern int i810_fstatus(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
+extern int i810_ov0_flip(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
+extern int i810_dma_mc(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
 
-#define I810_VERBOSE 0
 
+extern void i810_dma_quiescent(drm_device_t *dev);
 
 int i810_dma_vertex(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long arg);
diff --git a/drivers/char/drm/i830.h b/drivers/char/drm/i830.h
new file mode 100644 (file)
index 0000000..fb7a0b3
--- /dev/null
@@ -0,0 +1,116 @@
+/* i830.h -- Intel I830 DRM template customization -*- linux-c -*-
+ * Created: Thu Feb 15 00:01:12 2001 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
+ * VA LINUX SYSTEMS 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>
+ */
+
+#ifndef __I830_H__
+#define __I830_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) i830_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP             1
+#define __MUST_HAVE_AGP                1
+#define __HAVE_MTRR            1
+#define __HAVE_CTX_BITMAP      1
+
+/* Driver customization:
+ */
+#define __HAVE_RELEASE         1
+#define DRIVER_RELEASE() do {                                          \
+       i830_reclaim_buffers( dev, priv->pid );                         \
+} while (0)
+
+/* DMA customization:
+ */
+#define __HAVE_DMA             1
+#define __HAVE_DMA_QUEUE       1
+#define __HAVE_DMA_WAITLIST    1
+#define __HAVE_DMA_RECLAIM     1
+
+#define __HAVE_DMA_QUIESCENT   1
+#define DRIVER_DMA_QUIESCENT() do {                                    \
+       i830_dma_quiescent( dev );                                      \
+} while (0)
+
+#define __HAVE_DMA_IRQ         1
+#define __HAVE_DMA_IRQ_BH      1
+#define __HAVE_SHARED_IRQ       1
+#define DRIVER_PREINSTALL() do {                                       \
+       drm_i830_private_t *dev_priv =                                  \
+               (drm_i830_private_t *)dev->dev_private;                 \
+       u16 tmp;                                                        \
+       tmp = I830_READ16( I830REG_HWSTAM );                            \
+       tmp = tmp & 0x6000;                                             \
+       I830_WRITE16( I830REG_HWSTAM, tmp );                            \
+                                                                       \
+       tmp = I830_READ16( I830REG_INT_MASK_R );                        \
+       tmp = tmp & 0x6000;             /* Unmask interrupts */         \
+       I830_WRITE16( I830REG_INT_MASK_R, tmp );                        \
+       tmp = I830_READ16( I830REG_INT_ENABLE_R );                      \
+       tmp = tmp & 0x6000;             /* Disable all interrupts */    \
+       I830_WRITE16( I830REG_INT_ENABLE_R, tmp );                      \
+} while (0)
+
+#define DRIVER_POSTINSTALL() do {                                      \
+       drm_i830_private_t *dev_priv =                                  \
+               (drm_i830_private_t *)dev->dev_private; \
+       u16 tmp;                                                        \
+       tmp = I830_READ16( I830REG_INT_ENABLE_R );                      \
+       tmp = tmp & 0x6000;                                             \
+       tmp = tmp | 0x0003;     /* Enable bp & user interrupts */       \
+       I830_WRITE16( I830REG_INT_ENABLE_R, tmp );                      \
+} while (0)
+
+#define DRIVER_UNINSTALL() do {                                                \
+       drm_i830_private_t *dev_priv =                                  \
+               (drm_i830_private_t *)dev->dev_private;                 \
+       u16 tmp;                                                        \
+       if ( dev_priv ) {                                               \
+               tmp = I830_READ16( I830REG_INT_IDENTITY_R );            \
+               tmp = tmp & ~(0x6000);  /* Clear all interrupts */      \
+               if ( tmp != 0 )                                         \
+                       I830_WRITE16( I830REG_INT_IDENTITY_R, tmp );    \
+                                                                       \
+               tmp = I830_READ16( I830REG_INT_ENABLE_R );              \
+               tmp = tmp & 0x6000;     /* Disable all interrupts */    \
+               I830_WRITE16( I830REG_INT_ENABLE_R, tmp );              \
+       }                                                               \
+} while (0)
+
+/* Buffer customization:
+ */
+
+#define DRIVER_BUF_PRIV_T      drm_i830_buf_priv_t
+
+#define DRIVER_AGP_BUFFERS_MAP( dev )                                  \
+       ((drm_i830_private_t *)((dev)->dev_private))->buffer_map
+
+#endif
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
new file mode 100644 (file)
index 0000000..a0a6185
--- /dev/null
@@ -0,0 +1,1423 @@
+/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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: Rickard E. (Rik) Faith <faith@valinux.com>
+ *         Jeff Hartmann <jhartmann@valinux.com>
+ *      Keith Whitwell <keithw@valinux.com>
+ *      Abraham vd Merwe <abraham@2d3d.co.za>
+ *
+ */
+
+#define __NO_VERSION__
+#include "i830.h"
+#include "drmP.h"
+#include "i830_drv.h"
+#include <linux/interrupt.h>   /* For task queue support */
+
+/* in case we don't have a 2.3.99-pre6 kernel or later: */
+#ifndef VM_DONTCOPY
+#define VM_DONTCOPY 0
+#endif
+
+#define I830_BUF_FREE          2
+#define I830_BUF_CLIENT                1
+#define I830_BUF_HARDWARE              0
+
+#define I830_BUF_UNMAPPED 0
+#define I830_BUF_MAPPED   1
+
+#define RING_LOCALS    unsigned int outring, ringmask; volatile char *virt;
+
+
+#define DO_IDLE_WORKAROUND()                                   \
+do {                                                           \
+   int _head;                                                  \
+   int _tail;                                                  \
+   int _i;                                                     \
+   do {                                                        \
+      _head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;      \
+      _tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;      \
+      udelay(10);                                              \
+   } while(_head != _tail);                                    \
+} while(0)
+
+#define I830_SYNC_WORKAROUND 0
+
+#define BEGIN_LP_RING(n) do {                          \
+       if (I830_VERBOSE)                               \
+               DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",  \
+                         n, __FUNCTION__);             \
+       if (I830_SYNC_WORKAROUND)                       \
+               DO_IDLE_WORKAROUND();                   \
+       if (dev_priv->ring.space < n*4)                 \
+               i830_wait_ring(dev, n*4);               \
+       dev_priv->ring.space -= n*4;                    \
+       outring = dev_priv->ring.tail;                  \
+       ringmask = dev_priv->ring.tail_mask;            \
+       virt = dev_priv->ring.virtual_start;            \
+} while (0)
+
+#define ADVANCE_LP_RING() do {                                 \
+       if (I830_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");       \
+       dev_priv->ring.tail = outring;                          \
+       I830_WRITE(LP_RING + RING_TAIL, outring);               \
+} while(0)
+
+#define OUT_RING(n) do {                                               \
+       if (I830_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
+       *(volatile unsigned int *)(virt + outring) = n;                 \
+       outring += 4;                                                   \
+       outring &= ringmask;                                            \
+} while (0)
+
+static inline void i830_print_status_page(drm_device_t *dev)
+{
+       drm_device_dma_t *dma = dev->dma;
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       u32 *temp = (u32 *)dev_priv->hw_status_page;
+       int i;
+
+       DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
+       DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
+       DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
+       DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
+       DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
+       for(i = 9; i < dma->buf_count + 9; i++) {
+               DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 9, temp[i]);
+       }
+}
+
+static drm_buf_t *i830_freelist_get(drm_device_t *dev)
+{
+       drm_device_dma_t *dma = dev->dma;
+       int              i;
+       int              used;
+   
+       /* Linear search might not be the best solution */
+
+       for (i = 0; i < dma->buf_count; i++) {
+               drm_buf_t *buf = dma->buflist[ i ];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+               /* In use is already a pointer */
+               used = cmpxchg(buf_priv->in_use, I830_BUF_FREE, 
+                              I830_BUF_CLIENT);
+               if(used == I830_BUF_FREE) {
+                       return buf;
+               }
+       }
+       return NULL;
+}
+
+/* This should only be called if the buffer is not sent to the hardware
+ * yet, the hardware updates in use for us once its on the ring buffer.
+ */
+
+static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
+{
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       int used;
+   
+       /* In use is already a pointer */
+       used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
+       if(used != I830_BUF_CLIENT) {
+               DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+               return -EINVAL;
+       }
+   
+       return 0;
+}
+
+static struct file_operations i830_buffer_fops = {
+       open:    DRM(open),
+       flush:   DRM(flush),
+       release: DRM(release),
+       ioctl:   DRM(ioctl),
+       mmap:    i830_mmap_buffers,
+       read:    DRM(read),
+       fasync:  DRM(fasync),
+       poll:    DRM(poll),
+};
+
+int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+{
+       drm_file_t          *priv         = filp->private_data;
+       drm_device_t        *dev;
+       drm_i830_private_t  *dev_priv;
+       drm_buf_t           *buf;
+       drm_i830_buf_priv_t *buf_priv;
+
+       lock_kernel();
+       dev      = priv->dev;
+       dev_priv = dev->dev_private;
+       buf      = dev_priv->mmap_buffer;
+       buf_priv = buf->dev_private;
+   
+       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+       vma->vm_file = filp;
+   
+       buf_priv->currently_mapped = I830_BUF_MAPPED;
+       unlock_kernel();
+
+       if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
+                            VM_OFFSET(vma),
+                            vma->vm_end - vma->vm_start,
+                            vma->vm_page_prot)) return -EAGAIN;
+       return 0;
+}
+
+static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
+{
+       drm_file_t        *priv   = filp->private_data;
+       drm_device_t      *dev    = priv->dev;
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       struct file_operations *old_fops;
+       int retcode = 0;
+
+       if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL;
+
+       if(VM_DONTCOPY != 0) {
+#if LINUX_VERSION_CODE <= 0x020402
+               down( &current->mm->mmap_sem );
+#else
+               down_write( &current->mm->mmap_sem );
+#endif
+               old_fops = filp->f_op;
+               filp->f_op = &i830_buffer_fops;
+               dev_priv->mmap_buffer = buf;
+               buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, 
+                                                   PROT_READ|PROT_WRITE,
+                                                   MAP_SHARED, 
+                                                   buf->bus_address);
+               dev_priv->mmap_buffer = NULL;
+               filp->f_op = old_fops;
+               if ((unsigned long)buf_priv->virtual > -1024UL) {
+                       /* Real error */
+                       DRM_DEBUG("mmap error\n");
+                       retcode = (signed int)buf_priv->virtual;
+                       buf_priv->virtual = 0;
+               }
+#if LINUX_VERSION_CODE <= 0x020402
+               up( &current->mm->mmap_sem );
+#else
+               up_write( &current->mm->mmap_sem );
+#endif
+       } else {
+               buf_priv->virtual = buf_priv->kernel_virtual;
+               buf_priv->currently_mapped = I830_BUF_MAPPED;
+       }
+       return retcode;
+}
+
+static int i830_unmap_buffer(drm_buf_t *buf)
+{
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       int retcode = 0;
+
+       if(VM_DONTCOPY != 0) {
+               if(buf_priv->currently_mapped != I830_BUF_MAPPED) 
+                       return -EINVAL;
+#if LINUX_VERSION_CODE <= 0x020402
+               down( &current->mm->mmap_sem );
+#else
+               down_write( &current->mm->mmap_sem );
+#endif
+
+               retcode = do_munmap(current->mm, 
+                                   (unsigned long)buf_priv->virtual, 
+                                   (size_t) buf->total);
+
+#if LINUX_VERSION_CODE <= 0x020402
+               up( &current->mm->mmap_sem );
+#else
+               up_write( &current->mm->mmap_sem );
+#endif
+       }
+       buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+       buf_priv->virtual = 0;
+
+       return retcode;
+}
+
+static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, 
+                              struct file *filp)
+{
+       drm_file_t        *priv   = filp->private_data;
+       drm_buf_t         *buf;
+       drm_i830_buf_priv_t *buf_priv;
+       int retcode = 0;
+
+       buf = i830_freelist_get(dev);
+       if (!buf) {
+               retcode = -ENOMEM;
+               DRM_DEBUG("retcode=%d\n", retcode);
+               return retcode;
+       }
+   
+       retcode = i830_map_buffer(buf, filp);
+       if(retcode) {
+               i830_freelist_put(dev, buf);
+               DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
+               return retcode;
+       }
+       buf->pid     = priv->pid;
+       buf_priv = buf->dev_private;    
+       d->granted = 1;
+       d->request_idx = buf->idx;
+       d->request_size = buf->total;
+       d->virtual = buf_priv->virtual;
+
+       return retcode;
+}
+
+static unsigned long i830_alloc_page(drm_device_t *dev)
+{
+       unsigned long address;
+   
+       address = __get_free_page(GFP_KERNEL);
+       if(address == 0UL) 
+               return 0;
+       
+#if LINUX_VERSION_CODE < 0x020500
+       atomic_inc(&virt_to_page(address)->count);
+       set_bit(PG_locked, &virt_to_page(address)->flags);
+#else
+       get_page(virt_to_page(address));
+       SetPageLocked(virt_to_page(address));
+#endif
+       return address;
+}
+
+static void i830_free_page(drm_device_t *dev, unsigned long page)
+{
+       if (page) {
+#if LINUX_VERSION_CODE < 0x020500
+               atomic_dec(&virt_to_page(page)->count);
+               clear_bit(PG_locked, &virt_to_page(page)->flags);
+               wake_up(&virt_to_page(page)->wait);
+#else
+               struct page *p = virt_to_page(page);
+               put_page(p);
+               unlock_page(p);
+#endif
+               free_page(page);
+       }
+}
+
+static int i830_dma_cleanup(drm_device_t *dev)
+{
+       drm_device_dma_t *dma = dev->dma;
+
+       if(dev->dev_private) {
+               int i;
+               drm_i830_private_t *dev_priv = 
+                       (drm_i830_private_t *) dev->dev_private;
+          
+               if(dev_priv->ring.virtual_start) {
+                       DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
+                                        dev_priv->ring.Size);
+               }
+               if(dev_priv->hw_status_page != 0UL) {
+                       i830_free_page(dev, dev_priv->hw_status_page);
+                       /* Need to rewrite hardware status page */
+                       I830_WRITE(0x02080, 0x1ffff000);
+               }
+               DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), 
+                        DRM_MEM_DRIVER);
+               dev->dev_private = NULL;
+
+               for (i = 0; i < dma->buf_count; i++) {
+                       drm_buf_t *buf = dma->buflist[ i ];
+                       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+                       DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total);
+               }
+       }
+       return 0;
+}
+
+static int i830_wait_ring(drm_device_t *dev, int n)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+       int iters = 0;
+       unsigned long end;
+       unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+
+       end = jiffies + (HZ*3);
+       while (ring->space < n) {
+               int i;
+       
+               ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+               ring->space = ring->head - (ring->tail+8);
+               if (ring->space < 0) ring->space += ring->Size;
+          
+               if (ring->head != last_head) {
+                       end = jiffies + (HZ*3);
+                       last_head = ring->head;
+               }
+         
+               iters++;
+               if((signed)(end - jiffies) <= 0) {
+                       DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+                       DRM_ERROR("lockup\n");
+                       goto out_wait_ring;
+               }
+
+               udelay(1);
+       }
+
+out_wait_ring:   
+       return iters;
+}
+
+static void i830_kernel_lost_context(drm_device_t *dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+      
+       ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+       ring->tail = I830_READ(LP_RING + RING_TAIL);
+       ring->space = ring->head - (ring->tail+8);
+       if (ring->space < 0) ring->space += ring->Size;
+}
+
+static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
+{
+       drm_device_dma_t *dma = dev->dma;
+       int my_idx = 36;
+       u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
+       int i;
+
+       if(dma->buf_count > 1019) {
+               /* Not enough space in the status page for the freelist */
+               return -EINVAL;
+       }
+
+       for (i = 0; i < dma->buf_count; i++) {
+               drm_buf_t *buf = dma->buflist[ i ];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+
+               buf_priv->in_use = hw_status++;
+               buf_priv->my_use_idx = my_idx;
+               my_idx += 4;
+
+               *buf_priv->in_use = I830_BUF_FREE;
+
+               buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, 
+                                                       buf->total);
+       }
+       return 0;
+}
+
+static int i830_dma_initialize(drm_device_t *dev, 
+                              drm_i830_private_t *dev_priv,
+                              drm_i830_init_t *init)
+{
+       struct list_head *list;
+
+       memset(dev_priv, 0, sizeof(drm_i830_private_t));
+
+       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_map = r_list->map;
+                       break;
+               }
+       }
+
+       if(!dev_priv->sarea_map) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not find sarea!\n");
+               return -EINVAL;
+       }
+       DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+       if(!dev_priv->mmio_map) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not find mmio map!\n");
+               return -EINVAL;
+       }
+       DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
+       if(!dev_priv->buffer_map) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not find dma buffer map!\n");
+               return -EINVAL;
+       }
+
+       dev_priv->sarea_priv = (drm_i830_sarea_t *)
+               ((u8 *)dev_priv->sarea_map->handle +
+                init->sarea_priv_offset);
+
+       atomic_set(&dev_priv->flush_done, 0);
+       init_waitqueue_head(&dev_priv->flush_queue);
+
+       dev_priv->ring.Start = init->ring_start;
+       dev_priv->ring.End = init->ring_end;
+       dev_priv->ring.Size = init->ring_size;
+
+       dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + 
+                                                   init->ring_start, 
+                                                   init->ring_size);
+
+       if (dev_priv->ring.virtual_start == NULL) {
+               dev->dev_private = (void *) dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return -ENOMEM;
+       }
+
+       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+   
+       dev_priv->w = init->w;
+       dev_priv->h = init->h;
+       dev_priv->pitch = init->pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->depth_offset = init->depth_offset;
+
+       dev_priv->front_di1 = init->front_offset | init->pitch_bits;
+       dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+       dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+
+       dev_priv->cpp = init->cpp;
+       /* We are using seperate values as placeholders for mechanisms for
+        * private backbuffer/depthbuffer usage.
+        */
+
+       dev_priv->back_pitch = init->back_pitch;
+       dev_priv->depth_pitch = init->depth_pitch;
+
+       /* Program Hardware Status Page */
+       dev_priv->hw_status_page = i830_alloc_page(dev);
+       if(dev_priv->hw_status_page == 0UL) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("Can not allocate hardware status page\n");
+               return -ENOMEM;
+       }
+       memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
+       DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
+   
+       I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
+       DRM_DEBUG("Enabled hardware status page\n");
+   
+       /* Now we need to init our freelist */
+       if(i830_freelist_init(dev, dev_priv) != 0) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("Not enough space in the status page for"
+                         " the freelist\n");
+               return -ENOMEM;
+       }
+       dev->dev_private = (void *)dev_priv;
+
+       return 0;
+}
+
+int i830_dma_init(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_i830_private_t *dev_priv;
+       drm_i830_init_t init;
+       int retcode = 0;
+       
+       if (copy_from_user(&init, (drm_i830_init_t *)arg, sizeof(init)))
+               return -EFAULT;
+       
+       switch(init.func) {
+               case I830_INIT_DMA:
+                       dev_priv = DRM(alloc)(sizeof(drm_i830_private_t), 
+                                             DRM_MEM_DRIVER);
+                       if(dev_priv == NULL) return -ENOMEM;
+                       retcode = i830_dma_initialize(dev, dev_priv, &init);
+               break;
+               case I830_CLEANUP_DMA:
+                       retcode = i830_dma_cleanup(dev);
+               break;
+               default:
+                       retcode = -EINVAL;
+               break;
+       }
+   
+       return retcode;
+}
+
+/* Most efficient way to verify state for the i830 is as it is
+ * emitted.  Non-conformant state is silently dropped.
+ *
+ * Use 'volatile' & local var tmp to force the emitted values to be
+ * identical to the verified ones.
+ */
+static void i830EmitContextVerified( drm_device_t *dev, 
+                                    volatile unsigned int *code )
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I830_CTX_SETUP_SIZE );
+       for ( i = 0 ; i < I830_CTX_SETUP_SIZE ; i++ ) {
+               tmp = code[i];
+
+#if 0
+               if ((tmp & (7<<29)) == (3<<29) &&
+                   (tmp & (0x1f<<24)) < (0x1d<<24)) {
+                       OUT_RING( tmp ); 
+                       j++;
+               } else {
+                       printk("Skipping %d\n", i);
+               }
+#else
+               OUT_RING( tmp ); 
+               j++;
+#endif
+       }
+
+       if (j & 1) 
+               OUT_RING( 0 ); 
+
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitTexVerified( drm_device_t *dev, 
+                                volatile unsigned int *code ) 
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
+
+       OUT_RING( GFX_OP_MAP_INFO );
+       OUT_RING( code[I830_TEXREG_MI1] );
+       OUT_RING( code[I830_TEXREG_MI2] );
+       OUT_RING( code[I830_TEXREG_MI3] );
+       OUT_RING( code[I830_TEXREG_MI4] );
+       OUT_RING( code[I830_TEXREG_MI5] );
+
+       for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
+               tmp = code[i];
+               OUT_RING( tmp ); 
+               j++;
+       } 
+
+       if (j & 1) 
+               OUT_RING( 0 ); 
+
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitTexBlendVerified( drm_device_t *dev, 
+                                    volatile unsigned int *code,
+                                    volatile unsigned int num)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( num );
+
+       for ( i = 0 ; i < num ; i++ ) {
+               tmp = code[i];
+               OUT_RING( tmp );
+               j++;
+       }
+
+       if (j & 1) 
+               OUT_RING( 0 ); 
+
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitTexPalette( drm_device_t *dev,
+                               unsigned int *palette,
+                               int number,
+                               int is_shared )
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( 258 );
+
+       if(is_shared == 1) {
+               OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
+                        MAP_PALETTE_NUM(0) |
+                        MAP_PALETTE_BOTH);
+       } else {
+               OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
+       }
+       for(i = 0; i < 256; i++) {
+               OUT_RING(palette[i]);
+       }
+       OUT_RING(0);
+}
+
+/* Need to do some additional checking when setting the dest buffer.
+ */
+static void i830EmitDestVerified( drm_device_t *dev, 
+                                 volatile unsigned int *code ) 
+{      
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 6 );
+
+       tmp = code[I830_DESTREG_CBUFADDR];
+       if (tmp == dev_priv->front_di1) {
+               /* Don't use fence when front buffer rendering */
+               OUT_RING( CMD_OP_DESTBUFFER_INFO );
+               OUT_RING( BUF_3D_ID_COLOR_BACK | 
+                         BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) );
+               OUT_RING( tmp );
+
+               OUT_RING( CMD_OP_DESTBUFFER_INFO );
+               OUT_RING( BUF_3D_ID_DEPTH |
+                         BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
+               OUT_RING( dev_priv->zi1 );
+       } else if(tmp == dev_priv->back_di1) {
+               OUT_RING( CMD_OP_DESTBUFFER_INFO );
+               OUT_RING( BUF_3D_ID_COLOR_BACK | 
+                         BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
+                         BUF_3D_USE_FENCE);
+               OUT_RING( tmp );
+
+               OUT_RING( CMD_OP_DESTBUFFER_INFO );
+               OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | 
+                         BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
+               OUT_RING( dev_priv->zi1 );
+       } else {
+               DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+                         tmp, dev_priv->front_di1, dev_priv->back_di1);
+       }
+
+       /* invarient:
+        */
+
+
+       OUT_RING( GFX_OP_DESTBUFFER_VARS );
+       OUT_RING( code[I830_DESTREG_DV1] );
+
+       OUT_RING( GFX_OP_DRAWRECT_INFO );
+       OUT_RING( code[I830_DESTREG_DR1] );
+       OUT_RING( code[I830_DESTREG_DR2] );
+       OUT_RING( code[I830_DESTREG_DR3] );
+       OUT_RING( code[I830_DESTREG_DR4] );
+
+       /* Need to verify this */
+       tmp = code[I830_DESTREG_SENABLE];
+       if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
+               OUT_RING( tmp );
+       } else {
+               DRM_DEBUG("bad scissor enable\n");
+               OUT_RING( 0 );
+       }
+
+       OUT_RING( code[I830_DESTREG_SENABLE] );
+
+       OUT_RING( GFX_OP_SCISSOR_RECT );
+       OUT_RING( code[I830_DESTREG_SR1] );
+       OUT_RING( code[I830_DESTREG_SR2] );
+
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitState( drm_device_t *dev )
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
+
+       if (dirty & I830_UPLOAD_BUFFERS) {
+               i830EmitDestVerified( dev, sarea_priv->BufferState );
+               sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
+       }
+
+       if (dirty & I830_UPLOAD_CTX) {
+               i830EmitContextVerified( dev, sarea_priv->ContextState );
+               sarea_priv->dirty &= ~I830_UPLOAD_CTX;
+       }
+
+       if (dirty & I830_UPLOAD_TEX0) {
+               i830EmitTexVerified( dev, sarea_priv->TexState[0] );
+               sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
+       }
+
+       if (dirty & I830_UPLOAD_TEX1) {
+               i830EmitTexVerified( dev, sarea_priv->TexState[1] );
+               sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
+       }
+
+       if (dirty & I830_UPLOAD_TEXBLEND0) {
+               i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[0],
+                               sarea_priv->TexBlendStateWordsUsed[0]);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
+       }
+
+       if (dirty & I830_UPLOAD_TEXBLEND1) {
+               i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[1],
+                               sarea_priv->TexBlendStateWordsUsed[1]);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
+       }
+
+       if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
+          i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
+       } else {
+          if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
+             i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
+             sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
+          }
+          if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
+             i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
+             sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
+          }
+       }
+}
+
+static void i830_dma_dispatch_clear( drm_device_t *dev, int flags, 
+                                   unsigned int clear_color,
+                                   unsigned int clear_zval,
+                                   unsigned int clear_depthmask)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = dev_priv->cpp;
+       int i;
+       unsigned int BR13, CMD, D_CMD;
+       RING_LOCALS;
+
+       i830_kernel_lost_context(dev);
+
+       switch(cpp) {
+       case 2: 
+               BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
+               D_CMD = CMD = XY_COLOR_BLT_CMD;
+               break;
+       case 4:
+               BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
+               CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | 
+                      XY_COLOR_BLT_WRITE_RGB);
+               D_CMD = XY_COLOR_BLT_CMD;
+               if(clear_depthmask & 0x00ffffff)
+                       D_CMD |= XY_COLOR_BLT_WRITE_RGB;
+               if(clear_depthmask & 0xff000000)
+                       D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
+               break;
+       default:
+               BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
+               D_CMD = CMD = XY_COLOR_BLT_CMD;
+               break;
+       }
+
+       if (nbox > I830_NR_SAREA_CLIPRECTS)
+               nbox = I830_NR_SAREA_CLIPRECTS;
+
+       for (i = 0 ; i < nbox ; i++, pbox++) {
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w ||
+                   pbox->y2 > dev_priv->h)
+                       continue;
+
+               if ( flags & I830_FRONT ) {         
+                       DRM_DEBUG("clear front\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( CMD );
+                       OUT_RING( BR13 );
+                       OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+                       OUT_RING( (pbox->y2 << 16) | pbox->x2 );
+                       OUT_RING( 0 );
+                       OUT_RING( clear_color );
+                       ADVANCE_LP_RING();
+               }
+
+               if ( flags & I830_BACK ) {
+                       DRM_DEBUG("clear back\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( CMD );
+                       OUT_RING( BR13 );
+                       OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+                       OUT_RING( (pbox->y2 << 16) | pbox->x2 );
+                       OUT_RING( dev_priv->back_offset );
+                       OUT_RING( clear_color );
+                       ADVANCE_LP_RING();
+               }
+
+               if ( flags & I830_DEPTH ) {
+                       DRM_DEBUG("clear depth\n");
+                       BEGIN_LP_RING( 6 );
+                       OUT_RING( D_CMD );
+                       OUT_RING( BR13 );
+                       OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+                       OUT_RING( (pbox->y2 << 16) | pbox->x2 );
+                       OUT_RING( dev_priv->depth_offset );
+                       OUT_RING( clear_zval );
+                       ADVANCE_LP_RING();
+               }
+       }
+}
+
+static void i830_dma_dispatch_swap( drm_device_t *dev )
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = dev_priv->cpp;
+       int ofs = dev_priv->back_offset;
+       int i;
+       unsigned int CMD, BR13;
+       RING_LOCALS;
+
+       DRM_DEBUG("swapbuffers\n");
+
+       switch(cpp) {
+       case 2: 
+               BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
+               CMD = XY_SRC_COPY_BLT_CMD;
+               break;
+       case 4:
+               BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
+               CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+                      XY_SRC_COPY_BLT_WRITE_RGB);
+               break;
+       default:
+               BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
+               CMD = XY_SRC_COPY_BLT_CMD;
+               break;
+       }
+
+       i830_kernel_lost_context(dev);
+
+       if (nbox > I830_NR_SAREA_CLIPRECTS)
+               nbox = I830_NR_SAREA_CLIPRECTS;
+
+       for (i = 0 ; i < nbox; i++, pbox++) 
+       {
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w ||
+                   pbox->y2 > dev_priv->h)
+                       continue;
+               DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+                         pbox->x1, pbox->y1,
+                         pbox->x2, pbox->y2);
+
+               BEGIN_LP_RING( 8 );
+               OUT_RING( CMD );
+               OUT_RING( BR13 );
+
+               OUT_RING( (pbox->y1 << 16) |
+                         pbox->x1 );
+               OUT_RING( (pbox->y2 << 16) |
+                         pbox->x2 );
+
+               OUT_RING( 0 /* front ofs always zero */ );
+               OUT_RING( (pbox->y1 << 16) |
+                         pbox->x1 );
+
+               OUT_RING( BR13 & 0xffff );
+               OUT_RING( ofs );
+
+               ADVANCE_LP_RING();
+       }
+}
+
+
+static void i830_dma_dispatch_vertex(drm_device_t *dev, 
+                                    drm_buf_t *buf,
+                                    int discard,
+                                    int used)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_clip_rect_t *box = sarea_priv->boxes;
+       int nbox = sarea_priv->nbox;
+       unsigned long address = (unsigned long)buf->bus_address;
+       unsigned long start = address - dev->agp->base;     
+       int i = 0, u;
+       RING_LOCALS;
+
+       i830_kernel_lost_context(dev);
+
+       if (nbox > I830_NR_SAREA_CLIPRECTS) 
+               nbox = I830_NR_SAREA_CLIPRECTS;
+
+       if (discard) {
+               u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 
+                           I830_BUF_HARDWARE);
+               if(u != I830_BUF_CLIENT) {
+                       DRM_DEBUG("xxxx 2\n");
+               }
+       }
+
+       if (used > 4*1024) 
+               used = 0;
+
+       if (sarea_priv->dirty)
+          i830EmitState( dev );
+
+       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 
+                 address, used, nbox);
+
+       dev_priv->counter++;
+       DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);
+       DRM_DEBUG(  "i830_dma_dispatch\n");
+       DRM_DEBUG(  "start : %lx\n", start);
+       DRM_DEBUG(  "used : %d\n", used);
+       DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
+
+       if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
+               *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
+                                            sarea_priv->vertex_prim |
+                                            ((used/4)-2));
+               
+               if (used & 4) {
+                       *(u32 *)((u32)buf_priv->virtual + used) = 0;
+                       used += 4;
+               }
+
+               i830_unmap_buffer(buf);
+       }
+                  
+       if (used) {
+               do {
+                       if (i < nbox) {
+                               BEGIN_LP_RING(6);
+                               OUT_RING( GFX_OP_DRAWRECT_INFO );
+                               OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] );
+                               OUT_RING( box[i].x1 | (box[i].y1<<16) );
+                               OUT_RING( box[i].x2 | (box[i].y2<<16) );
+                               OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] );
+                               OUT_RING( 0 );
+                               ADVANCE_LP_RING();
+                       }
+
+                       BEGIN_LP_RING(4);
+
+                       OUT_RING( MI_BATCH_BUFFER );
+                       OUT_RING( start | MI_BATCH_NON_SECURE );
+                       OUT_RING( start + used - 4 );
+                       OUT_RING( 0 );
+                       ADVANCE_LP_RING();
+                       
+               } while (++i < nbox);
+       }
+
+       BEGIN_LP_RING(10);
+       OUT_RING( CMD_STORE_DWORD_IDX );
+       OUT_RING( 20 );
+       OUT_RING( dev_priv->counter );
+       OUT_RING( 0 );
+
+       if (discard) {
+               OUT_RING( CMD_STORE_DWORD_IDX );
+               OUT_RING( buf_priv->my_use_idx );
+               OUT_RING( I830_BUF_FREE );
+               OUT_RING( 0 );
+       }
+
+       OUT_RING( CMD_REPORT_HEAD );
+       OUT_RING( 0 );
+       ADVANCE_LP_RING();
+}
+
+/* Interrupts are only for flushing */
+void i830_dma_service(int irq, void *device, struct pt_regs *regs)
+{
+       drm_device_t     *dev = (drm_device_t *)device;
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+       u16 temp;
+   
+       temp = I830_READ16(I830REG_INT_IDENTITY_R);
+       temp = temp & ~(0x6000);
+       if(temp != 0) I830_WRITE16(I830REG_INT_IDENTITY_R, 
+                                  temp); /* Clear all interrupts */
+       else
+          return;
+       queue_task(&dev->tq, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+}
+
+void DRM(dma_immediate_bh)(void *device)
+{
+       drm_device_t *dev = (drm_device_t *) device;
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+
+       atomic_set(&dev_priv->flush_done, 1);
+       wake_up_interruptible(&dev_priv->flush_queue);
+}
+
+static inline void i830_dma_emit_flush(drm_device_t *dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       i830_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(2);
+       OUT_RING( CMD_REPORT_HEAD );
+       OUT_RING( GFX_OP_USER_INTERRUPT );
+       ADVANCE_LP_RING();
+
+       i830_wait_ring( dev, dev_priv->ring.Size - 8 );
+       atomic_set(&dev_priv->flush_done, 1);
+       wake_up_interruptible(&dev_priv->flush_queue);
+}
+
+static inline void i830_dma_quiescent_emit(drm_device_t *dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       i830_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(4);
+       OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
+       OUT_RING( CMD_REPORT_HEAD );
+       OUT_RING( 0 );
+       OUT_RING( GFX_OP_USER_INTERRUPT );
+       ADVANCE_LP_RING();
+
+       i830_wait_ring( dev, dev_priv->ring.Size - 8 );
+       atomic_set(&dev_priv->flush_done, 1);
+       wake_up_interruptible(&dev_priv->flush_queue);
+}
+
+void i830_dma_quiescent(drm_device_t *dev)
+{
+       DECLARE_WAITQUEUE(entry, current);
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+       unsigned long end;      
+
+       if(dev_priv == NULL) {
+               return;
+       }
+       atomic_set(&dev_priv->flush_done, 0);
+       add_wait_queue(&dev_priv->flush_queue, &entry);
+       end = jiffies + (HZ*3);
+   
+       for (;;) {
+               current->state = TASK_INTERRUPTIBLE;
+               i830_dma_quiescent_emit(dev);
+               if (atomic_read(&dev_priv->flush_done) == 1) break;
+               if((signed)(end - jiffies) <= 0) {
+                       DRM_ERROR("lockup\n");
+                       break;
+               }          
+               schedule_timeout(HZ*3);
+               if (signal_pending(current)) {
+                       break;
+               }
+       }
+   
+       current->state = TASK_RUNNING;
+       remove_wait_queue(&dev_priv->flush_queue, &entry);
+   
+       return;
+}
+
+static int i830_flush_queue(drm_device_t *dev)
+{
+       DECLARE_WAITQUEUE(entry, current);
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
+       unsigned long end;
+       int i, ret = 0;      
+
+       if(dev_priv == NULL) {
+               return 0;
+       }
+       atomic_set(&dev_priv->flush_done, 0);
+       add_wait_queue(&dev_priv->flush_queue, &entry);
+       end = jiffies + (HZ*3);
+       for (;;) {
+               current->state = TASK_INTERRUPTIBLE;
+               i830_dma_emit_flush(dev);
+               if (atomic_read(&dev_priv->flush_done) == 1) break;
+               if((signed)(end - jiffies) <= 0) {
+                       DRM_ERROR("lockup\n");
+                       break;
+               }          
+               schedule_timeout(HZ*3);
+               if (signal_pending(current)) {
+                       ret = -EINTR; /* Can't restart */
+                       break;
+               }
+       }
+   
+       current->state = TASK_RUNNING;
+       remove_wait_queue(&dev_priv->flush_queue, &entry);
+
+
+       for (i = 0; i < dma->buf_count; i++) {
+               drm_buf_t *buf = dma->buflist[ i ];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+          
+               int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE, 
+                                  I830_BUF_FREE);
+
+               if (used == I830_BUF_HARDWARE)
+                       DRM_DEBUG("reclaimed from HARDWARE\n");
+               if (used == I830_BUF_CLIENT)
+                       DRM_DEBUG("still on client HARDWARE\n");
+       }
+
+       return ret;
+}
+
+/* Must be called with the lock held */
+void i830_reclaim_buffers(drm_device_t *dev, pid_t pid)
+{
+       drm_device_dma_t *dma = dev->dma;
+       int              i;
+
+       if (!dma) return;
+       if (!dev->dev_private) return;
+       if (!dma->buflist) return;
+
+        i830_flush_queue(dev);
+
+       for (i = 0; i < dma->buf_count; i++) {
+               drm_buf_t *buf = dma->buflist[ i ];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+          
+               if (buf->pid == pid && buf_priv) {
+                       int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 
+                                          I830_BUF_FREE);
+
+                       if (used == I830_BUF_CLIENT)
+                               DRM_DEBUG("reclaimed from client\n");
+                       if(buf_priv->currently_mapped == I830_BUF_MAPPED)
+                               buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+               }
+       }
+}
+
+int i830_flush_ioctl(struct inode *inode, struct file *filp, 
+                    unsigned int cmd, unsigned long arg)
+{
+       drm_file_t        *priv   = filp->private_data;
+       drm_device_t      *dev    = priv->dev;
+   
+       DRM_DEBUG("i830_flush_ioctl\n");
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i830_flush_ioctl called without lock held\n");
+               return -EINVAL;
+       }
+
+       i830_flush_queue(dev);
+       return 0;
+}
+
+int i830_dma_vertex(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_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
+                                       dev_priv->sarea_priv; 
+       drm_i830_vertex_t vertex;
+
+       if (copy_from_user(&vertex, (drm_i830_vertex_t *)arg, sizeof(vertex)))
+               return -EFAULT;
+
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i830_dma_vertex called without lock held\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
+                 vertex.idx, vertex.used, vertex.discard);
+
+       if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
+
+       i830_dma_dispatch_vertex( dev, 
+                                 dma->buflist[ vertex.idx ], 
+                                 vertex.discard, vertex.used );
+
+       sarea_priv->last_enqueue = dev_priv->counter-1;
+       sarea_priv->last_dispatch = (int) hw_status[5];
+   
+       return 0;
+}
+
+int i830_clear_bufs(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_i830_clear_t clear;
+
+       if (copy_from_user(&clear, (drm_i830_clear_t *)arg, sizeof(clear)))
+               return -EFAULT;
+   
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i830_clear_bufs called without lock held\n");
+               return -EINVAL;
+       }
+
+       /* GH: Someone's doing nasty things... */
+       if (!dev->dev_private) {
+               return -EINVAL;
+       }
+
+       i830_dma_dispatch_clear( dev, clear.flags, 
+                                clear.clear_color, 
+                                clear.clear_depth,
+                                clear.clear_depthmask);
+       return 0;
+}
+
+int i830_swap_bufs(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_DEBUG("i830_swap_bufs\n");
+
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i830_swap_buf called without lock held\n");
+               return -EINVAL;
+       }
+
+       i830_dma_dispatch_swap( dev );
+       return 0;
+}
+
+int i830_getage(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_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
+                                       dev_priv->sarea_priv; 
+
+       sarea_priv->last_dispatch = (int) hw_status[5];
+       return 0;
+}
+
+int i830_getbuf(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;
+       int               retcode   = 0;
+       drm_i830_dma_t    d;
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
+                                       dev_priv->sarea_priv; 
+
+       DRM_DEBUG("getbuf\n");
+       if (copy_from_user(&d, (drm_i830_dma_t *)arg, sizeof(d)))
+               return -EFAULT;
+   
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i830_dma called without lock held\n");
+               return -EINVAL;
+       }
+       
+       d.granted = 0;
+
+       retcode = i830_dma_get_buffer(dev, &d, filp);
+
+       DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
+                 current->pid, retcode, d.granted);
+
+       if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
+               return -EFAULT;
+       sarea_priv->last_dispatch = (int) hw_status[5];
+
+       return retcode;
+}
+
+int i830_copybuf(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_i830_copy_t   d;
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
+                                       dev_priv->sarea_priv; 
+       drm_buf_t *buf;
+       drm_i830_buf_priv_t *buf_priv;
+       drm_device_dma_t *dma = dev->dma;
+
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i830_dma called without lock held\n");
+               return -EINVAL;
+       }
+   
+       if (copy_from_user(&d, (drm_i830_copy_t *)arg, sizeof(d)))
+               return -EFAULT;
+
+       if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL;
+       buf = dma->buflist[ d.idx ];
+       buf_priv = buf->dev_private;
+       if (buf_priv->currently_mapped != I830_BUF_MAPPED) return -EPERM;
+
+       if(d.used < 0 || d.used > buf->total) return -EINVAL;
+
+       if (copy_from_user(buf_priv->virtual, d.address, d.used))
+               return -EFAULT;
+
+       sarea_priv->last_dispatch = (int) hw_status[5];
+
+       return 0;
+}
+
+int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+               unsigned long arg)
+{
+       if(VM_DONTCOPY == 0) return 1;
+       return 0;
+}
diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
new file mode 100644 (file)
index 0000000..e4a2a25
--- /dev/null
@@ -0,0 +1,238 @@
+#ifndef _I830_DRM_H_
+#define _I830_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _I830_DEFINES_
+#define _I830_DEFINES_
+
+#define I830_DMA_BUF_ORDER             12
+#define I830_DMA_BUF_SZ                (1<<I830_DMA_BUF_ORDER)
+#define I830_DMA_BUF_NR                256
+#define I830_NR_SAREA_CLIPRECTS        8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I830_NR_TEX_REGIONS 64
+#define I830_LOG_MIN_TEX_REGION_SIZE 16
+
+/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */
+#if !defined(I830_ENABLE_4_TEXTURES)
+#define I830_TEXTURE_COUNT     2
+#define I830_TEXBLEND_COUNT    2       /* always same as TEXTURE_COUNT? */
+#else /* defined(I830_ENABLE_4_TEXTURES) */
+#define I830_TEXTURE_COUNT     4
+#define I830_TEXBLEND_COUNT    4       /* always same as TEXTURE_COUNT? */
+#endif /* I830_ENABLE_4_TEXTURES */
+
+#define I830_TEXBLEND_SIZE     12      /* (4 args + op) * 2 + COLOR_FACTOR */
+
+#define I830_UPLOAD_CTX                        0x1
+#define I830_UPLOAD_BUFFERS            0x2
+#define I830_UPLOAD_CLIPRECTS          0x4
+#define I830_UPLOAD_TEX0_IMAGE         0x100 /* handled clientside */
+#define I830_UPLOAD_TEX0_CUBE          0x200 /* handled clientside */
+#define I830_UPLOAD_TEX1_IMAGE         0x400 /* handled clientside */
+#define I830_UPLOAD_TEX1_CUBE          0x800 /* handled clientside */
+#define I830_UPLOAD_TEX2_IMAGE         0x1000 /* handled clientside */
+#define I830_UPLOAD_TEX2_CUBE          0x2000 /* handled clientside */
+#define I830_UPLOAD_TEX3_IMAGE         0x4000 /* handled clientside */
+#define I830_UPLOAD_TEX3_CUBE          0x8000 /* handled clientside */
+#define I830_UPLOAD_TEX_N_IMAGE(n)     (0x100 << (n * 2))
+#define I830_UPLOAD_TEX_N_CUBE(n)      (0x200 << (n * 2))
+#define I830_UPLOAD_TEXIMAGE_MASK      0xff00
+#define I830_UPLOAD_TEX0                       0x10000
+#define I830_UPLOAD_TEX1                       0x20000
+#define I830_UPLOAD_TEX2                       0x40000
+#define I830_UPLOAD_TEX3                       0x80000
+#define I830_UPLOAD_TEX_N(n)           (0x10000 << (n))
+#define I830_UPLOAD_TEX_MASK           0xf0000
+#define I830_UPLOAD_TEXBLEND0          0x100000
+#define I830_UPLOAD_TEXBLEND1          0x200000
+#define I830_UPLOAD_TEXBLEND2          0x400000
+#define I830_UPLOAD_TEXBLEND3          0x800000
+#define I830_UPLOAD_TEXBLEND_N(n)      (0x100000 << (n))
+#define I830_UPLOAD_TEXBLEND_MASK      0xf00000
+#define I830_UPLOAD_TEX_PALETTE_N(n)    (0x1000000 << (n))
+#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer.  These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state 
+ *    - backbuffer linear offset and pitch -- invarient in the current dri
+ *    - zbuffer linear offset and pitch -- also invarient
+ *    - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to acommodate private buffers
+ * in the future.
+ */
+
+#define I830_DESTREG_CBUFADDR 0
+/* Invarient */
+#define I830_DESTREG_DBUFADDR 1
+#define I830_DESTREG_DV0 2
+#define I830_DESTREG_DV1 3
+#define I830_DESTREG_SENABLE 4
+#define I830_DESTREG_SR0 5
+#define I830_DESTREG_SR1 6
+#define I830_DESTREG_SR2 7
+#define I830_DESTREG_DR0 8
+#define I830_DESTREG_DR1 9
+#define I830_DESTREG_DR2 10
+#define I830_DESTREG_DR3 11
+#define I830_DESTREG_DR4 12
+#define I830_DEST_SETUP_SIZE 13
+
+/* Context state
+ */
+#define I830_CTXREG_STATE1             0
+#define I830_CTXREG_STATE2             1
+#define I830_CTXREG_STATE3             2
+#define I830_CTXREG_STATE4             3
+#define I830_CTXREG_STATE5             4
+#define I830_CTXREG_IALPHAB            5
+#define I830_CTXREG_STENCILTST         6
+#define I830_CTXREG_ENABLES_1          7
+#define I830_CTXREG_ENABLES_2          8
+#define I830_CTXREG_AA                 9
+#define I830_CTXREG_FOGCOLOR           10
+#define I830_CTXREG_BLENDCOLR0         11
+#define I830_CTXREG_BLENDCOLR          12 /* Dword 1 of 2 dword command */
+#define I830_CTXREG_VF                 13
+#define I830_CTXREG_VF2                        14
+#define I830_CTXREG_MCSB0              15
+#define I830_CTXREG_MCSB1              16
+#define I830_CTX_SETUP_SIZE            17
+
+/* Texture state (per tex unit)
+ */
+
+#define I830_TEXREG_MI0        0       /* GFX_OP_MAP_INFO (6 dwords) */
+#define I830_TEXREG_MI1        1
+#define I830_TEXREG_MI2        2
+#define I830_TEXREG_MI3        3
+#define I830_TEXREG_MI4        4
+#define I830_TEXREG_MI5        5
+#define I830_TEXREG_MF 6       /* GFX_OP_MAP_FILTER */
+#define I830_TEXREG_MLC        7       /* GFX_OP_MAP_LOD_CTL */
+#define I830_TEXREG_MLL        8       /* GFX_OP_MAP_LOD_LIMITS */
+#define I830_TEXREG_MCS        9       /* GFX_OP_MAP_COORD_SETS */
+#define I830_TEX_SETUP_SIZE 10
+
+#define I830_FRONT   0x1
+#define I830_BACK    0x2
+#define I830_DEPTH   0x4
+
+#endif /* _I830_DEFINES_ */
+
+typedef struct _drm_i830_init {
+       enum {
+               I830_INIT_DMA = 0x01,
+               I830_CLEANUP_DMA = 0x02
+       } func;
+       unsigned int mmio_offset;
+       unsigned int buffers_offset;
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits;
+       unsigned int back_pitch;
+       unsigned int depth_pitch;
+       unsigned int cpp;
+} drm_i830_init_t;
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+typedef struct _drm_i830_tex_region {
+       unsigned char next, prev; /* indices to form a circular LRU  */
+       unsigned char in_use;   /* owned by a client, or free? */
+       int age;                /* tracked by clients to update local LRU's */
+} drm_i830_tex_region_t;
+
+typedef struct _drm_i830_sarea {
+       unsigned int ContextState[I830_CTX_SETUP_SIZE];
+       unsigned int BufferState[I830_DEST_SETUP_SIZE];
+       unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
+       unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
+       unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
+       unsigned int Palette[2][256];
+       unsigned int dirty;
+
+       unsigned int nbox;
+       drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS];
+
+       /* Maintain an LRU of contiguous regions of texture space.  If
+        * you think you own a region of texture memory, and it has an
+        * age different to the one you set, then you are mistaken and
+        * it has been stolen by another client.  If global texAge
+        * hasn't changed, there is no need to walk the list.
+        *
+        * These regions can be used as a proxy for the fine-grained
+        * texture information of other clients - by maintaining them
+        * in the same lru which is used to age their own textures,
+        * clients have an approximate lru for the whole of global
+        * texture space, and can make informed decisions as to which
+        * areas to kick out.  There is no need to choose whether to
+        * kick out your own texture or someone else's - simply eject
+        * them all in LRU order.  
+        */
+
+       drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS+1]; 
+                               /* Last elt is sentinal */
+        int texAge;            /* last time texture was uploaded */
+        int last_enqueue;      /* last time a buffer was enqueued */
+       int last_dispatch;      /* age of the most recently dispatched buffer */
+       int last_quiescent;     /*  */
+       int ctxOwner;           /* last context to upload state */
+
+       int vertex_prim;
+} drm_i830_sarea_t;
+
+typedef struct _drm_i830_clear {
+       int clear_color;
+       int clear_depth;
+       int flags;
+       unsigned int clear_colormask;
+       unsigned int clear_depthmask;
+} drm_i830_clear_t;
+
+
+
+/* These may be placeholders if we have more cliprects than
+ * I830_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
+ * false, indicating that the buffer will be dispatched again with a
+ * new set of cliprects.
+ */
+typedef struct _drm_i830_vertex {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       int discard;            /* client is finished with the buffer? */
+} drm_i830_vertex_t;
+
+typedef struct _drm_i830_copy_t {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       void *address;          /* Address to copy from */
+} drm_i830_copy_t;
+
+typedef struct drm_i830_dma {
+       void *virtual;
+       int request_idx;
+       int request_size;
+       int granted;
+} drm_i830_dma_t;
+
+#endif /* _I830_DRM_H_ */
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
new file mode 100644 (file)
index 0000000..904f366
--- /dev/null
@@ -0,0 +1,102 @@
+/* i830_drv.c -- I810 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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
+ * VA LINUX SYSTEMS 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:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Abraham vd Merwe <abraham@2d3d.co.za>
+ */
+
+#include <linux/config.h>
+#include "i830.h"
+#include "drmP.h"
+#include "i830_drv.h"
+
+#define DRIVER_AUTHOR          "VA Linux Systems Inc."
+
+#define DRIVER_NAME            "i830"
+#define DRIVER_DESC            "Intel 830M"
+#define DRIVER_DATE            "20011004"
+
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           2
+#define DRIVER_PATCHLEVEL      0
+
+#define DRIVER_IOCTLS                                                      \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)]   = { i830_dma_init,    1, 1 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex,  1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)]  = { i830_clear_bufs,  1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)]  = { i830_flush_ioctl, 1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage,      1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf,      1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)]   = { i830_swap_bufs,   1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)]   = { i830_copybuf,     1, 0 }, \
+       [DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy,      1, 0 },
+
+#define __HAVE_COUNTERS         4
+#define __HAVE_COUNTER6         _DRM_STAT_IRQ
+#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
+#define __HAVE_COUNTER9         _DRM_STAT_DMA
+
+
+#include "drm_agpsupport.h"
+#include "drm_auth.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
+
+#ifndef MODULE
+/* DRM(options) is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO).  It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+
+/* JH- We have to hand expand the string ourselves because of the cpp.  If
+ * anyone can think of a way that we can fit into the __setup macro without
+ * changing it, then please send the solution my way.
+ */
+static int __init i830_options( char *str )
+{
+   DRM(parse_options)( str );
+   return 1;
+}
+
+__setup( DRIVER_NAME "=", i830_options );
+#endif
+
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_lists.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
new file mode 100644 (file)
index 0000000..4e9d6c8
--- /dev/null
@@ -0,0 +1,213 @@
+/* i830_drv.h -- Private header for the I830 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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: Rickard E. (Rik) Faith <faith@valinux.com>
+ *         Jeff Hartmann <jhartmann@valinux.com>
+ *
+ */
+
+#ifndef _I830_DRV_H_
+#define _I830_DRV_H_
+
+typedef struct drm_i830_buf_priv {
+       u32 *in_use;
+       int my_use_idx;
+       int currently_mapped;
+       void *virtual;
+       void *kernel_virtual;
+       int map_count;
+       struct vm_area_struct *vma;
+} drm_i830_buf_priv_t;
+
+typedef struct _drm_i830_ring_buffer{
+       int tail_mask;
+       unsigned long Start;
+       unsigned long End;
+       unsigned long Size;
+       u8 *virtual_start;
+       int head;
+       int tail;
+       int space;
+} drm_i830_ring_buffer_t;
+
+typedef struct drm_i830_private {
+       drm_map_t *sarea_map;
+       drm_map_t *buffer_map;
+       drm_map_t *mmio_map;
+
+       drm_i830_sarea_t *sarea_priv;
+       drm_i830_ring_buffer_t ring;
+
+       unsigned long hw_status_page;
+       unsigned long counter;
+
+       atomic_t flush_done;
+       wait_queue_head_t flush_queue;  /* Processes waiting until flush    */
+       drm_buf_t *mmap_buffer;
+       
+       u32 front_di1, back_di1, zi1;
+       
+       int back_offset;
+       int depth_offset;
+       int w, h;
+       int pitch;
+       int back_pitch;
+       int depth_pitch;
+       unsigned int cpp;
+} drm_i830_private_t;
+
+                               /* i830_dma.c */
+extern int  i830_dma_schedule(drm_device_t *dev, int locked);
+extern int  i830_getbuf(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
+extern int  i830_dma_init(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg);
+extern int  i830_flush_ioctl(struct inode *inode, struct file *filp,
+                            unsigned int cmd, unsigned long arg);
+extern void i830_reclaim_buffers(drm_device_t *dev, pid_t pid);
+extern int  i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+                       unsigned long arg);
+extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
+extern int i830_copybuf(struct inode *inode, struct file *filp, 
+                       unsigned int cmd, unsigned long arg);
+extern int i830_docopy(struct inode *inode, struct file *filp, 
+                      unsigned int cmd, unsigned long arg);
+
+extern void i830_dma_quiescent(drm_device_t *dev);
+
+extern int i830_dma_vertex(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg);
+
+extern int i830_swap_bufs(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg);
+
+extern int i830_clear_bufs(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg);
+
+#define I830_VERBOSE 0
+
+#define I830_BASE(reg)         ((unsigned long) \
+                               dev_priv->mmio_map->handle)
+#define I830_ADDR(reg)         (I830_BASE(reg) + reg)
+#define I830_DEREF(reg)                *(__volatile__ int *)I830_ADDR(reg)
+#define I830_READ(reg)         I830_DEREF(reg)
+#define I830_WRITE(reg,val)    do { I830_DEREF(reg) = val; } while (0)
+#define I830_DEREF16(reg)      *(__volatile__ u16 *)I830_ADDR(reg)
+#define I830_READ16(reg)       I830_DEREF16(reg)
+#define I830_WRITE16(reg,val)  do { I830_DEREF16(reg) = val; } while (0)
+
+#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD                        (7<<23)
+#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+
+#define INST_PARSER_CLIENT   0x00000000
+#define INST_OP_FLUSH        0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+
+#define BB1_START_ADDR_MASK   (~0x7)
+#define BB1_PROTECTED         (1<<0)
+#define BB1_UNPROTECTED       (0<<0)
+#define BB2_END_ADDR_MASK     (~0x7)
+
+#define I830REG_HWSTAM         0x02098
+#define I830REG_INT_IDENTITY_R 0x020a4
+#define I830REG_INT_MASK_R     0x020a8
+#define I830REG_INT_ENABLE_R   0x020a0
+
+#define LP_RING                0x2030
+#define HP_RING                0x2040
+#define RING_TAIL                      0x00
+#define TAIL_ADDR              0x000FFFF8
+#define RING_HEAD                      0x04
+#define HEAD_WRAP_COUNT        0xFFE00000
+#define HEAD_WRAP_ONE          0x00200000
+#define HEAD_ADDR              0x001FFFFC
+#define RING_START                     0x08
+#define START_ADDR             0x00FFFFF8
+#define RING_LEN                       0x0C
+#define RING_NR_PAGES          0x000FF000 
+#define RING_REPORT_MASK       0x00000006
+#define RING_REPORT_64K        0x00000002
+#define RING_REPORT_128K       0x00000004
+#define RING_NO_REPORT         0x00000000
+#define RING_VALID_MASK        0x00000001
+#define RING_VALID             0x00000001
+#define RING_INVALID           0x00000000
+
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR       (0x1<<1)
+#define SC_ENABLE_MASK          (0x1<<0)
+#define SC_ENABLE               (0x1<<0)
+
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK      (0xffff<<16)
+#define SCI_XMIN_MASK      (0xffff<<0)
+#define SCI_YMAX_MASK      (0xffff<<16)
+#define SCI_XMAX_MASK      (0xffff<<0)
+
+#define GFX_OP_SCISSOR_ENABLE   ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT     ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
+
+#define CMD_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+
+
+#define BR00_BITBLT_CLIENT   0x40000000
+#define BR00_OP_COLOR_BLT    0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN   0x80000000
+
+#define BUF_3D_ID_COLOR_BACK    (0x3<<24)
+#define BUF_3D_ID_DEPTH         (0x7<<24)
+#define BUF_3D_USE_FENCE        (1<<23)
+#define BUF_3D_PITCH(x)         (((x)/4)<<2)
+
+#define CMD_OP_MAP_PALETTE_LOAD        ((3<<29)|(0x1d<<24)|(0x82<<16)|255)
+#define MAP_PALETTE_NUM(x)     ((x<<8) & (1<<8))
+#define MAP_PALETTE_BOTH       (1<<11)
+
+#define XY_COLOR_BLT_CMD               ((2<<29)|(0x50<<22)|0x4)
+#define XY_COLOR_BLT_WRITE_ALPHA       (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB         (1<<20)
+
+#define XY_SRC_COPY_BLT_CMD             ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA     (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20)
+
+#define MI_BATCH_BUFFER        ((0x30<<23)|1)
+#define MI_BATCH_NON_SECURE    (1)
+
+
+#endif
+
index 41b2e9a17689c954ad0cf2c12159ecf6c36bfce4..16919514a9d7c235ac048dbbd5dcb137ea85cc6c 100644 (file)
@@ -163,6 +163,9 @@ static inline void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
        drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
        DMA_LOCALS;
 
+/*     printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
+/*            tex->texctl, tex->texctl2); */
+
        BEGIN_DMA( 6 );
 
        DMA_BLOCK( MGA_TEXCTL2,         tex->texctl2 | MGA_G400_TC2_MAGIC,
@@ -204,6 +207,9 @@ static inline void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
        drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
        DMA_LOCALS;
 
+/*     printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg,  */
+/*            tex->texctl, tex->texctl2); */
+
        BEGIN_DMA( 5 );
 
        DMA_BLOCK( MGA_TEXCTL2,         (tex->texctl2 |
@@ -272,6 +278,8 @@ static inline void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
        unsigned int pipe = sarea_priv->warp_pipe;
        DMA_LOCALS;
 
+/*     printk("mga_g400_emit_pipe %x\n", pipe); */
+
        BEGIN_DMA( 10 );
 
        DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND,
index d4eda6c8c1207d327604ca11b21275c0b74259e3..d8d7be4f619d2eb7b9d396f13b66529d31848592 100644 (file)
 
 #define DRIVER_NAME            "r128"
 #define DRIVER_DESC            "ATI Rage 128"
-#define DRIVER_DATE            "20010405"
+#define DRIVER_DATE            "20010917"
 
 #define DRIVER_MAJOR           2
-#define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      6
+#define DRIVER_MINOR           2
+#define DRIVER_PATCHLEVEL      0
 
 #define DRIVER_IOCTLS                                                      \
    [DRM_IOCTL_NR(DRM_IOCTL_DMA)]             = { r128_cce_buffers,  1, 0 }, \
index 66af5c45686a116e7a4620d32fc6150487da46a8..9de1b6b9c0d523309119ffb9d86ac60b714ec808 100644 (file)
@@ -1519,10 +1519,75 @@ int r128_cce_indirect( struct inode *inode, struct file *filp,
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
+       drm_buf_t *buf;
+       drm_r128_buf_priv_t *buf_priv;
+       drm_r128_indirect_t indirect;
+#if 0
+       RING_LOCALS;
+#endif
 
        LOCK_TEST_WITH_RETURN( dev );
 
-       /* Indirect buffer firing is not supported at this time.
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+               return -EINVAL;
+       }
+
+       if ( copy_from_user( &indirect, (drm_r128_indirect_t *)arg,
+                            sizeof(indirect) ) )
+               return -EFAULT;
+
+       DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
+                  indirect.idx, indirect.start,
+                  indirect.end, indirect.discard );
+
+       if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
+               DRM_ERROR( "buffer index %d (of %d max)\n",
+                          indirect.idx, dma->buf_count - 1 );
+               return -EINVAL;
+       }
+
+       buf = dma->buflist[indirect.idx];
+       buf_priv = buf->dev_private;
+
+       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", indirect.idx );
+               return -EINVAL;
+       }
+
+       if ( indirect.start < buf->used ) {
+               DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
+                          indirect.start, buf->used );
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+       buf->used = indirect.end;
+       buf_priv->discard = indirect.discard;
+
+#if 0
+       /* Wait for the 3D stream to idle before the indirect buffer
+        * containing 2D acceleration commands is processed.
         */
-       return -EINVAL;
+       BEGIN_RING( 2 );
+       RADEON_WAIT_UNTIL_3D_IDLE();
+       ADVANCE_RING();
+#endif
+
+       /* Dispatch the indirect buffer full of commands from the
+        * X server.  This is insecure and is thus only available to
+        * privileged clients.
+        */
+       r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+
+       return 0;
 }
index 904c8b779ee73a780253df4b8500e9cfb1420a74..d47cbe3adfffd4e166cdfda123853b93f8002f9c 100644 (file)
@@ -744,17 +744,17 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
         * and screwing with the clear operation.
         */
        dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
-                                          RADEON_Z_ENABLE |
                                           (dev_priv->color_fmt << 10) |
-                                          RADEON_ZBLOCK16);
+                                          (1<<15));
 
-       dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt |
-                                                  RADEON_Z_TEST_ALWAYS |
-                                                  RADEON_STENCIL_TEST_ALWAYS |
-                                                  RADEON_STENCIL_S_FAIL_KEEP |
-                                                  RADEON_STENCIL_ZPASS_KEEP |
-                                                  RADEON_STENCIL_ZFAIL_KEEP |
-                                                  RADEON_Z_WRITE_ENABLE);
+       dev_priv->depth_clear.rb3d_zstencilcntl = 
+               (dev_priv->depth_fmt |
+                RADEON_Z_TEST_ALWAYS |
+                RADEON_STENCIL_TEST_ALWAYS |
+                RADEON_STENCIL_S_FAIL_REPLACE |
+                RADEON_STENCIL_ZPASS_REPLACE |
+                RADEON_STENCIL_ZFAIL_REPLACE |
+                RADEON_Z_WRITE_ENABLE);
 
        dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
                                         RADEON_BFACE_SOLID |
@@ -964,9 +964,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
        radeon_cp_load_microcode( dev_priv );
        radeon_cp_init_ring_buffer( dev, dev_priv );
 
-#if ROTATE_BUFS
        dev_priv->last_buf = 0;
-#endif
 
        dev->dev_private = (void *)dev_priv;
 
@@ -1146,116 +1144,27 @@ int radeon_engine_reset( struct inode *inode, struct file *filp,
  * Fullscreen mode
  */
 
-static int radeon_do_init_pageflip( drm_device_t *dev )
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG( "%s\n", __FUNCTION__ );
-
-       dev_priv->crtc_offset =      RADEON_READ( RADEON_CRTC_OFFSET );
-       dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL );
-
-       RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset );
-       RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL,
-                     dev_priv->crtc_offset_cntl |
-                     RADEON_CRTC_OFFSET_FLIP_CNTL );
-
-       dev_priv->page_flipping = 1;
-       dev_priv->current_page = 0;
-
-       return 0;
-}
-
-int radeon_do_cleanup_pageflip( drm_device_t *dev )
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG( "%s\n", __FUNCTION__ );
-
-       RADEON_WRITE( RADEON_CRTC_OFFSET,      dev_priv->crtc_offset );
-       RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
-
-       dev_priv->page_flipping = 0;
-       dev_priv->current_page = 0;
-
-       return 0;
-}
-
+/* KW: Deprecated to say the least:
+ */
 int radeon_fullscreen( 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_fullscreen_t fs;
-
-       LOCK_TEST_WITH_RETURN( dev );
-
-       if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
-                            sizeof(fs) ) )
-               return -EFAULT;
-
-       switch ( fs.func ) {
-       case RADEON_INIT_FULLSCREEN:
-               return radeon_do_init_pageflip( dev );
-       case RADEON_CLEANUP_FULLSCREEN:
-               return radeon_do_cleanup_pageflip( dev );
-       }
-
-       return -EINVAL;
+       return 0;
 }
 
 
 /* ================================================================
  * Freelist management
  */
-#define RADEON_BUFFER_USED     0xffffffff
-#define RADEON_BUFFER_FREE     0
-
-#if 0
-static int radeon_freelist_init( drm_device_t *dev )
-{
-       drm_device_dma_t *dma = dev->dma;
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_buf_t *buf;
-       drm_radeon_buf_priv_t *buf_priv;
-       drm_radeon_freelist_t *entry;
-       int i;
-
-       dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t),
-                                    DRM_MEM_DRIVER );
-       if ( dev_priv->head == NULL )
-               return -ENOMEM;
-
-       memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) );
-       dev_priv->head->age = RADEON_BUFFER_USED;
-
-       for ( i = 0 ; i < dma->buf_count ; i++ ) {
-               buf = dma->buflist[i];
-               buf_priv = buf->dev_private;
-
-               entry = DRM(alloc)( sizeof(drm_radeon_freelist_t),
-                                   DRM_MEM_DRIVER );
-               if ( !entry ) return -ENOMEM;
-
-               entry->age = RADEON_BUFFER_FREE;
-               entry->buf = buf;
-               entry->prev = dev_priv->head;
-               entry->next = dev_priv->head->next;
-               if ( !entry->next )
-                       dev_priv->tail = entry;
 
-               buf_priv->discard = 0;
-               buf_priv->dispatched = 0;
-               buf_priv->list_entry = entry;
-
-               dev_priv->head->next = entry;
-
-               if ( dev_priv->head->next )
-                       dev_priv->head->next->prev = entry;
-       }
-
-       return 0;
-
-}
-#endif
+/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
+ *   bufs until freelist code is used.  Note this hides a problem with
+ *   the scratch register * (used to keep track of last buffer
+ *   completed) being written to before * the last buffer has actually
+ *   completed rendering.  
+ *
+ * KW:  It's also a good way to find free buffers quickly.
+ */
 
 drm_buf_t *radeon_freelist_get( drm_device_t *dev )
 {
@@ -1264,57 +1173,24 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
        drm_radeon_buf_priv_t *buf_priv;
        drm_buf_t *buf;
        int i, t;
-#if ROTATE_BUFS
        int start;
-#endif
-
-       /* FIXME: Optimize -- use freelist code */
 
-       for ( i = 0 ; i < dma->buf_count ; i++ ) {
-               buf = dma->buflist[i];
-               buf_priv = buf->dev_private;
-               if ( buf->pid == 0 ) {
-                       DRM_DEBUG( "  ret buf=%d last=%d pid=0\n",
-                                  buf->idx, dev_priv->last_buf );
-                       return buf;
-               }
-               DRM_DEBUG( "    skipping buf=%d pid=%d\n",
-                          buf->idx, buf->pid );
-       }
-
-#if ROTATE_BUFS
        if ( ++dev_priv->last_buf >= dma->buf_count )
                dev_priv->last_buf = 0;
+
        start = dev_priv->last_buf;
-#endif
+
        for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
-#if 0
-               /* FIXME: Disable this for now */
-               u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH];
-#else
                u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG );
-#endif
-#if ROTATE_BUFS
                for ( i = start ; i < dma->buf_count ; i++ ) {
-#else
-               for ( i = 0 ; i < dma->buf_count ; i++ ) {
-#endif
                        buf = dma->buflist[i];
                        buf_priv = buf->dev_private;
-                       if ( buf->pending && buf_priv->age <= done_age ) {
-                               /* The buffer has been processed, so it
-                                * can now be used.
-                                */
+                       if ( buf->pid == 0 || (buf->pending && 
+                                              buf_priv->age <= done_age) ) {
                                buf->pending = 0;
-                               DRM_DEBUG( "  ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age );
                                return buf;
                        }
-                       DRM_DEBUG( "    skipping buf=%d age=%d done=%d\n",
-                                  buf->idx, buf_priv->age,
-                                  done_age );
-#if ROTATE_BUFS
                        start = 0;
-#endif
                }
                udelay( 1 );
        }
@@ -1326,14 +1202,10 @@ drm_buf_t *radeon_freelist_get( drm_device_t *dev )
 void radeon_freelist_reset( drm_device_t *dev )
 {
        drm_device_dma_t *dma = dev->dma;
-#if ROTATE_BUFS
        drm_radeon_private_t *dev_priv = dev->dev_private;
-#endif
        int i;
 
-#if ROTATE_BUFS
        dev_priv->last_buf = 0;
-#endif
        for ( i = 0 ; i < dma->buf_count ; i++ ) {
                drm_buf_t *buf = dma->buflist[i];
                drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
index 4ae387ff01495b0b67997138631383bcf3c1db09..bb5a4b6d05d2b52cbfcefc388ffee16a6f3332f3 100644 (file)
@@ -2,6 +2,7 @@
  *
  * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -26,6 +27,7 @@
  * Authors:
  *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keith_whitwell@yahoo.com>
  */
 
 #ifndef __RADEON_DRM_H__
@@ -37,7 +39,8 @@
 #ifndef __RADEON_SAREA_DEFINES__
 #define __RADEON_SAREA_DEFINES__
 
-/* What needs to be changed for the current vertex buffer?
+/* Old style state flags, required for sarea interface (1.1 and 1.2
+ * clears) and 1.2 drm_vertex2 ioctl.
  */
 #define RADEON_UPLOAD_CONTEXT          0x00000001
 #define RADEON_UPLOAD_VERTFMT          0x00000002
 #define RADEON_UPLOAD_TEX2IMAGES       0x00004000
 #define RADEON_UPLOAD_CLIPRECTS                0x00008000 /* handled client-side */
 #define RADEON_REQUIRE_QUIESCENCE      0x00010000
-#define RADEON_UPLOAD_ALL              0x0001ffff
+#define RADEON_UPLOAD_ZBIAS            0x00020000 /* version 1.2 and newer */
+#define RADEON_UPLOAD_ALL              0x003effff
+#define RADEON_UPLOAD_CONTEXT_ALL       0x003e01ff
+
+
+/* New style per-packet identifiers for use in cmd_buffer ioctl with
+ * the RADEON_EMIT_PACKET command.  Comments relate new packets to old
+ * state bits and the packet size:
+ */
+#define RADEON_EMIT_PP_MISC                         0 /* context/7 */
+#define RADEON_EMIT_PP_CNTL                         1 /* context/3 */
+#define RADEON_EMIT_RB3D_COLORPITCH                 2 /* context/1 */
+#define RADEON_EMIT_RE_LINE_PATTERN                 3 /* line/2 */
+#define RADEON_EMIT_SE_LINE_WIDTH                   4 /* line/1 */
+#define RADEON_EMIT_PP_LUM_MATRIX                   5 /* bumpmap/1 */
+#define RADEON_EMIT_PP_ROT_MATRIX_0                 6 /* bumpmap/2 */
+#define RADEON_EMIT_RB3D_STENCILREFMASK             7 /* masks/3 */
+#define RADEON_EMIT_SE_VPORT_XSCALE                 8 /* viewport/6 */
+#define RADEON_EMIT_SE_CNTL                         9 /* setup/2 */
+#define RADEON_EMIT_SE_CNTL_STATUS                  10 /* setup/1 */
+#define RADEON_EMIT_RE_MISC                         11 /* misc/1 */
+#define RADEON_EMIT_PP_TXFILTER_0                   12 /* tex0/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_0               13 /* tex0/1 */
+#define RADEON_EMIT_PP_TXFILTER_1                   14 /* tex1/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_1               15 /* tex1/1 */
+#define RADEON_EMIT_PP_TXFILTER_2                   16 /* tex2/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_2               17 /* tex2/1 */
+#define RADEON_EMIT_SE_ZBIAS_FACTOR                 18 /* zbias/2 */
+#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT           19 /* tcl/11 */
+#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED   20 /* material/17 */
+#define RADEON_MAX_STATE_PACKETS                    21
+
+
+/* Commands understood by cmd_buffer ioctl.  More can be added but
+ * obviously these can't be removed or changed:
+ */
+#define RADEON_CMD_PACKET      1 /* emit one of the register packets above */
+#define RADEON_CMD_SCALARS     2 /* emit scalar data */
+#define RADEON_CMD_VECTORS     3 /* emit vector data */
+#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
+#define RADEON_CMD_PACKET3     5 /* emit hw packet */
+#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
+
+
+typedef union {
+       int i;
+       struct { 
+               char cmd_type, pad0, pad1, pad2;
+       } header;
+       struct { 
+               char cmd_type, packet_id, pad0, pad1;
+       } packet;
+       struct { 
+               char cmd_type, offset, stride, count; 
+       } scalars;
+       struct { 
+               char cmd_type, offset, stride, count; 
+       } vectors;
+       struct { 
+               char cmd_type, buf_idx, pad0, pad1; 
+       } dma;
+} drm_radeon_cmd_header_t;
+
 
 #define RADEON_FRONT                   0x1
 #define RADEON_BACK                    0x2
 #define RADEON_DEPTH                   0x4
+#define RADEON_STENCIL                  0x8
 
 /* Primitive types
  */
 /* Byte offsets for indirect buffer data
  */
 #define RADEON_INDEX_PRIM_OFFSET       20
-#define RADEON_HOSTDATA_BLIT_OFFSET    32
 
 #define RADEON_SCRATCH_REG_OFFSET      32
 
-/* Keep these small for testing
- */
 #define RADEON_NR_SAREA_CLIPRECTS      12
 
 /* There are 2 heaps (local/AGP).  Each region within a heap is a
 #define RADEON_NR_TEX_REGIONS          64
 #define RADEON_LOG_TEX_GRANULARITY     16
 
-#define RADEON_MAX_TEXTURE_LEVELS      11
+#define RADEON_MAX_TEXTURE_LEVELS      12
 #define RADEON_MAX_TEXTURE_UNITS       3
 
 #endif /* __RADEON_SAREA_DEFINES__ */
@@ -155,28 +218,18 @@ typedef struct {
        /* Setup state */
        unsigned int se_cntl_status;                    /* 0x2140 */
 
-#ifdef TCL_ENABLE
-       /* TCL state */
-       radeon_color_regs_t se_tcl_material_emmissive;  /* 0x2210 */
-       radeon_color_regs_t se_tcl_material_ambient;
-       radeon_color_regs_t se_tcl_material_diffuse;
-       radeon_color_regs_t se_tcl_material_specular;
-       unsigned int se_tcl_shininess;
-       unsigned int se_tcl_output_vtx_fmt;
-       unsigned int se_tcl_output_vtx_sel;
-       unsigned int se_tcl_matrix_select_0;
-       unsigned int se_tcl_matrix_select_1;
-       unsigned int se_tcl_ucp_vert_blend_ctl;
-       unsigned int se_tcl_texture_proc_ctl;
-       unsigned int se_tcl_light_model_ctl;
-       unsigned int se_tcl_per_light_ctl[4];
-#endif
-
        /* Misc state */
        unsigned int re_top_left;                       /* 0x26c0 */
        unsigned int re_misc;
 } drm_radeon_context_regs_t;
 
+typedef struct {
+       /* Zbias state */
+       unsigned int se_zbias_factor;                   /* 0x1dac */
+       unsigned int se_zbias_constant;
+} drm_radeon_context2_regs_t;
+
+
 /* Setup registers for each texture unit
  */
 typedef struct {
@@ -186,15 +239,27 @@ typedef struct {
        unsigned int pp_txcblend;
        unsigned int pp_txablend;
        unsigned int pp_tfactor;
-
        unsigned int pp_border_color;
-
-#ifdef CUBIC_ENABLE
-       unsigned int pp_cubic_faces;
-       unsigned int pp_cubic_offset[5];
-#endif
 } drm_radeon_texture_regs_t;
 
+typedef struct {
+       unsigned int start;
+       unsigned int finish;
+       unsigned int prim:8;
+       unsigned int stateidx:8;
+       unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
+        unsigned int vc_format;   /* vertex format */
+} drm_radeon_prim_t;
+
+
+typedef struct {
+       drm_radeon_context_regs_t context;
+       drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
+       drm_radeon_context2_regs_t context2;
+       unsigned int dirty;
+} drm_radeon_state_t;
+
+
 typedef struct {
        unsigned char next, prev;
        unsigned char in_use;
@@ -202,8 +267,9 @@ typedef struct {
 } drm_radeon_tex_region_t;
 
 typedef struct {
-       /* The channel for communication of state information to the kernel
-        * on firing a vertex buffer.
+       /* The channel for communication of state information to the
+        * kernel on firing a vertex buffer with either of the
+        * obsoleted vertex/index ioctls.
         */
        drm_radeon_context_regs_t context_state;
        drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
@@ -225,11 +291,15 @@ typedef struct {
        drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
        int tex_age[RADEON_NR_TEX_HEAPS];
        int ctx_owner;
+        int pfState;                /* number of 3d windows (0,1,2ormore) */
+        int pfCurrentPage;         /* which buffer is being displayed? */
 } drm_radeon_sarea_t;
 
 
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the Xserver file (xf86drmRadeon.h)
+ *
+ * KW: actually it's illegal to change any of this (backwards compatibility).
  */
 typedef struct drm_radeon_init {
        enum {
@@ -285,7 +355,7 @@ typedef struct drm_radeon_clear {
        unsigned int clear_color;
        unsigned int clear_depth;
        unsigned int color_mask;
-       unsigned int depth_mask;
+       unsigned int depth_mask;   /* misnamed field:  should be stencil */
        drm_radeon_clear_rect_t *depth_boxes;
 } drm_radeon_clear_t;
 
@@ -304,6 +374,36 @@ typedef struct drm_radeon_indices {
        int discard;                    /* Client finished with buffer? */
 } drm_radeon_indices_t;
 
+/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
+ *      - allows multiple primitives and state changes in a single ioctl
+ *      - supports driver change to emit native primitives
+ */
+typedef struct drm_radeon_vertex2 {
+       int idx;                        /* Index of vertex buffer */
+       int discard;                    /* Client finished with buffer? */
+       int nr_states;
+       drm_radeon_state_t *state;
+       int nr_prims;
+       drm_radeon_prim_t *prim;
+} drm_radeon_vertex2_t;
+
+/* v1.3 - obsoletes drm_radeon_vertex2
+ *      - allows arbitarily large cliprect list 
+ *      - allows updating of tcl packet, vector and scalar state
+ *      - allows memory-efficient description of state updates
+ *      - allows state to be emitted without a primitive 
+ *           (for clears, ctx switches)
+ *      - allows more than one dma buffer to be referenced per ioctl
+ *      - supports tcl driver
+ *      - may be extended in future versions with new cmd types, packets
+ */
+typedef struct drm_radeon_cmd_buffer {
+       int bufsz;
+       char *buf;
+       int nbox;
+       drm_clip_rect_t *boxes;
+} drm_radeon_cmd_buffer_t;
+
 typedef struct drm_radeon_tex_image {
        unsigned int x, y;              /* Blit coordinates */
        unsigned int width, height;
@@ -330,4 +430,15 @@ typedef struct drm_radeon_indirect {
        int discard;
 } drm_radeon_indirect_t;
 
+
+/* 1.3: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.  
+ */
+#define RADEON_PARAM_AGP_BUFFER_OFFSET 0x1
+
+typedef struct drm_radeon_getparam {
+       int param;
+       int *value;
+} drm_radeon_getparam_t;
+
 #endif
index 49599bc82587423d3ccc84a80e349c3cd2e12701..641e48511136110db5b8ad87c5a1f0f587a5adf0 100644 (file)
 
 #define DRIVER_NAME            "radeon"
 #define DRIVER_DESC            "ATI Radeon"
-#define DRIVER_DATE            "20010405"
+#define DRIVER_DATE            "20020521"
 
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           1
-#define DRIVER_PATCHLEVEL      1
+#define DRIVER_MINOR           3
+#define DRIVER_PATCHLEVEL      0
 
+/* Interface history:
+ *
+ * 1.1 - ??
+ * 1.2 - Add vertex2 ioctl (keith)
+ *     - Add stencil capability to clear ioctl (gareth, keith)
+ *     - Increase MAX_TEXTURE_LEVELS (brian)
+ * 1.3 - Add cmdbuf ioctl (keith)
+ *     - Add support for new radeon packets (keith)
+ *     - Add getparam ioctl (keith)
+ *     - Add flip-buffers ioctl, deprecate fullscreen foo (keith).
+ */
 #define DRIVER_IOCTLS                                                       \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)]    = { radeon_cp_init,     1, 1 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)]    = { radeon_cp_indices,  1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)]    = { radeon_cp_texture,  1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)]    = { radeon_cp_stipple,  1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]   = { radeon_cp_indirect, 1, 1 },
-
-
-#if 0
-/* GH: Count data sent to card via ring or vertex/indirect buffers.
- */
-#define __HAVE_COUNTERS         3
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-#endif
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]   = { radeon_cp_indirect, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)]    = { radeon_cp_vertex2,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)]     = { radeon_cp_cmdbuf,   1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)]   = { radeon_cp_getparam, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)]       = { radeon_cp_flip,     1, 0 }, 
 
 
 #include "drm_agpsupport.h"
index 5afea7d105a8d3cceca2b23d3d1f8f4bec56e98e..4b4231c843710427a88fad00cc40ff348edf7526 100644 (file)
@@ -71,14 +71,7 @@ typedef struct drm_radeon_private {
 
        drm_radeon_freelist_t *head;
        drm_radeon_freelist_t *tail;
-/* FIXME: ROTATE_BUFS is a hask to cycle through bufs until freelist
-   code is used.  Note this hides a problem with the scratch register
-   (used to keep track of last buffer completed) being written to before
-   the last buffer has actually completed rendering. */
-#define ROTATE_BUFS 1
-#if ROTATE_BUFS
        int last_buf;
-#endif
        volatile u32 *scratch;
 
        int usec_timeout;
@@ -120,10 +113,6 @@ typedef struct drm_radeon_private {
 
 typedef struct drm_radeon_buf_priv {
        u32 age;
-       int prim;
-       int discard;
-       int dispatched;
-       drm_radeon_freelist_t *list_entry;
 } drm_radeon_buf_priv_t;
 
                                /* radeon_cp.c */
@@ -176,6 +165,15 @@ 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 );
+extern int radeon_cp_vertex2( struct inode *inode, struct file *filp,
+                             unsigned int cmd, unsigned long arg );
+extern int radeon_cp_cmdbuf( struct inode *inode, struct file *filp,
+                             unsigned int cmd, unsigned long arg );
+extern int radeon_cp_getparam( struct inode *inode, struct file *filp,
+                             unsigned int cmd, unsigned long arg );
+extern int radeon_cp_flip( struct inode *inode, struct file *filp,
+                          unsigned int cmd, unsigned long arg );
+
 
 
 /* Register definitions, register access macros and drmAddMap constants
@@ -204,8 +202,6 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
 #      define RADEON_CRTC_OFFSET_FLIP_CNTL     (1 << 16)
 
 #define RADEON_RB3D_COLORPITCH         0x1c48
-#define RADEON_RB3D_DEPTHCLEARVALUE    0x1c30
-#define RADEON_RB3D_DEPTHXY_OFFSET     0x1c60
 
 #define RADEON_DP_GUI_MASTER_CNTL      0x146c
 #      define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
@@ -290,9 +286,6 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
 #      define RADEON_ROP_ENABLE                (1 << 6)
 #      define RADEON_STENCIL_ENABLE            (1 << 7)
 #      define RADEON_Z_ENABLE                  (1 << 8)
-#      define RADEON_DEPTH_XZ_OFFEST_ENABLE    (1 << 9)
-#      define RADEON_ZBLOCK8                   (0 << 15)
-#      define RADEON_ZBLOCK16                  (1 << 15)
 #define RADEON_RB3D_DEPTHOFFSET                0x1c24
 #define RADEON_RB3D_PLANEMASK          0x1d84
 #define RADEON_RB3D_STENCILREFMASK     0x1d7c
@@ -306,9 +299,9 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
 #      define RADEON_Z_TEST_MASK               (7 << 4)
 #      define RADEON_Z_TEST_ALWAYS             (7 << 4)
 #      define RADEON_STENCIL_TEST_ALWAYS       (7 << 12)
-#      define RADEON_STENCIL_S_FAIL_KEEP       (0 << 16)
-#      define RADEON_STENCIL_ZPASS_KEEP        (0 << 20)
-#      define RADEON_STENCIL_ZFAIL_KEEP        (0 << 20)
+#      define RADEON_STENCIL_S_FAIL_REPLACE    (2 << 16)
+#      define RADEON_STENCIL_ZPASS_REPLACE     (2 << 20)
+#      define RADEON_STENCIL_ZFAIL_REPLACE     (2 << 24)
 #      define RADEON_Z_WRITE_ENABLE            (1 << 30)
 #define RADEON_RBBM_SOFT_RESET         0x00f0
 #      define RADEON_SOFT_RESET_CP             (1 <<  0)
@@ -357,6 +350,16 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
 #define RADEON_SE_CNTL_STATUS          0x2140
 #define RADEON_SE_LINE_WIDTH           0x1db8
 #define RADEON_SE_VPORT_XSCALE         0x1d98
+#define RADEON_SE_ZBIAS_FACTOR         0x1db0
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
+#define RADEON_SE_TCL_OUTPUT_VTX_FMT         0x2254
+#define RADEON_SE_TCL_VECTOR_INDX_REG        0x2200
+#       define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT  16
+#       define RADEON_VEC_INDX_DWORD_COUNT_SHIFT     28
+#define RADEON_SE_TCL_VECTOR_DATA_REG       0x2204
+#define RADEON_SE_TCL_SCALAR_INDX_REG       0x2208
+#       define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT  16
+#define RADEON_SE_TCL_SCALAR_DATA_REG       0x220C
 #define RADEON_SURFACE_ACCESS_FLAGS    0x0bf8
 #define RADEON_SURFACE_ACCESS_CLR      0x0bfc
 #define RADEON_SURFACE_CNTL            0x0b00
@@ -457,8 +460,10 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
 #define RADEON_CP_PACKET3              0xC0000000
 #      define RADEON_3D_RNDR_GEN_INDX_PRIM     0x00002300
 #      define RADEON_WAIT_FOR_IDLE             0x00002600
+#      define RADEON_3D_DRAW_VBUF              0x00002800
 #      define RADEON_3D_DRAW_IMMD              0x00002900
-#      define RADEON_3D_CLEAR_ZMASK            0x00003200
+#      define RADEON_3D_DRAW_INDX              0x00002A00
+#      define RADEON_3D_LOAD_VBPNTR            0x00002F00
 #      define RADEON_CNTL_HOSTDATA_BLT         0x00009400
 #      define RADEON_CNTL_PAINT_MULTI          0x00009A00
 #      define RADEON_CNTL_BITBLT_MULTI         0x00009B00
@@ -470,6 +475,7 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
 #define RADEON_CP_PACKET1_REG1_MASK    0x003ff800
 
 #define RADEON_VTX_Z_PRESENT                   (1 << 31)
+#define RADEON_VTX_PKCOLOR_PRESENT             (1 << 3)
 
 #define RADEON_PRIM_TYPE_NONE                  (0 << 0)
 #define RADEON_PRIM_TYPE_POINT                 (1 << 0)
@@ -482,6 +488,7 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
 #define RADEON_PRIM_TYPE_RECT_LIST             (8 << 0)
 #define RADEON_PRIM_TYPE_3VRT_POINT_LIST       (9 << 0)
 #define RADEON_PRIM_TYPE_3VRT_LINE_LIST                (10 << 0)
+#define RADEON_PRIM_TYPE_MASK                   0xf
 #define RADEON_PRIM_WALK_IND                   (1 << 4)
 #define RADEON_PRIM_WALK_LIST                  (2 << 4)
 #define RADEON_PRIM_WALK_RING                  (3 << 4)
@@ -699,7 +706,7 @@ do {                                                                        \
 
 #define RADEON_VERBOSE 0
 
-#define RING_LOCALS    int write; unsigned int mask; volatile u32 *ring;
+#define RING_LOCALS    int write, _nr; unsigned int mask; volatile u32 *ring;
 
 #define BEGIN_RING( n ) do {                                           \
        if ( RADEON_VERBOSE ) {                                         \
@@ -709,7 +716,7 @@ do {                                                                        \
        if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {              \
                radeon_wait_ring( dev_priv, (n) * sizeof(u32) );        \
        }                                                               \
-       dev_priv->ring.space -= (n) * sizeof(u32);                      \
+       _nr = n; dev_priv->ring.space -= (n) * sizeof(u32);             \
        ring = dev_priv->ring.start;                                    \
        write = dev_priv->ring.tail;                                    \
        mask = dev_priv->ring.tail_mask;                                \
@@ -721,7 +728,13 @@ do {                                                                       \
                          write, dev_priv->ring.tail );                 \
        }                                                               \
        radeon_flush_write_combine();                                   \
-       dev_priv->ring.tail = write;                                    \
+       if (((dev_priv->ring.tail + _nr) & mask) != write) {            \
+               DRM_ERROR(                                              \
+                       "ADVANCE_RING(): mismatch: nr: %x write: %x\n", \
+                       ((dev_priv->ring.tail + _nr) & mask),           \
+                       write);                                         \
+       } else                                                          \
+               dev_priv->ring.tail = write;                            \
        RADEON_WRITE( RADEON_CP_RB_WPTR, write );                       \
 } while (0)
 
@@ -734,6 +747,11 @@ do {                                                                       \
        write &= mask;                                                  \
 } while (0)
 
+#define OUT_RING_REG( reg, val ) do {                                  \
+       OUT_RING( CP_PACKET0( reg, 0 ) );                               \
+       OUT_RING( val );                                                \
+} while (0)
+
 #define RADEON_PERFORMANCE_BOXES       0
 
 #endif /* __RADEON_DRV_H__ */
index 0a209245bef05d6141f3520866544f50e81b9caa..7bb1f79ccd5b3ee18005a640bcac2e59dc593424 100644 (file)
@@ -48,358 +48,209 @@ static inline void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
                   box->x1, box->y1, box->x2, box->y2 );
 
        BEGIN_RING( 4 );
-
        OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
        OUT_RING( (box->y1 << 16) | box->x1 );
-
        OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
-       OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_context( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 14 );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
-       OUT_RING( ctx->pp_misc );
-       OUT_RING( ctx->pp_fog_color );
-       OUT_RING( ctx->re_solid_color );
-       OUT_RING( ctx->rb3d_blendcntl );
-       OUT_RING( ctx->rb3d_depthoffset );
-       OUT_RING( ctx->rb3d_depthpitch );
-       OUT_RING( ctx->rb3d_zstencilcntl );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
-       OUT_RING( ctx->pp_cntl );
-       OUT_RING( ctx->rb3d_cntl );
-       OUT_RING( ctx->rb3d_coloroffset );
-
-       OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
-       OUT_RING( ctx->rb3d_colorpitch );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_vertfmt( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 2 );
-
-       OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
-       OUT_RING( ctx->se_coord_fmt );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_line( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 5 );
-
-       OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
-       OUT_RING( ctx->re_line_pattern );
-       OUT_RING( ctx->re_line_state );
-
-       OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
-       OUT_RING( ctx->se_line_width );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_bumpmap( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 5 );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
-       OUT_RING( ctx->pp_lum_matrix );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
-       OUT_RING( ctx->pp_rot_matrix_0 );
-       OUT_RING( ctx->pp_rot_matrix_1 );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_masks( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 4 );
-
-       OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
-       OUT_RING( ctx->rb3d_stencilrefmask );
-       OUT_RING( ctx->rb3d_ropcntl );
-       OUT_RING( ctx->rb3d_planemask );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_viewport( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 7 );
-
-       OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
-       OUT_RING( ctx->se_vport_xscale );
-       OUT_RING( ctx->se_vport_xoffset );
-       OUT_RING( ctx->se_vport_yscale );
-       OUT_RING( ctx->se_vport_yoffset );
-       OUT_RING( ctx->se_vport_zscale );
-       OUT_RING( ctx->se_vport_zoffset );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_setup( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 4 );
-
-       OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
-       OUT_RING( ctx->se_cntl );
-       OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
-       OUT_RING( ctx->se_cntl_status );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv )
-{
-#ifdef TCL_ENABLE
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 29 );
-
-       OUT_RING( CP_PACKET0( RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 27 ) );
-       OUT_RING( ctx->se_tcl_material_emmissive.red );
-       OUT_RING( ctx->se_tcl_material_emmissive.green );
-       OUT_RING( ctx->se_tcl_material_emmissive.blue );
-       OUT_RING( ctx->se_tcl_material_emmissive.alpha );
-       OUT_RING( ctx->se_tcl_material_ambient.red );
-       OUT_RING( ctx->se_tcl_material_ambient.green );
-       OUT_RING( ctx->se_tcl_material_ambient.blue );
-       OUT_RING( ctx->se_tcl_material_ambient.alpha );
-       OUT_RING( ctx->se_tcl_material_diffuse.red );
-       OUT_RING( ctx->se_tcl_material_diffuse.green );
-       OUT_RING( ctx->se_tcl_material_diffuse.blue );
-       OUT_RING( ctx->se_tcl_material_diffuse.alpha );
-       OUT_RING( ctx->se_tcl_material_specular.red );
-       OUT_RING( ctx->se_tcl_material_specular.green );
-       OUT_RING( ctx->se_tcl_material_specular.blue );
-       OUT_RING( ctx->se_tcl_material_specular.alpha );
-       OUT_RING( ctx->se_tcl_shininess );
-       OUT_RING( ctx->se_tcl_output_vtx_fmt );
-       OUT_RING( ctx->se_tcl_output_vtx_sel );
-       OUT_RING( ctx->se_tcl_matrix_select_0 );
-       OUT_RING( ctx->se_tcl_matrix_select_1 );
-       OUT_RING( ctx->se_tcl_ucp_vert_blend_ctl );
-       OUT_RING( ctx->se_tcl_texture_proc_ctl );
-       OUT_RING( ctx->se_tcl_light_model_ctl );
-       for ( i = 0 ; i < 4 ; i++ ) {
-               OUT_RING( ctx->se_tcl_per_light_ctl[i] );
-       }
-
-       ADVANCE_RING();
-#else
-       DRM_ERROR( "TCL not enabled!\n" );
-#endif
-}
-
-static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 2 );
-
-       OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
-       OUT_RING( ctx->re_misc );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0];
-       RING_LOCALS;
-       DRM_DEBUG( "    %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
-
-       BEGIN_RING( 9 );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
-       OUT_RING( tex->pp_txfilter );
-       OUT_RING( tex->pp_txformat );
-       OUT_RING( tex->pp_txoffset );
-       OUT_RING( tex->pp_txcblend );
-       OUT_RING( tex->pp_txablend );
-       OUT_RING( tex->pp_tfactor );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
-       OUT_RING( tex->pp_border_color );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1];
-       RING_LOCALS;
-       DRM_DEBUG( "    %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
-
-       BEGIN_RING( 9 );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
-       OUT_RING( tex->pp_txfilter );
-       OUT_RING( tex->pp_txformat );
-       OUT_RING( tex->pp_txoffset );
-       OUT_RING( tex->pp_txcblend );
-       OUT_RING( tex->pp_txablend );
-       OUT_RING( tex->pp_tfactor );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
-       OUT_RING( tex->pp_border_color );
-
+/*     OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );*/
+       OUT_RING( (box->y2 << 16) | box->x2 );
        ADVANCE_RING();
 }
 
-static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv )
+/* Emit 1.1 state
+ */
+static void radeon_emit_state( drm_radeon_private_t *dev_priv,
+                              drm_radeon_context_regs_t *ctx,
+                              drm_radeon_texture_regs_t *tex,
+                              unsigned int dirty )
 {
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2];
        RING_LOCALS;
-       DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-       BEGIN_RING( 9 );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
-       OUT_RING( tex->pp_txfilter );
-       OUT_RING( tex->pp_txformat );
-       OUT_RING( tex->pp_txoffset );
-       OUT_RING( tex->pp_txcblend );
-       OUT_RING( tex->pp_txablend );
-       OUT_RING( tex->pp_tfactor );
-
-       OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
-       OUT_RING( tex->pp_border_color );
-
-       ADVANCE_RING();
-}
-
-static inline void radeon_emit_state( drm_radeon_private_t *dev_priv )
-{
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int dirty = sarea_priv->dirty;
-
        DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
 
        if ( dirty & RADEON_UPLOAD_CONTEXT ) {
-               radeon_emit_context( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT;
+               BEGIN_RING( 14 );
+               OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
+               OUT_RING( ctx->pp_misc );
+               OUT_RING( ctx->pp_fog_color );
+               OUT_RING( ctx->re_solid_color );
+               OUT_RING( ctx->rb3d_blendcntl );
+               OUT_RING( ctx->rb3d_depthoffset );
+               OUT_RING( ctx->rb3d_depthpitch );
+               OUT_RING( ctx->rb3d_zstencilcntl );
+               OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
+               OUT_RING( ctx->pp_cntl );
+               OUT_RING( ctx->rb3d_cntl );
+               OUT_RING( ctx->rb3d_coloroffset );
+               OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
+               OUT_RING( ctx->rb3d_colorpitch );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_VERTFMT ) {
-               radeon_emit_vertfmt( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT;
+               BEGIN_RING( 2 );
+               OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
+               OUT_RING( ctx->se_coord_fmt );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_LINE ) {
-               radeon_emit_line( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_LINE;
+               BEGIN_RING( 5 );
+               OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
+               OUT_RING( ctx->re_line_pattern );
+               OUT_RING( ctx->re_line_state );
+               OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
+               OUT_RING( ctx->se_line_width );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
-               radeon_emit_bumpmap( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP;
+               BEGIN_RING( 5 );
+               OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
+               OUT_RING( ctx->pp_lum_matrix );
+               OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
+               OUT_RING( ctx->pp_rot_matrix_0 );
+               OUT_RING( ctx->pp_rot_matrix_1 );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_MASKS ) {
-               radeon_emit_masks( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS;
+               BEGIN_RING( 4 );
+               OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
+               OUT_RING( ctx->rb3d_stencilrefmask );
+               OUT_RING( ctx->rb3d_ropcntl );
+               OUT_RING( ctx->rb3d_planemask );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
-               radeon_emit_viewport( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT;
+               BEGIN_RING( 7 );
+               OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
+               OUT_RING( ctx->se_vport_xscale );
+               OUT_RING( ctx->se_vport_xoffset );
+               OUT_RING( ctx->se_vport_yscale );
+               OUT_RING( ctx->se_vport_yoffset );
+               OUT_RING( ctx->se_vport_zscale );
+               OUT_RING( ctx->se_vport_zoffset );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_SETUP ) {
-               radeon_emit_setup( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP;
-       }
-
-       if ( dirty & RADEON_UPLOAD_TCL ) {
-#ifdef TCL_ENABLE
-               radeon_emit_tcl( dev_priv );
-#endif
-               sarea_priv->dirty &= ~RADEON_UPLOAD_TCL;
+               BEGIN_RING( 4 );
+               OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+               OUT_RING( ctx->se_cntl );
+               OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
+               OUT_RING( ctx->se_cntl_status );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_MISC ) {
-               radeon_emit_misc( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_MISC;
+               BEGIN_RING( 2 );
+               OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
+               OUT_RING( ctx->re_misc );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_TEX0 ) {
-               radeon_emit_tex0( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0;
+               BEGIN_RING( 9 );
+               OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
+               OUT_RING( tex[0].pp_txfilter );
+               OUT_RING( tex[0].pp_txformat );
+               OUT_RING( tex[0].pp_txoffset );
+               OUT_RING( tex[0].pp_txcblend );
+               OUT_RING( tex[0].pp_txablend );
+               OUT_RING( tex[0].pp_tfactor );
+               OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
+               OUT_RING( tex[0].pp_border_color );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_TEX1 ) {
-               radeon_emit_tex1( dev_priv );
-               sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1;
+               BEGIN_RING( 9 );
+               OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
+               OUT_RING( tex[1].pp_txfilter );
+               OUT_RING( tex[1].pp_txformat );
+               OUT_RING( tex[1].pp_txoffset );
+               OUT_RING( tex[1].pp_txcblend );
+               OUT_RING( tex[1].pp_txablend );
+               OUT_RING( tex[1].pp_tfactor );
+               OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
+               OUT_RING( tex[1].pp_border_color );
+               ADVANCE_RING();
        }
 
        if ( dirty & RADEON_UPLOAD_TEX2 ) {
-#if 0
-               radeon_emit_tex2( dev_priv );
-#endif
-               sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2;
+               BEGIN_RING( 9 );
+               OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
+               OUT_RING( tex[2].pp_txfilter );
+               OUT_RING( tex[2].pp_txformat );
+               OUT_RING( tex[2].pp_txoffset );
+               OUT_RING( tex[2].pp_txcblend );
+               OUT_RING( tex[2].pp_txablend );
+               OUT_RING( tex[2].pp_tfactor );
+               OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
+               OUT_RING( tex[2].pp_border_color );
+               ADVANCE_RING();
+       }
+}
+
+/* Emit 1.2 state
+ */
+static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
+                               drm_radeon_state_t *state )
+{
+       RING_LOCALS;
+
+       if (state->dirty & RADEON_UPLOAD_ZBIAS) {
+               BEGIN_RING( 3 );
+               OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) );
+               OUT_RING( state->context2.se_zbias_factor ); 
+               OUT_RING( state->context2.se_zbias_constant ); 
+               ADVANCE_RING();
        }
 
-       sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
-                              RADEON_UPLOAD_TEX1IMAGES |
-                              RADEON_UPLOAD_TEX2IMAGES |
-                              RADEON_REQUIRE_QUIESCENCE);
+       radeon_emit_state( dev_priv, &state->context, 
+                          state->tex, state->dirty );
 }
 
+/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.  
+ */
+static struct { 
+       int start; 
+       int len; 
+       const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+       { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
+       { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
+       { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
+       { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
+       { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
+       { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
+       { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
+       { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
+       { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
+       { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
+       { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
+       { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
+       { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
+       { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
+       { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
+       { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
+       { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
+       { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
+       { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
+       { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
+       { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
+};
+
+
+
+
+
+
+
+
+
 
 #if RADEON_PERFORMANCE_BOXES
 /* ================================================================
@@ -464,39 +315,20 @@ static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
  * CP command dispatch functions
  */
 
-static void radeon_print_dirty( const char *msg, unsigned int flags )
-{
-       DRM_DEBUG( "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-                  msg,
-                  flags,
-                  (flags & RADEON_UPLOAD_CONTEXT)     ? "context, " : "",
-                  (flags & RADEON_UPLOAD_VERTFMT)     ? "vertfmt, " : "",
-                  (flags & RADEON_UPLOAD_LINE)        ? "line, " : "",
-                  (flags & RADEON_UPLOAD_BUMPMAP)     ? "bumpmap, " : "",
-                  (flags & RADEON_UPLOAD_MASKS)       ? "masks, " : "",
-                  (flags & RADEON_UPLOAD_VIEWPORT)    ? "viewport, " : "",
-                  (flags & RADEON_UPLOAD_SETUP)       ? "setup, " : "",
-                  (flags & RADEON_UPLOAD_TCL)         ? "tcl, " : "",
-                  (flags & RADEON_UPLOAD_MISC)        ? "misc, " : "",
-                  (flags & RADEON_UPLOAD_TEX0)        ? "tex0, " : "",
-                  (flags & RADEON_UPLOAD_TEX1)        ? "tex1, " : "",
-                  (flags & RADEON_UPLOAD_TEX2)        ? "tex2, " : "",
-                  (flags & RADEON_UPLOAD_CLIPRECTS)   ? "cliprects, " : "",
-                  (flags & RADEON_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
-}
-
 static void radeon_cp_dispatch_clear( drm_device_t *dev,
                                      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;
+       drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
        int nbox = sarea_priv->nbox;
        drm_clip_rect_t *pbox = sarea_priv->boxes;
        unsigned int flags = clear->flags;
+       u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0;
        int i;
        RING_LOCALS;
-       DRM_DEBUG( "%s\n", __FUNCTION__ );
+       DRM_DEBUG( __FUNCTION__": flags = 0x%x\n", flags );
 
        if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
                unsigned int tmp = flags;
@@ -506,6 +338,28 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
                if ( tmp & RADEON_BACK )  flags |= RADEON_FRONT;
        }
 
+       /* We have to clear the depth and/or stencil buffers by
+        * rendering a quad into just those buffers.  Thus, we have to
+        * make sure the 3D engine is configured correctly.
+        */
+       if ( flags & (RADEON_DEPTH | RADEON_STENCIL) ) {
+               rb3d_cntl = depth_clear->rb3d_cntl;
+
+               if ( flags & RADEON_DEPTH ) {
+                       rb3d_cntl |=  RADEON_Z_ENABLE;
+               } else {
+                       rb3d_cntl &= ~RADEON_Z_ENABLE;
+               }
+
+               if ( flags & RADEON_STENCIL ) {
+                       rb3d_cntl |=  RADEON_STENCIL_ENABLE;
+                       rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
+               } else {
+                       rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
+                       rb3d_stencilrefmask = 0x00000000;
+               }
+       }
+
        for ( i = 0 ; i < nbox ; i++ ) {
                int x = pbox[i].x1;
                int y = pbox[i].y1;
@@ -530,8 +384,7 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
 
                        /* Make sure we restore the 3D state next time.
                         */
-                       dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
-                                                       RADEON_UPLOAD_MASKS);
+                       dev_priv->sarea_priv->ctx_owner = 0;
                }
 
                if ( flags & RADEON_FRONT ) {
@@ -572,36 +425,36 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
                        OUT_RING( (w << 16) | h );
 
                        ADVANCE_RING();
-
                }
 
-               if ( flags & RADEON_DEPTH ) {
-                       drm_radeon_depth_clear_t *depth_clear =
-                          &dev_priv->depth_clear;
+               if ( flags & (RADEON_DEPTH | RADEON_STENCIL) ) {
 
-                       if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-                               radeon_emit_state( dev_priv );
-                       }
+                       radeon_emit_clip_rect( dev_priv,
+                                              &sarea_priv->boxes[i] );
 
-                       /* FIXME: Render a rectangle to clear the depth
-                        * buffer.  So much for those "fast Z clears"...
-                        */
-                       BEGIN_RING( 23 );
+                       BEGIN_RING( 28 );
 
                        RADEON_WAIT_UNTIL_2D_IDLE();
 
                        OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
                        OUT_RING( 0x00000000 );
-                       OUT_RING( depth_clear->rb3d_cntl );
-                       OUT_RING( CP_PACKET0( RADEON_RB3D_ZSTENCILCNTL, 0 ) );
-                       OUT_RING( depth_clear->rb3d_zstencilcntl );
-                       OUT_RING( CP_PACKET0( RADEON_RB3D_PLANEMASK, 0 ) );
-                       OUT_RING( 0x00000000 );
-                       OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
-                       OUT_RING( depth_clear->se_cntl );
-
-                       OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 10 ) );
-                       OUT_RING( RADEON_VTX_Z_PRESENT );
+                       OUT_RING( rb3d_cntl );
+
+                       OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
+                                     depth_clear->rb3d_zstencilcntl );
+                       OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
+                                     rb3d_stencilrefmask );
+                       OUT_RING_REG( RADEON_RB3D_PLANEMASK,
+                                     0x00000000 );
+                       OUT_RING_REG( RADEON_SE_CNTL,
+                                     depth_clear->se_cntl );
+
+                       /* Radeon 7500 doesn't like vertices without
+                        * color.
+                        */
+                       OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) );
+                       OUT_RING( RADEON_VTX_Z_PRESENT |
+                                 RADEON_VTX_PKCOLOR_PRESENT);
                        OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
                                   RADEON_PRIM_WALK_RING |
                                   RADEON_MAOS_ENABLE |
@@ -611,22 +464,23 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev,
                        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( 0x0 );
 
                        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( 0x0 );
 
                        OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
                        OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
                        OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+                       OUT_RING( 0x0 );
 
                        ADVANCE_RING();
 
                        /* Make sure we restore the 3D state next time.
                         */
-                       dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
-                                                       RADEON_UPLOAD_SETUP |
-                                                       RADEON_UPLOAD_MASKS);
+                       dev_priv->sarea_priv->ctx_owner = 0;
                }
        }
 
@@ -690,9 +544,17 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
                          RADEON_DP_SRC_SOURCE_MEMORY |
                          RADEON_GMC_CLR_CMP_CNTL_DIS |
                          RADEON_GMC_WR_MSK_DIS );
-
-               OUT_RING( dev_priv->back_pitch_offset );
-               OUT_RING( dev_priv->front_pitch_offset );
+               
+               /* Make this work even if front & back are flipped:
+                */
+               if (dev_priv->current_page == 0) {
+                       OUT_RING( dev_priv->back_pitch_offset );
+                       OUT_RING( dev_priv->front_pitch_offset );
+               } 
+               else {
+                       OUT_RING( dev_priv->front_pitch_offset );
+                       OUT_RING( dev_priv->back_pitch_offset );
+               }
 
                OUT_RING( (x << 16) | y );
                OUT_RING( (x << 16) | y );
@@ -727,11 +589,12 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
        radeon_cp_performance_boxes( dev_priv );
 #endif
 
-       BEGIN_RING( 6 );
+       BEGIN_RING( 4 );
 
        RADEON_WAIT_UNTIL_3D_IDLE();
+/*
        RADEON_WAIT_UNTIL_PAGE_FLIPPED();
-
+*/
        OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) );
 
        if ( dev_priv->current_page == 0 ) {
@@ -749,6 +612,7 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
         * performing the swapbuffer ioctl.
         */
        dev_priv->sarea_priv->last_frame++;
+       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
 
        BEGIN_RING( 2 );
 
@@ -757,82 +621,121 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
        ADVANCE_RING();
 }
 
+static int bad_prim_vertex_nr( int primitive, int nr )
+{
+       switch (primitive & RADEON_PRIM_TYPE_MASK) {
+       case RADEON_PRIM_TYPE_NONE:
+       case RADEON_PRIM_TYPE_POINT:
+               return nr < 1;
+       case RADEON_PRIM_TYPE_LINE:
+               return (nr & 1) || nr == 0;
+       case RADEON_PRIM_TYPE_LINE_STRIP:
+               return nr < 2;
+       case RADEON_PRIM_TYPE_TRI_LIST:
+       case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
+       case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
+       case RADEON_PRIM_TYPE_RECT_LIST:
+               return nr % 3 || nr == 0;
+       case RADEON_PRIM_TYPE_TRI_FAN:
+       case RADEON_PRIM_TYPE_TRI_STRIP:
+               return nr < 3;
+       default:
+               return 1;
+       }       
+}
+
+
+
+typedef struct {
+       unsigned int start;
+       unsigned int finish;
+       unsigned int prim;
+       unsigned int numverts;
+       unsigned int offset;   
+        unsigned int vc_format;
+} drm_radeon_tcl_prim_t;
+
 static void radeon_cp_dispatch_vertex( drm_device_t *dev,
-                                      drm_buf_t *buf )
+                                      drm_buf_t *buf,
+                                      drm_radeon_tcl_prim_t *prim,
+                                      drm_clip_rect_t *boxes,
+                                      int nbox )
+
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int format = sarea_priv->vc_format;
-       int offset = dev_priv->agp_buffers_offset + buf->offset;
-       int size = buf->used;
-       int prim = buf_priv->prim;
+       drm_clip_rect_t box;
+       int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start;
+       int numverts = (int)prim->numverts;
        int i = 0;
        RING_LOCALS;
-       DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
 
-       if ( 0 )
-               radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
 
-       if ( buf->used ) {
-               buf_priv->dispatched = 1;
+       DRM_DEBUG("%s: hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
+                 __FUNCTION__,
+                 prim->prim,
+                 prim->vc_format,
+                 prim->start,
+                 prim->finish,
+                 prim->numverts);
 
-               if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-                       radeon_emit_state( dev_priv );
+       if (bad_prim_vertex_nr( prim->prim, prim->numverts )) {
+               DRM_ERROR( "bad prim %x numverts %d\n", 
+                          prim->prim, prim->numverts );
+               return;
+       }
+
+
+       do {
+               /* Emit the next cliprect */
+               if ( i < nbox ) {
+                       if (__copy_from_user( &box, &boxes[i], sizeof(box) ))
+                               return;
+
+                       radeon_emit_clip_rect( dev_priv, &box );
                }
 
-               do {
-                       /* Emit the next set of up to three cliprects */
-                       if ( i < sarea_priv->nbox ) {
-                               radeon_emit_clip_rect( dev_priv,
-                                                      &sarea_priv->boxes[i] );
-                       }
+               /* Emit the vertex buffer rendering commands */
+               BEGIN_RING( 5 );
 
-                       /* Emit the vertex buffer rendering commands */
-                       BEGIN_RING( 5 );
+               OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+               OUT_RING( offset );
+               OUT_RING( numverts );
+               OUT_RING( prim->vc_format );
+               OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST |
+                         RADEON_COLOR_ORDER_RGBA |
+                         RADEON_VTX_FMT_RADEON_MODE |
+                         (numverts << RADEON_NUM_VERTICES_SHIFT) );
 
-                       OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
-                       OUT_RING( offset );
-                       OUT_RING( size );
-                       OUT_RING( format );
-                       OUT_RING( prim | RADEON_PRIM_WALK_LIST |
-                                 RADEON_COLOR_ORDER_RGBA |
-                                 RADEON_VTX_FMT_RADEON_MODE |
-                                 (size << RADEON_NUM_VERTICES_SHIFT) );
+               ADVANCE_RING();
 
-                       ADVANCE_RING();
+               i++;
+       } while ( i < nbox );
+}
 
-                       i++;
-               } while ( i < sarea_priv->nbox );
-       }
 
-       if ( buf_priv->discard ) {
-               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
 
-               /* Emit the vertex buffer age */
-               BEGIN_RING( 2 );
-               RADEON_DISPATCH_AGE( buf_priv->age );
-               ADVANCE_RING();
+static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+       RING_LOCALS;
 
-               buf->pending = 1;
-               buf->used = 0;
-               /* FIXME: Check dispatched field */
-               buf_priv->dispatched = 0;
-       }
+       buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
 
-       dev_priv->sarea_priv->last_dispatch++;
+       /* Emit the vertex buffer age */
+       BEGIN_RING( 2 );
+       RADEON_DISPATCH_AGE( buf_priv->age );
+       ADVANCE_RING();
 
-       sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
-       sarea_priv->nbox = 0;
+       buf->pending = 1;
+       buf->used = 0;
 }
 
-
 static void radeon_cp_dispatch_indirect( drm_device_t *dev,
                                         drm_buf_t *buf,
                                         int start, int end )
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
        RING_LOCALS;
        DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
                   buf->idx, start, end );
@@ -853,8 +756,6 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
                        data[dwords++] = RADEON_CP_PACKET2;
                }
 
-               buf_priv->dispatched = 1;
-
                /* Fire off the indirect buffer */
                BEGIN_RING( 3 );
 
@@ -864,100 +765,76 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
 
                ADVANCE_RING();
        }
-
-       if ( buf_priv->discard ) {
-               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
-
-               /* Emit the indirect buffer age */
-               BEGIN_RING( 2 );
-               RADEON_DISPATCH_AGE( buf_priv->age );
-               ADVANCE_RING();
-
-               buf->pending = 1;
-               buf->used = 0;
-               /* FIXME: Check dispatched field */
-               buf_priv->dispatched = 0;
-       }
-
-       dev_priv->sarea_priv->last_dispatch++;
 }
 
+
 static void radeon_cp_dispatch_indices( drm_device_t *dev,
-                                       drm_buf_t *buf,
-                                       int start, int end,
-                                       int count )
+                                       drm_buf_t *elt_buf,
+                                       drm_radeon_tcl_prim_t *prim, 
+                                       drm_clip_rect_t *boxes,
+                                       int nbox )
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int format = sarea_priv->vc_format;
-       int offset = dev_priv->agp_buffers_offset;
-       int prim = buf_priv->prim;
+       drm_clip_rect_t box;
+       int offset = dev_priv->agp_buffers_offset + prim->offset;
        u32 *data;
        int dwords;
        int i = 0;
-       RING_LOCALS;
-       DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
-
-       if ( 0 )
-               radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
-
-       if ( start != end ) {
-               buf_priv->dispatched = 1;
-
-               if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-                       radeon_emit_state( dev_priv );
-               }
-
-               dwords = (end - start + 3) / sizeof(u32);
-
-               data = (u32 *)((char *)dev_priv->buffers->handle
-                              + buf->offset + start);
-
-               data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
-
-               data[1] = offset;
-               data[2] = RADEON_MAX_VB_VERTS;
-               data[3] = format;
-               data[4] = (prim | RADEON_PRIM_WALK_IND |
-                          RADEON_COLOR_ORDER_RGBA |
-                          RADEON_VTX_FMT_RADEON_MODE |
-                          (count << RADEON_NUM_VERTICES_SHIFT) );
-
-               if ( count & 0x1 ) {
-                       data[dwords-1] &= 0x0000ffff;
-               }
-
-               do {
-                       /* Emit the next set of up to three cliprects */
-                       if ( i < sarea_priv->nbox ) {
-                               radeon_emit_clip_rect( dev_priv,
-                                                      &sarea_priv->boxes[i] );
-                       }
+       int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
+       int count = (prim->finish - start) / sizeof(u16);
+
+       DRM_DEBUG("%s: hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
+                 __FUNCTION__,
+                 prim->prim,
+                 prim->vc_format,
+                 prim->start,
+                 prim->finish,
+                 prim->offset,
+                 prim->numverts);
+
+       if (bad_prim_vertex_nr( prim->prim, count )) {
+               DRM_ERROR( "bad prim %x count %d\n", 
+                          prim->prim, count );
+               return;
+       }
 
-                       radeon_cp_dispatch_indirect( dev, buf, start, end );
 
-                       i++;
-               } while ( i < sarea_priv->nbox );
+       if ( start >= prim->finish ||
+            (prim->start & 0x7) ) {
+               DRM_ERROR( "buffer prim %d\n", prim->prim );
+               return;
        }
 
-       if ( buf_priv->discard ) {
-               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
-
-               /* Emit the vertex buffer age */
-               BEGIN_RING( 2 );
-               RADEON_DISPATCH_AGE( buf_priv->age );
-               ADVANCE_RING();
+       dwords = (prim->finish - prim->start + 3) / sizeof(u32);
+
+       data = (u32 *)((char *)dev_priv->buffers->handle +
+                      elt_buf->offset + prim->start);
+
+       data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+       data[1] = offset;
+       data[2] = prim->numverts;
+       data[3] = prim->vc_format;
+       data[4] = (prim->prim |
+                  RADEON_PRIM_WALK_IND |
+                  RADEON_COLOR_ORDER_RGBA |
+                  RADEON_VTX_FMT_RADEON_MODE |
+                  (count << RADEON_NUM_VERTICES_SHIFT) );
+
+       do {
+               if ( i < nbox ) {
+                       if (__copy_from_user( &box, &boxes[i], sizeof(box) ))
+                               return;
+                       
+                       radeon_emit_clip_rect( dev_priv, &box );
+               }
 
-               buf->pending = 1;
-               /* FIXME: Check dispatched field */
-               buf_priv->dispatched = 0;
-       }
+               radeon_cp_dispatch_indirect( dev, elt_buf,
+                                            prim->start,
+                                            prim->finish );
 
-       dev_priv->sarea_priv->last_dispatch++;
+               i++;
+       } while ( i < nbox );
 
-       sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
-       sarea_priv->nbox = 0;
 }
 
 #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
@@ -968,7 +845,6 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_buf_t *buf;
-       drm_radeon_buf_priv_t *buf_priv;
        u32 format;
        u32 *buffer;
        u8 *data;
@@ -986,8 +862,6 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
                   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.
@@ -1058,7 +932,7 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
                        DRM_ERROR( "EFAULT on tex->image\n" );
                        return -EFAULT;
                }
-       } else if ( size < 4 ) {
+       } else if ( size < 4 && size > 0 ) {
                size = 4;
        }
 
@@ -1113,9 +987,9 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
 
        buf->pid = current->pid;
        buf->used = (dwords + 8) * sizeof(u32);
-       buf_priv->discard = 1;
 
        radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
+       radeon_cp_discard_buffer( dev, buf );
 
        /* Flush the pixel cache after the blit completes.  This ensures
         * the texture data is written out to memory before rendering
@@ -1187,7 +1061,67 @@ int radeon_cp_clear( struct inode *inode, struct file *filp,
        return 0;
 }
 
-int radeon_cp_swap( struct inode *inode, struct file *filp,
+
+
+/* Not sure why this isn't set all the time:
+ */ 
+static int radeon_do_init_pageflip( drm_device_t *dev )
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       dev_priv->crtc_offset =      RADEON_READ( RADEON_CRTC_OFFSET );
+       dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL );
+
+       RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset );
+       RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL,
+                     dev_priv->crtc_offset_cntl |
+                     RADEON_CRTC_OFFSET_FLIP_CNTL );
+
+       dev_priv->page_flipping = 1;
+       dev_priv->current_page = 0;
+
+       return 0;
+}
+
+int radeon_do_cleanup_pageflip( drm_device_t *dev )
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+       RADEON_WRITE( RADEON_CRTC_OFFSET,      dev_priv->crtc_offset );
+       RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
+
+       dev_priv->page_flipping = 0;
+       dev_priv->current_page = 0;
+
+       return 0;
+}
+
+/* Swapping and flipping are different operations, need different ioctls.
+ * They can & should be intermixed to support multiple 3d windows.  
+ */
+int radeon_cp_flip( 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_DEBUG( "%s\n", __FUNCTION__ );
+
+       LOCK_TEST_WITH_RETURN( dev );
+
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+       if (!dev_priv->page_flipping) 
+               radeon_do_init_pageflip( dev );
+               
+       radeon_cp_dispatch_flip( dev );
+
+       return 0;
+}
+
+int radeon_cp_swap( struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long arg )
 {
        drm_file_t *priv = filp->private_data;
@@ -1203,13 +1137,8 @@ int radeon_cp_swap( struct inode *inode, struct file *filp,
        if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
                sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-       if ( !dev_priv->page_flipping ) {
-               radeon_cp_dispatch_swap( dev );
-               dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
-                                               RADEON_UPLOAD_MASKS);
-       } else {
-               radeon_cp_dispatch_flip( dev );
-       }
+       radeon_cp_dispatch_swap( dev );
+       dev_priv->sarea_priv->ctx_owner = 0;
 
        return 0;
 }
@@ -1220,10 +1149,11 @@ int radeon_cp_vertex( 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_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_device_dma_t *dma = dev->dma;
        drm_buf_t *buf;
-       drm_radeon_buf_priv_t *buf_priv;
        drm_radeon_vertex_t vertex;
+       drm_radeon_tcl_prim_t prim;
 
        LOCK_TEST_WITH_RETURN( dev );
 
@@ -1255,7 +1185,6 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
        VB_AGE_TEST_WITH_RETURN( dev_priv );
 
        buf = dma->buflist[vertex.idx];
-       buf_priv = buf->dev_private;
 
        if ( buf->pid != current->pid ) {
                DRM_ERROR( "process %d using buffer owned by %d\n",
@@ -1267,11 +1196,37 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       buf->used = vertex.count;
-       buf_priv->prim = vertex.prim;
-       buf_priv->discard = vertex.discard;
+       /* Build up a prim_t record:
+        */
+       if (vertex.count) {
+               buf->used = vertex.count; /* not used? */
 
-       radeon_cp_dispatch_vertex( dev, buf );
+               if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+                       radeon_emit_state( dev_priv,
+                                          &sarea_priv->context_state,
+                                          sarea_priv->tex_state,
+                                          sarea_priv->dirty );
+                       
+                       sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+                                              RADEON_UPLOAD_TEX1IMAGES |
+                                              RADEON_UPLOAD_TEX2IMAGES |
+                                              RADEON_REQUIRE_QUIESCENCE);
+               }
+
+               prim.start = 0;
+               prim.finish = vertex.count; /* unused */
+               prim.prim = vertex.prim;
+               prim.numverts = vertex.count;
+               prim.vc_format = dev_priv->sarea_priv->vc_format;
+               
+               radeon_cp_dispatch_vertex( dev, buf, &prim,
+                                          dev_priv->sarea_priv->boxes,
+                                          dev_priv->sarea_priv->nbox );
+       }
+
+       if (vertex.discard) {
+               radeon_cp_discard_buffer( dev, buf );
+       }
 
        return 0;
 }
@@ -1282,10 +1237,11 @@ int radeon_cp_indices( 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_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_device_dma_t *dma = dev->dma;
        drm_buf_t *buf;
-       drm_radeon_buf_priv_t *buf_priv;
        drm_radeon_indices_t elts;
+       drm_radeon_tcl_prim_t prim;
        int count;
 
        LOCK_TEST_WITH_RETURN( dev );
@@ -1318,7 +1274,6 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
        VB_AGE_TEST_WITH_RETURN( dev_priv );
 
        buf = dma->buflist[elts.idx];
-       buf_priv = buf->dev_private;
 
        if ( buf->pid != current->pid ) {
                DRM_ERROR( "process %d using buffer owned by %d\n",
@@ -1343,10 +1298,35 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
        }
 
        buf->used = elts.end;
-       buf_priv->prim = elts.prim;
-       buf_priv->discard = elts.discard;
 
-       radeon_cp_dispatch_indices( dev, buf, elts.start, elts.end, count );
+       if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+               radeon_emit_state( dev_priv,
+                                  &sarea_priv->context_state,
+                                  sarea_priv->tex_state,
+                                  sarea_priv->dirty );
+
+               sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+                                      RADEON_UPLOAD_TEX1IMAGES |
+                                      RADEON_UPLOAD_TEX2IMAGES |
+                                      RADEON_REQUIRE_QUIESCENCE);
+       }
+
+
+       /* Build up a prim_t record:
+        */
+       prim.start = elts.start;
+       prim.finish = elts.end; 
+       prim.prim = elts.prim;
+       prim.offset = 0;        /* offset from start of dma buffers */
+       prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+       prim.vc_format = dev_priv->sarea_priv->vc_format;
+       
+       radeon_cp_dispatch_indices( dev, buf, &prim,
+                                  dev_priv->sarea_priv->boxes,
+                                  dev_priv->sarea_priv->nbox );
+       if (elts.discard) {
+               radeon_cp_discard_buffer( dev, buf );
+       }
 
        return 0;
 }
@@ -1414,7 +1394,6 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
        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;
        drm_radeon_indirect_t indirect;
        RING_LOCALS;
 
@@ -1440,7 +1419,6 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
        }
 
        buf = dma->buflist[indirect.idx];
-       buf_priv = buf->dev_private;
 
        if ( buf->pid != current->pid ) {
                DRM_ERROR( "process %d using buffer owned by %d\n",
@@ -1462,7 +1440,6 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
        VB_AGE_TEST_WITH_RETURN( dev_priv );
 
        buf->used = indirect.end;
-       buf_priv->discard = indirect.discard;
 
        /* Wait for the 3D stream to idle before the indirect buffer
         * containing 2D acceleration commands is processed.
@@ -1478,6 +1455,434 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp,
         * privileged clients.
         */
        radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+       if (indirect.discard) {
+               radeon_cp_discard_buffer( dev, buf );
+       }
+
+
+       return 0;
+}
 
+int radeon_cp_vertex2( 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_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_device_dma_t *dma = dev->dma;
+       drm_buf_t *buf;
+       drm_radeon_vertex2_t vertex;
+       int i;
+       unsigned char laststate;
+
+       LOCK_TEST_WITH_RETURN( dev );
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+               return -EINVAL;
+       }
+
+       if ( copy_from_user( &vertex, (drm_radeon_vertex_t *)arg,
+                            sizeof(vertex) ) )
+               return -EFAULT;
+
+       DRM_DEBUG( __FUNCTION__": pid=%d index=%d discard=%d\n",
+                  current->pid, vertex.idx, vertex.discard );
+
+       if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+               DRM_ERROR( "buffer index %d (of %d max)\n",
+                          vertex.idx, dma->buf_count - 1 );
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+       buf = dma->buflist[vertex.idx];
+
+       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", vertex.idx );
+               return -EINVAL;
+       }
+       
+       if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+               return -EINVAL;
+
+       for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
+               drm_radeon_prim_t prim;
+               drm_radeon_tcl_prim_t tclprim;
+               
+               if ( copy_from_user( &prim, &vertex.prim[i], sizeof(prim) ) )
+                       return -EFAULT;
+               
+               if ( prim.stateidx != laststate ) {
+                       drm_radeon_state_t state;                              
+                               
+                       if ( copy_from_user( &state, 
+                                            &vertex.state[prim.stateidx], 
+                                            sizeof(state) ) )
+                               return -EFAULT;
+
+                       radeon_emit_state2( dev_priv, &state );
+
+                       laststate = prim.stateidx;
+               }
+
+               tclprim.start = prim.start;
+               tclprim.finish = prim.finish;
+               tclprim.prim = prim.prim;
+               tclprim.vc_format = prim.vc_format;
+
+               if ( prim.prim & RADEON_PRIM_WALK_IND ) {
+                       tclprim.offset = prim.numverts * 64;
+                       tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+
+                       radeon_cp_dispatch_indices( dev, buf, &tclprim,
+                                                   sarea_priv->boxes,
+                                                   sarea_priv->nbox);
+               } else {
+                       tclprim.numverts = prim.numverts;
+                       tclprim.offset = 0; /* not used */
+
+                       radeon_cp_dispatch_vertex( dev, buf, &tclprim,
+                                                  sarea_priv->boxes,
+                                                  sarea_priv->nbox);
+               }
+               
+               if (sarea_priv->nbox == 1)
+                       sarea_priv->nbox = 0;
+       }
+
+       if ( vertex.discard ) {
+               radeon_cp_discard_buffer( dev, buf );
+       }
+
+       return 0;
+}
+
+
+static int radeon_emit_packets( 
+       drm_radeon_private_t *dev_priv,
+       drm_radeon_cmd_header_t header,
+       drm_radeon_cmd_buffer_t *cmdbuf )
+{
+       int sz = packet[(int)header.packet.packet_id].len;
+       int reg = packet[(int)header.packet.packet_id].start;
+       int i, tmp, *data = (int *)cmdbuf->buf;
+       RING_LOCALS;
+   
+       if (sz * sizeof(int) > cmdbuf->bufsz) 
+               return -EINVAL;
+
+       BEGIN_RING( (sz+1) );
+       OUT_RING( CP_PACKET0( reg, (sz-1) ) );
+       for ( i = 0 ; i < sz ; i++ ) {
+               if (__get_user( tmp, &data[i] ))
+                       return -EFAULT;
+               OUT_RING( tmp );
+       }
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+static inline int radeon_emit_scalars( 
+       drm_radeon_private_t *dev_priv,
+       drm_radeon_cmd_header_t header,
+       drm_radeon_cmd_buffer_t *cmdbuf )
+{
+       int sz = header.scalars.count;
+       int i, tmp, *data = (int *)cmdbuf->buf;
+       int start = header.scalars.offset;
+       int stride = header.scalars.stride;
+       RING_LOCALS;
+
+       BEGIN_RING( 3+sz );
+       OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
+       OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+       OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
+       for ( i = 0 ; i < sz ; i++ ) {
+               if (__get_user( tmp, &data[i] ))
+                       return -EFAULT;
+               OUT_RING( tmp );
+       }       
+       ADVANCE_RING();
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+static inline int radeon_emit_vectors( 
+       drm_radeon_private_t *dev_priv,
+       drm_radeon_cmd_header_t header,
+       drm_radeon_cmd_buffer_t *cmdbuf )
+{
+       int sz = header.vectors.count;
+       int i, tmp, *data = (int *)cmdbuf->buf;
+       int start = header.vectors.offset;
+       int stride = header.vectors.stride;
+       RING_LOCALS;
+
+       BEGIN_RING( 3+sz );
+       OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
+       OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+       OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
+       for ( i = 0 ; i < sz ; i++ ) {
+               if (__get_user( tmp, &data[i] ))
+                       return -EFAULT;
+               OUT_RING( tmp );
+       }       
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+
+static int radeon_emit_packet3( drm_device_t *dev,
+                               drm_radeon_cmd_buffer_t *cmdbuf )
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       int cmdsz, tmp;
+       int *cmd = (int *)cmdbuf->buf;
+       int j;
+       RING_LOCALS;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       if (__get_user( tmp, &cmd[0]))
+               return -EFAULT;
+
+       cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+       if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
+           cmdsz * 4 > cmdbuf->bufsz)
+               return -EINVAL;
+
+
+       BEGIN_RING( cmdsz );
+       for (j = 0 ; j < cmdsz ; j++) {
+               if (__get_user( tmp, &cmd[j] ))
+                       return -EFAULT;
+/*             printk( "pk3 %d: %x\n", j, tmp); */
+               OUT_RING( tmp );
+       }
+       ADVANCE_RING();
+
+       cmdbuf->buf += cmdsz * 4;
+       cmdbuf->bufsz -= cmdsz * 4;
+       return 0;
+}
+
+
+static int radeon_emit_packet3_cliprect( drm_device_t *dev,
+                                        drm_radeon_cmd_buffer_t *cmdbuf )
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_clip_rect_t box;
+       int cmdsz, tmp;
+       int *cmd = (int *)cmdbuf->buf;
+       drm_clip_rect_t *boxes = cmdbuf->boxes;
+       int i = 0, j;
+       RING_LOCALS;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       if (__get_user( tmp, &cmd[0]))
+               return -EFAULT;
+
+       cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+       if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
+           cmdsz * 4 > cmdbuf->bufsz)
+               return -EINVAL;
+
+       do {
+               if ( i < cmdbuf->nbox ) {
+                       if (__copy_from_user( &box, &boxes[i], sizeof(box) ))
+                               return -EFAULT;
+                       radeon_emit_clip_rect( dev_priv, &box );
+               }
+               
+               BEGIN_RING( cmdsz );
+               for (j = 0 ; j < cmdsz ; j++) {
+                       if (__get_user( tmp, &cmd[j] ))
+                               return -EFAULT;
+/*                     printk( "pk3_clip %d: %x\n", j, tmp); */
+                       OUT_RING( tmp );
+               }
+               ADVANCE_RING();
+
+       } while ( ++i < cmdbuf->nbox );
+
+       if (cmdbuf->nbox == 1)
+               cmdbuf->nbox = 0;
+
+       cmdbuf->buf += cmdsz * 4;
+       cmdbuf->bufsz -= cmdsz * 4;
+       return 0;
+}
+
+
+
+int radeon_cp_cmdbuf( 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_buf_t *buf = 0;
+       int idx;
+       drm_radeon_cmd_buffer_t cmdbuf;
+       drm_radeon_cmd_header_t header;
+
+       LOCK_TEST_WITH_RETURN( dev );
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+               return -EINVAL;
+       }
+
+       if ( copy_from_user( &cmdbuf, (drm_radeon_cmd_buffer_t *)arg,
+                            sizeof(cmdbuf) ) ) {
+               DRM_ERROR("copy_from_user\n");
+               return -EFAULT;
+       }
+
+       DRM_DEBUG( __FUNCTION__": pid=%d\n", current->pid );
+       RING_SPACE_TEST_WITH_RETURN( dev_priv );
+       VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+
+       if (verify_area( VERIFY_READ, cmdbuf.buf, cmdbuf.bufsz ))
+               return -EFAULT;
+
+       if (verify_area( VERIFY_READ, cmdbuf.boxes, 
+                        cmdbuf.nbox * sizeof(drm_clip_rect_t)))
+               return -EFAULT;
+
+       while ( cmdbuf.bufsz >= sizeof(header) ) {
+               
+               if (__get_user( header.i, (int *)cmdbuf.buf )) {
+                       DRM_ERROR("__get_user %p\n", cmdbuf.buf);
+                       return -EFAULT;
+               }
+
+               cmdbuf.buf += sizeof(header);
+               cmdbuf.bufsz -= sizeof(header);
+
+               switch (header.header.cmd_type) {
+               case RADEON_CMD_PACKET: 
+                       if (radeon_emit_packets( dev_priv, header, &cmdbuf )) {
+                               DRM_ERROR("radeon_emit_packets failed\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               case RADEON_CMD_SCALARS:
+                       if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
+                               DRM_ERROR("radeon_emit_scalars failed\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               case RADEON_CMD_VECTORS:
+                       if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
+                               DRM_ERROR("radeon_emit_vectors failed\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               case RADEON_CMD_DMA_DISCARD:
+                       idx = header.dma.buf_idx;
+                       if ( idx < 0 || idx >= dma->buf_count ) {
+                               DRM_ERROR( "buffer index %d (of %d max)\n",
+                                          idx, dma->buf_count - 1 );
+                               return -EINVAL;
+                       }
+
+                       buf = dma->buflist[idx];
+                       if ( buf->pid != current->pid || buf->pending ) {
+                               DRM_ERROR( "bad buffer\n" );
+                               return -EINVAL;
+                       }
+
+                       radeon_cp_discard_buffer( dev, buf );
+                       break;
+
+               case RADEON_CMD_PACKET3:
+                       if (radeon_emit_packet3( dev, &cmdbuf )) {
+                               DRM_ERROR("radeon_emit_packet3 failed\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               case RADEON_CMD_PACKET3_CLIP:
+                       if (radeon_emit_packet3_cliprect( dev, &cmdbuf )) {
+                               DRM_ERROR("radeon_emit_packet3_clip failed\n");
+                               return -EINVAL;
+                       }
+                       break;
+
+               default:
+                       DRM_ERROR("bad cmd_type %d at %p\n", 
+                                 header.header.cmd_type,
+                                 cmdbuf.buf - sizeof(header));
+                       return -EINVAL;
+               }
+       }
+
+
+       return 0;
+}
+
+
+
+int radeon_cp_getparam( 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_radeon_getparam_t param;
+       int value;
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+               return -EINVAL;
+       }
+
+       if ( copy_from_user( &param, (drm_radeon_getparam_t *)arg,
+                            sizeof(param) ) ) {
+               DRM_ERROR("copy_from_user\n");
+               return -EFAULT;
+       }
+
+       DRM_DEBUG( __FUNCTION__": pid=%d\n", current->pid );
+
+       switch( param.param ) {
+       case RADEON_PARAM_AGP_BUFFER_OFFSET:
+               value = dev_priv->agp_buffers_offset;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
+               DRM_ERROR( "copy_to_user\n" );
+               return -EFAULT;
+       }
+       
        return 0;
 }
diff --git a/drivers/char/drm/sis.h b/drivers/char/drm/sis.h
new file mode 100644 (file)
index 0000000..02f0308
--- /dev/null
@@ -0,0 +1,56 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ * 
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.2 2001/12/19 21:25:59 dawes Exp $ */
+
+#ifndef __SIS_H__
+#define __SIS_H__
+
+/* This remains constant for all DRM template files.
+ * Name it sisdrv_##x as there's a conflict with sis_free/malloc in the kernel
+ * that's used for fb devices 
+ */
+#define DRM(x) sisdrv_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP             1
+#define __MUST_HAVE_AGP                0
+#define __HAVE_MTRR            1
+#define __HAVE_CTX_BITMAP      1
+
+/* Buffer customization:
+ */
+#define DRIVER_AGP_BUFFERS_MAP( dev )                                  \
+       ((drm_sis_private_t *)((dev)->dev_private))->buffers
+
+extern int sis_init_context(int context);
+extern int sis_final_context(int context);
+
+#define DRIVER_CTX_CTOR sis_init_context
+#define DRIVER_CTX_DTOR sis_final_context
+
+#endif
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
new file mode 100644 (file)
index 0000000..339ed5a
--- /dev/null
@@ -0,0 +1,36 @@
+
+#ifndef _sis_drm_public_h_
+#define _sis_drm_public_h_
+
+typedef struct {
+  int context;
+  unsigned int offset;
+  unsigned int size;
+  unsigned int free;
+} drm_sis_mem_t;
+
+typedef struct {
+  unsigned int offset, size;
+} drm_sis_agp_t;
+
+typedef struct {
+  unsigned int left, right;
+} drm_sis_flip_t;
+
+#ifdef __KERNEL__
+
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+
+int sisp_agp_init(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+
+#endif
+
+#endif
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
new file mode 100644 (file)
index 0000000..2d9612f
--- /dev/null
@@ -0,0 +1,74 @@
+/* sis.c -- sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include "sis.h"
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+
+#define DRIVER_AUTHOR   "SIS"
+#define DRIVER_NAME     "sis"
+#define DRIVER_DESC     "SIS 300/630/540"
+#define DRIVER_DATE     "20010503"
+#define DRIVER_MAJOR    1
+#define DRIVER_MINOR    0
+#define DRIVER_PATCHLEVEL  0
+
+#define DRIVER_IOCTLS \
+        [DRM_IOCTL_NR(SIS_IOCTL_FB_ALLOC)]   = { sis_fb_alloc,   1, 0 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_FB_FREE)]    = { sis_fb_free,    1, 0 }, \
+        /* AGP Memory Management */                                      \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_INIT)]   = { sisp_agp_init,          1, 0 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_ALLOC)]  = { sisp_agp_alloc,  1, 0 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_FREE)]   = { sisp_agp_free,          1, 0 }
+#if 0 /* these don't appear to be defined */
+       /* SIS Stereo */                                                 
+       [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]    = { sis_control,     1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP)]       = { sis_flip,       1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_INIT)]  = { sis_flip_init,          1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_FINAL)] = { sis_flip_final,  1, 1 }
+#endif
+
+#define __HAVE_COUNTERS                5
+
+#include "drm_auth.h"
+#include "drm_agpsupport.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lists.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
new file mode 100644 (file)
index 0000000..844e38b
--- /dev/null
@@ -0,0 +1,45 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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.
+ * 
+ */
+
+#ifndef _SIS_DRV_H_
+#define _SIS_DRV_H_
+
+typedef struct drm_sis_private {
+       drm_map_t *buffers;
+} drm_sis_private_t;
+
+/* Stereo ? - this was never committed */
+
+int sis_flip(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+int sis_flip_init(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+int sis_flip_final(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg);
+void flip_final(void);
+
+#endif
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
new file mode 100644 (file)
index 0000000..95880a4
--- /dev/null
@@ -0,0 +1,406 @@
+/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ * 
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+
+#include "sis_ds.h"
+
+/* Set Data Structure, not check repeated value
+ * temporarily used
+ */
+
+set_t *setInit(void)
+{
+  int i;
+  set_t *set;
+
+  set = (set_t *)MALLOC(sizeof(set_t));
+  for(i = 0; i < SET_SIZE; i++){
+    set->list[i].free_next = i+1;    
+    set->list[i].alloc_next = -1;
+  }    
+  set->list[SET_SIZE-1].free_next = -1;
+  set->free = 0;
+  set->alloc = -1;
+  set->trace = -1;
+  
+  return set;
+}
+
+int setAdd(set_t *set, ITEM_TYPE item)
+{
+  int free = set->free;
+  
+  if(free != -1){
+    set->list[free].val = item;
+    set->free = set->list[free].free_next;
+  }
+  else{
+    return 0;
+  }
+
+  set->list[free].alloc_next = set->alloc;
+  set->alloc = free;  
+  set->list[free].free_next = -1;    
+
+  return 1;
+}
+
+int setDel(set_t *set, ITEM_TYPE item)
+{
+  int alloc = set->alloc;
+  int prev = -1;  
+  
+  while(alloc != -1){
+    if(set->list[alloc].val == item){
+      if(prev != -1)      
+        set->list[prev].alloc_next = set->list[alloc].alloc_next; 
+      else
+        set->alloc = set->list[alloc].alloc_next;
+      break;
+    }
+    prev = alloc;
+    alloc = set->list[alloc].alloc_next;      
+  }
+
+  if(alloc == -1)
+    return 0;
+  
+  set->list[alloc].free_next = set->free;
+  set->free = alloc;
+  set->list[alloc].alloc_next = -1;   
+
+  return 1;
+}
+
+/* setFirst -> setAdd -> setNext is wrong */
+
+int setFirst(set_t *set, ITEM_TYPE *item)
+{
+  if(set->alloc == -1)
+    return 0;
+
+  *item = set->list[set->alloc].val;
+  set->trace = set->list[set->alloc].alloc_next; 
+
+  return 1;
+}
+
+int setNext(set_t *set, ITEM_TYPE *item)
+{
+  if(set->trace == -1)
+    return 0;
+  
+  *item = set->list[set->trace].val;
+  set->trace = set->list[set->trace].alloc_next;      
+
+  return 1;
+}
+
+int setDestroy(set_t *set)
+{
+  FREE(set);
+
+  return 1;
+}
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Keith Whitwell
+ *
+ * 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 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
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define ISFREE(bptr) ((bptr)->free)
+
+#define PRINTF(fmt, arg...) do{}while(0)
+#define fprintf(fmt, arg...) do{}while(0)
+
+static void *calloc(size_t nmemb, size_t size)
+{
+  void *addr;
+  addr = kmalloc(nmemb*size, GFP_KERNEL);
+  memset(addr, 0, nmemb*size);
+  return addr;
+}
+#define free(n) kfree(n)
+           
+void mmDumpMemInfo( memHeap_t *heap )
+{
+  TMemBlock *p;
+
+  PRINTF ("Memory heap %p:\n", heap);
+  if (heap == 0) {
+    PRINTF ("  heap == 0\n");
+  } else {
+    p = (TMemBlock *)heap;
+    while (p) {
+      PRINTF ("  Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
+            p->free ? '.':'U',
+            p->reserved ? 'R':'.');
+      p = p->next;
+    }
+  }
+  PRINTF ("End of memory blocks\n");
+}
+
+memHeap_t *mmInit(int ofs,
+                 int size)
+{
+   PMemBlock blocks;
+  
+   if (size <= 0) {
+      return 0;
+   }
+   blocks = (TMemBlock *) calloc(1,sizeof(TMemBlock));
+   if (blocks) {
+      blocks->ofs = ofs;
+      blocks->size = size;
+      blocks->free = 1;
+      return (memHeap_t *)blocks;
+   } else
+      return 0;
+}
+
+/* Kludgey workaround for existing i810 server.  Remove soon.
+ */
+memHeap_t *mmAddRange( memHeap_t *heap,
+                      int ofs,
+                      int size )
+{
+   PMemBlock blocks;
+   blocks = (TMemBlock *) calloc(2,sizeof(TMemBlock));
+   if (blocks) {
+      blocks[0].size = size;
+      blocks[0].free = 1;
+      blocks[0].ofs = ofs;
+      blocks[0].next = &blocks[1];
+
+      /* Discontinuity - stops JoinBlock from trying to join non-adjacent
+       * ranges.
+       */
+      blocks[1].size = 0;
+      blocks[1].free = 0;
+      blocks[1].ofs = ofs+size;
+      blocks[1].next = (PMemBlock) heap;      
+      return (memHeap_t *)blocks;
+   } 
+   else
+      return heap;
+}
+
+static TMemBlock* SliceBlock(TMemBlock *p, 
+                            int startofs, int size, 
+                            int reserved, int alignment)
+{
+  TMemBlock *newblock;
+
+  /* break left */
+  if (startofs > p->ofs) {
+    newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+    newblock->ofs = startofs;
+    newblock->size = p->size - (startofs - p->ofs);
+    newblock->free = 1;
+    newblock->next = p->next;
+    p->size -= newblock->size;
+    p->next = newblock;
+    p = newblock;
+  }
+
+  /* break right */
+  if (size < p->size) {
+    newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+    newblock->ofs = startofs + size;
+    newblock->size = p->size - size;
+    newblock->free = 1;
+    newblock->next = p->next;
+    p->size = size;
+    p->next = newblock;
+  }
+
+  /* p = middle block */
+  p->align = alignment;
+  p->free = 0;
+  p->reserved = reserved;
+  return p;
+}
+
+PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
+{
+  int mask,startofs,endofs;
+  TMemBlock *p;
+
+  if (!heap || align2 < 0 || size <= 0)
+    return NULL;
+  mask = (1 << align2)-1;
+  startofs = 0;
+  p = (TMemBlock *)heap;
+  while (p) {
+    if (ISFREE(p)) {
+      startofs = (p->ofs + mask) & ~mask;
+      if ( startofs < startSearch ) {
+       startofs = startSearch;
+      }
+      endofs = startofs+size;
+      if (endofs <= (p->ofs+p->size))
+       break;
+    }
+    p = p->next;
+  }
+  if (!p)
+    return NULL;
+  p = SliceBlock(p,startofs,size,0,mask+1);
+  p->heap = heap;
+  return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock *p)
+{
+  if (p->free && p->next && p->next->free) {
+    TMemBlock *q = p->next;
+    p->size += q->size;
+    p->next = q->next;
+    free(q);
+    return 1;
+  }
+  return 0;
+}
+
+int mmFreeMem(PMemBlock b)
+{
+  TMemBlock *p,*prev;
+
+  if (!b)
+    return 0;
+  if (!b->heap) {
+     fprintf(stderr, "no heap\n");
+     return -1;
+  }
+  p = b->heap;
+  prev = NULL;
+  while (p && p != b) {
+    prev = p;
+    p = p->next;
+  }
+  if (!p || p->free || p->reserved) {
+     if (!p)
+       fprintf(stderr, "block not found in heap\n");
+     else if (p->free)
+       fprintf(stderr, "block already free\n");
+     else
+       fprintf(stderr, "block is reserved\n");
+    return -1;
+  }
+  p->free = 1;
+  Join2Blocks(p);
+  if (prev)
+    Join2Blocks(prev);
+  return 0;
+}
+
+int mmReserveMem(memHeap_t *heap, int offset,int size)
+{
+  int endofs;
+  TMemBlock *p;
+
+  if (!heap || size <= 0)
+    return -1;
+  endofs = offset+size;
+  p = (TMemBlock *)heap;
+  while (p && p->ofs <= offset) {
+    if (ISFREE(p) && endofs <= (p->ofs+p->size)) {
+      SliceBlock(p,offset,size,1,1);
+      return 0;
+    }
+    p = p->next;
+  }
+  return -1;
+}
+
+int mmFreeReserved(memHeap_t *heap, int offset)
+{
+  TMemBlock *p,*prev;
+
+  if (!heap)
+    return -1;
+  p = (TMemBlock *)heap;
+  prev = NULL;
+  while (p && p->ofs != offset) {
+    prev = p;
+    p = p->next;
+  }
+  if (!p || !p->reserved)
+    return -1;
+  p->free = 1;
+  p->reserved = 0;
+  Join2Blocks(p);
+  if (prev)
+    Join2Blocks(prev);
+  return 0;
+}
+
+void mmDestroy(memHeap_t *heap)
+{
+  TMemBlock *p,*q;
+
+  if (!heap)
+    return;
+  p = (TMemBlock *)heap;
+  while (p) {
+    q = p->next;
+    free(p);
+    p = q;
+  }
+}
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
new file mode 100644 (file)
index 0000000..c3367db
--- /dev/null
@@ -0,0 +1,163 @@
+/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ * 
+ */
+
+#ifndef _sis_ds_h_
+#define _sis_ds_h_
+
+/* Set Data Structure */
+
+#define SET_SIZE 5000
+#define MALLOC(s) kmalloc(s, GFP_KERNEL)
+#define FREE(s) kfree(s)
+
+typedef unsigned int ITEM_TYPE;
+
+typedef struct {
+  ITEM_TYPE val;
+  int alloc_next, free_next;
+} list_item_t;
+
+typedef struct {
+  int alloc;
+  int free;
+  int trace;
+  list_item_t list[SET_SIZE];
+} set_t;
+
+set_t *setInit(void);
+int setAdd(set_t *set, ITEM_TYPE item);
+int setDel(set_t *set, ITEM_TYPE item);
+int setFirst(set_t *set, ITEM_TYPE *item);
+int setNext(set_t *set, ITEM_TYPE *item);
+int setDestroy(set_t *set);
+
+#endif
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Keith Whitwell
+ *
+ * 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 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
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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.
+ *
+ */
+
+#ifndef MM_INC
+#define MM_INC
+
+struct mem_block_t {
+  struct mem_block_t *next;
+  struct mem_block_t *heap;
+  int ofs,size;
+  int align;
+  int free:1;
+  int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{ return b->size; }
+
+static __inline__ int mmOffset(PMemBlock b)
+{ return b->ofs; }
+
+static __inline__ void mmMarkReserved(PMemBlock b)
+{ b->reserved = 1; }
+
+/* 
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *mmInit( int ofs, int size );
+
+
+
+memHeap_t *mmAddRange( memHeap_t *heap,
+                      int ofs,
+                      int size );
+
+
+/*
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+ * restrict the search to free memory after 'startSearch'
+ * depth and back buffers should be in different 4mb banks
+ * to get better page hits if possible
+ * input:      size = size of block
+ *             align2 = 2^align2 bytes alignment
+ *             startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+PMemBlock  mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch );
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int  mmFreeMem( PMemBlock b );
+
+/*
+ * Reserve 'size' bytes block start at offset
+ * This is used to prevent allocation of memory already used
+ * by the X server for the front buffer, pixmaps, and cursor
+ * input: size, offset
+ * output: 0 if OK, -1 if error
+ */
+int mmReserveMem( memHeap_t *heap, int offset,int size );
+int mmFreeReserved( memHeap_t *heap, int offset );
+
+/*
+ * destroy MM
+ */
+void mmDestroy( memHeap_t *mmInit );
+
+/* For debuging purpose. */
+void mmDumpMemInfo( memHeap_t *mmInit );
+
+#endif
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
new file mode 100644 (file)
index 0000000..8183276
--- /dev/null
@@ -0,0 +1,307 @@
+/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ * 
+ */
+
+#define __NO_VERSION__
+#include "sis.h"
+#include <linux/sisfb.h>
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+#include "sis_ds.h"
+
+#define MAX_CONTEXT 100
+#define VIDEO_TYPE 0 
+#define AGP_TYPE 1
+
+typedef struct {
+  int used;
+  int context;
+  set_t *sets[2]; /* 0 for video, 1 for AGP */
+} sis_context_t;
+
+static sis_context_t global_ppriv[MAX_CONTEXT];
+
+static int add_alloc_set(int context, int type, unsigned int val)
+{
+  int i, retval = 0;
+  
+  for(i = 0; i < MAX_CONTEXT; i++)
+    if(global_ppriv[i].used && global_ppriv[i].context == context){
+      retval = setAdd(global_ppriv[i].sets[type], val);
+      break;
+    }
+  return retval;
+}
+
+static int del_alloc_set(int context, int type, unsigned int val)
+{  
+  int i, retval = 0;
+  for(i = 0; i < MAX_CONTEXT; i++)
+    if(global_ppriv[i].used && global_ppriv[i].context == context){
+      retval = setDel(global_ppriv[i].sets[type], val);
+      break;
+    }
+  return retval;
+}
+
+/* fb management via fb device */ 
+#if 1
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg)
+{
+  drm_sis_mem_t fb;
+  struct sis_memreq req;
+  int retval = 0;
+   
+  if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
+         return -EFAULT;
+  
+  req.size = fb.size;
+  sis_malloc(&req);
+  if(req.offset){
+    /* TODO */
+    fb.offset = req.offset;
+    fb.free = req.offset;
+    if(!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)){
+      DRM_DEBUG("adding to allocation set fails\n");
+      sis_free(req.offset);
+      retval = -1;
+    }
+  }
+  else{  
+    fb.offset = 0;
+    fb.size = 0;
+    fb.free = 0;
+  }
+   
+  if (copy_to_user((drm_sis_mem_t *)arg, &fb, sizeof(fb))) return -EFAULT;
+
+  DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+
+  return retval;
+}
+
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg)
+{
+  drm_sis_mem_t fb;
+  int retval = 0;
+    
+  if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
+         return -EFAULT;
+  
+  if(!fb.free){
+    return -1;
+  }
+
+  sis_free(fb.free);
+  if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
+    retval = -1;
+
+  DRM_DEBUG("free fb, offset = %d\n", fb.free);
+  
+  return retval;
+}
+
+#else
+
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg)
+{
+  return -1;
+}
+
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg)
+{
+  return 0;
+}
+
+#endif
+
+/* agp memory management */ 
+#if 1
+
+static memHeap_t *AgpHeap = NULL;
+
+int sisp_agp_init(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg)
+{
+  drm_sis_agp_t agp;
+   
+  if (copy_from_user(&agp, (drm_sis_agp_t *)arg, sizeof(agp)))
+         return -EFAULT;
+
+  AgpHeap = mmInit(agp.offset, agp.size);
+
+  DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+  
+  return 0;
+}
+
+int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg)
+{
+  drm_sis_mem_t agp;
+  PMemBlock block;
+  int retval = 0;
+   
+  if(!AgpHeap)
+    return -1;
+  
+  if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
+         return -EFAULT;
+  
+  block = mmAllocMem(AgpHeap, agp.size, 0, 0);
+  if(block){
+    /* TODO */
+    agp.offset = block->ofs;
+    agp.free = (unsigned int)block;
+    if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){
+      DRM_DEBUG("adding to allocation set fails\n");
+      mmFreeMem((PMemBlock)agp.free);
+      retval = -1;
+    }
+  }
+  else{  
+    agp.offset = 0;
+    agp.size = 0;
+    agp.free = 0;
+  }
+   
+  if (copy_to_user((drm_sis_mem_t *)arg, &agp, sizeof(agp))) return -EFAULT;
+
+  DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
+
+  return retval;
+}
+
+int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
+                 unsigned long arg)
+{
+  drm_sis_mem_t agp;
+  int retval = 0;
+
+  if(!AgpHeap)
+    return -1;
+    
+  if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
+         return -EFAULT;
+  
+  if(!agp.free){
+    return -1;
+  }
+
+  mmFreeMem((PMemBlock)agp.free);
+  if(!del_alloc_set(agp.context, AGP_TYPE, agp.free))
+    retval = -1;
+
+  DRM_DEBUG("free agp, free = %d\n", agp.free);
+  
+  return retval;
+}
+
+#endif
+
+int sis_init_context(int context)
+{
+       int i;
+       
+       for(i = 0; i < MAX_CONTEXT ; i++)
+         if(global_ppriv[i].used && (global_ppriv[i].context == context))
+           break;
+
+       if(i >= MAX_CONTEXT){
+         for(i = 0; i < MAX_CONTEXT ; i++){
+           if(!global_ppriv[i].used){
+             global_ppriv[i].context = context;
+             global_ppriv[i].used = 1;
+             global_ppriv[i].sets[0] = setInit();
+             global_ppriv[i].sets[1] = setInit();
+             DRM_DEBUG("init allocation set, socket=%d, context = %d\n", 
+                        i, context);
+             break;
+           }   
+         }
+         if((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+            (global_ppriv[i].sets[1] == NULL)){
+           return 0;
+         }
+       }
+       
+       return 1;
+}
+
+int sis_final_context(int context)
+{
+       int i;
+
+       for(i=0; i<MAX_CONTEXT; i++)
+         if(global_ppriv[i].used && (global_ppriv[i].context == context))
+           break;
+          
+       if(i < MAX_CONTEXT){
+         set_t *set;
+         unsigned int item;
+         int retval;
+         
+         DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+         /* Video Memory */
+         set = global_ppriv[i].sets[0];
+         retval = setFirst(set, &item);
+         while(retval){
+           DRM_DEBUG("free video memory 0x%x\n", item);
+            sis_free(item);
+           retval = setNext(set, &item);
+         }
+         setDestroy(set);
+
+         /* AGP Memory */
+         set = global_ppriv[i].sets[1];
+         retval = setFirst(set, &item);
+         while(retval){
+           DRM_DEBUG("free agp memory 0x%x\n", item);
+           mmFreeMem((PMemBlock)item);
+           retval = setNext(set, &item);
+         }
+         setDestroy(set);
+         
+         global_ppriv[i].used = 0;       
+        }
+
+       /* turn-off auto-flip */
+       /* TODO */
+#if defined(SIS_STEREO)
+       flip_final();
+#endif
+       
+       return 1;
+}