Merge branch 'radeon-ttm' of git://people.freedesktop.org/~airlied/drm into modesetti...
authorJerome Glisse <glisse@freedesktop.org>
Sat, 27 Oct 2007 22:55:27 +0000 (00:55 +0200)
committerJerome Glisse <glisse@freedesktop.org>
Sat, 27 Oct 2007 22:55:27 +0000 (00:55 +0200)
Conflicts:

linux-core/Makefile.kernel
linux-core/drmP.h
shared-core/radeon_cp.c
shared-core/radeon_drv.h
shared-core/radeon_irq.c

modified:   linux-core/Makefile.kernel
modified:   linux-core/ati_pcigart.c
modified:   linux-core/drmP.h
new file:   linux-core/radeon_buffer.c
modified:   linux-core/radeon_drv.c
new file:   linux-core/radeon_fence.c
modified:   shared-core/radeon_cp.c
modified:   shared-core/radeon_drm.h
modified:   shared-core/radeon_drv.h
modified:   shared-core/radeon_irq.c
modified:   tests/ttmtest/src/ttmtest.c

293 files changed:
.gitignore
Makefile.am
bsd-core/Makefile
bsd-core/ati_pcigart.c
bsd-core/drm.h [new symlink]
bsd-core/drmP.h
bsd-core/drm_agpsupport.c
bsd-core/drm_auth.c
bsd-core/drm_bufs.c
bsd-core/drm_context.c
bsd-core/drm_dma.c
bsd-core/drm_drawable.c
bsd-core/drm_drv.c
bsd-core/drm_fops.c
bsd-core/drm_ioctl.c
bsd-core/drm_irq.c
bsd-core/drm_lock.c
bsd-core/drm_memory.c
bsd-core/drm_pci.c
bsd-core/drm_sarea.h [new symlink]
bsd-core/drm_scatter.c
bsd-core/drm_sysctl.c
bsd-core/drm_vm.c
bsd-core/i915_dma.c [new symlink]
bsd-core/i915_drm.h [new symlink]
bsd-core/i915_drv.h [new symlink]
bsd-core/i915_irq.c [new symlink]
bsd-core/i915_mem.c [new symlink]
bsd-core/mach64_dma.c [new symlink]
bsd-core/mach64_drm.h [new symlink]
bsd-core/mach64_drv.h [new symlink]
bsd-core/mach64_irq.c [new symlink]
bsd-core/mach64_state.c [new symlink]
bsd-core/mga_dma.c [new symlink]
bsd-core/mga_drm.h [new symlink]
bsd-core/mga_drv.h [new symlink]
bsd-core/mga_irq.c [new symlink]
bsd-core/mga_state.c [new symlink]
bsd-core/mga_ucode.h [new symlink]
bsd-core/mga_warp.c [new symlink]
bsd-core/r128_cce.c [new symlink]
bsd-core/r128_drm.h [new symlink]
bsd-core/r128_drv.h [new symlink]
bsd-core/r128_irq.c [new symlink]
bsd-core/r128_state.c [new symlink]
bsd-core/r300_cmdbuf.c [new symlink]
bsd-core/r300_reg.h [new symlink]
bsd-core/radeon_cp.c [new symlink]
bsd-core/radeon_drm.h [new symlink]
bsd-core/radeon_drv.h [new symlink]
bsd-core/radeon_irq.c [new symlink]
bsd-core/radeon_mem.c [new symlink]
bsd-core/radeon_state.c [new symlink]
bsd-core/savage_bci.c [new symlink]
bsd-core/savage_drm.h [new symlink]
bsd-core/savage_drv.h [new symlink]
bsd-core/savage_state.c [new symlink]
bsd-core/sis_drm.h [new symlink]
bsd-core/sis_drv.h [new symlink]
bsd-core/sis_ds.c [new symlink]
bsd-core/sis_ds.h [new symlink]
bsd-core/sis_mm.c [new symlink]
bsd-core/tdfx_drv.h [new symlink]
bsd-core/via_3d_reg.h [new symlink]
bsd-core/via_dma.c [new symlink]
bsd-core/via_drm.h [new symlink]
bsd-core/via_drv.h [new symlink]
bsd-core/via_ds.c [new symlink]
bsd-core/via_ds.h [new symlink]
bsd-core/via_irq.c [new symlink]
bsd-core/via_map.c [new symlink]
bsd-core/via_mm.c [new symlink]
bsd-core/via_mm.h [new symlink]
bsd-core/via_verifier.c [new symlink]
bsd-core/via_verifier.h [new symlink]
bsd-core/via_video.c [new symlink]
configure.ac
libdrm/Makefile.am
libdrm/xf86drm.c
libdrm/xf86drm.h
libdrm/xf86drmHash.c
libdrm/xf86drmMode.c [new file with mode: 0644]
libdrm/xf86drmMode.h [new file with mode: 0644]
libdrm/xf86drmRandom.c
libdrm/xf86drmSL.c
libdrm/xf86mm.h
linux-core/Makefile
linux-core/Makefile.kernel
linux-core/ati_pcigart.c
linux-core/drmP.h
linux-core/drm_agpsupport.c
linux-core/drm_auth.c
linux-core/drm_bo.c
linux-core/drm_bo_lock.c [new file with mode: 0644]
linux-core/drm_bo_move.c
linux-core/drm_bufs.c
linux-core/drm_compat.c
linux-core/drm_compat.h
linux-core/drm_context.c
linux-core/drm_crtc.c [new file with mode: 0644]
linux-core/drm_crtc.h [new file with mode: 0644]
linux-core/drm_dma.c
linux-core/drm_drawable.c
linux-core/drm_drv.c
linux-core/drm_edid.c [new file with mode: 0644]
linux-core/drm_edid.h [new file with mode: 0644]
linux-core/drm_fb.c [new file with mode: 0644]
linux-core/drm_fence.c
linux-core/drm_fops.c
linux-core/drm_hashtab.c
linux-core/drm_hashtab.h
linux-core/drm_ioc32.c
linux-core/drm_ioctl.c
linux-core/drm_irq.c
linux-core/drm_lock.c
linux-core/drm_memory.c
linux-core/drm_memory_debug.c
linux-core/drm_memory_debug.h
linux-core/drm_mm.c
linux-core/drm_modes.c [new file with mode: 0644]
linux-core/drm_object.c
linux-core/drm_objects.h
linux-core/drm_os_linux.h
linux-core/drm_pci.c
linux-core/drm_proc.c
linux-core/drm_scatter.c
linux-core/drm_sman.c
linux-core/drm_sman.h
linux-core/drm_stub.c
linux-core/drm_sysfs.c
linux-core/drm_ttm.c
linux-core/drm_vm.c
linux-core/ffb_context.c
linux-core/ffb_drv.c
linux-core/ffb_drv.h
linux-core/i810_dma.c
linux-core/i810_drm.h
linux-core/i810_drv.h
linux-core/i915_buffer.c
linux-core/i915_drv.c
linux-core/i915_fence.c
linux-core/i915_init.c [new symlink]
linux-core/i915_ioc32.c
linux-core/intel_crt.c [new file with mode: 0644]
linux-core/intel_display.c [new file with mode: 0644]
linux-core/intel_drv.h [new file with mode: 0644]
linux-core/intel_fb.c [new file with mode: 0644]
linux-core/intel_i2c.c [new file with mode: 0644]
linux-core/intel_lvds.c [new file with mode: 0644]
linux-core/intel_modes.c [new file with mode: 0644]
linux-core/intel_sdvo.c [new file with mode: 0644]
linux-core/intel_sdvo_regs.h [new file with mode: 0644]
linux-core/mga_drv.c
linux-core/mga_ioc32.c
linux-core/nouveau_dma.c [new symlink]
linux-core/nouveau_dma.h [new symlink]
linux-core/nouveau_drv.c
linux-core/nouveau_ioc32.c
linux-core/nouveau_notifier.c [new symlink]
linux-core/nouveau_sgdma.c [new file with mode: 0644]
linux-core/nouveau_swmthd.c [new symlink]
linux-core/nouveau_swmthd.h [new symlink]
linux-core/nv04_fifo.c [new symlink]
linux-core/nv04_instmem.c [new symlink]
linux-core/nv10_fifo.c [new symlink]
linux-core/nv30_graph.c [deleted symlink]
linux-core/nv40_fifo.c [new symlink]
linux-core/nv50_fifo.c [new symlink]
linux-core/nv50_graph.c [new symlink]
linux-core/nv50_instmem.c [new symlink]
linux-core/nv50_mc.c [new symlink]
linux-core/r128_ioc32.c
linux-core/radeon_buffer.c
linux-core/radeon_drv.c
linux-core/radeon_fence.c
linux-core/radeon_ioc32.c
linux-core/sis_drv.c
linux-core/sis_mm.c
linux-core/via_buffer.c
linux-core/via_dmablit.c
linux-core/via_dmablit.h
linux-core/via_fence.c
linux-core/via_mm.c
linux-core/xgi_cmdlist.c [new file with mode: 0644]
linux-core/xgi_cmdlist.h [new file with mode: 0644]
linux-core/xgi_drm.h [new symlink]
linux-core/xgi_drv.c [new file with mode: 0644]
linux-core/xgi_drv.h [new file with mode: 0644]
linux-core/xgi_fb.c [new file with mode: 0644]
linux-core/xgi_fence.c [new file with mode: 0644]
linux-core/xgi_ioc32.c [new file with mode: 0644]
linux-core/xgi_misc.c [new file with mode: 0644]
linux-core/xgi_misc.h [new file with mode: 0644]
linux-core/xgi_pcie.c [new file with mode: 0644]
linux-core/xgi_regs.h [new file with mode: 0644]
shared-core/Makefile.am
shared-core/drm.h
shared-core/drm_pciids.txt
shared-core/drm_sarea.h
shared-core/i915_dma.c
shared-core/i915_drm.h
shared-core/i915_drv.h
shared-core/i915_init.c [new file with mode: 0644]
shared-core/i915_irq.c
shared-core/i915_mem.c
shared-core/mach64_dma.c
shared-core/mach64_drm.h
shared-core/mach64_drv.h
shared-core/mach64_irq.c
shared-core/mach64_state.c
shared-core/mga_dma.c
shared-core/mga_drm.h
shared-core/mga_drv.h
shared-core/mga_irq.c
shared-core/mga_state.c
shared-core/mga_warp.c
shared-core/nouveau_dma.c [new file with mode: 0644]
shared-core/nouveau_dma.h [new file with mode: 0644]
shared-core/nouveau_drm.h
shared-core/nouveau_drv.h
shared-core/nouveau_fifo.c
shared-core/nouveau_irq.c
shared-core/nouveau_mem.c
shared-core/nouveau_notifier.c [new file with mode: 0644]
shared-core/nouveau_object.c
shared-core/nouveau_reg.h
shared-core/nouveau_state.c
shared-core/nouveau_swmthd.c [new file with mode: 0644]
shared-core/nouveau_swmthd.h [new file with mode: 0644]
shared-core/nv04_fb.c
shared-core/nv04_fifo.c [new file with mode: 0644]
shared-core/nv04_graph.c
shared-core/nv04_instmem.c [new file with mode: 0644]
shared-core/nv04_mc.c
shared-core/nv04_timer.c
shared-core/nv10_fb.c
shared-core/nv10_fifo.c [new file with mode: 0644]
shared-core/nv10_graph.c
shared-core/nv20_graph.c
shared-core/nv30_graph.c [deleted file]
shared-core/nv40_fb.c
shared-core/nv40_fifo.c [new file with mode: 0644]
shared-core/nv40_graph.c
shared-core/nv40_mc.c
shared-core/nv50_fifo.c [new file with mode: 0644]
shared-core/nv50_graph.c [new file with mode: 0644]
shared-core/nv50_instmem.c [new file with mode: 0644]
shared-core/nv50_mc.c [new file with mode: 0644]
shared-core/r128_cce.c
shared-core/r128_drm.h
shared-core/r128_drv.h
shared-core/r128_irq.c
shared-core/r128_state.c
shared-core/r300_cmdbuf.c
shared-core/r300_reg.h
shared-core/radeon_cp.c
shared-core/radeon_drm.h
shared-core/radeon_drv.h
shared-core/radeon_irq.c
shared-core/radeon_mem.c
shared-core/radeon_state.c
shared-core/savage_bci.c
shared-core/savage_drm.h
shared-core/savage_drv.h
shared-core/savage_state.c
shared-core/sis_drv.h
shared-core/sis_mm.c
shared-core/via_dma.c
shared-core/via_drm.h
shared-core/via_drv.c
shared-core/via_drv.h
shared-core/via_irq.c
shared-core/via_map.c
shared-core/via_mm.c
shared-core/via_verifier.c
shared-core/via_verifier.h
shared-core/via_video.c
shared-core/xgi_drm.h [new file with mode: 0644]
tests/Makefile [deleted file]
tests/Makefile.am [new file with mode: 0644]
tests/auth.c [new file with mode: 0644]
tests/drmtest.c [new file with mode: 0644]
tests/drmtest.h [new file with mode: 0644]
tests/getclient.c [new file with mode: 0644]
tests/getstats.c [new file with mode: 0644]
tests/getversion.c [new file with mode: 0644]
tests/lock.c [new file with mode: 0644]
tests/mode/Makefile [new file with mode: 0644]
tests/mode/modetest.c [new file with mode: 0644]
tests/mode/test [new file with mode: 0755]
tests/openclose.c [new file with mode: 0644]
tests/setversion.c [new file with mode: 0644]
tests/updatedraw.c [new file with mode: 0644]

index 0fb0f49..0991da8 100644 (file)
@@ -1,55 +1,5 @@
-bsd-core/linux
-bsd-core/drm.h
-bsd-core/drm_sarea.h
-bsd-core/i915_dma.c
-bsd-core/i915_drm.h
-bsd-core/i915_drv.h
-bsd-core/i915_irq.c
-bsd-core/i915_mem.c
-bsd-core/mach64_dma.c
-bsd-core/mach64_drm.h
-bsd-core/mach64_drv.h
-bsd-core/mach64_irq.c
-bsd-core/mach64_state.c
-bsd-core/mga_dma.c
-bsd-core/mga_drm.h
-bsd-core/mga_drv.h
-bsd-core/mga_irq.c
-bsd-core/mga_state.c
-bsd-core/mga_ucode.h
-bsd-core/mga_warp.c
-bsd-core/nv_drv.h
-bsd-core/r128_cce.c
-bsd-core/r128_drm.h
-bsd-core/r128_drv.h
-bsd-core/r128_irq.c
-bsd-core/r128_state.c
-bsd-core/r300_cmdbuf.c
-bsd-core/r300_reg.h
-bsd-core/radeon_cp.c
-bsd-core/radeon_drm.h
-bsd-core/radeon_drv.h
-bsd-core/radeon_irq.c
-bsd-core/radeon_mem.c
-bsd-core/radeon_state.c
-bsd-core/savage_bci.c
-bsd-core/savage_drm.h
-bsd-core/savage_drv.h
-bsd-core/savage_state.c
-bsd-core/sis_drm.h
-bsd-core/sis_drv.h
-bsd-core/tdfx_drv.h
-bsd-core/via_3d_reg.h
-bsd-core/via_dma.c
-bsd-core/via_drm.h
-bsd-core/via_drv.c
-bsd-core/via_drv.h
-bsd-core/via_irq.c
-bsd-core/via_map.c
-bsd-core/via_verifier.c
-bsd-core/via_verifier.h
-bsd-core/via_video.c
-*~
+bsd-core/*/@
+bsd-core/*/machine
 *.flags
 *.ko
 *.ko.cmd
@@ -75,6 +25,7 @@ config.log
 config.status
 config.sub
 configure
+configure.lineno
 cscope.*
 depcomp
 device_if.h
@@ -100,3 +51,13 @@ sis.kld
 stamp-h1
 tdfx.kld
 via.kld
+tests/auth
+tests/dristat
+tests/drmstat
+tests/getclient
+tests/getstats
+tests/getversion
+tests/lock
+tests/openclose
+tests/setversion
+tests/updatedraw
index 8c5dc70..5b1ae60 100644 (file)
@@ -22,7 +22,7 @@
 # here too, but let's just do libdrm for now
 
 AUTOMAKE_OPTIONS = foreign
-SUBDIRS = libdrm shared-core
+SUBDIRS = libdrm shared-core tests
 
 pkgconfigdir = @pkgconfigdir@
 pkgconfig_DATA = libdrm.pc
index 00889da..a58ac0a 100644 (file)
@@ -1,71 +1,11 @@
 SHARED=                ../shared-core
-SHAREDFILES=   drm.h \
-               drm_sarea.h \
-               i915_dma.c \
-               i915_drm.h \
-               i915_drv.h \
-               i915_irq.c \
-               i915_mem.c \
-               mach64_dma.c \
-               mach64_drm.h \
-               mach64_drv.h \
-               mach64_irq.c \
-               mach64_state.c \
-               mga_dma.c \
-               mga_drm.h \
-               mga_drv.h \
-               mga_irq.c \
-               mga_state.c \
-               mga_ucode.h \
-               mga_warp.c \
-               r128_cce.c \
-               r128_drm.h \
-               r128_drv.h \
-               r128_irq.c \
-               r128_state.c \
-               radeon_cp.c \
-               radeon_drm.h \
-               radeon_drv.h \
-               radeon_irq.c \
-               radeon_mem.c \
-               radeon_state.c \
-               r300_cmdbuf.c \
-               r300_reg.h \
-               savage_bci.c \
-               savage_drm.h \
-               savage_drv.h \
-               savage_state.c \
-               sis_drm.h \
-               sis_drv.h \
-               sis_ds.c \
-               sis_ds.h \
-               sis_mm.c \
-               tdfx_drv.h \
-               via_3d_reg.h \
-               via_dma.c \
-               via_drm.h \
-               via_drv.h \
-               via_ds.c \
-               via_ds.h \
-               via_irq.c \
-               via_map.c \
-               via_mm.c \
-               via_mm.h \
-               via_verifier.c \
-               via_verifier.h \
-               via_video.c
 
 SUBDIR = drm mach64 mga r128 radeon savage sis tdfx i915 # via
 
-CLEANFILES+= ${SHAREDFILES}
-
 .include <bsd.obj.mk>
 
-depend: drm_pciids.h ${SHAREDFILES}
-all: drm_pciids.h ${SHAREDFILES}
+depend: drm_pciids.h
+all: drm_pciids.h
 
 drm_pciids.h: ${SHARED}/drm_pciids.txt
        sh ../scripts/create_bsd_pci_lists.sh < ${SHARED}/drm_pciids.txt
-
-${SHAREDFILES}:
-       ln -sf ${SHARED}/$@ $@
index 682eace..db19a75 100644 (file)
@@ -1,6 +1,3 @@
-/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
- * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
- */
 /*-
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
  */
 
+/** @file ati_pcigart.c
+ * Implementation of ATI's PCIGART, which provides an aperture in card virtual
+ * address space with addresses remapped to system memory.
+ */
+
 #include "drmP.h"
 
 #define ATI_PCIGART_PAGE_SIZE          4096    /* PCI GART page size */
diff --git a/bsd-core/drm.h b/bsd-core/drm.h
new file mode 120000 (symlink)
index 0000000..2963669
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/drm.h
\ No newline at end of file
index 9ba3d50..8a768f0 100644 (file)
@@ -59,6 +59,8 @@ typedef struct drm_file drm_file_t;
 #include <sys/bus.h>
 #include <sys/signalvar.h>
 #include <sys/poll.h>
+#include <sys/tree.h>
+#include <sys/taskqueue.h>
 #include <vm/vm.h>
 #include <vm/pmap.h>
 #include <vm/vm_extern.h>
@@ -152,6 +154,7 @@ typedef struct drm_file drm_file_t;
 #define DRM_MEM_CTXBITMAP 17
 #define DRM_MEM_STUB     18
 #define DRM_MEM_SGLISTS          19
+#define DRM_MEM_DRAWABLE  20
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
@@ -184,10 +187,15 @@ MALLOC_DECLARE(M_DRM);
 #define DRM_CURPROC            curthread
 #define DRM_STRUCTPROC         struct thread
 #define DRM_SPINTYPE           struct mtx
-#define DRM_SPININIT(l,name)   mtx_init(&l, name, NULL, MTX_DEF)
-#define DRM_SPINUNINIT(l)      mtx_destroy(&l)
+#define DRM_SPININIT(l,name)   mtx_init(l, name, NULL, MTX_DEF)
+#define DRM_SPINUNINIT(l)      mtx_destroy(l)
 #define DRM_SPINLOCK(l)                mtx_lock(l)
-#define DRM_SPINUNLOCK(u)      mtx_unlock(u);
+#define DRM_SPINUNLOCK(u)      mtx_unlock(u)
+#define DRM_SPINLOCK_IRQSAVE(l, irqflags) do {         \
+       mtx_lock(l);                                    \
+       (void)irqflags;                                 \
+} while (0)
+#define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) mtx_unlock(u)
 #define DRM_SPINLOCK_ASSERT(l) mtx_assert(l, MA_OWNED)
 #define DRM_CURRENTPID         curthread->td_proc->p_pid
 #define DRM_LOCK()             mtx_lock(&dev->dev_lock)
@@ -209,10 +217,6 @@ MALLOC_DECLARE(M_DRM);
 #define spldrm()               spltty()
 #endif /* __NetBSD__ || __OpenBSD__ */
 
-/* Currently our DRMFILE (filp) is a void * which is actually the pid
- * of the current process.  It should be a per-open unique pointer, but
- * code for that is not yet written */
-#define DRMFILE                        void *
 #define DRM_IRQ_ARGS           void *arg
 typedef void                   irqreturn_t;
 #define IRQ_HANDLED            /* nothing */
@@ -226,11 +230,15 @@ enum {
 #define DRM_AGP_MEM            struct agp_memory_info
 
 #if defined(__FreeBSD__)
-#define DRM_DEVICE                                                     \
-       drm_device_t *dev = kdev->si_drv1
-#define DRM_IOCTL_ARGS         struct cdev *kdev, u_long cmd, caddr_t data, \
-                               int flags, DRM_STRUCTPROC *p, DRMFILE filp
+#define drm_get_device_from_kdev(_kdev) (_kdev->si_drv1)
+#elif defined(__NetBSD__)
+#define drm_get_device_from_kdev(_kdev) device_lookup(&drm_cd, minor(_kdev))
+#elif defined(__OpenBSD__)
+#define drm_get_device_from_kdev(_kdev) device_lookup(&drm_cd, \
+    minor(_kdev)))->dv_cfdata->cf_driver->cd_devs[minor(_kdev)]
+#endif
 
+#if defined(__FreeBSD__)
 #define PAGE_ALIGN(addr) round_page(addr)
 /* DRM_SUSER returns true if the user is superuser */
 #if __FreeBSD_version >= 700000
@@ -244,17 +252,6 @@ enum {
 
 #else /* __FreeBSD__ */
 
-#if defined(__NetBSD__)
-#define DRM_DEVICE                                                     \
-       drm_device_t *dev = device_lookup(&drm_cd, minor(kdev))
-#elif defined(__OpenBSD__)
-#define DRM_DEVICE                                                     \
-       drm_device_t *dev = (device_lookup(&drm_cd,                     \
-           minor(kdev)))->dv_cfdata->cf_driver->cd_devs[minor(kdev)]
-#endif /* __OpenBSD__ */
-#define DRM_IOCTL_ARGS         dev_t kdev, u_long cmd, caddr_t data, \
-                               int flags, DRM_STRUCTPROC *p, DRMFILE filp
-
 #define CDEV_MAJOR             34
 #define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
 /* DRM_SUSER returns true if the user is superuser */
@@ -342,14 +339,6 @@ typedef vaddr_t vm_offset_t;
        (!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ))
 #endif /* !__FreeBSD__ */
 
-#define DRM_COPY_TO_USER_IOCTL(user, kern, size)       \
-       if ( IOCPARM_LEN(cmd) != size)                  \
-               return EINVAL;                          \
-       *user = kern;
-#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \
-       if ( IOCPARM_LEN(cmd) != size)                  \
-               return EINVAL;                          \
-       kern = *user;
 #define DRM_COPY_TO_USER(user, kern, size) \
        copyout(kern, user, size)
 #define DRM_COPY_FROM_USER(kern, user, size) \
@@ -369,7 +358,6 @@ typedef vaddr_t vm_offset_t;
 #define cpu_to_le32(x) htole32(x)
 #define le32_to_cpu(x) le32toh(x)
 
-#define DRM_ERR(v)             v
 #define DRM_HZ                 hz
 #define DRM_UDELAY(udelay)     DELAY(udelay)
 #define DRM_TIME_SLICE         (hz/20)  /* Time slice for GLXContexts    */
@@ -378,23 +366,10 @@ typedef vaddr_t vm_offset_t;
        (_map) = (_dev)->context_sareas[_ctx];          \
 } while(0)
 
-#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp)                 \
-do {                                                           \
-       if (_filp != (DRMFILE)(intptr_t)DRM_CURRENTPID) {       \
-               DRM_ERROR("filp doesn't match curproc\n");      \
-               return EINVAL;                                  \
-       }                                                       \
-       _priv = drm_find_file_by_proc(dev, DRM_CURPROC);        \
-       if (_priv == NULL) {                                    \
-               DRM_ERROR("can't find authenticator\n");        \
-               return EINVAL;                                  \
-       }                                                       \
-} while (0)
-
-#define LOCK_TEST_WITH_RETURN(dev, filp)                               \
+#define LOCK_TEST_WITH_RETURN(dev, file_priv)                          \
 do {                                                                   \
        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||              \
-            dev->lock.filp != filp) {                                  \
+            dev->lock.file_priv != file_priv) {                        \
                DRM_ERROR("%s called without lock held\n",              \
                           __FUNCTION__);                               \
                return EINVAL;                                          \
@@ -402,22 +377,24 @@ do {                                                                      \
 } while (0)
 
 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
+/* Returns -errno to shared code */
 #define DRM_WAIT_ON( ret, queue, timeout, condition )          \
 for ( ret = 0 ; !ret && !(condition) ; ) {                     \
        DRM_UNLOCK();                                           \
        mtx_lock(&dev->irq_lock);                               \
        if (!(condition))                                       \
-          ret = msleep(&(queue), &dev->irq_lock,               \
+          ret = -msleep(&(queue), &dev->irq_lock,              \
                         PZERO | PCATCH, "drmwtq", (timeout));  \
        mtx_unlock(&dev->irq_lock);                             \
        DRM_LOCK();                                             \
 }
 #else
+/* Returns -errno to shared code */
 #define DRM_WAIT_ON( ret, queue, timeout, condition )  \
 for ( ret = 0 ; !ret && !(condition) ; ) {             \
         int s = spldrm();                              \
        if (!(condition))                               \
-          ret = tsleep( &(queue), PZERO | PCATCH,      \
+          ret = -tsleep( &(queue), PZERO | PCATCH,     \
                         "drmwtq", (timeout) );         \
        splx(s);                                        \
 }
@@ -447,9 +424,16 @@ typedef struct drm_pci_id_list
 #define DRM_MASTER     0x2
 #define DRM_ROOT_ONLY  0x4
 typedef struct drm_ioctl_desc {
-       int                  (*func)(DRM_IOCTL_ARGS);
+       unsigned long cmd;
+       int (*func)(drm_device_t *dev, void *data, struct drm_file *file_priv);
        int flags;
 } drm_ioctl_desc_t;
+/**
+ * Creates a driver or general drm_ioctl_desc array entry for the given
+ * ioctl, for use by drm_ioctl().
+ */
+#define DRM_IOCTL_DEF(ioctl, func, flags) \
+       [DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags}
 
 typedef struct drm_magic_entry {
        drm_magic_t            magic;
@@ -472,7 +456,7 @@ typedef struct drm_buf {
        unsigned long     bus_address; /* Bus address of buffer              */
        struct drm_buf    *next;       /* Kernel-only: used for free list    */
        __volatile__ int  pending;     /* On hardware DMA queue              */
-       DRMFILE           filp;        /* Unique identifier of holding process */
+       struct drm_file   *file_priv;  /* Unique identifier of holding process */
        int               context;     /* Kernel queue for this buffer       */
        enum {
                DRM_LIST_NONE    = 0,
@@ -534,7 +518,7 @@ struct drm_file {
 
 typedef struct drm_lock_data {
        drm_hw_lock_t     *hw_lock;     /* Hardware lock                   */
-       DRMFILE           filp;         /* Unique identifier of holding process (NULL is kernel)*/
+       struct drm_file   *file_priv;   /* Unique identifier of holding process (NULL is kernel)*/
        int               lock_queue;   /* Queue of blocked processes      */
        unsigned long     lock_time;    /* Time of last lock in jiffies    */
 } drm_lock_data_t;
@@ -638,12 +622,13 @@ struct drm_driver_info {
        int     (*load)(struct drm_device *, unsigned long flags);
        int     (*firstopen)(struct drm_device *);
        int     (*open)(struct drm_device *, drm_file_t *);
-       void    (*preclose)(struct drm_device *, void *filp);
+       void    (*preclose)(struct drm_device *, struct drm_file *file_priv);
        void    (*postclose)(struct drm_device *, drm_file_t *);
        void    (*lastclose)(struct drm_device *);
        int     (*unload)(struct drm_device *);
-       void    (*reclaim_buffers_locked)(struct drm_device *, void *filp);
-       int     (*dma_ioctl)(DRM_IOCTL_ARGS);
+       void    (*reclaim_buffers_locked)(struct drm_device *,
+                                         struct drm_file *file_priv);
+       int     (*dma_ioctl)(drm_device_t *dev, void *data, struct drm_file *file_priv);
        void    (*dma_ready)(struct drm_device *);
        int     (*dma_quiescent)(struct drm_device *);
        int     (*dma_flush_block_and_flush)(struct drm_device *, int context,
@@ -732,6 +717,8 @@ struct drm_device {
        struct mtx        irq_lock;     /* protects irq condition checks */
        struct mtx        dev_lock;     /* protects everything else */
 #endif
+       DRM_SPINTYPE      drw_lock;
+
                                /* Usage Counters */
        int               open_count;   /* Outstanding files open          */
        int               buf_use;      /* Buffers in use -- cannot alloc  */
@@ -780,6 +767,7 @@ struct drm_device {
        int               last_context; /* Last current context            */
        int               vbl_queue;    /* vbl wait channel */
        atomic_t          vbl_received;
+       atomic_t          vbl_received2;
 
 #ifdef __FreeBSD__
        struct sigio      *buf_sigio;   /* Processes waiting for SIGIO     */
@@ -796,6 +784,13 @@ struct drm_device {
        void              *dev_private;
        unsigned int      agp_buffer_token;
        drm_local_map_t   *agp_buffer_map;
+
+       struct unrhdr     *drw_unrhdr;
+       /* RB tree of drawable infos */
+       RB_HEAD(drawable_tree, bsd_drm_drawable_info) drw_head;
+
+       struct task       locked_task;
+       void              (*locked_task_call)(drm_device_t *dev);
 };
 
 extern int     drm_debug_flag;
@@ -883,7 +878,7 @@ int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request);
 int    drm_dma_setup(drm_device_t *dev);
 void   drm_dma_takedown(drm_device_t *dev);
 void   drm_free_buffer(drm_device_t *dev, drm_buf_t *buf);
-void   drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
+void   drm_reclaim_buffers(drm_device_t *dev, struct drm_file *file_priv);
 #define drm_core_reclaim_buffers drm_reclaim_buffers
 
 /* IRQ support (drm_irq.c) */
@@ -915,6 +910,7 @@ int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
 
 /* Scatter Gather Support (drm_scatter.c) */
 void   drm_sg_cleanup(drm_sg_mem_t *entry);
+int    drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request);
 
 #ifdef __FreeBSD__
 /* sysctl support (drm_sysctl.h) */
@@ -929,68 +925,72 @@ int       drm_ati_pcigart_cleanup(drm_device_t *dev,
                                drm_ati_pcigart_info *gart_info);
 
 /* Locking IOCTL support (drm_drv.c) */
-int    drm_lock(DRM_IOCTL_ARGS);
-int    drm_unlock(DRM_IOCTL_ARGS);
-int    drm_version(DRM_IOCTL_ARGS);
-int    drm_setversion(DRM_IOCTL_ARGS);
+int    drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_unlock(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_version(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_setversion(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* Misc. IOCTL support (drm_ioctl.c) */
-int    drm_irq_by_busid(DRM_IOCTL_ARGS);
-int    drm_getunique(DRM_IOCTL_ARGS);
-int    drm_setunique(DRM_IOCTL_ARGS);
-int    drm_getmap(DRM_IOCTL_ARGS);
-int    drm_getclient(DRM_IOCTL_ARGS);
-int    drm_getstats(DRM_IOCTL_ARGS);
-int    drm_noop(DRM_IOCTL_ARGS);
+int    drm_irq_by_busid(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_getunique(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_setunique(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_getmap(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_getclient(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_getstats(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_noop(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* Context IOCTL support (drm_context.c) */
-int    drm_resctx(DRM_IOCTL_ARGS);
-int    drm_addctx(DRM_IOCTL_ARGS);
-int    drm_modctx(DRM_IOCTL_ARGS);
-int    drm_getctx(DRM_IOCTL_ARGS);
-int    drm_switchctx(DRM_IOCTL_ARGS);
-int    drm_newctx(DRM_IOCTL_ARGS);
-int    drm_rmctx(DRM_IOCTL_ARGS);
-int    drm_setsareactx(DRM_IOCTL_ARGS);
-int    drm_getsareactx(DRM_IOCTL_ARGS);
+int    drm_resctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_addctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_modctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_getctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_switchctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_newctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_rmctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_setsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_getsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* Drawable IOCTL support (drm_drawable.c) */
-int    drm_adddraw(DRM_IOCTL_ARGS);
-int    drm_rmdraw(DRM_IOCTL_ARGS);
+int    drm_adddraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv);
+struct drm_drawable_info *drm_get_drawable_info(drm_device_t *dev, int handle);
 
 /* Authentication IOCTL support (drm_auth.c) */
-int    drm_getmagic(DRM_IOCTL_ARGS);
-int    drm_authmagic(DRM_IOCTL_ARGS);
+int    drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* Buffer management support (drm_bufs.c) */
-int    drm_addmap_ioctl(DRM_IOCTL_ARGS);
-int    drm_rmmap_ioctl(DRM_IOCTL_ARGS);
-int    drm_addbufs_ioctl(DRM_IOCTL_ARGS);
-int    drm_infobufs(DRM_IOCTL_ARGS);
-int    drm_markbufs(DRM_IOCTL_ARGS);
-int    drm_freebufs(DRM_IOCTL_ARGS);
-int    drm_mapbufs(DRM_IOCTL_ARGS);
+int    drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_rmmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_addbufs_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_infobufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_markbufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_freebufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_mapbufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* DMA support (drm_dma.c) */
-int    drm_dma(DRM_IOCTL_ARGS);
+int    drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* IRQ support (drm_irq.c) */
-int    drm_control(DRM_IOCTL_ARGS);
-int    drm_wait_vblank(DRM_IOCTL_ARGS);
+int    drm_control(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv);
+void   drm_locked_tasklet(drm_device_t *dev,
+                          void (*tasklet)(drm_device_t *dev));
 
 /* AGP/GART support (drm_agpsupport.c) */
-int    drm_agp_acquire_ioctl(DRM_IOCTL_ARGS);
-int    drm_agp_release_ioctl(DRM_IOCTL_ARGS);
-int    drm_agp_enable_ioctl(DRM_IOCTL_ARGS);
-int    drm_agp_info_ioctl(DRM_IOCTL_ARGS);
-int    drm_agp_alloc_ioctl(DRM_IOCTL_ARGS);
-int    drm_agp_free_ioctl(DRM_IOCTL_ARGS);
-int    drm_agp_unbind_ioctl(DRM_IOCTL_ARGS);
-int    drm_agp_bind_ioctl(DRM_IOCTL_ARGS);
+int    drm_agp_acquire_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_agp_release_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_agp_enable_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_agp_info_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_agp_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_agp_free_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_agp_unbind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_agp_bind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* Scatter Gather Support (drm_scatter.c) */
-int    drm_sg_alloc(DRM_IOCTL_ARGS);
-int    drm_sg_free(DRM_IOCTL_ARGS);
+int    drm_sg_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int    drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv);
 
 /* consistent PCI memory functions (drm_pci.c) */
 drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size, size_t align,
index 28239d1..6f963b9 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
- * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com
- */
 /*-
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_agpsupport.c
+ * Support code for tying the kernel AGP support to DRM drivers and
+ * the DRM's AGP ioctls.
+ */
+
 #include "drmP.h"
 
 #ifdef __FreeBSD__
@@ -125,11 +127,10 @@ int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
        return 0;
 }
 
-int drm_agp_info_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_info_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
        int err;
        drm_agp_info_t info;
-       DRM_DEVICE;
 
        err = drm_agp_info(dev, &info);
        if (err != 0)
@@ -139,9 +140,8 @@ int drm_agp_info_ioctl(DRM_IOCTL_ARGS)
        return 0;
 }
 
-int drm_agp_acquire_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_acquire_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
        return drm_agp_acquire(dev);
 }
@@ -161,9 +161,8 @@ int drm_agp_acquire(drm_device_t *dev)
        return 0;
 }
 
-int drm_agp_release_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_release_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
        return drm_agp_release(dev);
 }
@@ -185,15 +184,13 @@ int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
        
        dev->agp->mode    = mode.mode;
        agp_enable(dev->agp->agpdev, mode.mode);
-       dev->agp->base    = dev->agp->info.ai_aperture_base;
        dev->agp->enabled = 1;
        return 0;
 }
 
-int drm_agp_enable_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_enable_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
        drm_agp_mode_t mode;
-       DRM_DEVICE;
 
        mode = *(drm_agp_mode_t *) data;
 
@@ -243,9 +240,8 @@ int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
        return 0;
 }
 
-int drm_agp_alloc_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_agp_buffer_t request;
        int retcode;
 
@@ -292,9 +288,8 @@ int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
        return retcode;
 }
 
-int drm_agp_unbind_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_unbind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_agp_binding_t request;
        int retcode;
 
@@ -333,9 +328,8 @@ int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
        return retcode;
 }
 
-int drm_agp_bind_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_bind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_agp_binding_t request;
        int retcode;
 
@@ -378,9 +372,8 @@ int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
 
 }
 
-int drm_agp_free_ioctl(DRM_IOCTL_ARGS)
+int drm_agp_free_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_agp_buffer_t request;
        int retcode;
 
@@ -411,6 +404,7 @@ drm_agp_head_t *drm_agp_init(void)
                        return NULL;
                head->agpdev = agpdev;
                agp_get_info(agpdev, &head->info);
+               head->base = head->info.ai_aperture_base;
                head->memory = NULL;
                DRM_INFO("AGP at 0x%08lx %dMB\n",
                         (long)head->info.ai_aperture_base,
index aa0e29c..aa8238c 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
- */
 /*-
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_auth.c
+ * Implementation of the get/authmagic ioctls implementing the authentication
+ * scheme between the master and clients.
+ */
+
 #include "drmP.h"
 
 static int drm_hash_magic(drm_magic_t magic)
@@ -38,25 +40,29 @@ static int drm_hash_magic(drm_magic_t magic)
        return magic & (DRM_HASH_SIZE-1);
 }
 
+/**
+ * Returns the file private associated with the given magic number.
+ */
 static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
 {
-       drm_file_t        *retval = NULL;
        drm_magic_entry_t *pt;
-       int               hash;
+       int hash = drm_hash_magic(magic);
 
-       hash = drm_hash_magic(magic);
+       DRM_SPINLOCK_ASSERT(&dev->dev_lock);
 
-       DRM_LOCK();
        for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
                if (pt->magic == magic) {
-                       retval = pt->priv;
-                       break;
+                       return pt->priv;
                }
        }
-       DRM_UNLOCK();
-       return retval;
+
+       return NULL;
 }
 
+/**
+ * Inserts the given magic number into the hash table of used magic number
+ * lists.
+ */
 static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
 {
        int               hash;
@@ -64,9 +70,11 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
 
        DRM_DEBUG("%d\n", magic);
 
+       DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
        hash = drm_hash_magic(magic);
        entry = malloc(sizeof(*entry), M_DRM, M_ZERO | M_NOWAIT);
-       if (!entry) return DRM_ERR(ENOMEM);
+       if (!entry) return ENOMEM;
        entry->magic = magic;
        entry->priv  = priv;
        entry->next  = NULL;
@@ -84,16 +92,21 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
        return 0;
 }
 
+/**
+ * Removes the given magic number from the hash table of used magic number
+ * lists.
+ */
 static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
 {
        drm_magic_entry_t *prev = NULL;
        drm_magic_entry_t *pt;
        int               hash;
 
+       DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
        DRM_DEBUG("%d\n", magic);
        hash = drm_hash_magic(magic);
 
-       DRM_LOCK();
        for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
                if (pt->magic == magic) {
                        if (dev->magiclist[hash].head == pt) {
@@ -105,68 +118,69 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
                        if (prev) {
                                prev->next = pt->next;
                        }
-                       DRM_UNLOCK();
                        return 0;
                }
        }
-       DRM_UNLOCK();
 
        free(pt, M_DRM);
-       return DRM_ERR(EINVAL);
+       return EINVAL;
 }
 
-int drm_getmagic(DRM_IOCTL_ARGS)
+/**
+ * Called by the client, this returns a unique magic number to be authorized
+ * by the master.
+ *
+ * The master may use its own knowledge of the client (such as the X
+ * connection that the magic is passed over) to determine if the magic number
+ * should be authenticated.
+ */
+int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        static drm_magic_t sequence = 0;
-       drm_auth_t auth;
-       drm_file_t *priv;
-
-       DRM_LOCK();
-       priv = drm_find_file_by_proc(dev, p);
-       DRM_UNLOCK();
-       if (priv == NULL) {
-               DRM_ERROR("can't find authenticator\n");
-               return EINVAL;
-       }
+       drm_auth_t *auth = data;
 
                                /* Find unique magic */
-       if (priv->magic) {
-               auth.magic = priv->magic;
+       if (file_priv->magic) {
+               auth->magic = file_priv->magic;
        } else {
+               DRM_LOCK();
                do {
                        int old = sequence;
-                       
-                       auth.magic = old+1;
-                       
-                       if (!atomic_cmpset_int(&sequence, old, auth.magic))
+
+                       auth->magic = old+1;
+
+                       if (!atomic_cmpset_int(&sequence, old, auth->magic))
                                continue;
-               } while (drm_find_file(dev, auth.magic));
-               priv->magic = auth.magic;
-               drm_add_magic(dev, priv, auth.magic);
+               } while (drm_find_file(dev, auth->magic));
+               file_priv->magic = auth->magic;
+               drm_add_magic(dev, file_priv, auth->magic);
+               DRM_UNLOCK();
        }
 
-       DRM_DEBUG("%u\n", auth.magic);
-
-       DRM_COPY_TO_USER_IOCTL((drm_auth_t *)data, auth, sizeof(auth));
+       DRM_DEBUG("%u\n", auth->magic);
 
        return 0;
 }
 
-int drm_authmagic(DRM_IOCTL_ARGS)
+/**
+ * Marks the client associated with the given magic number as authenticated.
+ */
+int drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       drm_auth_t         auth;
-       drm_file_t         *file;
-       DRM_DEVICE;
-
-       DRM_COPY_FROM_USER_IOCTL(auth, (drm_auth_t *)data, sizeof(auth));
+       drm_auth_t *auth = data;
+       drm_file_t *priv;
 
-       DRM_DEBUG("%u\n", auth.magic);
+       DRM_DEBUG("%u\n", auth->magic);
 
-       if ((file = drm_find_file(dev, auth.magic))) {
-               file->authenticated = 1;
-               drm_remove_magic(dev, auth.magic);
+       DRM_LOCK();
+       priv = drm_find_file(dev, auth->magic);
+       if (priv != NULL) {
+               priv->authenticated = 1;
+               drm_remove_magic(dev, auth->magic);
+               DRM_UNLOCK();
                return 0;
+       } else {
+               DRM_UNLOCK();
+               return EINVAL;
        }
-       return DRM_ERR(EINVAL);
 }
index 343ab1e..9b58c59 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_bufs.h -- Generic buffer template -*- linux-c -*-
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
- */
 /*-
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_bufs.c
+ * Implementation of the ioctls for setup of DRM mappings and DMA buffers.
+ */
+
 #include "dev/pci/pcireg.h"
 
 #include "drmP.h"
@@ -149,7 +150,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
         */
        map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT);
        if ( !map )
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
 
        map->offset = offset;
        map->size = size;
@@ -172,7 +173,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
                           map->size, drm_order(map->size), map->handle );
                if ( !map->handle ) {
                        free(map, M_DRM);
-                       return DRM_ERR(ENOMEM);
+                       return ENOMEM;
                }
                map->offset = (unsigned long)map->handle;
                if ( map->flags & _DRM_CONTAINS_LOCK ) {
@@ -182,7 +183,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
                                DRM_UNLOCK();
                                free(map->handle, M_DRM);
                                free(map, M_DRM);
-                               return DRM_ERR(EBUSY);
+                               return EBUSY;
                        }
                        dev->lock.hw_lock = map->handle; /* Pointer to lock */
                        DRM_UNLOCK();
@@ -190,7 +191,17 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
                break;
        case _DRM_AGP:
                /*valid = 0;*/
-               map->offset += dev->agp->base;
+               /* In some cases (i810 driver), user space may have already
+                * added the AGP base itself, because dev->agp->base previously
+                * only got set during AGP enable.  So, only add the base
+                * address if the map's offset isn't already within the
+                * aperture.
+                */
+               if (map->offset < dev->agp->base ||
+                   map->offset > dev->agp->base +
+                   dev->agp->info.ai_aperture_size - 1) {
+                       map->offset += dev->agp->base;
+               }
                map->mtrr   = dev->agp->mtrr; /* for getmap */
                /*for (entry = dev->agp->memory; entry; entry = entry->next) {
                        if ((map->offset >= entry->bound) &&
@@ -202,13 +213,13 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
                }
                if (!valid) {
                        free(map, M_DRM);
-                       return DRM_ERR(EACCES);
+                       return EACCES;
                }*/
                break;
        case _DRM_SCATTER_GATHER:
                if (!dev->sg) {
                        free(map, M_DRM);
-                       return DRM_ERR(EINVAL);
+                       return EINVAL;
                }
                map->offset = map->offset + dev->sg->handle;
                break;
@@ -225,7 +236,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
                map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful);
                if (map->dmah == NULL) {
                        free(map, M_DRM);
-                       return DRM_ERR(ENOMEM);
+                       return ENOMEM;
                }
                map->handle = map->dmah->vaddr;
                map->offset = map->dmah->busaddr;
@@ -233,7 +244,7 @@ int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
        default:
                DRM_ERROR("Bad map type %d\n", map->type);
                free(map, M_DRM);
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }
 
        DRM_LOCK();
@@ -250,39 +261,35 @@ done:
        return 0;
 }
 
-int drm_addmap_ioctl(DRM_IOCTL_ARGS)
+int drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       drm_map_t request;
+       drm_map_t *request = data;
        drm_local_map_t *map;
        int err;
-       DRM_DEVICE;
 
        if (!(dev->flags & (FREAD|FWRITE)))
-               return DRM_ERR(EACCES); /* Require read/write */
+               return EACCES; /* Require read/write */
 
-       DRM_COPY_FROM_USER_IOCTL(request, (drm_map_t *)data, sizeof(drm_map_t));
-
-       if (!DRM_SUSER(p) && request.type != _DRM_AGP)
-               return DRM_ERR(EACCES);
+       if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP)
+               return EACCES;
 
        DRM_LOCK();
-       err = drm_addmap(dev, request.offset, request.size, request.type,
-           request.flags, &map);
+       err = drm_addmap(dev, request->offset, request->size, request->type,
+           request->flags, &map);
        DRM_UNLOCK();
        if (err != 0)
                return err;
 
-       request.offset = map->offset;
-       request.size = map->size;
-       request.type = map->type;
-       request.flags = map->flags;
-       request.mtrr   = map->mtrr;
-       request.handle = map->handle;
+       request->offset = map->offset;
+       request->size = map->size;
+       request->type = map->type;
+       request->flags = map->flags;
+       request->mtrr   = map->mtrr;
+       request->handle = map->handle;
 
-       if (request.type != _DRM_SHM) {
-               request.handle = (void *)request.offset;
+       if (request->type != _DRM_SHM) {
+               request->handle = (void *)request->offset;
        }
-       DRM_COPY_TO_USER_IOCTL((drm_map_t *)data, request, sizeof(drm_map_t));
 
        return 0;
 }
@@ -333,17 +340,14 @@ void drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
  * isn't in use.
  */
 
-int drm_rmmap_ioctl(DRM_IOCTL_ARGS)
+int drm_rmmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_local_map_t *map;
-       drm_map_t request;
-
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(request) );
+       drm_map_t *request = data;
 
        DRM_LOCK();
        TAILQ_FOREACH(map, &dev->maplist, link) {
-               if (map->handle == request.handle &&
+               if (map->handle == request->handle &&
                    map->flags & _DRM_REMOVABLE)
                        break;
        }
@@ -351,7 +355,7 @@ int drm_rmmap_ioctl(DRM_IOCTL_ARGS)
        /* No match found. */
        if (map == NULL) {
                DRM_UNLOCK();
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }
 
        drm_rmmap(dev, map);
@@ -441,7 +445,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
        }
        if (!valid) {
                DRM_DEBUG("zone invalid\n");
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }*/
 
        entry = &dma->bufs[order];
@@ -449,7 +453,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
        entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
            M_NOWAIT | M_ZERO);
        if ( !entry->buflist ) {
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
 
        entry->buf_size = size;
@@ -469,7 +473,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
                buf->address = (void *)(agp_offset + offset);
                buf->next    = NULL;
                buf->pending = 0;
-               buf->filp    = NULL;
+               buf->file_priv = NULL;
 
                buf->dev_priv_size = dev->driver.buf_priv_size;
                buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
@@ -478,7 +482,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
                        /* Set count correctly so we free the proper amount. */
                        entry->buf_count = count;
                        drm_cleanup_buf_error(dev, entry);
-                       return DRM_ERR(ENOMEM);
+                       return ENOMEM;
                }
 
                offset += alignment;
@@ -494,7 +498,7 @@ static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
        if (temp_buflist == NULL) {
                /* Free the entry because it isn't valid */
                drm_cleanup_buf_error(dev, entry);
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
        dma->buflist = temp_buflist;
 
@@ -563,7 +567,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
            temp_pagelist == NULL) {
                free(entry->buflist, M_DRM);
                free(entry->seglist, M_DRM);
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
        
        memcpy(temp_pagelist, dma->pagelist, dma->page_count * 
@@ -586,7 +590,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
                        entry->seg_count = count;
                        drm_cleanup_buf_error(dev, entry);
                        free(temp_pagelist, M_DRM);
-                       return DRM_ERR(ENOMEM);
+                       return ENOMEM;
                }
 
                entry->seglist[entry->seg_count++] = dmah;
@@ -610,7 +614,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
                        buf->bus_address = dmah->busaddr + offset;
                        buf->next    = NULL;
                        buf->pending = 0;
-                       buf->filp    = NULL;
+                       buf->file_priv = NULL;
 
                        buf->dev_priv_size = dev->driver.buf_priv_size;
                        buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
@@ -621,7 +625,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
                                entry->seg_count = count;
                                drm_cleanup_buf_error(dev, entry);
                                free(temp_pagelist, M_DRM);
-                               return DRM_ERR(ENOMEM);
+                               return ENOMEM;
                        }
 
                        DRM_DEBUG( "buffer %d @ %p\n",
@@ -637,7 +641,7 @@ static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
                /* Free the entry because it isn't valid */
                drm_cleanup_buf_error(dev, entry);
                free(temp_pagelist, M_DRM);
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
        dma->buflist = temp_buflist;
 
@@ -705,7 +709,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
        entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
            M_NOWAIT | M_ZERO);
        if (entry->buflist == NULL)
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
 
        entry->buf_size = size;
        entry->page_order = page_order;
@@ -724,7 +728,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
                buf->address = (void *)(agp_offset + offset + dev->sg->handle);
                buf->next    = NULL;
                buf->pending = 0;
-               buf->filp    = NULL;
+               buf->file_priv = NULL;
 
                buf->dev_priv_size = dev->driver.buf_priv_size;
                buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
@@ -733,7 +737,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
                        /* Set count correctly so we free the proper amount. */
                        entry->buf_count = count;
                        drm_cleanup_buf_error(dev, entry);
-                       return DRM_ERR(ENOMEM);
+                       return ENOMEM;
                }
 
                DRM_DEBUG( "buffer %d @ %p\n",
@@ -752,7 +756,7 @@ static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
        if (temp_buflist == NULL) {
                /* Free the entry because it isn't valid */
                drm_cleanup_buf_error(dev, entry);
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
        dma->buflist = temp_buflist;
 
@@ -781,21 +785,21 @@ int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
        DRM_SPINLOCK(&dev->dma_lock);
 
        if (request->count < 0 || request->count > 4096)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        
        order = drm_order(request->size);
        if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
 
        /* No more allocations after first buffer-using ioctl. */
        if (dev->buf_use != 0) {
                DRM_SPINUNLOCK(&dev->dma_lock);
-               return DRM_ERR(EBUSY);
+               return EBUSY;
        }
        /* No more than one allocation per order */
        if (dev->dma->bufs[order].buf_count != 0) {
                DRM_SPINUNLOCK(&dev->dma_lock);
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
 
        ret = drm_do_addbufs_agp(dev, request);
@@ -812,24 +816,24 @@ int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
        DRM_SPINLOCK(&dev->dma_lock);
 
        if (!DRM_SUSER(DRM_CURPROC))
-               return DRM_ERR(EACCES);
+               return EACCES;
 
        if (request->count < 0 || request->count > 4096)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        
        order = drm_order(request->size);
        if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
 
        /* No more allocations after first buffer-using ioctl. */
        if (dev->buf_use != 0) {
                DRM_SPINUNLOCK(&dev->dma_lock);
-               return DRM_ERR(EBUSY);
+               return EBUSY;
        }
        /* No more than one allocation per order */
        if (dev->dma->bufs[order].buf_count != 0) {
                DRM_SPINUNLOCK(&dev->dma_lock);
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
 
        ret = drm_do_addbufs_sg(dev, request);
@@ -846,24 +850,24 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
        DRM_SPINLOCK(&dev->dma_lock);
 
        if (!DRM_SUSER(DRM_CURPROC))
-               return DRM_ERR(EACCES);
+               return EACCES;
 
        if (request->count < 0 || request->count > 4096)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        
        order = drm_order(request->size);
        if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
 
        /* No more allocations after first buffer-using ioctl. */
        if (dev->buf_use != 0) {
                DRM_SPINUNLOCK(&dev->dma_lock);
-               return DRM_ERR(EBUSY);
+               return EBUSY;
        }
        /* No more than one allocation per order */
        if (dev->dma->bufs[order].buf_count != 0) {
                DRM_SPINUNLOCK(&dev->dma_lock);
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
 
        ret = drm_do_addbufs_pci(dev, request);
@@ -873,39 +877,29 @@ int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
        return ret;
 }
 
-int drm_addbufs_ioctl(DRM_IOCTL_ARGS)
+int drm_addbufs_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_buf_desc_t request;
+       drm_buf_desc_t *request = data;
        int err;
 
-       DRM_COPY_FROM_USER_IOCTL(request, (drm_buf_desc_t *)data,
-           sizeof(request));
-
-       if (request.flags & _DRM_AGP_BUFFER)
-               err = drm_addbufs_agp(dev, &request);
-       else if (request.flags & _DRM_SG_BUFFER)
-               err = drm_addbufs_sg(dev, &request);
+       if (request->flags & _DRM_AGP_BUFFER)
+               err = drm_addbufs_agp(dev, request);
+       else if (request->flags & _DRM_SG_BUFFER)
+               err = drm_addbufs_sg(dev, request);
        else
-               err = drm_addbufs_pci(dev, &request);
-
-       DRM_COPY_TO_USER_IOCTL((drm_buf_desc_t *)data, request,
-           sizeof(request));
+               err = drm_addbufs_pci(dev, request);
 
        return err;
 }
 
-int drm_infobufs(DRM_IOCTL_ARGS)
+int drm_infobufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_device_dma_t *dma = dev->dma;
-       drm_buf_info_t request;
+       drm_buf_info_t *request = data;
        int i;
        int count;
        int retcode = 0;
 
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_info_t *)data, sizeof(request) );
-
        DRM_SPINLOCK(&dev->dma_lock);
        ++dev->buf_use;         /* Can't allocate more after this call */
        DRM_SPINUNLOCK(&dev->dma_lock);
@@ -916,7 +910,7 @@ int drm_infobufs(DRM_IOCTL_ARGS)
 
        DRM_DEBUG( "count = %d\n", count );
 
-       if ( request.count >= count ) {
+       if ( request->count >= count ) {
                for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
                        if ( dma->bufs[i].buf_count ) {
                                drm_buf_desc_t from;
@@ -926,9 +920,9 @@ int drm_infobufs(DRM_IOCTL_ARGS)
                                from.low_mark = dma->bufs[i].freelist.low_mark;
                                from.high_mark = dma->bufs[i].freelist.high_mark;
 
-                               if (DRM_COPY_TO_USER(&request.list[count], &from,
+                               if (DRM_COPY_TO_USER(&request->list[count], &from,
                                    sizeof(drm_buf_desc_t)) != 0) {
-                                       retcode = DRM_ERR(EFAULT);
+                                       retcode = EFAULT;
                                        break;
                                }
 
@@ -942,76 +936,68 @@ int drm_infobufs(DRM_IOCTL_ARGS)
                        }
                }
        }
-       request.count = count;
-
-       DRM_COPY_TO_USER_IOCTL( (drm_buf_info_t *)data, request, sizeof(request) );
+       request->count = count;
 
        return retcode;
 }
 
-int drm_markbufs(DRM_IOCTL_ARGS)
+int drm_markbufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_device_dma_t *dma = dev->dma;
-       drm_buf_desc_t request;
+       drm_buf_desc_t *request = data;
        int order;
 
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_desc_t *)data, sizeof(request) );
-
        DRM_DEBUG( "%d, %d, %d\n",
-                  request.size, request.low_mark, request.high_mark );
+                  request->size, request->low_mark, request->high_mark );
        
 
-       order = drm_order(request.size);        
+       order = drm_order(request->size);       
        if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ||
-           request.low_mark < 0 || request.high_mark < 0) {
-               return DRM_ERR(EINVAL);
+           request->low_mark < 0 || request->high_mark < 0) {
+               return EINVAL;
        }
 
        DRM_SPINLOCK(&dev->dma_lock);
-       if (request.low_mark > dma->bufs[order].buf_count ||
-           request.high_mark > dma->bufs[order].buf_count) {
-               return DRM_ERR(EINVAL);
+       if (request->low_mark > dma->bufs[order].buf_count ||
+           request->high_mark > dma->bufs[order].buf_count) {
+               return EINVAL;
        }
 
-       dma->bufs[order].freelist.low_mark  = request.low_mark;
-       dma->bufs[order].freelist.high_mark = request.high_mark;
+       dma->bufs[order].freelist.low_mark  = request->low_mark;
+       dma->bufs[order].freelist.high_mark = request->high_mark;
        DRM_SPINUNLOCK(&dev->dma_lock);
 
        return 0;
 }
 
-int drm_freebufs(DRM_IOCTL_ARGS)
+int drm_freebufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_device_dma_t *dma = dev->dma;
-       drm_buf_free_t request;
+       drm_buf_free_t *request = data;
        int i;
        int idx;
        drm_buf_t *buf;
        int retcode = 0;
 
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_free_t *)data, sizeof(request) );
-
-       DRM_DEBUG( "%d\n", request.count );
+       DRM_DEBUG( "%d\n", request->count );
        
        DRM_SPINLOCK(&dev->dma_lock);
-       for ( i = 0 ; i < request.count ; i++ ) {
-               if (DRM_COPY_FROM_USER(&idx, &request.list[i], sizeof(idx))) {
-                       retcode = DRM_ERR(EFAULT);
+       for ( i = 0 ; i < request->count ; i++ ) {
+               if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) {
+                       retcode = EFAULT;
                        break;
                }
                if ( idx < 0 || idx >= dma->buf_count ) {
                        DRM_ERROR( "Index %d (of %d max)\n",
                                   idx, dma->buf_count - 1 );
-                       retcode = DRM_ERR(EINVAL);
+                       retcode = EINVAL;
                        break;
                }
                buf = dma->buflist[idx];
-               if ( buf->filp != filp ) {
+               if ( buf->file_priv != file_priv ) {
                        DRM_ERROR("Process %d freeing buffer not owned\n",
                                   DRM_CURRENTPID);
-                       retcode = DRM_ERR(EINVAL);
+                       retcode = EINVAL;
                        break;
                }
                drm_free_buffer(dev, buf);
@@ -1021,9 +1007,8 @@ int drm_freebufs(DRM_IOCTL_ARGS)
        return retcode;
 }
 
-int drm_mapbufs(DRM_IOCTL_ARGS)
+int drm_mapbufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_device_dma_t *dma = dev->dma;
        int retcode = 0;
        const int zero = 0;
@@ -1040,27 +1025,25 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
        vaddr_t vaddr;
 #endif /* __NetBSD__ || __OpenBSD__ */
 
-       drm_buf_map_t request;
+       drm_buf_map_t *request = data;
        int i;
 
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_buf_map_t *)data, sizeof(request) );
-
 #if defined(__NetBSD__) || defined(__OpenBSD__)
        if (!vfinddev(kdev, VCHR, &vn))
                return 0;       /* FIXME: Shouldn't this be EINVAL or something? */
 #endif /* __NetBSD__ || __OpenBSD */
 
 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
-       vms = p->td_proc->p_vmspace;
+       vms = DRM_CURPROC->td_proc->p_vmspace;
 #else
-       vms = p->p_vmspace;
+       vms = DRM_CURPROC->p_vmspace;
 #endif
 
        DRM_SPINLOCK(&dev->dma_lock);
        dev->buf_use++;         /* Can't allocate more after this call */
        DRM_SPINUNLOCK(&dev->dma_lock);
 
-       if (request.count < dma->buf_count)
+       if (request->count < dma->buf_count)
                goto done;
 
        if ((dev->driver.use_agp && (dma->flags & _DRM_DMA_USE_AGP)) ||
@@ -1082,10 +1065,11 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
        vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
 #if __FreeBSD_version >= 600023
        retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
-           VM_PROT_ALL, MAP_SHARED, OBJT_DEVICE, kdev, foff );
+           VM_PROT_ALL, MAP_SHARED, OBJT_DEVICE, dev->devnode, foff);
 #else
        retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
-           VM_PROT_ALL, MAP_SHARED, SLIST_FIRST(&kdev->si_hlist), foff );
+           VM_PROT_ALL, MAP_SHARED, SLIST_FIRST(&dev->devnode->si_hlist),
+           foff);
 #endif
 #elif defined(__NetBSD__) || defined(__OpenBSD__)
        vaddr = round_page((vaddr_t)vms->vm_daddr + MAXDSIZ);
@@ -1096,26 +1080,26 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
        if (retcode)
                goto done;
 
-       request.virtual = (void *)vaddr;
+       request->virtual = (void *)vaddr;
 
        for ( i = 0 ; i < dma->buf_count ; i++ ) {
-               if (DRM_COPY_TO_USER(&request.list[i].idx,
-                   &dma->buflist[i]->idx, sizeof(request.list[0].idx))) {
+               if (DRM_COPY_TO_USER(&request->list[i].idx,
+                   &dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
                        retcode = EFAULT;
                        goto done;
                }
-               if (DRM_COPY_TO_USER(&request.list[i].total,
-                   &dma->buflist[i]->total, sizeof(request.list[0].total))) {
+               if (DRM_COPY_TO_USER(&request->list[i].total,
+                   &dma->buflist[i]->total, sizeof(request->list[0].total))) {
                        retcode = EFAULT;
                        goto done;
                }
-               if (DRM_COPY_TO_USER(&request.list[i].used, &zero,
+               if (DRM_COPY_TO_USER(&request->list[i].used, &zero,
                    sizeof(zero))) {
                        retcode = EFAULT;
                        goto done;
                }
                address = vaddr + dma->buflist[i]->offset; /* *** */
-               if (DRM_COPY_TO_USER(&request.list[i].address, &address,
+               if (DRM_COPY_TO_USER(&request->list[i].address, &address,
                    sizeof(address))) {
                        retcode = EFAULT;
                        goto done;
@@ -1123,11 +1107,9 @@ int drm_mapbufs(DRM_IOCTL_ARGS)
        }
 
  done:
-       request.count = dma->buf_count;
-
-       DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
+       request->count = dma->buf_count;
 
-       DRM_COPY_TO_USER_IOCTL((drm_buf_map_t *)data, request, sizeof(request));
+       DRM_DEBUG( "%d buffers, retcode = %d\n", request->count, retcode );
 
-       return DRM_ERR(retcode);
+       return retcode;
 }
index 8e00954..4155ee9 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
- */
 /*-
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_context.c
+ * Implementation of the context management ioctls.
+ */
+
 #include "drmP.h"
 
 /* ================================================================
@@ -109,7 +110,7 @@ int drm_ctxbitmap_init(drm_device_t *dev)
        dev->ctx_bitmap = malloc(PAGE_SIZE, M_DRM, M_NOWAIT | M_ZERO);
        if ( dev->ctx_bitmap == NULL ) {
                DRM_UNLOCK();
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
        dev->context_sareas = NULL;
        dev->max_context = -1;
@@ -136,48 +137,39 @@ void drm_ctxbitmap_cleanup(drm_device_t *dev)
  * Per Context SAREA Support
  */
 
-int drm_getsareactx( DRM_IOCTL_ARGS )
+int drm_getsareactx( drm_device_t *dev, void *data, struct drm_file *file_priv )
 {
-       DRM_DEVICE;
-       drm_ctx_priv_map_t request;
+       drm_ctx_priv_map_t *request = data;
        drm_local_map_t *map;
 
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data, 
-                          sizeof(request) );
-
        DRM_LOCK();
-       if (dev->max_context < 0 || request.ctx_id >= (unsigned) dev->max_context) {
+       if (dev->max_context < 0 ||
+           request->ctx_id >= (unsigned) dev->max_context) {
                DRM_UNLOCK();
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }
 
-       map = dev->context_sareas[request.ctx_id];
+       map = dev->context_sareas[request->ctx_id];
        DRM_UNLOCK();
 
-       request.handle = map->handle;
-
-       DRM_COPY_TO_USER_IOCTL( (drm_ctx_priv_map_t *)data, request, sizeof(request) );
+       request->handle = map->handle;
 
        return 0;
 }
 
-int drm_setsareactx( DRM_IOCTL_ARGS )
+int drm_setsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_ctx_priv_map_t request;
+       drm_ctx_priv_map_t *request = data;
        drm_local_map_t *map = NULL;
 
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
-                          sizeof(request) );
-
        DRM_LOCK();
        TAILQ_FOREACH(map, &dev->maplist, link) {
-               if (map->handle == request.handle) {
+               if (map->handle == request->handle) {
                        if (dev->max_context < 0)
                                goto bad;
-                       if (request.ctx_id >= (unsigned) dev->max_context)
+                       if (request->ctx_id >= (unsigned) dev->max_context)
                                goto bad;
-                       dev->context_sareas[request.ctx_id] = map;
+                       dev->context_sareas[request->ctx_id] = map;
                        DRM_UNLOCK();
                        return 0;
                }
@@ -185,7 +177,7 @@ int drm_setsareactx( DRM_IOCTL_ARGS )
 
 bad:
        DRM_UNLOCK();
-       return DRM_ERR(EINVAL);
+       return EINVAL;
 }
 
 /* ================================================================
@@ -196,7 +188,7 @@ int drm_context_switch(drm_device_t *dev, int old, int new)
 {
         if ( test_and_set_bit( 0, &dev->context_flag ) ) {
                 DRM_ERROR( "Reentering -- FIXME\n" );
-                return DRM_ERR(EBUSY);
+                return EBUSY;
         }
 
         DRM_DEBUG( "Context switch from %d to %d\n", old, new );
@@ -225,120 +217,98 @@ int drm_context_switch_complete(drm_device_t *dev, int new)
         return 0;
 }
 
-int drm_resctx(DRM_IOCTL_ARGS)
+int drm_resctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       drm_ctx_res_t res;
+       drm_ctx_res_t *res = data;
        drm_ctx_t ctx;
        int i;
 
-       DRM_COPY_FROM_USER_IOCTL( res, (drm_ctx_res_t *)data, sizeof(res) );
-
-       if ( res.count >= DRM_RESERVED_CONTEXTS ) {
+       if ( res->count >= DRM_RESERVED_CONTEXTS ) {
                bzero(&ctx, sizeof(ctx));
                for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
                        ctx.handle = i;
-                       if ( DRM_COPY_TO_USER( &res.contexts[i],
+                       if ( DRM_COPY_TO_USER( &res->contexts[i],
                                           &ctx, sizeof(ctx) ) )
-                               return DRM_ERR(EFAULT);
+                               return EFAULT;
                }
        }
-       res.count = DRM_RESERVED_CONTEXTS;
-
-       DRM_COPY_TO_USER_IOCTL( (drm_ctx_res_t *)data, res, sizeof(res) );
+       res->count = DRM_RESERVED_CONTEXTS;
 
        return 0;
 }
 
-int drm_addctx(DRM_IOCTL_ARGS)
+int drm_addctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_ctx_t ctx;
-
-       DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+       drm_ctx_t *ctx = data;
 
-       ctx.handle = drm_ctxbitmap_next(dev);
-       if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
+       ctx->handle = drm_ctxbitmap_next(dev);
+       if ( ctx->handle == DRM_KERNEL_CONTEXT ) {
                                /* Skip kernel's context and get a new one. */
-               ctx.handle = drm_ctxbitmap_next(dev);
+               ctx->handle = drm_ctxbitmap_next(dev);
        }
-       DRM_DEBUG( "%d\n", ctx.handle );
-       if ( ctx.handle == -1 ) {
+       DRM_DEBUG( "%d\n", ctx->handle );
+       if ( ctx->handle == -1 ) {
                DRM_DEBUG( "Not enough free contexts.\n" );
                                /* Should this return -EBUSY instead? */
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
        }
 
-       if (dev->driver.context_ctor && ctx.handle != DRM_KERNEL_CONTEXT) {
+       if (dev->driver.context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
                DRM_LOCK();
-               dev->driver.context_ctor(dev, ctx.handle);
+               dev->driver.context_ctor(dev, ctx->handle);
                DRM_UNLOCK();
        }
 
-       DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
-
        return 0;
 }
 
-int drm_modctx(DRM_IOCTL_ARGS)
+int drm_modctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
        /* This does nothing */
        return 0;
 }
 
-int drm_getctx(DRM_IOCTL_ARGS)
+int drm_getctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       drm_ctx_t ctx;
-
-       DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+       drm_ctx_t *ctx = data;
 
        /* This is 0, because we don't handle any context flags */
-       ctx.flags = 0;
-
-       DRM_COPY_TO_USER_IOCTL( (drm_ctx_t *)data, ctx, sizeof(ctx) );
+       ctx->flags = 0;
 
        return 0;
 }
 
-int drm_switchctx(DRM_IOCTL_ARGS)
+int drm_switchctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_ctx_t ctx;
+       drm_ctx_t *ctx = data;
 
-       DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
-
-       DRM_DEBUG( "%d\n", ctx.handle );
-       return drm_context_switch(dev, dev->last_context, ctx.handle);
+       DRM_DEBUG( "%d\n", ctx->handle );
+       return drm_context_switch(dev, dev->last_context, ctx->handle);
 }
 
-int drm_newctx(DRM_IOCTL_ARGS)
+int drm_newctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_ctx_t ctx;
-
-       DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+       drm_ctx_t *ctx = data;
 
-       DRM_DEBUG( "%d\n", ctx.handle );
-       drm_context_switch_complete(dev, ctx.handle);
+       DRM_DEBUG( "%d\n", ctx->handle );
+       drm_context_switch_complete(dev, ctx->handle);
 
        return 0;
 }
 
-int drm_rmctx(DRM_IOCTL_ARGS)
+int drm_rmctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_ctx_t ctx;
-
-       DRM_COPY_FROM_USER_IOCTL( ctx, (drm_ctx_t *)data, sizeof(ctx) );
+       drm_ctx_t *ctx = data;
 
-       DRM_DEBUG( "%d\n", ctx.handle );
-       if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
+       DRM_DEBUG( "%d\n", ctx->handle );
+       if ( ctx->handle != DRM_KERNEL_CONTEXT ) {
                if (dev->driver.context_dtor) {
                        DRM_LOCK();
-                       dev->driver.context_dtor(dev, ctx.handle);
+                       dev->driver.context_dtor(dev, ctx->handle);
                        DRM_UNLOCK();
                }
 
-               drm_ctxbitmap_free(dev, ctx.handle);
+               drm_ctxbitmap_free(dev, ctx->handle);
        }
 
        return 0;
index 67b3fe2..71ef845 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
- */
 /*-
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_dma.c
+ * Support code for DMA buffer management.
+ *
+ * The implementation used to be significantly more complicated, but the
+ * complexity has been moved into the drivers as different buffer management
+ * schemes evolved.
+ */
+
 #include "drmP.h"
 
 int drm_dma_setup(drm_device_t *dev)
@@ -38,9 +43,9 @@ int drm_dma_setup(drm_device_t *dev)
 
        dev->dma = malloc(sizeof(*dev->dma), M_DRM, M_NOWAIT | M_ZERO);
        if (dev->dma == NULL)
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
 
-       DRM_SPININIT(dev->dma_lock, "drmdma");
+       DRM_SPININIT(&dev->dma_lock, "drmdma");
 
        return 0;
 }
@@ -80,7 +85,7 @@ void drm_dma_takedown(drm_device_t *dev)
        free(dma->pagelist, M_DRM);
        free(dev->dma, M_DRM);
        dev->dma = NULL;
-       DRM_SPINUNINIT(dev->dma_lock);
+       DRM_SPINUNINIT(&dev->dma_lock);
 }
 
 
@@ -89,18 +94,18 @@ void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
        if (!buf) return;
 
        buf->pending  = 0;
-       buf->filp     = NULL;
+       buf->file_priv= NULL;
        buf->used     = 0;
 }
 
-void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
+void drm_reclaim_buffers(drm_device_t *dev, struct drm_file *file_priv)
 {
        drm_device_dma_t *dma = dev->dma;
        int              i;
 
        if (!dma) return;
        for (i = 0; i < dma->buf_count; i++) {
-               if (dma->buflist[i]->filp == filp) {
+               if (dma->buflist[i]->file_priv == file_priv) {
                        switch (dma->buflist[i]->list) {
                        case DRM_LIST_NONE:
                                drm_free_buffer(dev, dma->buflist[i]);
@@ -117,12 +122,12 @@ void drm_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
 }
 
 /* Call into the driver-specific DMA handler */
-int drm_dma(DRM_IOCTL_ARGS)
+int drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
        if (dev->driver.dma_ioctl) {
-               return dev->driver.dma_ioctl(kdev, cmd, data, flags, p, filp);
+               /* shared code returns -errno */
+               return -dev->driver.dma_ioctl(dev, data, file_priv);
        } else {
                DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
                return EINVAL;
index 379e0aa..fb318d4 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
- */
 /*-
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_drawable.c
+ * This file implements ioctls to store information along with DRM drawables,
+ * such as the current set of cliprects for vblank-synced buffer swaps.
+ */
+
 #include "drmP.h"
 
-int drm_adddraw(DRM_IOCTL_ARGS)
+struct bsd_drm_drawable_info {
+       struct drm_drawable_info info;
+       int handle;
+       RB_ENTRY(bsd_drm_drawable_info) tree;
+};
+
+static int
+drm_drawable_compare(struct bsd_drm_drawable_info *a,
+    struct bsd_drm_drawable_info *b)
+{
+       if (a->handle > b->handle)
+               return 1;
+       if (a->handle < b->handle)
+               return -1;
+       return 0;
+}
+
+RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
+    drm_drawable_compare);
+
+struct drm_drawable_info *
+drm_get_drawable_info(drm_device_t *dev, int handle)
+{
+       struct bsd_drm_drawable_info find, *result;
+
+       find.handle = handle;
+       result = RB_FIND(drawable_tree, &dev->drw_head, &find);
+
+       return &result->info;
+}
+
+int drm_adddraw(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       drm_draw_t draw;
+       drm_draw_t *draw = data;
+       struct bsd_drm_drawable_info *info;
 
-       draw.handle = 0;        /* NOOP */
-       DRM_DEBUG("%d\n", draw.handle);
-       
-       DRM_COPY_TO_USER_IOCTL( (drm_draw_t *)data, draw, sizeof(draw) );
+       info = drm_calloc(1, sizeof(struct bsd_drm_drawable_info),
+           DRM_MEM_DRAWABLE);
+       if (info == NULL)
+               return ENOMEM;
+
+       info->handle = alloc_unr(dev->drw_unrhdr);
+       DRM_SPINLOCK(&dev->drw_lock);
+       RB_INSERT(drawable_tree, &dev->drw_head, info);
+       draw->handle = info->handle;
+       DRM_SPINUNLOCK(&dev->drw_lock);
+
+       DRM_DEBUG("%d\n", draw->handle);
 
        return 0;
 }
 
-int drm_rmdraw(DRM_IOCTL_ARGS)
+int drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       return 0;               /* NOOP */
+       drm_draw_t *draw = (drm_draw_t *)data;
+       struct drm_drawable_info *info;
+
+       DRM_SPINLOCK(&dev->drw_lock);
+       info = drm_get_drawable_info(dev, draw->handle);
+       if (info != NULL) {
+               RB_REMOVE(drawable_tree, &dev->drw_head,
+                   (struct bsd_drm_drawable_info *)info);
+               DRM_SPINUNLOCK(&dev->drw_lock);
+               free_unr(dev->drw_unrhdr, draw->handle);
+               drm_free(info, sizeof(struct bsd_drm_drawable_info),
+                   DRM_MEM_DRAWABLE);
+               return 0;
+       } else {
+               DRM_SPINUNLOCK(&dev->drw_lock);
+               return EINVAL;
+       }
+}
+
+int drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_drawable_info *info;
+       struct drm_update_draw *update = (struct drm_update_draw *)data;
+       int ret;
+
+       info = drm_get_drawable_info(dev, update->handle);
+       if (info == NULL)
+               return EINVAL;
+
+       switch (update->type) {
+       case DRM_DRAWABLE_CLIPRECTS:
+               DRM_SPINLOCK(&dev->drw_lock);
+               if (update->num != info->num_rects) {
+                       drm_free(info->rects,
+                           sizeof(*info->rects) * info->num_rects,
+                           DRM_MEM_DRAWABLE);
+                       info->rects = NULL;
+                       info->num_rects = 0;
+               }
+               if (update->num == 0) {
+                       DRM_SPINUNLOCK(&dev->drw_lock);
+                       return 0;
+               }
+               if (info->rects == NULL) {
+                       info->rects = drm_alloc(sizeof(*info->rects) *
+                           update->num, DRM_MEM_DRAWABLE);
+                       if (info->rects == NULL)
+                               return ENOMEM;
+                       info->num_rects = update->num;
+               }
+               /* For some reason the pointer arg is unsigned long long. */
+               ret = copyin((void *)(intptr_t)update->data, info->rects,
+                   sizeof(*info->rects) * info->num_rects);
+               DRM_SPINUNLOCK(&dev->drw_lock);
+               return ret;
+       default:
+               return EINVAL;
+       }
 }
index baaeb43..d6868b9 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_drv.h -- Generic driver template -*- linux-c -*-
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
- */
 /*-
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_drv.c
+ * The catch-all file for DRM device support, including module setup/teardown,
+ * open/close, and ioctl dispatch.
+ */
+
+
+#include <sys/limits.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_sarea.h"
@@ -64,63 +68,64 @@ MODULE_DEPEND(drm, mem, 1, 1, 1);
 #endif /* __NetBSD__ || __OpenBSD__ */
 
 static drm_ioctl_desc_t                  drm_ioctls[256] = {
-       [DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { drm_version,     0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { drm_getunique,   0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { drm_getmagic,    0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { drm_getmap,      0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { drm_getclient,   0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { drm_getstats,    0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)]   = { drm_setversion,  DRM_MASTER|DRM_ROOT_ONLY },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { drm_setunique,   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]         = { drm_noop,        DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { drm_noop,        DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { drm_authmagic,   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { drm_rmmap_ioctl, DRM_AUTH },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, DRM_AUTH },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { drm_addctx,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { drm_rmctx,       DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]       = { drm_modctx,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]       = { drm_getctx,      DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]    = { drm_switchctx,   DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]       = { drm_newctx,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]       = { drm_resctx,      DRM_AUTH },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { drm_adddraw,     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { drm_rmdraw,      DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_LOCK)]          = { drm_lock,        DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { drm_unlock,      DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { drm_noop,        DRM_AUTH },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { drm_markbufs,    DRM_AUTH|DRM_MASTER },
-       [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { drm_infobufs,    DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { drm_mapbufs,     DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { drm_freebufs,    DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_IOCTL_DMA)]           = { drm_dma,         DRM_AUTH },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { drm_control,     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { drm_agp_info_ioctl, DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { drm_sg_alloc,    DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { drm_sg_free,     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { drm_wait_vblank, 0 },
+       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_DMA, drm_dma, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 };
 
 #ifdef __FreeBSD__
@@ -198,6 +203,7 @@ int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)
                        "dri/card%d", unit);
 #if __FreeBSD_version >= 500000
        mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF);
+       mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF);
 #endif
 
        id_entry = drm_find_description(pci_get_vendor(dev->device),
@@ -496,7 +502,7 @@ static int drm_lastclose(drm_device_t *dev)
        drm_dma_takedown(dev);
        if ( dev->lock.hw_lock ) {
                dev->lock.hw_lock = NULL; /* SHM removed */
-               dev->lock.filp = NULL;
+               dev->lock.file_priv = NULL;
                DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
        }
 
@@ -510,8 +516,11 @@ static int drm_load(drm_device_t *dev)
        DRM_DEBUG( "\n" );
 
        dev->irq = pci_get_irq(dev->device);
-       /* XXX Fix domain number (alpha hoses) */
+#if defined(__FreeBSD__) && __FreeBSD_version >= 700053
+       dev->pci_domain = pci_get_domain(dev->device);
+#else
        dev->pci_domain = 0;
+#endif
        dev->pci_bus = pci_get_bus(dev->device);
        dev->pci_slot = pci_get_slot(dev->device);
        dev->pci_func = pci_get_function(dev->device);
@@ -529,7 +538,9 @@ static int drm_load(drm_device_t *dev)
 
        if (dev->driver.load != NULL) {
                DRM_LOCK();
-               retcode = dev->driver.load(dev, dev->id_entry->driver_private);
+               /* Shared code returns -errno. */
+               retcode = -dev->driver.load(dev,
+                   dev->id_entry->driver_private);
                DRM_UNLOCK();
                if (retcode != 0)
                        goto error;
@@ -541,7 +552,7 @@ static int drm_load(drm_device_t *dev)
                if (dev->driver.require_agp && dev->agp == NULL) {
                        DRM_ERROR("Card isn't AGP, or couldn't initialize "
                            "AGP.\n");
-                       retcode = DRM_ERR(ENOMEM);
+                       retcode = ENOMEM;
                        goto error;
                }
                if (dev->agp != NULL) {
@@ -556,7 +567,13 @@ static int drm_load(drm_device_t *dev)
                DRM_ERROR("Cannot allocate memory for context bitmap.\n");
                goto error;
        }
-       
+
+       dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL);
+       if (dev->drw_unrhdr == NULL) {
+               DRM_ERROR("Couldn't allocate drawable number allocator\n");
+               goto error;
+       }
+
        DRM_INFO("Initialized %s %d.%d.%d %s\n",
                dev->driver.name,
                dev->driver.major,
@@ -628,6 +645,8 @@ static void drm_unload(drm_device_t *dev)
        if (dev->driver.unload != NULL)
                dev->driver.unload(dev);
 
+       delete_unrhdr(dev->drw_unrhdr);
+
        drm_mem_uninit();
 #if defined(__FreeBSD__) &&  __FreeBSD_version >= 500000
        mtx_destroy(&dev->dev_lock);
@@ -635,32 +654,27 @@ static void drm_unload(drm_device_t *dev)
 }
 
 
-int drm_version(DRM_IOCTL_ARGS)
+int drm_version(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_version_t version;
+       drm_version_t *version = data;
        int len;
 
-       DRM_COPY_FROM_USER_IOCTL( version, (drm_version_t *)data, sizeof(version) );
-
 #define DRM_COPY( name, value )                                                \
        len = strlen( value );                                          \
        if ( len > name##_len ) len = name##_len;                       \
        name##_len = strlen( value );                                   \
        if ( len && name ) {                                            \
                if ( DRM_COPY_TO_USER( name, value, len ) )             \
-                       return DRM_ERR(EFAULT);                         \
+                       return EFAULT;                          \
        }
 
-       version.version_major           = dev->driver.major;
-       version.version_minor           = dev->driver.minor;
-       version.version_patchlevel      = dev->driver.patchlevel;
-
-       DRM_COPY(version.name, dev->driver.name);
-       DRM_COPY(version.date, dev->driver.date);
-       DRM_COPY(version.desc, dev->driver.desc);
+       version->version_major          = dev->driver.major;
+       version->version_minor          = dev->driver.minor;
+       version->version_patchlevel     = dev->driver.patchlevel;
 
-       DRM_COPY_TO_USER_IOCTL( (drm_version_t *)data, version, sizeof(version) );
+       DRM_COPY(version->name, dev->driver.name);
+       DRM_COPY(version->date, dev->driver.date);
+       DRM_COPY(version->desc, dev->driver.desc);
 
        return 0;
 }
@@ -692,24 +706,26 @@ int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 
 int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 {
-       drm_file_t *priv;
-       DRM_DEVICE;
+       drm_device_t *dev = drm_get_device_from_kdev(kdev);
+       drm_file_t *file_priv;
        int retcode = 0;
-       DRMFILE filp = (void *)(uintptr_t)(DRM_CURRENTPID);
-       
+
        DRM_DEBUG( "open_count = %d\n", dev->open_count );
 
        DRM_LOCK();
 
-       priv = drm_find_file_by_proc(dev, p);
-       if (!priv) {
+       file_priv = drm_find_file_by_proc(dev, p);
+       if (!file_priv) {
                DRM_UNLOCK();
                DRM_ERROR("can't find authenticator\n");
                return EINVAL;
        }
 
+       if (--file_priv->refs != 0)
+               goto done;
+
        if (dev->driver.preclose != NULL)
-               dev->driver.preclose(dev, filp);
+               dev->driver.preclose(dev, file_priv);
 
        /* ========================================================
         * Begin inline drm_release
@@ -724,12 +740,12 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 #endif
 
        if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
-           && dev->lock.filp == filp) {
+           && dev->lock.file_priv == file_priv) {
                DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
                          DRM_CURRENTPID,
                          _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
                if (dev->driver.reclaim_buffers_locked != NULL)
-                       dev->driver.reclaim_buffers_locked(dev, filp);
+                       dev->driver.reclaim_buffers_locked(dev, file_priv);
 
                drm_lock_free(dev, &dev->lock.hw_lock->lock,
                    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
@@ -744,12 +760,12 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
                for (;;) {
                        if ( !dev->lock.hw_lock ) {
                                /* Device has been unregistered */
-                               retcode = DRM_ERR(EINTR);
+                               retcode = EINTR;
                                break;
                        }
                        if (drm_lock_take(&dev->lock.hw_lock->lock,
                            DRM_KERNEL_CONTEXT)) {
-                               dev->lock.filp = filp;
+                               dev->lock.file_priv = file_priv;
                                dev->lock.lock_time = jiffies;
                                 atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
                                break;  /* Got lock */
@@ -766,14 +782,14 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
                                break;
                }
                if (retcode == 0) {
-                       dev->driver.reclaim_buffers_locked(dev, filp);
+                       dev->driver.reclaim_buffers_locked(dev, file_priv);
                        drm_lock_free(dev, &dev->lock.hw_lock->lock,
                            DRM_KERNEL_CONTEXT);
                }
        }
 
        if (dev->driver.use_dma && !dev->driver.reclaim_buffers_locked)
-               drm_reclaim_buffers(dev, filp);
+               drm_reclaim_buffers(dev, file_priv);
 
 #if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
        funsetown(&dev->buf_sigio);
@@ -783,17 +799,16 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
        dev->buf_pgid = 0;
 #endif /* __NetBSD__  || __OpenBSD__ */
 
-       if (--priv->refs == 0) {
-               if (dev->driver.postclose != NULL)
-                       dev->driver.postclose(dev, priv);
-               TAILQ_REMOVE(&dev->files, priv, link);
-               free(priv, M_DRM);
-       }
+       if (dev->driver.postclose != NULL)
+               dev->driver.postclose(dev, file_priv);
+       TAILQ_REMOVE(&dev->files, file_priv, link);
+       free(file_priv, M_DRM);
 
        /* ========================================================
         * End inline drm_release
         */
 
+done:
        atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
 #ifdef __FreeBSD__
        device_unbusy(dev->device);
@@ -812,32 +827,33 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, 
     DRM_STRUCTPROC *p)
 {
-       DRM_DEVICE;
+       drm_device_t *dev = drm_get_device_from_kdev(kdev);
        int retcode = 0;
        drm_ioctl_desc_t *ioctl;
-       int (*func)(DRM_IOCTL_ARGS);
+       int (*func)(drm_device_t *dev, void *data, struct drm_file *file_priv);
        int nr = DRM_IOCTL_NR(cmd);
        int is_driver_ioctl = 0;
-       drm_file_t *priv;
-       DRMFILE filp = (DRMFILE)(uintptr_t)DRM_CURRENTPID;
+       drm_file_t *file_priv;
 
        DRM_LOCK();
-       priv = drm_find_file_by_proc(dev, p);
+       file_priv = drm_find_file_by_proc(dev, p);
        DRM_UNLOCK();
-       if (priv == NULL) {
+       if (file_priv == NULL) {
                DRM_ERROR("can't find authenticator\n");
                return EINVAL;
        }
 
        atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
-       ++priv->ioctl_count;
+       ++file_priv->ioctl_count;
 
 #ifdef __FreeBSD__
        DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
-                DRM_CURRENTPID, cmd, nr, (long)dev->device, priv->authenticated );
+           DRM_CURRENTPID, cmd, nr, (long)dev->device,
+           file_priv->authenticated );
 #elif defined(__NetBSD__) || defined(__OpenBSD__)
        DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
-                DRM_CURRENTPID, cmd, nr, (long)&dev->device, priv->authenticated );
+           DRM_CURRENTPID, cmd, nr, (long)&dev->device,
+           file_priv->authenticated );
 #endif
 
        switch (cmd) {
@@ -892,24 +908,25 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
                DRM_DEBUG( "no function\n" );
                return EINVAL;
        }
-       /* ioctl->master check should be against something in the filp set up
-        * for the first opener, but it doesn't matter yet.
-        */
+
        if (((ioctl->flags & DRM_ROOT_ONLY) && !DRM_SUSER(p)) ||
-           ((ioctl->flags & DRM_AUTH) && !priv->authenticated) ||
-           ((ioctl->flags & DRM_MASTER) && !priv->master))
+           ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
+           ((ioctl->flags & DRM_MASTER) && !file_priv->master))
                return EACCES;
 
-       if (is_driver_ioctl)
+       if (is_driver_ioctl) {
                DRM_LOCK();
-       retcode = func(kdev, cmd, data, flags, p, filp);
-       if (is_driver_ioctl)
+               /* shared code returns -errno */
+               retcode = -func(dev, data, file_priv);
                DRM_UNLOCK();
+       } else {
+               retcode = func(dev, data, file_priv);
+       }
 
        if (retcode != 0)
                DRM_DEBUG("    returning %d\n", retcode);
 
-       return DRM_ERR(retcode);
+       return retcode;
 }
 
 drm_local_map_t *drm_getsarea(drm_device_t *dev)
index f5c9349..20bae8d 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_fops.h -- File operations for DRM -*- linux-c -*-
- * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
- */
 /*-
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_fops.c
+ * Support code for dealing with the file privates associated with each
+ * open of the DRM device.
+ */
+
 #include "drmP.h"
 
 drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p)
@@ -75,7 +77,7 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
                priv = malloc(sizeof(*priv), M_DRM, M_NOWAIT | M_ZERO);
                if (priv == NULL) {
                        DRM_UNLOCK();
-                       return DRM_ERR(ENOMEM);
+                       return ENOMEM;
                }
 #if __FreeBSD_version >= 500000
                priv->uid               = p->td_ucred->cr_svuid;
@@ -93,7 +95,8 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
                priv->authenticated     = DRM_SUSER(p);
 
                if (dev->driver.open) {
-                       retcode = dev->driver.open(dev, priv);
+                       /* shared code returns -errno */
+                       retcode = -dev->driver.open(dev, priv);
                        if (retcode != 0) {
                                free(priv, M_DRM);
                                DRM_UNLOCK();
index e22faa8..ce78bb8 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
- * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
- */
 /*-
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_ioctl.c
+ * Varios minor DRM ioctls not applicable to other files, such as versioning
+ * information and reporting DRM information to userland.
+ */
+
 #include "drmP.h"
 
 /*
  * before setunique has been called.  The format for the bus-specific part of
  * the unique is not defined for any other bus.
  */
-int drm_getunique(DRM_IOCTL_ARGS)
+int drm_getunique(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_unique_t     u;
-
-       DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );
+       drm_unique_t     *u = data;
 
-       if (u.unique_len >= dev->unique_len) {
-               if (DRM_COPY_TO_USER(u.unique, dev->unique, dev->unique_len))
-                       return DRM_ERR(EFAULT);
+       if (u->unique_len >= dev->unique_len) {
+               if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
+                       return EFAULT;
        }
-       u.unique_len = dev->unique_len;
-
-       DRM_COPY_TO_USER_IOCTL( (drm_unique_t *)data, u, sizeof(u) );
+       u->unique_len = dev->unique_len;
 
        return 0;
 }
@@ -60,28 +57,25 @@ int drm_getunique(DRM_IOCTL_ARGS)
 /* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
  * requested version 1.1 or greater.
  */
-int drm_setunique(DRM_IOCTL_ARGS)
+int drm_setunique(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_unique_t u;
+       drm_unique_t *u = data;
        int domain, bus, slot, func, ret;
        char *busid;
 
-       DRM_COPY_FROM_USER_IOCTL( u, (drm_unique_t *)data, sizeof(u) );
-
        /* Check and copy in the submitted Bus ID */
-       if (!u.unique_len || u.unique_len > 1024)
-               return DRM_ERR(EINVAL);
+       if (!u->unique_len || u->unique_len > 1024)
+               return EINVAL;
 
-       busid = malloc(u.unique_len + 1, M_DRM, M_WAITOK);
+       busid = malloc(u->unique_len + 1, M_DRM, M_WAITOK);
        if (busid == NULL)
-               return DRM_ERR(ENOMEM);
+               return ENOMEM;
 
-       if (DRM_COPY_FROM_USER(busid, u.unique, u.unique_len)) {
+       if (DRM_COPY_FROM_USER(busid, u->unique, u->unique_len)) {
                free(busid, M_DRM);
-               return DRM_ERR(EFAULT);
+               return EFAULT;
        }
-       busid[u.unique_len] = '\0';
+       busid[u->unique_len] = '\0';
 
        /* Return error if the busid submitted doesn't match the device's actual
         * busid.
@@ -89,7 +83,7 @@ int drm_setunique(DRM_IOCTL_ARGS)
        ret = sscanf(busid, "PCI:%d:%d:%d", &bus, &slot, &func);
        if (ret != 3) {
                free(busid, M_DRM);
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }
        domain = bus >> 8;
        bus &= 0xff;
@@ -99,17 +93,17 @@ int drm_setunique(DRM_IOCTL_ARGS)
            (slot != dev->pci_slot) ||
            (func != dev->pci_func)) {
                free(busid, M_DRM);
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }
 
        /* Actually set the device's busid now. */
        DRM_LOCK();
        if (dev->unique_len || dev->unique) {
                DRM_UNLOCK();
-               return DRM_ERR(EBUSY);
+               return EBUSY;
        }
 
-       dev->unique_len = u.unique_len;
+       dev->unique_len = u->unique_len;
        dev->unique = busid;
        DRM_UNLOCK();
 
@@ -143,32 +137,29 @@ drm_set_busid(drm_device_t *dev)
        return 0;
 }
 
-int drm_getmap(DRM_IOCTL_ARGS)
+int drm_getmap(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_map_t    map;
+       drm_map_t    *map = data;
        drm_local_map_t    *mapinlist;
        int          idx;
        int          i = 0;
 
-       DRM_COPY_FROM_USER_IOCTL( map, (drm_map_t *)data, sizeof(map) );
-
-       idx = map.offset;
+       idx = map->offset;
 
        DRM_LOCK();
        if (idx < 0) {
                DRM_UNLOCK();
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }
 
        TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
                if (i==idx) {
-                       map.offset = mapinlist->offset;
-                       map.size   = mapinlist->size;
-                       map.type   = mapinlist->type;
-                       map.flags  = mapinlist->flags;
-                       map.handle = mapinlist->handle;
-                       map.mtrr   = mapinlist->mtrr;
+                       map->offset = mapinlist->offset;
+                       map->size   = mapinlist->size;
+                       map->type   = mapinlist->type;
+                       map->flags  = mapinlist->flags;
+                       map->handle = mapinlist->handle;
+                       map->mtrr   = mapinlist->mtrr;
                        break;
                }
                i++;
@@ -179,100 +170,89 @@ int drm_getmap(DRM_IOCTL_ARGS)
        if (mapinlist == NULL)
                return EINVAL;
 
-       DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) );
-
        return 0;
 }
 
-int drm_getclient(DRM_IOCTL_ARGS)
+int drm_getclient(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_client_t client;
+       drm_client_t *client = data;
        drm_file_t   *pt;
        int          idx;
        int          i = 0;
 
-       DRM_COPY_FROM_USER_IOCTL( client, (drm_client_t *)data, sizeof(client) );
-
-       idx = client.idx;
+       idx = client->idx;
        DRM_LOCK();
        TAILQ_FOREACH(pt, &dev->files, link) {
                if (i==idx)
                {
-                       client.auth  = pt->authenticated;
-                       client.pid   = pt->pid;
-                       client.uid   = pt->uid;
-                       client.magic = pt->magic;
-                       client.iocs  = pt->ioctl_count;
+                       client->auth  = pt->authenticated;
+                       client->pid   = pt->pid;
+                       client->uid   = pt->uid;
+                       client->magic = pt->magic;
+                       client->iocs  = pt->ioctl_count;
                        DRM_UNLOCK();
-
-                       *(drm_client_t *)data = client;
                        return 0;
                }
                i++;
        }
        DRM_UNLOCK();
 
-       DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) );
-
-       return 0;
+       return EINVAL;
 }
 
-int drm_getstats(DRM_IOCTL_ARGS)
+int drm_getstats(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_stats_t  stats;
+       drm_stats_t  *stats = data;
        int          i;
 
-       memset(&stats, 0, sizeof(stats));
+       memset(stats, 0, sizeof(drm_stats_t));
        
        DRM_LOCK();
 
        for (i = 0; i < dev->counters; i++) {
                if (dev->types[i] == _DRM_STAT_LOCK)
-                       stats.data[i].value
+                       stats->data[i].value
                                = (dev->lock.hw_lock
                                   ? dev->lock.hw_lock->lock : 0);
                else 
-                       stats.data[i].value = atomic_read(&dev->counts[i]);
-               stats.data[i].type  = dev->types[i];
+                       stats->data[i].value = atomic_read(&dev->counts[i]);
+               stats->data[i].type  = dev->types[i];
        }
        
-       stats.count = dev->counters;
+       stats->count = dev->counters;
 
        DRM_UNLOCK();
 
-       DRM_COPY_TO_USER_IOCTL( (drm_stats_t *)data, stats, sizeof(stats) );
-
        return 0;
 }
 
 #define DRM_IF_MAJOR   1
 #define DRM_IF_MINOR   2
 
-int drm_setversion(DRM_IOCTL_ARGS)
+int drm_setversion(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_set_version_t sv;
-       drm_set_version_t retv;
+       drm_set_version_t *sv = data;
+       drm_set_version_t ver;
        int if_version;
 
-       DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv));
-
-       retv.drm_di_major = DRM_IF_MAJOR;
-       retv.drm_di_minor = DRM_IF_MINOR;
-       retv.drm_dd_major = dev->driver.major;
-       retv.drm_dd_minor = dev->driver.minor;
-
-       DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv));
-
-       if (sv.drm_di_major != -1) {
-               if (sv.drm_di_major != DRM_IF_MAJOR ||
-                   sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
+       /* Save the incoming data, and set the response before continuing
+        * any further.
+        */
+       ver = *sv;
+       sv->drm_di_major = DRM_IF_MAJOR;
+       sv->drm_di_minor = DRM_IF_MINOR;
+       sv->drm_dd_major = dev->driver.major;
+       sv->drm_dd_minor = dev->driver.minor;
+
+       if (ver.drm_di_major != -1) {
+               if (ver.drm_di_major != DRM_IF_MAJOR ||
+                   ver.drm_di_minor < 0 || ver.drm_di_minor > DRM_IF_MINOR) {
                        return EINVAL;
-               if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
+               }
+               if_version = DRM_IF_VERSION(ver.drm_di_major,
+                   ver.drm_dd_minor);
                dev->if_version = DRM_MAX(if_version, dev->if_version);
-               if (sv.drm_di_minor >= 1) {
+               if (ver.drm_di_minor >= 1) {
                        /*
                         * Version 1.1 includes tying of DRM to specific device
                         */
@@ -280,16 +260,20 @@ int drm_setversion(DRM_IOCTL_ARGS)
                }
        }
 
-       if (sv.drm_dd_major != -1) {
-               if (sv.drm_dd_major != dev->driver.major ||
-                   sv.drm_dd_minor < 0 || sv.drm_dd_minor > dev->driver.minor)
+       if (ver.drm_dd_major != -1) {
+               if (ver.drm_dd_major != dev->driver.major ||
+                   ver.drm_dd_minor < 0 ||
+                   ver.drm_dd_minor > dev->driver.minor)
+               {
                        return EINVAL;
+               }
        }
+
        return 0;
 }
 
 
-int drm_noop(DRM_IOCTL_ARGS)
+int drm_noop(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
        DRM_DEBUG("\n");
        return 0;
index f7da5ed..0772445 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_irq.c -- IRQ IOCTL and function support
- * Created: Fri Oct 18 2003 by anholt@FreeBSD.org
- */
 /*-
  * Copyright 2003 Eric Anholt
  * All Rights Reserved.
  *
  */
 
+/** @file drm_irq.c
+ * Support code for handling setup/teardown of interrupt handlers and
+ * handing interrupt handlers off to the drivers.
+ */
+
 #include "drmP.h"
 #include "drm.h"
 
-int drm_irq_by_busid(DRM_IOCTL_ARGS)
-{
-       DRM_DEVICE;
-       drm_irq_busid_t irq;
+static void drm_locked_task(void *context, int pending __unused);
 
-       DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq));
+int drm_irq_by_busid(drm_device_t *dev, void *data, struct drm_file *file_priv)
+{
+       drm_irq_busid_t *irq = data;
 
-       if ((irq.busnum >> 8) != dev->pci_domain ||
-           (irq.busnum & 0xff) != dev->pci_bus ||
-           irq.devnum != dev->pci_slot ||
-           irq.funcnum != dev->pci_func)
+       if ((irq->busnum >> 8) != dev->pci_domain ||
+           (irq->busnum & 0xff) != dev->pci_bus ||
+           irq->devnum != dev->pci_slot ||
+           irq->funcnum != dev->pci_func)
                return EINVAL;
 
-       irq.irq = dev->irq;
+       irq->irq = dev->irq;
 
        DRM_DEBUG("%d:%d:%d => IRQ %d\n",
-                 irq.busnum, irq.devnum, irq.funcnum, irq.irq);
-
-       DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) );
+                 irq->busnum, irq->devnum, irq->funcnum, irq->irq);
 
        return 0;
 }
@@ -74,20 +73,20 @@ int drm_irq_install(drm_device_t *dev)
 #endif
 
        if (dev->irq == 0 || dev->dev_private == NULL)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
 
        DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
 
        DRM_LOCK();
        if (dev->irq_enabled) {
                DRM_UNLOCK();
-               return DRM_ERR(EBUSY);
+               return EBUSY;
        }
        dev->irq_enabled = 1;
 
        dev->context_flag = 0;
 
-       DRM_SPININIT(dev->irq_lock, "DRM IRQ lock");
+       DRM_SPININIT(&dev->irq_lock, "DRM IRQ lock");
 
                                /* Before installing handler */
        dev->driver.irq_preinstall(dev);
@@ -131,6 +130,7 @@ int drm_irq_install(drm_device_t *dev)
        dev->driver.irq_postinstall(dev);
        DRM_UNLOCK();
 
+       TASK_INIT(&dev->locked_task, 0, drm_locked_task, dev);
        return 0;
 err:
        DRM_LOCK();
@@ -142,7 +142,7 @@ err:
                dev->irqrid = 0;
        }
 #endif
-       DRM_SPINUNINIT(dev->irq_lock);
+       DRM_SPINUNINIT(&dev->irq_lock);
        DRM_UNLOCK();
        return retcode;
 }
@@ -154,7 +154,7 @@ int drm_irq_uninstall(drm_device_t *dev)
 #endif
 
        if (!dev->irq_enabled)
-               return DRM_ERR(EINVAL);
+               return EINVAL;
 
        dev->irq_enabled = 0;
 #ifdef __FreeBSD__
@@ -174,20 +174,17 @@ int drm_irq_uninstall(drm_device_t *dev)
 #elif defined(__NetBSD__) || defined(__OpenBSD__)
        pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
 #endif
-       DRM_SPINUNINIT(dev->irq_lock);
+       DRM_SPINUNINIT(&dev->irq_lock);
 
        return 0;
 }
 
-int drm_control(DRM_IOCTL_ARGS)
+int drm_control(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_control_t ctl;
+       drm_control_t *ctl = data;
        int err;
 
-       DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) );
-
-       switch ( ctl.func ) {
+       switch ( ctl->func ) {
        case DRM_INST_HANDLER:
                /* Handle drivers whose DRM used to require IRQ setup but the
                 * no longer does.
@@ -195,8 +192,8 @@ int drm_control(DRM_IOCTL_ARGS)
                if (!dev->driver.use_irq)
                        return 0;
                if (dev->if_version < DRM_IF_VERSION(1, 2) &&
-                   ctl.irq != dev->irq)
-                       return DRM_ERR(EINVAL);
+                   ctl->irq != dev->irq)
+                       return EINVAL;
                return drm_irq_install(dev);
        case DRM_UNINST_HANDLER:
                if (!dev->driver.use_irq)
@@ -206,29 +203,25 @@ int drm_control(DRM_IOCTL_ARGS)
                DRM_UNLOCK();
                return err;
        default:
-               return DRM_ERR(EINVAL);
+               return EINVAL;
        }
 }
 
-int drm_wait_vblank(DRM_IOCTL_ARGS)
+int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_wait_vblank_t vblwait;
+       drm_wait_vblank_t *vblwait = data;
        struct timeval now;
-       int ret;
+       int ret, flags;
 
        if (!dev->irq_enabled)
-               return DRM_ERR(EINVAL);
-
-       DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
-                                 sizeof(vblwait) );
+               return EINVAL;
 
-       if (vblwait.request.type & _DRM_VBLANK_RELATIVE) {
-               vblwait.request.sequence += atomic_read(&dev->vbl_received);
-               vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+       if (vblwait->request.type & _DRM_VBLANK_RELATIVE) {
+               vblwait->request.sequence += atomic_read(&dev->vbl_received);
+               vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
        }
 
-       flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+       flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
        if (flags & _DRM_VBLANK_SIGNAL) {
 #if 0 /* disabled */
                drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM,
@@ -236,11 +229,11 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
                if (vbl_sig == NULL)
                        return ENOMEM;
 
-               vbl_sig->sequence = vblwait.request.sequence;
-               vbl_sig->signo = vblwait.request.signal;
+               vbl_sig->sequence = vblwait->request.sequence;
+               vbl_sig->signo = vblwait->request.signal;
                vbl_sig->pid = DRM_CURRENTPID;
 
-               vblwait.reply.sequence = atomic_read(&dev->vbl_received);
+               vblwait->reply.sequence = atomic_read(&dev->vbl_received);
                
                DRM_SPINLOCK(&dev->irq_lock);
                TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
@@ -250,17 +243,16 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
                ret = EINVAL;
        } else {
                DRM_LOCK();
-               ret = dev->driver.vblank_wait(dev, &vblwait.request.sequence);
+               /* shared code returns -errno */
+               ret = -dev->driver.vblank_wait(dev,
+                   &vblwait->request.sequence);
                DRM_UNLOCK();
 
                microtime(&now);
-               vblwait.reply.tval_sec = now.tv_sec;
-               vblwait.reply.tval_usec = now.tv_usec;
+               vblwait->reply.tval_sec = now.tv_sec;
+               vblwait->reply.tval_usec = now.tv_usec;
        }
 
-       DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
-                               sizeof(vblwait) );
-
        return ret;
 }
 
@@ -291,3 +283,45 @@ void drm_vbl_send_signals( drm_device_t *dev )
        }
 }
 #endif
+
+static void drm_locked_task(void *context, int pending __unused)
+{
+       drm_device_t *dev = context;
+
+       DRM_LOCK();
+       for (;;) {
+               int ret;
+
+               if (drm_lock_take(&dev->lock.hw_lock->lock,
+                   DRM_KERNEL_CONTEXT))
+               {
+                       dev->lock.file_priv = NULL; /* kernel owned */
+                       dev->lock.lock_time = jiffies;
+                       atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+                       break;  /* Got lock */
+               }
+
+               /* Contention */
+#if defined(__FreeBSD__) && __FreeBSD_version > 500000
+               ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
+                   PZERO | PCATCH, "drmlk2", 0);
+#else
+               ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
+                   "drmlk2", 0);
+#endif
+               if (ret != 0)
+                       return;
+       }
+       DRM_UNLOCK();
+
+       dev->locked_task_call(dev);
+
+       drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
+}
+
+void
+drm_locked_tasklet(drm_device_t *dev, void (*tasklet)(drm_device_t *dev))
+{
+       dev->locked_task_call = tasklet;
+       taskqueue_enqueue(taskqueue_swi, &dev->locked_task);
+}
index d0e61d3..fb86fc6 100644 (file)
@@ -1,6 +1,3 @@
-/* lock.c -- IOCTLs for locking -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
- */
 /*-
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_lock.c
+ * Implementation of the ioctls and other support code for dealing with the
+ * hardware lock.
+ *
+ * The DRM hardware lock is a shared structure between the kernel and userland.
+ *
+ * On uncontended access where the new context was the last context, the
+ * client may take the lock without dropping down into the kernel, using atomic
+ * compare-and-set.
+ *
+ * If the client finds during compare-and-set that it was not the last owner
+ * of the lock, it calls the DRM lock ioctl, which may sleep waiting for the
+ * lock, and may have side-effects of kernel-managed context switching.
+ *
+ * When the client releases the lock, if the lock is marked as being contended
+ * by another client, then the DRM unlock ioctl is called so that the
+ * contending client may be woken up.
+ */
+
 #include "drmP.h"
 
 int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
@@ -66,7 +82,7 @@ int drm_lock_transfer(drm_device_t *dev,
 {
        unsigned int old, new;
 
-       dev->lock.filp = NULL;
+       dev->lock.file_priv = NULL;
        do {
                old  = *lock;
                new  = context | _DRM_LOCK_HELD;
@@ -80,7 +96,7 @@ int drm_lock_free(drm_device_t *dev,
 {
        unsigned int old, new;
 
-       dev->lock.filp = NULL;
+       dev->lock.file_priv = NULL;
        do {
                old  = *lock;
                new  = 0;
@@ -95,30 +111,28 @@ int drm_lock_free(drm_device_t *dev,
        return 0;
 }
 
-int drm_lock(DRM_IOCTL_ARGS)
+int drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-        drm_lock_t lock;
+        drm_lock_t *lock = data;
         int ret = 0;
 
-       DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
-
-        if (lock.context == DRM_KERNEL_CONTEXT) {
+        if (lock->context == DRM_KERNEL_CONTEXT) {
                 DRM_ERROR("Process %d using kernel context %d\n",
-                   DRM_CURRENTPID, lock.context);
+                   DRM_CURRENTPID, lock->context);
                 return EINVAL;
         }
 
         DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-           lock.context, DRM_CURRENTPID, dev->lock.hw_lock->lock, lock.flags);
+           lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
+           lock->flags);
 
-        if (dev->driver.use_dma_queue && lock.context < 0)
+        if (dev->driver.use_dma_queue && lock->context < 0)
                 return EINVAL;
 
        DRM_LOCK();
        for (;;) {
-               if (drm_lock_take(&dev->lock.hw_lock->lock, lock.context)) {
-                       dev->lock.filp = (void *)(uintptr_t)DRM_CURRENTPID;
+               if (drm_lock_take(&dev->lock.hw_lock->lock, lock->context)) {
+                       dev->lock.file_priv = file_priv;
                        dev->lock.lock_time = jiffies;
                        atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
                        break;  /* Got lock */
@@ -136,7 +150,7 @@ int drm_lock(DRM_IOCTL_ARGS)
                        break;
        }
        DRM_UNLOCK();
-       DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+       DRM_DEBUG("%d %s\n", lock->context, ret ? "interrupted" : "has lock");
 
        if (ret != 0)
                return ret;
@@ -144,24 +158,27 @@ int drm_lock(DRM_IOCTL_ARGS)
        /* XXX: Add signal blocking here */
 
        if (dev->driver.dma_quiescent != NULL &&
-           (lock.flags & _DRM_LOCK_QUIESCENT))
+           (lock->flags & _DRM_LOCK_QUIESCENT))
                dev->driver.dma_quiescent(dev);
 
        return 0;
 }
 
-int drm_unlock(DRM_IOCTL_ARGS)
+int drm_unlock(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_lock_t lock;
+       drm_lock_t *lock = data;
 
-       DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t *)data, sizeof(lock));
-
-       if (lock.context == DRM_KERNEL_CONTEXT) {
+       if (lock->context == DRM_KERNEL_CONTEXT) {
                DRM_ERROR("Process %d using kernel context %d\n",
-                   DRM_CURRENTPID, lock.context);
+                   DRM_CURRENTPID, lock->context);
                return EINVAL;
        }
+       /* Check that the context unlock being requested actually matches
+        * who currently holds the lock.
+        */
+       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
+           _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) != lock->context)
+               return EINVAL;
 
        atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
 
index 6d467e9..1f1f7f4 100644 (file)
@@ -1,6 +1,3 @@
-/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
- * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
- */
 /*-
  *Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  *
  */
 
+/** @file drm_memory.c
+ * Wrappers for kernel memory allocation routines, and MTRR management support.
+ *
+ * This file previously implemented a memory consumption tracking system using
+ * the "area" argument for various different types of allocations, but that
+ * has been stripped out for now.
+ */
+
 #include "drmP.h"
 
 MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures");
index a33f5f9..6ec6b98 100644 (file)
@@ -1,10 +1,3 @@
-/**
- * \file drm_pci.h
- * \brief PCI consistent, DMA-accessible memory functions.
- *
- * \author Eric Anholt <anholt@FreeBSD.org>
- */
-
 /*-
  * Copyright 2003 Eric Anholt.
  * All Rights Reserved.
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+/**
+ * \file drm_pci.h
+ * \brief PCI consistent, DMA-accessible memory allocation.
+ *
+ * \author Eric Anholt <anholt@FreeBSD.org>
+ */
+
 #include "drmP.h"
 
 /**********************************************************************/
diff --git a/bsd-core/drm_sarea.h b/bsd-core/drm_sarea.h
new file mode 120000 (symlink)
index 0000000..fd428f4
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/drm_sarea.h
\ No newline at end of file
index 9dc280a..92e715e 100644 (file)
@@ -1,5 +1,3 @@
-/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
- * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com */
 /*-
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
  */
 
+/** @file drm_scatter.c
+ * Allocation of memory for scatter-gather mappings by the graphics chip.
+ *
+ * The memory allocated here is then made into an aperture in the card
+ * by drm_ati_pcigart_init().
+ */
+
 #include "drmP.h"
 
 #define DEBUG_SCATTER 0
@@ -40,28 +45,21 @@ void drm_sg_cleanup(drm_sg_mem_t *entry)
        free(entry, M_DRM);
 }
 
-int drm_sg_alloc(DRM_IOCTL_ARGS)
+int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)
 {
-       DRM_DEVICE;
-       drm_scatter_gather_t request;
        drm_sg_mem_t *entry;
        unsigned long pages;
        int i;
 
-       DRM_DEBUG( "%s\n", __FUNCTION__ );
-
        if ( dev->sg )
                return EINVAL;
 
-       DRM_COPY_FROM_USER_IOCTL(request, (drm_scatter_gather_t *)data,
-                            sizeof(request) );
-
        entry = malloc(sizeof(*entry), M_DRM, M_WAITOK | M_ZERO);
        if ( !entry )
                return ENOMEM;
 
-       pages = round_page(request.size) / PAGE_SIZE;
-       DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
+       pages = round_page(request->size) / PAGE_SIZE;
+       DRM_DEBUG( "sg size=%ld pages=%ld\n", request->size, pages );
 
        entry->pages = pages;
 
@@ -86,11 +84,7 @@ int drm_sg_alloc(DRM_IOCTL_ARGS)
        DRM_DEBUG( "sg alloc handle  = %08lx\n", entry->handle );
 
        entry->virtual = (void *)entry->handle;
-       request.handle = entry->handle;
-
-       DRM_COPY_TO_USER_IOCTL( (drm_scatter_gather_t *)data,
-                          request,
-                          sizeof(request) );
+       request->handle = entry->handle;
 
        DRM_LOCK();
        if (dev->sg) {
@@ -104,21 +98,28 @@ int drm_sg_alloc(DRM_IOCTL_ARGS)
        return 0;
 }
 
-int drm_sg_free(DRM_IOCTL_ARGS)
+int drm_sg_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_scatter_gather_t request;
-       drm_sg_mem_t *entry;
+       drm_scatter_gather_t *request = data;
+       int ret;
+
+       DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-       DRM_COPY_FROM_USER_IOCTL( request, (drm_scatter_gather_t *)data,
-                            sizeof(request) );
+       ret = drm_sg_alloc(dev, request);
+       return ret;
+}
+
+int drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv)
+{
+       drm_scatter_gather_t *request = data;
+       drm_sg_mem_t *entry;
 
        DRM_LOCK();
        entry = dev->sg;
        dev->sg = NULL;
        DRM_UNLOCK();
 
-       if ( !entry || entry->handle != request.handle )
+       if ( !entry || entry->handle != request->handle )
                return EINVAL;
 
        DRM_DEBUG( "sg free virtual  = 0x%lx\n", entry->handle );
index b2d0cc0..3de5b8a 100644 (file)
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+/** @file drm_sysctl.c
+ * Implementation of various sysctls for controlling DRM behavior and reporting
+ * debug information.
+ */
+
 #include "drmP.h"
 #include "drm.h"
 
index 7f732c9..fea31f5 100644 (file)
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+/** @file drm_vm.c
+ * Support code for mmaping of DRM maps.
+ */
+
 #include "drmP.h"
 #include "drm.h"
 
@@ -33,7 +37,7 @@ int drm_mmap(dev_t kdev, vm_offset_t offset, int prot)
 paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
 #endif
 {
-       DRM_DEVICE;
+       drm_device_t *dev = drm_get_device_from_kdev(kdev);
        drm_local_map_t *map;
        drm_file_t *priv;
        drm_map_type_t type;
@@ -52,7 +56,7 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
        }
 
        if (!priv->authenticated)
-               return DRM_ERR(EACCES);
+               return EACCES;
 
        if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) {
                drm_device_dma_t *dma = dev->dma;
diff --git a/bsd-core/i915_dma.c b/bsd-core/i915_dma.c
new file mode 120000 (symlink)
index 0000000..c61d967
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/i915_dma.c
\ No newline at end of file
diff --git a/bsd-core/i915_drm.h b/bsd-core/i915_drm.h
new file mode 120000 (symlink)
index 0000000..ed53f01
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/i915_drm.h
\ No newline at end of file
diff --git a/bsd-core/i915_drv.h b/bsd-core/i915_drv.h
new file mode 120000 (symlink)
index 0000000..085558c
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/i915_drv.h
\ No newline at end of file
diff --git a/bsd-core/i915_irq.c b/bsd-core/i915_irq.c
new file mode 120000 (symlink)
index 0000000..2058a2e
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/i915_irq.c
\ No newline at end of file
diff --git a/bsd-core/i915_mem.c b/bsd-core/i915_mem.c
new file mode 120000 (symlink)
index 0000000..e8e5655
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/i915_mem.c
\ No newline at end of file
diff --git a/bsd-core/mach64_dma.c b/bsd-core/mach64_dma.c
new file mode 120000 (symlink)
index 0000000..e5c2897
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mach64_dma.c
\ No newline at end of file
diff --git a/bsd-core/mach64_drm.h b/bsd-core/mach64_drm.h
new file mode 120000 (symlink)
index 0000000..136ea93
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mach64_drm.h
\ No newline at end of file
diff --git a/bsd-core/mach64_drv.h b/bsd-core/mach64_drv.h
new file mode 120000 (symlink)
index 0000000..85222cc
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mach64_drv.h
\ No newline at end of file
diff --git a/bsd-core/mach64_irq.c b/bsd-core/mach64_irq.c
new file mode 120000 (symlink)
index 0000000..a1235d5
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mach64_irq.c
\ No newline at end of file
diff --git a/bsd-core/mach64_state.c b/bsd-core/mach64_state.c
new file mode 120000 (symlink)
index 0000000..b11f202
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mach64_state.c
\ No newline at end of file
diff --git a/bsd-core/mga_dma.c b/bsd-core/mga_dma.c
new file mode 120000 (symlink)
index 0000000..f290be9
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mga_dma.c
\ No newline at end of file
diff --git a/bsd-core/mga_drm.h b/bsd-core/mga_drm.h
new file mode 120000 (symlink)
index 0000000..1c87036
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mga_drm.h
\ No newline at end of file
diff --git a/bsd-core/mga_drv.h b/bsd-core/mga_drv.h
new file mode 120000 (symlink)
index 0000000..cb0c9e1
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mga_drv.h
\ No newline at end of file
diff --git a/bsd-core/mga_irq.c b/bsd-core/mga_irq.c
new file mode 120000 (symlink)
index 0000000..cf521d2
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mga_irq.c
\ No newline at end of file
diff --git a/bsd-core/mga_state.c b/bsd-core/mga_state.c
new file mode 120000 (symlink)
index 0000000..8bda8ba
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mga_state.c
\ No newline at end of file
diff --git a/bsd-core/mga_ucode.h b/bsd-core/mga_ucode.h
new file mode 120000 (symlink)
index 0000000..728b9ac
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mga_ucode.h
\ No newline at end of file
diff --git a/bsd-core/mga_warp.c b/bsd-core/mga_warp.c
new file mode 120000 (symlink)
index 0000000..d35b325
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/mga_warp.c
\ No newline at end of file
diff --git a/bsd-core/r128_cce.c b/bsd-core/r128_cce.c
new file mode 120000 (symlink)
index 0000000..0c1d659
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/r128_cce.c
\ No newline at end of file
diff --git a/bsd-core/r128_drm.h b/bsd-core/r128_drm.h
new file mode 120000 (symlink)
index 0000000..363852c
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/r128_drm.h
\ No newline at end of file
diff --git a/bsd-core/r128_drv.h b/bsd-core/r128_drv.h
new file mode 120000 (symlink)
index 0000000..4f7e822
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/r128_drv.h
\ No newline at end of file
diff --git a/bsd-core/r128_irq.c b/bsd-core/r128_irq.c
new file mode 120000 (symlink)
index 0000000..66d28b0
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/r128_irq.c
\ No newline at end of file
diff --git a/bsd-core/r128_state.c b/bsd-core/r128_state.c
new file mode 120000 (symlink)
index 0000000..e83d84b
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/r128_state.c
\ No newline at end of file
diff --git a/bsd-core/r300_cmdbuf.c b/bsd-core/r300_cmdbuf.c
new file mode 120000 (symlink)
index 0000000..6674d05
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/r300_cmdbuf.c
\ No newline at end of file
diff --git a/bsd-core/r300_reg.h b/bsd-core/r300_reg.h
new file mode 120000 (symlink)
index 0000000..ef54eba
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/r300_reg.h
\ No newline at end of file
diff --git a/bsd-core/radeon_cp.c b/bsd-core/radeon_cp.c
new file mode 120000 (symlink)
index 0000000..ee86094
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/radeon_cp.c
\ No newline at end of file
diff --git a/bsd-core/radeon_drm.h b/bsd-core/radeon_drm.h
new file mode 120000 (symlink)
index 0000000..54f595a
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/radeon_drm.h
\ No newline at end of file
diff --git a/bsd-core/radeon_drv.h b/bsd-core/radeon_drv.h
new file mode 120000 (symlink)
index 0000000..5b415ea
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/radeon_drv.h
\ No newline at end of file
diff --git a/bsd-core/radeon_irq.c b/bsd-core/radeon_irq.c
new file mode 120000 (symlink)
index 0000000..2f394a5
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/radeon_irq.c
\ No newline at end of file
diff --git a/bsd-core/radeon_mem.c b/bsd-core/radeon_mem.c
new file mode 120000 (symlink)
index 0000000..8cc2798
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/radeon_mem.c
\ No newline at end of file
diff --git a/bsd-core/radeon_state.c b/bsd-core/radeon_state.c
new file mode 120000 (symlink)
index 0000000..ccee876
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/radeon_state.c
\ No newline at end of file
diff --git a/bsd-core/savage_bci.c b/bsd-core/savage_bci.c
new file mode 120000 (symlink)
index 0000000..b843671
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/savage_bci.c
\ No newline at end of file
diff --git a/bsd-core/savage_drm.h b/bsd-core/savage_drm.h
new file mode 120000 (symlink)
index 0000000..0dab2e3
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/savage_drm.h
\ No newline at end of file
diff --git a/bsd-core/savage_drv.h b/bsd-core/savage_drv.h
new file mode 120000 (symlink)
index 0000000..8397009
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/savage_drv.h
\ No newline at end of file
diff --git a/bsd-core/savage_state.c b/bsd-core/savage_state.c
new file mode 120000 (symlink)
index 0000000..e55dc5d
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/savage_state.c
\ No newline at end of file
diff --git a/bsd-core/sis_drm.h b/bsd-core/sis_drm.h
new file mode 120000 (symlink)
index 0000000..36c77aa
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/sis_drm.h
\ No newline at end of file
diff --git a/bsd-core/sis_drv.h b/bsd-core/sis_drv.h
new file mode 120000 (symlink)
index 0000000..3fddfda
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/sis_drv.h
\ No newline at end of file
diff --git a/bsd-core/sis_ds.c b/bsd-core/sis_ds.c
new file mode 120000 (symlink)
index 0000000..242310a
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/sis_ds.c
\ No newline at end of file
diff --git a/bsd-core/sis_ds.h b/bsd-core/sis_ds.h
new file mode 120000 (symlink)
index 0000000..8cbdaf3
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/sis_ds.h
\ No newline at end of file
diff --git a/bsd-core/sis_mm.c b/bsd-core/sis_mm.c
new file mode 120000 (symlink)
index 0000000..8f802ec
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/sis_mm.c
\ No newline at end of file
diff --git a/bsd-core/tdfx_drv.h b/bsd-core/tdfx_drv.h
new file mode 120000 (symlink)
index 0000000..8df7032
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/tdfx_drv.h
\ No newline at end of file
diff --git a/bsd-core/via_3d_reg.h b/bsd-core/via_3d_reg.h
new file mode 120000 (symlink)
index 0000000..90d238e
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_3d_reg.h
\ No newline at end of file
diff --git a/bsd-core/via_dma.c b/bsd-core/via_dma.c
new file mode 120000 (symlink)
index 0000000..1f4d920
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_dma.c
\ No newline at end of file
diff --git a/bsd-core/via_drm.h b/bsd-core/via_drm.h
new file mode 120000 (symlink)
index 0000000..7cd175d
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_drm.h
\ No newline at end of file
diff --git a/bsd-core/via_drv.h b/bsd-core/via_drv.h
new file mode 120000 (symlink)
index 0000000..8954fe8
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_drv.h
\ No newline at end of file
diff --git a/bsd-core/via_ds.c b/bsd-core/via_ds.c
new file mode 120000 (symlink)
index 0000000..b0fbb69
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_ds.c
\ No newline at end of file
diff --git a/bsd-core/via_ds.h b/bsd-core/via_ds.h
new file mode 120000 (symlink)
index 0000000..dc8f2f4
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_ds.h
\ No newline at end of file
diff --git a/bsd-core/via_irq.c b/bsd-core/via_irq.c
new file mode 120000 (symlink)
index 0000000..f615af8
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_irq.c
\ No newline at end of file
diff --git a/bsd-core/via_map.c b/bsd-core/via_map.c
new file mode 120000 (symlink)
index 0000000..b505663
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_map.c
\ No newline at end of file
diff --git a/bsd-core/via_mm.c b/bsd-core/via_mm.c
new file mode 120000 (symlink)
index 0000000..f9ec0f3
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_mm.c
\ No newline at end of file
diff --git a/bsd-core/via_mm.h b/bsd-core/via_mm.h
new file mode 120000 (symlink)
index 0000000..fe2234f
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_mm.h
\ No newline at end of file
diff --git a/bsd-core/via_verifier.c b/bsd-core/via_verifier.c
new file mode 120000 (symlink)
index 0000000..00b411b
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_verifier.c
\ No newline at end of file
diff --git a/bsd-core/via_verifier.h b/bsd-core/via_verifier.h
new file mode 120000 (symlink)
index 0000000..62d3e28
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_verifier.h
\ No newline at end of file
diff --git a/bsd-core/via_video.c b/bsd-core/via_video.c
new file mode 120000 (symlink)
index 0000000..a6d2794
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/via_video.c
\ No newline at end of file
index 94c47bd..7820334 100644 (file)
@@ -35,4 +35,9 @@ AC_SYS_LARGEFILE
 pkgconfigdir=${libdir}/pkgconfig
 AC_SUBST(pkgconfigdir)
 
-AC_OUTPUT([Makefile libdrm/Makefile shared-core/Makefile libdrm.pc])
+AC_OUTPUT([
+       Makefile
+       libdrm/Makefile
+       shared-core/Makefile
+       tests/Makefile
+       libdrm.pc])
index e7e07e4..24c3203 100644 (file)
@@ -23,9 +23,9 @@ libdrm_ladir = $(libdir)
 libdrm_la_LDFLAGS = -version-number 2:3:0 -no-undefined
 
 AM_CFLAGS = -I$(top_srcdir)/shared-core
-libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c
+libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c xf86drmMode.c
 
 libdrmincludedir = ${includedir}
-libdrminclude_HEADERS = xf86drm.h xf86mm.h
+libdrminclude_HEADERS = xf86drm.h xf86mm.h xf86drmMode.h
 
 EXTRA_DIST = ChangeLog TODO
index 1f242fe..7001a0e 100644 (file)
@@ -49,7 +49,6 @@
 #include <sys/mman.h>
 #include <sys/time.h>
 #include <stdarg.h>
-#include "drm.h"
 
 /* Not all systems have MAP_FAILED defined */
 #ifndef MAP_FAILED
@@ -2346,7 +2345,7 @@ int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data,
  * DRM_FENCE_MASK_DRIVER
  */
 
-int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
+int drmFenceCreate(int fd, unsigned flags, int fence_class, unsigned type,
                   drmFence *fence)
 {
     drm_fence_arg_t arg;
@@ -2354,12 +2353,12 @@ int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
     memset(&arg, 0, sizeof(arg));
     arg.flags = flags;
     arg.type = type;
-    arg.class = class;
-    arg.op = drm_fence_create;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+    arg.fence_class = fence_class;
+
+    if (ioctl(fd, DRM_IOCTL_FENCE_CREATE, &arg))
        return -errno;
     fence->handle = arg.handle;
-    fence->class = arg.class;
+    fence->fence_class = arg.fence_class;
     fence->type = arg.type;
     fence->flags = arg.flags;
     fence->signaled = 0;
@@ -2372,34 +2371,24 @@ int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
  * DRM_FENCE_MASK_DRIVER
  */
 
-int drmFenceBuffers(int fd, unsigned flags, drmFence *fence)
+int drmFenceBuffers(int fd, unsigned flags, uint32_t fence_class, drmFence *fence)
 {
     drm_fence_arg_t arg;
 
     memset(&arg, 0, sizeof(arg));
     arg.flags = flags;
-    arg.op = drm_fence_buffers;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+    arg.fence_class = fence_class;
+
+    if (ioctl(fd, DRM_IOCTL_FENCE_BUFFERS, &arg))
        return -errno;
     fence->handle = arg.handle;
-    fence->class = arg.class;
+    fence->fence_class = arg.fence_class;
     fence->type = arg.type;
     fence->flags = arg.flags;
+    fence->sequence = arg.sequence;
     fence->signaled = 0;
     return 0;
 }
-    
-int drmFenceDestroy(int fd, const drmFence *fence)
-{
-    drm_fence_arg_t arg;
-
-    memset(&arg, 0, sizeof(arg));
-    arg.handle = fence->handle;
-    arg.op = drm_fence_destroy;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
-       return -errno;
-    return 0;
-}
 
 int drmFenceReference(int fd, unsigned handle, drmFence *fence)
 {
@@ -2407,11 +2396,11 @@ int drmFenceReference(int fd, unsigned handle, drmFence *fence)
 
     memset(&arg, 0, sizeof(arg));
     arg.handle = handle;
-    arg.op = drm_fence_reference;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+
+    if (ioctl(fd, DRM_IOCTL_FENCE_REFERENCE, &arg))
        return -errno;
     fence->handle = arg.handle;
-    fence->class = arg.class;
+    fence->fence_class = arg.fence_class;
     fence->type = arg.type;
     fence->flags = arg.flags;
     fence->signaled = arg.signaled;
@@ -2424,8 +2413,8 @@ int drmFenceUnreference(int fd, const drmFence *fence)
 
     memset(&arg, 0, sizeof(arg));
     arg.handle = fence->handle;
-    arg.op = drm_fence_unreference;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+
+    if (ioctl(fd, DRM_IOCTL_FENCE_UNREFERENCE, &arg))
        return -errno;
     return 0;
 }
@@ -2437,10 +2426,10 @@ int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type)
     memset(&arg, 0, sizeof(arg));
     arg.handle = fence->handle;
     arg.type = flush_type;
-    arg.op = drm_fence_flush;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+
+    if (ioctl(fd, DRM_IOCTL_FENCE_FLUSH, &arg))
        return -errno;
-    fence->class = arg.class;
+    fence->fence_class = arg.fence_class;
     fence->type = arg.type;
     fence->signaled = arg.signaled;
     return 0;
@@ -2452,10 +2441,10 @@ int drmFenceUpdate(int fd, drmFence *fence)
 
     memset(&arg, 0, sizeof(arg));
     arg.handle = fence->handle;
-    arg.op = drm_fence_signaled;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+
+    if (ioctl(fd, DRM_IOCTL_FENCE_SIGNALED, &arg))
        return -errno;
-    fence->class = arg.class;
+    fence->fence_class = arg.fence_class;
     fence->type = arg.type;
     fence->signaled = arg.signaled;
     return 0;
@@ -2488,14 +2477,14 @@ int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type)
     drm_fence_arg_t arg;
 
     memset(&arg, 0, sizeof(arg));
-    arg.class = fence->class;
+    arg.fence_class = fence->fence_class;
     arg.flags = flags;
     arg.handle = fence->handle;
     arg.type = emit_type;
-    arg.op = drm_fence_emit;
-    if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+
+    if (ioctl(fd, DRM_IOCTL_FENCE_EMIT, &arg))
        return -errno;
-    fence->class = arg.class;
+    fence->fence_class = arg.fence_class;
     fence->type = arg.type;
     fence->signaled = arg.signaled;
     return 0;
@@ -2526,159 +2515,21 @@ int drmFenceWait(int fd, unsigned flags, drmFence *fence, unsigned flush_type)
     arg.handle = fence->handle;
     arg.type = flush_type;
     arg.flags = flags;
-    arg.op = drm_fence_wait;
+
     do {
-       ret = ioctl(fd, DRM_IOCTL_FENCE, &arg);
+       ret = ioctl(fd, DRM_IOCTL_FENCE_WAIT, &arg);
     } while (ret != 0 && errno == EAGAIN);
 
     if (ret)
        return -errno;
 
-    fence->class = arg.class;
+    fence->fence_class = arg.fence_class;
     fence->type = arg.type;
     fence->signaled = arg.signaled;
     return 0;
 }    
 
-static int drmAdjustListNodes(drmBOList *list)
-{
-    drmBONode *node;
-    drmMMListHead *l;
-    int ret = 0;
-
-    while(list->numCurrent < list->numTarget) {
-       node = (drmBONode *) malloc(sizeof(*node));
-       if (!node) {
-           ret = -ENOMEM;
-           break;
-       }
-       list->numCurrent++;
-       DRMLISTADD(&node->head, &list->free);
-    }
-
-    while(list->numCurrent > list->numTarget) {
-       l = list->free.next;
-       if (l == &list->free)
-           break;
-       DRMLISTDEL(l);
-       node = DRMLISTENTRY(drmBONode, l, head);
-       free(node);
-       list->numCurrent--;
-    }
-    return ret;
-}
-
-void drmBOFreeList(drmBOList *list)
-{
-    drmBONode *node;
-    drmMMListHead *l;
-
-    l = list->list.next;
-    while(l != &list->list) {
-       DRMLISTDEL(l);
-       node = DRMLISTENTRY(drmBONode, l, head);
-       free(node);
-       l = list->list.next;
-       list->numCurrent--;
-       list->numOnList--;
-    }
-
-    l = list->free.next;
-    while(l != &list->free) {
-       DRMLISTDEL(l);
-       node = DRMLISTENTRY(drmBONode, l, head);
-       free(node);
-       l = list->free.next;
-       list->numCurrent--;
-    }
-}
-       
-int drmBOResetList(drmBOList *list)
-{
-    drmMMListHead *l;
-    int ret;
-
-    ret = drmAdjustListNodes(list);
-    if (ret)
-       return ret;
-
-    l = list->list.next;
-    while (l != &list->list) {
-       DRMLISTDEL(l);
-       DRMLISTADD(l, &list->free);
-       list->numOnList--;
-       l = list->list.next;
-    }
-    return drmAdjustListNodes(list);
-}
-       
-static drmBONode *drmAddListItem(drmBOList *list, drmBO *item, 
-                                unsigned long arg0,
-                                unsigned long arg1)
-{
-    drmBONode *node;
-    drmMMListHead *l;
-
-    l = list->free.next;
-    if (l == &list->free) {
-       node = (drmBONode *) malloc(sizeof(*node));
-       if (!node) {
-           return NULL;
-       }
-       list->numCurrent++;
-    }
-    else {
-       DRMLISTDEL(l);
-       node = DRMLISTENTRY(drmBONode, l, head);
-    }
-    node->buf = item;
-    node->arg0 = arg0;
-    node->arg1 = arg1;
-    DRMLISTADD(&node->head, &list->list);
-    list->numOnList++;
-    return node;
-}
-       
-void *drmBOListIterator(drmBOList *list)
-{
-    void *ret = list->list.next;
-
-    if (ret == &list->list)
-       return NULL;
-    return ret;
-}
-
-void *drmBOListNext(drmBOList *list, void *iterator)
-{
-    void *ret;
-
-    drmMMListHead *l = (drmMMListHead *) iterator;
-    ret = l->next;
-    if (ret == &list->list)
-       return NULL;
-    return ret;
-}
-
-drmBO *drmBOListBuf(void *iterator)
-{
-    drmBONode *node;
-    drmMMListHead *l = (drmMMListHead *) iterator;
-    node = DRMLISTENTRY(drmBONode, l, head);
-    return node->buf;
-}
-
-
-int drmBOCreateList(int numTarget, drmBOList *list)
-{
-    DRMINITLISTHEAD(&list->list);
-    DRMINITLISTHEAD(&list->free);
-    list->numTarget = numTarget;
-    list->numCurrent = 0;
-    list->numOnList = 0;
-    return drmAdjustListNodes(list);
-}
-
-static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, drmBO *buf)
+static void drmBOCopyReply(const struct drm_bo_info_rep *rep, drmBO *buf)
 {
     buf->handle = rep->handle;
     buf->flags = rep->flags;
@@ -2690,16 +2541,21 @@ static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, drmBO *buf)
     buf->fenceFlags = rep->fence_flags;
     buf->replyFlags = rep->rep_flags;
     buf->pageAlignment = rep->page_alignment;
+    buf->tileInfo = rep->tile_info;
+    buf->hwTileStride = rep->hw_tile_stride;
+    buf->desiredTileStride = rep->desired_tile_stride;
 }
 
-int drmBOCreate(int fd, unsigned long start, unsigned long size, 
-               unsigned pageAlignment, void *user_buffer, drm_bo_type_t type, 
-               unsigned mask,
+
+
+int drmBOCreate(int fd, unsigned long size,
+               unsigned pageAlignment, void *user_buffer,
+               uint64_t mask,
                unsigned hint, drmBO *buf)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+    struct drm_bo_create_arg arg;
+    struct drm_bo_create_req *req = &arg.d.req;
+    struct drm_bo_info_rep *rep = &arg.d.rep;
     int ret;
 
     memset(buf, 0, sizeof(*buf));
@@ -2707,40 +2563,17 @@ int drmBOCreate(int fd, unsigned long start, unsigned long size,
     req->mask = mask;
     req->hint = hint;
     req->size = size;
-    req->type = type;
     req->page_alignment = pageAlignment;
+    req->buffer_start = (unsigned long) user_buffer;
 
     buf->virtual = NULL;
 
-    switch(type) {
-    case drm_bo_type_dc:
-        req->buffer_start = start;
-       break;
-    case drm_bo_type_user:
-       req->buffer_start = (unsigned long) user_buffer;
-       buf->virtual = user_buffer;
-       break;
-    case drm_bo_type_fake:
-        req->buffer_start = start;
-       break;
-    default:
-       return -EINVAL;
-    }
-    req->op = drm_bo_create;
-
     do {
-       ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
+       ret = ioctl(fd, DRM_IOCTL_BO_CREATE, &arg);
     } while (ret != 0 && errno == EAGAIN);
 
     if (ret)
        return -errno;
-    if (!arg.handled) {
-       return -EFAULT;
-    }
-    if (rep->ret) {
-        fprintf(stderr, "Error %d\n", rep->ret);
-       return rep->ret;
-    }
     
     drmBOCopyReply(rep, buf);
     buf->mapVirtual = NULL;
@@ -2749,56 +2582,19 @@ int drmBOCreate(int fd, unsigned long start, unsigned long size,
     return 0;
 }
 
-int drmBODestroy(int fd, drmBO *buf)
-{
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
-    
-    if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) {
-       (void) drmUnmap(buf->mapVirtual, buf->start + buf->size);
-       buf->mapVirtual = NULL;
-       buf->virtual = NULL;
-    }
-
-    memset(&arg, 0, sizeof(arg));
-    req->handle = buf->handle;
-    req->op = drm_bo_destroy;
-
-    if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
-       return -errno;
-    if (!arg.handled) {
-       return -EFAULT;
-    }
-    if (rep->ret) {
-       return rep->ret;
-    }
-
-    buf->handle = 0;
-    return 0;
-}
 int drmBOReference(int fd, unsigned handle, drmBO *buf)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+    struct drm_bo_reference_info_arg arg;
+    struct drm_bo_handle_arg *req = &arg.d.req;
+    struct drm_bo_info_rep *rep = &arg.d.rep;
     
     memset(&arg, 0, sizeof(arg));
     req->handle = handle;
-    req->op = drm_bo_reference;
     
-    if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
+    if (ioctl(fd, DRM_IOCTL_BO_REFERENCE, &arg))
        return -errno;
-    if (!arg.handled) {
-       return -EFAULT;
-    }
-    if (rep->ret) {
-       return rep->ret;
-    }
 
     drmBOCopyReply(rep, buf);
-    buf->type = drm_bo_type_dc;
     buf->mapVirtual = NULL;
     buf->mapCount = 0;
     buf->virtual = NULL;
@@ -2806,35 +2602,27 @@ int drmBOReference(int fd, unsigned handle, drmBO *buf)
     return 0;
 }
 
-int drmBOUnReference(int fd, drmBO *buf)
+int drmBOUnreference(int fd, drmBO *buf)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+    struct drm_bo_handle_arg arg;
 
-    if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) {
+    if (buf->mapVirtual) {
        (void) munmap(buf->mapVirtual, buf->start + buf->size);
        buf->mapVirtual = NULL;
        buf->virtual = NULL;
     }
 
     memset(&arg, 0, sizeof(arg));
-    req->handle = buf->handle;
-    req->op = drm_bo_unreference;
+    arg.handle = buf->handle;
 
-    if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg))
+    if (ioctl(fd, DRM_IOCTL_BO_UNREFERENCE, &arg))
        return -errno;
-    if (!arg.handled) {
-       return -EFAULT;
-    }
-    if (rep->ret) {
-       return rep->ret;
-    }
 
     buf->handle = 0;
     return 0;
 }   
 
+
 /*
  * Flags can be  DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE or'ed together
  * Hint currently be DRM_BO_HINT_DONT_BLOCK, which makes the
@@ -2844,16 +2632,16 @@ int drmBOUnReference(int fd, drmBO *buf)
 int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
             void **address)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+    struct drm_bo_map_wait_idle_arg arg;
+    struct drm_bo_info_req *req = &arg.d.req;
+    struct drm_bo_info_rep *rep = &arg.d.rep;
     int ret = 0;
 
     /*
      * Make sure we have a virtual address of the buffer.
      */
 
-    if (!buf->virtual && buf->type != drm_bo_type_fake) {
+    if (!buf->virtual) {
        drmAddress virtual;
        virtual = mmap(0, buf->size + buf->start, 
                       PROT_READ | PROT_WRITE, MAP_SHARED,
@@ -2871,7 +2659,6 @@ int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
     req->handle = buf->handle;
     req->mask = mapFlags;
     req->hint = mapHint;
-    req->op = drm_bo_map;
 
     /*
      * May hang if the buffer object is busy.
@@ -2879,15 +2666,11 @@ int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
      */
     
     do {
-       ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
+       ret = ioctl(fd, DRM_IOCTL_BO_MAP, &arg);
     } while (ret != 0 && errno == EAGAIN);
 
     if (ret) 
        return -errno;
-    if (!arg.handled) 
-       return -EFAULT;
-    if (rep->ret)
-       return rep->ret;
 
     drmBOCopyReply(rep, buf);  
     buf->mapFlags = mapFlags;
@@ -2897,129 +2680,90 @@ int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
     return 0;
 }
 
+
 int drmBOUnmap(int fd, drmBO *buf)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+    struct drm_bo_handle_arg arg;
 
     memset(&arg, 0, sizeof(arg));
-    req->handle = buf->handle;
-    req->op = drm_bo_unmap;
+    arg.handle = buf->handle;
 
-    if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) {
+    if (ioctl(fd, DRM_IOCTL_BO_UNMAP, &arg)) {
        return -errno;
     }
-    if (!arg.handled) 
-        return -EFAULT;
-    if (rep->ret)
-       return rep->ret;
-
+    buf->mapCount--;
     return 0;
 }
-    
-int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask, 
-                 unsigned hint)
+
+int drmBOSetStatus(int fd, drmBO *buf, 
+                  uint64_t flags, uint64_t mask,
+                  unsigned int hint, 
+                  unsigned int desired_tile_stride,
+                  unsigned int tile_info)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+
+    struct drm_bo_map_wait_idle_arg arg;
+    struct drm_bo_info_req *req = &arg.d.req;
+    struct drm_bo_info_rep *rep = &arg.d.rep;
     int ret = 0;
 
     memset(&arg, 0, sizeof(arg));
+    req->mask = mask;
+    req->flags = flags;
     req->handle = buf->handle;
-    req->mask = flags;
     req->hint = hint;
-    req->arg_handle = mask; /* Encode mask in the arg_handle field :/ */
-    req->op = drm_bo_validate;
-
-    do{
-       ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
+    req->desired_tile_stride = desired_tile_stride;
+    req->tile_info = tile_info;
+    
+    do {
+           ret = ioctl(fd, DRM_IOCTL_BO_SETSTATUS, &arg);
     } while (ret && errno == EAGAIN);
 
     if (ret) 
-       return -errno;
-    if (!arg.handled)
-       return -EFAULT;
-    if (rep->ret)
-       return rep->ret;
+           return -errno;
 
     drmBOCopyReply(rep, buf);
-    return 0;
 }
            
 
-int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle)
-{
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
-    int ret = 0;
-
-    memset(&arg, 0, sizeof(arg));
-    req->handle = buf->handle;
-    req->mask = flags;
-    req->arg_handle = fenceHandle;
-    req->op = drm_bo_fence;
-
-    ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
-
-    if (ret) 
-       return -errno;
-    if (!arg.handled)
-       return -EFAULT;
-    if (rep->ret)
-       return rep->ret;
-    return 0;
-}
-
 int drmBOInfo(int fd, drmBO *buf)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+    struct drm_bo_reference_info_arg arg;
+    struct drm_bo_handle_arg *req = &arg.d.req;
+    struct drm_bo_info_rep *rep = &arg.d.rep;
     int ret = 0;
 
     memset(&arg, 0, sizeof(arg));
     req->handle = buf->handle;
-    req->op = drm_bo_info;
-
-    ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
 
+    ret = ioctl(fd, DRM_IOCTL_BO_INFO, &arg);
     if (ret) 
        return -errno;
-    if (!arg.handled)
-       return -EFAULT;
-    if (rep->ret)
-       return rep->ret;
+
     drmBOCopyReply(rep, buf);
     return 0;
 }
 
 int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint)
 {
-    drm_bo_arg_t arg;
-    drm_bo_arg_request_t *req = &arg.d.req;
-    drm_bo_arg_reply_t *rep = &arg.d.rep;
+    struct drm_bo_map_wait_idle_arg arg;
+    struct drm_bo_info_req *req = &arg.d.req;
+    struct drm_bo_info_rep *rep = &arg.d.rep;
     int ret = 0;
 
     if ((buf->flags & DRM_BO_FLAG_SHAREABLE) ||
        (buf->replyFlags & DRM_BO_REP_BUSY)) {
         memset(&arg, 0, sizeof(arg));
        req->handle = buf->handle;
-       req->op = drm_bo_wait_idle;
        req->hint = hint;
 
        do {
-           ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
+           ret = ioctl(fd, DRM_IOCTL_BO_WAIT_IDLE, &arg);
        } while (ret && errno == EAGAIN);
 
        if (ret) 
            return -errno;
-       if (!arg.handled)
-           return -EFAULT;
-       if (rep->ret)
-           return rep->ret;
+
        drmBOCopyReply(rep, buf);
     }
     return 0;
@@ -3041,194 +2785,19 @@ int drmBOBusy(int fd, drmBO *buf, int *busy)
     }
 }
     
-    
-int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, 
-                      unsigned mask,
-                      int *newItem)
-{
-    drmBONode *node, *cur;
-    drmMMListHead *l;
-
-    *newItem = 0;
-    cur = NULL;
-
-    for (l = list->list.next; l != &list->list; l = l->next) {
-       node = DRMLISTENTRY(drmBONode, l, head);
-       if (node->buf == buf) {
-           cur = node;
-           break;
-       }
-    }
-    if (!cur) {
-       cur = drmAddListItem(list, buf, flags, mask);
-       if (!cur) {
-           drmMsg("Out of memory creating validate list node.\n");
-           return -ENOMEM;
-       }
-       *newItem = 1;
-       cur->arg0 = flags;
-       cur->arg1 = mask;
-    }
-    else {
-       unsigned memMask = (cur->arg1 | mask) & DRM_BO_MASK_MEM;
-       unsigned memFlags = cur->arg0 & flags & memMask;
-       
-       if (!memFlags) {
-           drmMsg("Incompatible memory location requests "
-                  "on validate list.\n");
-           drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n",
-                  cur->arg0, cur->arg1);
-           drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n",
-                  flags, mask);
-           return -EINVAL;
-       }
-       if (mask & cur->arg1 & ~DRM_BO_MASK_MEM  & (cur->arg0 ^ flags)) {
-           drmMsg("Incompatible buffer flag requests "
-                  "on validate list.\n");
-           drmMsg("Previous flag: 0x%08lx, mask: 0x%08lx\n",
-                  cur->arg0, cur->arg1);
-           drmMsg("Current flag: 0x%08lx, mask: 0x%08lx\n",
-                  flags, mask);
-           return -EINVAL;
-       }
-       cur->arg1 |= mask;
-       cur->arg0 = memFlags | ((cur->arg0 | flags) & 
-                               cur->arg1 & ~DRM_BO_MASK_MEM);  
-    }
-    return 0;
-}
-
-
-int drmBOValidateList(int fd, drmBOList *list)
-{
-    drmBONode *node;
-    drmMMListHead *l;
-    drm_bo_arg_t *arg, *first;
-    drm_bo_arg_request_t *req;
-    drm_bo_arg_reply_t *rep;
-    drm_u64_t *prevNext = NULL;
-    drmBO *buf;
-    int ret;
-
-    first = NULL;
-
-    for (l = list->list.next; l != &list->list; l = l->next) {
-       node = DRMLISTENTRY(drmBONode, l, head);
-
-       arg = &node->bo_arg;
-       req = &arg->d.req;
-
-       if (!first)
-           first = arg;
-
-       if (prevNext)
-           *prevNext = (unsigned long) arg;
-
-       memset(arg, 0, sizeof(*arg));
-       prevNext = &arg->next;
-       req->handle = node->buf->handle;
-       req->op = drm_bo_validate;
-       req->mask = node->arg0;
-       req->hint = 0;
-       req->arg_handle = node->arg1;
-    }
-  
-    if (!first) 
-       return 0;
-
-    do {
-       ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
-    } while (ret && errno == EAGAIN);
-
-    if (ret)
-       return -errno;
-  
-    for (l = list->list.next; l != &list->list; l = l->next) {
-       node = DRMLISTENTRY(drmBONode, l, head);
-       arg = &node->bo_arg;
-       rep = &arg->d.rep;
-
-       if (!arg->handled) {
-           drmMsg("Unhandled request\n");
-           return -EFAULT;
-       }
-       if (rep->ret)
-           return rep->ret;
-
-       buf = node->buf;
-       drmBOCopyReply(rep, buf);
-    }
-
-    return 0;
-}
-         
-
-int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle)
-{
-    drmBONode *node;
-    drmMMListHead *l;
-    drm_bo_arg_t *arg, *first;
-    drm_bo_arg_request_t *req;
-    drm_bo_arg_reply_t *rep;
-    drm_u64_t *prevNext = NULL;
-    drmBO *buf;
-    unsigned fence_flags;
-    int ret;
-
-    first = NULL;
-
-    for (l = list->list.next; l != &list->list; l = l->next) {
-       node = DRMLISTENTRY(drmBONode, l, head);
-
-       arg = &node->bo_arg;
-       req = &arg->d.req;
-
-       if (!first)
-           first = arg;
-
-       if (prevNext)
-           *prevNext = (unsigned long) arg;
-
-       memset(arg, 0, sizeof(*arg));
-       prevNext = &arg->next;
-       req->handle = node->buf->handle;
-       req->op = drm_bo_fence;
-       req->mask = node->arg0;
-       req->arg_handle = fenceHandle;
-    }
-  
-    if (!first) 
-       return 0;
-
-    ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
-
-    if (ret)
-       return -errno;
-  
-    for (l = list->list.next; l != &list->list; l = l->next) {
-       node = DRMLISTENTRY(drmBONode, l, head);
-       arg = &node->bo_arg;
-       rep = &arg->d.rep;
-       if (!arg->handled)
-           return -EFAULT;
-       if (rep->ret)
-           return rep->ret;
-       drmBOCopyReply(rep, node->buf);
-    }
-
-    return 0;
-}
-
 int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
              unsigned memType)
 {
-    drm_mm_init_arg_t arg;
+    struct drm_mm_init_arg arg;
 
     memset(&arg, 0, sizeof(arg));
-    arg.req.op = mm_init;
-    arg.req.p_offset = pOffset;
-    arg.req.p_size = pSize;
-    arg.req.mem_type = memType;
+
+    arg.magic = DRM_BO_INIT_MAGIC;
+    arg.major = DRM_BO_INIT_MAJOR;
+    arg.minor = DRM_BO_INIT_MINOR;
+    arg.p_offset = pOffset;
+    arg.p_size = pSize;
+    arg.mem_type = memType;
 
     if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
        return -errno;
@@ -3237,47 +2806,79 @@ int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
 
 int drmMMTakedown(int fd, unsigned memType)
 {
-    drm_mm_init_arg_t arg;
+    struct drm_mm_type_arg arg;
 
     memset(&arg, 0, sizeof(arg));
-    arg.req.op = mm_takedown;
-    arg.req.mem_type = memType;
+    arg.mem_type = memType;
 
-    if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
+    if (ioctl(fd, DRM_IOCTL_MM_TAKEDOWN, &arg))
        return -errno;
     return 0;  
 }
 
-int drmMMLock(int fd, unsigned memType)
+/*
+ * If this function returns an error, and lockBM was set to 1,
+ * the buffer manager is NOT locked.
+ */
+
+int drmMMLock(int fd, unsigned memType, int lockBM, int ignoreNoEvict)
 {
-    drm_mm_init_arg_t arg;
+    struct drm_mm_type_arg arg;
     int ret;
 
     memset(&arg, 0, sizeof(arg));
-    arg.req.op = mm_lock;
-    arg.req.mem_type = memType;
+    arg.mem_type = memType;
+    arg.lock_flags |= (lockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0;
+    arg.lock_flags |= (ignoreNoEvict) ? DRM_BO_LOCK_IGNORE_NO_EVICT : 0;
 
     do{
-       ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
+        ret = ioctl(fd, DRM_IOCTL_MM_LOCK, &arg);
     } while (ret && errno == EAGAIN);
-    return -errno;     
+
+    return (ret) ? -errno : 0;
 }
 
-int drmMMUnlock(int fd, unsigned memType)
+int drmMMUnlock(int fd, unsigned memType, int unlockBM)
 {
-    drm_mm_init_arg_t arg;
+    struct drm_mm_type_arg arg;
     int ret;
 
     memset(&arg, 0, sizeof(arg));
-    arg.req.op = mm_unlock;
-    arg.req.mem_type = memType;
+    
+    arg.mem_type = memType;
+    arg.lock_flags |= (unlockBM) ? DRM_BO_LOCK_UNLOCK_BM : 0;
 
     do{
-       ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
+       ret = ioctl(fd, DRM_IOCTL_MM_UNLOCK, &arg);
     } while (ret && errno == EAGAIN);
-    return -errno;     
+
+    return (ret) ? -errno : 0;
 }
 
+int drmBOVersion(int fd, unsigned int *major,
+                unsigned int *minor,
+                unsigned int *patchlevel)
+{
+    struct drm_bo_version_arg arg;
+    int ret;
+
+    memset(&arg, 0, sizeof(arg));
+    ret = ioctl(fd, DRM_IOCTL_BO_VERSION, &arg);
+    if (ret)
+       return -errno;
+
+    if (major)
+       *major = arg.major;
+    if (minor)
+       *minor = arg.minor;
+    if (patchlevel)
+       *patchlevel = arg.patchlevel;
+
+    return 0;
+}
+
+
+
 #define DRM_MAX_FDS 16
 static struct {
     char *BusID;
index d4260cc..230f54c 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <stdarg.h>
 #include <sys/types.h>
+#include <stdint.h>
 #include <drm.h>
 
                                /* Defaults, if nothing set in xf86config */
index d1ade06..82cbc2a 100644 (file)
@@ -74,7 +74,6 @@
 #define HASH_MAIN 0
 
 #if !HASH_MAIN
-# include "drm.h"
 # include "xf86drm.h"
 #endif
 
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
new file mode 100644 (file)
index 0000000..a7241ff
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * \file xf86drmMode.c
+ * Header for DRM modesetting interface.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * \par Acknowledgements:
+ * Feb 2007, Dave Airlie <airlied@linux.ie>
+ */
+
+/*
+ * Copyright (c) <year> <copyright holders>
+ *
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ */
+
+/*
+ * TODO the types we are after are defined in diffrent headers on diffrent
+ * platforms find which headers to include to get uint32_t
+ */
+#include <stdint.h>
+
+#include "xf86drmMode.h"
+#include "xf86drm.h"
+#include <drm.h>
+#include <string.h>
+
+/*
+ * Util functions
+ */
+
+void* drmAllocCpy(void *array, int count, int entry_size)
+{
+       char *r;
+       int i;
+
+       if (!count || !array || !entry_size)
+               return 0;
+
+       if (!(r = drmMalloc(count*entry_size)))
+               return 0;
+
+       for (i = 0; i < count; i++)
+               memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
+
+       return r;
+}
+
+/**
+ * Generate crtc and output ids.
+ *
+ * Will generate ids starting from 1 up to count if count is greater then 0.
+ */
+static uint32_t* drmAllocGenerate(int count)
+{
+       uint32_t *r;
+       int i;
+
+       if(0 <= count)
+               return 0;
+
+       if (!(r = drmMalloc(count*sizeof(*r))))
+               return 0;
+
+       for (i = 0; i < count; r[i] = ++i);
+
+       return 0;
+}
+
+/*
+ * A couple of free functions.
+ */
+
+void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr);
+}
+
+void drmModeFreeResources(drmModeResPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr->modes);
+       drmFree(ptr);
+
+}
+
+void drmModeFreeFB(drmModeFBPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       /* we might add more frees later. */
+       drmFree(ptr);
+}
+
+void drmModeFreeCrtc(drmModeCrtcPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr);
+
+}
+
+void drmModeFreeOutput(drmModeOutputPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr->modes);
+       drmFree(ptr);
+
+}
+
+/*
+ * ModeSetting functions.
+ */
+
+drmModeResPtr drmModeGetResources(int fd)
+{
+       struct drm_mode_card_res res;
+       int i;
+       drmModeResPtr r = 0;
+
+       memset(&res, 0, sizeof(struct drm_mode_card_res));
+
+       if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
+               return 0;
+
+       if (res.count_fbs)
+               res.fb_id = drmMalloc(res.count_fbs*sizeof(uint32_t));
+       if (res.count_crtcs)
+               res.crtc_id = drmMalloc(res.count_crtcs*sizeof(uint32_t));
+       if (res.count_outputs)
+               res.output_id = drmMalloc(res.count_outputs*sizeof(uint32_t));
+       if (res.count_modes)
+               res.modes = drmMalloc(res.count_modes*sizeof(*res.modes));
+
+       if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
+               r = NULL;
+               goto err_allocs;
+       }
+
+       /*
+        * return
+        */
+
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return 0;
+
+       r->count_fbs     = res.count_fbs;
+       r->count_crtcs   = res.count_crtcs;
+       r->count_outputs = res.count_outputs;
+       r->count_modes   = res.count_modes;
+       /* TODO we realy should test if these allocs fails. */
+       r->fbs           = drmAllocCpy(res.fb_id, res.count_fbs, sizeof(uint32_t));
+       r->crtcs         = drmAllocCpy(res.crtc_id, res.count_crtcs, sizeof(uint32_t));
+       r->outputs       = drmAllocCpy(res.output_id, res.count_outputs, sizeof(uint32_t));
+       r->modes         = drmAllocCpy(res.modes, res.count_modes, sizeof(struct drm_mode_modeinfo));
+
+err_allocs:
+       drmFree(res.fb_id);
+       drmFree(res.crtc_id);
+       drmFree(res.output_id);
+       drmFree(res.modes);
+
+       return r;
+}
+
+int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
+                 uint8_t bpp, uint32_t pitch, drmBO *bo, uint32_t *buf_id)
+{
+       struct drm_mode_fb_cmd f;
+       int ret;
+
+       f.width  = width;
+       f.height = height;
+       f.pitch  = pitch;
+       f.bpp    = bpp;
+       f.depth  = depth;
+       f.handle = bo->handle;
+
+       if (ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f))
+               return ret;
+
+       *buf_id = f.buffer_id;
+       return 0;
+}
+
+int drmModeRmFB(int fd, uint32_t bufferId)
+{
+       return ioctl(fd, DRM_IOCTL_MODE_RMFB, bufferId);
+}
+
+drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
+{
+       struct drm_mode_fb_cmd info;
+       drmModeFBPtr r;
+
+       info.buffer_id = buf;
+
+       if (ioctl(fd, DRM_IOCTL_MODE_GETFB, &info))
+               return NULL;
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return NULL;
+
+       r->buffer_id = info.buffer_id;
+       r->width = info.width;
+       r->height = info.height;
+       r->pitch = info.pitch;
+       r->bpp = info.bpp;
+       r->handle = info.handle;
+       r->depth = info.depth;
+
+       return r;
+}
+
+
+/*
+ * Crtc functions
+ */
+
+drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
+{
+       struct drm_mode_crtc crtc;
+       drmModeCrtcPtr r;
+       int i = 0;
+
+       crtc.count_outputs   = 0;
+       crtc.outputs         = 0;
+       crtc.count_possibles = 0;
+       crtc.possibles       = 0;
+       crtc.crtc_id = crtcId;
+
+       if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
+               return 0;
+
+       /*
+        * return
+        */
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return 0;
+
+       r->x               = crtc.x;
+       r->y               = crtc.y;
+       r->mode            = crtc.mode;
+       r->buffer_id       = crtc.fb_id;
+       r->gamma_size      = crtc.gamma_size;
+       r->count_outputs   = crtc.count_outputs;
+       r->count_possibles = crtc.count_possibles;
+       /* TODO we realy should test if these alloc & cpy fails. */
+       r->outputs         = crtc.outputs;
+       r->possibles       = crtc.possibles;
+
+       return r;
+
+err_allocs:
+
+       return 0;
+}
+
+
+int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+                   uint32_t x, uint32_t y, uint32_t modeId,
+                   uint32_t *outputs, int count)
+{
+       struct drm_mode_crtc crtc;
+
+       crtc.count_outputs   = 0;
+       crtc.outputs         = 0;
+       crtc.count_possibles = 0;
+       crtc.possibles       = 0;
+
+       crtc.x             = x;
+       crtc.y             = y;
+       crtc.crtc_id       = crtcId;
+       crtc.fb_id         = bufferId;
+       crtc.set_outputs   = outputs;
+       crtc.count_outputs = count;
+       crtc.mode          = modeId;
+
+       return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
+}
+
+
+/*
+ * Output manipulation
+ */
+
+drmModeOutputPtr drmModeGetOutput(int fd, uint32_t output_id)
+{
+       struct drm_mode_get_output out;
+       drmModeOutputPtr r = 0;
+
+       out.output = output_id;
+       out.count_crtcs  = 0;
+       out.crtcs        = 0;
+       out.count_clones = 0;
+       out.clones       = 0;
+       out.count_modes  = 0;
+       out.modes        = 0;
+
+       if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
+               return 0;
+
+       if (out.count_modes)
+               out.modes = drmMalloc(out.count_modes*sizeof(uint32_t));
+
+       if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
+               goto err_allocs;
+
+       if(!(r = drmMalloc(sizeof(*r))))
+               return 0;
+
+       r->connection   = out.connection;
+       r->mmWidth      = out.mm_width;
+       r->mmHeight     = out.mm_height;
+       r->subpixel     = out.subpixel;
+       r->count_crtcs  = out.count_crtcs;
+       r->count_clones = out.count_clones;
+       r->count_modes  = out.count_modes;
+       /* TODO we should test if these alloc & cpy fails. */
+       r->crtcs        = out.crtcs;
+       r->clones       = out.clones;
+       r->modes        = drmAllocCpy(out.modes, out.count_modes, sizeof(uint32_t));
+       strncpy(r->name, out.name, DRM_OUTPUT_NAME_LEN);
+       r->name[DRM_OUTPUT_NAME_LEN-1] = 0;
+       return r;
+
+err_allocs:
+       drmFree(out.modes);
+
+       return 0;
+}
+
+uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *mode_info)
+{
+       if (ioctl(fd, DRM_IOCTL_MODE_ADDMODE, mode_info))
+               return 0;
+       
+       return mode_info->id;
+}
+
+int drmModeRmMode(int fd, uint32_t mode_id)
+{
+       return ioctl(fd, DRM_IOCTL_MODE_RMMODE, mode_id);
+}
+
+int drmModeAttachMode(int fd, uint32_t output_id, uint32_t mode_id)
+{
+
+       struct drm_mode_mode_cmd res;
+
+       res.output_id = output_id;
+       res.mode_id = mode_id;
+
+       return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
+}
+
+int drmModeDetachMode(int fd, uint32_t output_id, uint32_t mode_id)
+{
+       struct drm_mode_mode_cmd res;
+
+       res.output_id = output_id;
+       res.mode_id = mode_id;
+
+       return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
+}
+
+
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
new file mode 100644 (file)
index 0000000..b25a661
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * \file xf86drmMode.h
+ * Header for DRM modesetting interface.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * \par Acknowledgements:
+ * Feb 2007, Dave Airlie <airlied@linux.ie>
+ */
+
+/*
+ * Copyright (c) <year> <copyright holders>
+ *
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS 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 <drm.h>
+#include "xf86mm.h"
+
+/*
+ * This is the interface for modesetting for drm.
+ *
+ * In order to use this interface you must include either <stdint.h> or another
+ * header defining uint32_t, int32_t and uint16_t.
+ *
+ * It aims to provide a randr1.2 compatible interface for modesettings in the
+ * kernel, the interface is also ment to be used by libraries like EGL.
+ *
+ * More information can be found in randrproto.txt which can be found here:
+ * http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git
+ *
+ * There are some major diffrences to be noted. Unlike the randr1.2 proto you
+ * need to create the memory object of the framebuffer yourself with the ttm
+ * buffer object interface. This object needs to be pinned.
+ */
+
+
+typedef struct _drmModeRes {
+
+       int count_fbs;
+       uint32_t *fbs;
+
+       int count_crtcs;
+       uint32_t *crtcs;
+
+       int count_outputs;
+       uint32_t *outputs;
+
+       int count_modes;
+       struct drm_mode_modeinfo *modes;
+
+} drmModeRes, *drmModeResPtr;
+
+typedef struct drm_mode_fb_cmd drmModeFB, *drmModeFBPtr;
+
+typedef struct _drmModeCrtc {
+
+       unsigned int buffer_id; /**< FB id to connect to 0 = disconnect*/
+
+       uint32_t x, y; /**< Position on the frameuffer */
+       uint32_t width, height;
+       uint32_t mode; /**< Current mode used */
+
+       int count_outputs;
+       uint32_t outputs; /**< Outputs that are connected */
+
+       int count_possibles;
+       uint32_t possibles; /**< Outputs that can be connected */
+
+       int gamma_size; /**< Number of gamma stops */
+
+} drmModeCrtc, *drmModeCrtcPtr;
+
+typedef enum {
+       DRM_MODE_CONNECTED         = 1,
+       DRM_MODE_DISCONNECTED      = 2,
+       DRM_MODE_UNKNOWNCONNECTION = 3
+} drmModeConnection;
+
+typedef enum {
+       DRM_MODE_SUBPIXEL_UNKNOWN        = 1,
+       DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2,
+       DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3,
+       DRM_MODE_SUBPIXEL_VERTICAL_RGB   = 4,
+       DRM_MODE_SUBPIXEL_VERTICAL_BGR   = 5,
+       DRM_MODE_SUBPIXEL_NONE           = 6
+} drmModeSubPixel;
+
+typedef struct _drmModeOutput {
+
+       unsigned int crtc; /**< Crtc currently connected to */
+       unsigned char name[DRM_OUTPUT_NAME_LEN];
+       drmModeConnection connection;
+       uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
+       drmModeSubPixel subpixel;
+
+       int count_crtcs;
+       uint32_t crtcs; /**< Possible crtc to connect to */
+
+       int count_clones;
+       uint32_t clones; /**< Mask of clones */
+
+       int count_modes;
+       uint32_t *modes; /**< List of modes ids */
+
+} drmModeOutput, *drmModeOutputPtr;
+
+
+
+extern void drmModeFreeModeInfo( struct drm_mode_modeinfo *ptr );
+extern void drmModeFreeResources( drmModeResPtr ptr );
+extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
+extern void drmModeFreeOutput( drmModeOutputPtr ptr );
+
+/**
+ * Retrives all of the resources associated with a card.
+ */
+extern drmModeResPtr drmModeGetResources(int fd);
+
+
+/*
+ * FrameBuffer manipulation.
+ */
+
+/**
+ * Retrive information about framebuffer bufferId
+ */
+extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+
+/**
+ * Creates a new framebuffer with an buffer object as its scanout buffer.
+ */
+extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
+                       uint8_t bpp, uint32_t pitch, drmBO *bo,
+                       uint32_t *buf_id);
+/**
+ * Destroies the given framebuffer.
+ */
+extern int drmModeRmFB(int fd, uint32_t bufferId);
+
+
+/*
+ * Crtc functions
+ */
+
+/**
+ * Retrive information about the ctrt crtcId
+ */
+extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId);
+
+/**
+ * Set the mode on a crtc crtcId with the given mode modeId.
+ */
+extern int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+               uint32_t x, uint32_t y, uint32_t modeId,
+               uint32_t *outputs, int count);
+
+
+/*
+ * Output manipulation
+ */
+
+/**
+ * Retrive information about the output outputId.
+ */
+extern drmModeOutputPtr drmModeGetOutput(int fd,
+               uint32_t outputId);
+
+/**
+ * Adds a new mode from the given mode info.
+ * Name must be unique.
+ */
+extern uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *modeInfo);
+
+/**
+ * Removes a mode created with AddMode, must be unused.
+ */
+extern int drmModeRmMode(int fd, uint32_t modeId);
+
+/**
+ * Attaches the given mode to an output.
+ */
+extern int drmModeAttachMode(int fd, uint32_t outputId, uint32_t modeId);
+
+/**
+ * Detaches a mode from the output
+ * must be unused, by the given mode.
+ */
+extern int drmModeDetachMode(int fd, uint32_t outputId, uint32_t modeId);
+
index 61ffb07..ecab9e2 100644 (file)
@@ -77,7 +77,6 @@
 #define RANDOM_MAIN 0
 
 #if !RANDOM_MAIN
-# include "drm.h"
 # include "xf86drm.h"
 #endif
 
index ce60648..58aefac 100644 (file)
@@ -44,7 +44,6 @@
 #define SL_MAIN 0
 
 #if !SL_MAIN
-# include "drm.h"
 # include "xf86drm.h"
 #else
 # include <sys/time.h>
index b3822d4..d3df849 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef _XF86MM_H_
 #define _XF86MM_H_
 #include <stddef.h>
+#include <stdint.h>
 #include "drm.h"
 
 /*
@@ -37,7 +38,7 @@
  * be protected using an external mutex.
  *
  * Note: Don't protect the following functions, as it may lead to deadlocks:
- * drmBOUnmap(), drmFenceBuffers().
+ * drmBOUnmap().
  * The kernel is synchronizing and refcounting buffer maps. 
  * User space only needs to refcount object usage within the same application.
  */
@@ -96,20 +97,20 @@ typedef struct _drmMMListHead
 typedef struct _drmFence
 {
     unsigned handle;
-    int class;
+    int fence_class;
     unsigned type; 
     unsigned flags;
     unsigned signaled;
+    uint32_t sequence;
     unsigned pad[4]; /* for future expansion */
 } drmFence;
 
 typedef struct _drmBO
 {
-    drm_bo_type_t type;
     unsigned handle;
-    drm_u64_t mapHandle;
-    unsigned flags;
-    unsigned mask;
+    uint64_t mapHandle;
+    uint64_t flags;
+    uint64_t mask;
     unsigned mapFlags;
     unsigned long size;
     unsigned long offset;
@@ -117,37 +118,21 @@ typedef struct _drmBO
     unsigned replyFlags;
     unsigned fenceFlags;
     unsigned pageAlignment;
+    unsigned tileInfo;
+    unsigned hwTileStride;
+    unsigned desiredTileStride;
     void *virtual;
     void *mapVirtual;
     int mapCount;
     unsigned pad[8];     /* for future expansion */
 } drmBO;
 
-typedef struct _drmBONode
-{
-    drmMMListHead head;
-    drmBO *buf;
-    drm_bo_arg_t bo_arg;
-    unsigned long arg0;
-    unsigned long arg1;
-} drmBONode;
-
-typedef struct _drmBOList {
-    unsigned numTarget;
-    unsigned numCurrent;
-    unsigned numOnList;
-    drmMMListHead list;
-    drmMMListHead free;
-} drmBOList;
-
-
 /*
  * Fence functions.
  */
 
-extern int drmFenceCreate(int fd, unsigned flags, int class,
+extern int drmFenceCreate(int fd, unsigned flags, int fence_class,
                           unsigned type, drmFence *fence);
-extern int drmFenceDestroy(int fd, const drmFence *fence);
 extern int drmFenceReference(int fd, unsigned handle, drmFence *fence);
 extern int drmFenceUnreference(int fd, const drmFence *fence);
 extern int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type);
@@ -157,46 +142,25 @@ extern int drmFenceWait(int fd, unsigned flags, drmFence *fence,
                         unsigned flush_type);
 extern int drmFenceEmit(int fd, unsigned flags, drmFence *fence, 
                         unsigned emit_type);
-extern int drmFenceBuffers(int fd, unsigned flags, drmFence *fence);
+extern int drmFenceBuffers(int fd, unsigned flags, uint32_t fence_class, drmFence *fence);
 
 
 /*
- * Buffer object list functions.
- */
-
-extern void drmBOFreeList(drmBOList *list);
-extern int drmBOResetList(drmBOList *list);
-extern void *drmBOListIterator(drmBOList *list);
-extern void *drmBOListNext(drmBOList *list, void *iterator);
-extern drmBO *drmBOListBuf(void *iterator);
-extern int drmBOCreateList(int numTarget, drmBOList *list);
-
-/*
  * Buffer object functions.
  */
 
-extern int drmBOCreate(int fd, unsigned long start, unsigned long size,
-                      unsigned pageAlignment,void *user_buffer, 
-                      drm_bo_type_t type, unsigned mask,
-                      unsigned hint, drmBO *buf);
-extern int drmBODestroy(int fd, drmBO *buf);
+extern int drmBOCreate(int fd, unsigned long size,
+                      unsigned pageAlignment, void *user_buffer,
+                      uint64_t mask, unsigned hint, drmBO *buf);
 extern int drmBOReference(int fd, unsigned handle, drmBO *buf);
-extern int drmBOUnReference(int fd, drmBO *buf);
+extern int drmBOUnreference(int fd, drmBO *buf);
 extern int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
                    void **address);
 extern int drmBOUnmap(int fd, drmBO *buf);
-extern int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask, 
-                        unsigned hint);
 extern int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle);
 extern int drmBOInfo(int fd, drmBO *buf);
 extern int drmBOBusy(int fd, drmBO *buf, int *busy);
 
-
-extern int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, 
-                      unsigned mask,
-                      int *newItem);
-extern int drmBOValidateList(int fd, drmBOList *list);
-extern int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle);
 extern int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint);
 
 /*
@@ -206,8 +170,16 @@ extern int drmBOWaitIdle(int fd, drmBO *buf, unsigned hint);
 extern int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
                     unsigned memType);
 extern int drmMMTakedown(int fd, unsigned memType);
-extern int drmMMLock(int fd, unsigned memType);
-extern int drmMMUnlock(int fd, unsigned memType);
+extern int drmMMLock(int fd, unsigned memType, int lockBM, int ignoreNoEvict);
+extern int drmMMUnlock(int fd, unsigned memType, int unlockBM);
+extern int drmBOSetStatus(int fd, drmBO *buf, 
+                         uint64_t flags, uint64_t mask,
+                         unsigned int hint, 
+                         unsigned int desired_tile_stride,
+                         unsigned int tile_info);
+extern int drmBOVersion(int fd, unsigned int *major,
+                       unsigned int *minor,
+                       unsigned int *patchlevel);
 
 
 #endif
index 1758777..7f6b123 100644 (file)
@@ -58,7 +58,7 @@ endif
 
 # Modules for all architectures
 MODULE_LIST := drm.o tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o \
-               mach64.o nv.o nouveau.o
+               mach64.o nv.o nouveau.o xgi.o
 
 # Modules only for ix86 architectures
 ifneq (,$(findstring 86,$(MACHINE)))
@@ -91,6 +91,7 @@ MACH64HEADERS = mach64_drv.h mach64_drm.h $(DRMHEADERS)
 NVHEADERS =     nv_drv.h $(DRMHEADERS)
 FFBHEADERS =   ffb_drv.h $(DRMHEADERS)
 NOUVEAUHEADERS = nouveau_drv.h nouveau_drm.h nouveau_reg.h $(DRMHEADERS)
+XGIHEADERS = xgi_cmdlist.h xgi_drv.h xgi_misc.h xgi_regs.h $(DRMHEADERS)
 
 PROGS = dristat drmstat
 
@@ -162,7 +163,7 @@ endif
 all: modules
 
 modules: includes
-       make -C $(LINUXDIR) $(GETCONFIG) SUBDIRS=`pwd` DRMSRCDIR=`pwd` modules
+       +make -C $(LINUXDIR) $(GETCONFIG) SUBDIRS=`pwd` DRMSRCDIR=`pwd` modules
 
 ifeq ($(HEADERFROMBOOT),1)
 
@@ -284,6 +285,7 @@ CONFIG_DRM_VIA := n
 CONFIG_DRM_MACH64 := n
 CONFIG_DRM_NV := n
 CONFIG_DRM_NOUVEAU := n
+CONFIG_DRM_XGI := n
 
 # Enable module builds for the modules requested/supported.
 
@@ -320,6 +322,9 @@ endif
 ifneq (,$(findstring nouveau,$(DRM_MODULES)))
 CONFIG_DRM_NOUVEAU := m
 endif
+ifneq (,$(findstring xgi,$(DRM_MODULES)))
+CONFIG_DRM_XGI := m
+endif
 
 # These require AGP support
 
@@ -347,6 +352,7 @@ $(via-objs):        $(VIAHEADERS)
 $(mach64-objs): $(MACH64HEADERS)
 $(nv-objs):     $(NVHEADERS)
 $(nouveau-objs): $(NOUVEAUHEADERS)
+$(xgi-objs):    $(XGIHEADERS)
 
 endif
 
index 510509c..0ed5471 100644 (file)
@@ -13,20 +13,25 @@ drm-objs    := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
                drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \
                drm_memory_debug.o ati_pcigart.o drm_sman.o \
                drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \
-               drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o
+               drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_crtc.o \
+               drm_edid.o drm_modes.o drm_bo_lock.o
 tdfx-objs   := tdfx_drv.o
 r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
 mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
 i810-objs   := i810_drv.o i810_dma.o
 i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
-               i915_buffer.o
+               i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \
+               intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o
 nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
-               nouveau_object.o nouveau_irq.o \
+               nouveau_object.o nouveau_irq.o nouveau_notifier.o nouveau_swmthd.o \
+               nouveau_sgdma.o nouveau_dma.o \
                nv04_timer.o \
-               nv04_mc.o nv40_mc.o \
+               nv04_mc.o nv40_mc.o nv50_mc.o \
                nv04_fb.o nv10_fb.o nv40_fb.o \
-               nv04_graph.o nv10_graph.o nv20_graph.o nv30_graph.o \
-               nv40_graph.o
+               nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
+               nv04_graph.o nv10_graph.o nv20_graph.o \
+               nv40_graph.o nv50_graph.o \
+               nv04_instmem.o nv50_instmem.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o radeon_fence.o radeon_buffer.o
 sis-objs    := sis_drv.o sis_mm.o
 ffb-objs    := ffb_drv.o ffb_context.o
@@ -35,6 +40,8 @@ via-objs    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o \
                via_video.o via_dmablit.o via_fence.o via_buffer.o
 mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
 nv-objs := nv_drv.o
+xgi-objs    := xgi_cmdlist.o xgi_drv.o xgi_fb.o xgi_misc.o xgi_pcie.o \
+               xgi_fence.o
 
 ifeq ($(CONFIG_COMPAT),y)
 drm-objs    += drm_ioc32.o
@@ -43,6 +50,7 @@ mga-objs    += mga_ioc32.o
 r128-objs   += r128_ioc32.o
 i915-objs   += i915_ioc32.o
 nouveau-objs += nouveau_ioc32.o
+xgi-objs    += xgi_ioc32.o
 endif
 
 obj-m                  += drm.o
@@ -59,3 +67,4 @@ obj-$(CONFIG_DRM_VIA)   += via.o
 obj-$(CONFIG_DRM_MACH64)+= mach64.o
 obj-$(CONFIG_DRM_NV)    += nv.o
 obj-$(CONFIG_DRM_NOUVEAU) += nouveau.o
+obj-$(CONFIG_DRM_XGI)   += xgi.o
index ebf19a2..64e0e75 100644 (file)
@@ -120,9 +120,9 @@ static void drm_ati_free_pcigart_table(void *address, int order)
        free_pages((unsigned long)address, order);
 }
 
-int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_cleanup(struct drm_device *dev, struct ati_pcigart_info *gart_info)
 {
-       drm_sg_mem_t *entry = dev->sg;
+       struct drm_sg_mem *entry = dev->sg;
        unsigned long pages;
        int i;
        int order;
@@ -171,9 +171,9 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
 }
 EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
 
-int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
+int drm_ati_pcigart_init(struct drm_device *dev, struct ati_pcigart_info *gart_info)
 {
-       drm_sg_mem_t *entry = dev->sg;
+       struct drm_sg_mem *entry = dev->sg;
        void *address = NULL;
        unsigned long pages;
        u32 *pci_gart, page_base, bus_address = 0;
@@ -286,9 +286,8 @@ static int ati_pcigart_populate(drm_ttm_backend_t *backend,
        return 0;
 }
 
-static int ati_pcigart_bind_ttm(drm_ttm_backend_t *backend,
-                               unsigned long offset,
-                               int cached)
+static int ati_pcigart_bind_ttm(struct drm_ttm_backend *backend,
+                               struct drm_bo_mem_reg *bo_mem)
 {
        ati_pcigart_ttm_backend_t *atipci_be =
                container_of(backend, ati_pcigart_ttm_backend_t, backend);
@@ -297,9 +296,10 @@ static int ati_pcigart_bind_ttm(drm_ttm_backend_t *backend,
        struct ati_pcigart_info *info = atipci_be->gart_info;
        u32 *pci_gart;
        u32 page_base;
+       unsigned long offset = bo_mem->mm_node->start;
        pci_gart = info->addr;
 
-       DRM_ERROR("Offset is %08lX\n", offset);
+       DRM_ERROR("Offset is %08lX\n", bo_mem->mm_node->start);
         j = offset;
         while (j < (offset + atipci_be->num_pages)) {
                if (get_page_base_from_table(info, pci_gart+j))
@@ -382,7 +382,7 @@ static void ati_pcigart_destroy_ttm(drm_ttm_backend_t *backend)
        }
 }
 
-static drm_ttm_backend_func_t ati_pcigart_ttm_backend = 
+static struct drm_ttm_backend_func ati_pcigart_ttm_backend = 
 {
        .needs_ub_cache_adjust = ati_pcigart_needs_unbind_cache_adjust,
        .populate = ati_pcigart_populate,
@@ -392,7 +392,7 @@ static drm_ttm_backend_func_t ati_pcigart_ttm_backend =
        .destroy =  ati_pcigart_destroy_ttm,
 };
 
-drm_ttm_backend_t *ati_pcigart_init_ttm(struct drm_device *dev, struct ati_pcigart_info *info, void (*gart_flush_fn)(struct drm_device *dev))
+struct drm_ttm_backend *ati_pcigart_init_ttm(struct drm_device *dev, struct ati_pcigart_info *info, void (*gart_flush_fn)(struct drm_device *dev))
 {
        ati_pcigart_ttm_backend_t *atipci_be;
 
@@ -402,7 +402,6 @@ drm_ttm_backend_t *ati_pcigart_init_ttm(struct drm_device *dev, struct ati_pciga
        
        atipci_be->populated = 0;
        atipci_be->backend.func = &ati_pcigart_ttm_backend;
-       atipci_be->backend.mem_type = DRM_BO_MEM_TT;
        atipci_be->gart_info = info;
        atipci_be->gart_flush_fn = gart_flush_fn;
        atipci_be->dev = dev;
index 4b54c24..2d1f6db 100644 (file)
@@ -84,6 +84,8 @@
 #include "drm_os_linux.h"
 #include "drm_hashtab.h"
 
+struct drm_file;
+
 /* If you want the memory alloc debug functionality, change define below */
 /* #define DEBUG_MEMORY */
 
 
 #include "drm_compat.h"
 
+#include "drm_crtc.h"
+
 /***********************************************************************/
 /** \name Macros to make printk easier */
 /*@{*/
  * Test that the hardware lock is held by the caller, returning otherwise.
  *
  * \param dev DRM device.
- * \param filp file pointer of the caller.
+ * \param file_priv DRM file private pointer of the caller.
  */
-#define LOCK_TEST_WITH_RETURN( dev, filp )                             \
+#define LOCK_TEST_WITH_RETURN( dev, file_priv )                                \
 do {                                                                   \
        if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||           \
-            dev->lock.filp != filp )   {                               \
+            dev->lock.file_priv != file_priv ) {                       \
                DRM_ERROR( "%s called without lock held, held  %d owner %p %p\n",\
                           __FUNCTION__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
-                          dev->lock.filp, filp );                      \
+                          dev->lock.file_priv, file_priv );            \
                return -EINVAL;                                         \
        }                                                               \
 } while (0)
@@ -273,16 +277,19 @@ do {                                                                      \
                        return -EFAULT;                                 \
        }
 
+struct drm_device;
+struct drm_file;
+
 /**
  * Ioctl function type.
  *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg argument.
+ * \param dev DRM device structure
+ * \param data pointer to kernel-space stored data, copied in and out according
+ *            to ioctl description.
+ * \param file_priv DRM file private pointer.
  */
-typedef int drm_ioctl_t(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
+typedef int drm_ioctl_t(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
 
 typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
                               unsigned long arg);
@@ -291,31 +298,34 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
 #define DRM_MASTER      0x2
 #define DRM_ROOT_ONLY   0x4
 
-typedef struct drm_ioctl_desc {
+struct drm_ioctl_desc {
+       unsigned int cmd;
        drm_ioctl_t *func;
        int flags;
-} drm_ioctl_desc_t;
-
-typedef struct drm_devstate {
-       pid_t owner;                    /**< X server pid holding x_lock */
-} drm_devstate_t;
+};
+/**
+ * Creates a driver or general drm_ioctl_desc array entry for the given
+ * ioctl, for use by drm_ioctl().
+ */
+#define DRM_IOCTL_DEF(ioctl, func, flags) \
+       [DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags}
 
-typedef struct drm_magic_entry {
+struct drm_magic_entry {
        struct list_head head;
-       drm_hash_item_t hash_item;
+       struct drm_hash_item hash_item;
        struct drm_file *priv;
-} drm_magic_entry_t;
+};
 
-typedef struct drm_vma_entry {
+struct drm_vma_entry {
        struct list_head head;
        struct vm_area_struct *vma;
        pid_t pid;
-} drm_vma_entry_t;
+};
 
 /**
  * DMA buffer.
  */
-typedef struct drm_buf {
+struct drm_buf {
        int idx;                       /**< Index into master buflist */
        int total;                     /**< Buffer size */
        int order;                     /**< log-base-2(total) */
@@ -327,7 +337,7 @@ typedef struct drm_buf {
        __volatile__ int waiting;      /**< On kernel DMA queue */
        __volatile__ int pending;      /**< On hardware DMA queue */
        wait_queue_head_t dma_wait;    /**< Processes waiting */
-       struct file *filp;             /**< Pointer to holding file descr */
+       struct drm_file *file_priv;    /**< Private of holding file descr */
        int context;                   /**< Kernel queue for this buffer */
        int while_locked;              /**< Dispatch this buffer while locked */
        enum {
@@ -341,30 +351,30 @@ typedef struct drm_buf {
 
        int dev_priv_size;              /**< Size of buffer private storage */
        void *dev_private;              /**< Per-buffer private storage */
-} drm_buf_t;
+};
 
 /** bufs is one longer than it has to be */
-typedef struct drm_waitlist {
+struct drm_waitlist {
        int count;                      /**< Number of possible buffers */
-       drm_buf_t **bufs;               /**< List of pointers to buffers */
-       drm_buf_t **rp;                 /**< Read pointer */
-       drm_buf_t **wp;                 /**< Write pointer */
-       drm_buf_t **end;                /**< End pointer */
+       struct drm_buf **bufs;          /**< List of pointers to buffers */
+       struct drm_buf **rp;                    /**< Read pointer */
+       struct drm_buf **wp;                    /**< Write pointer */
+       struct drm_buf **end;           /**< End pointer */
        spinlock_t read_lock;
        spinlock_t write_lock;
-} drm_waitlist_t;
+};
 
-typedef struct drm_freelist {
+struct drm_freelist {
        int initialized;               /**< Freelist in use */
        atomic_t count;                /**< Number of free buffers */
-       drm_buf_t *next;               /**< End pointer */
+       struct drm_buf *next;          /**< End pointer */
 
        wait_queue_head_t waiting;     /**< Processes waiting on free bufs */
        int low_mark;                  /**< Low water mark */
        int high_mark;                 /**< High water mark */
        atomic_t wfh;                  /**< If waiting for high mark */
        spinlock_t lock;
-} drm_freelist_t;
+};
 
 typedef struct drm_dma_handle {
        dma_addr_t busaddr;
@@ -375,15 +385,15 @@ typedef struct drm_dma_handle {
 /**
  * Buffer entry.  There is one of this for each buffer size order.
  */
-typedef struct drm_buf_entry {
+struct drm_buf_entry {
        int buf_size;                   /**< size */
        int buf_count;                  /**< number of buffers */
-       drm_buf_t *buflist;             /**< buffer list */
+       struct drm_buf *buflist;                /**< buffer list */
        int seg_count;
        int page_order;
-       drm_dma_handle_t **seglist;
-       drm_freelist_t freelist;
-} drm_buf_entry_t;
+       struct drm_dma_handle **seglist;
+       struct drm_freelist freelist;
+};
 
 /*
  * This should be small enough to allow the use of kmalloc for hash tables
@@ -391,15 +401,15 @@ typedef struct drm_buf_entry {
  */
 
 #define DRM_FILE_HASH_ORDER 8
-typedef enum{
+enum drm_ref_type {
        _DRM_REF_USE=0,
        _DRM_REF_TYPE1,
        _DRM_NO_REF_TYPES
-} drm_ref_t;
+};
 
 
 /** File private data */
-typedef struct drm_file {
+struct drm_file {
        int authenticated;
        int master;
        int minor;
@@ -420,14 +430,16 @@ typedef struct drm_file {
         */
 
        struct list_head refd_objects;
-       struct list_head user_objects;
 
-       drm_open_hash_t refd_object_hash[_DRM_NO_REF_TYPES];
+       struct drm_open_hash refd_object_hash[_DRM_NO_REF_TYPES];
+       struct file *filp;
        void *driver_priv;
-} drm_file_t;
+
+       struct list_head fbs;
+};
 
 /** Wait queue */
-typedef struct drm_queue {
+struct drm_queue {
        atomic_t use_count;             /**< Outstanding uses (+1) */
        atomic_t finalization;          /**< Finalization in progress */
        atomic_t block_count;           /**< Count of processes waiting */
@@ -440,33 +452,34 @@ typedef struct drm_queue {
        atomic_t total_flushed;         /**< Total flushes statistic */
        atomic_t total_locks;           /**< Total locks statistics */
 #endif
-       drm_ctx_flags_t flags;          /**< Context preserving and 2D-only */
-       drm_waitlist_t waitlist;        /**< Pending buffers */
+       enum drm_ctx_flags flags;       /**< Context preserving and 2D-only */
+       struct drm_waitlist waitlist;   /**< Pending buffers */
        wait_queue_head_t flush_queue;  /**< Processes waiting until flush */
-} drm_queue_t;
+};
 
 /**
  * Lock data.
  */
-typedef struct drm_lock_data {
-       drm_hw_lock_t *hw_lock;         /**< Hardware lock */
-       struct file *filp;              /**< File descr of lock holder (0=kernel) */
+struct drm_lock_data {
+       struct drm_hw_lock *hw_lock;            /**< Hardware lock */
+       /** Private of lock holder's file (NULL=kernel) */
+       struct drm_file *file_priv;
        wait_queue_head_t lock_queue;   /**< Queue of blocked processes */
        unsigned long lock_time;        /**< Time of last lock in jiffies */
        spinlock_t spinlock;
        uint32_t kernel_waiters;
        uint32_t user_waiters;
        int idle_has_lock;
-} drm_lock_data_t;
+};
 
 /**
  * DMA data.
  */
-typedef struct drm_device_dma {
+struct drm_device_dma {
 
-       drm_buf_entry_t bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */
+       struct drm_buf_entry bufs[DRM_MAX_ORDER + 1];   /**< buffers, grouped by their size order */
        int buf_count;                  /**< total number of buffers */
-       drm_buf_t **buflist;            /**< Vector of pointers into drm_device_dma::bufs */
+       struct drm_buf **buflist;               /**< Vector of pointers into drm_device_dma::bufs */
        int seg_count;
        int page_count;                 /**< number of pages */
        unsigned long *pagelist;        /**< page list */
@@ -478,25 +491,25 @@ typedef struct drm_device_dma {
                _DRM_DMA_USE_PCI_RO = 0x08
        } flags;
 
-} drm_device_dma_t;
+};
 
 /**
  * AGP memory entry.  Stored as a doubly linked list.
  */
-typedef struct drm_agp_mem {
+struct drm_agp_mem {
        unsigned long handle;           /**< handle */
        DRM_AGP_MEM *memory;
        unsigned long bound;            /**< address */
        int pages;
        struct list_head head;
-} drm_agp_mem_t;
+};
 
 /**
  * AGP data.
  *
  * \sa drm_agp_init)() and drm_device::agp.
  */
-typedef struct drm_agp_head {
+struct drm_agp_head {
        DRM_AGP_KERN agp_info;          /**< AGP device information */
        struct list_head memory;
        unsigned long mode;             /**< AGP mode */
@@ -509,30 +522,30 @@ typedef struct drm_agp_head {
        int agp_mtrr;
        int cant_use_aperture;
        unsigned long page_mask;
-} drm_agp_head_t;
+};
 
 /**
  * Scatter-gather memory.
  */
-typedef struct drm_sg_mem {
+struct drm_sg_mem {
        unsigned long handle;
        void *virtual;
        int pages;
        struct page **pagelist;
        dma_addr_t *busaddr;
-} drm_sg_mem_t;
+};
 
-typedef struct drm_sigdata {
+struct drm_sigdata {
        int context;
-       drm_hw_lock_t *lock;
-} drm_sigdata_t;
+       struct drm_hw_lock *lock;
+};
 
 
 /*
  * Generic memory manager structs
  */
 
-typedef struct drm_mm_node {
+struct drm_mm_node {
        struct list_head fl_entry;
        struct list_head ml_entry;
        int free;
@@ -540,48 +553,42 @@ typedef struct drm_mm_node {
        unsigned long size;
        struct drm_mm *mm;
        void *private;
-} drm_mm_node_t;
+};
 
-typedef struct drm_mm {
+struct drm_mm {
        struct list_head fl_entry;
        struct list_head ml_entry;
-} drm_mm_t;
+};
 
 
 /**
  * Mappings list
  */
-typedef struct drm_map_list {
+struct drm_map_list {
        struct list_head head;          /**< list head */
-       drm_hash_item_t hash;
-       drm_map_t *map;                 /**< mapping */
-       drm_u64_t user_token;
-       drm_mm_node_t *file_offset_node;
-} drm_map_list_t;
+       struct drm_hash_item hash;
+       struct drm_map *map;                    /**< mapping */
+       uint64_t user_token;
+       struct drm_mm_node *file_offset_node;
+};
 
-typedef drm_map_t drm_local_map_t;
+typedef struct drm_map drm_local_map_t;
 
 /**
  * Context handle list
  */
-typedef struct drm_ctx_list {
+struct drm_ctx_list {
        struct list_head head;          /**< list head */
        drm_context_t handle;           /**< context handle */
-       drm_file_t *tag;                /**< associated fd private data */
-} drm_ctx_list_t;
-
-struct drm_ctx_sarea_list {
-       struct list_head head;
-       int ctx_id;
-       drm_map_t *map;
+       struct drm_file *tag;           /**< associated fd private data */
 };
 
-typedef struct drm_vbl_sig {
+struct drm_vbl_sig {
        struct list_head head;
        unsigned int sequence;
        struct siginfo info;
        struct task_struct *task;
-} drm_vbl_sig_t;
+};
 
 /* location of GART table */
 #define DRM_ATI_GART_MAIN 1
@@ -591,19 +598,13 @@ typedef struct drm_vbl_sig {
 #define DRM_ATI_GART_PCIE 2
 #define DRM_ATI_GART_IGP 3
 
-typedef struct ati_pcigart_info {
+struct ati_pcigart_info {
        int gart_table_location;
        int gart_reg_if;
        void *addr;
        dma_addr_t bus_addr;
        drm_local_map_t mapping;
        int table_size;
-} drm_ati_pcigart_info;
-
-struct drm_drawable_list {
-       struct list_head head;
-       int id;
-       drm_drawable_info_t info;
 };
 
 #include "drm_objects.h"
@@ -614,16 +615,15 @@ struct drm_drawable_list {
  * in this family
  */
 
-struct drm_device;
 struct drm_driver {
        int (*load) (struct drm_device *, unsigned long flags);
        int (*firstopen) (struct drm_device *);
-       int (*open) (struct drm_device *, drm_file_t *);
-       void (*preclose) (struct drm_device *, struct file * filp);
-       void (*postclose) (struct drm_device *, drm_file_t *);
+       int (*open) (struct drm_device *, struct drm_file *);
+       void (*preclose) (struct drm_device *, struct drm_file *file_priv);
+       void (*postclose) (struct drm_device *, struct drm_file *);
        void (*lastclose) (struct drm_device *);
        int (*unload) (struct drm_device *);
-       int (*dma_ioctl) (DRM_IOCTL_ARGS);
+       int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
        void (*dma_ready) (struct drm_device *);
        int (*dma_quiescent) (struct drm_device *);
        int (*context_ctor) (struct drm_device * dev, int context);
@@ -653,14 +653,19 @@ struct drm_driver {
        void (*irq_preinstall) (struct drm_device * dev);
        void (*irq_postinstall) (struct drm_device * dev);
        void (*irq_uninstall) (struct drm_device * dev);
-       void (*reclaim_buffers) (struct drm_device *dev, struct file * filp);
+       void (*reclaim_buffers) (struct drm_device *dev,
+                                struct drm_file *file_priv);
        void (*reclaim_buffers_locked) (struct drm_device *dev,
-                                       struct file * filp);
+                                       struct drm_file *file_priv);
        void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
-                                       struct file * filp);
-       unsigned long (*get_map_ofs) (drm_map_t * map);
+                                           struct drm_file *file_priv);
+       unsigned long (*get_map_ofs) (struct drm_map * map);
        unsigned long (*get_reg_ofs) (struct drm_device * dev);
-       void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
+       void (*set_version) (struct drm_device * dev, struct drm_set_version * sv);
+
+       /* FB routines, if present */
+       int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc);
+       int (*fb_remove)(struct drm_device *dev, struct drm_crtc *crtc);
 
        struct drm_fence_driver *fence_driver;
        struct drm_bo_driver *bo_driver;
@@ -675,7 +680,7 @@ struct drm_driver {
 /* variables */
        u32 driver_features;
        int dev_priv_size;
-       drm_ioctl_desc_t *ioctls;
+       struct drm_ioctl_desc *ioctls;
        int num_ioctls;
        struct file_operations fops;
        struct pci_driver pci_driver;
@@ -686,20 +691,20 @@ struct drm_driver {
  * that may contain multiple heads. Embed one per head of these in the
  * private drm_device structure.
  */
-typedef struct drm_head {
+struct drm_head {
        int minor;                      /**< Minor device number */
        struct drm_device *dev;
        struct proc_dir_entry *dev_root;  /**< proc directory entry */
        dev_t device;                   /**< Device number for mknod */
        struct class_device *dev_class;
-} drm_head_t;
+};
 
 
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
  */
-typedef struct drm_device {
+struct drm_device {
        char *unique;                   /**< Unique identifier: e.g., busid */
        int unique_len;                 /**< Length of unique field */
        char *devname;                  /**< For /proc/interrupts */
@@ -725,14 +730,14 @@ typedef struct drm_device {
        /** \name Performance counters */
        /*@{ */
        unsigned long counters;
-       drm_stat_type_t types[15];
+       enum drm_stat_type types[15];
        atomic_t counts[15];
        /*@} */
 
        /** \name Authentication */
        /*@{ */
        struct list_head filelist;
-       drm_open_hash_t magiclist;
+       struct drm_open_hash magiclist;
        struct list_head magicfree;
        /*@} */
 
@@ -740,9 +745,9 @@ typedef struct drm_device {
        /*@{ */
        struct list_head maplist;       /**< Linked list of regions */
        int map_count;                  /**< Number of mappable regions */
-       drm_open_hash_t map_hash;       /**< User token hash table for maps */
-       drm_mm_t offset_manager;        /**< User token manager */
-       drm_open_hash_t object_hash;    /**< User token hash table for objects */
+       struct drm_open_hash map_hash;       /**< User token hash table for maps */
+       struct drm_mm offset_manager;        /**< User token manager */
+       struct drm_open_hash object_hash;    /**< User token hash table for objects */
        struct address_space *dev_mapping;  /**< For unmap_mapping_range() */
        struct page *ttm_dummy_page;
 
@@ -753,10 +758,9 @@ typedef struct drm_device {
        struct mutex ctxlist_mutex;     /**< For ctxlist */
 
        struct idr ctx_idr;
-       struct list_head context_sarealist;
 
        struct list_head vmalist;       /**< List of vmas (for debugging) */
-       drm_lock_data_t lock;           /**< Information on hardware lock */
+       struct drm_lock_data lock;              /**< Information on hardware lock */
        /*@} */
 
        /** \name DMA queues (contexts) */
@@ -764,8 +768,8 @@ typedef struct drm_device {
        int queue_count;                /**< Number of active DMA queues */
        int queue_reserved;             /**< Number of reserved DMA queues */
        int queue_slots;                /**< Actual length of queuelist */
-       drm_queue_t **queuelist;        /**< Vector of pointers to DMA queues */
-       drm_device_dma_t *dma;          /**< Optional pointer for DMA support */
+       struct drm_queue **queuelist;   /**< Vector of pointers to DMA queues */
+       struct drm_device_dma *dma;             /**< Optional pointer for DMA support */
        /*@} */
 
        /** \name Context support */
@@ -805,7 +809,7 @@ typedef struct drm_device {
        wait_queue_head_t buf_readers;  /**< Processes waiting to read */
        wait_queue_head_t buf_writers;  /**< Processes waiting to ctx switch */
 
-       drm_agp_head_t *agp;            /**< AGP data */
+       struct drm_agp_head *agp;               /**< AGP data */
 
        struct pci_dev *pdev;           /**< PCI device structure */
        int pci_vendor;                 /**< PCI vendor id */
@@ -813,38 +817,40 @@ typedef struct drm_device {
 #ifdef __alpha__
        struct pci_controller *hose;
 #endif
-       drm_sg_mem_t *sg;               /**< Scatter gather memory */
+       struct drm_sg_mem *sg;          /**< Scatter gather memory */
        void *dev_private;              /**< device private data */
-       drm_sigdata_t sigdata;          /**< For block_all_signals */
+       struct drm_sigdata sigdata;             /**< For block_all_signals */
        sigset_t sigmask;
 
        struct drm_driver *driver;
        drm_local_map_t *agp_buffer_map;
        unsigned int agp_buffer_token;
-       drm_head_t primary;             /**< primary screen head */
+       struct drm_head primary;                /**< primary screen head */
 
-       drm_fence_manager_t fm;
-       drm_buffer_manager_t bm;
+       struct drm_fence_manager fm;
+       struct drm_buffer_manager bm;
 
        /** \name Drawable information */
        /*@{ */
        spinlock_t drw_lock;
        struct idr drw_idr;
-       struct list_head drwlist;
        /*@} */
-} drm_device_t;
+
+       /* DRM mode setting */
+       struct drm_mode_config mode_config;
+};
 
 #if __OS_HAS_AGP
-typedef struct drm_agp_ttm_backend {
-        drm_ttm_backend_t backend;
+struct drm_agp_ttm_backend {
+       struct drm_ttm_backend backend;
        DRM_AGP_MEM *mem;
        struct agp_bridge_data *bridge;
        int populated;
-} drm_agp_ttm_backend_t;
+};
 #endif
 
 typedef struct ati_pcigart_ttm_backend {
-       drm_ttm_backend_t backend;
+       struct drm_ttm_backend backend;
        int populated;
        void (*gart_flush_fn)(struct drm_device *dev);
        struct ati_pcigart_info *gart_info;
@@ -852,7 +858,7 @@ typedef struct ati_pcigart_ttm_backend {
        struct page **pages;
        int num_pages;
        int bound;
-       drm_device_t *dev;
+       struct drm_device *dev;
 } ati_pcigart_ttm_backend_t;
 
 static __inline__ int drm_core_check_feature(struct drm_device *dev,
@@ -926,10 +932,12 @@ extern void drm_exit(struct drm_driver *driver);
 extern void drm_cleanup_pci(struct pci_dev *pdev);
 extern int drm_ioctl(struct inode *inode, struct file *filp,
                     unsigned int cmd, unsigned long arg);
+extern long drm_unlocked_ioctl(struct file *filp,
+                              unsigned int cmd, unsigned long arg);
 extern long drm_compat_ioctl(struct file *filp,
                             unsigned int cmd, unsigned long arg);
 
-extern int drm_lastclose(drm_device_t * dev);
+extern int drm_lastclose(struct drm_device *dev);
 
                                /* Device support (drm_fops.h) */
 extern int drm_open(struct inode *inode, struct file *filp);
@@ -940,7 +948,7 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
 
                                /* Mapping support (drm_vm.h) */
 extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
-extern unsigned long drm_core_get_map_ofs(drm_map_t * map);
+extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
 extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
 extern pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma);
 
@@ -953,173 +961,179 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area);
 extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
 extern unsigned long drm_alloc_pages(int order, int area);
 extern void drm_free_pages(unsigned long address, int order, int area);
-extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type);
+extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
 extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
 extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
 extern int drm_unbind_agp(DRM_AGP_MEM * handle);
 
 extern void drm_free_memctl(size_t size);
 extern int drm_alloc_memctl(size_t size);
-extern void drm_query_memctl(drm_u64_t *cur_used,
-                            drm_u64_t *low_threshold,
-                            drm_u64_t *high_threshold);
+extern void drm_query_memctl(uint64_t *cur_used,
+                            uint64_t *low_threshold,
+                            uint64_t *high_threshold);
 extern void drm_init_memctl(size_t low_threshold,
                            size_t high_threshold,
                            size_t unit_size);
 
                                /* Misc. IOCTL support (drm_ioctl.h) */
-extern int drm_irq_by_busid(struct inode *inode, struct file *filp,
-                           unsigned int cmd, unsigned long arg);
-extern int drm_getunique(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
-extern int drm_setunique(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
-extern int drm_getmap(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_getclient(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
-extern int drm_getstats(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_setversion(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int drm_noop(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg);
+extern int drm_irq_by_busid(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int drm_getunique(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_setunique(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_getmap(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_getclient(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_getstats(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_setversion(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+extern int drm_noop(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv);
 
                                /* Context IOCTL support (drm_context.h) */
-extern int drm_resctx(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_addctx(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_modctx(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_getctx(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_switchctx(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
-extern int drm_newctx(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_rmctx(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg);
-
-extern int drm_ctxbitmap_init(drm_device_t * dev);
-extern void drm_ctxbitmap_cleanup(drm_device_t * dev);
-extern void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle);
-
-extern int drm_setsareactx(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg);
-extern int drm_getsareactx(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg);
+extern int drm_resctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_addctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_modctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_getctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_switchctx(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_newctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_rmctx(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv);
+
+extern int drm_ctxbitmap_init(struct drm_device *dev);
+extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
+extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
+
+extern int drm_setsareactx(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int drm_getsareactx(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
 
                                /* Drawable IOCTL support (drm_drawable.h) */
-extern int drm_adddraw(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg);
-extern int drm_rmdraw(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg);
-extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev,
-                                                 drm_drawable_t id);
+extern int drm_adddraw(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern int drm_rmdraw(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_update_drawable_info(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
+                                                      drm_drawable_t id);
+extern void drm_drawable_free_all(struct drm_device *dev);
 
                                /* Authentication IOCTL support (drm_auth.h) */
-extern int drm_getmagic(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_authmagic(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
+extern int drm_getmagic(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_authmagic(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
 
                                /* Locking IOCTL support (drm_lock.h) */
-extern int drm_lock(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg);
-extern int drm_unlock(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int drm_lock_take(drm_lock_data_t *lock_data, unsigned int context);
-extern int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context);
-extern void drm_idlelock_take(drm_lock_data_t *lock_data);
-extern void drm_idlelock_release(drm_lock_data_t *lock_data);
+extern int drm_lock(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv);
+extern int drm_unlock(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
+extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
+extern void drm_idlelock_take(struct drm_lock_data *lock_data);
+extern void drm_idlelock_release(struct drm_lock_data *lock_data);
 
 /*
  * These are exported to drivers so that they can implement fencing using
  * DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
  */
 
-extern int drm_i_have_hw_lock(struct file *filp);
-extern int drm_kernel_take_hw_lock(struct file *filp);
+extern int drm_i_have_hw_lock(struct drm_device *dev,
+                             struct drm_file *file_priv);
 
                                /* Buffer management support (drm_bufs.h) */
-extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addbufs_fb (drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addmap(drm_device_t * dev, unsigned int offset,
-                     unsigned int size, drm_map_type_t type,
-                     drm_map_flags_t flags, drm_local_map_t ** map_ptr);
-extern int drm_addmap_ioctl(struct inode *inode, struct file *filp,
-                           unsigned int cmd, unsigned long arg);
-extern int drm_rmmap(drm_device_t *dev, drm_local_map_t *map);
-extern int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map);
-extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg);
-extern int drm_addbufs(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg);
-extern int drm_infobufs(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_markbufs(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_freebufs(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_mapbufs(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg);
+extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addbufs_fb (struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addmap(struct drm_device *dev, unsigned int offset,
+                     unsigned int size, enum drm_map_type type,
+                     enum drm_map_flags flags, drm_local_map_t ** map_ptr);
+extern int drm_addmap_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int drm_rmmap(struct drm_device *dev, drm_local_map_t *map);
+extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map);
+extern int drm_rmmap_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int drm_addbufs(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern int drm_infobufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_markbufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_freebufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_mapbufs(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
 extern int drm_order(unsigned long size);
-extern unsigned long drm_get_resource_start(drm_device_t *dev,
+extern unsigned long drm_get_resource_start(struct drm_device *dev,
                                            unsigned int resource);
-extern unsigned long drm_get_resource_len(drm_device_t *dev,
+extern unsigned long drm_get_resource_len(struct drm_device *dev,
                                          unsigned int resource);
+extern struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
+                                                 drm_local_map_t *map);
+
 
                                /* DMA support (drm_dma.h) */
-extern int drm_dma_setup(drm_device_t * dev);
-extern void drm_dma_takedown(drm_device_t * dev);
-extern void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf);
-extern void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp);
+extern int drm_dma_setup(struct drm_device *dev);
+extern void drm_dma_takedown(struct drm_device *dev);
+extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf);
+extern void drm_core_reclaim_buffers(struct drm_device *dev,
+                                    struct drm_file *filp);
 
                                /* IRQ support (drm_irq.h) */
-extern int drm_control(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg);
+extern int drm_control(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
 extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-extern int drm_irq_uninstall(drm_device_t *dev);
-extern void drm_driver_irq_preinstall(drm_device_t * dev);
-extern void drm_driver_irq_postinstall(drm_device_t * dev);
-extern void drm_driver_irq_uninstall(drm_device_t * dev);
-
-extern int drm_wait_vblank(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg);
-extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals(drm_device_t * dev);
-extern void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*));
+extern int drm_irq_install(struct drm_device *dev);
+extern int drm_irq_uninstall(struct drm_device *dev);
+extern void drm_driver_irq_preinstall(struct drm_device *dev);
+extern void drm_driver_irq_postinstall(struct drm_device *dev);
+extern void drm_driver_irq_uninstall(struct drm_device *dev);
+
+extern int drm_wait_vblank(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+extern void drm_vbl_send_signals(struct drm_device *dev);
+extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
 
                                /* AGP/GART support (drm_agpsupport.h) */
-extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
-extern int drm_agp_acquire(drm_device_t * dev);
-extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg);
-extern int drm_agp_release(drm_device_t *dev);
-extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg);
-extern int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode);
-extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info);
-extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);
-extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg);
-extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);
-extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
-extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg);
-extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);
-extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
+extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+extern int drm_agp_acquire(struct drm_device *dev);
+extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern int drm_agp_release(struct drm_device *dev);
+extern int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
+extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
+extern int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)
 extern DRM_AGP_MEM *drm_agp_allocate_memory(size_t pages, u32 type);
 #else
@@ -1128,22 +1142,22 @@ extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size
 extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
 extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
 extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
-extern drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev);
+extern struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev);
                                /* Stub support (drm_stub.h) */
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                     struct drm_driver *driver);
-extern int drm_put_dev(drm_device_t * dev);
-extern int drm_put_head(drm_head_t * head);
+extern int drm_put_dev(struct drm_device *dev);
+extern int drm_put_head(struct drm_head * head);
 extern unsigned int drm_debug; /* 1 to enable debug output */
 extern unsigned int drm_cards_limit;
-extern drm_head_t **drm_heads;
-extern struct drm_sysfs_class *drm_class;
+extern struct drm_head **drm_heads;
+extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
 extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
 
                                /* Proc support (drm_proc.h) */
-extern int drm_proc_init(drm_device_t * dev,
+extern int drm_proc_init(struct drm_device *dev,
                         int minor,
                         struct proc_dir_entry *root,
                         struct proc_dir_entry **dev_root);
@@ -1152,48 +1166,48 @@ extern int drm_proc_cleanup(int minor,
                            struct proc_dir_entry *dev_root);
 
                                /* Scatter Gather Support (drm_scatter.h) */
-extern void drm_sg_cleanup(drm_sg_mem_t * entry);
-extern int drm_sg_alloc(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
-extern int drm_sg_free(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg);
+extern void drm_sg_cleanup(struct drm_sg_mem * entry);
+extern int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request);
+extern int drm_sg_free(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
 
                               /* ATI PCIGART support (ati_pcigart.h) */
-extern int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info *gart_info);
-extern int drm_ati_pcigart_cleanup(drm_device_t * dev, drm_ati_pcigart_info *gart_info);
-extern drm_ttm_backend_t *ati_pcigart_init_ttm(struct drm_device *dev, struct ati_pcigart_info *info, void (*gart_flush_fn)(struct drm_device *dev));
+extern int drm_ati_pcigart_init(struct drm_device *dev, struct ati_pcigart_info *gart_info);
+extern int drm_ati_pcigart_cleanup(struct drm_device *dev, struct ati_pcigart_info *gart_info);
+extern struct drm_ttm_backend *ati_pcigart_init_ttm(struct drm_device *dev, struct ati_pcigart_info *info, void (*gart_flush_fn)(struct drm_device *dev));
 
-extern drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size,
+extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
                           size_t align, dma_addr_t maxaddr);
-extern void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah);
-extern void drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah);
+extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah);
+extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah);
 
                               /* sysfs support (drm_sysfs.c) */
 struct drm_sysfs_class;
-extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
-                                               char *name);
-extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
-extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
-                                                drm_head_t * head);
+extern struct class *drm_sysfs_create(struct module *owner, char *name);
+extern void drm_sysfs_destroy(struct class *cs);
+extern struct class_device *drm_sysfs_device_add(struct class *cs,
+                                                struct drm_head * head);
 extern void drm_sysfs_device_remove(struct class_device *class_dev);
 
 /*
  * Basic memory manager support (drm_mm.c)
  */
 
-extern drm_mm_node_t * drm_mm_get_block(drm_mm_node_t * parent, unsigned long size,
+extern struct drm_mm_node * drm_mm_get_block(struct drm_mm_node * parent, unsigned long size,
                                               unsigned alignment);
-extern void drm_mm_put_block(drm_mm_node_t *cur);
-extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size,
+extern void drm_mm_put_block(struct drm_mm_node *cur);
+extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size,
                                                unsigned alignment, int best_match);
-extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
-extern void drm_mm_takedown(drm_mm_t *mm);
-extern int drm_mm_clean(drm_mm_t *mm);
-extern unsigned long drm_mm_tail_space(drm_mm_t *mm);
-extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size);
-extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size);
-
-static inline drm_mm_t *drm_get_mm(drm_mm_node_t *block)
+extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size);
+extern void drm_mm_takedown(struct drm_mm *mm);
+extern int drm_mm_clean(struct drm_mm *mm);
+extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
+extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
+extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
+
+static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
 {
        return block->mm;
 }
@@ -1204,14 +1218,14 @@ extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
 static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
                                                   unsigned int token)
 {
-       drm_map_list_t *_entry;
+       struct drm_map_list *_entry;
        list_for_each_entry(_entry, &dev->maplist, head)
                if (_entry->user_token == token)
                        return _entry->map;
        return NULL;
 }
 
-static __inline__ int drm_device_is_agp(drm_device_t *dev)
+static __inline__ int drm_device_is_agp(struct drm_device *dev)
 {
        if ( dev->driver->device_is_agp != NULL ) {
                int err = (*dev->driver->device_is_agp)( dev );
@@ -1224,7 +1238,7 @@ static __inline__ int drm_device_is_agp(drm_device_t *dev)
        return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
 
-static __inline__ int drm_device_is_pcie(drm_device_t *dev)
+static __inline__ int drm_device_is_pcie(struct drm_device *dev)
 {
        return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
 }
@@ -1285,5 +1299,19 @@ static inline void drm_ctl_free(void *pt, size_t size, int area)
 
 /*@}*/
 
+/** Type for the OS's non-sleepable mutex lock */
+#define DRM_SPINTYPE           spinlock_t
+/**
+ * Initialize the lock for use.  name is an optional string describing the
+ * lock
+ */
+#define DRM_SPININIT(l,name)   spin_lock_init(l)
+#define DRM_SPINUNINIT(l)
+#define DRM_SPINLOCK(l)                spin_lock(l)
+#define DRM_SPINUNLOCK(l)      spin_unlock(l)
+#define DRM_SPINLOCK_IRQSAVE(l, _flags)        spin_lock_irqsave(l, _flags);
+#define DRM_SPINUNLOCK_IRQRESTORE(l, _flags) spin_unlock_irqrestore(l, _flags);
+#define DRM_SPINLOCK_ASSERT(l)         do {} while (0) 
+
 #endif                         /* __KERNEL__ */
 #endif
index f134563..b68efc6 100644 (file)
@@ -40,7 +40,7 @@
  * Get AGP information.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a (output) drm_agp_info structure.
  * \return zero on success or a negative number on failure.
@@ -48,7 +48,7 @@
  * Verifies the AGP device has been initialized and acquired and fills in the
  * drm_agp_info structure with the information in drm_agp_head::agp_info.
  */
-int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
+int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info)
 {
        DRM_AGP_KERN *kern;
 
@@ -70,20 +70,16 @@ int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
 }
 EXPORT_SYMBOL(drm_agp_info);
 
-int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_agp_info_t info;
+       struct drm_agp_info *info = data;
        int err;
 
-       err = drm_agp_info(dev, &info);
+       err = drm_agp_info(dev, info);
        if (err)
                return err;
-       
-       if (copy_to_user((drm_agp_info_t __user *) arg, &info, sizeof(info)))
-               return -EFAULT;
+
        return 0;
 }
 
@@ -96,7 +92,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
  * Verifies the AGP device hasn't been acquired before and calls
  * \c agp_backend_acquire.
  */
-int drm_agp_acquire(drm_device_t * dev)
+int drm_agp_acquire(struct drm_device * dev)
 {
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)
        int retcode;
@@ -123,7 +119,7 @@ EXPORT_SYMBOL(drm_agp_acquire);
  * Acquire the AGP device (ioctl).
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument.
  * \return zero on success or a negative number on failure.
@@ -131,12 +127,10 @@ EXPORT_SYMBOL(drm_agp_acquire);
  * Verifies the AGP device hasn't been acquired before and calls
  * \c agp_backend_acquire.
  */
-int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg)
+int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       
-       return drm_agp_acquire( (drm_device_t *) priv->head->dev );
+       return drm_agp_acquire( (struct drm_device *) file_priv->head->dev );
 }
 
 /**
@@ -147,7 +141,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
  *
  * Verifies the AGP device has been acquired and calls \c agp_backend_release.
  */
-int drm_agp_release(drm_device_t *dev)
+int drm_agp_release(struct drm_device *dev)
 {
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
@@ -162,12 +156,9 @@ int drm_agp_release(drm_device_t *dev)
 }
 EXPORT_SYMBOL(drm_agp_release);
 
-int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg)
+int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       
        return drm_agp_release(dev);
 }
 
@@ -181,7 +172,7 @@ int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
  * Verifies the AGP device has been acquired but not enabled, and calls
  * \c agp_enable.
  */
-int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
+int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
 {
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
@@ -192,31 +183,24 @@ int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
 #else
        agp_enable(dev->agp->bridge, mode.mode);
 #endif
-       dev->agp->base = dev->agp->agp_info.aper_base;
        dev->agp->enabled = 1;
        return 0;
 }
 EXPORT_SYMBOL(drm_agp_enable);
 
-int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
-                  unsigned int cmd, unsigned long arg)
+int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_agp_mode_t mode;
-
+       struct drm_agp_mode *mode = data;
 
-       if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
-               return -EFAULT;
-
-       return drm_agp_enable(dev, mode);
+       return drm_agp_enable(dev, *mode);
 }
 
 /**
  * Allocate AGP memory.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv file private pointer.
  * \param cmd command.
  * \param arg pointer to a drm_agp_buffer structure.
  * \return zero on success or a negative number on failure.
@@ -224,9 +208,9 @@ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
  * Verifies the AGP device is present and has been acquired, allocates the
  * memory via alloc_agp() and creates a drm_agp_mem entry for it.
  */
-int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
 {
-       drm_agp_mem_t *entry;
+       struct drm_agp_mem *entry;
        DRM_AGP_MEM *memory;
        unsigned long pages;
        u32 type;
@@ -259,35 +243,12 @@ int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
 EXPORT_SYMBOL(drm_agp_alloc);
 
 
-int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg)
+int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_agp_buffer_t request;
-       drm_agp_buffer_t __user *argp = (void __user *)arg;
-       int err;
-
-       if (copy_from_user(&request, argp, sizeof(request)))
-               return -EFAULT;
+       struct drm_agp_buffer *request = data;
 
-       err = drm_agp_alloc(dev, &request);
-       if (err)
-               return err;
-
-       if (copy_to_user(argp, &request, sizeof(request))) {
-               drm_agp_mem_t *entry;
-               list_for_each_entry(entry, &dev->agp->memory, head) {
-                       if (entry->handle == request.handle)
-                               break;
-               }
-               list_del(&entry->head);
-               drm_free_agp(entry->memory, entry->pages);
-               drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-               return -EFAULT;
-       }
-
-       return 0;
+       return drm_agp_alloc(dev, request);
 }
 
 /**
@@ -299,10 +260,10 @@ int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
  *
  * Walks through drm_agp_head::memory until finding a matching handle.
  */
-static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
+static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
                                           unsigned long handle)
 {
-       drm_agp_mem_t *entry;
+       struct drm_agp_mem *entry;
 
        list_for_each_entry(entry, &dev->agp->memory, head) {
                if (entry->handle == handle)
@@ -315,7 +276,7 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
  * Unbind AGP memory from the GATT (ioctl).
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_agp_binding structure.
  * \return zero on success or a negative number on failure.
@@ -323,9 +284,9 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
  * Verifies the AGP device is present and acquired, looks-up the AGP memory
  * entry and passes it to the unbind_agp() function.
  */
-int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
 {
-       drm_agp_mem_t *entry;
+       struct drm_agp_mem *entry;
        int ret;
 
        if (!dev->agp || !dev->agp->acquired)
@@ -342,18 +303,12 @@ int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
 EXPORT_SYMBOL(drm_agp_unbind);
 
 
-int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg)
+int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_agp_binding_t request;
-
-       if (copy_from_user
-           (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
-               return -EFAULT;
+       struct drm_agp_binding *request = data;
 
-       return drm_agp_unbind(dev, &request);
+       return drm_agp_unbind(dev, request);
 }
 
 
@@ -361,7 +316,7 @@ int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
  * Bind AGP memory into the GATT (ioctl)
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_agp_binding structure.
  * \return zero on success or a negative number on failure.
@@ -370,9 +325,9 @@ int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
  * is currently bound into the GATT. Looks-up the AGP memory entry and passes
  * it to bind_agp() function.
  */
-int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
 {
-       drm_agp_mem_t *entry;
+       struct drm_agp_mem *entry;
        int retcode;
        int page;
 
@@ -393,18 +348,12 @@ int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
 EXPORT_SYMBOL(drm_agp_bind);
 
 
-int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg)
+int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_agp_binding_t request;
+       struct drm_agp_binding *request = data;
 
-       if (copy_from_user
-           (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
-               return -EFAULT;
-
-       return drm_agp_bind(dev, &request);
+       return drm_agp_bind(dev, request);
 }
 
 
@@ -412,7 +361,7 @@ int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
  * Free AGP memory (ioctl).
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_agp_buffer structure.
  * \return zero on success or a negative number on failure.
@@ -422,9 +371,9 @@ int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
  * unbind_agp(). Frees it via free_agp() as well as the entry itself
  * and unlinks from the doubly linked list it's inserted in.
  */
-int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
 {
-       drm_agp_mem_t *entry;
+       struct drm_agp_mem *entry;
 
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
@@ -443,18 +392,12 @@ EXPORT_SYMBOL(drm_agp_free);
 
 
 
-int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg)
+int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_agp_buffer_t request;
-
-       if (copy_from_user
-           (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
-               return -EFAULT;
+       struct drm_agp_buffer *request = data;
 
-       return drm_agp_free(dev, &request);
+       return drm_agp_free(dev, request);
 }
 
 
@@ -467,9 +410,9 @@ int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
  * via the inter_module_* functions. Creates and initializes a drm_agp_head
  * structure.
  */
-drm_agp_head_t *drm_agp_init(drm_device_t *dev)
+struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 {
-       drm_agp_head_t *head = NULL;
+       struct drm_agp_head *head = NULL;
 
        if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
                return NULL;
@@ -497,6 +440,7 @@ drm_agp_head_t *drm_agp_init(drm_device_t *dev)
        INIT_LIST_HEAD(&head->memory);
        head->cant_use_aperture = head->agp_info.cant_use_aperture;
        head->page_mask = head->agp_info.page_mask;
+       head->base = head->agp_info.aper_base;
        return head;
 }
 
@@ -554,16 +498,16 @@ int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
 #define AGP_REQUIRED_MAJOR 0
 #define AGP_REQUIRED_MINOR 102
 
-static int drm_agp_needs_unbind_cache_adjust(drm_ttm_backend_t *backend) {
+static int drm_agp_needs_unbind_cache_adjust(struct drm_ttm_backend *backend) {
        return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
 }
 
 
-static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages,
+static int drm_agp_populate(struct drm_ttm_backend *backend, unsigned long num_pages,
                            struct page **pages) {
 
-       drm_agp_ttm_backend_t *agp_be = 
-               container_of(backend, drm_agp_ttm_backend_t, backend);
+       struct drm_agp_ttm_backend *agp_be = 
+               container_of(backend, struct drm_agp_ttm_backend, backend);
        struct page **cur_page, **last_page = pages + num_pages;
        DRM_AGP_MEM *mem;
 
@@ -590,32 +534,32 @@ static int drm_agp_populate(drm_ttm_backend_t *backend, unsigned long num_pages,
        return 0;
 }
 
-static int drm_agp_bind_ttm(drm_ttm_backend_t *backend,
-                           unsigned long offset,
-                           int cached)
+static int drm_agp_bind_ttm(struct drm_ttm_backend *backend,
+                           struct drm_bo_mem_reg *bo_mem)
 {
-       drm_agp_ttm_backend_t *agp_be = 
-               container_of(backend, drm_agp_ttm_backend_t, backend);
+       struct drm_agp_ttm_backend *agp_be =
+               container_of(backend, struct drm_agp_ttm_backend, backend);
        DRM_AGP_MEM *mem = agp_be->mem;
        int ret;
 
        DRM_DEBUG("drm_agp_bind_ttm\n");
        mem->is_flushed = TRUE;
-       mem->type = (cached) ? AGP_USER_CACHED_MEMORY : 
+       mem->type = (bo_mem->flags & DRM_BO_FLAG_CACHED) ? AGP_USER_CACHED_MEMORY :
                AGP_USER_MEMORY;
-       ret = drm_agp_bind_memory(mem, offset);
+       ret = drm_agp_bind_memory(mem, bo_mem->mm_node->start);
        if (ret) {
                DRM_ERROR("AGP Bind memory failed\n");
        }
-       DRM_FLAG_MASKED(backend->flags, (cached) ? DRM_BE_FLAG_BOUND_CACHED : 0,
+       DRM_FLAG_MASKED(backend->flags, (bo_mem->flags & DRM_BO_FLAG_CACHED) ?
+                       DRM_BE_FLAG_BOUND_CACHED : 0,
                        DRM_BE_FLAG_BOUND_CACHED);
        return ret;
 }
 
-static int drm_agp_unbind_ttm(drm_ttm_backend_t *backend) {
+static int drm_agp_unbind_ttm(struct drm_ttm_backend *backend) {
 
-       drm_agp_ttm_backend_t *agp_be = 
-               container_of(backend, drm_agp_ttm_backend_t, backend);
+       struct drm_agp_ttm_backend *agp_be = 
+               container_of(backend, struct drm_agp_ttm_backend, backend);
 
        DRM_DEBUG("drm_agp_unbind_ttm\n");
        if (agp_be->mem->is_bound)
@@ -624,10 +568,10 @@ static int drm_agp_unbind_ttm(drm_ttm_backend_t *backend) {
                return 0;
 }
 
-static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) {
+static void drm_agp_clear_ttm(struct drm_ttm_backend *backend) {
 
-       drm_agp_ttm_backend_t *agp_be = 
-               container_of(backend, drm_agp_ttm_backend_t, backend);
+       struct drm_agp_ttm_backend *agp_be = 
+               container_of(backend, struct drm_agp_ttm_backend, backend);
        DRM_AGP_MEM *mem = agp_be->mem;
 
        DRM_DEBUG("drm_agp_clear_ttm\n");
@@ -640,13 +584,13 @@ static void drm_agp_clear_ttm(drm_ttm_backend_t *backend) {
        agp_be->mem = NULL;
 }
 
-static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) {
+static void drm_agp_destroy_ttm(struct drm_ttm_backend *backend) {
 
-       drm_agp_ttm_backend_t *agp_be;
+       struct drm_agp_ttm_backend *agp_be;
 
        if (backend) {
                DRM_DEBUG("drm_agp_destroy_ttm\n");
-               agp_be = container_of(backend, drm_agp_ttm_backend_t, backend);
+               agp_be = container_of(backend, struct drm_agp_ttm_backend, backend);
                if (agp_be) {
                        if (agp_be->mem) {
                                backend->func->clear(backend);
@@ -656,7 +600,7 @@ static void drm_agp_destroy_ttm(drm_ttm_backend_t *backend) {
        }
 }
 
-static drm_ttm_backend_func_t agp_ttm_backend = 
+static struct drm_ttm_backend_func agp_ttm_backend = 
 {
        .needs_ub_cache_adjust = drm_agp_needs_unbind_cache_adjust,
        .populate = drm_agp_populate,
@@ -666,10 +610,10 @@ static drm_ttm_backend_func_t agp_ttm_backend =
        .destroy =  drm_agp_destroy_ttm,
 };
 
-drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev)
+struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev)
 {
 
-       drm_agp_ttm_backend_t *agp_be;
+       struct drm_agp_ttm_backend *agp_be;
        struct agp_kern_info *info;
 
        if (!dev->agp) {
@@ -699,7 +643,8 @@ drm_ttm_backend_t *drm_agp_init_ttm(struct drm_device *dev)
        agp_be->bridge = dev->agp->bridge;
        agp_be->populated = FALSE;
        agp_be->backend.func = &agp_ttm_backend;
-       agp_be->backend.mem_type = DRM_BO_MEM_TT;
+       //      agp_be->backend.mem_type = DRM_BO_MEM_TT;
+       agp_be->backend.dev = dev;
 
        return &agp_be->backend;
 }
index 6948d85..e35e8b6 100644 (file)
  * the one with matching magic number, while holding the drm_device::struct_mutex
  * lock.
  */
-static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
 {
-       drm_file_t *retval = NULL;
-       drm_magic_entry_t *pt;
-       drm_hash_item_t *hash;
+       struct drm_file *retval = NULL;
+       struct drm_magic_entry *pt;
+       struct drm_hash_item *hash;
 
-       mutex_lock(&dev->struct_mutex); 
-       if (!drm_ht_find_item(&dev->magiclist, (unsigned long) magic, &hash)) {
-               pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+       mutex_lock(&dev->struct_mutex);
+       if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+               pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
                retval = pt->priv;
        }
        mutex_unlock(&dev->struct_mutex);
@@ -71,10 +71,10 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic)
  * associated the magic number hash key in drm_device::magiclist, while holding
  * the drm_device::struct_mutex lock.
  */
-static int drm_add_magic(drm_device_t *dev, drm_file_t *priv,
+static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
                         drm_magic_t magic)
 {
-       drm_magic_entry_t *entry;
+       struct drm_magic_entry *entry;
 
        DRM_DEBUG("%d\n", magic);
 
@@ -101,10 +101,10 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv,
  * Searches and unlinks the entry in drm_device::magiclist with the magic
  * number hash key, while holding the drm_device::struct_mutex lock.
  */
-static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
+static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
 {
-       drm_magic_entry_t *pt;
-       drm_hash_item_t *hash;
+       struct drm_magic_entry *pt;
+       struct drm_hash_item *hash;
 
        DRM_DEBUG("%d\n", magic);
 
@@ -113,7 +113,7 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
                mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
        }
-       pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item);
+       pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
        drm_ht_remove_item(&dev->magiclist, hash);
        list_del(&pt->head);
        mutex_unlock(&dev->struct_mutex);
@@ -127,42 +127,38 @@ static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic)
  * Get a unique magic number (ioctl).
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a resulting drm_auth structure.
  * \return zero on success, or a negative number on failure.
  *
  * If there is a magic number in drm_file::magic then use it, otherwise
  * searches an unique non-zero magic number and add it associating it with \p
- * filp.
+ * file_priv.
  */
-int drm_getmagic(struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        static drm_magic_t sequence = 0;
        static DEFINE_SPINLOCK(lock);
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_auth_t auth;
+       struct drm_auth *auth = data;
 
        /* Find unique magic */
-       if (priv->magic) {
-               auth.magic = priv->magic;
+       if (file_priv->magic) {
+               auth->magic = file_priv->magic;
        } else {
                do {
                        spin_lock(&lock);
                        if (!sequence)
                                ++sequence;     /* reserve 0 */
-                       auth.magic = sequence++;
+                       auth->magic = sequence++;
                        spin_unlock(&lock);
-               } while (drm_find_file(dev, auth.magic));
-               priv->magic = auth.magic;
-               drm_add_magic(dev, priv, auth.magic);
+               } while (drm_find_file(dev, auth->magic));
+               file_priv->magic = auth->magic;
+               drm_add_magic(dev, file_priv, auth->magic);
        }
 
-       DRM_DEBUG("%u\n", auth.magic);
-       if (copy_to_user((drm_auth_t __user *) arg, &auth, sizeof(auth)))
-               return -EFAULT;
+       DRM_DEBUG("%u\n", auth->magic);
+
        return 0;
 }
 
@@ -170,27 +166,23 @@ int drm_getmagic(struct inode *inode, struct file *filp,
  * Authenticate with a magic.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_auth structure.
  * \return zero if authentication successed, or a negative number otherwise.
  *
- * Checks if \p filp is associated with the magic number passed in \arg.
+ * Checks if \p file_priv is associated with the magic number passed in \arg.
  */
-int drm_authmagic(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int drm_authmagic(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_auth_t auth;
-       drm_file_t *file;
-
-       if (copy_from_user(&auth, (drm_auth_t __user *) arg, sizeof(auth)))
-               return -EFAULT;
-       DRM_DEBUG("%u\n", auth.magic);
-       if ((file = drm_find_file(dev, auth.magic))) {
+       struct drm_auth *auth = data;
+       struct drm_file *file;
+
+       DRM_DEBUG("%u\n", auth->magic);
+       if ((file = drm_find_file(dev, auth->magic))) {
                file->authenticated = 1;
-               drm_remove_magic(dev, auth.magic);
+               drm_remove_magic(dev, auth->magic);
                return 0;
        }
        return -EINVAL;
index 1c7013b..04900fe 100644 (file)
  *
  */
 
-static void drm_bo_destroy_locked(drm_buffer_object_t * bo);
-static int drm_bo_setup_vm_locked(drm_buffer_object_t * bo);
-static void drm_bo_takedown_vm_locked(drm_buffer_object_t * bo);
-static void drm_bo_unmap_virtual(drm_buffer_object_t * bo);
+static void drm_bo_destroy_locked(struct drm_buffer_object * bo);
+static int drm_bo_setup_vm_locked(struct drm_buffer_object * bo);
+static void drm_bo_takedown_vm_locked(struct drm_buffer_object * bo);
+static void drm_bo_unmap_virtual(struct drm_buffer_object * bo);
 
-static inline uint32_t drm_bo_type_flags(unsigned type)
+static inline uint64_t drm_bo_type_flags(unsigned type)
 {
-       return (1 << (24 + type));
+       return (1ULL << (24 + type));
 }
 
 /*
  * bo locked. dev->struct_mutex locked.
  */
 
-void drm_bo_add_to_pinned_lru(drm_buffer_object_t * bo)
+void drm_bo_add_to_pinned_lru(struct drm_buffer_object * bo)
 {
-       drm_mem_type_manager_t *man;
+       struct drm_mem_type_manager *man;
+
+       DRM_ASSERT_LOCKED(&bo->dev->struct_mutex);
+       DRM_ASSERT_LOCKED(&bo->mutex);
 
        man = &bo->dev->bm.man[bo->pinned_mem_type];
        list_add_tail(&bo->pinned_lru, &man->pinned);
 }
 
-void drm_bo_add_to_lru(drm_buffer_object_t * bo)
+void drm_bo_add_to_lru(struct drm_buffer_object * bo)
 {
-       drm_mem_type_manager_t *man;
+       struct drm_mem_type_manager *man;
+
+       DRM_ASSERT_LOCKED(&bo->dev->struct_mutex);
 
        if (!(bo->mem.mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))
            || bo->mem.mem_type != bo->pinned_mem_type) {
@@ -84,7 +89,7 @@ void drm_bo_add_to_lru(drm_buffer_object_t * bo)
        }
 }
 
-static int drm_bo_vm_pre_move(drm_buffer_object_t * bo, int old_is_pci)
+static int drm_bo_vm_pre_move(struct drm_buffer_object * bo, int old_is_pci)
 {
 #ifdef DRM_ODD_MM_COMPAT
        int ret;
@@ -107,7 +112,7 @@ static int drm_bo_vm_pre_move(drm_buffer_object_t * bo, int old_is_pci)
        return 0;
 }
 
-static void drm_bo_vm_post_move(drm_buffer_object_t * bo)
+static void drm_bo_vm_post_move(struct drm_buffer_object * bo)
 {
 #ifdef DRM_ODD_MM_COMPAT
        int ret;
@@ -128,25 +133,22 @@ static void drm_bo_vm_post_move(drm_buffer_object_t * bo)
  * Call bo->mutex locked.
  */
 
-static int drm_bo_add_ttm(drm_buffer_object_t * bo)
+static int drm_bo_add_ttm(struct drm_buffer_object * bo)
 {
-       drm_device_t *dev = bo->dev;
+       struct drm_device *dev = bo->dev;
        int ret = 0;
        bo->ttm = NULL;
 
+       DRM_ASSERT_LOCKED(&bo->mutex);
+
        switch (bo->type) {
        case drm_bo_type_dc:
-               bo->ttm = drm_ttm_init(dev, bo->mem.num_pages << PAGE_SHIFT);
-               if (!bo->ttm)
-                       ret = -ENOMEM;
-               break;
        case drm_bo_type_kernel:
-               bo->ttm = drm_ttm_init(dev, bo->mem.num_pages << PAGE_SHIFT);
+               bo->ttm = drm_ttm_init(dev, bo->num_pages << PAGE_SHIFT);
                if (!bo->ttm)
                        ret = -ENOMEM;
                break;
        case drm_bo_type_user:
-       case drm_bo_type_fake:
                break;
        default:
                DRM_ERROR("Illegal buffer object type\n");
@@ -157,19 +159,20 @@ static int drm_bo_add_ttm(drm_buffer_object_t * bo)
        return ret;
 }
 
-static int drm_bo_handle_move_mem(drm_buffer_object_t * bo,
-                                 drm_bo_mem_reg_t * mem,
+static int drm_bo_handle_move_mem(struct drm_buffer_object * bo,
+                                 struct drm_bo_mem_reg * mem,
                                  int evict, int no_wait)
 {
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
        int old_is_pci = drm_mem_reg_is_pci(dev, &bo->mem);
        int new_is_pci = drm_mem_reg_is_pci(dev, mem);
-       drm_mem_type_manager_t *old_man = &bm->man[bo->mem.mem_type];
-       drm_mem_type_manager_t *new_man = &bm->man[mem->mem_type];
+       struct drm_mem_type_manager *old_man = &bm->man[bo->mem.mem_type];
+       struct drm_mem_type_manager *new_man = &bm->man[mem->mem_type];
        int ret = 0;
 
-       if (old_is_pci || new_is_pci)
+       if (old_is_pci || new_is_pci ||
+           ((mem->flags ^ bo->mem.flags) & DRM_BO_FLAG_CACHED))
                ret = drm_bo_vm_pre_move(bo, old_is_pci);
        if (ret)
                return ret;
@@ -184,9 +187,7 @@ static int drm_bo_handle_move_mem(drm_buffer_object_t * bo,
                        goto out_err;
 
                if (mem->mem_type != DRM_BO_MEM_LOCAL) {
-                       ret = drm_bind_ttm(bo->ttm, new_man->flags &
-                                          DRM_BO_FLAG_CACHED,
-                                          mem->mm_node->start);
+                       ret = drm_bind_ttm(bo->ttm, mem);
                        if (ret)
                                goto out_err;
                }
@@ -194,9 +195,9 @@ static int drm_bo_handle_move_mem(drm_buffer_object_t * bo,
 
        if ((bo->mem.mem_type == DRM_BO_MEM_LOCAL) && bo->ttm == NULL) {
 
-               drm_bo_mem_reg_t *old_mem = &bo->mem;
-               uint32_t save_flags = old_mem->flags;
-               uint32_t save_mask = old_mem->mask;
+               struct drm_bo_mem_reg *old_mem = &bo->mem;
+               uint64_t save_flags = old_mem->flags;
+               uint64_t save_mask = old_mem->mask;
 
                *old_mem = *mem;
                mem->mm_node = NULL;
@@ -236,7 +237,9 @@ static int drm_bo_handle_move_mem(drm_buffer_object_t * bo,
                        _DRM_BO_FLAG_EVICTED);
 
        if (bo->mem.mm_node)
-               bo->offset = bo->mem.mm_node->start << PAGE_SHIFT;
+               bo->offset = (bo->mem.mm_node->start << PAGE_SHIFT) +
+                       bm->man[bo->mem.mem_type].gpu_offset;
+
 
        return 0;
 
@@ -259,40 +262,37 @@ static int drm_bo_handle_move_mem(drm_buffer_object_t * bo,
  * Wait until the buffer is idle.
  */
 
-int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
+int drm_bo_wait(struct drm_buffer_object * bo, int lazy, int ignore_signals,
                int no_wait)
 {
-
-       drm_fence_object_t *fence = bo->fence;
        int ret;
 
-       if (fence) {
-               drm_device_t *dev = bo->dev;
-               if (drm_fence_object_signaled(fence, bo->fence_type)) {
-                       drm_fence_usage_deref_unlocked(dev, fence);
-                       bo->fence = NULL;
+       DRM_ASSERT_LOCKED(&bo->mutex);
+
+       if (bo->fence) {
+               if (drm_fence_object_signaled(bo->fence, bo->fence_type, 0)) {
+                       drm_fence_usage_deref_unlocked(&bo->fence);
                        return 0;
                }
                if (no_wait) {
                        return -EBUSY;
                }
                ret =
-                   drm_fence_object_wait(dev, fence, lazy, ignore_signals,
+                   drm_fence_object_wait(bo->fence, lazy, ignore_signals,
                                          bo->fence_type);
                if (ret)
                        return ret;
 
-               drm_fence_usage_deref_unlocked(dev, fence);
-               bo->fence = NULL;
-
+               drm_fence_usage_deref_unlocked(&bo->fence);
        }
        return 0;
 }
+EXPORT_SYMBOL(drm_bo_wait);
 
-static int drm_bo_expire_fence(drm_buffer_object_t * bo, int allow_errors)
+static int drm_bo_expire_fence(struct drm_buffer_object * bo, int allow_errors)
 {
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
 
        if (bo->fence) {
                if (bm->nice_mode) {
@@ -312,10 +312,8 @@ static int drm_bo_expire_fence(drm_buffer_object_t * bo, int allow_errors)
                                          "Evicting buffer.\n");
                        }
                }
-               if (bo->fence) {
-                       drm_fence_usage_deref_unlocked(dev, bo->fence);
-                       bo->fence = NULL;
-               }
+               if (bo->fence)
+                       drm_fence_usage_deref_unlocked(&bo->fence);
        }
        return 0;
 }
@@ -326,10 +324,12 @@ static int drm_bo_expire_fence(drm_buffer_object_t * bo, int allow_errors)
  * fence object and removing from lru lists and memory managers.
  */
 
-static void drm_bo_cleanup_refs(drm_buffer_object_t * bo, int remove_all)
+static void drm_bo_cleanup_refs(struct drm_buffer_object * bo, int remove_all)
 {
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
+
+       DRM_ASSERT_LOCKED(&dev->struct_mutex);
 
        atomic_inc(&bo->usage);
        mutex_unlock(&dev->struct_mutex);
@@ -337,10 +337,9 @@ static void drm_bo_cleanup_refs(drm_buffer_object_t * bo, int remove_all)
 
        DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
 
-       if (bo->fence && drm_fence_object_signaled(bo->fence, bo->fence_type)) {
-               drm_fence_usage_deref_locked(dev, bo->fence);
-               bo->fence = NULL;
-       }
+       if (bo->fence && drm_fence_object_signaled(bo->fence,
+                                                  bo->fence_type, 0))
+               drm_fence_usage_deref_unlocked(&bo->fence);
 
        if (bo->fence && remove_all)
                (void)drm_bo_expire_fence(bo, 0);
@@ -371,7 +370,7 @@ static void drm_bo_cleanup_refs(drm_buffer_object_t * bo, int remove_all)
        }
 
        if (list_empty(&bo->ddestroy)) {
-               drm_fence_object_flush(dev, bo->fence, bo->fence_type);
+               drm_fence_object_flush(bo->fence, bo->fence_type);
                list_add_tail(&bo->ddestroy, &bm->ddestroy);
                schedule_delayed_work(&bm->wq,
                                      ((DRM_HZ / 100) < 1) ? 1 : DRM_HZ / 100);
@@ -387,10 +386,12 @@ static void drm_bo_cleanup_refs(drm_buffer_object_t * bo, int remove_all)
  * to the buffer object. Then destroy it.
  */
 
-static void drm_bo_destroy_locked(drm_buffer_object_t * bo)
+static void drm_bo_destroy_locked(struct drm_buffer_object * bo)
 {
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
+
+       DRM_ASSERT_LOCKED(&dev->struct_mutex);
 
        if (list_empty(&bo->lru) && bo->mem.mm_node == NULL &&
            list_empty(&bo->pinned_lru) && bo->pinned_node == NULL &&
@@ -433,19 +434,19 @@ static void drm_bo_destroy_locked(drm_buffer_object_t * bo)
  * Call dev->struct_mutex locked.
  */
 
-static void drm_bo_delayed_delete(drm_device_t * dev, int remove_all)
+static void drm_bo_delayed_delete(struct drm_device * dev, int remove_all)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_buffer_manager *bm = &dev->bm;
 
-       drm_buffer_object_t *entry, *nentry;
+       struct drm_buffer_object *entry, *nentry;
        struct list_head *list, *next;
 
        list_for_each_safe(list, next, &bm->ddestroy) {
-               entry = list_entry(list, drm_buffer_object_t, ddestroy);
+               entry = list_entry(list, struct drm_buffer_object, ddestroy);
 
                nentry = NULL;
                if (next != &bm->ddestroy) {
-                       nentry = list_entry(next, drm_buffer_object_t,
+                       nentry = list_entry(next, struct drm_buffer_object,
                                            ddestroy);
                        atomic_inc(&nentry->usage);
                }
@@ -465,12 +466,12 @@ static void drm_bo_delayed_workqueue(struct work_struct *work)
 #endif
 {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-       drm_device_t *dev = (drm_device_t *) data;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_device *dev = (struct drm_device *) data;
+       struct drm_buffer_manager *bm = &dev->bm;
 #else
-       drm_buffer_manager_t *bm =
-           container_of(work, drm_buffer_manager_t, wq.work);
-       drm_device_t *dev = container_of(bm, drm_device_t, bm);
+       struct drm_buffer_manager *bm =
+           container_of(work, struct drm_buffer_manager, wq.work);
+       struct drm_device *dev = container_of(bm, struct drm_device, bm);
 #endif
 
        DRM_DEBUG("Delayed delete Worker\n");
@@ -488,66 +489,116 @@ static void drm_bo_delayed_workqueue(struct work_struct *work)
        mutex_unlock(&dev->struct_mutex);
 }
 
-void drm_bo_usage_deref_locked(drm_buffer_object_t * bo)
+void drm_bo_usage_deref_locked(struct drm_buffer_object ** bo)
 {
-       if (atomic_dec_and_test(&bo->usage)) {
-               drm_bo_destroy_locked(bo);
+        struct drm_buffer_object *tmp_bo = *bo;
+       bo = NULL;
+
+       DRM_ASSERT_LOCKED(&tmp_bo->dev->struct_mutex);
+
+       if (atomic_dec_and_test(&tmp_bo->usage)) {
+               drm_bo_destroy_locked(tmp_bo);
        }
 }
+EXPORT_SYMBOL(drm_bo_usage_deref_locked);
 
-static void drm_bo_base_deref_locked(drm_file_t * priv, drm_user_object_t * uo)
+static void drm_bo_base_deref_locked(struct drm_file * file_priv,
+                                    struct drm_user_object * uo)
 {
-       drm_buffer_object_t *bo =
-           drm_user_object_entry(uo, drm_buffer_object_t, base);
+       struct drm_buffer_object *bo =
+           drm_user_object_entry(uo, struct drm_buffer_object, base);
+
+       DRM_ASSERT_LOCKED(&bo->dev->struct_mutex);
 
        drm_bo_takedown_vm_locked(bo);
-       drm_bo_usage_deref_locked(bo);
+       drm_bo_usage_deref_locked(&bo);
 }
 
-static void drm_bo_usage_deref_unlocked(drm_buffer_object_t * bo)
+void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo)
 {
-       drm_device_t *dev = bo->dev;
+       struct drm_buffer_object *tmp_bo = *bo;
+       struct drm_device *dev = tmp_bo->dev;
 
-       if (atomic_dec_and_test(&bo->usage)) {
+       *bo = NULL;
+       if (atomic_dec_and_test(&tmp_bo->usage)) {
                mutex_lock(&dev->struct_mutex);
-               if (atomic_read(&bo->usage) == 0)
-                       drm_bo_destroy_locked(bo);
+               if (atomic_read(&tmp_bo->usage) == 0)
+                       drm_bo_destroy_locked(tmp_bo);
+               mutex_unlock(&dev->struct_mutex);
+       }
+}
+EXPORT_SYMBOL(drm_bo_usage_deref_unlocked);
+
+void drm_putback_buffer_objects(struct drm_device *dev)
+{
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct list_head *list = &bm->unfenced;
+       struct drm_buffer_object *entry, *next;
+
+       mutex_lock(&dev->struct_mutex);
+       list_for_each_entry_safe(entry, next, list, lru) {
+               atomic_inc(&entry->usage);
                mutex_unlock(&dev->struct_mutex);
+
+               mutex_lock(&entry->mutex);
+               BUG_ON(!(entry->priv_flags & _DRM_BO_FLAG_UNFENCED));
+               mutex_lock(&dev->struct_mutex);
+
+               list_del_init(&entry->lru);
+               DRM_FLAG_MASKED(entry->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
+               DRM_WAKEUP(&entry->event_queue);
+
+               /*
+                * FIXME: Might want to put back on head of list
+                * instead of tail here.
+                */
+
+               drm_bo_add_to_lru(entry);
+               mutex_unlock(&entry->mutex);
+               drm_bo_usage_deref_locked(&entry);
        }
+       mutex_unlock(&dev->struct_mutex);
 }
+EXPORT_SYMBOL(drm_putback_buffer_objects);
+
 
 /*
  * Note. The caller has to register (if applicable)
  * and deregister fence object usage.
  */
 
-int drm_fence_buffer_objects(drm_file_t * priv,
+int drm_fence_buffer_objects(struct drm_device *dev,
                             struct list_head *list,
                             uint32_t fence_flags,
-                            drm_fence_object_t * fence,
-                            drm_fence_object_t ** used_fence)
+                            struct drm_fence_object * fence,
+                            struct drm_fence_object ** used_fence)
 {
-       drm_device_t *dev = priv->head->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
-
-       drm_buffer_object_t *entry;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_buffer_object *entry;
        uint32_t fence_type = 0;
+       uint32_t fence_class = ~0;
        int count = 0;
        int ret = 0;
        struct list_head *l;
-       LIST_HEAD(f_list);
 
        mutex_lock(&dev->struct_mutex);
 
        if (!list)
                list = &bm->unfenced;
 
+       if (fence)
+               fence_class = fence->fence_class;
+
        list_for_each_entry(entry, list, lru) {
                BUG_ON(!(entry->priv_flags & _DRM_BO_FLAG_UNFENCED));
-               fence_type |= entry->fence_type;
-               if (entry->fence_class != 0) {
-                       DRM_ERROR("Fence class %d is not implemented yet.\n",
-                                 entry->fence_class);
+               fence_type |= entry->new_fence_type;
+               if (fence_class == ~0)
+                       fence_class = entry->new_fence_class;
+               else if (entry->new_fence_class != fence_class) {
+                       DRM_ERROR("Unmatching fence classes on unfenced list: "
+                                 "%d and %d.\n",
+                                 fence_class,
+                                 entry->new_fence_class);
                        ret = -EINVAL;
                        goto out;
                }
@@ -559,16 +610,9 @@ int drm_fence_buffer_objects(drm_file_t * priv,
                goto out;
        }
 
-       /*
-        * Transfer to a local list before we release the dev->struct_mutex;
-        * This is so we don't get any new unfenced objects while fencing
-        * the ones we already have..
-        */
-
-       list_splice_init(list, &f_list);
-
        if (fence) {
-               if ((fence_type & fence->type) != fence_type) {
+               if ((fence_type & fence->type) != fence_type ||
+                   (fence->fence_class != fence_class)) {
                        DRM_ERROR("Given fence doesn't match buffers "
                                  "on unfenced list.\n");
                        ret = -EINVAL;
@@ -576,7 +620,7 @@ int drm_fence_buffer_objects(drm_file_t * priv,
                }
        } else {
                mutex_unlock(&dev->struct_mutex);
-               ret = drm_fence_object_create(dev, 0, fence_type,
+               ret = drm_fence_object_create(dev, fence_class, fence_type,
                                              fence_flags | DRM_FENCE_FLAG_EMIT,
                                              &fence);
                mutex_lock(&dev->struct_mutex);
@@ -585,10 +629,10 @@ int drm_fence_buffer_objects(drm_file_t * priv,
        }
 
        count = 0;
-       l = f_list.next;
-       while (l != &f_list) {
+       l = list->next;
+       while (l != list) {
                prefetch(l->next);
-               entry = list_entry(l, drm_buffer_object_t, lru);
+               entry = list_entry(l, struct drm_buffer_object, lru);
                atomic_inc(&entry->usage);
                mutex_unlock(&dev->struct_mutex);
                mutex_lock(&entry->mutex);
@@ -597,37 +641,37 @@ int drm_fence_buffer_objects(drm_file_t * priv,
                if (entry->priv_flags & _DRM_BO_FLAG_UNFENCED) {
                        count++;
                        if (entry->fence)
-                               drm_fence_usage_deref_locked(dev, entry->fence);
-                       entry->fence = fence;
+                               drm_fence_usage_deref_locked(&entry->fence);
+                       entry->fence = drm_fence_reference_locked(fence);
+                       entry->fence_class = entry->new_fence_class;
+                       entry->fence_type = entry->new_fence_type;
                        DRM_FLAG_MASKED(entry->priv_flags, 0,
                                        _DRM_BO_FLAG_UNFENCED);
                        DRM_WAKEUP(&entry->event_queue);
                        drm_bo_add_to_lru(entry);
                }
                mutex_unlock(&entry->mutex);
-               drm_bo_usage_deref_locked(entry);
-               l = f_list.next;
+               drm_bo_usage_deref_locked(&entry);
+               l = list->next;
        }
-       atomic_add(count, &fence->usage);
        DRM_DEBUG("Fenced %d buffers\n", count);
       out:
        mutex_unlock(&dev->struct_mutex);
        *used_fence = fence;
        return ret;
 }
-
 EXPORT_SYMBOL(drm_fence_buffer_objects);
 
 /*
  * bo->mutex locked
  */
 
-static int drm_bo_evict(drm_buffer_object_t * bo, unsigned mem_type,
+static int drm_bo_evict(struct drm_buffer_object * bo, unsigned mem_type,
                        int no_wait)
 {
        int ret = 0;
-       drm_device_t *dev = bo->dev;
-       drm_bo_mem_reg_t evict_mem;
+       struct drm_device *dev = bo->dev;
+       struct drm_bo_mem_reg evict_mem;
 
        /*
         * Someone might have modified the buffer before we took the buffer mutex.
@@ -649,12 +693,6 @@ static int drm_bo_evict(drm_buffer_object_t * bo, unsigned mem_type,
        evict_mem = bo->mem;
        evict_mem.mm_node = NULL;
 
-       if (bo->type == drm_bo_type_fake) {
-               bo->mem.mem_type = DRM_BO_MEM_LOCAL;
-               bo->mem.mm_node = NULL;
-               goto out1;
-       }
-
        evict_mem = bo->mem;
        evict_mem.mask = dev->driver->bo_driver->evict_mask(bo);
        ret = drm_bo_mem_space(bo, &evict_mem, no_wait);
@@ -674,7 +712,6 @@ static int drm_bo_evict(drm_buffer_object_t * bo, unsigned mem_type,
                goto out;
        }
 
-      out1:
        mutex_lock(&dev->struct_mutex);
        if (evict_mem.mm_node) {
                if (evict_mem.mm_node != bo->pinned_node)
@@ -692,14 +729,18 @@ static int drm_bo_evict(drm_buffer_object_t * bo, unsigned mem_type,
        return ret;
 }
 
-static int drm_bo_mem_force_space(drm_device_t * dev,
-                                 drm_bo_mem_reg_t * mem,
+/**
+ * Repeatedly evict memory from the LRU for @mem_type until we create enough
+ * space, or we've evicted everything and there isn't enough space.
+ */
+static int drm_bo_mem_force_space(struct drm_device * dev,
+                                 struct drm_bo_mem_reg * mem,
                                  uint32_t mem_type, int no_wait)
 {
-       drm_mm_node_t *node;
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_buffer_object_t *entry;
-       drm_mem_type_manager_t *man = &bm->man[mem_type];
+       struct drm_mm_node *node;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_buffer_object *entry;
+       struct drm_mem_type_manager *man = &bm->man[mem_type];
        struct list_head *lru;
        unsigned long num_pages = mem->num_pages;
        int ret;
@@ -715,7 +756,7 @@ static int drm_bo_mem_force_space(drm_device_t * dev,
                if (lru->next == lru)
                        break;
 
-               entry = list_entry(lru->next, drm_buffer_object_t, lru);
+               entry = list_entry(lru->next, struct drm_buffer_object, lru);
                atomic_inc(&entry->usage);
                mutex_unlock(&dev->struct_mutex);
                mutex_lock(&entry->mutex);
@@ -723,7 +764,7 @@ static int drm_bo_mem_force_space(drm_device_t * dev,
 
                ret = drm_bo_evict(entry, mem_type, no_wait);
                mutex_unlock(&entry->mutex);
-               drm_bo_usage_deref_unlocked(entry);
+               drm_bo_usage_deref_unlocked(&entry);
                if (ret)
                        return ret;
                mutex_lock(&dev->struct_mutex);
@@ -741,12 +782,12 @@ static int drm_bo_mem_force_space(drm_device_t * dev,
        return 0;
 }
 
-static int drm_bo_mt_compatible(drm_mem_type_manager_t * man,
+static int drm_bo_mt_compatible(struct drm_mem_type_manager * man,
                                uint32_t mem_type,
-                               uint32_t mask, uint32_t * res_mask)
+                               uint64_t mask, uint32_t * res_mask)
 {
-       uint32_t cur_flags = drm_bo_type_flags(mem_type);
-       uint32_t flag_diff;
+       uint64_t cur_flags = drm_bo_type_flags(mem_type);
+       uint64_t flag_diff;
 
        if (man->flags & _DRM_FLAG_MEMTYPE_CACHED)
                cur_flags |= DRM_BO_FLAG_CACHED;
@@ -778,12 +819,20 @@ static int drm_bo_mt_compatible(drm_mem_type_manager_t * man,
        return 1;
 }
 
-int drm_bo_mem_space(drm_buffer_object_t * bo,
-                    drm_bo_mem_reg_t * mem, int no_wait)
+/**
+ * Creates space for memory region @mem according to its type.
+ *
+ * This function first searches for free space in compatible memory types in
+ * the priority order defined by the driver.  If free space isn't found, then
+ * drm_bo_mem_force_space is attempted in priority order to evict and find
+ * space.
+ */
+int drm_bo_mem_space(struct drm_buffer_object * bo,
+                    struct drm_bo_mem_reg * mem, int no_wait)
 {
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_mem_type_manager_t *man;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_mem_type_manager *man;
 
        uint32_t num_prios = dev->driver->bo_driver->num_mem_type_prio;
        const uint32_t *prios = dev->driver->bo_driver->mem_type_prio;
@@ -793,7 +842,7 @@ int drm_bo_mem_space(drm_buffer_object_t * bo,
        int type_found = 0;
        int type_ok = 0;
        int has_eagain = 0;
-       drm_mm_node_t *node = NULL;
+       struct drm_mm_node *node = NULL;
        int ret;
 
        mem->mm_node = NULL;
@@ -870,37 +919,38 @@ int drm_bo_mem_space(drm_buffer_object_t * bo,
 
 EXPORT_SYMBOL(drm_bo_mem_space);
 
-static int drm_bo_new_mask(drm_buffer_object_t * bo,
-                          uint32_t new_mask, uint32_t hint)
+static int drm_bo_new_mask(struct drm_buffer_object * bo,
+                          uint64_t new_flags, uint64_t used_mask)
 {
        uint32_t new_props;
 
        if (bo->type == drm_bo_type_user) {
-               DRM_ERROR("User buffers are not supported yet\n");
-               return -EINVAL;
-       }
-       if (bo->type == drm_bo_type_fake &&
-           !(new_mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))) {
-               DRM_ERROR("Fake buffers must be pinned.\n");
+               DRM_ERROR("User buffers are not supported yet.\n");
                return -EINVAL;
        }
 
-       if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) {
+       if ((used_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) {
                DRM_ERROR
                    ("DRM_BO_FLAG_NO_EVICT is only available to priviliged "
-                    "processes\n");
+                    "processes.\n");
+               return -EPERM;
+       }
+
+       if ((new_flags & DRM_BO_FLAG_NO_MOVE)) {
+               DRM_ERROR
+                       ("DRM_BO_FLAG_NO_MOVE is not properly implemented yet.\n");
                return -EPERM;
        }
 
-       new_props = new_mask & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE |
-                               DRM_BO_FLAG_READ);
+       new_props = new_flags & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE |
+                                DRM_BO_FLAG_READ);
 
        if (!new_props) {
                DRM_ERROR("Invalid buffer object rwx properties\n");
                return -EINVAL;
        }
 
-       bo->mem.mask = new_mask;
+       bo->mem.mask = new_flags;
        return 0;
 }
 
@@ -908,28 +958,29 @@ static int drm_bo_new_mask(drm_buffer_object_t * bo,
  * Call dev->struct_mutex locked.
  */
 
-drm_buffer_object_t *drm_lookup_buffer_object(drm_file_t * priv,
+struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv,
                                              uint32_t handle, int check_owner)
 {
-       drm_user_object_t *uo;
-       drm_buffer_object_t *bo;
+       struct drm_user_object *uo;
+       struct drm_buffer_object *bo;
 
-       uo = drm_lookup_user_object(priv, handle);
+       uo = drm_lookup_user_object(file_priv, handle);
 
        if (!uo || (uo->type != drm_buffer_type)) {
                DRM_ERROR("Could not find buffer object 0x%08x\n", handle);
                return NULL;
        }
 
-       if (check_owner && priv != uo->owner) {
-               if (!drm_lookup_ref_object(priv, uo, _DRM_REF_USE))
+       if (check_owner && file_priv != uo->owner) {
+               if (!drm_lookup_ref_object(file_priv, uo, _DRM_REF_USE))
                        return NULL;
        }
 
-       bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
+       bo = drm_user_object_entry(uo, struct drm_buffer_object, base);
        atomic_inc(&bo->usage);
        return bo;
 }
+EXPORT_SYMBOL(drm_lookup_buffer_object);
 
 /*
  * Call bo->mutex locked.
@@ -937,16 +988,14 @@ drm_buffer_object_t *drm_lookup_buffer_object(drm_file_t * priv,
  * Doesn't do any fence flushing as opposed to the drm_bo_busy function.
  */
 
-static int drm_bo_quick_busy(drm_buffer_object_t * bo)
+static int drm_bo_quick_busy(struct drm_buffer_object * bo)
 {
-       drm_fence_object_t *fence = bo->fence;
+       struct drm_fence_object *fence = bo->fence;
 
        BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNFENCED);
        if (fence) {
-               drm_device_t *dev = bo->dev;
-               if (drm_fence_object_signaled(fence, bo->fence_type)) {
-                       drm_fence_usage_deref_unlocked(dev, fence);
-                       bo->fence = NULL;
+               if (drm_fence_object_signaled(fence, bo->fence_type, 0)) {
+                       drm_fence_usage_deref_unlocked(&bo->fence);
                        return 0;
                }
                return 1;
@@ -959,22 +1008,19 @@ static int drm_bo_quick_busy(drm_buffer_object_t * bo)
  * Returns 1 if the buffer is currently rendered to or from. 0 otherwise.
  */
 
-static int drm_bo_busy(drm_buffer_object_t * bo)
+static int drm_bo_busy(struct drm_buffer_object * bo)
 {
-       drm_fence_object_t *fence = bo->fence;
+       struct drm_fence_object *fence = bo->fence;
 
        BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNFENCED);
        if (fence) {
-               drm_device_t *dev = bo->dev;
-               if (drm_fence_object_signaled(fence, bo->fence_type)) {
-                       drm_fence_usage_deref_unlocked(dev, fence);
-                       bo->fence = NULL;
+               if (drm_fence_object_signaled(fence, bo->fence_type, 0)) {
+                       drm_fence_usage_deref_unlocked(&bo->fence);
                        return 0;
                }
-               drm_fence_object_flush(dev, fence, DRM_FENCE_TYPE_EXE);
-               if (drm_fence_object_signaled(fence, bo->fence_type)) {
-                       drm_fence_usage_deref_unlocked(dev, fence);
-                       bo->fence = NULL;
+               drm_fence_object_flush(fence, DRM_FENCE_TYPE_EXE);
+               if (drm_fence_object_signaled(fence, bo->fence_type, 0)) {
+                       drm_fence_usage_deref_unlocked(&bo->fence);
                        return 0;
                }
                return 1;
@@ -982,7 +1028,7 @@ static int drm_bo_busy(drm_buffer_object_t * bo)
        return 0;
 }
 
-static int drm_bo_read_cached(drm_buffer_object_t * bo)
+static int drm_bo_read_cached(struct drm_buffer_object * bo)
 {
        int ret = 0;
 
@@ -996,7 +1042,7 @@ static int drm_bo_read_cached(drm_buffer_object_t * bo)
  * Wait until a buffer is unmapped.
  */
 
-static int drm_bo_wait_unmapped(drm_buffer_object_t * bo, int no_wait)
+static int drm_bo_wait_unmapped(struct drm_buffer_object * bo, int no_wait)
 {
        int ret = 0;
 
@@ -1012,7 +1058,7 @@ static int drm_bo_wait_unmapped(drm_buffer_object_t * bo, int no_wait)
        return ret;
 }
 
-static int drm_bo_check_unfenced(drm_buffer_object_t * bo)
+static int drm_bo_check_unfenced(struct drm_buffer_object * bo)
 {
        int ret;
 
@@ -1025,16 +1071,9 @@ static int drm_bo_check_unfenced(drm_buffer_object_t * bo)
 /*
  * Wait until a buffer, scheduled to be fenced moves off the unfenced list.
  * Until then, we cannot really do anything with it except delete it.
- * The unfenced list is a PITA, and the operations
- * 1) validating
- * 2) submitting commands
- * 3) fencing
- * Should really be an atomic operation.
- * We now "solve" this problem by keeping
- * the buffer "unfenced" after validating, but before fencing.
  */
 
-static int drm_bo_wait_unfenced(drm_buffer_object_t * bo, int no_wait,
+static int drm_bo_wait_unfenced(struct drm_buffer_object * bo, int no_wait,
                                int eagain_if_wait)
 {
        int ret = (bo->priv_flags & _DRM_BO_FLAG_UNFENCED);
@@ -1067,12 +1106,15 @@ static int drm_bo_wait_unfenced(drm_buffer_object_t * bo, int no_wait,
  * Bo locked.
  */
 
-static void drm_bo_fill_rep_arg(drm_buffer_object_t * bo,
-                               drm_bo_arg_reply_t * rep)
+static void drm_bo_fill_rep_arg(struct drm_buffer_object * bo,
+                               struct drm_bo_info_rep *rep)
 {
+       if (!rep)
+               return;
+
        rep->handle = bo->base.hash.key;
        rep->flags = bo->mem.flags;
-       rep->size = bo->mem.num_pages * PAGE_SIZE;
+       rep->size = bo->num_pages * PAGE_SIZE;
        rep->offset = bo->offset;
        rep->arg_handle = bo->map_list.user_token;
        rep->mask = bo->mem.mask;
@@ -1094,28 +1136,26 @@ static void drm_bo_fill_rep_arg(drm_buffer_object_t * bo,
  * unregistered.
  */
 
-static int drm_buffer_object_map(drm_file_t * priv, uint32_t handle,
+static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle,
                                 uint32_t map_flags, unsigned hint,
-                                drm_bo_arg_reply_t * rep)
+                                struct drm_bo_info_rep *rep)
 {
-       drm_buffer_object_t *bo;
-       drm_device_t *dev = priv->head->dev;
+       struct drm_buffer_object *bo;
+       struct drm_device *dev = file_priv->head->dev;
        int ret = 0;
        int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
 
        mutex_lock(&dev->struct_mutex);
-       bo = drm_lookup_buffer_object(priv, handle, 1);
+       bo = drm_lookup_buffer_object(file_priv, handle, 1);
        mutex_unlock(&dev->struct_mutex);
 
        if (!bo)
                return -EINVAL;
 
        mutex_lock(&bo->mutex);
-       if (!(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) {
-               ret = drm_bo_wait_unfenced(bo, no_wait, 0);
-               if (ret)
-                       goto out;
-       }
+       ret = drm_bo_wait_unfenced(bo, no_wait, 0);
+       if (ret)
+               goto out;
 
        /*
         * If this returns true, we are currently unmapped.
@@ -1161,7 +1201,7 @@ static int drm_buffer_object_map(drm_file_t * priv, uint32_t handle,
        }
 
        mutex_lock(&dev->struct_mutex);
-       ret = drm_add_ref_object(priv, &bo->base, _DRM_REF_TYPE1);
+       ret = drm_add_ref_object(file_priv, &bo->base, _DRM_REF_TYPE1);
        mutex_unlock(&dev->struct_mutex);
        if (ret) {
                if (atomic_add_negative(-1, &bo->mapped))
@@ -1171,33 +1211,33 @@ static int drm_buffer_object_map(drm_file_t * priv, uint32_t handle,
                drm_bo_fill_rep_arg(bo, rep);
       out:
        mutex_unlock(&bo->mutex);
-       drm_bo_usage_deref_unlocked(bo);
+       drm_bo_usage_deref_unlocked(&bo);
        return ret;
 }
 
-static int drm_buffer_object_unmap(drm_file_t * priv, uint32_t handle)
+static int drm_buffer_object_unmap(struct drm_file *file_priv, uint32_t handle)
 {
-       drm_device_t *dev = priv->head->dev;
-       drm_buffer_object_t *bo;
-       drm_ref_object_t *ro;
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_buffer_object *bo;
+       struct drm_ref_object *ro;
        int ret = 0;
 
        mutex_lock(&dev->struct_mutex);
 
-       bo = drm_lookup_buffer_object(priv, handle, 1);
+       bo = drm_lookup_buffer_object(file_priv, handle, 1);
        if (!bo) {
                ret = -EINVAL;
                goto out;
        }
 
-       ro = drm_lookup_ref_object(priv, &bo->base, _DRM_REF_TYPE1);
+       ro = drm_lookup_ref_object(file_priv, &bo->base, _DRM_REF_TYPE1);
        if (!ro) {
                ret = -EINVAL;
                goto out;
        }
 
-       drm_remove_ref_object(priv, ro);
-       drm_bo_usage_deref_locked(bo);
+       drm_remove_ref_object(file_priv, ro);
+       drm_bo_usage_deref_locked(&bo);
       out:
        mutex_unlock(&dev->struct_mutex);
        return ret;
@@ -1207,12 +1247,12 @@ static int drm_buffer_object_unmap(drm_file_t * priv, uint32_t handle)
  * Call struct-sem locked.
  */
 
-static void drm_buffer_user_object_unmap(drm_file_t * priv,
-                                        drm_user_object_t * uo,
-                                        drm_ref_t action)
+static void drm_buffer_user_object_unmap(struct drm_file *file_priv,
+                                        struct drm_user_object * uo,
+                                        enum drm_ref_type action)
 {
-       drm_buffer_object_t *bo =
-           drm_user_object_entry(uo, drm_buffer_object_t, base);
+       struct drm_buffer_object *bo =
+           drm_user_object_entry(uo, struct drm_buffer_object, base);
 
        /*
         * We DON'T want to take the bo->lock here, because we want to
@@ -1230,13 +1270,13 @@ static void drm_buffer_user_object_unmap(drm_file_t * priv,
  * Note that new_mem_flags are NOT transferred to the bo->mem.mask.
  */
 
-int drm_bo_move_buffer(drm_buffer_object_t * bo, uint32_t new_mem_flags,
+int drm_bo_move_buffer(struct drm_buffer_object * bo, uint64_t new_mem_flags,
                       int no_wait, int move_unfenced)
 {
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
        int ret = 0;
-       drm_bo_mem_reg_t mem;
+       struct drm_bo_mem_reg mem;
        /*
         * Flush outstanding fences.
         */
@@ -1251,17 +1291,14 @@ int drm_bo_move_buffer(drm_buffer_object_t * bo, uint32_t new_mem_flags,
        if (ret)
                return ret;
 
-       mem.num_pages = bo->mem.num_pages;
+       mem.num_pages = bo->num_pages;
        mem.size = mem.num_pages << PAGE_SHIFT;
        mem.mask = new_mem_flags;
        mem.page_alignment = bo->mem.page_alignment;
 
        mutex_lock(&bm->evict_mutex);
        mutex_lock(&dev->struct_mutex);
-       list_del(&bo->lru);
-       list_add_tail(&bo->lru, &bm->unfenced);
-       DRM_FLAG_MASKED(bo->priv_flags, _DRM_BO_FLAG_UNFENCED,
-                       _DRM_BO_FLAG_UNFENCED);
+       list_del_init(&bo->lru);
        mutex_unlock(&dev->struct_mutex);
 
        /*
@@ -1281,10 +1318,6 @@ int drm_bo_move_buffer(drm_buffer_object_t * bo, uint32_t new_mem_flags,
                                drm_mm_put_block(mem.mm_node);
                        mem.mm_node = NULL;
                }
-               DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
-               DRM_WAKEUP(&bo->event_queue);
-               list_del(&bo->lru);
-               drm_bo_add_to_lru(bo);
                mutex_unlock(&dev->struct_mutex);
        }
 
@@ -1292,14 +1325,14 @@ int drm_bo_move_buffer(drm_buffer_object_t * bo, uint32_t new_mem_flags,
        return ret;
 }
 
-static int drm_bo_mem_compat(drm_bo_mem_reg_t * mem)
+static int drm_bo_mem_compat(struct drm_bo_mem_reg * mem)
 {
        uint32_t flag_diff = (mem->mask ^ mem->flags);
 
        if ((mem->mask & mem->flags & DRM_BO_MASK_MEM) == 0)
                return 0;
        if ((flag_diff & DRM_BO_FLAG_CACHED) &&
-           (!(mem->mask & DRM_BO_FLAG_CACHED) ||
+           (/* !(mem->mask & DRM_BO_FLAG_CACHED) ||*/
             (mem->mask & DRM_BO_FLAG_FORCE_CACHING))) {
          return 0;
        }
@@ -1310,72 +1343,55 @@ static int drm_bo_mem_compat(drm_bo_mem_reg_t * mem)
        return 1;
 }
 
-static int drm_bo_check_fake(drm_device_t * dev, drm_bo_mem_reg_t * mem)
-{
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_mem_type_manager_t *man;
-       uint32_t num_prios = dev->driver->bo_driver->num_mem_type_prio;
-       const uint32_t *prios = dev->driver->bo_driver->mem_type_prio;
-       uint32_t i;
-       int type_ok = 0;
-       uint32_t mem_type = 0;
-       uint32_t cur_flags;
-
-       if (drm_bo_mem_compat(mem))
-               return 0;
-
-       BUG_ON(mem->mm_node);
-
-       for (i = 0; i < num_prios; ++i) {
-               mem_type = prios[i];
-               man = &bm->man[mem_type];
-               type_ok = drm_bo_mt_compatible(man, mem_type, mem->mask,
-                                              &cur_flags);
-               if (type_ok)
-                       break;
-       }
-
-       if (type_ok) {
-               mem->mm_node = NULL;
-               mem->mem_type = mem_type;
-               mem->flags = cur_flags;
-               DRM_FLAG_MASKED(mem->flags, mem->mask, ~DRM_BO_MASK_MEMTYPE);
-               return 0;
-       }
-
-       DRM_ERROR("Illegal fake buffer flags 0x%08x\n", mem->mask);
-       return -EINVAL;
-}
-
 /*
  * bo locked.
  */
 
-static int drm_buffer_object_validate(drm_buffer_object_t * bo,
+static int drm_buffer_object_validate(struct drm_buffer_object * bo,
+                                     uint32_t fence_class,
                                      int move_unfenced, int no_wait)
 {
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_bo_driver_t *driver = dev->driver->bo_driver;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_bo_driver *driver = dev->driver->bo_driver;
+       uint32_t ftype;
        int ret;
 
-       DRM_DEBUG("New flags 0x%08x, Old flags 0x%08x\n", bo->mem.mask,
-                 bo->mem.flags);
-       ret =
-           driver->fence_type(bo, &bo->fence_class, &bo->fence_type);
+       DRM_DEBUG("New flags 0x%016llx, Old flags 0x%016llx\n",
+                 (unsigned long long) bo->mem.mask,
+                 (unsigned long long) bo->mem.flags);
+
+       ret = driver->fence_type(bo, &fence_class, &ftype);
+
        if (ret) {
                DRM_ERROR("Driver did not support given buffer permissions\n");
                return ret;
        }
 
-       ret = drm_bo_wait_unmapped(bo, no_wait);
-       if (ret)
-               return ret;
+       /*
+        * We're switching command submission mechanism,
+        * or cannot simply rely on the hardware serializing for us.
+        *
+        * Wait for buffer idle.
+        */
+
+       if ((fence_class != bo->fence_class) ||
+           ((ftype ^ bo->fence_type) & bo->fence_type)) {
+
+               ret = drm_bo_wait(bo, 0, 0, no_wait);
 
-       if (bo->type == drm_bo_type_fake) {
-               ret = drm_bo_check_fake(dev, &bo->mem);
                if (ret)
                        return ret;
+
+       }
+
+       bo->new_fence_class = fence_class;
+       bo->new_fence_type = ftype;
+
+       ret = drm_bo_wait_unmapped(bo, no_wait);
+       if (ret) {
+               DRM_ERROR("Timed out waiting for buffer unmap.\n");
+               return ret;
        }
 
        /*
@@ -1457,18 +1473,13 @@ static int drm_buffer_object_validate(drm_buffer_object_t * bo,
        return 0;
 }
 
-static int drm_bo_handle_validate(drm_file_t * priv, uint32_t handle,
-                                 uint32_t flags, uint32_t mask, uint32_t hint,
-                                 drm_bo_arg_reply_t * rep)
+int drm_bo_do_validate(struct drm_buffer_object *bo,
+                      uint64_t flags, uint64_t mask, uint32_t hint,
+                      uint32_t fence_class,
+                      int no_wait,
+                      struct drm_bo_info_rep *rep)
 {
-       drm_buffer_object_t *bo;
        int ret;
-       int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
-
-       bo = drm_lookup_buffer_object(priv, handle, 1);
-       if (!bo) {
-               return -EINVAL;
-       }
 
        mutex_lock(&bo->mutex);
        ret = drm_bo_wait_unfenced(bo, no_wait, 0);
@@ -1476,30 +1487,79 @@ static int drm_bo_handle_validate(drm_file_t * priv, uint32_t handle,
        if (ret)
                goto out;
 
+
        DRM_FLAG_MASKED(flags, bo->mem.mask, ~mask);
-       ret = drm_bo_new_mask(bo, flags, hint);
+       ret = drm_bo_new_mask(bo, flags, mask);
        if (ret)
                goto out;
 
-       ret =
-           drm_buffer_object_validate(bo, !(hint & DRM_BO_HINT_DONT_FENCE),
-                                      no_wait);
-       drm_bo_fill_rep_arg(bo, rep);
-
-      out:
+       ret = drm_buffer_object_validate(bo,
+                                        fence_class,
+                                        !(hint & DRM_BO_HINT_DONT_FENCE),
+                                        no_wait);
+out:
+       if (rep)
+               drm_bo_fill_rep_arg(bo, rep);
 
        mutex_unlock(&bo->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(drm_bo_do_validate);
+
+
+int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle,
+                          uint32_t fence_class,
+                          uint64_t flags, uint64_t mask, 
+                          uint32_t hint,
+                          int use_old_fence_class,
+                          struct drm_bo_info_rep * rep,
+                          struct drm_buffer_object **bo_rep)
+{
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_buffer_object *bo;
+       int ret;
+       int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
+
+       mutex_lock(&dev->struct_mutex);
+       bo = drm_lookup_buffer_object(file_priv, handle, 1);
+       mutex_unlock(&dev->struct_mutex);
+
+       if (!bo) 
+               return -EINVAL;
+
+       if (use_old_fence_class)
+               fence_class = bo->fence_class;
+
+       /*
+        * Only allow creator to change shared buffer mask.
+        */
+
+       if (bo->base.owner != file_priv) 
+               mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE);
+
+               
+       ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class,
+                                no_wait, rep);
+
+       if (!ret && bo_rep)
+               *bo_rep = bo;
+       else
+               drm_bo_usage_deref_unlocked(&bo);
 
-       drm_bo_usage_deref_unlocked(bo);
        return ret;
 }
+EXPORT_SYMBOL(drm_bo_handle_validate);
 
-static int drm_bo_handle_info(drm_file_t * priv, uint32_t handle,
-                             drm_bo_arg_reply_t * rep)
+static int drm_bo_handle_info(struct drm_file *file_priv, uint32_t handle,
+                             struct drm_bo_info_rep *rep)
 {
-       drm_buffer_object_t *bo;
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_buffer_object *bo;
+
+       mutex_lock(&dev->struct_mutex);
+       bo = drm_lookup_buffer_object(file_priv, handle, 1);
+       mutex_unlock(&dev->struct_mutex);
 
-       bo = drm_lookup_buffer_object(priv, handle, 1);
        if (!bo) {
                return -EINVAL;
        }
@@ -1508,18 +1568,23 @@ static int drm_bo_handle_info(drm_file_t * priv, uint32_t handle,
                (void)drm_bo_busy(bo);
        drm_bo_fill_rep_arg(bo, rep);
        mutex_unlock(&bo->mutex);
-       drm_bo_usage_deref_unlocked(bo);
+       drm_bo_usage_deref_unlocked(&bo);
        return 0;
 }
 
-static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle,
-                             uint32_t hint, drm_bo_arg_reply_t * rep)
+static int drm_bo_handle_wait(struct drm_file *file_priv, uint32_t handle,
+                             uint32_t hint,
+                             struct drm_bo_info_rep *rep)
 {
-       drm_buffer_object_t *bo;
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_buffer_object *bo;
        int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
        int ret;
 
-       bo = drm_lookup_buffer_object(priv, handle, 1);
+       mutex_lock(&dev->struct_mutex);
+       bo = drm_lookup_buffer_object(file_priv, handle, 1);
+       mutex_unlock(&dev->struct_mutex);
+
        if (!bo) {
                return -EINVAL;
        }
@@ -1536,25 +1601,25 @@ static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle,
 
       out:
        mutex_unlock(&bo->mutex);
-       drm_bo_usage_deref_unlocked(bo);
+       drm_bo_usage_deref_unlocked(&bo);
        return ret;
 }
 
-int drm_buffer_object_create(drm_device_t *dev,
+int drm_buffer_object_create(struct drm_device *dev,
                             unsigned long size,
-                            drm_bo_type_t type,
-                            uint32_t mask,
+                            enum drm_bo_type type,
+                            uint64_t mask,
                             uint32_t hint,
                             uint32_t page_alignment,
                             unsigned long buffer_start,
-                            drm_buffer_object_t ** buf_obj)
+                            struct drm_buffer_object ** buf_obj)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_buffer_object_t *bo;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_buffer_object *bo;
        int ret = 0;
        unsigned long num_pages;
 
-       if ((buffer_start & ~PAGE_MASK) && (type != drm_bo_type_fake)) {
+       if (buffer_start & ~PAGE_MASK) {
                DRM_ERROR("Invalid buffer object start.\n");
                return -EINVAL;
        }
@@ -1583,20 +1648,21 @@ int drm_buffer_object_create(drm_device_t *dev,
        INIT_LIST_HEAD(&bo->vma_list);
 #endif
        bo->dev = dev;
-       bo->type = type;
+       if (buffer_start != 0)
+               bo->type = drm_bo_type_user;
+       else
+               bo->type = type;
+       bo->num_pages = num_pages;
        bo->mem.mem_type = DRM_BO_MEM_LOCAL;
-       bo->mem.num_pages = num_pages;
+       bo->mem.num_pages = bo->num_pages;
        bo->mem.mm_node = NULL;
        bo->mem.page_alignment = page_alignment;
-       if (bo->type == drm_bo_type_fake) {
-               bo->offset = buffer_start;
-               bo->buffer_start = 0;
-       } else {
-               bo->buffer_start = buffer_start;
-       }
+       bo->buffer_start = buffer_start;
        bo->priv_flags = 0;
-       bo->mem.flags = 0;
-       bo->mem.mask = 0;
+       bo->mem.flags = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | 
+               DRM_BO_FLAG_MAPPABLE;
+       bo->mem.mask = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED |
+               DRM_BO_FLAG_MAPPABLE;
        atomic_inc(&bm->count);
        ret = drm_bo_new_mask(bo, mask, hint);
 
@@ -1610,7 +1676,8 @@ int drm_buffer_object_create(drm_device_t *dev,
                if (ret)
                        goto out_err;
        }
-       ret = drm_buffer_object_validate(bo, 0, hint & DRM_BO_HINT_DONT_BLOCK);
+
+       ret = drm_buffer_object_validate(bo, 0, 0, hint & DRM_BO_HINT_DONT_BLOCK);
        if (ret)
                goto out_err;
 
@@ -1621,18 +1688,20 @@ int drm_buffer_object_create(drm_device_t *dev,
       out_err:
        mutex_unlock(&bo->mutex);
 
-       drm_bo_usage_deref_unlocked(bo);
+       drm_bo_usage_deref_unlocked(&bo);
        return ret;
 }
+EXPORT_SYMBOL(drm_buffer_object_create);
+
 
-static int drm_bo_add_user_object(drm_file_t * priv, drm_buffer_object_t * bo,
-                                 int shareable)
+static int drm_bo_add_user_object(struct drm_file *file_priv,
+                                 struct drm_buffer_object *bo, int shareable)
 {
-       drm_device_t *dev = priv->head->dev;
+       struct drm_device *dev = file_priv->head->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
-       ret = drm_add_user_object(priv, &bo->base, shareable);
+       ret = drm_add_user_object(file_priv, &bo->base, shareable);
        if (ret)
                goto out;
 
@@ -1646,182 +1715,191 @@ static int drm_bo_add_user_object(drm_file_t * priv, drm_buffer_object_t * bo,
        return ret;
 }
 
-static int drm_bo_lock_test(drm_device_t * dev, struct file *filp)
+int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       LOCK_TEST_WITH_RETURN(dev, filp);
-       return 0;
+       struct drm_bo_create_arg *arg = data;
+       struct drm_bo_create_req *req = &arg->d.req;
+       struct drm_bo_info_rep *rep = &arg->d.rep;
+       struct drm_buffer_object *entry;
+       int ret = 0;
+
+       DRM_DEBUG("drm_bo_create_ioctl: %dkb, %dkb align\n",
+           (int)(req->size / 1024), req->page_alignment * 4);
+
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized.\n");
+               return -EINVAL;
+       }
+
+       ret = drm_buffer_object_create(file_priv->head->dev,
+                                      req->size, drm_bo_type_dc, req->mask,
+                                      req->hint, req->page_alignment,
+                                      req->buffer_start, &entry);
+       if (ret)
+               goto out;
+       
+       ret = drm_bo_add_user_object(file_priv, entry,
+                                    req->mask & DRM_BO_FLAG_SHAREABLE);
+       if (ret) {
+               drm_bo_usage_deref_unlocked(&entry);
+               goto out;
+       }
+       
+       mutex_lock(&entry->mutex);
+       drm_bo_fill_rep_arg(entry, rep);
+       mutex_unlock(&entry->mutex);
+
+out:
+       return ret;
 }
 
-int drm_bo_ioctl(DRM_IOCTL_ARGS)
+int drm_bo_setstatus_ioctl(struct drm_device *dev, 
+                          void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_bo_arg_t arg;
-       drm_bo_arg_request_t *req = &arg.d.req;
-       drm_bo_arg_reply_t rep;
-       unsigned long next;
-       drm_user_object_t *uo;
-       drm_buffer_object_t *entry;
+       struct drm_bo_map_wait_idle_arg *arg = data;
+       struct drm_bo_info_req *req = &arg->d.req;
+       struct drm_bo_info_rep *rep = &arg->d.rep;
+       int ret;
 
        if (!dev->bm.initialized) {
                DRM_ERROR("Buffer object manager is not initialized.\n");
                return -EINVAL;
        }
 
-       do {
-               DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
+       ret = drm_bo_read_lock(&dev->bm.bm_lock);
+       if (ret)
+               return ret;
 
-               if (arg.handled) {
-                       data = arg.next;
-                       continue;
-               }
+       ret = drm_bo_handle_validate(file_priv, req->handle, req->fence_class,
+                                    req->flags,
+                                    req->mask,
+                                    req->hint | DRM_BO_HINT_DONT_FENCE,
+                                    1,
+                                    rep, NULL);
 
-               rep.ret = 0;
-               switch (req->op) {
-               case drm_bo_create:
-                       rep.ret = drm_bo_lock_test(dev, filp);
-                       if (rep.ret)
-                               break;  
-                       rep.ret =
-                           drm_buffer_object_create(priv->head->dev,
-                                                    req->size,
-                                                    req->type,
-                                                    req->mask,
-                                                    req->hint,
-                                                    req->page_alignment,
-                                                    req->buffer_start, &entry);
-                       if (rep.ret)
-                               break;
-
-                       rep.ret =
-                           drm_bo_add_user_object(priv, entry,
-                                                  req->
-                                                  mask &
-                                                  DRM_BO_FLAG_SHAREABLE);
-                       if (rep.ret)
-                               drm_bo_usage_deref_unlocked(entry);
-
-                       if (rep.ret)
-                               break;
-
-                       mutex_lock(&entry->mutex);
-                       drm_bo_fill_rep_arg(entry, &rep);
-                       mutex_unlock(&entry->mutex);
-                       break;
-               case drm_bo_unmap:
-                       rep.ret = drm_buffer_object_unmap(priv, req->handle);
-                       break;
-               case drm_bo_map:
-                       rep.ret = drm_buffer_object_map(priv, req->handle,
-                                                       req->mask,
-                                                       req->hint, &rep);
-                       break;
-               case drm_bo_destroy:
-                       mutex_lock(&dev->struct_mutex);
-                       uo = drm_lookup_user_object(priv, req->handle);
-                       if (!uo || (uo->type != drm_buffer_type)
-                           || uo->owner != priv) {
-                               mutex_unlock(&dev->struct_mutex);
-                               rep.ret = -EINVAL;
-                               break;
-                       }
-                       rep.ret = drm_remove_user_object(priv, uo);
-                       mutex_unlock(&dev->struct_mutex);
-                       break;
-               case drm_bo_reference:
-                       rep.ret = drm_user_object_ref(priv, req->handle,
-                                                     drm_buffer_type, &uo);
-                       if (rep.ret)
-                               break;
+       (void) drm_bo_read_unlock(&dev->bm.bm_lock);
+       if (ret)
+               return ret;
 
-                       rep.ret = drm_bo_handle_info(priv, req->handle, &rep);
-                       break;
-               case drm_bo_unreference:
-                       rep.ret = drm_user_object_unref(priv, req->handle,
-                                                       drm_buffer_type);
-                       break;
-               case drm_bo_validate:
-                       rep.ret = drm_bo_lock_test(dev, filp);
-
-                       if (rep.ret)
-                               break;
-                       rep.ret =
-                           drm_bo_handle_validate(priv, req->handle, req->mask,
-                                                  req->arg_handle, req->hint,
-                                                  &rep);
-                       break;
-               case drm_bo_fence:
-                       rep.ret = drm_bo_lock_test(dev, filp);
-                       if (rep.ret)
-                               break;
-                        /**/ break;
-               case drm_bo_info:
-                       rep.ret = drm_bo_handle_info(priv, req->handle, &rep);
-                       break;
-               case drm_bo_wait_idle:
-                       rep.ret = drm_bo_handle_wait(priv, req->handle,
-                                                    req->hint, &rep);
-                       break;
-               case drm_bo_ref_fence:
-                       rep.ret = -EINVAL;
-                       DRM_ERROR("Function is not implemented yet.\n");
-               default:
-                       rep.ret = -EINVAL;
-               }
-               next = arg.next;
+       return 0;
+}
 
-               /*
-                * A signal interrupted us. Make sure the ioctl is restartable.
-                */
+int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_bo_map_wait_idle_arg *arg = data;
+       struct drm_bo_info_req *req = &arg->d.req;
+       struct drm_bo_info_rep *rep = &arg->d.rep;
+       int ret;
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized.\n");
+               return -EINVAL;
+       }
 
-               if (rep.ret == -EAGAIN)
-                       return -EAGAIN;
+       ret = drm_buffer_object_map(file_priv, req->handle, req->mask,
+                                   req->hint, rep);
+       if (ret)
+               return ret;
 
-               arg.handled = 1;
-               arg.d.rep = rep;
-               DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
-               data = next;
-       } while (data);
        return 0;
 }
 
-/**
- *Clean the unfenced list and put on regular LRU.
- *This is part of the memory manager cleanup and should only be
- *called with the DRI lock held.
- *Call dev->struct_sem locked.
- */
+int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_bo_handle_arg *arg = data;
+       int ret;
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized.\n");
+               return -EINVAL;
+       }
+
+       ret = drm_buffer_object_unmap(file_priv, arg->handle);
+       return ret;
+}
+
 
-static void drm_bo_clean_unfenced(drm_device_t *dev)
+int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_buffer_manager_t *bm  = &dev->bm;
-       struct list_head *head, *list;
-       drm_buffer_object_t *entry;
+       struct drm_bo_reference_info_arg *arg = data;
+       struct drm_bo_handle_arg *req = &arg->d.req;
+       struct drm_bo_info_rep *rep = &arg->d.rep;
+       struct drm_user_object *uo;
+       int ret;
 
-       head = &bm->unfenced;
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized.\n");
+               return -EINVAL;
+       }
 
-       list = head->next;
-       while(list != head) {
-               prefetch(list->next);
-               entry = list_entry(list, drm_buffer_object_t, lru);
+       ret = drm_user_object_ref(file_priv, req->handle,
+                                 drm_buffer_type, &uo);
+       if (ret)
+               return ret;
+       
+       ret = drm_bo_handle_info(file_priv, req->handle, rep);
+       if (ret)
+               return ret;
 
-               atomic_inc(&entry->usage);
-               mutex_unlock(&dev->struct_mutex);
-               mutex_lock(&entry->mutex);
-               mutex_lock(&dev->struct_mutex);
+       return 0;
+}
 
-               list_del(&entry->lru);
-               DRM_FLAG_MASKED(entry->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
-               drm_bo_add_to_lru(entry);
-               mutex_unlock(&entry->mutex);
-               list = head->next;
+int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_bo_handle_arg *arg = data;
+       int ret = 0;
+
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized.\n");
+               return -EINVAL;
+       }
+
+       ret = drm_user_object_unref(file_priv, arg->handle, drm_buffer_type);
+       return ret;
+}
+
+int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_bo_reference_info_arg *arg = data;
+       struct drm_bo_handle_arg *req = &arg->d.req;
+       struct drm_bo_info_rep *rep = &arg->d.rep;
+       int ret;
+
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized.\n");
+               return -EINVAL;
        }
+
+       ret = drm_bo_handle_info(file_priv, req->handle, rep);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
-static int drm_bo_leave_list(drm_buffer_object_t * bo,
+int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_bo_map_wait_idle_arg *arg = data;
+       struct drm_bo_info_req *req = &arg->d.req;
+       struct drm_bo_info_rep *rep = &arg->d.rep;
+       int ret;
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized.\n");
+               return -EINVAL;
+       }
+
+       ret = drm_bo_handle_wait(file_priv, req->handle,
+                                req->hint, rep);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int drm_bo_leave_list(struct drm_buffer_object * bo,
                             uint32_t mem_type,
-                            int free_pinned, int allow_errors)
+                            int free_pinned,
+                            int allow_errors)
 {
-       drm_device_t *dev = bo->dev;
+       struct drm_device *dev = bo->dev;
        int ret = 0;
 
        mutex_lock(&bo->mutex);
@@ -1868,20 +1946,20 @@ static int drm_bo_leave_list(drm_buffer_object_t * bo,
 }
 
 
-static drm_buffer_object_t *drm_bo_entry(struct list_head *list,
+static struct drm_buffer_object *drm_bo_entry(struct list_head *list,
                                         int pinned_list)
 {
        if (pinned_list)
-               return list_entry(list, drm_buffer_object_t, pinned_lru);
+               return list_entry(list, struct drm_buffer_object, pinned_lru);
        else
-               return list_entry(list, drm_buffer_object_t, lru);
+               return list_entry(list, struct drm_buffer_object, lru);
 }
 
 /*
  * dev->struct_mutex locked.
  */
 
-static int drm_bo_force_list_clean(drm_device_t * dev,
+static int drm_bo_force_list_clean(struct drm_device * dev,
                                   struct list_head *head,
                                   unsigned mem_type,
                                   int free_pinned,
@@ -1889,7 +1967,7 @@ static int drm_bo_force_list_clean(drm_device_t * dev,
                                   int pinned_list)
 {
        struct list_head *list, *next, *prev;
-       drm_buffer_object_t *entry, *nentry;
+       struct drm_buffer_object *entry, *nentry;
        int ret;
        int do_restart;
 
@@ -1927,7 +2005,7 @@ restart:
                                        allow_errors);
                mutex_lock(&dev->struct_mutex);
 
-               drm_bo_usage_deref_locked(entry);
+               drm_bo_usage_deref_locked(&entry);
                if (ret)
                        return ret;
 
@@ -1937,10 +2015,8 @@ restart:
 
                do_restart = ((next->prev != list) && (next->prev != prev));
 
-               if (nentry != NULL && do_restart) {
-                       drm_bo_usage_deref_locked(nentry);
-                       nentry = NULL;
-               }
+               if (nentry != NULL && do_restart)
+                       drm_bo_usage_deref_locked(&nentry);
 
                if (do_restart)
                        goto restart;
@@ -1948,10 +2024,10 @@ restart:
        return 0;
 }
 
-int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
+int drm_bo_clean_mm(struct drm_device * dev, unsigned mem_type)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_mem_type_manager_t *man = &bm->man[mem_type];
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_mem_type_manager *man = &bm->man[mem_type];
        int ret = -EINVAL;
 
        if (mem_type >= DRM_BO_MEM_TYPES) {
@@ -1961,7 +2037,7 @@ int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
 
        if (!man->has_type) {
                DRM_ERROR("Trying to take down uninitialized "
-                         "memory manager type\n");
+                         "memory manager type %u\n", mem_type);
                return ret;
        }
        man->use_type = 0;
@@ -1969,8 +2045,7 @@ int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
 
        ret = 0;
        if (mem_type > 0) {
-
-               drm_bo_clean_unfenced(dev);
+               BUG_ON(!list_empty(&bm->unfenced));
                drm_bo_force_list_clean(dev, &man->lru, mem_type, 1, 0, 0);
                drm_bo_force_list_clean(dev, &man->pinned, mem_type, 1, 0, 1);
 
@@ -1983,6 +2058,7 @@ int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
 
        return ret;
 }
+EXPORT_SYMBOL(drm_bo_clean_mm);
 
 /**
  *Evict all buffers of a particular mem_type, but leave memory manager
@@ -1990,11 +2066,11 @@ int drm_bo_clean_mm(drm_device_t * dev, unsigned mem_type)
  *point since we have the hardware lock.
  */
 
-static int drm_bo_lock_mm(drm_device_t * dev, unsigned mem_type)
+static int drm_bo_lock_mm(struct drm_device * dev, unsigned mem_type)
 {
        int ret;
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_mem_type_manager_t *man = &bm->man[mem_type];
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_mem_type_manager *man = &bm->man[mem_type];
 
        if (mem_type == 0 || mem_type >= DRM_BO_MEM_TYPES) {
                DRM_ERROR("Illegal memory manager memory type %u.\n", mem_type);
@@ -2007,7 +2083,6 @@ static int drm_bo_lock_mm(drm_device_t * dev, unsigned mem_type)
                return 0;
        }
 
-       drm_bo_clean_unfenced(dev);
        ret = drm_bo_force_list_clean(dev, &man->lru, mem_type, 0, 1, 0);
        if (ret)
                return ret;
@@ -2016,13 +2091,13 @@ static int drm_bo_lock_mm(drm_device_t * dev, unsigned mem_type)
        return ret;
 }
 
-int drm_bo_init_mm(drm_device_t * dev,
+int drm_bo_init_mm(struct drm_device * dev,
                   unsigned type,
                   unsigned long p_offset, unsigned long p_size)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_buffer_manager *bm = &dev->bm;
        int ret = -EINVAL;
-       drm_mem_type_manager_t *man;
+       struct drm_mem_type_manager *man;
 
        if (type >= DRM_BO_MEM_TYPES) {
                DRM_ERROR("Illegal memory type %d\n", type);
@@ -2061,18 +2136,19 @@ int drm_bo_init_mm(drm_device_t * dev,
 EXPORT_SYMBOL(drm_bo_init_mm);
 
 /*
- * This is called from lastclose, so we don't need to bother about
- * any clients still running when we set the initialized flag to zero.
+ * This function is intended to be called on drm driver unload.
+ * If you decide to call it from lastclose, you must protect the call
+ * from a potentially racing drm_bo_driver_init in firstopen. 
+ * (This may happen on X server restart).
  */
 
-int drm_bo_driver_finish(drm_device_t * dev)
+int drm_bo_driver_finish(struct drm_device * dev)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_buffer_manager *bm = &dev->bm;
        int ret = 0;
        unsigned i = DRM_BO_MEM_TYPES;
-       drm_mem_type_manager_t *man;
+       struct drm_mem_type_manager *man;
 
-       mutex_lock(&dev->bm.init_mutex);
        mutex_lock(&dev->struct_mutex);
 
        if (!bm->initialized)
@@ -2112,17 +2188,24 @@ int drm_bo_driver_finish(drm_device_t * dev)
        }
       out:
        mutex_unlock(&dev->struct_mutex);
-       mutex_unlock(&dev->bm.init_mutex);
        return ret;
 }
+EXPORT_SYMBOL(drm_bo_driver_finish);
 
-int drm_bo_driver_init(drm_device_t * dev)
+/*
+ * This function is intended to be called on drm driver load.
+ * If you decide to call it from firstopen, you must protect the call
+ * from a potentially racing drm_bo_driver_finish in lastclose. 
+ * (This may happen on X server restart).
+ */
+
+int drm_bo_driver_init(struct drm_device * dev)
 {
-       drm_bo_driver_t *driver = dev->driver->bo_driver;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_bo_driver *driver = dev->driver->bo_driver;
+       struct drm_buffer_manager *bm = &dev->bm;
        int ret = -EINVAL;
 
-       mutex_lock(&dev->bm.init_mutex);
+       drm_bo_init_lock(&bm->bm_lock);
        mutex_lock(&dev->struct_mutex);
        if (!driver)
                goto out_unlock;
@@ -2131,8 +2214,7 @@ int drm_bo_driver_init(drm_device_t * dev)
         * Initialize the system memory buffer type.
         * Other types need to be driver / IOCTL initialized.
         */
-
-       ret = drm_bo_init_mm(dev, 0, 0, 0);
+       ret = drm_bo_init_mm(dev, DRM_BO_MEM_LOCAL, 0, 0);
        if (ret)
                goto out_unlock;
 
@@ -2149,87 +2231,155 @@ int drm_bo_driver_init(drm_device_t * dev)
        INIT_LIST_HEAD(&bm->ddestroy);
       out_unlock:
        mutex_unlock(&dev->struct_mutex);
-       mutex_unlock(&dev->bm.init_mutex);
        return ret;
 }
 
 EXPORT_SYMBOL(drm_bo_driver_init);
 
-int drm_mm_init_ioctl(DRM_IOCTL_ARGS)
+int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-
-       int ret = 0;
-       drm_mm_init_arg_t arg;
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_bo_driver_t *driver = dev->driver->bo_driver;
+       struct drm_mm_init_arg *arg = data;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_bo_driver *driver = dev->driver->bo_driver;
+       int ret;
 
        if (!driver) {
                DRM_ERROR("Buffer objects are not supported by this driver\n");
                return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
+       ret = drm_bo_write_lock(&bm->bm_lock, file_priv);
+       if (ret)
+               return ret;
 
-       switch (arg.req.op) {
-       case mm_init:
-               ret = -EINVAL;
-               mutex_lock(&dev->bm.init_mutex);
-               mutex_lock(&dev->struct_mutex);
-               if (!bm->initialized) {
-                       DRM_ERROR("DRM memory manager was not initialized.\n");
-                       break;
-               }
-               if (arg.req.mem_type == 0) {
-                       DRM_ERROR
-                           ("System memory buffers already initialized.\n");
-                       break;
-               }
-               ret = drm_bo_init_mm(dev, arg.req.mem_type,
-                                    arg.req.p_offset, arg.req.p_size);
-               break;
-       case mm_takedown:
-               LOCK_TEST_WITH_RETURN(dev, filp);
-               mutex_lock(&dev->bm.init_mutex);
-               mutex_lock(&dev->struct_mutex);
-               ret = -EINVAL;
-               if (!bm->initialized) {
-                       DRM_ERROR("DRM memory manager was not initialized\n");
-                       break;
-               }
-               if (arg.req.mem_type == 0) {
-                       DRM_ERROR("No takedown for System memory buffers.\n");
-                       break;
-               }
-               ret = 0;
-               if (drm_bo_clean_mm(dev, arg.req.mem_type)) {
-                       DRM_ERROR("Memory manager type %d not clean. "
-                                 "Delaying takedown\n", arg.req.mem_type);
-               }
-               break;
-       case mm_lock:
-               LOCK_TEST_WITH_RETURN(dev, filp);
-               mutex_lock(&dev->bm.init_mutex);
-               mutex_lock(&dev->struct_mutex);
-               ret = drm_bo_lock_mm(dev, arg.req.mem_type);
-               break;
-       case mm_unlock:
-               LOCK_TEST_WITH_RETURN(dev, filp);
-               mutex_lock(&dev->bm.init_mutex);
-               mutex_lock(&dev->struct_mutex);
-               ret = 0;
-               break;
-       default:
-               DRM_ERROR("Function not implemented yet\n");
+       ret = -EINVAL;
+       if (arg->magic != DRM_BO_INIT_MAGIC) {
+               DRM_ERROR("You are using an old libdrm that is not compatible with\n"
+                         "\tthe kernel DRM module. Please upgrade your libdrm.\n");
+               return -EINVAL;
+       }
+       if (arg->major != DRM_BO_INIT_MAJOR) {
+               DRM_ERROR("libdrm and kernel DRM buffer object interface major\n"
+                         "\tversion don't match. Got %d, expected %d.\n",
+                         arg->major, DRM_BO_INIT_MAJOR);
                return -EINVAL;
        }
 
+       mutex_lock(&dev->struct_mutex);
+       if (!bm->initialized) {
+               DRM_ERROR("DRM memory manager was not initialized.\n");
+               goto out;
+       }
+       if (arg->mem_type == 0) {
+               DRM_ERROR("System memory buffers already initialized.\n");
+               goto out;
+       }
+       ret = drm_bo_init_mm(dev, arg->mem_type,
+                            arg->p_offset, arg->p_size);
+
+out:
+       mutex_unlock(&dev->struct_mutex);
+       (void) drm_bo_write_unlock(&bm->bm_lock, file_priv);
+
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_mm_type_arg *arg = data;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_bo_driver *driver = dev->driver->bo_driver;
+       int ret;
+
+       if (!driver) {
+               DRM_ERROR("Buffer objects are not supported by this driver\n");
+               return -EINVAL;
+       }
+
+       ret = drm_bo_write_lock(&bm->bm_lock, file_priv);
+       if (ret)
+               return ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = -EINVAL;
+       if (!bm->initialized) {
+               DRM_ERROR("DRM memory manager was not initialized\n");
+               goto out;
+       }
+       if (arg->mem_type == 0) {
+               DRM_ERROR("No takedown for System memory buffers.\n");
+               goto out;
+       }
+       ret = 0;
+       if (drm_bo_clean_mm(dev, arg->mem_type)) {
+               DRM_ERROR("Memory manager type %d not clean. "
+                         "Delaying takedown\n", arg->mem_type);
+       }
+out:
        mutex_unlock(&dev->struct_mutex);
-       mutex_unlock(&dev->bm.init_mutex);
+       (void) drm_bo_write_unlock(&bm->bm_lock, file_priv);
+
        if (ret)
                return ret;
 
-       DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
+       return 0;
+}
+
+int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_mm_type_arg *arg = data;
+       struct drm_bo_driver *driver = dev->driver->bo_driver;
+       int ret;
+
+       if (!driver) {
+               DRM_ERROR("Buffer objects are not supported by this driver\n");
+               return -EINVAL;
+       }
+
+       if (arg->lock_flags & DRM_BO_LOCK_IGNORE_NO_EVICT) {
+               DRM_ERROR("Lock flag DRM_BO_LOCK_IGNORE_NO_EVICT not supported yet.\n");
+               return -EINVAL;
+       }
+               
+       if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) {
+               ret = drm_bo_write_lock(&dev->bm.bm_lock, file_priv);
+               if (ret)
+                       return ret;
+       }
+               
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_bo_lock_mm(dev, arg->mem_type);
+       mutex_unlock(&dev->struct_mutex);
+       if (ret) {
+               (void) drm_bo_write_unlock(&dev->bm.bm_lock, file_priv);
+               return ret;
+       }
+
+       return 0;
+}
+
+int drm_mm_unlock_ioctl(struct drm_device *dev, 
+                       void *data, 
+                       struct drm_file *file_priv)
+{
+       struct drm_mm_type_arg *arg = data;
+       struct drm_bo_driver *driver = dev->driver->bo_driver;
+       int ret;
+
+       if (!driver) {
+               DRM_ERROR("Buffer objects are not supported by this driver\n");
+               return -EINVAL;
+       }
+
+       if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) {
+               ret = drm_bo_write_unlock(&dev->bm.bm_lock, file_priv);
+               if (ret)
+                       return ret;
+       }
+               
        return 0;
 }
 
@@ -2237,10 +2387,10 @@ int drm_mm_init_ioctl(DRM_IOCTL_ARGS)
  * buffer object vm functions.
  */
 
-int drm_mem_reg_is_pci(drm_device_t * dev, drm_bo_mem_reg_t * mem)
+int drm_mem_reg_is_pci(struct drm_device * dev, struct drm_bo_mem_reg * mem)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_mem_type_manager_t *man = &bm->man[mem->mem_type];
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_mem_type_manager *man = &bm->man[mem->mem_type];
 
        if (!(man->flags & _DRM_FLAG_MEMTYPE_FIXED)) {
                if (mem->mem_type == DRM_BO_MEM_LOCAL)
@@ -2271,13 +2421,13 @@ EXPORT_SYMBOL(drm_mem_reg_is_pci);
  * Otherwise returns zero.
  */
 
-int drm_bo_pci_offset(drm_device_t * dev,
-                     drm_bo_mem_reg_t * mem,
+int drm_bo_pci_offset(struct drm_device *dev,
+                     struct drm_bo_mem_reg *mem,
                      unsigned long *bus_base,
                      unsigned long *bus_offset, unsigned long *bus_size)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_mem_type_manager_t *man = &bm->man[mem->mem_type];
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_mem_type_manager *man = &bm->man[mem->mem_type];
 
        *bus_size = 0;
        if (!(man->flags & _DRM_FLAG_MEMTYPE_MAPPABLE))
@@ -2300,9 +2450,9 @@ int drm_bo_pci_offset(drm_device_t * dev,
  * Call bo->mutex locked.
  */
 
-void drm_bo_unmap_virtual(drm_buffer_object_t * bo)
+void drm_bo_unmap_virtual(struct drm_buffer_object * bo)
 {
-       drm_device_t *dev = bo->dev;
+       struct drm_device *dev = bo->dev;
        loff_t offset = ((loff_t) bo->map_list.hash.key) << PAGE_SHIFT;
        loff_t holelen = ((loff_t) bo->mem.num_pages) << PAGE_SHIFT;
 
@@ -2312,12 +2462,13 @@ void drm_bo_unmap_virtual(drm_buffer_object_t * bo)
        unmap_mapping_range(dev->dev_mapping, offset, holelen, 1);
 }
 
-static void drm_bo_takedown_vm_locked(drm_buffer_object_t * bo)
+static void drm_bo_takedown_vm_locked(struct drm_buffer_object * bo)
 {
-       drm_map_list_t *list = &bo->map_list;
+       struct drm_map_list *list = &bo->map_list;
        drm_local_map_t *map;
-       drm_device_t *dev = bo->dev;
+       struct drm_device *dev = bo->dev;
 
+       DRM_ASSERT_LOCKED(&dev->struct_mutex);
        if (list->user_token) {
                drm_ht_remove_item(&dev->map_hash, &list->hash);
                list->user_token = 0;
@@ -2334,15 +2485,16 @@ static void drm_bo_takedown_vm_locked(drm_buffer_object_t * bo)
        drm_ctl_free(map, sizeof(*map), DRM_MEM_BUFOBJ);
        list->map = NULL;
        list->user_token = 0ULL;
-       drm_bo_usage_deref_locked(bo);
+       drm_bo_usage_deref_locked(&bo);
 }
 
-static int drm_bo_setup_vm_locked(drm_buffer_object_t * bo)
+static int drm_bo_setup_vm_locked(struct drm_buffer_object * bo)
 {
-       drm_map_list_t *list = &bo->map_list;
+       struct drm_map_list *list = &bo->map_list;
        drm_local_map_t *map;
-       drm_device_t *dev = bo->dev;
+       struct drm_device *dev = bo->dev;
 
+       DRM_ASSERT_LOCKED(&dev->struct_mutex);
        list->map = drm_ctl_calloc(1, sizeof(*map), DRM_MEM_BUFOBJ);
        if (!list->map)
                return -ENOMEM;
@@ -2372,7 +2524,19 @@ static int drm_bo_setup_vm_locked(drm_buffer_object_t * bo)
                return -ENOMEM;
        }
 
-       list->user_token = ((drm_u64_t) list->hash.key) << PAGE_SHIFT;
+       list->user_token = ((uint64_t) list->hash.key) << PAGE_SHIFT;
+
+       return 0;
+}
+
+int drm_bo_version_ioctl(struct drm_device *dev, void *data, 
+                        struct drm_file *file_priv)
+{
+       struct drm_bo_version_arg *arg = (struct drm_bo_version_arg *)data;
+       
+       arg->major = DRM_BO_INIT_MAJOR;
+       arg->minor = DRM_BO_INIT_MINOR;
+       arg->patchlevel = DRM_BO_INIT_PATCH;
 
        return 0;
 }
diff --git a/linux-core/drm_bo_lock.c b/linux-core/drm_bo_lock.c
new file mode 100644 (file)
index 0000000..e5a8682
--- /dev/null
@@ -0,0 +1,178 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+/*
+ * This file implements a simple replacement for the buffer manager use
+ * of the heavyweight hardware lock.
+ * The lock is a read-write lock. Taking it in read mode is fast, and 
+ * intended for in-kernel use only.
+ * Taking it in write mode is slow.
+ *
+ * The write mode is used only when there is a need to block all 
+ * user-space processes from allocating a 
+ * new memory area.
+ * Typical use in write mode is X server VT switching, and it's allowed
+ * to leave kernel space with the write lock held. If a user-space process
+ * dies while having the write-lock, it will be released during the file
+ * descriptor release.
+ *
+ * The read lock is typically placed at the start of an IOCTL- or 
+ * user-space callable function that may end up allocating a memory area.
+ * This includes setstatus, super-ioctls and no_pfn; the latter may move
+ * unmappable regions to mappable. It's a bug to leave kernel space with the
+ * read lock held.
+ *
+ * Both read- and write lock taking is interruptible for low signal-delivery
+ * latency. The locking functions will return -EAGAIN if interrupted by a
+ * signal.
+ *
+ * Locking order: The lock should be taken BEFORE any kernel mutexes 
+ * or spinlocks.
+ */
+
+#include "drmP.h"
+
+void drm_bo_init_lock(struct drm_bo_lock *lock)
+{
+       DRM_INIT_WAITQUEUE(&lock->queue);
+       atomic_set(&lock->write_lock_pending, 0);
+       atomic_set(&lock->readers, 0);
+}
+
+void drm_bo_read_unlock(struct drm_bo_lock *lock)
+{
+       if (unlikely(atomic_add_negative(-1, &lock->readers)))
+               BUG();
+       if (atomic_read(&lock->readers) == 0)
+               wake_up_interruptible(&lock->queue);
+}
+
+EXPORT_SYMBOL(drm_bo_read_unlock);
+
+int drm_bo_read_lock(struct drm_bo_lock *lock)
+{
+       while (unlikely(atomic_read(&lock->write_lock_pending) != 0)) {
+               int ret;
+               ret = wait_event_interruptible
+                   (lock->queue, atomic_read(&lock->write_lock_pending) == 0);
+               if (ret)
+                       return -EAGAIN;
+       }
+
+       while (unlikely(!atomic_add_unless(&lock->readers, 1, -1))) {
+               int ret;
+               ret = wait_event_interruptible
+                   (lock->queue, atomic_add_unless(&lock->readers, 1, -1));
+               if (ret)
+                       return -EAGAIN;
+       }
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_bo_read_lock);
+
+static int __drm_bo_write_unlock(struct drm_bo_lock *lock)
+{
+       if (unlikely(atomic_cmpxchg(&lock->readers, -1, 0) != -1))
+               return -EINVAL;
+       if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 1, 0) != 1))
+               return -EINVAL;
+       wake_up_interruptible(&lock->queue);
+       return 0;
+}
+
+static void drm_bo_write_lock_remove(struct drm_file *file_priv,
+                                    struct drm_user_object *item)
+{
+       struct drm_bo_lock *lock = container_of(item, struct drm_bo_lock, base);
+       int ret;
+
+       ret = __drm_bo_write_unlock(lock);
+       BUG_ON(ret);
+}
+
+int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv)
+{
+       int ret = 0;
+       struct drm_device *dev;
+
+       if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 0, 1) != 0)) {
+               return -EINVAL;
+       }
+
+       while (unlikely(atomic_cmpxchg(&lock->readers, 0, -1) != 0)) {
+               ret = wait_event_interruptible
+                   (lock->queue, atomic_cmpxchg(&lock->readers, 0, -1) == 0);
+
+               if (ret) {
+                       atomic_set(&lock->write_lock_pending, 0);
+                       wake_up_interruptible(&lock->queue);
+                       return -EAGAIN;
+               }
+       }
+
+       /*
+        * Add a dummy user-object, the destructor of which will
+        * make sure the lock is released if the client dies 
+        * while holding it.
+        */
+
+       dev = file_priv->head->dev;
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_add_user_object(file_priv, &lock->base, 0);
+       lock->base.remove = &drm_bo_write_lock_remove;
+       lock->base.type = drm_lock_type;
+       if (ret) {
+               (void)__drm_bo_write_unlock(lock);
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+
+int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv)
+{
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_ref_object *ro;
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (lock->base.owner != file_priv) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+       ro = drm_lookup_ref_object(file_priv, &lock->base, _DRM_REF_USE);
+       BUG_ON(!ro);
+       drm_remove_ref_object(file_priv, ro);
+       lock->base.owner = NULL;
+
+       mutex_unlock(&dev->struct_mutex);
+       return 0;
+}
index 4f75206..06b2e5a 100644 (file)
@@ -35,9 +35,9 @@
  * have not been requested to free also pinned regions.
  */
 
-static void drm_bo_free_old_node(drm_buffer_object_t * bo)
+static void drm_bo_free_old_node(struct drm_buffer_object * bo)
 {
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
 
        if (old_mem->mm_node && (old_mem->mm_node != bo->pinned_node)) {
                mutex_lock(&bo->dev->struct_mutex);
@@ -48,13 +48,13 @@ static void drm_bo_free_old_node(drm_buffer_object_t * bo)
        old_mem->mm_node = NULL;
 }
 
-int drm_bo_move_ttm(drm_buffer_object_t * bo,
-                   int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
+int drm_bo_move_ttm(struct drm_buffer_object * bo,
+                   int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
 {
-       drm_ttm_t *ttm = bo->ttm;
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
-       uint32_t save_flags = old_mem->flags;
-       uint32_t save_mask = old_mem->mask;
+       struct drm_ttm *ttm = bo->ttm;
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
+       uint64_t save_flags = old_mem->flags;
+       uint64_t save_mask = old_mem->mask;
        int ret;
 
        if (old_mem->mem_type == DRM_BO_MEM_TT) {
@@ -71,9 +71,7 @@ int drm_bo_move_ttm(drm_buffer_object_t * bo,
                save_flags = old_mem->flags;
        }
        if (new_mem->mem_type != DRM_BO_MEM_LOCAL) {
-               ret = drm_bind_ttm(ttm,
-                                  new_mem->flags & DRM_BO_FLAG_CACHED,
-                                  new_mem->mm_node->start);
+               ret = drm_bind_ttm(ttm, new_mem);
                if (ret)
                        return ret;
        }
@@ -102,11 +100,11 @@ EXPORT_SYMBOL(drm_bo_move_ttm);
  * Call bo->mutex locked.
  */
 
-int drm_mem_reg_ioremap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
+int drm_mem_reg_ioremap(struct drm_device * dev, struct drm_bo_mem_reg * mem,
                        void **virtual)
 {
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_mem_type_manager_t *man = &bm->man[mem->mem_type];
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_mem_type_manager *man = &bm->man[mem->mem_type];
        unsigned long bus_offset;
        unsigned long bus_size;
        unsigned long bus_base;
@@ -128,6 +126,7 @@ int drm_mem_reg_ioremap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
        *virtual = addr;
        return 0;
 }
+EXPORT_SYMBOL(drm_mem_reg_ioremap);
 
 /**
  * \c Unmap mapping obtained using drm_bo_ioremap
@@ -137,11 +136,11 @@ int drm_mem_reg_ioremap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
  * Call bo->mutex locked.
  */
 
-void drm_mem_reg_iounmap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
+void drm_mem_reg_iounmap(struct drm_device * dev, struct drm_bo_mem_reg * mem,
                         void *virtual)
 {
-       drm_buffer_manager_t *bm;
-       drm_mem_type_manager_t *man;
+       struct drm_buffer_manager *bm;
+       struct drm_mem_type_manager *man;
 
        bm = &dev->bm;
        man = &bm->man[mem->mem_type];
@@ -150,6 +149,7 @@ void drm_mem_reg_iounmap(drm_device_t * dev, drm_bo_mem_reg_t * mem,
                iounmap(virtual);
        }
 }
+EXPORT_SYMBOL(drm_mem_reg_iounmap);
 
 static int drm_copy_io_page(void *dst, void *src, unsigned long page)
 {
@@ -164,7 +164,7 @@ static int drm_copy_io_page(void *dst, void *src, unsigned long page)
        return 0;
 }
 
-static int drm_copy_io_ttm_page(drm_ttm_t * ttm, void *src, unsigned long page)
+static int drm_copy_io_ttm_page(struct drm_ttm * ttm, void *src, unsigned long page)
 {
        struct page *d = drm_ttm_get_page(ttm, page);
        void *dst;
@@ -182,7 +182,7 @@ static int drm_copy_io_ttm_page(drm_ttm_t * ttm, void *src, unsigned long page)
        return 0;
 }
 
-static int drm_copy_ttm_io_page(drm_ttm_t * ttm, void *dst, unsigned long page)
+static int drm_copy_ttm_io_page(struct drm_ttm * ttm, void *dst, unsigned long page)
 {
        struct page *s = drm_ttm_get_page(ttm, page);
        void *src;
@@ -200,19 +200,19 @@ static int drm_copy_ttm_io_page(drm_ttm_t * ttm, void *dst, unsigned long page)
        return 0;
 }
 
-int drm_bo_move_memcpy(drm_buffer_object_t * bo,
-                      int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
+int drm_bo_move_memcpy(struct drm_buffer_object * bo,
+                      int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
 {
-       drm_device_t *dev = bo->dev;
-       drm_mem_type_manager_t *man = &dev->bm.man[new_mem->mem_type];
-       drm_ttm_t *ttm = bo->ttm;
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
-       drm_bo_mem_reg_t old_copy = *old_mem;
+       struct drm_device *dev = bo->dev;
+       struct drm_mem_type_manager *man = &dev->bm.man[new_mem->mem_type];
+       struct drm_ttm *ttm = bo->ttm;
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
+       struct drm_bo_mem_reg old_copy = *old_mem;
        void *old_iomap;
        void *new_iomap;
        int ret;
-       uint32_t save_flags = old_mem->flags;
-       uint32_t save_mask = old_mem->mask;
+       uint64_t save_flags = old_mem->flags;
+       uint64_t save_mask = old_mem->mask;
        unsigned long i;
        unsigned long page;
        unsigned long add = 0;
@@ -281,12 +281,12 @@ EXPORT_SYMBOL(drm_bo_move_memcpy);
  * object. Call bo->mutex locked.
  */
 
-int drm_buffer_object_transfer(drm_buffer_object_t * bo,
-                              drm_buffer_object_t ** new_obj)
+int drm_buffer_object_transfer(struct drm_buffer_object * bo,
+                              struct drm_buffer_object ** new_obj)
 {
-       drm_buffer_object_t *fbo;
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
+       struct drm_buffer_object *fbo;
+       struct drm_device *dev = bo->dev;
+       struct drm_buffer_manager *bm = &dev->bm;
 
        fbo = drm_ctl_calloc(1, sizeof(*fbo), DRM_MEM_BUFOBJ);
        if (!fbo)
@@ -306,7 +306,7 @@ int drm_buffer_object_transfer(drm_buffer_object_t * bo,
        INIT_LIST_HEAD(&fbo->p_mm_list);
 #endif
 
-       atomic_inc(&bo->fence->usage);
+       drm_fence_reference_unlocked(&fbo->fence, bo->fence);
        fbo->pinned_node = NULL;
        fbo->mem.mm_node->private = (void *)fbo;
        atomic_set(&fbo->usage, 1);
@@ -323,26 +323,27 @@ int drm_buffer_object_transfer(drm_buffer_object_t * bo,
  * We cannot restart until it has finished.
  */
 
-int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
+int drm_bo_move_accel_cleanup(struct drm_buffer_object * bo,
                              int evict,
                              int no_wait,
                              uint32_t fence_class,
                              uint32_t fence_type,
-                             uint32_t fence_flags, drm_bo_mem_reg_t * new_mem)
+                             uint32_t fence_flags, struct drm_bo_mem_reg * new_mem)
 {
-       drm_device_t *dev = bo->dev;
-       drm_mem_type_manager_t *man = &dev->bm.man[new_mem->mem_type];
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       struct drm_device *dev = bo->dev;
+       struct drm_mem_type_manager *man = &dev->bm.man[new_mem->mem_type];
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
        int ret;
-       uint32_t save_flags = old_mem->flags;
-       uint32_t save_mask = old_mem->mask;
-       drm_buffer_object_t *old_obj;
+       uint64_t save_flags = old_mem->flags;
+       uint64_t save_mask = old_mem->mask;
+       struct drm_buffer_object *old_obj;
 
        if (bo->fence)
-               drm_fence_usage_deref_unlocked(dev, bo->fence);
+               drm_fence_usage_deref_unlocked(&bo->fence);
        ret = drm_fence_object_create(dev, fence_class, fence_type,
                                      fence_flags | DRM_FENCE_FLAG_EMIT,
                                      &bo->fence);
+       bo->fence_type = fence_type;
        if (ret)
                return ret;
 
@@ -396,7 +397,7 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
                DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
                drm_bo_add_to_lru(old_obj);
 
-               drm_bo_usage_deref_locked(old_obj);
+               drm_bo_usage_deref_locked(&old_obj);
                mutex_unlock(&dev->struct_mutex);
 
        }
@@ -409,3 +410,194 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
 }
 
 EXPORT_SYMBOL(drm_bo_move_accel_cleanup);
+
+int drm_bo_same_page(unsigned long offset,
+                    unsigned long offset2)
+{
+       return (offset & PAGE_MASK) == (offset2 & PAGE_MASK);
+}
+EXPORT_SYMBOL(drm_bo_same_page);
+
+unsigned long drm_bo_offset_end(unsigned long offset,
+                               unsigned long end)
+{
+
+       offset = (offset + PAGE_SIZE) & PAGE_MASK;
+       return (end < offset) ? end : offset;
+}
+EXPORT_SYMBOL(drm_bo_offset_end);
+
+
+static pgprot_t drm_kernel_io_prot(uint32_t map_type)
+{
+       pgprot_t tmp = PAGE_KERNEL;
+
+#if defined(__i386__) || defined(__x86_64__)
+#ifdef USE_PAT_WC
+#warning using pat
+       if (drm_use_pat() && map_type == _DRM_TTM) {
+               pgprot_val(tmp) |= _PAGE_PAT;
+               return tmp;
+       }
+#endif
+       if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
+               pgprot_val(tmp) |= _PAGE_PCD;
+               pgprot_val(tmp) &= ~_PAGE_PWT;
+       }
+#elif defined(__powerpc__)
+       pgprot_val(tmp) |= _PAGE_NO_CACHE;
+       if (map_type == _DRM_REGISTERS)
+               pgprot_val(tmp) |= _PAGE_GUARDED;
+#endif
+#if defined(__ia64__)
+       if (map_type == _DRM_TTM)
+               tmp = pgprot_writecombine(tmp);
+       else
+               tmp = pgprot_noncached(tmp);
+#endif
+       return tmp;
+}
+
+static int drm_bo_ioremap(struct drm_buffer_object *bo, unsigned long bus_base,
+                         unsigned long bus_offset, unsigned long bus_size,
+                         struct drm_bo_kmap_obj *map)
+{
+       struct drm_device *dev = bo->dev;
+       struct drm_bo_mem_reg *mem = &bo->mem;
+       struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type];
+
+       if (!(man->flags & _DRM_FLAG_NEEDS_IOREMAP)) {
+               map->bo_kmap_type = bo_map_premapped;
+               map->virtual = (void *)(((u8 *) man->io_addr) + bus_offset);
+       } else {
+               map->bo_kmap_type = bo_map_iomap;
+               map->virtual = ioremap_nocache(bus_base + bus_offset, bus_size);
+       }
+       return (!map->virtual) ? -ENOMEM : 0;
+}
+
+static int drm_bo_kmap_ttm(struct drm_buffer_object *bo, unsigned long start_page,
+                          unsigned long num_pages, struct drm_bo_kmap_obj *map)
+{
+       struct drm_device *dev = bo->dev;
+       struct drm_bo_mem_reg *mem = &bo->mem;
+       struct drm_mem_type_manager *man = &dev->bm.man[mem->mem_type];
+       pgprot_t prot;
+       struct drm_ttm *ttm = bo->ttm;
+       struct page *d;
+       int i;
+
+       BUG_ON(!ttm);
+
+       if (num_pages == 1 && (mem->flags & DRM_BO_FLAG_CACHED)) {
+
+               /*
+                * We're mapping a single page, and the desired
+                * page protection is consistent with the bo.
+                */
+
+               map->bo_kmap_type = bo_map_kmap;
+               map->page = drm_ttm_get_page(ttm, start_page);
+               map->virtual = kmap(map->page);
+       } else {
+               /*
+                * Populate the part we're mapping;
+                */
+
+               for (i = start_page; i< start_page + num_pages; ++i) {
+                       d = drm_ttm_get_page(ttm, i);
+                       if (!d)
+                               return -ENOMEM;
+               }
+
+               /*
+                * We need to use vmap to get the desired page protection
+                * or to make the buffer object look contigous.
+                */
+
+               prot = (mem->flags & DRM_BO_FLAG_CACHED) ?
+                       PAGE_KERNEL :
+                       drm_kernel_io_prot(man->drm_bus_maptype);
+               map->bo_kmap_type = bo_map_vmap;
+               map->virtual = vmap(ttm->pages + start_page,
+                                   num_pages, 0, prot);
+       }
+       return (!map->virtual) ? -ENOMEM : 0;
+}
+
+/*
+ * This function is to be used for kernel mapping of buffer objects.
+ * It chooses the appropriate mapping method depending on the memory type
+ * and caching policy the buffer currently has.
+ * Mapping multiple pages or buffers that live in io memory is a bit slow and
+ * consumes vmalloc space. Be restrictive with such mappings.
+ * Mapping single pages usually returns the logical kernel address, (which is fast)
+ * BUG may use slower temporary mappings for high memory pages or
+ * uncached / write-combined pages.
+ *
+ * The function fills in a drm_bo_kmap_obj which can be used to return the
+ * kernel virtual address of the buffer.
+ *
+ * Code servicing a non-priviliged user request is only allowed to map one
+ * page at a time. We might need to implement a better scheme to stop such
+ * processes from consuming all vmalloc space.
+ */
+
+int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
+               unsigned long num_pages, struct drm_bo_kmap_obj *map)
+{
+       int ret;
+       unsigned long bus_base;
+       unsigned long bus_offset;
+       unsigned long bus_size;
+
+       map->virtual = NULL;
+
+       if (num_pages > bo->num_pages)
+               return -EINVAL;
+       if (start_page > bo->num_pages)
+               return -EINVAL;
+#if 0
+       if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC))
+               return -EPERM;
+#endif
+       ret = drm_bo_pci_offset(bo->dev, &bo->mem, &bus_base,
+                               &bus_offset, &bus_size);
+
+       if (ret)
+               return ret;
+
+       if (bus_size == 0) {
+               return drm_bo_kmap_ttm(bo, start_page, num_pages, map);
+       } else {
+               bus_offset += start_page << PAGE_SHIFT;
+               bus_size = num_pages << PAGE_SHIFT;
+               return drm_bo_ioremap(bo, bus_base, bus_offset, bus_size, map);
+       }
+}
+EXPORT_SYMBOL(drm_bo_kmap);
+
+void drm_bo_kunmap(struct drm_bo_kmap_obj *map)
+{
+       if (!map->virtual)
+               return;
+
+       switch(map->bo_kmap_type) {
+       case bo_map_iomap:
+               iounmap(map->virtual);
+               break;
+       case bo_map_vmap:
+               vunmap(map->virtual);
+               break;
+       case bo_map_kmap:
+               kunmap(map->page);
+               break;
+       case bo_map_premapped:
+               break;
+       default:
+               BUG();
+       }
+       map->virtual = NULL;
+       map->page = NULL;
+}
+EXPORT_SYMBOL(drm_bo_kunmap);
index a2c8a75..dc7f342 100644 (file)
 #include <linux/vmalloc.h>
 #include "drmP.h"
 
-unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource)
 {
        return pci_resource_start(dev->pdev, resource);
 }
 EXPORT_SYMBOL(drm_get_resource_start);
 
-unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource)
 {
        return pci_resource_len(dev->pdev, resource);
 }
 EXPORT_SYMBOL(drm_get_resource_len);
 
-static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
-                                             drm_local_map_t *map)
+struct drm_map_list *drm_find_matching_map(struct drm_device *dev, drm_local_map_t *map)
 {
-       drm_map_list_t *entry;
+       struct drm_map_list *entry;
        list_for_each_entry(entry, &dev->maplist, head) {
                if (entry->map && map->type == entry->map->type &&
                    ((entry->map->offset == map->offset) || 
-                    (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
+                    ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) {
                        return entry;
                }
        }
 
        return NULL;
 }
+EXPORT_SYMBOL(drm_find_matching_map);
 
-static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
+static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
                          unsigned long user_token, int hashed_handle)
 {
        int use_hashed_handle;
@@ -92,7 +92,7 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
  * Ioctl to specify a range of memory that is available for mapping by a non-root process.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_map structure.
  * \return zero on success or a negative value on error.
@@ -101,12 +101,13 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
  * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
  * applicable and if supported by the kernel.
  */
-static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
-                   unsigned int size, drm_map_type_t type,
-                   drm_map_flags_t flags, drm_map_list_t ** maplist)
+static int drm_addmap_core(struct drm_device *dev, unsigned int offset,
+                          unsigned int size, enum drm_map_type type,
+                          enum drm_map_flags flags,
+                          struct drm_map_list **maplist)
 {
-       drm_map_t *map;
-       drm_map_list_t *list;
+       struct drm_map *map;
+       struct drm_map_list *list;
        drm_dma_handle_t *dmah;
        unsigned long user_token;
        int ret;
@@ -212,7 +213,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
                }
                break;
        case _DRM_AGP: {
-               drm_agp_mem_t *entry;
+               struct drm_agp_mem *entry;
                int valid = 0;
 
                if (!drm_core_has_AGP(dev)) {
@@ -222,11 +223,17 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
 #ifdef __alpha__
                map->offset += dev->hose->mem_space->start;
 #endif
-               /* Note: dev->agp->base may actually be 0 when the DRM
-                * is not in control of AGP space. But if user space is
-                * it should already have added the AGP base itself.
+               /* In some cases (i810 driver), user space may have already
+                * added the AGP base itself, because dev->agp->base previously
+                * only got set during AGP enable.  So, only add the base
+                * address if the map's offset isn't already within the
+                * aperture.
                 */
-               map->offset += dev->agp->base;
+               if (map->offset < dev->agp->base ||
+                   map->offset > dev->agp->base +
+                   dev->agp->agp_info.aper_size * 1024 * 1024 - 1) {
+                       map->offset += dev->agp->base;
+               }
                map->mtrr = dev->agp->agp_mtrr; /* for getmap */
 
                /* This assumes the DRM is in total control of AGP space.
@@ -310,11 +317,11 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
        return 0;
 }
 
-int drm_addmap(drm_device_t * dev, unsigned int offset,
-              unsigned int size, drm_map_type_t type,
-              drm_map_flags_t flags, drm_local_map_t ** map_ptr)
+int drm_addmap(struct drm_device *dev, unsigned int offset,
+              unsigned int size, enum drm_map_type type,
+              enum drm_map_flags flags, drm_local_map_t ** map_ptr)
 {
-       drm_map_list_t *list;
+       struct drm_map_list *list;
        int rc;
 
        rc = drm_addmap_core(dev, offset, size, type, flags, &list);
@@ -325,38 +332,24 @@ int drm_addmap(drm_device_t * dev, unsigned int offset,
 
 EXPORT_SYMBOL(drm_addmap);
 
-int drm_addmap_ioctl(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+int drm_addmap_ioctl(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_map_t map;
-       drm_map_list_t *maplist;
-       drm_map_t __user *argp = (void __user *)arg;
+       struct drm_map *map = data;
+       struct drm_map_list *maplist;
        int err;
 
-       if (!(filp->f_mode & 3))
-               return -EACCES; /* Require read/write */
-
-       if (copy_from_user(&map, argp, sizeof(map))) {
-               return -EFAULT;
-       }
-
-       if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP))
+       if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP))
                return -EPERM;
 
-       err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
-                             &maplist);
+       err = drm_addmap_core(dev, map->offset, map->size, map->type,
+                             map->flags, &maplist);
 
        if (err)
                return err;
 
-       if (copy_to_user(argp, maplist->map, sizeof(drm_map_t)))
-               return -EFAULT;
-
        /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
-       if (put_user((void *)(unsigned long)maplist->user_token, &argp->handle))
-               return -EFAULT;
+       map->handle = (void *)(unsigned long)maplist->user_token;
        return 0;
 }
 
@@ -365,9 +358,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
  * isn't in use.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
- * \param arg pointer to a drm_map_t structure.
+ * \param arg pointer to a struct drm_map structure.
  * \return zero on success or a negative value on error.
  *
  * Searches the map on drm_device::maplist, removes it from the list, see if
@@ -376,9 +369,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
  *
  * \sa drm_addmap
  */
-int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
 {
-       drm_map_list_t *r_list = NULL, *list_t;
+       struct drm_map_list *r_list = NULL, *list_t;
        drm_dma_handle_t dmah;
        int found = 0;
 
@@ -414,6 +407,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
                break;
        case _DRM_SHM:
                vfree(map->handle);
+               dev->sigdata.lock = dev->lock.hw_lock = NULL;   /* SHM removed */
                break;
        case _DRM_AGP:
        case _DRM_SCATTER_GATHER:
@@ -433,7 +427,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
 }
 EXPORT_SYMBOL(drm_rmmap_locked);
 
-int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
+int drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
 {
        int ret;
 
@@ -454,24 +448,18 @@ EXPORT_SYMBOL(drm_rmmap);
  * gets used by drivers that the server doesn't need to care about.  This seems
  * unlikely.
  */
-int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg)
+int drm_rmmap_ioctl(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_map_t request;
+       struct drm_map *request = data;
        drm_local_map_t *map = NULL;
-       drm_map_list_t *r_list;
+       struct drm_map_list *r_list;
        int ret;
 
-       if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
-               return -EFAULT;
-       }
-
        mutex_lock(&dev->struct_mutex);
        list_for_each_entry(r_list, &dev->maplist, head) {
                if (r_list->map &&
-                   r_list->user_token == (unsigned long)request.handle &&
+                   r_list->user_token == (unsigned long)request->handle &&
                    r_list->map->flags & _DRM_REMOVABLE) {
                        map = r_list->map;
                        break;
@@ -486,11 +474,6 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       if (!map) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
        /* Register and framebuffer maps are permanent */
        if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
                mutex_unlock(&dev->struct_mutex);
@@ -512,7 +495,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
  *
  * Frees any pages and buffers associated with the given entry.
  */
-static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
+static void drm_cleanup_buf_error(struct drm_device *dev, struct drm_buf_entry * entry)
 {
        int i;
 
@@ -549,20 +532,20 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry)
 /**
  * Add AGP buffers for DMA transfers
  *
- * \param dev drm_device_t to which the buffers are to be added.
- * \param request pointer to a drm_buf_desc_t describing the request.
+ * \param dev struct drm_device to which the buffers are to be added.
+ * \param request pointer to a struct drm_buf_desc describing the request.
  * \return zero on success or a negative number on failure.
  *
  * After some sanity checks creates a drm_buf structure for each buffer and
  * reallocates the buffer list of the same size order to accommodate the new
  * buffers.
  */
-int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request)
 {
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_entry_t *entry;
-       drm_agp_mem_t *agp_entry;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_entry *entry;
+       struct drm_agp_mem *agp_entry;
+       struct drm_buf *buf;
        unsigned long offset;
        unsigned long agp_offset;
        int count;
@@ -573,7 +556,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
        int total;
        int byte_count;
        int i, valid;
-       drm_buf_t **temp_buflist;
+       struct drm_buf **temp_buflist;
 
        if (!dma)
                return -EINVAL;
@@ -666,7 +649,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
                buf->waiting = 0;
                buf->pending = 0;
                init_waitqueue_head(&buf->dma_wait);
-               buf->filp = NULL;
+               buf->file_priv = NULL;
 
                buf->dev_priv_size = dev->driver->dev_priv_size;
                buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
@@ -727,24 +710,24 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
 EXPORT_SYMBOL(drm_addbufs_agp);
 #endif                         /* __OS_HAS_AGP */
 
-int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int count;
        int order;
        int size;
        int total;
        int page_order;
-       drm_buf_entry_t *entry;
+       struct drm_buf_entry *entry;
        drm_dma_handle_t *dmah;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        int alignment;
        unsigned long offset;
        int i;
        int byte_count;
        int page_count;
        unsigned long *temp_pagelist;
-       drm_buf_t **temp_buflist;
+       struct drm_buf **temp_buflist;
 
        if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
                return -EINVAL;
@@ -877,7 +860,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
                        buf->waiting = 0;
                        buf->pending = 0;
                        init_waitqueue_head(&buf->dma_wait);
-                       buf->filp = NULL;
+                       buf->file_priv = NULL;
 
                        buf->dev_priv_size = dev->driver->dev_priv_size;
                        buf->dev_private = drm_alloc(buf->dev_priv_size,
@@ -953,11 +936,11 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
 }
 EXPORT_SYMBOL(drm_addbufs_pci);
 
-static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc * request)
 {
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_entry_t *entry;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_entry *entry;
+       struct drm_buf *buf;
        unsigned long offset;
        unsigned long agp_offset;
        int count;
@@ -968,7 +951,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
        int total;
        int byte_count;
        int i;
-       drm_buf_t **temp_buflist;
+       struct drm_buf **temp_buflist;
 
        if (!drm_core_check_feature(dev, DRIVER_SG))
                return -EINVAL;
@@ -1055,7 +1038,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
                buf->waiting = 0;
                buf->pending = 0;
                init_waitqueue_head(&buf->dma_wait);
-               buf->filp = NULL;
+               buf->file_priv = NULL;
 
                buf->dev_priv_size = dev->driver->dev_priv_size;
                buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
@@ -1115,11 +1098,11 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
        return 0;
 }
 
-int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+int drm_addbufs_fb(struct drm_device *dev, struct drm_buf_desc *request)
 {
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_entry_t *entry;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_entry *entry;
+       struct drm_buf *buf;
        unsigned long offset;
        unsigned long agp_offset;
        int count;
@@ -1130,7 +1113,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
        int total;
        int byte_count;
        int i;
-       drm_buf_t **temp_buflist;
+       struct drm_buf **temp_buflist;
 
        if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
                return -EINVAL;
@@ -1216,7 +1199,7 @@ int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
                buf->waiting = 0;
                buf->pending = 0;
                init_waitqueue_head(&buf->dma_wait);
-               buf->filp = NULL;
+               buf->file_priv = NULL;
 
                buf->dev_priv_size = dev->driver->dev_priv_size;
                buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
@@ -1281,9 +1264,9 @@ EXPORT_SYMBOL(drm_addbufs_fb);
  * Add buffers for DMA transfers (ioctl).
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
- * \param arg pointer to a drm_buf_desc_t request.
+ * \param arg pointer to a struct drm_buf_desc request.
  * \return zero on success or a negative number on failure.
  *
  * According with the memory type specified in drm_buf_desc::flags and the
@@ -1291,39 +1274,27 @@ EXPORT_SYMBOL(drm_addbufs_fb);
  * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
  * PCI memory respectively.
  */
-int drm_addbufs(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+int drm_addbufs(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
 {
-       drm_buf_desc_t request;
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
+       struct drm_buf_desc *request = data;
        int ret;
 
        if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
                return -EINVAL;
 
-       if (copy_from_user(&request, (drm_buf_desc_t __user *) arg,
-                          sizeof(request)))
-               return -EFAULT;
-
 #if __OS_HAS_AGP
-       if (request.flags & _DRM_AGP_BUFFER)
-               ret = drm_addbufs_agp(dev, &request);
+       if (request->flags & _DRM_AGP_BUFFER)
+               ret = drm_addbufs_agp(dev, request);
        else
 #endif
-       if (request.flags & _DRM_SG_BUFFER)
-               ret = drm_addbufs_sg(dev, &request);
-       else if (request.flags & _DRM_FB_BUFFER)
-               ret = drm_addbufs_fb(dev, &request);
+       if (request->flags & _DRM_SG_BUFFER)
+               ret = drm_addbufs_sg(dev, request);
+       else if (request->flags & _DRM_FB_BUFFER)
+               ret = drm_addbufs_fb(dev, request);
        else
-               ret = drm_addbufs_pci(dev, &request);
+               ret = drm_addbufs_pci(dev, request);
 
-       if (ret == 0) {
-               if (copy_to_user((void __user *) arg, &request,
-                                 sizeof(request))) {
-                       ret = -EFAULT;
-               }
-       }
        return ret;
 }
 
@@ -1335,7 +1306,7 @@ int drm_addbufs(struct inode *inode, struct file *filp,
  * large buffers can be used for image transfer).
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_buf_info structure.
  * \return zero on success or a negative number on failure.
@@ -1344,14 +1315,11 @@ int drm_addbufs(struct inode *inode, struct file *filp,
  * lock, preventing of allocating more buffers after this call. Information
  * about each requested buffer is then copied into user space.
  */
-int drm_infobufs(struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+int drm_infobufs(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_info_t request;
-       drm_buf_info_t __user *argp = (void __user *)arg;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_info *request = data;
        int i;
        int count;
 
@@ -1369,9 +1337,6 @@ int drm_infobufs(struct inode *inode, struct file *filp,
        ++dev->buf_use;         /* Can't allocate more after this call */
        spin_unlock(&dev->count_lock);
 
-       if (copy_from_user(&request, argp, sizeof(request)))
-               return -EFAULT;
-
        for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
                if (dma->bufs[i].buf_count)
                        ++count;
@@ -1379,13 +1344,13 @@ int drm_infobufs(struct inode *inode, struct file *filp,
 
        DRM_DEBUG("count = %d\n", count);
 
-       if (request.count >= count) {
+       if (request->count >= count) {
                for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
                        if (dma->bufs[i].buf_count) {
-                               drm_buf_desc_t __user *to =
-                                   &request.list[count];
-                               drm_buf_entry_t *from = &dma->bufs[i];
-                               drm_freelist_t *list = &dma->bufs[i].freelist;
+                               struct drm_buf_desc __user *to =
+                                   &request->list[count];
+                               struct drm_buf_entry *from = &dma->bufs[i];
+                               struct drm_freelist *list = &dma->bufs[i].freelist;
                                if (copy_to_user(&to->count,
                                                 &from->buf_count,
                                                 sizeof(from->buf_count)) ||
@@ -1410,10 +1375,7 @@ int drm_infobufs(struct inode *inode, struct file *filp,
                        }
                }
        }
-       request.count = count;
-
-       if (copy_to_user(argp, &request, sizeof(request)))
-               return -EFAULT;
+       request->count = count;
 
        return 0;
 }
@@ -1422,7 +1384,7 @@ int drm_infobufs(struct inode *inode, struct file *filp,
  * Specifies a low and high water mark for buffer allocation
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg a pointer to a drm_buf_desc structure.
  * \return zero on success or a negative number on failure.
@@ -1432,15 +1394,13 @@ int drm_infobufs(struct inode *inode, struct file *filp,
  *
  * \note This ioctl is deprecated and mostly never used.
  */
-int drm_markbufs(struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+int drm_markbufs(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_desc_t request;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_desc *request = data;
        int order;
-       drm_buf_entry_t *entry;
+       struct drm_buf_entry *entry;
 
        if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
                return -EINVAL;
@@ -1448,24 +1408,20 @@ int drm_markbufs(struct inode *inode, struct file *filp,
        if (!dma)
                return -EINVAL;
 
-       if (copy_from_user(&request,
-                          (drm_buf_desc_t __user *) arg, sizeof(request)))
-               return -EFAULT;
-
        DRM_DEBUG("%d, %d, %d\n",
-                 request.size, request.low_mark, request.high_mark);
-       order = drm_order(request.size);
+                 request->size, request->low_mark, request->high_mark);
+       order = drm_order(request->size);
        if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
                return -EINVAL;
        entry = &dma->bufs[order];
 
-       if (request.low_mark < 0 || request.low_mark > entry->buf_count)
+       if (request->low_mark < 0 || request->low_mark > entry->buf_count)
                return -EINVAL;
-       if (request.high_mark < 0 || request.high_mark > entry->buf_count)
+       if (request->high_mark < 0 || request->high_mark > entry->buf_count)
                return -EINVAL;
 
-       entry->freelist.low_mark = request.low_mark;
-       entry->freelist.high_mark = request.high_mark;
+       entry->freelist.low_mark = request->low_mark;
+       entry->freelist.high_mark = request->high_mark;
 
        return 0;
 }
@@ -1474,7 +1430,7 @@ int drm_markbufs(struct inode *inode, struct file *filp,
  * Unreserve the buffers in list, previously reserved using drmDMA.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_buf_free structure.
  * \return zero on success or a negative number on failure.
@@ -1482,16 +1438,14 @@ int drm_markbufs(struct inode *inode, struct file *filp,
  * Calls free_buffer() for each used buffer.
  * This function is primarily used for debugging.
  */
-int drm_freebufs(struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+int drm_freebufs(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_free_t request;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_free *request = data;
        int i;
        int idx;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
 
        if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
                return -EINVAL;
@@ -1499,13 +1453,9 @@ int drm_freebufs(struct inode *inode, struct file *filp,
        if (!dma)
                return -EINVAL;
 
-       if (copy_from_user(&request,
-                          (drm_buf_free_t __user *) arg, sizeof(request)))
-               return -EFAULT;
-
-       DRM_DEBUG("%d\n", request.count);
-       for (i = 0; i < request.count; i++) {
-               if (copy_from_user(&idx, &request.list[i], sizeof(idx)))
+       DRM_DEBUG("%d\n", request->count);
+       for (i = 0; i < request->count; i++) {
+               if (copy_from_user(&idx, &request->list[i], sizeof(idx)))
                        return -EFAULT;
                if (idx < 0 || idx >= dma->buf_count) {
                        DRM_ERROR("Index %d (of %d max)\n",
@@ -1513,7 +1463,7 @@ int drm_freebufs(struct inode *inode, struct file *filp,
                        return -EINVAL;
                }
                buf = dma->buflist[idx];
-               if (buf->filp != filp) {
+               if (buf->file_priv != file_priv) {
                        DRM_ERROR("Process %d freeing buffer not owned\n",
                                  current->pid);
                        return -EINVAL;
@@ -1528,7 +1478,7 @@ int drm_freebufs(struct inode *inode, struct file *filp,
  * Maps all of the DMA buffers into client-virtual space (ioctl).
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg pointer to a drm_buf_map structure.
  * \return zero on success or a negative number on failure.
@@ -1538,18 +1488,15 @@ int drm_freebufs(struct inode *inode, struct file *filp,
  * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
  * drm_mmap_dma().
  */
-int drm_mapbufs(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+int drm_mapbufs(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_map_t __user *argp = (void __user *)arg;
+       struct drm_device_dma *dma = dev->dma;
        int retcode = 0;
        const int zero = 0;
        unsigned long virtual;
        unsigned long address;
-       drm_buf_map_t request;
+       struct drm_buf_map *request = data;
        int i;
 
        if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
@@ -1566,16 +1513,13 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
        dev->buf_use++;         /* Can't allocate more after this call */
        spin_unlock(&dev->count_lock);
 
-       if (copy_from_user(&request, argp, sizeof(request)))
-               return -EFAULT;
-
-       if (request.count >= dma->buf_count) {
+       if (request->count >= dma->buf_count) {
                if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
                    || (drm_core_check_feature(dev, DRIVER_SG)
                        && (dma->flags & _DRM_DMA_USE_SG))
                    || (drm_core_check_feature(dev, DRIVER_FB_DMA)
                        && (dma->flags & _DRM_DMA_USE_FB))) {
-                       drm_map_t *map = dev->agp_buffer_map;
+                       struct drm_map *map = dev->agp_buffer_map;
                        unsigned long token = dev->agp_buffer_token;
 
                        if (!map) {
@@ -1583,14 +1527,14 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
                                goto done;
                        }
                        down_write(&current->mm->mmap_sem);
-                       virtual = do_mmap(filp, 0, map->size,
+                       virtual = do_mmap(file_priv->filp, 0, map->size,
                                          PROT_READ | PROT_WRITE,
                                          MAP_SHARED,
                                          token);
                        up_write(&current->mm->mmap_sem);
                } else {
                        down_write(&current->mm->mmap_sem);
-                       virtual = do_mmap(filp, 0, dma->byte_count,
+                       virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
                                          PROT_READ | PROT_WRITE,
                                          MAP_SHARED, 0);
                        up_write(&current->mm->mmap_sem);
@@ -1600,28 +1544,28 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
                        retcode = (signed long)virtual;
                        goto done;
                }
-               request.virtual = (void __user *)virtual;
+               request->virtual = (void __user *)virtual;
 
                for (i = 0; i < dma->buf_count; i++) {
-                       if (copy_to_user(&request.list[i].idx,
+                       if (copy_to_user(&request->list[i].idx,
                                         &dma->buflist[i]->idx,
-                                        sizeof(request.list[0].idx))) {
+                                        sizeof(request->list[0].idx))) {
                                retcode = -EFAULT;
                                goto done;
                        }
-                       if (copy_to_user(&request.list[i].total,
+                       if (copy_to_user(&request->list[i].total,
                                         &dma->buflist[i]->total,
-                                        sizeof(request.list[0].total))) {
+                                        sizeof(request->list[0].total))) {
                                retcode = -EFAULT;
                                goto done;
                        }
-                       if (copy_to_user(&request.list[i].used,
+                       if (copy_to_user(&request->list[i].used,
                                         &zero, sizeof(zero))) {
                                retcode = -EFAULT;
                                goto done;
                        }
                        address = virtual + dma->buflist[i]->offset;    /* *** */
-                       if (copy_to_user(&request.list[i].address,
+                       if (copy_to_user(&request->list[i].address,
                                         &address, sizeof(address))) {
                                retcode = -EFAULT;
                                goto done;
@@ -1629,11 +1573,8 @@ int drm_mapbufs(struct inode *inode, struct file *filp,
                }
        }
       done:
-       request.count = dma->buf_count;
-       DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
-
-       if (copy_to_user(argp, &request, sizeof(request)))
-               return -EFAULT;
+       request->count = dma->buf_count;
+       DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
 
        return retcode;
 }
index 9ac5658..ae44e50 100644 (file)
@@ -196,21 +196,24 @@ static int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
        return ret;
 }
 
-static struct page *drm_bo_vm_fault(struct vm_area_struct *vma, 
+
+static struct page *drm_bo_vm_fault(struct vm_area_struct *vma,
                                    struct fault_data *data)
 {
        unsigned long address = data->address;
-       drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
+       struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
        unsigned long page_offset;
        struct page *page = NULL;
-       drm_ttm_t *ttm; 
-       drm_device_t *dev;
+       struct drm_ttm *ttm; 
+       struct drm_device *dev;
        unsigned long pfn;
        int err;
        unsigned long bus_base;
        unsigned long bus_offset;
        unsigned long bus_size;
        
+       dev = bo->dev;
+       while(drm_bo_read_lock(&dev->bm.bm_lock));
 
        mutex_lock(&bo->mutex);
 
@@ -261,7 +264,7 @@ static struct page *drm_bo_vm_fault(struct vm_area_struct *vma,
        page_offset = (address - vma->vm_start) >> PAGE_SHIFT;
 
        if (bus_size) {
-               drm_mem_type_manager_t *man = &dev->bm.man[bo->mem.mem_type];
+               struct drm_mem_type_manager *man = &dev->bm.man[bo->mem.mem_type];
 
                pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) + page_offset;
                vma->vm_page_prot = drm_io_prot(man->drm_bus_maptype, vma);
@@ -288,6 +291,7 @@ static struct page *drm_bo_vm_fault(struct vm_area_struct *vma,
                data->type = VM_FAULT_OOM;
 out_unlock:
        mutex_unlock(&bo->mutex);
+       drm_bo_read_unlock(&dev->bm.bm_lock);
        return NULL;
 }
 
@@ -350,11 +354,11 @@ struct page *drm_bo_vm_nopage(struct vm_area_struct *vma,
                               unsigned long address, 
                               int *type)
 {
-       drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
+       struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
        unsigned long page_offset;
        struct page *page;
-       drm_ttm_t *ttm; 
-       drm_device_t *dev;
+       struct drm_ttm *ttm; 
+       struct drm_device *dev;
 
        mutex_lock(&bo->mutex);
 
@@ -394,7 +398,7 @@ out_unlock:
 
 int drm_bo_map_bound(struct vm_area_struct *vma)
 {
-       drm_buffer_object_t *bo = (drm_buffer_object_t *)vma->vm_private_data;
+       struct drm_buffer_object *bo = (struct drm_buffer_object *)vma->vm_private_data;
        int ret = 0;
        unsigned long bus_base;
        unsigned long bus_offset;
@@ -405,7 +409,7 @@ int drm_bo_map_bound(struct vm_area_struct *vma)
        BUG_ON(ret);
 
        if (bus_size) {
-               drm_mem_type_manager_t *man = &bo->dev->bm.man[bo->mem.mem_type];
+               struct drm_mem_type_manager *man = &bo->dev->bm.man[bo->mem.mem_type];
                unsigned long pfn = (bus_base + bus_offset) >> PAGE_SHIFT;
                pgprot_t pgprot = drm_io_prot(man->drm_bus_maptype, vma);
                ret = io_remap_pfn_range(vma, vma->vm_start, pfn,
@@ -417,7 +421,7 @@ int drm_bo_map_bound(struct vm_area_struct *vma)
 }
        
 
-int drm_bo_add_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
+int drm_bo_add_vma(struct drm_buffer_object * bo, struct vm_area_struct *vma)
 {
        p_mm_entry_t *entry, *n_entry;
        vma_entry_t *v_entry;
@@ -453,7 +457,7 @@ int drm_bo_add_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
        return 0;
 }
 
-void drm_bo_delete_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
+void drm_bo_delete_vma(struct drm_buffer_object * bo, struct vm_area_struct *vma)
 {
        p_mm_entry_t *entry, *n;
        vma_entry_t *v_entry, *v_n;
@@ -485,7 +489,7 @@ void drm_bo_delete_vma(drm_buffer_object_t * bo, struct vm_area_struct *vma)
 
 
 
-int drm_bo_lock_kmm(drm_buffer_object_t * bo)
+int drm_bo_lock_kmm(struct drm_buffer_object * bo)
 {
        p_mm_entry_t *entry;
        int lock_ok = 1;
@@ -517,7 +521,7 @@ int drm_bo_lock_kmm(drm_buffer_object_t * bo)
        return -EAGAIN;
 }
 
-void drm_bo_unlock_kmm(drm_buffer_object_t * bo)
+void drm_bo_unlock_kmm(struct drm_buffer_object * bo)
 {
        p_mm_entry_t *entry;
        
@@ -528,7 +532,7 @@ void drm_bo_unlock_kmm(drm_buffer_object_t * bo)
        }
 }
 
-int drm_bo_remap_bound(drm_buffer_object_t *bo) 
+int drm_bo_remap_bound(struct drm_buffer_object *bo) 
 {
        vma_entry_t *v_entry;
        int ret = 0;
@@ -544,7 +548,7 @@ int drm_bo_remap_bound(drm_buffer_object_t *bo)
        return ret;
 }
 
-void drm_bo_finish_unmap(drm_buffer_object_t *bo)
+void drm_bo_finish_unmap(struct drm_buffer_object *bo)
 {
        vma_entry_t *v_entry;
 
@@ -555,3 +559,173 @@ void drm_bo_finish_unmap(drm_buffer_object_t *bo)
 
 #endif
 
+#ifdef DRM_IDR_COMPAT_FN
+/* only called when idp->lock is held */
+static void __free_layer(struct idr *idp, struct idr_layer *p)
+{
+       p->ary[0] = idp->id_free;
+       idp->id_free = p;
+       idp->id_free_cnt++;
+}
+
+static void free_layer(struct idr *idp, struct idr_layer *p)
+{
+       unsigned long flags;
+
+       /*
+        * Depends on the return element being zeroed.
+        */
+       spin_lock_irqsave(&idp->lock, flags);
+       __free_layer(idp, p);
+       spin_unlock_irqrestore(&idp->lock, flags);
+}
+
+/**
+ * idr_for_each - iterate through all stored pointers
+ * @idp: idr handle
+ * @fn: function to be called for each pointer
+ * @data: data passed back to callback function
+ *
+ * Iterate over the pointers registered with the given idr.  The
+ * callback function will be called for each pointer currently
+ * registered, passing the id, the pointer and the data pointer passed
+ * to this function.  It is not safe to modify the idr tree while in
+ * the callback, so functions such as idr_get_new and idr_remove are
+ * not allowed.
+ *
+ * We check the return of @fn each time. If it returns anything other
+ * than 0, we break out and return that value.
+ *
+* The caller must serialize idr_find() vs idr_get_new() and idr_remove().
+ */
+int idr_for_each(struct idr *idp,
+                int (*fn)(int id, void *p, void *data), void *data)
+{
+       int n, id, max, error = 0;
+       struct idr_layer *p;
+       struct idr_layer *pa[MAX_LEVEL];
+       struct idr_layer **paa = &pa[0];
+
+       n = idp->layers * IDR_BITS;
+       p = idp->top;
+       max = 1 << n;
+
+       id = 0;
+       while (id < max) {
+               while (n > 0 && p) {
+                       n -= IDR_BITS;
+                       *paa++ = p;
+                       p = p->ary[(id >> n) & IDR_MASK];
+               }
+
+               if (p) {
+                       error = fn(id, (void *)p, data);
+                       if (error)
+                               break;
+               }
+
+               id += 1 << n;
+               while (n < fls(id)) {
+                       n += IDR_BITS;
+                       p = *--paa;
+               }
+       }
+
+       return error;
+}
+EXPORT_SYMBOL(idr_for_each);
+
+/**
+ * idr_remove_all - remove all ids from the given idr tree
+ * @idp: idr handle
+ *
+ * idr_destroy() only frees up unused, cached idp_layers, but this
+ * function will remove all id mappings and leave all idp_layers
+ * unused.
+ *
+ * A typical clean-up sequence for objects stored in an idr tree, will
+ * use idr_for_each() to free all objects, if necessay, then
+ * idr_remove_all() to remove all ids, and idr_destroy() to free
+ * up the cached idr_layers.
+ */
+void idr_remove_all(struct idr *idp)
+{
+       int n, id, max, error = 0;
+       struct idr_layer *p;
+       struct idr_layer *pa[MAX_LEVEL];
+       struct idr_layer **paa = &pa[0];
+
+       n = idp->layers * IDR_BITS;
+       p = idp->top;
+       max = 1 << n;
+
+       id = 0;
+       while (id < max && !error) {
+               while (n > IDR_BITS && p) {
+                       n -= IDR_BITS;
+                       *paa++ = p;
+                       p = p->ary[(id >> n) & IDR_MASK];
+               }
+
+               id += 1 << n;
+               while (n < fls(id)) {
+                       if (p) {
+                               memset(p, 0, sizeof *p);
+                               free_layer(idp, p);
+                       }
+                       n += IDR_BITS;
+                       p = *--paa;
+               }
+       }
+       idp->top = NULL;
+       idp->layers = 0;
+}
+EXPORT_SYMBOL(idr_remove_all);
+
+#endif /* DRM_IDR_COMPAT_FN */
+
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
+/**
+ * idr_replace - replace pointer for given id
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the id
+ * @id: lookup key
+ *
+ * Replace the pointer registered with an id and return the old value.
+ * A -ENOENT return indicates that @id was not found.
+ * A -EINVAL return indicates that @id was not within valid constraints.
+ *
+ * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove().
+ */
+void *idr_replace(struct idr *idp, void *ptr, int id)
+{
+       int n;
+       struct idr_layer *p, *old_p;
+
+       n = idp->layers * IDR_BITS;
+       p = idp->top;
+
+       id &= MAX_ID_MASK;
+
+       if (id >= (1 << n))
+               return ERR_PTR(-EINVAL);
+
+       n -= IDR_BITS;
+       while ((n > 0) && p) {
+               p = p->ary[(id >> n) & IDR_MASK];
+               n -= IDR_BITS;
+       }
+
+       n = id & IDR_MASK;
+       if (unlikely(p == NULL || !test_bit(n, &p->bitmap)))
+               return ERR_PTR(-ENOENT);
+
+       old_p = p->ary[n];
+       p->ary[n] = ptr;
+
+       return (void *)old_p;
+}
+EXPORT_SYMBOL(idr_replace);
+#endif
index bc5fadc..0895e5e 100644 (file)
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
 #undef DRM_IRQ_ARGS
 #define DRM_IRQ_ARGS           int irq, void *arg, struct pt_regs *regs
+
+typedef _Bool bool;
+enum {
+        false   = 0,
+        true    = 1
+};
+
 #endif
 
 #ifndef list_for_each_safe
@@ -193,7 +200,10 @@ extern void drm_clear_vma(struct vm_area_struct *vma,
 extern pgprot_t vm_get_page_prot(unsigned long vm_flags);
 
 #ifndef GFP_DMA32
-#define GFP_DMA32 0
+#define GFP_DMA32 GFP_KERNEL
+#endif
+#ifndef __GFP_DMA32
+#define __GFP_DMA32 GFP_KERNEL
 #endif
 
 #if defined(CONFIG_X86) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
@@ -305,4 +315,24 @@ extern int drm_bo_remap_bound(struct drm_buffer_object *bo);
 extern int drm_bo_map_bound(struct vm_area_struct *vma);
 
 #endif
+
+/* fixme when functions are upstreamed - upstreamed for 2.6.23 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
+#define DRM_IDR_COMPAT_FN
+#endif
+#ifdef DRM_IDR_COMPAT_FN
+int idr_for_each(struct idr *idp,
+                int (*fn)(int id, void *p, void *data), void *data);
+void idr_remove_all(struct idr *idp);
+#endif
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
+void *idr_replace(struct idr *idp, void *ptr, int id);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+typedef _Bool                   bool;
+#endif
+
 #endif
index 5cb79b1..7854e89 100644 (file)
  * \param ctx_handle context handle.
  *
  * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_mutex
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
  * lock.
  */
-void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
+void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
 {
-       struct drm_ctx_sarea_list *ctx_sarea;
-
        mutex_lock(&dev->struct_mutex);
-       ctx_sarea = idr_find(&dev->ctx_idr, ctx_handle);
-       if (ctx_sarea) {
-               idr_remove(&dev->ctx_idr, ctx_handle);
-               list_del(&ctx_sarea->head);
-               drm_free(ctx_sarea, sizeof(struct drm_ctx_sarea_list), DRM_MEM_BUFS);
-       } else
-               DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
+       idr_remove(&dev->ctx_idr, ctx_handle);
        mutex_unlock(&dev->struct_mutex);
-       return;
 }
 
 /**
@@ -78,37 +69,28 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
  * \param dev DRM device.
  * \return (non-negative) context handle on success or a negative number on failure.
  *
- * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
- * drm_device::context_sareas to accommodate the new entry while holding the
+ * Allocate a new idr from drm_device::ctx_idr while holding the
  * drm_device::struct_mutex lock.
  */
-static int drm_ctxbitmap_next(drm_device_t * dev)
+static int drm_ctxbitmap_next(struct drm_device *dev)
 {
        int new_id;
        int ret;
-       struct drm_ctx_sarea_list *new_ctx;
-
-       new_ctx = drm_calloc(1, sizeof(struct drm_ctx_sarea_list), DRM_MEM_BUFS);
-       if (!new_ctx)
-               return -1;
 
 again:
        if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
                DRM_ERROR("Out of memory expanding drawable idr\n");
-               drm_free(new_ctx, sizeof(struct drm_ctx_sarea_list), DRM_MEM_BUFS);
                return -ENOMEM;
        }
        mutex_lock(&dev->struct_mutex);
-       ret = idr_get_new_above(&dev->ctx_idr, new_ctx, DRM_RESERVED_CONTEXTS, &new_id);
+       ret = idr_get_new_above(&dev->ctx_idr, NULL,
+                               DRM_RESERVED_CONTEXTS, &new_id);
        if (ret == -EAGAIN) {
                mutex_unlock(&dev->struct_mutex);
                goto again;
        }
        
        mutex_unlock(&dev->struct_mutex);
-
-       new_ctx->ctx_id = new_id;
-       list_add(&new_ctx->head, &dev->context_sarealist);
        return new_id;
 }
 
@@ -117,14 +99,11 @@ again:
  *
  * \param dev DRM device.
  *
- * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Initialise the drm_device::ctx_idr
  */
-int drm_ctxbitmap_init(drm_device_t * dev)
+int drm_ctxbitmap_init(struct drm_device *dev)
 {
        idr_init(&dev->ctx_idr);
-       INIT_LIST_HEAD(&dev->context_sarealist);
-
        return 0;
 }
 
@@ -133,18 +112,13 @@ int drm_ctxbitmap_init(drm_device_t * dev)
  *
  * \param dev DRM device.
  *
- * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
  */
-void drm_ctxbitmap_cleanup(drm_device_t * dev)
+void drm_ctxbitmap_cleanup(struct drm_device *dev)
 {
-       struct drm_ctx_sarea_list *ctx_entry, *ctx_temp;
-
        mutex_lock(&dev->struct_mutex);
-       list_for_each_entry_safe(ctx_entry, ctx_temp, &dev->context_sarealist, head) {
-               idr_remove(&dev->ctx_idr, ctx_entry->ctx_id);
-               drm_free(ctx_entry, sizeof(struct drm_ctx_sarea_list), DRM_MEM_MAPS);
-       }
+       idr_remove_all(&dev->ctx_idr);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -158,52 +132,42 @@ void drm_ctxbitmap_cleanup(drm_device_t * dev)
  * Get per-context SAREA.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx_priv_map structure.
  * \return zero on success or a negative number on failure.
  *
- * Gets the map from drm_device::context_sareas with the handle specified and
+ * Gets the map from drm_device::ctx_idr with the handle specified and
  * returns its handle.
  */
-int drm_getsareactx(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg)
+int drm_getsareactx(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_ctx_priv_map_t __user *argp = (void __user *)arg;
-       drm_ctx_priv_map_t request;
-       drm_map_t *map;
-       drm_map_list_t *_entry;
-       struct drm_ctx_sarea_list *ctx_sarea;
-
-       if (copy_from_user(&request, argp, sizeof(request)))
-               return -EFAULT;
+       struct drm_ctx_priv_map *request = data;
+       struct drm_map *map;
+       struct drm_map_list *_entry;
 
        mutex_lock(&dev->struct_mutex);
 
-       ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id);
-       if (!ctx_sarea) {
+       map = idr_find(&dev->ctx_idr, request->ctx_id);
+       if (!map) {
                mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
        }
-       
-       map = ctx_sarea->map;
+
        mutex_unlock(&dev->struct_mutex);
 
-       request.handle = NULL;
+       request->handle = NULL;
        list_for_each_entry(_entry, &dev->maplist, head) {
                if (_entry->map == map) {
-                       request.handle = 
+                       request->handle = 
                            (void *)(unsigned long)_entry->user_token;
                        break;
                }
        }
-       if (request.handle == NULL)
+       if (request->handle == NULL)
                return -EINVAL;
 
-       if (copy_to_user(argp, &request, sizeof(request)))
-               return -EFAULT;
        return 0;
 }
 
@@ -211,32 +175,25 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
  * Set per-context SAREA.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx_priv_map structure.
  * \return zero on success or a negative number on failure.
  *
  * Searches the mapping specified in \p arg and update the entry in
- * drm_device::context_sareas with it.
+ * drm_device::ctx_idr with it.
  */
-int drm_setsareactx(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg)
+int drm_setsareactx(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_ctx_priv_map_t request;
-       drm_map_t *map = NULL;
-       drm_map_list_t *r_list = NULL;
-       struct drm_ctx_sarea_list *ctx_sarea;
-
-       if (copy_from_user(&request,
-                          (drm_ctx_priv_map_t __user *) arg, sizeof(request)))
-               return -EFAULT;
+       struct drm_ctx_priv_map *request = data;
+       struct drm_map *map = NULL;
+       struct drm_map_list *r_list = NULL;
 
        mutex_lock(&dev->struct_mutex);
        list_for_each_entry(r_list, &dev->maplist, head) {
                if (r_list->map
-                   && r_list->user_token == (unsigned long) request.handle)
+                   && r_list->user_token == (unsigned long) request->handle)
                        goto found;
        }
       bad:
@@ -248,15 +205,11 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
        if (!map)
                goto bad;
 
-       mutex_lock(&dev->struct_mutex);
-
-       ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id);
-       if (!ctx_sarea) {
+       if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
                goto bad;
-       }
-       
-       ctx_sarea->map = map;
+
        mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -276,7 +229,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
  *
  * Attempt to set drm_device::context_flag.
  */
-static int drm_context_switch(drm_device_t * dev, int old, int new)
+static int drm_context_switch(struct drm_device *dev, int old, int new)
 {
        if (test_and_set_bit(0, &dev->context_flag)) {
                DRM_ERROR("Reentering -- FIXME\n");
@@ -304,7 +257,7 @@ static int drm_context_switch(drm_device_t * dev, int old, int new)
  * hardware lock is held, clears the drm_device::context_flag and wakes up
  * drm_device::context_wait.
  */
-static int drm_context_switch_complete(drm_device_t * dev, int new)
+static int drm_context_switch_complete(struct drm_device *dev, int new)
 {
        dev->last_context = new;        /* PRE/POST: This is the _only_ writer. */
        dev->last_switch = jiffies;
@@ -326,34 +279,28 @@ static int drm_context_switch_complete(drm_device_t * dev, int new)
  * Reserve contexts.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx_res structure.
  * \return zero on success or a negative number on failure.
  */
-int drm_resctx(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_resctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
 {
-       drm_ctx_res_t res;
-       drm_ctx_t __user *argp = (void __user *)arg;
-       drm_ctx_t ctx;
+       struct drm_ctx_res *res = data;
+       struct drm_ctx ctx;
        int i;
 
-       if (copy_from_user(&res, argp, sizeof(res)))
-               return -EFAULT;
-
-       if (res.count >= DRM_RESERVED_CONTEXTS) {
+       if (res->count >= DRM_RESERVED_CONTEXTS) {
                memset(&ctx, 0, sizeof(ctx));
                for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
                        ctx.handle = i;
-                       if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx)))
+                       if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
                                return -EFAULT;
                }
        }
-       res.count = DRM_RESERVED_CONTEXTS;
+       res->count = DRM_RESERVED_CONTEXTS;
 
-       if (copy_to_user(argp, &res, sizeof(res)))
-               return -EFAULT;
        return 0;
 }
 
@@ -361,40 +308,34 @@ int drm_resctx(struct inode *inode, struct file *filp,
  * Add context.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx structure.
  * \return zero on success or a negative number on failure.
  *
  * Get a new handle for the context and copy to userspace.
  */
-int drm_addctx(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_addctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_ctx_list_t *ctx_entry;
-       drm_ctx_t __user *argp = (void __user *)arg;
-       drm_ctx_t ctx;
+       struct drm_ctx_list *ctx_entry;
+       struct drm_ctx *ctx = data;
 
-       if (copy_from_user(&ctx, argp, sizeof(ctx)))
-               return -EFAULT;
-
-       ctx.handle = drm_ctxbitmap_next(dev);
-       if (ctx.handle == DRM_KERNEL_CONTEXT) {
+       ctx->handle = drm_ctxbitmap_next(dev);
+       if (ctx->handle == DRM_KERNEL_CONTEXT) {
                /* Skip kernel's context and get a new one. */
-               ctx.handle = drm_ctxbitmap_next(dev);
+               ctx->handle = drm_ctxbitmap_next(dev);
        }
-       DRM_DEBUG("%d\n", ctx.handle);
-       if (ctx.handle == -1) {
+       DRM_DEBUG("%d\n", ctx->handle);
+       if (ctx->handle == -1) {
                DRM_DEBUG("Not enough free contexts.\n");
                /* Should this return -EBUSY instead? */
                return -ENOMEM;
        }
 
-       if (ctx.handle != DRM_KERNEL_CONTEXT) {
+       if (ctx->handle != DRM_KERNEL_CONTEXT) {
                if (dev->driver->context_ctor)
-                       if (!dev->driver->context_ctor(dev, ctx.handle)) {
+                       if (!dev->driver->context_ctor(dev, ctx->handle)) {
                                DRM_DEBUG("Running out of ctxs or memory.\n");
                                return -ENOMEM;
                        }
@@ -407,21 +348,18 @@ int drm_addctx(struct inode *inode, struct file *filp,
        }
 
        INIT_LIST_HEAD(&ctx_entry->head);
-       ctx_entry->handle = ctx.handle;
-       ctx_entry->tag = priv;
+       ctx_entry->handle = ctx->handle;
+       ctx_entry->tag = file_priv;
 
        mutex_lock(&dev->ctxlist_mutex);
        list_add(&ctx_entry->head, &dev->ctxlist);
        ++dev->ctx_count;
        mutex_unlock(&dev->ctxlist_mutex);
 
-       if (copy_to_user(argp, &ctx, sizeof(ctx)))
-               return -EFAULT;
        return 0;
 }
 
-int drm_modctx(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        /* This does nothing */
        return 0;
@@ -431,25 +369,18 @@ int drm_modctx(struct inode *inode, struct file *filp,
  * Get context.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx structure.
  * \return zero on success or a negative number on failure.
  */
-int drm_getctx(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_ctx_t __user *argp = (void __user *)arg;
-       drm_ctx_t ctx;
-
-       if (copy_from_user(&ctx, argp, sizeof(ctx)))
-               return -EFAULT;
+       struct drm_ctx *ctx = data;
 
        /* This is 0, because we don't handle any context flags */
-       ctx.flags = 0;
+       ctx->flags = 0;
 
-       if (copy_to_user(argp, &ctx, sizeof(ctx)))
-               return -EFAULT;
        return 0;
 }
 
@@ -457,50 +388,40 @@ int drm_getctx(struct inode *inode, struct file *filp,
  * Switch context.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx structure.
  * \return zero on success or a negative number on failure.
  *
  * Calls context_switch().
  */
-int drm_switchctx(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int drm_switchctx(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_ctx_t ctx;
-
-       if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
-               return -EFAULT;
+       struct drm_ctx *ctx = data;
 
-       DRM_DEBUG("%d\n", ctx.handle);
-       return drm_context_switch(dev, dev->last_context, ctx.handle);
+       DRM_DEBUG("%d\n", ctx->handle);
+       return drm_context_switch(dev, dev->last_context, ctx->handle);
 }
 
 /**
  * New context.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx structure.
  * \return zero on success or a negative number on failure.
  *
  * Calls context_switch_complete().
  */
-int drm_newctx(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_newctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_ctx_t ctx;
+       struct drm_ctx *ctx = data;
 
-       if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
-               return -EFAULT;
-
-       DRM_DEBUG("%d\n", ctx.handle);
-       drm_context_switch_complete(dev, ctx.handle);
+       DRM_DEBUG("%d\n", ctx->handle);
+       drm_context_switch_complete(dev, ctx->handle);
 
        return 0;
 }
@@ -509,39 +430,34 @@ int drm_newctx(struct inode *inode, struct file *filp,
  * Remove context.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument pointing to a drm_ctx structure.
  * \return zero on success or a negative number on failure.
  *
  * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
  */
-int drm_rmctx(struct inode *inode, struct file *filp,
-             unsigned int cmd, unsigned long arg)
+int drm_rmctx(struct drm_device *dev, void *data,
+             struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_ctx_t ctx;
-
-       if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
-               return -EFAULT;
+       struct drm_ctx *ctx = data;
 
-       DRM_DEBUG("%d\n", ctx.handle);
-       if (ctx.handle == DRM_KERNEL_CONTEXT + 1) {
-               priv->remove_auth_on_close = 1;
+       DRM_DEBUG("%d\n", ctx->handle);
+       if (ctx->handle == DRM_KERNEL_CONTEXT + 1) {
+               file_priv->remove_auth_on_close = 1;
        }
-       if (ctx.handle != DRM_KERNEL_CONTEXT) {
+       if (ctx->handle != DRM_KERNEL_CONTEXT) {
                if (dev->driver->context_dtor)
-                       dev->driver->context_dtor(dev, ctx.handle);
-               drm_ctxbitmap_free(dev, ctx.handle);
+                       dev->driver->context_dtor(dev, ctx->handle);
+               drm_ctxbitmap_free(dev, ctx->handle);
        }
 
        mutex_lock(&dev->ctxlist_mutex);
        if (!list_empty(&dev->ctxlist)) {
-               drm_ctx_list_t *pos, *n;
+               struct drm_ctx_list *pos, *n;
 
                list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-                       if (pos->handle == ctx.handle) {
+                       if (pos->handle == ctx->handle) {
                                list_del(&pos->head);
                                drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
                                --dev->ctx_count;
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
new file mode 100644 (file)
index 0000000..5bc0220
--- /dev/null
@@ -0,0 +1,1872 @@
+/*
+ * Copyright (c) 2006-2007 Intel Corporation
+ * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
+ *
+ * DRM core CRTC related functions
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Authors:
+ *      Keith Packard
+ *     Eric Anholt <eric@anholt.net>
+ *      Dave Airlie <airlied@linux.ie>
+ *      Jesse Barnes <jesse.barnes@intel.com>
+ */
+#include <linux/list.h>
+#include "drm.h"
+#include "drmP.h"
+#include "drm_crtc.h"
+
+/**
+ * drm_idr_get - allocate a new identifier
+ * @dev: DRM device
+ * @ptr: object pointer, used to generate unique ID
+ *
+ * LOCKING:
+ * Caller must hold DRM mode_config lock.
+ *
+ * Create a unique identifier based on @ptr in @dev's identifier space.  Used
+ * for tracking modes, CRTCs and outputs.
+ *
+ * RETURNS:
+ * New unique (relative to other objects in @dev) integer identifier for the
+ * object.
+ */
+int drm_idr_get(struct drm_device *dev, void *ptr)
+{
+       int new_id = 0;
+       int ret;
+again:
+       if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Ran out memory getting a mode number\n");
+               return 0;
+       }
+
+       ret = idr_get_new_above(&dev->mode_config.crtc_idr, ptr, 1, &new_id);
+       if (ret == -EAGAIN)
+               goto again;     
+
+       return new_id;
+}
+
+/**
+ * drm_idr_put - free an identifer
+ * @dev: DRM device
+ * @id: ID to free
+ *
+ * LOCKING:
+ * Caller must hold DRM mode_config lock.
+ *
+ * Free @id from @dev's unique identifier pool.
+ */
+void drm_idr_put(struct drm_device *dev, int id)
+{
+       idr_remove(&dev->mode_config.crtc_idr, id);
+}
+
+/**
+ * drm_crtc_from_fb - find the CRTC structure associated with an fb
+ * @dev: DRM device
+ * @fb: framebuffer in question
+ *
+ * LOCKING:
+ * Caller must hold mode_config lock.
+ *
+ * Find CRTC in the mode_config structure that matches @fb.
+ *
+ * RETURNS:
+ * Pointer to the CRTC or NULL if it wasn't found.
+ */
+struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
+                                 struct drm_framebuffer *fb)
+{
+       struct drm_crtc *crtc;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (crtc->fb == fb)
+                       return crtc;
+       }
+       return NULL;
+}
+
+/**
+ * drm_framebuffer_create - create a new framebuffer object
+ * @dev: DRM device
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Creates a new framebuffer objects and adds it to @dev's DRM mode_config.
+ *
+ * RETURNS:
+ * Pointer to new framebuffer or NULL on error.
+ */
+struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev)
+{
+       struct drm_framebuffer *fb;
+
+       /* Limit to single framebuffer for now */
+       if (dev->mode_config.num_fb > 1) {
+               mutex_unlock(&dev->mode_config.mutex);
+               DRM_ERROR("Attempt to add multiple framebuffers failed\n");
+               return NULL;
+       }
+
+       fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL);
+       if (!fb)
+               return NULL;
+       
+       fb->id = drm_idr_get(dev, fb);
+       fb->dev = dev;
+       dev->mode_config.num_fb++;
+       list_add(&fb->head, &dev->mode_config.fb_list);
+
+       return fb;
+}
+EXPORT_SYMBOL(drm_framebuffer_create);
+
+/**
+ * drm_framebuffer_destroy - remove a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
+ * it, setting it to NULL.
+ */
+void drm_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+       struct drm_device *dev = fb->dev;
+       struct drm_crtc *crtc;
+
+       /* remove from any CRTC */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (crtc->fb == fb)
+                       crtc->fb = NULL;
+       }
+
+       drm_idr_put(dev, fb->id);
+       list_del(&fb->head);
+       dev->mode_config.num_fb--;
+
+       kfree(fb);
+}
+EXPORT_SYMBOL(drm_framebuffer_destroy);
+
+/**
+ * drm_crtc_create - create a new CRTC object
+ * @dev: DRM device
+ * @funcs: callbacks for the new CRTC
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Creates a new CRTC object and adds it to @dev's mode_config structure.
+ *
+ * RETURNS:
+ * Pointer to new CRTC object or NULL on error.
+ */
+struct drm_crtc *drm_crtc_create(struct drm_device *dev,
+                                const struct drm_crtc_funcs *funcs)
+{
+       struct drm_crtc *crtc;
+
+       crtc = kzalloc(sizeof(struct drm_crtc), GFP_KERNEL);
+       if (!crtc)
+               return NULL;
+
+       crtc->dev = dev;
+       crtc->funcs = funcs;
+
+       crtc->id = drm_idr_get(dev, crtc);
+
+       list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
+       dev->mode_config.num_crtc++;
+
+       return crtc;
+}
+EXPORT_SYMBOL(drm_crtc_create);
+
+/**
+ * drm_crtc_destroy - remove a CRTC object
+ * @crtc: CRTC to remove
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Cleanup @crtc.  Calls @crtc's cleanup function, then removes @crtc from
+ * its associated DRM device's mode_config.  Frees it afterwards.
+ */
+void drm_crtc_destroy(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+
+       if (crtc->funcs->cleanup)
+               (*crtc->funcs->cleanup)(crtc);
+
+       drm_idr_put(dev, crtc->id);
+       list_del(&crtc->head);
+       dev->mode_config.num_crtc--;
+       kfree(crtc);
+}
+EXPORT_SYMBOL(drm_crtc_destroy);
+
+/**
+ * drm_crtc_in_use - check if a given CRTC is in a mode_config
+ * @crtc: CRTC to check
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Walk @crtc's DRM device's mode_config and see if it's in use.
+ *
+ * RETURNS:
+ * True if @crtc is part of the mode_config, false otherwise.
+ */
+bool drm_crtc_in_use(struct drm_crtc *crtc)
+{
+       struct drm_output *output;
+       struct drm_device *dev = crtc->dev;
+       /* FIXME: Locking around list access? */
+       list_for_each_entry(output, &dev->mode_config.output_list, head)
+               if (output->crtc == crtc)
+                       return true;
+       return false;
+}
+EXPORT_SYMBOL(drm_crtc_in_use);
+
+/*
+ * Detailed mode info for a standard 640x480@60Hz monitor
+ */
+static struct drm_display_mode std_mode[] = {
+       { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
+                  752, 800, 0, 480, 490, 492, 525, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
+};
+
+/**
+ * drm_crtc_probe_output_modes - get complete set of display modes
+ * @dev: DRM device
+ * @maxX: max width for modes
+ * @maxY: max height for modes
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Based on @dev's mode_config layout, scan all the outputs and try to detect
+ * modes on them.  Modes will first be added to the output's probed_modes
+ * list, then culled (based on validity and the @maxX, @maxY parameters) and
+ * put into the normal modes list.
+ *
+ * Intended to be used either at bootup time or when major configuration
+ * changes have occurred.
+ *
+ * FIXME: take into account monitor limits
+ */
+void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY)
+{
+       struct drm_output *output;
+       struct drm_display_mode *mode, *t;
+       int ret;
+       //if (maxX == 0 || maxY == 0) 
+       // TODO
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+
+               /* set all modes to the unverified state */
+               list_for_each_entry_safe(mode, t, &output->modes, head)
+                       mode->status = MODE_UNVERIFIED;
+               
+               output->status = (*output->funcs->detect)(output);
+
+               if (output->status == output_status_disconnected) {
+                       DRM_DEBUG("%s is disconnected\n", output->name);
+                       /* TODO set EDID to NULL */
+                       continue;
+               }
+
+               ret = (*output->funcs->get_modes)(output);
+
+               if (ret) {
+                       drm_mode_output_list_update(output);
+               }
+
+               if (maxX && maxY)
+                       drm_mode_validate_size(dev, &output->modes, maxX,
+                                              maxY, 0);
+               list_for_each_entry_safe(mode, t, &output->modes, head) {
+                       if (mode->status == MODE_OK)
+                               mode->status = (*output->funcs->mode_valid)(output,mode);
+               }
+               
+
+               drm_mode_prune_invalid(dev, &output->modes, TRUE);
+
+               if (list_empty(&output->modes)) {
+                       struct drm_display_mode *stdmode;
+
+                       DRM_DEBUG("No valid modes on %s\n", output->name);
+
+                       /* Should we do this here ???
+                        * When no valid EDID modes are available we end up
+                        * here and bailed in the past, now we add a standard
+                        * 640x480@60Hz mode and carry on.
+                        */
+                       stdmode = drm_mode_duplicate(dev, &std_mode[0]);
+                       drm_mode_probed_add(output, stdmode);
+                       drm_mode_list_concat(&output->probed_modes,
+                                            &output->modes);
+
+                       DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
+                                                               output->name);
+               }
+
+               drm_mode_sort(&output->modes);
+
+               DRM_DEBUG("Probed modes for %s\n", output->name);
+               list_for_each_entry_safe(mode, t, &output->modes, head) {
+                       mode->vrefresh = drm_mode_vrefresh(mode);
+
+                       drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+                       drm_mode_debug_printmodeline(dev, mode);
+               }
+       }
+}
+
+/**
+ * drm_crtc_set_mode - set a mode
+ * @crtc: CRTC to program
+ * @mode: mode to use
+ * @x: width of mode
+ * @y: height of mode
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Try to set @mode on @crtc.  Give @crtc and its associated outputs a chance
+ * to fixup or reject the mode prior to trying to set it.
+ *
+ * RETURNS:
+ * True if the mode was set successfully, or false otherwise.
+ */
+bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                      int x, int y)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_display_mode *adjusted_mode, saved_mode;
+       int saved_x, saved_y;
+       bool didLock = false;
+       bool ret = false;
+       struct drm_output *output;
+
+       adjusted_mode = drm_mode_duplicate(dev, mode);
+
+       crtc->enabled = drm_crtc_in_use(crtc);
+
+       if (!crtc->enabled) {
+               return true;
+       }
+
+       didLock = crtc->funcs->lock(crtc);
+
+       saved_mode = crtc->mode;
+       saved_x = crtc->x;
+       saved_y = crtc->y;
+       
+       /* Update crtc values up front so the driver can rely on them for mode
+        * setting.
+        */
+       crtc->mode = *mode;
+       crtc->x = x;
+       crtc->y = y;
+
+       /* XXX short-circuit changes to base location only */
+       
+       /* Pass our mode to the outputs and the CRTC to give them a chance to
+        * adjust it according to limitations or output properties, and also
+        * a chance to reject the mode entirely.
+        */
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+               
+               if (output->crtc != crtc)
+                       continue;
+               
+               if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
+                       goto done;
+               }
+       }
+       
+       if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
+               goto done;
+       }
+
+       /* Prepare the outputs and CRTCs before setting the mode. */
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+
+               if (output->crtc != crtc)
+                       continue;
+               
+               /* Disable the output as the first thing we do. */
+               output->funcs->prepare(output);
+       }
+       
+       crtc->funcs->prepare(crtc);
+       
+       /* Set up the DPLL and any output state that needs to adjust or depend
+        * on the DPLL.
+        */
+       crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+
+               if (output->crtc != crtc)
+                       continue;
+               
+               DRM_INFO("%s: set mode %s\n", output->name, mode->name);
+
+               output->funcs->mode_set(output, mode, adjusted_mode);
+       }
+       
+       /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
+       crtc->funcs->commit(crtc);
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+
+               if (output->crtc != crtc)
+                       continue;
+               
+               output->funcs->commit(output);
+
+#if 0 // TODO def RANDR_12_INTERFACE
+               if (output->randr_output)
+                       RRPostPendingProperties (output->randr_output);
+#endif
+       }
+       
+       /* XXX free adjustedmode */
+       drm_mode_destroy(dev, adjusted_mode);
+       ret = TRUE;
+       /* TODO */
+//     if (scrn->pScreen)
+//             drm_crtc_set_screen_sub_pixel_order(dev);
+
+done:
+       if (!ret) {
+               crtc->x = saved_x;
+               crtc->y = saved_y;
+               crtc->mode = saved_mode;
+       }
+       
+       if (didLock)
+               crtc->funcs->unlock (crtc);
+       
+       return ret;
+}
+EXPORT_SYMBOL(drm_crtc_set_mode);
+
+/**
+ * drm_disable_unused_functions - disable unused objects
+ * @dev: DRM device
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * If an output or CRTC isn't part of @dev's mode_config, it can be disabled
+ * by calling its dpms function, which should power it off.
+ */
+void drm_disable_unused_functions(struct drm_device *dev)
+{
+       struct drm_output *output;
+       struct drm_crtc *crtc;
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+               if (!output->crtc)
+                       (*output->funcs->dpms)(output, DPMSModeOff);
+       }
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (!crtc->enabled)
+                       crtc->funcs->dpms(crtc, DPMSModeOff);
+       }
+}
+       
+/**
+ * drm_mode_probed_add - add a mode to the specified output's probed mode list
+ * @output: output the new mode
+ * @mode: mode data
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ * 
+ * Add @mode to @output's mode list for later use.
+ */
+void drm_mode_probed_add(struct drm_output *output,
+                        struct drm_display_mode *mode)
+{
+       list_add(&mode->head, &output->probed_modes);
+}
+EXPORT_SYMBOL(drm_mode_probed_add);
+
+/**
+ * drm_mode_remove - remove and free a mode
+ * @output: output list to modify
+ * @mode: mode to remove
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ * 
+ * Remove @mode from @output's mode list, then free it.
+ */
+void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode)
+{
+       list_del(&mode->head);
+       kfree(mode);
+}
+EXPORT_SYMBOL(drm_mode_remove);
+
+/**
+ * drm_output_create - create a new output
+ * @dev: DRM device
+ * @funcs: callbacks for this output
+ * @name: user visible name of the output
+ *
+ * LOCKING:
+ * Caller must hold @dev's mode_config lock.
+ *
+ * Creates a new drm_output structure and adds it to @dev's mode_config
+ * structure.
+ *
+ * RETURNS:
+ * Pointer to the new output or NULL on error.
+ */
+struct drm_output *drm_output_create(struct drm_device *dev,
+                                    const struct drm_output_funcs *funcs,
+                                    const char *name)
+{
+       struct drm_output *output = NULL;
+
+       output = kzalloc(sizeof(struct drm_output), GFP_KERNEL);
+       if (!output)
+               return NULL;
+               
+       output->dev = dev;
+       output->funcs = funcs;
+       output->id = drm_idr_get(dev, output);
+       if (name)
+               strncpy(output->name, name, DRM_OUTPUT_LEN);
+       output->name[DRM_OUTPUT_LEN - 1] = 0;
+       output->subpixel_order = SubPixelUnknown;
+       INIT_LIST_HEAD(&output->probed_modes);
+       INIT_LIST_HEAD(&output->modes);
+       /* randr_output? */
+       /* output_set_monitor(output)? */
+       /* check for output_ignored(output)? */
+
+       mutex_lock(&dev->mode_config.mutex);
+       list_add_tail(&output->head, &dev->mode_config.output_list);
+       dev->mode_config.num_output++;
+
+       mutex_unlock(&dev->mode_config.mutex);
+
+       return output;
+
+}
+EXPORT_SYMBOL(drm_output_create);
+
+/**
+ * drm_output_destroy - remove an output
+ * @output: output to remove
+ *
+ * LOCKING:
+ * Caller must hold @dev's mode_config lock.
+ *
+ * Call @output's cleanup function, then remove the output from the DRM
+ * mode_config after freeing @output's modes.
+ */
+void drm_output_destroy(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_display_mode *mode, *t;
+
+       if (*output->funcs->cleanup)
+               (*output->funcs->cleanup)(output);
+
+       list_for_each_entry_safe(mode, t, &output->probed_modes, head)
+               drm_mode_remove(output, mode);
+
+       list_for_each_entry_safe(mode, t, &output->modes, head)
+               drm_mode_remove(output, mode);
+
+       mutex_lock(&dev->mode_config.mutex);
+       drm_idr_put(dev, output->id);
+       list_del(&output->head);
+       mutex_unlock(&dev->mode_config.mutex);
+       kfree(output);
+}
+EXPORT_SYMBOL(drm_output_destroy);
+
+/**
+ * drm_output_rename - rename an output
+ * @output: output to rename
+ * @name: new user visible name
+ *
+ * LOCKING:
+ * None.
+ *
+ * Simply stuff a new name into @output's name field, based on @name.
+ *
+ * RETURNS:
+ * True if the name was changed, false otherwise.
+ */
+bool drm_output_rename(struct drm_output *output, const char *name)
+{
+       if (!name)
+               return false;
+
+       strncpy(output->name, name, DRM_OUTPUT_LEN);
+       output->name[DRM_OUTPUT_LEN - 1] = 0;
+
+       DRM_DEBUG("Changed name to %s\n", output->name);
+//     drm_output_set_monitor(output);
+//     if (drm_output_ignored(output))
+//             return FALSE;
+
+       return TRUE;
+}
+EXPORT_SYMBOL(drm_output_rename);
+
+/**
+ * drm_mode_create - create a new display mode
+ * @dev: DRM device
+ *
+ * LOCKING:
+ * None.
+ *
+ * Create a new drm_display_mode, give it an ID, and return it.
+ *
+ * RETURNS:
+ * Pointer to new mode on success, NULL on error.
+ */
+struct drm_display_mode *drm_mode_create(struct drm_device *dev)
+{
+       struct drm_display_mode *nmode;
+
+       nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
+       if (!nmode)
+               return NULL;
+
+       nmode->mode_id = drm_idr_get(dev, nmode);
+       return nmode;
+}
+EXPORT_SYMBOL(drm_mode_create);
+
+/**
+ * drm_mode_destroy - remove a mode
+ * @dev: DRM device
+ * @mode: mode to remove
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Free @mode's unique identifier, then free it.
+ */
+void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
+{
+       drm_idr_put(dev, mode->mode_id);
+
+       kfree(mode);
+}
+EXPORT_SYMBOL(drm_mode_destroy);
+
+/**
+ * drm_mode_config_init - initialize DRM mode_configuration structure
+ * @dev: DRM device
+ *
+ * LOCKING:
+ * None, should happen single threaded at init time.
+ *
+ * Initialize @dev's mode_config structure, used for tracking the graphics
+ * configuration of @dev.
+ */
+void drm_mode_config_init(struct drm_device *dev)
+{
+       mutex_init(&dev->mode_config.mutex);
+       INIT_LIST_HEAD(&dev->mode_config.fb_list);
+       INIT_LIST_HEAD(&dev->mode_config.crtc_list);
+       INIT_LIST_HEAD(&dev->mode_config.output_list);
+       INIT_LIST_HEAD(&dev->mode_config.usermode_list);
+       idr_init(&dev->mode_config.crtc_idr);
+}
+EXPORT_SYMBOL(drm_mode_config_init);
+
+/**
+ * drm_get_buffer_object - find the buffer object for a given handle
+ * @dev: DRM device
+ * @bo: pointer to caller's buffer_object pointer
+ * @handle: handle to lookup
+ *
+ * LOCKING:
+ * Must take @dev's struct_mutex to protect buffer object lookup.
+ *
+ * Given @handle, lookup the buffer object in @dev and put it in the caller's
+ * @bo pointer.
+ *
+ * RETURNS:
+ * Zero on success, -EINVAL if the handle couldn't be found.
+ */
+static int drm_get_buffer_object(struct drm_device *dev, struct drm_buffer_object **bo, unsigned long handle)
+{
+       struct drm_user_object *uo;
+       struct drm_hash_item *hash;
+       int ret;
+
+       *bo = NULL;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_ht_find_item(&dev->object_hash, handle, &hash);
+       if (ret) {
+               DRM_ERROR("Couldn't find handle.\n");
+               ret = -EINVAL;
+               goto out_err;
+       }
+
+       uo = drm_hash_entry(hash, struct drm_user_object, hash);
+       if (uo->type != drm_buffer_type) {
+               ret = -EINVAL;
+               goto out_err;
+       }
+       
+       *bo = drm_user_object_entry(uo, struct drm_buffer_object, base);
+       ret = 0;
+out_err:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+/**
+ * drm_pick_crtcs - pick crtcs for output devices
+ * @dev: DRM device
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ */
+static void drm_pick_crtcs (struct drm_device *dev)
+{
+       int c, o, assigned;
+       struct drm_output *output, *output_equal;
+       struct drm_crtc   *crtc;
+       struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+                       output->crtc = NULL;
+    
+               /* Don't hook up outputs that are disconnected ??
+                *
+                * This is debateable. Do we want fixed /dev/fbX or
+                * dynamic on hotplug (need mode code for that though) ?
+                *
+                * If we don't hook up outputs now, then we only create
+                * /dev/fbX for the output that's enabled, that's good as
+                * the users console will be on that output.
+                *
+                * If we do hook up outputs that are disconnected now, then
+                * the user may end up having to muck about with the fbcon
+                * map flags to assign his console to the enabled output. Ugh.
+                */
+               if (output->status != output_status_connected)
+                       continue;
+
+               des_mode = NULL;
+               list_for_each_entry(des_mode, &output->modes, head) {
+                       if (des_mode->type & DRM_MODE_TYPE_PREFERRED)
+                               break;
+               }
+
+               /* No preferred mode, let's just select the first available */
+               if (!des_mode || !(des_mode->type & DRM_MODE_TYPE_PREFERRED)) {
+                       list_for_each_entry(des_mode, &output->modes, head) {
+                               if (des_mode)
+                                       break;
+                       }
+               }
+
+               c = -1;
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       assigned = 0;
+
+                       c++;
+                       if ((output->possible_crtcs & (1 << c)) == 0)
+                               continue;
+       
+                       list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
+                               if (output->id == output_equal->id)
+                                       continue;
+
+                               /* Find out if crtc has been assigned before */
+                               if (output_equal->crtc == crtc)
+                                       assigned = 1;
+                       }
+
+#if 1 /* continue for now */
+                       if (assigned)
+                               continue;
+#endif
+
+                       o = -1;
+                       list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
+                               o++;
+                               if (output->id == output_equal->id)
+                                       continue;
+
+                               list_for_each_entry(modes, &output->modes, head) {
+                                       list_for_each_entry(modes_equal, &output_equal->modes, head) {
+                                               if (drm_mode_equal (modes, modes_equal)) {
+                                                       if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) {
+                                                               printk("Cloning %s (0x%lx) to %s (0x%lx)\n",output->name,output->possible_clones,output_equal->name,output_equal->possible_clones);
+                                                               assigned = 0;
+                                                               goto clone;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+clone:
+                       /* crtc has been assigned skip it */
+                       if (assigned)
+                               continue;
+
+                       /* Found a CRTC to attach to, do it ! */
+                       output->crtc = crtc;
+                       output->crtc->desired_mode = des_mode;
+                       output->initial_x = 0;
+                       output->initial_y = 0;
+                       DRM_DEBUG("Desired mode for CRTC %d is %s\n",c,des_mode->name);
+                       break;
+               }
+       }
+}
+
+
+/**
+ * drm_initial_config - setup a sane initial output configuration
+ * @dev: DRM device
+ * @can_grow: this configuration is growable
+ *
+ * LOCKING:
+ * Called at init time, must take mode config lock.
+ *
+ * Scan the CRTCs and outputs and try to put together an initial setup.
+ * At the moment, this is a cloned configuration across all heads with
+ * a new framebuffer object as the backing store.
+ *
+ * RETURNS:
+ * Zero if everything went ok, nonzero otherwise.
+ */
+bool drm_initial_config(struct drm_device *dev, bool can_grow)
+{
+       struct drm_output *output;
+       struct drm_crtc *crtc;
+       int ret = false;
+
+       mutex_lock(&dev->mode_config.mutex);
+
+       drm_crtc_probe_output_modes(dev, 2048, 2048);
+
+       drm_pick_crtcs(dev);
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+               /* can't setup the crtc if there's no assigned mode */
+               if (!crtc->desired_mode)
+                       continue;
+
+               /* Now setup the fbdev for attached crtcs */
+               dev->driver->fb_probe(dev, crtc);
+       }
+
+       /* This is a little screwy, as we've already walked the outputs 
+        * above, but it's a little bit of magic too. There's the potential
+        * for things not to get setup above if an existing device gets
+        * re-assigned thus confusing the hardware. By walking the outputs
+        * this fixes up their crtc's.
+        */
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+
+               /* can't setup the output if there's no assigned mode */
+               if (!output->crtc || !output->crtc->desired_mode)
+                       continue;
+
+               /* and needs an attached fb */
+               if (output->crtc->fb)
+                       drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0);
+       }
+
+       drm_disable_unused_functions(dev);
+
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+EXPORT_SYMBOL(drm_initial_config);
+
+/**
+ * drm_mode_config_cleanup - free up DRM mode_config info
+ * @dev: DRM device
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Free up all the outputs and CRTCs associated with this DRM device, then
+ * free up the framebuffers and associated buffer objects.
+ *
+ * FIXME: cleanup any dangling user buffer objects too
+ */
+void drm_mode_config_cleanup(struct drm_device *dev)
+{
+       struct drm_output *output, *ot;
+       struct drm_crtc *crtc, *ct;
+       struct drm_framebuffer *fb, *fbt;
+       struct drm_display_mode *mode, *mt;
+       list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) {
+               drm_output_destroy(output);
+       }
+
+       list_for_each_entry_safe(mode, mt, &dev->mode_config.usermode_list, head) {
+               drm_mode_destroy(dev, mode);
+       }
+               
+       list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
+               if (fb->bo->type != drm_bo_type_kernel)
+                       drm_framebuffer_destroy(fb);
+               else
+                       dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
+       }
+
+       list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
+               drm_crtc_destroy(crtc);
+       }
+
+}
+EXPORT_SYMBOL(drm_mode_config_cleanup);
+
+/**
+ * drm_crtc_set_config - set a new config from userspace
+ * @crtc: CRTC to setup
+ * @crtc_info: user provided configuration
+ * @new_mode: new mode to set
+ * @output_set: set of outputs for the new config
+ * @fb: new framebuffer
+ *
+ * LOCKING:
+ * Caller must hold mode config lock.
+ *
+ * Setup a new configuration, provided by the user in @crtc_info, and enable
+ * it.
+ *
+ * RETURNS:
+ * Zero. (FIXME)
+ */
+int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_display_mode *new_mode, struct drm_output **output_set, struct drm_framebuffer *fb)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_crtc **save_crtcs, *new_crtc;
+       bool save_enabled = crtc->enabled;
+       bool changed;
+       struct drm_output *output;
+       int count = 0, ro;
+
+       save_crtcs = kzalloc(dev->mode_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL);
+       if (!save_crtcs)
+               return -ENOMEM;
+
+       if (crtc->fb != fb)
+               changed = true;
+
+       if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
+               changed = true;
+
+       if (new_mode && (crtc->mode.mode_id != new_mode->mode_id))
+               changed = true;
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+               save_crtcs[count++] = output->crtc;
+
+               if (output->crtc == crtc)
+                       new_crtc = NULL;
+               else
+                       new_crtc = output->crtc;
+
+               for (ro = 0; ro < crtc_info->count_outputs; ro++) {
+                       if (output_set[ro] == output)
+                               new_crtc = crtc;
+               }
+               if (new_crtc != output->crtc) {
+                       changed = true;
+                       output->crtc = new_crtc;
+               }
+       }
+
+       if (changed) {
+               crtc->fb = fb;
+               crtc->enabled = (new_mode != NULL);
+               if (new_mode != NULL) {
+                       DRM_DEBUG("attempting to set mode from userspace\n");
+                       drm_mode_debug_printmodeline(dev, new_mode);
+                       if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x,
+                                              crtc_info->y)) {
+                               crtc->enabled = save_enabled;
+                               count = 0;
+                               list_for_each_entry(output, &dev->mode_config.output_list, head)
+                                       output->crtc = save_crtcs[count++];
+                               kfree(save_crtcs);
+                               return -EINVAL;
+                       }
+                       crtc->desired_x = crtc_info->x;
+                       crtc->desired_y = crtc_info->y;
+                       crtc->desired_mode = new_mode;
+               }
+               drm_disable_unused_functions(dev);
+       }
+       kfree(save_crtcs);
+       return 0;
+}
+
+/**
+ * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
+ * @out: drm_mode_modeinfo struct to return to the user
+ * @in: drm_display_mode to use
+ *
+ * LOCKING:
+ * None.
+ *
+ * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
+ * the user.
+ */
+void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in)
+{
+
+       out->id = in->mode_id;
+       out->clock = in->clock;
+       out->hdisplay = in->hdisplay;
+       out->hsync_start = in->hsync_start;
+       out->hsync_end = in->hsync_end;
+       out->htotal = in->htotal;
+       out->hskew = in->hskew;
+       out->vdisplay = in->vdisplay;
+       out->vsync_start = in->vsync_start;
+       out->vsync_end = in->vsync_end;
+       out->vtotal = in->vtotal;
+       out->vscan = in->vscan;
+       out->vrefresh = in->vrefresh;
+       out->flags = in->flags;
+       strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
+       out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+}
+
+/**
+ * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
+ * @out: drm_display_mode to return to the user
+ * @in: drm_mode_modeinfo to use
+ *
+ * LOCKING:
+ * None.
+ *
+ * Convert a drmo_mode_modeinfo into a drm_display_mode structure to return to
+ * the caller.
+ */
+void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modeinfo *in)
+{
+       out->clock = in->clock;
+       out->hdisplay = in->hdisplay;
+       out->hsync_start = in->hsync_start;
+       out->hsync_end = in->hsync_end;
+       out->htotal = in->htotal;
+       out->hskew = in->hskew;
+       out->vdisplay = in->vdisplay;
+       out->vsync_start = in->vsync_start;
+       out->vsync_end = in->vsync_end;
+       out->vtotal = in->vtotal;
+       out->vscan = in->vscan;
+       out->vrefresh = in->vrefresh;
+       out->flags = in->flags;
+       strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
+       out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+}
+       
+/**
+ * drm_mode_getresources - get graphics configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Takes mode config lock.
+ *
+ * Construct a set of configuration description structures and return
+ * them to the user, including CRTC, output and framebuffer configuration.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_getresources(struct drm_device *dev,
+                         void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_card_res *card_res = data;
+       struct list_head *lh;
+       struct drm_framebuffer *fb;
+       struct drm_output *output;
+       struct drm_crtc *crtc;
+       struct drm_mode_modeinfo u_mode;
+       struct drm_display_mode *mode;
+       int ret = 0;
+       int mode_count= 0;
+       int output_count = 0;
+       int crtc_count = 0;
+       int fb_count = 0;
+       int copied = 0;
+       
+       memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
+
+       mutex_lock(&dev->mode_config.mutex);
+
+       list_for_each(lh, &dev->mode_config.fb_list)
+               fb_count++;
+
+       list_for_each(lh, &dev->mode_config.crtc_list)
+               crtc_count++;
+
+       list_for_each_entry(output, &dev->mode_config.output_list,
+                           head) {
+               output_count++;
+               list_for_each(lh, &output->modes)
+                       mode_count++;
+       }
+       list_for_each(lh, &dev->mode_config.usermode_list)
+               mode_count++;
+
+       if (card_res->count_modes == 0) {
+               DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height);
+               drm_crtc_probe_output_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);
+               mode_count = 0;
+               list_for_each_entry(output, &dev->mode_config.output_list, head) {
+                       list_for_each(lh, &output->modes)
+                               mode_count++;
+               }
+               list_for_each(lh, &dev->mode_config.usermode_list)
+                       mode_count++;
+       }
+
+       /* handle this in 4 parts */
+       /* FBs */
+       if (card_res->count_fbs >= fb_count) {
+               copied = 0;
+               list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+                       card_res->fb_id[copied++] = fb->id;
+               }
+       }
+       card_res->count_fbs = fb_count;
+
+       /* CRTCs */
+       if (card_res->count_crtcs >= crtc_count) {
+               copied = 0;
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){
+                       DRM_DEBUG("CRTC ID is %d\n", crtc->id);
+                       card_res->crtc_id[copied++] = crtc->id;
+               }
+       }
+       card_res->count_crtcs = crtc_count;
+
+
+       /* Outputs */
+       if (card_res->count_outputs >= output_count) {
+               copied = 0;
+               list_for_each_entry(output, &dev->mode_config.output_list,
+                                   head) {
+                       DRM_DEBUG("OUTPUT ID is %d\n", output->id);
+                       card_res->output_id[copied++] = output->id;
+               }
+       }
+       card_res->count_outputs = output_count;
+       
+       /* Modes */
+       if (card_res->count_modes >= mode_count) {
+               copied = 0;
+               list_for_each_entry(output, &dev->mode_config.output_list,
+                                   head) {
+                       list_for_each_entry(mode, &output->modes, head) {
+                               drm_crtc_convert_to_umode(&u_mode, mode);
+                               card_res->modes[copied++] = u_mode;
+                       }
+               }
+               /* add in user modes */
+               list_for_each_entry(mode, &dev->mode_config.usermode_list, head) {
+                       drm_crtc_convert_to_umode(&u_mode, mode);
+                       card_res->modes[copied++] = u_mode;
+               }
+       }
+       card_res->count_modes = mode_count;
+
+       DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs,
+                 card_res->count_outputs,
+                 card_res->count_modes);
+       
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_mode_getcrtc - get CRTC configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Caller? (FIXME)
+ *
+ * Construct a CRTC configuration structure to return to the user.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_getcrtc(struct drm_device *dev,
+                    void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_crtc *crtc_resp = data;
+       struct drm_crtc *crtc;
+       struct drm_output *output;
+       int ocount;
+       int ret = 0;
+
+       mutex_lock(&dev->mode_config.mutex);
+       crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp->crtc_id);
+       if (!crtc || (crtc->id != crtc_resp->crtc_id)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       crtc_resp->x = crtc->x;
+       crtc_resp->y = crtc->y;
+       crtc_resp->fb_id = 1;
+
+       crtc_resp->outputs = 0;
+       if (crtc->enabled) {
+
+               crtc_resp->mode = crtc->mode.mode_id;
+               ocount = 0;
+               list_for_each_entry(output, &dev->mode_config.output_list, head) {
+                       if (output->crtc == crtc)
+                               crtc_resp->outputs |= 1 << (ocount++);
+               }
+       } else {
+               crtc_resp->mode = 0;
+       }
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_mode_getoutput - get output configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Caller? (FIXME)
+ *
+ * Construct a output configuration structure to return to the user.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_getoutput(struct drm_device *dev,
+                      void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_get_output *out_resp = data;
+       struct drm_output *output;
+       struct drm_display_mode *mode;
+       int mode_count = 0;
+       int ret = 0;
+       int copied = 0;
+       int i;
+
+       DRM_DEBUG("output id %d:\n", out_resp->output);
+
+       mutex_lock(&dev->mode_config.mutex);
+       output= idr_find(&dev->mode_config.crtc_idr, out_resp->output);
+       if (!output || (output->id != out_resp->output)) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       list_for_each_entry(mode, &output->modes, head)
+               mode_count++;
+       
+       for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++)
+               if (output->user_mode_ids[i] != 0)
+                       mode_count++;
+
+       strncpy(out_resp->name, output->name, DRM_OUTPUT_NAME_LEN);
+       out_resp->name[DRM_OUTPUT_NAME_LEN-1] = 0;
+
+       out_resp->mm_width = output->mm_width;
+       out_resp->mm_height = output->mm_height;
+       out_resp->subpixel = output->subpixel_order;
+       out_resp->connection = output->status;
+       if (output->crtc)
+               out_resp->crtc = output->crtc->id;
+       else
+               out_resp->crtc = 0;
+
+       if ((out_resp->count_modes >= mode_count) && mode_count) {
+               copied = 0;
+               list_for_each_entry(mode, &output->modes, head) {
+                       out_resp->modes[copied++] = mode->mode_id;
+               }
+               for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
+                       if (output->user_mode_ids[i] != 0)
+                               out_resp->modes[copied++] = output->user_mode_ids[i];
+               }
+                       
+       }
+       out_resp->count_modes = mode_count;
+
+done:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_mode_setcrtc - set CRTC configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Caller? (FIXME)
+ *
+ * Build a new CRTC configuration based on user request.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_setcrtc(struct drm_device *dev,
+                    void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_crtc *crtc_req = data;
+       struct drm_crtc *crtc;
+       struct drm_output **output_set = NULL, *output;
+       struct drm_display_mode *mode;
+       struct drm_framebuffer *fb = NULL;
+       int ret = 0;
+       int i;
+
+       mutex_lock(&dev->mode_config.mutex);
+       crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id);
+       if (!crtc || (crtc->id != crtc_req->crtc_id)) {
+               DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (crtc_req->mode) {
+               /* if we have a mode we need a framebuffer */
+               if (crtc_req->fb_id) {
+                       fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id);
+                       if (!fb || (fb->id != crtc_req->fb_id)) {
+                               DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id);
+                               ret = -EINVAL;
+                               goto out;
+                       }
+               }
+               mode = idr_find(&dev->mode_config.crtc_idr, crtc_req->mode);
+               if (!mode || (mode->mode_id != crtc_req->mode)) {
+                       struct drm_output *output;
+                       
+                       list_for_each_entry(output, 
+                                           &dev->mode_config.output_list,
+                                           head) {
+                               list_for_each_entry(mode, &output->modes,
+                                                   head) {
+                                       drm_mode_debug_printmodeline(dev, 
+                                                                    mode);
+                               }
+                       }
+
+                       DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req->mode, mode);
+                       ret = -EINVAL;
+                       goto out;
+               }
+       } else
+               mode = NULL;
+
+       if (crtc_req->count_outputs == 0 && mode) {
+               DRM_DEBUG("Count outputs is 0 but mode set\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (crtc_req->count_outputs > 0 && !mode && !fb) {
+               DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (crtc_req->count_outputs > 0) {
+               u32 out_id;
+               output_set = kmalloc(crtc_req->count_outputs *
+                                    sizeof(struct drm_output *), GFP_KERNEL);
+               if (!output_set) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               for (i = 0; i < crtc_req->count_outputs; i++) {
+                       if (get_user(out_id, &crtc_req->set_outputs[i])) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+
+                       output = idr_find(&dev->mode_config.crtc_idr, out_id);
+                       if (!output || (out_id != output->id)) {
+                               DRM_DEBUG("Output id %d unknown\n", out_id);
+                               ret = -EINVAL;
+                               goto out;
+                       }
+
+                       output_set[i] = output;
+               }
+       }
+               
+       ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb);
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_mode_addfb - add an FB to the graphics configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Takes mode config lock.
+ *
+ * Add a new FB to the specified CRTC, given a user request.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_addfb(struct drm_device *dev,
+                  void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_fb_cmd *r = data;
+       struct drm_mode_config *config = &dev->mode_config;
+       struct drm_framebuffer *fb;
+       struct drm_buffer_object *bo;
+       struct drm_crtc *crtc;
+       int ret = 0;
+
+       if ((config->min_width > r->width) || (r->width > config->max_width)) {
+               DRM_ERROR("mode new framebuffer width not within limits\n");
+               return -EINVAL;
+       }
+       if ((config->min_height > r->height) || (r->height > config->max_height)) {
+               DRM_ERROR("mode new framebuffer height not within limits\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&dev->mode_config.mutex);
+       /* TODO check limits are okay */
+       ret = drm_get_buffer_object(dev, &bo, r->handle);
+       if (ret || !bo) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* TODO check buffer is sufficently large */
+       /* TODO setup destructor callback */
+
+       fb = drm_framebuffer_create(dev);
+       if (!fb) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       fb->width = r->width;
+       fb->height = r->height;
+       fb->pitch = r->pitch;
+       fb->bits_per_pixel = r->bpp;
+       fb->depth = r->depth;
+       fb->offset = bo->offset;
+       fb->bo = bo;
+
+       r->buffer_id = fb->id;
+
+       list_add(&fb->filp_head, &file_priv->fbs);
+
+       /* FIXME: bind the fb to the right crtc */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               crtc->fb = fb;
+               dev->driver->fb_probe(dev, crtc);
+       }
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_mode_rmfb - remove an FB from the configuration
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Takes mode config lock.
+ *
+ * Remove the FB specified by the user.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_rmfb(struct drm_device *dev,
+                  void *data, struct drm_file *file_priv)
+{
+       struct drm_framebuffer *fb = 0;
+       uint32_t *id = data;
+       int ret = 0;
+
+       fb = idr_find(&dev->mode_config.crtc_idr, *id);
+       /* TODO check that we realy get a framebuffer back. */
+       if (!fb || (*id != fb->id)) {
+               DRM_ERROR("mode invalid framebuffer id\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* TODO check if we own the buffer */
+       /* TODO release all crtc connected to the framebuffer */
+       /* bind the fb to the crtc for now */
+       /* TODO unhock the destructor from the buffer object */
+
+       if (fb->bo->type != drm_bo_type_kernel)
+               drm_framebuffer_destroy(fb);
+       else
+               dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_mode_getfb - get FB info
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * LOCKING:
+ * Caller? (FIXME)
+ *
+ * Lookup the FB given its ID and return info about it.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_getfb(struct drm_device *dev,
+                  void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_fb_cmd *r = data;
+       struct drm_framebuffer *fb;
+       int ret = 0;
+
+       mutex_lock(&dev->mode_config.mutex);
+       fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id);
+       if (!fb || (r->buffer_id != fb->id)) {
+               DRM_ERROR("invalid framebuffer id\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       r->height = fb->height;
+       r->width = fb->width;
+       r->depth = fb->depth;
+       r->bpp = fb->bits_per_pixel;
+       r->handle = fb->bo->base.hash.key;
+       r->pitch = fb->pitch;
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_fb_release - remove and free the FBs on this file
+ * @filp: file * from the ioctl
+ *
+ * LOCKING:
+ * Takes mode config lock.
+ *
+ * Destroy all the FBs associated with @filp.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+void drm_fb_release(struct file *filp)
+{
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_framebuffer *fb, *tfb;
+
+       mutex_lock(&dev->mode_config.mutex);
+       list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
+               list_del(&fb->filp_head);
+               if (fb->bo->type != drm_bo_type_kernel)
+                       drm_framebuffer_destroy(fb);
+               else
+                       dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
+       }
+       mutex_unlock(&dev->mode_config.mutex);
+}
+
+/**
+ * drm_fb_newmode - adds a user defined mode
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * Adds a user specified mode to the kernel.
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * writes new mode id into arg.
+ * Zero on success, errno on failure.
+ */
+int drm_mode_addmode(struct drm_device *dev,
+                    void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_modeinfo *new_mode = data;
+       struct drm_display_mode *user_mode;
+       int ret = 0;
+
+       mutex_lock(&dev->mode_config.mutex);
+       user_mode = drm_mode_create(dev);
+       if (!user_mode) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       drm_crtc_convert_umode(user_mode, new_mode);
+       user_mode->type |= DRM_MODE_TYPE_USERDEF;
+
+       user_mode->output_count = 0;
+
+       list_add(&user_mode->head, &dev->mode_config.usermode_list);
+
+       new_mode->id = user_mode->mode_id;
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_fb_rmmode - removes a user defined mode
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * Remove the user defined mode specified by the user.
+ *
+ * Called by the user via ioctl
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_rmmode(struct drm_device *dev,
+                   void *data, struct drm_file *file_priv)
+{
+       uint32_t *id = data;
+       struct drm_display_mode *mode, *t;
+       int ret = -EINVAL;
+
+       mutex_lock(&dev->mode_config.mutex);    
+       mode = idr_find(&dev->mode_config.crtc_idr, *id);
+       if (!mode || (*id != mode->mode_id)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (!(mode->type & DRM_MODE_TYPE_USERDEF)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (mode->output_count) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       list_for_each_entry(t, &dev->mode_config.usermode_list, head) {
+               if (t == mode) {
+                       list_del(&mode->head);
+                       drm_mode_destroy(dev, mode);
+                       ret = 0;
+                       break;
+               }
+       }
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+/**
+ * drm_fb_attachmode - Attach a user mode to an output
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * This attaches a user specified mode to an output.
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_attachmode(struct drm_device *dev,
+                       void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_mode_cmd *mode_cmd = data;
+       struct drm_output *output;
+       struct drm_display_mode *mode;
+       int i, ret = 0;
+
+       mutex_lock(&dev->mode_config.mutex);
+
+       mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd->mode_id);
+       if (!mode || (mode->mode_id != mode_cmd->mode_id)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id);
+       if (!output || (output->id != mode_cmd->output_id)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
+               if (output->user_mode_ids[i] == 0) {
+                       output->user_mode_ids[i] = mode->mode_id;
+                       mode->output_count++;
+                       break;
+               }
+       }
+
+       if (i == DRM_OUTPUT_MAX_UMODES)
+               ret = -ENOSPC;
+
+out:
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
+
+
+/**
+ * drm_fb_detachmode - Detach a user specified mode from an output
+ * @inode: inode from the ioctl
+ * @filp: file * from the ioctl
+ * @cmd: cmd from ioctl
+ * @arg: arg from ioctl
+ *
+ * Called by the user via ioctl.
+ *
+ * RETURNS:
+ * Zero on success, errno on failure.
+ */
+int drm_mode_detachmode(struct drm_device *dev,
+                       void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_mode_cmd *mode_cmd = data;
+       struct drm_output *output;
+       struct drm_display_mode *mode;
+       int i, found = 0, ret = 0;
+
+       mutex_lock(&dev->mode_config.mutex);
+
+       mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd->mode_id);
+       if (!mode || (mode->mode_id != mode_cmd->mode_id)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id);
+       if (!output || (output->id != mode_cmd->output_id)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+
+       for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
+               if (output->user_mode_ids[i] == mode->mode_id) {
+                       output->user_mode_ids[i] = 0;
+                       mode->output_count--;
+                       found = 1;
+               }
+       }
+
+       if (!found)
+               ret = -EINVAL;
+
+out:          
+       mutex_unlock(&dev->mode_config.mutex);
+       return ret;
+}
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
new file mode 100644 (file)
index 0000000..d97cd19
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2007 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ */
+#ifndef __DRM_CRTC_H__
+#define __DRM_CRTC_H__
+
+#include <linux/i2c.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/idr.h>
+
+#include <linux/fb.h>
+
+struct drm_device;
+
+/*
+ * Note on terminology:  here, for brevity and convenience, we refer to output
+ * control chips as 'CRTCs'.  They can control any type of output, VGA, LVDS,
+ * DVI, etc.  And 'screen' refers to the whole of the visible display, which
+ * may span multiple monitors (and therefore multiple CRTC and output
+ * structures).
+ */
+
+enum drm_mode_status {
+    MODE_OK    = 0,    /* Mode OK */
+    MODE_HSYNC,                /* hsync out of range */
+    MODE_VSYNC,                /* vsync out of range */
+    MODE_H_ILLEGAL,    /* mode has illegal horizontal timings */
+    MODE_V_ILLEGAL,    /* mode has illegal horizontal timings */
+    MODE_BAD_WIDTH,    /* requires an unsupported linepitch */
+    MODE_NOMODE,       /* no mode with a maching name */
+    MODE_NO_INTERLACE, /* interlaced mode not supported */
+    MODE_NO_DBLESCAN,  /* doublescan mode not supported */
+    MODE_NO_VSCAN,     /* multiscan mode not supported */
+    MODE_MEM,          /* insufficient video memory */
+    MODE_VIRTUAL_X,    /* mode width too large for specified virtual size */
+    MODE_VIRTUAL_Y,    /* mode height too large for specified virtual size */
+    MODE_MEM_VIRT,     /* insufficient video memory given virtual size */
+    MODE_NOCLOCK,      /* no fixed clock available */
+    MODE_CLOCK_HIGH,   /* clock required is too high */
+    MODE_CLOCK_LOW,    /* clock required is too low */
+    MODE_CLOCK_RANGE,  /* clock/mode isn't in a ClockRange */
+    MODE_BAD_HVALUE,   /* horizontal timing was out of range */
+    MODE_BAD_VVALUE,   /* vertical timing was out of range */
+    MODE_BAD_VSCAN,    /* VScan value out of range */
+    MODE_HSYNC_NARROW, /* horizontal sync too narrow */
+    MODE_HSYNC_WIDE,   /* horizontal sync too wide */
+    MODE_HBLANK_NARROW,        /* horizontal blanking too narrow */
+    MODE_HBLANK_WIDE,  /* horizontal blanking too wide */
+    MODE_VSYNC_NARROW, /* vertical sync too narrow */
+    MODE_VSYNC_WIDE,   /* vertical sync too wide */
+    MODE_VBLANK_NARROW,        /* vertical blanking too narrow */
+    MODE_VBLANK_WIDE,  /* vertical blanking too wide */
+    MODE_PANEL,         /* exceeds panel dimensions */
+    MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */
+    MODE_ONE_WIDTH,     /* only one width is supported */
+    MODE_ONE_HEIGHT,    /* only one height is supported */
+    MODE_ONE_SIZE,      /* only one resolution is supported */
+    MODE_NO_REDUCED,    /* monitor doesn't accept reduced blanking */
+    MODE_UNVERIFIED = -3, /* mode needs to reverified */
+    MODE_BAD = -2,     /* unspecified reason */
+    MODE_ERROR = -1    /* error condition */
+};
+
+#define DRM_MODE_TYPE_BUILTIN  (1<<0)
+#define DRM_MODE_TYPE_CLOCK_C  ((1<<1) | DRM_MODE_TYPE_BUILTIN)
+#define DRM_MODE_TYPE_CRTC_C   ((1<<2) | DRM_MODE_TYPE_BUILTIN)
+#define DRM_MODE_TYPE_PREFERRED        (1<<3)
+#define DRM_MODE_TYPE_DEFAULT  (1<<4)
+#define DRM_MODE_TYPE_USERDEF  (1<<5)
+#define DRM_MODE_TYPE_DRIVER   (1<<6)
+
+#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \
+                                   DRM_MODE_TYPE_CRTC_C)
+
+#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \
+       .name = nm, .status = 0, .type = (t), .clock = (c), \
+       .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
+       .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \
+       .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
+       .vscan = (vs), .flags = (f), .vrefresh = 0
+
+struct drm_display_mode {
+       /* Header */
+       struct list_head head;
+       char name[DRM_DISPLAY_MODE_LEN];
+       int mode_id;
+       int output_count;
+       enum drm_mode_status status;
+       int type;
+
+       /* Proposed mode values */
+       int clock;
+       int hdisplay;
+       int hsync_start;
+       int hsync_end;
+       int htotal;
+       int hskew;
+       int vdisplay;
+       int vsync_start;
+       int vsync_end;
+       int vtotal;
+       int vscan;
+       unsigned int flags;
+
+       /* Actual mode we give to hw */
+       int clock_index;
+       int synth_clock;
+       int crtc_hdisplay;
+       int crtc_hblank_start;
+       int crtc_hblank_end;
+       int crtc_hsync_start;
+       int crtc_hsync_end;
+       int crtc_htotal;
+       int crtc_hskew;
+       int crtc_vdisplay;
+       int crtc_vblank_start;
+       int crtc_vblank_end;
+       int crtc_vsync_start;
+       int crtc_vsync_end;
+       int crtc_vtotal;
+       int crtc_hadjusted;
+       int crtc_vadjusted;
+
+       /* Driver private mode info */
+       int private_size;
+       int *private;
+       int private_flags;
+
+       int vrefresh;
+       float hsync;
+};
+
+/* Video mode flags */
+#define V_PHSYNC       (1<<0)
+#define V_NHSYNC       (1<<1)
+#define V_PVSYNC       (1<<2)
+#define V_NVSYNC       (1<<3)
+#define V_INTERLACE    (1<<4)
+#define V_DBLSCAN      (1<<5)
+#define V_CSYNC                (1<<6)
+#define V_PCSYNC       (1<<7)
+#define V_NCSYNC       (1<<8)
+#define V_HSKEW                (1<<9) /* hskew provided */
+#define V_BCAST                (1<<10)
+#define V_PIXMUX       (1<<11)
+#define V_DBLCLK       (1<<12)
+#define V_CLKDIV2      (1<<13)
+
+#define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */
+#define DPMSModeOn 0
+#define DPMSModeStandby 1
+#define DPMSModeSuspend 2
+#define DPMSModeOff 3
+
+enum drm_output_status {
+       output_status_connected,
+       output_status_disconnected,
+       output_status_unknown,
+};
+
+enum subpixel_order {
+       SubPixelUnknown = 0,
+       SubPixelHorizontalRGB,
+       SubPixelHorizontalBGR,
+       SubPixelVerticalRGB,
+       SubPixelVerticalBGR,
+       SubPixelNone,
+};
+
+/*
+ * Describes a given display (e.g. CRT or flat panel) and its limitations.
+ */
+struct drm_display_info {
+       char name[DRM_DISPLAY_INFO_LEN];
+       /* Input info */
+       bool serration_vsync;
+       bool sync_on_green;
+       bool composite_sync;
+       bool separate_syncs;
+       bool blank_to_black;
+       unsigned char video_level;
+       bool digital;
+       /* Physical size */
+        unsigned int width_mm;
+       unsigned int height_mm;
+
+       /* Display parameters */
+       unsigned char gamma; /* FIXME: storage format */
+       bool gtf_supported;
+       bool standard_color;
+       enum {
+               monochrome,
+               rgb,
+               other,
+               unknown,
+       } display_type;
+       bool active_off_supported;
+       bool suspend_supported;
+       bool standby_supported;
+
+       /* Color info FIXME: storage format */
+       unsigned short redx, redy;
+       unsigned short greenx, greeny;
+       unsigned short bluex, bluey;
+       unsigned short whitex, whitey;
+
+       /* Clock limits FIXME: storage format */
+       unsigned int min_vfreq, max_vfreq;
+       unsigned int min_hfreq, max_hfreq;
+       unsigned int pixel_clock;
+
+       /* White point indices FIXME: storage format */
+       unsigned int wpx1, wpy1;
+       unsigned int wpgamma1;
+       unsigned int wpx2, wpy2;
+       unsigned int wpgamma2;
+
+       /* Preferred mode (if any) */
+       struct drm_display_mode *preferred_mode;
+       char *raw_edid; /* if any */
+};
+
+struct drm_framebuffer {
+       struct drm_device *dev;
+       struct list_head head;
+       int id; /* idr assigned */
+       unsigned int pitch;
+       unsigned long offset;
+       unsigned int width;
+       unsigned int height;
+       /* depth can be 15 or 16 */
+       unsigned int depth;
+       int bits_per_pixel;
+       int flags;
+       struct drm_buffer_object *bo;
+       void *fbdev;
+       u32 pseudo_palette[17];
+       void *virtual_base;
+       struct list_head filp_head;
+};
+struct drm_crtc;
+struct drm_output;
+
+/**
+ * drm_crtc_funcs - control CRTCs for a given device
+ * @dpms: control display power levels
+ * @save: save CRTC state
+ * @resore: restore CRTC state
+ * @lock: lock the CRTC
+ * @unlock: unlock the CRTC
+ * @shadow_allocate: allocate shadow pixmap
+ * @shadow_create: create shadow pixmap for rotation support
+ * @shadow_destroy: free shadow pixmap
+ * @mode_fixup: fixup proposed mode
+ * @mode_set: set the desired mode on the CRTC
+ * @gamma_set: specify color ramp for CRTC
+ * @cleanup: cleanup driver private state prior to close
+ *
+ * The drm_crtc_funcs structure is the central CRTC management structure
+ * in the DRM.  Each CRTC controls one or more outputs (note that the name
+ * CRTC is simply historical, a CRTC may control LVDS, VGA, DVI, TV out, etc.
+ * outputs, not just CRTs).
+ *
+ * Each driver is responsible for filling out this structure at startup time,
+ * in addition to providing other modesetting features, like i2c and DDC
+ * bus accessors.
+ */
+struct drm_crtc_funcs {
+       /*
+        * Control power levels on the CRTC.  If the mode passed in is
+        * unsupported, the provider must use the next lowest power level.
+        */
+       void (*dpms)(struct drm_crtc *crtc, int mode);
+
+       /* JJJ:  Are these needed? */
+       /* Save CRTC state */
+       void (*save)(struct drm_crtc *crtc); /* suspend? */
+       /* Restore CRTC state */
+       void (*restore)(struct drm_crtc *crtc); /* resume? */
+       bool (*lock)(struct drm_crtc *crtc);
+       void (*unlock)(struct drm_crtc *crtc);
+
+       void (*prepare)(struct drm_crtc *crtc);
+       void (*commit)(struct drm_crtc *crtc);
+
+       /* Provider can fixup or change mode timings before modeset occurs */
+       bool (*mode_fixup)(struct drm_crtc *crtc,
+                          struct drm_display_mode *mode,
+                          struct drm_display_mode *adjusted_mode);
+       /* Actually set the mode */
+       void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                        struct drm_display_mode *adjusted_mode, int x, int y);
+       /* Set gamma on the CRTC */
+       void (*gamma_set)(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
+                         int regno);
+       /* Driver cleanup routine */
+       void (*cleanup)(struct drm_crtc *crtc);
+};
+
+/**
+ * drm_crtc - central CRTC control structure
+ * @enabled: is this CRTC enabled?
+ * @x: x position on screen
+ * @y: y position on screen
+ * @desired_mode: new desired mode
+ * @desired_x: desired x for desired_mode
+ * @desired_y: desired y for desired_mode
+ * @funcs: CRTC control functions
+ * @driver_private: arbitrary driver data
+ *
+ * Each CRTC may have one or more outputs associated with it.  This structure
+ * allows the CRTC to be controlled.
+ */
+struct drm_crtc {
+       struct drm_device *dev;
+       struct list_head head;
+
+       int id; /* idr assigned */
+
+       /* framebuffer the output is currently bound to */
+       struct drm_framebuffer *fb;
+
+       bool enabled;
+
+       /* JJJ: are these needed? */
+       bool cursor_in_range;
+       bool cursor_shown;
+
+       struct drm_display_mode mode;
+
+       int x, y;
+       struct drm_display_mode *desired_mode;
+       int desired_x, desired_y;
+       const struct drm_crtc_funcs *funcs;
+       void *driver_private;
+
+       /* RRCrtcPtr randr_crtc? */
+};
+
+extern struct drm_crtc *drm_crtc_create(struct drm_device *dev,
+                                       const struct drm_crtc_funcs *funcs);
+
+/**
+ * drm_output_funcs - control outputs on a given device
+ * @init: setup this output
+ * @dpms: set power state (see drm_crtc_funcs above)
+ * @save: save output state
+ * @restore: restore output state
+ * @mode_valid: is this mode valid on the given output?
+ * @mode_fixup: try to fixup proposed mode for this output
+ * @mode_set: set this mode
+ * @detect: is this output active?
+ * @get_modes: get mode list for this output
+ * @set_property: property for this output may need update
+ * @cleanup: output is going away, cleanup
+ *
+ * Each CRTC may have one or more outputs attached to it.  The functions
+ * below allow the core DRM code to control outputs, enumerate available modes,
+ * etc.
+ */
+struct drm_output_funcs {
+       void (*init)(struct drm_output *output);
+       void (*dpms)(struct drm_output *output, int mode);
+       void (*save)(struct drm_output *output);
+       void (*restore)(struct drm_output *output);
+       int (*mode_valid)(struct drm_output *output,
+                         struct drm_display_mode *mode);
+       bool (*mode_fixup)(struct drm_output *output,
+                          struct drm_display_mode *mode,
+                          struct drm_display_mode *adjusted_mode);
+       void (*prepare)(struct drm_output *output);
+       void (*commit)(struct drm_output *output);
+       void (*mode_set)(struct drm_output *output,
+                        struct drm_display_mode *mode,
+                        struct drm_display_mode *adjusted_mode);
+       enum drm_output_status (*detect)(struct drm_output *output);
+       int (*get_modes)(struct drm_output *output);
+       /* JJJ: type checking for properties via property value type */
+       bool (*set_property)(struct drm_output *output, int prop, void *val);
+       void (*cleanup)(struct drm_output *output);
+};
+
+#define DRM_OUTPUT_MAX_UMODES 16
+#define DRM_OUTPUT_LEN 32
+/**
+ * drm_output - central DRM output control structure
+ * @crtc: CRTC this output is currently connected to, NULL if none
+ * @possible_crtcs: bitmap of CRTCS this output could be attached to
+ * @possible_clones: bitmap of possible outputs this output could clone
+ * @interlace_allowed: can this output handle interlaced modes?
+ * @doublescan_allowed: can this output handle doublescan?
+ * @available_modes: modes available on this output (from get_modes() + user)
+ * @initial_x: initial x position for this output
+ * @initial_y: initial y position for this output
+ * @status: output connected?
+ * @subpixel_order: for this output
+ * @mm_width: displayable width of output in mm
+ * @mm_height: displayable height of output in mm
+ * @name: name of output (should be one of a few standard names)
+ * @funcs: output control functions
+ * @driver_private: private driver data
+ *
+ * Each output may be connected to one or more CRTCs, or may be clonable by
+ * another output if they can share a CRTC.  Each output also has a specific
+ * position in the broader display (referred to as a 'screen' though it could
+ * span multiple monitors).
+ */
+struct drm_output {
+       struct drm_device *dev;
+       struct list_head head;
+       struct drm_crtc *crtc;
+       int id; /* idr assigned */
+       unsigned long possible_crtcs;
+       unsigned long possible_clones;
+       bool interlace_allowed;
+       bool doublescan_allowed;
+       struct list_head modes; /* list of modes on this output */
+
+       /*
+         OptionInfoPtr options;
+         XF86ConfMonitorPtr conf_monitor;
+        */
+       int initial_x, initial_y;
+       enum drm_output_status status;
+
+       /* these are modes added by probing with DDC or the BIOS */
+       struct list_head probed_modes;
+       
+       /* xf86MonPtr MonInfo; */
+       enum subpixel_order subpixel_order;
+       int mm_width, mm_height;
+       struct drm_display_info *monitor_info; /* if any */
+       char name[DRM_OUTPUT_LEN];
+       const struct drm_output_funcs *funcs;
+       void *driver_private;
+
+       u32 user_mode_ids[DRM_OUTPUT_MAX_UMODES];
+
+};
+
+/**
+ * struct drm_mode_config_funcs - configure CRTCs for a given screen layout
+ * @resize: adjust CRTCs as necessary for the proposed layout
+ *
+ * Currently only a resize hook is available.  DRM will call back into the
+ * driver with a new screen width and height.  If the driver can't support
+ * the proposed size, it can return false.  Otherwise it should adjust
+ * the CRTC<->output mappings as needed and update its view of the screen.
+ */
+struct drm_mode_config_funcs {
+       bool (*resize)(struct drm_device *dev, int width, int height);
+};
+
+/**
+ * drm_mode_config - Mode configuration control structure
+ *
+ */
+struct drm_mode_config {
+       struct mutex mutex; /* protects configuration and IDR */
+       struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, output, modes - just makes life easier */
+       /* this is limited to one for now */
+       int num_fb;
+       struct list_head fb_list;
+       int num_output;
+       struct list_head output_list;
+
+       /* int compat_output? */
+       int num_crtc;
+       struct list_head crtc_list;
+
+       struct list_head usermode_list;
+       int min_width, min_height;
+       int max_width, max_height;
+       /* DamagePtr rotationDamage? */
+       /* DGA stuff? */
+       struct drm_mode_config_funcs *funcs;
+       unsigned long fb_base;
+};
+
+struct drm_output *drm_output_create(struct drm_device *dev,
+                                    const struct drm_output_funcs *funcs,
+                                    const char *name);
+extern void drm_output_destroy(struct drm_output *output);
+extern bool drm_output_rename(struct drm_output *output, const char *name);
+extern void drm_fb_release(struct file *filp);
+
+extern int drm_add_edid_modes(struct drm_output *output,
+                       struct i2c_adapter *adapter);
+extern void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode);
+extern void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode);
+extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
+                                                  struct drm_display_mode *mode);
+extern void drm_mode_debug_printmodeline(struct drm_device *dev,
+                                        struct drm_display_mode *mode);
+extern void drm_mode_config_init(struct drm_device *dev);
+extern void drm_mode_config_cleanup(struct drm_device *dev);
+extern void drm_mode_set_name(struct drm_display_mode *mode);
+extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2);
+extern void drm_disable_unused_functions(struct drm_device *dev);
+
+extern struct drm_display_mode *drm_mode_create(struct drm_device *dev);
+extern void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
+extern void drm_mode_list_concat(struct list_head *head,
+                                struct list_head *new);
+extern void drm_mode_validate_size(struct drm_device *dev,
+                                  struct list_head *mode_list,
+                                  int maxX, int maxY, int maxPitch);
+extern void drm_mode_prune_invalid(struct drm_device *dev,
+                                  struct list_head *mode_list, bool verbose);
+extern void drm_mode_sort(struct list_head *mode_list);
+extern int drm_mode_vrefresh(struct drm_display_mode *mode);
+extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
+                                 int adjust_flags);
+extern void drm_mode_output_list_update(struct drm_output *output);
+
+extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
+extern bool drm_initial_config(struct drm_device *dev, bool cangrow);
+extern void drm_framebuffer_set_object(struct drm_device *dev,
+                                      unsigned long handle);
+extern struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev);
+extern void drm_framebuffer_destroy(struct drm_framebuffer *fb);
+extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
+extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
+extern bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                      int x, int y);
+
+/* IOCTLs */
+extern int drm_mode_getresources(struct drm_device *dev,
+                                void *data, struct drm_file *file_priv);
+
+extern int drm_mode_getcrtc(struct drm_device *dev,
+                           void *data, struct drm_file *file_priv);
+extern int drm_mode_getoutput(struct drm_device *dev,
+                             void *data, struct drm_file *file_priv);
+extern int drm_mode_setcrtc(struct drm_device *dev,
+                           void *data, struct drm_file *file_priv);
+extern int drm_mode_addfb(struct drm_device *dev,
+                         void *data, struct drm_file *file_priv);
+extern int drm_mode_rmfb(struct drm_device *dev,
+                        void *data, struct drm_file *file_priv);
+extern int drm_mode_getfb(struct drm_device *dev,
+                         void *data, struct drm_file *file_priv);
+extern int drm_mode_addmode(struct drm_device *dev,
+                           void *data, struct drm_file *file_priv);
+extern int drm_mode_rmmode(struct drm_device *dev,
+                          void *data, struct drm_file *file_priv);
+extern int drm_mode_attachmode(struct drm_device *dev,
+                              void *data, struct drm_file *file_priv);
+extern int drm_mode_detachmode(struct drm_device *dev,
+                              void *data, struct drm_file *file_priv);
+
+#endif /* __DRM_CRTC_H__ */
+
index a7eee1a..7cc4419 100644 (file)
@@ -43,7 +43,7 @@
  *
  * Allocate and initialize a drm_device_dma structure.
  */
-int drm_dma_setup(drm_device_t * dev)
+int drm_dma_setup(struct drm_device * dev)
 {
        int i;
 
@@ -67,9 +67,9 @@ int drm_dma_setup(drm_device_t * dev)
  * Free all pages associated with DMA buffers, the buffers and pages lists, and
  * finally the the drm_device::dma structure itself.
  */
-void drm_dma_takedown(drm_device_t * dev)
+void drm_dma_takedown(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int i, j;
 
        if (!dma)
@@ -129,14 +129,14 @@ void drm_dma_takedown(drm_device_t * dev)
  *
  * Resets the fields of \p buf.
  */
-void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
+void drm_free_buffer(struct drm_device * dev, struct drm_buf * buf)
 {
        if (!buf)
                return;
 
        buf->waiting = 0;
        buf->pending = 0;
-       buf->filp = NULL;
+       buf->file_priv = NULL;
        buf->used = 0;
 
        if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
@@ -148,19 +148,20 @@ void drm_free_buffer(drm_device_t * dev, drm_buf_t * buf)
 /**
  * Reclaim the buffers.
  *
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  *
- * Frees each buffer associated with \p filp not already on the hardware.
+ * Frees each buffer associated with \p file_priv not already on the hardware.
  */
-void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp)
+void drm_core_reclaim_buffers(struct drm_device *dev,
+                             struct drm_file *file_priv)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int i;
 
        if (!dma)
                return;
        for (i = 0; i < dma->buf_count; i++) {
-               if (dma->buflist[i]->filp == filp) {
+               if (dma->buflist[i]->file_priv == file_priv) {
                        switch (dma->buflist[i]->list) {
                        case DRM_LIST_NONE:
                                drm_free_buffer(dev, dma->buflist[i]);
index d599430..1839c57 100644 (file)
 /**
  * Allocate drawable ID and memory to store information about it.
  */
-int drm_adddraw(DRM_IOCTL_ARGS)
+int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        unsigned long irqflags;
-       struct drm_drawable_list *draw_info;
-       drm_draw_t draw;
+       struct drm_draw *draw = data;
        int new_id = 0;
        int ret;
 
-       draw_info = drm_calloc(1, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
-       if (!draw_info)
-               return -ENOMEM;
-
 again:
        if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
                DRM_ERROR("Out of memory expanding drawable idr\n");
-               drm_free(draw_info, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
                return -ENOMEM;
        }
 
        spin_lock_irqsave(&dev->drw_lock, irqflags);
-       ret = idr_get_new_above(&dev->drw_idr, draw_info, 1, &new_id);
+       ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
        if (ret == -EAGAIN) {
                spin_unlock_irqrestore(&dev->drw_lock, irqflags);
                goto again;
        }
 
-       list_add(&draw_info->head, &dev->drwlist);
-
        spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
-       draw_info->id = new_id;
-       draw.handle = new_id;
-
-       DRM_DEBUG("%d\n", draw.handle);
+       draw->handle = new_id;
 
-       DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
+       DRM_DEBUG("%d\n", draw->handle);
 
        return 0;
 }
@@ -84,74 +72,64 @@ again:
 /**
  * Free drawable ID and memory to store information about it.
  */
-int drm_rmdraw(DRM_IOCTL_ARGS)
+int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_draw_t draw;
+       struct drm_draw *draw = data;
        unsigned long irqflags;
-       struct drm_drawable_list *draw_info;
-
-       DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
-                                sizeof(draw));
-
-       draw_info = idr_find(&dev->drw_idr, draw.handle);
-       if (!draw_info) {
-               DRM_DEBUG("No such drawable %d\n", draw.handle);
-               return -EINVAL;
-       }
 
        spin_lock_irqsave(&dev->drw_lock, irqflags);
 
-       list_del(&draw_info->head);
-       idr_remove(&dev->drw_idr, draw.handle);
-       drm_free(draw_info, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
+       drm_free(drm_get_drawable_info(dev, draw->handle),
+                sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
+
+       idr_remove(&dev->drw_idr, draw->handle);
 
        spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-       DRM_DEBUG("%d\n", draw.handle);
+       DRM_DEBUG("%d\n", draw->handle);
        return 0;
 }
 
-int drm_update_drawable_info(DRM_IOCTL_ARGS) {
-       DRM_DEVICE;
-       drm_update_draw_t update;
+int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_update_draw *update = data;
        unsigned long irqflags;
-       drm_drawable_info_t *info;
-       drm_clip_rect_t *rects;
-       struct drm_drawable_list *draw_info;
+       struct drm_clip_rect *rects;
+       struct drm_drawable_info *info;
        int err;
 
-       DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
-                                sizeof(update));
-
-       draw_info = idr_find(&dev->drw_idr, update.handle);
-       if (!draw_info) {
-               DRM_ERROR("No such drawable %d\n", update.handle);
-               return DRM_ERR(EINVAL);
+       info = idr_find(&dev->drw_idr, update->handle);
+       if (!info) {
+               info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
+               if (!info)
+                       return -ENOMEM;
+               if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) {
+                       DRM_ERROR("No such drawable %d\n", update->handle);
+                       drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+                       return -EINVAL;
+               }
        }
 
-       info = &draw_info->info;
-
-       switch (update.type) {
+       switch (update->type) {
        case DRM_DRAWABLE_CLIPRECTS:
-               if (update.num != info->num_rects) {
-                       rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
+               if (update->num != info->num_rects) {
+                       rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
                                         DRM_MEM_BUFS);
                } else
                        rects = info->rects;
 
-               if (update.num && !rects) {
+               if (update->num && !rects) {
                        DRM_ERROR("Failed to allocate cliprect memory\n");
-                       err = DRM_ERR(ENOMEM);
+                       err = -ENOMEM;
                        goto error;
                }
 
-               if (update.num && DRM_COPY_FROM_USER(rects,
-                                                    (drm_clip_rect_t __user *)
-                                                    (unsigned long)update.data,
-                                                    update.num *
+               if (update->num && DRM_COPY_FROM_USER(rects,
+                                                    (struct drm_clip_rect __user *)
+                                                    (unsigned long)update->data,
+                                                    update->num *
                                                     sizeof(*rects))) {
                        DRM_ERROR("Failed to copy cliprects from userspace\n");
-                       err = DRM_ERR(EFAULT);
+                       err = -EFAULT;
                        goto error;
                }
 
@@ -159,27 +137,27 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) {
 
                if (rects != info->rects) {
                        drm_free(info->rects, info->num_rects *
-                                sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+                                sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
                }
 
                info->rects = rects;
-               info->num_rects = update.num;
+               info->num_rects = update->num;
 
                spin_unlock_irqrestore(&dev->drw_lock, irqflags);
 
                DRM_DEBUG("Updated %d cliprects for drawable %d\n",
-                         info->num_rects, update.handle);
+                         info->num_rects, update->handle);
                break;
        default:
-               DRM_ERROR("Invalid update type %d\n", update.type);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("Invalid update type %d\n", update->type);
+               return -EINVAL;
        }
 
        return 0;
 
 error:
        if (rects != info->rects)
-               drm_free(rects, update.num * sizeof(drm_clip_rect_t),
+               drm_free(rects, update->num * sizeof(struct drm_clip_rect),
                         DRM_MEM_BUFS);
 
        return err;
@@ -188,14 +166,27 @@ error:
 /**
  * Caller must hold the drawable spinlock!
  */
-drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
-       struct drm_drawable_list *draw_info;
-       draw_info = idr_find(&dev->drw_idr, id);
-       if (!draw_info) {
-               DRM_DEBUG("No such drawable %d\n", id);
-               return NULL;
+struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
+{
+       return idr_find(&dev->drw_idr, id);
+}
+EXPORT_SYMBOL(drm_get_drawable_info);
+
+static int drm_drawable_free(int idr, void *p, void *data)
+{
+       struct drm_drawable_info *info = p;
+
+       if (info) {
+               drm_free(info->rects, info->num_rects *
+                        sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+               drm_free(info, sizeof(*info), DRM_MEM_BUFS);
        }
 
-       return &draw_info->info;
+       return 0;
+}
+
+void drm_drawable_free_all(struct drm_device *dev)
+{
+       idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
+       idr_remove_all(&dev->drw_idr);
 }
-EXPORT_SYMBOL(drm_get_drawable_info);
index 1695a79..4a871d6 100644 (file)
 #include "drmP.h"
 #include "drm_core.h"
 
-static void drm_cleanup(drm_device_t * dev);
+static void drm_cleanup(struct drm_device * dev);
 int drm_fb_loaded = 0;
 
-static int drm_version(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg);
+static int drm_version(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
 
 /** Ioctl table */
-static drm_ioctl_desc_t drm_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0},
-       [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0},
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH},
+static struct drm_ioctl_desc drm_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
        /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
-       [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH},
+       DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH),
 
-       [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
 #if __OS_HAS_AGP
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 #endif
 
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-
-       [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
-       [DRM_IOCTL_NR(DRM_IOCTL_FENCE)] = {drm_fence_ioctl, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_IOCTL_BUFOBJ)] = {drm_bo_ioctl, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_IOCTL_MM_INIT)] = {drm_mm_init_ioctl, 
-                                            DRM_AUTH },
-
-       [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+       // DRM_IOCTL_DEF(DRM_IOCTL_BUFOBJ, drm_bo_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, 
+                                            DRM_AUTH ),
+       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETOUTPUT, drm_mode_getoutput, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDMODE, drm_mode_addmode, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMMODE, drm_mode_rmmode, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode, DRM_MASTER|DRM_ROOT_ONLY),
+       //      DRM_IOCTL_DEF(DRM_IOCTL_BUFOBJ, drm_bo_ioctl, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+
+       DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, 
+                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, 
+                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, 
+                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, 
+                     DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_REFERENCE, drm_fence_reference_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_UNREFERENCE, drm_fence_unreference_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_SIGNALED, drm_fence_signaled_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_FLUSH, drm_fence_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_WAIT, drm_fence_wait_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_EMIT, drm_fence_emit_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FENCE_BUFFERS, drm_fence_buffers_ioctl, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_CREATE, drm_bo_create_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_MAP, drm_bo_map_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_UNMAP, drm_bo_unmap_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_REFERENCE, drm_bo_reference_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_UNREFERENCE, drm_bo_unreference_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0),
 };
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
@@ -137,12 +177,11 @@ static drm_ioctl_desc_t drm_ioctls[] = {
  *
  * \sa drm_device
  */
-int drm_lastclose(drm_device_t * dev)
+int drm_lastclose(struct drm_device * dev)
 {
-       drm_magic_entry_t *pt, *next;
-       drm_map_list_t *r_list, *list_t;
-       drm_vma_entry_t *vma, *vma_temp;
-       struct drm_drawable_list *drw_entry, *drw_temp;
+       struct drm_magic_entry *pt, *next;
+       struct drm_map_list *r_list, *list_t;
+       struct drm_vma_entry *vma, *vma_temp;
        int i;
 
        DRM_DEBUG("\n");
@@ -151,8 +190,6 @@ int drm_lastclose(drm_device_t * dev)
         * We can't do much about this function failing.
         */
 
-       drm_bo_driver_finish(dev);
-
        if (dev->driver->lastclose)
                dev->driver->lastclose(dev);
        DRM_DEBUG("driver lastclose completed\n");
@@ -167,16 +204,9 @@ int drm_lastclose(drm_device_t * dev)
                drm_irq_uninstall(dev);
 
        /* Free drawable information memory */
-       list_for_each_entry_safe(drw_entry, drw_temp, &dev->drwlist, head) {
-               drm_free(drw_entry->info.rects, drw_entry->info.num_rects *
-                        sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
-
-               idr_remove(&dev->drw_idr, drw_entry->id);
-               list_del(&drw_entry->head);
-               drm_free(drw_entry, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
-       }
-
        mutex_lock(&dev->struct_mutex);
+
+       drm_drawable_free_all(dev);
        del_timer(&dev->timer);
 
        if (dev->unique) {
@@ -197,7 +227,7 @@ int drm_lastclose(drm_device_t * dev)
 
        /* Clear AGP information */
        if (drm_core_has_AGP(dev) && dev->agp) {
-               drm_agp_mem_t *entry, *tempe;
+               struct drm_agp_mem *entry, *tempe;
 
                /* Remove AGP resources, but leave dev->agp
                   intact until drv_cleanup is called. */
@@ -253,7 +283,7 @@ int drm_lastclose(drm_device_t * dev)
 
        if (dev->lock.hw_lock) {
                dev->sigdata.lock = dev->lock.hw_lock = NULL;   /* SHM removed */
-               dev->lock.filp = NULL;
+               dev->lock.file_priv = NULL;
                wake_up_interruptible(&dev->lock.lock_queue);
        }
        dev->dev_mapping = NULL;
@@ -265,7 +295,7 @@ int drm_lastclose(drm_device_t * dev)
 
 void drm_cleanup_pci(struct pci_dev *pdev)
 {
-       drm_device_t *dev = pci_get_drvdata(pdev);
+       struct drm_device *dev = pci_get_drvdata(pdev);
 
        pci_set_drvdata(pdev, NULL);
        pci_release_regions(pdev);
@@ -304,6 +334,11 @@ int drm_init(struct drm_driver *driver,
                while ((pdev =
                        pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
                                       pid->subdevice, pdev))) {
+                       /* Are there device class requirements? */
+                       if ((pid->class != 0) 
+                               && ((pdev->class & pid->class_mask) != pid->class)) {
+                               continue;
+                       }
                        /* is there already a driver loaded, or (short circuit saves work) */
                        /* does something like VesaFB have control of the memory region? */
                        if (pci_dev_driver(pdev)
@@ -319,7 +354,7 @@ int drm_init(struct drm_driver *driver,
        }
 
        if (!drm_fb_loaded)
-               pci_register_driver(&driver->pci_driver);
+               return pci_register_driver(&driver->pci_driver);
        else {
                for (i = 0; pciidlist[i].vendor != 0; i++) {
                        pid = &pciidlist[i];
@@ -330,6 +365,11 @@ int drm_init(struct drm_driver *driver,
                                pci_get_subsys(pid->vendor, pid->device,
                                               pid->subvendor, pid->subdevice,
                                               pdev))) {
+                               /* Are there device class requirements? */
+                               if ((pid->class != 0) 
+                                       && ((pdev->class & pid->class_mask) != pid->class)) {
+                                       continue;
+                               }
                                /* stealth mode requires a manual probe */
                                pci_dev_get(pdev);
                                if ((rc = drm_get_dev(pdev, &pciidlist[i], driver))) {
@@ -351,7 +391,7 @@ EXPORT_SYMBOL(drm_init);
  *
  * \sa drm_init
  */
-static void drm_cleanup(drm_device_t * dev)
+static void drm_cleanup(struct drm_device * dev)
 {
 
        DRM_DEBUG("\n");
@@ -363,7 +403,6 @@ static void drm_cleanup(drm_device_t * dev)
        drm_lastclose(dev);
        drm_fence_manager_takedown(dev);
 
-       drm_ht_remove(&dev->map_hash);
        drm_mm_takedown(&dev->offset_manager);
        drm_ht_remove(&dev->object_hash);
 
@@ -381,12 +420,17 @@ static void drm_cleanup(drm_device_t * dev)
                DRM_DEBUG("mtrr_del=%d\n", retval);
        }
 
+       if (dev->driver->unload)
+               dev->driver->unload(dev);
+        
+       drm_ht_remove(&dev->map_hash);
        if (drm_core_has_AGP(dev) && dev->agp) {
                drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
                dev->agp = NULL;
        }
-       if (dev->driver->unload)
-               dev->driver->unload(dev);
+
+       if (!drm_fb_loaded)
+               pci_disable_device(dev->pdev);
 
        drm_put_head(&dev->primary);
        if (drm_put_dev(dev))
@@ -396,8 +440,8 @@ static void drm_cleanup(drm_device_t * dev)
 void drm_exit(struct drm_driver *driver)
 {
        int i;
-       drm_device_t *dev = NULL;
-       drm_head_t *head;
+       struct drm_device *dev = NULL;
+       struct drm_head *head;
 
        DRM_DEBUG("\n");
        if (drm_fb_loaded) {
@@ -515,34 +559,26 @@ module_exit(drm_core_exit);
  * Get version information
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_version structure.
  * \return zero on success or negative number on failure.
  *
  * Fills in the version information in \p arg.
  */
-static int drm_version(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+static int drm_version(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_version_t __user *argp = (void __user *)arg;
-       drm_version_t version;
+       struct drm_version *version = data;
        int len;
 
-       if (copy_from_user(&version, argp, sizeof(version)))
-               return -EFAULT;
+       version->version_major = dev->driver->major;
+       version->version_minor = dev->driver->minor;
+       version->version_patchlevel = dev->driver->patchlevel;
+       DRM_COPY(version->name, dev->driver->name);
+       DRM_COPY(version->date, dev->driver->date);
+       DRM_COPY(version->desc, dev->driver->desc);
 
-       version.version_major = dev->driver->major;
-       version.version_minor = dev->driver->minor;
-       version.version_patchlevel = dev->driver->patchlevel;
-       DRM_COPY(version.name, dev->driver->name);
-       DRM_COPY(version.date, dev->driver->date);
-       DRM_COPY(version.desc, dev->driver->desc);
-
-       if (copy_to_user(argp, &version, sizeof(version)))
-               return -EFAULT;
        return 0;
 }
 
@@ -550,31 +586,43 @@ static int drm_version(struct inode *inode, struct file *filp,
  * Called whenever a process performs an ioctl on /dev/drm.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument.
  * \return zero on success or negative number on failure.
  *
  * Looks up the ioctl function in the ::ioctls table, checking for root
  * previleges if so required, and dispatches to the respective function.
+ *
+ * Copies data in and out according to the size and direction given in cmd,
+ * which must match the ioctl cmd known by the kernel.  The kernel uses a 512
+ * byte stack buffer to store the ioctl arguments in kernel space.  Should we
+ * ever need much larger ioctl arguments, we may need to allocate memory.
  */
 int drm_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->head->dev;
-       drm_ioctl_desc_t *ioctl;
+       return drm_unlocked_ioctl(filp, cmd, arg);
+}
+EXPORT_SYMBOL(drm_ioctl);
+
+long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_ioctl_desc *ioctl;
        drm_ioctl_t *func;
        unsigned int nr = DRM_IOCTL_NR(cmd);
        int retcode = -EINVAL;
+       char kdata[512];
 
        atomic_inc(&dev->ioctl_count);
        atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
-       ++priv->ioctl_count;
+       ++file_priv->ioctl_count;
 
        DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
-                 current->pid, cmd, nr, (long)old_encode_dev(priv->head->device),
-                 priv->authenticated);
+                 current->pid, cmd, nr, (long)old_encode_dev(file_priv->head->device),
+                 file_priv->authenticated);
 
        if ((nr >= DRM_CORE_IOCTL_COUNT) &&
            ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
@@ -584,35 +632,63 @@ int drm_ioctl(struct inode *inode, struct file *filp,
                ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
        else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
                ioctl = &drm_ioctls[nr];
-       else
+       else {
+               retcode = -EINVAL;
                goto err_i1;
-
+       }
+#if 0
+       /*
+        * This check is disabled, because driver private ioctl->cmd
+        * are not the ioctl commands with size and direction bits but
+        * just the indices. The DRM core ioctl->cmd are the proper ioctl
+        * commands. The drivers' ioctl tables need to be fixed.
+        */
+       if (ioctl->cmd != cmd) {
+               retcode = -EINVAL;
+               goto err_i1;
+       }
+#endif
        func = ioctl->func;
        /* is there a local override? */
        if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
                func = dev->driver->dma_ioctl;
 
+       if (cmd & IOC_IN) {
+               if (copy_from_user(kdata, (void __user *)arg,
+                                  _IOC_SIZE(cmd)) != 0) {
+                       retcode = -EACCES;
+                       goto err_i1;
+               }
+       }
+
        if (!func) {
                DRM_DEBUG("no function\n");
                retcode = -EINVAL;
        } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
-                  ((ioctl->flags & DRM_AUTH) && !priv->authenticated) ||
-                  ((ioctl->flags & DRM_MASTER) && !priv->master)) {
+                  ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
+                  ((ioctl->flags & DRM_MASTER) && !file_priv->master)) {
                retcode = -EACCES;
        } else {
-               retcode = func(inode, filp, cmd, arg);
+               retcode = func(dev, kdata, file_priv);
+       }
+
+       if ((retcode == 0) && (cmd & IOC_OUT)) {
+               if (copy_to_user((void __user *)arg, kdata,
+                                _IOC_SIZE(cmd)) != 0)
+                       retcode = -EACCES;
        }
+
 err_i1:
        atomic_dec(&dev->ioctl_count);
        if (retcode)
-               DRM_DEBUG("ret = %x\n", retcode);
+               DRM_DEBUG("ret = %d\n", retcode);
        return retcode;
 }
-EXPORT_SYMBOL(drm_ioctl);
+EXPORT_SYMBOL(drm_unlocked_ioctl);
 
 drm_local_map_t *drm_getsarea(struct drm_device *dev)
 {
-       drm_map_list_t *entry;
+       struct drm_map_list *entry;
 
        list_for_each_entry(entry, &dev->maplist, head) {
                if (entry->map && entry->map->type == _DRM_SHM &&
diff --git a/linux-core/drm_edid.c b/linux-core/drm_edid.c
new file mode 100644 (file)
index 0000000..d7d3939
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2007 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
+ * FB layer.
+ *   Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
+ */
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include "drmP.h"
+#include "drm_edid.h"
+
+/* Valid EDID header has these bytes */
+static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
+
+/**
+ * edid_valid - sanity check EDID data
+ * @edid: EDID data
+ *
+ * Sanity check the EDID block by looking at the header, the version number
+ * and the checksum.  Return 0 if the EDID doesn't check out, or 1 if it's
+ * valid.
+ */
+static bool edid_valid(struct edid *edid)
+{
+       int i;
+       u8 csum = 0;
+       u8 *raw_edid = (u8 *)edid;
+
+       if (memcmp(edid->header, edid_header, sizeof(edid_header)))
+               goto bad;
+       if (edid->version != 1)
+               goto bad;
+       if (edid->revision <= 0 || edid->revision > 3)
+               goto bad;
+
+       for (i = 0; i < EDID_LENGTH; i++)
+               csum += raw_edid[i];
+       if (csum)
+               goto bad;
+
+       return 1;
+
+bad:
+       return 0;
+}
+
+/**
+ * drm_mode_std - convert standard mode info (width, height, refresh) into mode
+ * @t: standard timing params
+ *
+ * Take the standard timing params (in this case width, aspect, and refresh)
+ * and convert them into a real mode using CVT.
+ *
+ * Punts for now, but should eventually use the FB layer's CVT based mode
+ * generation code.
+ */
+struct drm_display_mode *drm_mode_std(struct drm_device *dev,
+                                     struct std_timing *t)
+{
+//     struct fb_videomode mode;
+
+//     fb_find_mode_cvt(&mode, 0, 0);
+       /* JJJ:  convert to drm_display_mode */
+       struct drm_display_mode *mode;
+       int hsize = t->hsize * 8 + 248, vsize;
+
+       mode = drm_mode_create(dev);
+       if (!mode)
+               return NULL;
+
+       if (t->aspect_ratio == 0)
+               vsize = (hsize * 10) / 16;
+       else if (t->aspect_ratio == 1)
+               vsize = (hsize * 3) / 4;
+       else if (t->aspect_ratio == 2)
+               vsize = (hsize * 4) / 5;
+       else
+               vsize = (hsize * 9) / 16;
+
+       drm_mode_set_name(mode);
+
+       return mode;
+}
+
+/**
+ * drm_mode_detailed - create a new mode from an EDID detailed timing section
+ * @timing: EDID detailed timing info
+ * @preferred: is this a preferred mode?
+ *
+ * An EDID detailed timing block contains enough info for us to create and
+ * return a new struct drm_display_mode.  The @preferred flag will be set
+ * if this is the display's preferred timing, and we'll use it to indicate
+ * to the other layers that this mode is desired.
+ */
+struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
+                                          struct detailed_timing *timing)
+{
+       struct drm_display_mode *mode;
+       struct detailed_pixel_timing *pt = &timing->data.pixel_data;
+
+       if (pt->stereo) {
+               printk(KERN_WARNING "stereo mode not supported\n");
+               return NULL;
+       }
+       if (!pt->separate_sync) {
+               printk(KERN_WARNING "integrated sync not supported\n");
+               return NULL;
+       }
+
+       mode = drm_mode_create(dev);
+       if (!mode)
+               return NULL;
+
+       mode->type = DRM_MODE_TYPE_DRIVER;
+       mode->clock = timing->pixel_clock * 10;
+
+       mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo;
+       mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) |
+                                             pt->hsync_offset_lo);
+       mode->hsync_end = mode->hsync_start +
+               ((pt->hsync_pulse_width_hi << 8) |
+                pt->hsync_pulse_width_lo);
+       mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
+
+       mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
+       mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) |
+                                             pt->vsync_offset_lo);
+       mode->vsync_end = mode->vsync_start +
+               ((pt->vsync_pulse_width_hi << 8) |
+                pt->vsync_pulse_width_lo);
+       mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
+
+       drm_mode_set_name(mode);
+
+       if (pt->interlaced)
+               mode->flags |= V_INTERLACE;
+
+       mode->flags |= pt->hsync_positive ? V_PHSYNC : V_NHSYNC;
+       mode->flags |= pt->vsync_positive ? V_PVSYNC : V_NVSYNC;
+
+       return mode;
+}
+
+/*
+ * Detailed mode info for the EDID "established modes" data to use.
+ */
+static struct drm_display_mode edid_est_modes[] = {
+       { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
+                  968, 1056, 0, 600, 601, 605, 628, 0,
+                  V_PHSYNC | V_PVSYNC) }, /* 800x600@60Hz */
+       { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
+                  896, 1024, 0, 600, 601, 603,  625, 0,
+                  V_PHSYNC | V_PVSYNC) }, /* 800x600@56Hz */
+       { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
+                  720, 840, 0, 480, 481, 484, 500, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 640x480@75Hz */
+       { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
+                  704,  832, 0, 480, 489, 491, 520, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 640x480@72Hz */
+       { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704,
+                  768,  864, 0, 480, 483, 486, 525, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 640x480@67Hz */
+       { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656,
+                  752, 800, 0, 480, 490, 492, 525, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
+       { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738,
+                  846, 900, 0, 400, 421, 423,  449, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 720x400@88Hz */
+       { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738,
+                  846,  900, 0, 400, 412, 414, 449, 0,
+                  V_NHSYNC | V_PVSYNC) }, /* 720x400@70Hz */
+       { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
+                  1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
+                  V_PHSYNC | V_PVSYNC) }, /* 1280x1024@75Hz */
+       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040,
+                  1136, 1312, 0,  768, 769, 772, 800, 0,
+                  V_PHSYNC | V_PVSYNC) }, /* 1024x768@75Hz */
+       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
+                  1184, 1328, 0,  768, 771, 777, 806, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 1024x768@70Hz */
+       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
+                  1184, 1344, 0,  768, 771, 777, 806, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 1024x768@60Hz */
+       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
+                  1208, 1264, 0, 768, 768, 776, 817, 0,
+                  V_PHSYNC | V_PVSYNC | V_INTERLACE) }, /* 1024x768@43Hz */
+       { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864,
+                  928, 1152, 0, 624, 625, 628, 667, 0,
+                  V_NHSYNC | V_NVSYNC) }, /* 832x624@75Hz */
+       { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
+                  896, 1056, 0, 600, 601, 604,  625, 0,
+                  V_PHSYNC | V_PVSYNC) }, /* 800x600@75Hz */
+       { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
+                  976, 1040, 0, 600, 637, 643, 666, 0,
+                  V_PHSYNC | V_PVSYNC) }, /* 800x600@72Hz */
+       { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
+                  1344, 1600, 0,  864, 865, 868, 900, 0,
+                  V_PHSYNC | V_PVSYNC) }, /* 1152x864@75Hz */
+};
+
+#define EDID_EST_TIMINGS 16
+#define EDID_STD_TIMINGS 8
+#define EDID_DETAILED_TIMINGS 4
+
+/**
+ * add_established_modes - get est. modes from EDID and add them
+ * @edid: EDID block to scan
+ *
+ * Each EDID block contains a bitmap of the supported "established modes" list
+ * (defined above).  Tease them out and add them to the global modes list.
+ */
+static int add_established_modes(struct drm_output *output, struct edid *edid)
+{
+       struct drm_device *dev = output->dev;
+       unsigned long est_bits = edid->established_timings.t1 |
+               (edid->established_timings.t2 << 8) |
+               ((edid->established_timings.mfg_rsvd & 0x80) << 9);
+       int i, modes = 0;
+
+       for (i = 0; i <= EDID_EST_TIMINGS; i++)
+               if (est_bits & (1<<i)) {
+                       struct drm_display_mode *newmode;
+                       newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
+                       drm_mode_probed_add(output, newmode);
+                       modes++;
+               }
+
+       return modes;
+}
+
+/**
+ * add_standard_modes - get std. modes from EDID and add them
+ * @edid: EDID block to scan
+ *
+ * Standard modes can be calculated using the CVT standard.  Grab them from
+ * @edid, calculate them, and add them to the list.
+ */
+static int add_standard_modes(struct drm_output *output, struct edid *edid)
+{
+       struct drm_device *dev = output->dev;
+       int i, modes = 0;
+
+       for (i = 0; i < EDID_STD_TIMINGS; i++) {
+               struct std_timing *t = &edid->standard_timings[i];
+               struct drm_display_mode *newmode;
+
+               /* If std timings bytes are 1, 1 it's empty */
+               if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1)
+                       continue;
+
+               newmode = drm_mode_std(dev, &edid->standard_timings[i]);
+               drm_mode_probed_add(output, newmode);
+               modes++;
+       }
+
+       return modes;
+}
+
+/**
+ * add_detailed_modes - get detailed mode info from EDID data
+ * @edid: EDID block to scan
+ *
+ * Some of the detailed timing sections may contain mode information.  Grab
+ * it and add it to the list.
+ */
+static int add_detailed_info(struct drm_output *output, struct edid *edid)
+{
+       struct drm_device *dev = output->dev;
+       int i, j, modes = 0;
+
+       for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
+               struct detailed_timing *timing = &edid->detailed_timings[i];
+               struct detailed_non_pixel *data = &timing->data.other_data;
+               struct drm_display_mode *newmode;
+
+               /* EDID up to and including 1.2 may put monitor info here */
+               if (edid->version == 1 && edid->revision < 3)
+                       continue;
+
+               /* Detailed mode timing */
+               if (timing->pixel_clock) {
+                       newmode = drm_mode_detailed(dev, timing);
+                       /* First detailed mode is preferred */
+                       if (i == 0 && edid->preferred_timing)
+                               newmode->type |= DRM_MODE_TYPE_PREFERRED;
+                       drm_mode_probed_add(output, newmode);
+                                    
+                       modes++;
+                       continue;
+               }
+
+               /* Other timing or info */
+               switch (data->type) {
+               case EDID_DETAIL_MONITOR_SERIAL:
+                       break;
+               case EDID_DETAIL_MONITOR_STRING:
+                       break;
+               case EDID_DETAIL_MONITOR_RANGE:
+                       /* Get monitor range data */
+                       break;
+               case EDID_DETAIL_MONITOR_NAME:
+                       break;
+               case EDID_DETAIL_MONITOR_CPDATA:
+                       break;
+               case EDID_DETAIL_STD_MODES:
+                       /* Five modes per detailed section */
+                       for (j = 0; j < 5; i++) {
+                               struct std_timing *std;
+                               struct drm_display_mode *newmode;
+
+                               std = &data->data.timings[j];
+                               newmode = drm_mode_std(dev, std);
+                               drm_mode_probed_add(output, newmode);
+                               modes++;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return modes;
+}
+
+#define DDC_ADDR 0x50
+
+static unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter)
+{
+       unsigned char start = 0x0;
+       unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+       struct i2c_msg msgs[] = {
+               {
+                       .addr   = DDC_ADDR,
+                       .flags  = 0,
+                       .len    = 1,
+                       .buf    = &start,
+               }, {
+                       .addr   = DDC_ADDR,
+                       .flags  = I2C_M_RD,
+                       .len    = EDID_LENGTH,
+                       .buf    = buf,
+               }
+       };
+
+       if (!buf) {
+               dev_warn(&adapter->dev, "unable to allocate memory for EDID "
+                        "block.\n");
+               return NULL;
+       }
+
+       if (i2c_transfer(adapter, msgs, 2) == 2)
+               return buf;
+
+       dev_info(&adapter->dev, "unable to read EDID block.\n");
+       kfree(buf);
+       return NULL;
+}
+
+static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
+{
+       struct i2c_algo_bit_data *algo_data = adapter->algo_data;
+       unsigned char *edid = NULL;
+       int i, j;
+
+       /*
+        * Startup the bus:
+        *   Set clock line high (but give it time to come up)
+        *   Then set clock & data low
+        */
+       algo_data->setscl(algo_data->data, 1);
+       udelay(550); /* startup delay */
+       algo_data->setscl(algo_data->data, 0);
+       algo_data->setsda(algo_data->data, 0);
+
+       for (i = 0; i < 3; i++) {
+               /* For some old monitors we need the
+                * following process to initialize/stop DDC
+                */
+               algo_data->setsda(algo_data->data, 0);
+               msleep(13);
+
+               algo_data->setscl(algo_data->data, 1);
+               for (j = 0; j < 5; j++) {
+                       msleep(10);
+                       if (algo_data->getscl(algo_data->data))
+                               break;
+               }
+               if (j == 5)
+                       continue;
+
+               algo_data->setsda(algo_data->data, 0);
+               msleep(15);
+               algo_data->setscl(algo_data->data, 0);
+               msleep(15);
+               algo_data->setsda(algo_data->data, 1);
+               msleep(15);
+
+               /* Do the real work */
+               edid = drm_do_probe_ddc_edid(adapter);
+               algo_data->setsda(algo_data->data, 0);
+               algo_data->setscl(algo_data->data, 0);
+               msleep(15);
+
+               algo_data->setscl(algo_data->data, 1);
+               for (j = 0; j < 10; j++) {
+                       msleep(10);
+                       if (algo_data->getscl(algo_data->data))
+                               break;
+               }
+
+               algo_data->setsda(algo_data->data, 1);
+               msleep(15);
+               algo_data->setscl(algo_data->data, 0);
+               if (edid)
+                       break;
+       }
+       /* Release the DDC lines when done or the Apple Cinema HD display
+        * will switch off
+        */
+       algo_data->setsda(algo_data->data, 0);
+       algo_data->setscl(algo_data->data, 0);
+       algo_data->setscl(algo_data->data, 1);
+
+       return edid;
+}
+
+/**
+ * drm_add_edid_modes - add modes from EDID data, if available
+ * @output: output we're probing
+ * @adapter: i2c adapter to use for DDC
+ *
+ * Poke the given output's i2c channel to grab EDID data if possible.  If we
+ * get any, add the specified modes to the output's mode list.
+ *
+ * Return number of modes added or 0 if we couldn't find any.
+ */
+int drm_add_edid_modes(struct drm_output *output, struct i2c_adapter *adapter)
+{
+       struct edid *edid;
+       int num_modes = 0;
+
+       edid = (struct edid *)drm_ddc_read(adapter);
+       if (!edid) {
+               dev_warn(&output->dev->pdev->dev, "%s: no EDID data\n",
+                        output->name);
+               goto out_err;
+       }
+
+       if (!edid_valid(edid)) {
+               dev_warn(&output->dev->pdev->dev, "%s: EDID invalid.\n",
+                        output->name);
+               goto out_err;
+       }
+
+       num_modes += add_established_modes(output, edid);
+       num_modes += add_standard_modes(output, edid);
+       num_modes += add_detailed_info(output, edid);
+
+       return num_modes;
+
+out_err:
+       kfree(edid);
+       return 0;
+}
+EXPORT_SYMBOL(drm_add_edid_modes);
diff --git a/linux-core/drm_edid.h b/linux-core/drm_edid.h
new file mode 100644 (file)
index 0000000..0d2eeaa
--- /dev/null
@@ -0,0 +1,176 @@
+#ifndef __DRM_EDID_H__
+#define __DRM_EDID_H__
+
+#include <linux/types.h>
+
+#define EDID_LENGTH 128
+#define DDC_ADDR 0x50
+
+#ifdef BIG_ENDIAN
+#error "EDID structure is little endian, need big endian versions"
+#endif
+
+struct est_timings {
+       u8 t1;
+       u8 t2;
+       u8 mfg_rsvd;
+} __attribute__((packed));
+
+struct std_timing {
+       u8 hsize; /* need to multiply by 8 then add 248 */
+       u8 vfreq:6; /* need to add 60 */
+       u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
+} __attribute__((packed));
+
+/* If detailed data is pixel timing */
+struct detailed_pixel_timing {
+       u8 hactive_lo;
+       u8 hblank_lo;
+       u8 hblank_hi:4;
+       u8 hactive_hi:4;
+       u8 vactive_lo;
+       u8 vblank_lo;
+       u8 vblank_hi:4;
+       u8 vactive_hi:4;
+       u8 hsync_offset_lo;
+       u8 hsync_pulse_width_lo;
+       u8 vsync_pulse_width_lo:4;
+       u8 vsync_offset_lo:4;
+       u8 hsync_pulse_width_hi:2;
+       u8 hsync_offset_hi:2;
+       u8 vsync_pulse_width_hi:2;
+       u8 vsync_offset_hi:2;
+       u8 width_mm_lo;
+       u8 height_mm_lo;
+       u8 height_mm_hi:4;
+       u8 width_mm_hi:4;
+       u8 hborder;
+       u8 vborder;
+       u8 unknown0:1;
+       u8 vsync_positive:1;
+       u8 hsync_positive:1;
+       u8 separate_sync:2;
+       u8 stereo:1;
+       u8 unknown6:1;
+       u8 interlaced:1;
+} __attribute__((packed));
+
+/* If it's not pixel timing, it'll be one of the below */
+struct detailed_data_string {
+       u8 str[13];
+} __attribute__((packed));
+
+struct detailed_data_monitor_range {
+       u8 min_vfreq;
+       u8 max_vfreq;
+       u8 min_hfreq_khz;
+       u8 max_hfreq_khz;
+       u8 pixel_clock_mhz; /* need to multiply by 10 */
+       u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */
+       u8 hfreq_start_khz; /* need to multiply by 2 */
+       u8 c; /* need to divide by 2 */
+       u16 m; /* FIXME: byte order */
+       u8 k;
+       u8 j; /* need to divide by 2 */
+} __attribute__((packed));
+
+struct detailed_data_wpindex {
+       u8 white_y_lo:2;
+       u8 white_x_lo:2;
+       u8 pad:4;
+       u8 white_x_hi;
+       u8 white_y_hi;
+       u8 gamma; /* need to divide by 100 then add 1 */
+} __attribute__((packed));
+
+struct detailed_data_color_point {
+       u8 windex1;
+       u8 wpindex1[3];
+       u8 windex2;
+       u8 wpindex2[3];
+} __attribute__((packed));
+
+struct detailed_non_pixel {
+       u8 pad1;
+       u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
+                   fb=color point data, fa=standard timing data,
+                   f9=undefined, f8=mfg. reserved */
+       u8 pad2;
+       union {
+               struct detailed_data_string str;
+               struct detailed_data_monitor_range range;
+               struct detailed_data_wpindex color;
+               struct std_timing timings[5];
+       } data;
+} __attribute__((packed));
+
+#define EDID_DETAIL_STD_MODES 0xfa
+#define EDID_DETAIL_MONITOR_CPDATA 0xfb
+#define EDID_DETAIL_MONITOR_NAME 0xfc
+#define EDID_DETAIL_MONITOR_RANGE 0xfd
+#define EDID_DETAIL_MONITOR_STRING 0xfe
+#define EDID_DETAIL_MONITOR_SERIAL 0xff
+
+struct detailed_timing {
+       u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */
+       union {
+               struct detailed_pixel_timing pixel_data;
+               struct detailed_non_pixel other_data;
+       } data;
+} __attribute__((packed));
+
+struct edid {
+       u8 header[8];
+       /* Vendor & product info */
+       u16 mfg_id; /* FIXME: byte order */
+       u16 prod_code; /* FIXME: byte order */
+       u32 serial; /* FIXME: byte order */
+       u8 mfg_week;
+       u8 mfg_year;
+       /* EDID version */
+       u8 version;
+       u8 revision;
+       /* Display info: */
+       /*   input definition */
+       u8 serration_vsync:1;
+       u8 sync_on_green:1;
+       u8 composite_sync:1;
+       u8 separate_syncs:1;
+       u8 blank_to_black:1;
+       u8 video_level:2;
+       u8 digital:1; /* bits below must be zero if set */
+       u8 width_cm;
+       u8 height_cm;
+       u8 gamma;
+       /*   feature support */
+       u8 default_gtf:1;
+       u8 preferred_timing:1;
+       u8 standard_color:1;
+       u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
+       u8 pm_active_off:1;
+       u8 pm_suspend:1;
+       u8 pm_standby:1;
+       /* Color characteristics */
+       u8 red_green_lo;
+       u8 black_white_lo;
+       u8 red_x;
+       u8 red_y;
+       u8 green_x;
+       u8 green_y;
+       u8 blue_x;
+       u8 blue_y;
+       u8 white_x;
+       u8 white_y;
+       /* Est. timings and mfg rsvd timings*/
+       struct est_timings established_timings;
+       /* Standard timings 1-8*/
+       struct std_timing standard_timings[8];
+       /* Detailing timings 1-4 */
+       struct detailed_timing detailed_timings[4];
+       /* Number of 128 byte ext. blocks */
+       u8 extensions;
+       /* Checksum */
+       u8 checksum;
+} __attribute__((packed));
+
+#endif /* __DRM_EDID_H__ */
diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c
new file mode 100644 (file)
index 0000000..775fd18
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * Copyright © 2007 David Airlie
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     David Airlie
+ */
+    /*
+     *  Modularization
+     */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include "drmP.h"
+#include "drm_crtc.h"
+
+struct drmfb_par {
+       struct drm_device *dev;
+       struct drm_crtc *crtc;
+};
+
+static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       struct drmfb_par *par = info->par;
+       struct drm_framebuffer *fb = par->crtc->fb;
+       struct drm_crtc *crtc = par->crtc;
+
+       if (regno > 255)
+               return 1;
+
+       if (fb->depth == 8) {
+               if (crtc->funcs->gamma_set) {
+                       crtc->funcs->gamma_set(crtc, red, green, blue, regno);
+               }
+               return 0;
+       }
+       
+       if (regno < 16) {
+               switch (fb->depth) {
+               case 15:
+                       fb->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
+                               ((green & 0xf800) >>  6) |
+                               ((blue & 0xf800) >> 11);
+                       break;
+               case 16:
+                       fb->pseudo_palette[regno] = (red & 0xf800) |
+                               ((green & 0xfc00) >>  5) |
+                               ((blue  & 0xf800) >> 11);
+                       break;
+               case 24:
+               case 32:
+                       fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
+                               (green & 0xff00) |
+                               ((blue  & 0xff00) >> 8);
+                       break;
+               }
+        }
+
+       return 0;
+}
+
+static int drmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct drmfb_par *par = info->par;
+       struct drm_device *dev = par->dev;
+       struct drm_framebuffer *fb = par->crtc->fb;
+       struct drm_display_mode *drm_mode;
+       struct drm_output *output;
+       int depth;
+
+       if (!var->pixclock)
+               return -EINVAL;
+
+       /* Need to resize the fb object !!! */
+       if (var->xres > fb->width || var->yres > fb->height) {
+               DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
+               DRM_ERROR("Need resizing code.\n");
+               return -EINVAL;
+       }
+
+       switch (var->bits_per_pixel) {
+       case 16:
+               depth = (var->green.length == 6) ? 16 : 15;
+               break;
+       case 32:
+               depth = (var->transp.length > 0) ? 32 : 24;
+               break;
+       default:
+               depth = var->bits_per_pixel;
+               break;
+       }
+               
+       switch (depth) {
+       case 8:
+               var->red.offset = 0;
+               var->green.offset = 0;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               break;
+       case 15:
+               var->red.offset = 10;
+               var->green.offset = 5;
+               var->blue.offset = 0;
+               var->red.length = 5;
+               var->green.length = 5;
+               var->blue.length = 5;
+               var->transp.length = 1;
+               var->transp.offset = 15;
+               break;
+       case 16:
+               var->red.offset = 11;
+               var->green.offset = 6;
+               var->blue.offset = 0;
+               var->red.length = 5;
+               var->green.length = 6;
+               var->blue.length = 5;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               break;
+       case 24:
+               var->red.offset = 16;
+               var->green.offset = 8;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               break;
+       case 32:
+               var->red.offset = 16;
+               var->green.offset = 8;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.length = 8;
+               var->transp.offset = 24;
+               break;
+       default:
+               return -EINVAL; 
+       }
+
+#if 0
+       /* Here we walk the output mode list and look for modes. If we haven't
+        * got it, then bail. Not very nice, so this is disabled.
+        * In the set_par code, we create our mode based on the incoming
+        * parameters. Nicer, but may not be desired by some.
+        */
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+               if (output->crtc == par->crtc)
+                       break;
+       }
+    
+       list_for_each_entry(drm_mode, &output->modes, head) {
+               if (drm_mode->hdisplay == var->xres &&
+                   drm_mode->vdisplay == var->yres &&
+                   drm_mode->clock != 0)
+                   break;
+       }
+
+       if (!drm_mode)
+               return -EINVAL;
+#endif
+
+       return 0;
+}
+
+/* this will let fbcon do the mode init */
+static int drmfb_set_par(struct fb_info *info)
+{
+       struct drmfb_par *par = info->par;
+       struct drm_framebuffer *fb = par->crtc->fb;
+       struct drm_device *dev = par->dev;
+       struct drm_display_mode *drm_mode;
+       struct fb_var_screeninfo *var = &info->var;
+       struct drm_output *output;
+
+       switch (var->bits_per_pixel) {
+       case 16:
+               fb->depth = (var->green.length == 6) ? 16 : 15;
+               break;
+       case 32:
+               fb->depth = (var->transp.length > 0) ? 32 : 24;
+               break;
+       default:
+               fb->depth = var->bits_per_pixel;
+               break;
+       }
+
+       fb->bits_per_pixel = var->bits_per_pixel;
+
+       info->fix.line_length = fb->pitch;
+       info->fix.smem_len = info->fix.line_length * fb->height;
+       info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+
+       info->screen_size = info->fix.smem_len; /* ??? */
+
+       /* Should we walk the output's modelist or just create our own ???
+        * For now, we create and destroy a mode based on the incoming 
+        * parameters. But there's commented out code below which scans 
+        * the output list too.
+        */
+#if 0
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+               if (output->crtc == par->crtc)
+                       break;
+       }
+    
+       list_for_each_entry(drm_mode, &output->modes, head) {
+               if (drm_mode->hdisplay == var->xres &&
+                   drm_mode->vdisplay == var->yres &&
+                   drm_mode->clock != 0)
+                   break;
+       }
+#else
+       drm_mode = drm_mode_create(dev);
+       drm_mode->hdisplay = var->xres;
+       drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
+       drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len;
+       drm_mode->htotal = drm_mode->hsync_end + var->left_margin;
+       drm_mode->vdisplay = var->yres;
+       drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin;
+       drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len;
+       drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin;
+       drm_mode->clock = PICOS2KHZ(var->pixclock);
+       drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
+       drm_mode_set_name(drm_mode);
+       drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V);
+#endif
+
+       if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
+               return -EINVAL;
+
+       /* Have to destroy our created mode if we're not searching the mode
+        * list for it.
+        */
+#if 1 
+       drm_mode_destroy(dev, drm_mode);
+#endif
+
+       return 0;
+}
+
+static struct fb_ops drmfb_ops = {
+       .owner = THIS_MODULE,
+       //      .fb_open = drmfb_open,
+       //      .fb_read = drmfb_read,
+       //      .fb_write = drmfb_write,
+       //      .fb_release = drmfb_release,
+       //      .fb_ioctl = drmfb_ioctl,
+       .fb_check_var = drmfb_check_var,
+       .fb_set_par = drmfb_set_par,
+       .fb_setcolreg = drmfb_setcolreg,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+};
+
+int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
+{
+       struct fb_info *info;
+       struct drm_framebuffer *fb = crtc->fb;
+       struct drmfb_par *par;
+       struct device *device = &dev->pdev->dev; 
+       struct drm_display_mode *mode = crtc->desired_mode;
+       int ret;
+
+       info = framebuffer_alloc(sizeof(struct drmfb_par), device);
+       if (!info)
+               return -ENOMEM;
+
+       fb->fbdev = info;
+               
+       par = info->par;
+
+       par->dev = dev;
+       par->crtc = crtc;
+
+       info->fbops = &drmfb_ops;
+
+       strcpy(info->fix.id, "drmfb");
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_TRUECOLOR;
+       info->fix.accel = FB_ACCEL_NONE;
+       info->fix.type_aux = 0;
+       info->fix.mmio_start = 0;
+       info->fix.mmio_len = 0;
+       info->fix.line_length = fb->pitch;
+       info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
+       info->fix.smem_len = info->fix.line_length * fb->height;
+
+       info->flags = FBINFO_DEFAULT;
+
+       ret = drm_mem_reg_ioremap(dev, &fb->bo->mem, &fb->virtual_base);
+       if (ret)
+               DRM_ERROR("error mapping fb: %d\n", ret);
+
+       info->screen_base = fb->virtual_base;
+       info->screen_size = info->fix.smem_len; /* ??? */
+       info->pseudo_palette = fb->pseudo_palette;
+       info->var.xres_virtual = fb->width;
+       info->var.yres_virtual = fb->height;
+       info->var.bits_per_pixel = fb->bits_per_pixel;
+       info->var.xoffset = 0;
+       info->var.yoffset = 0;
+       info->var.activate = FB_ACTIVATE_NOW;
+       info->var.height = -1;
+       info->var.width = -1;
+       info->var.vmode = FB_VMODE_NONINTERLACED;
+
+       info->var.xres = mode->hdisplay;
+       info->var.right_margin = mode->hsync_start - mode->hdisplay;
+       info->var.hsync_len = mode->hsync_end - mode->hsync_start;
+       info->var.left_margin = mode->htotal - mode->hsync_end;
+       info->var.yres = mode->vdisplay;
+       info->var.lower_margin = mode->vsync_start - mode->vdisplay;
+       info->var.vsync_len = mode->vsync_end - mode->vsync_start;
+       info->var.upper_margin = mode->vtotal - mode->vsync_end;
+       info->var.pixclock = 10000000 / mode->htotal * 1000 /
+                               mode->vtotal * 100;
+       /* avoid overflow */
+       info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
+
+       DRM_DEBUG("fb depth is %d\n", fb->depth);
+       switch(fb->depth) {
+       case 8:
+               info->var.red.offset = 0;
+               info->var.green.offset = 0;
+               info->var.blue.offset = 0;
+               info->var.red.length = 8; /* 8bit DAC */
+               info->var.green.length = 8;
+               info->var.blue.length = 8;
+               info->var.transp.offset = 0;
+               info->var.transp.length = 0;
+               break;
+       case 15:
+               info->var.red.offset = 10;
+               info->var.green.offset = 5;
+               info->var.blue.offset = 0;
+               info->var.red.length = info->var.green.length =
+                       info->var.blue.length = 5;
+               info->var.transp.offset = 15;
+               info->var.transp.length = 1;
+               break;
+       case 16:
+               info->var.red.offset = 11;
+               info->var.green.offset = 5;
+               info->var.blue.offset = 0;
+               info->var.red.length = 5;
+               info->var.green.length = 6;
+               info->var.blue.length = 5;
+               info->var.transp.offset = 0;
+               info->var.transp.length = 0;
+               break;
+       case 24:
+               info->var.red.offset = 16;
+               info->var.green.offset = 8;
+               info->var.blue.offset = 0;
+               info->var.red.length = info->var.green.length =
+                       info->var.blue.length = 8;
+               info->var.transp.offset = 0;
+               info->var.transp.length = 0;
+               break;
+       case 32:
+               info->var.red.offset = 16;
+               info->var.green.offset = 8;
+               info->var.blue.offset = 0;
+               info->var.red.length = info->var.green.length =
+                       info->var.blue.length = 8;
+               info->var.transp.offset = 24;
+               info->var.transp.length = 8;
+               break;
+       default:
+               break;
+       }
+
+       if (register_framebuffer(info) < 0) {
+               unregister_framebuffer(info);
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+              info->fix.id);
+       return 0;
+}
+EXPORT_SYMBOL(drmfb_probe);
+
+int drmfb_remove(struct drm_device *dev, struct drm_crtc *crtc)
+{
+       struct fb_info *info = fb->fbdev;
+       struct drm_framebuffer *fb = crtc->fb;
+       
+       if (info) {
+               drm_mem_reg_iounmap(dev, &fb->bo->mem, fb->virtual_base);
+               unregister_framebuffer(info);
+               framebuffer_release(info);
+       }
+       return 0;
+}
+EXPORT_SYMBOL(drmfb_remove);
+MODULE_LICENSE("GPL");
index ce161dc..e696b42 100644 (file)
  * Typically called by the IRQ handler.
  */
 
-void drm_fence_handler(drm_device_t * dev, uint32_t class,
-                      uint32_t sequence, uint32_t type)
+void drm_fence_handler(struct drm_device * dev, uint32_t fence_class,
+                      uint32_t sequence, uint32_t type, uint32_t error)
 {
        int wake = 0;
        uint32_t diff;
        uint32_t relevant;
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_class_manager_t *fc = &fm->class[class];
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_class_manager *fc = &fm->fence_class[fence_class];
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
        struct list_head *head;
-       drm_fence_object_t *fence, *next;
+       struct drm_fence_object *fence, *next;
        int found = 0;
        int is_exe = (type & DRM_FENCE_TYPE_EXE);
        int ge_last_exe;
 
+
        diff = (sequence - fc->exe_flush_sequence) & driver->sequence_mask;
 
        if (fc->pending_exe_flush && is_exe && diff < driver->wrap_diff)
@@ -57,9 +58,6 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
        diff = (sequence - fc->last_exe_flush) & driver->sequence_mask;
        ge_last_exe = diff < driver->wrap_diff;
 
-       if (ge_last_exe)
-               fc->pending_flush &= ~type;
-
        if (is_exe && ge_last_exe) {
                fc->last_exe_flush = sequence;
        }
@@ -75,36 +73,68 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
                }
        }
 
+       fc->pending_flush &= ~type;
        head = (found) ? &fence->ring : &fc->ring;
 
        list_for_each_entry_safe_reverse(fence, next, head, ring) {
                if (&fence->ring == &fc->ring)
                        break;
 
-               type |= fence->native_type;
+               if (error) {
+                       fence->error = error;
+                       fence->signaled = fence->type;
+                       fence->submitted_flush = fence->type;
+                       fence->flush_mask = fence->type;
+                       list_del_init(&fence->ring);
+                       wake = 1;
+                       break;
+               }
+
+               if (is_exe)
+                       type |= fence->native_type;
+
                relevant = type & fence->type;
 
                if ((fence->signaled | relevant) != fence->signaled) {
                        fence->signaled |= relevant;
+                       fence->flush_mask |= relevant;
+                       fence->submitted_flush |= relevant;
                        DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n",
                                  fence->base.hash.key, fence->signaled);
-                       fence->submitted_flush |= relevant;
                        wake = 1;
                }
 
                relevant = fence->flush_mask &
-                   ~(fence->signaled | fence->submitted_flush);
+                       ~(fence->submitted_flush | fence->signaled);
 
-               if (relevant) {
-                       fc->pending_flush |= relevant;
-                       fence->submitted_flush = fence->flush_mask;
-               }
+               fc->pending_flush |= relevant;
+               fence->submitted_flush |= relevant;
 
                if (!(fence->type & ~fence->signaled)) {
                        DRM_DEBUG("Fence completely signaled 0x%08lx\n",
                                  fence->base.hash.key);
                        list_del_init(&fence->ring);
                }
+
+       }
+
+       /*
+        * Reinstate lost flush flags.
+        */
+
+       if ((fc->pending_flush & type) != type) {
+               head = head->prev;
+               list_for_each_entry(fence, head, ring) {
+                       if (&fence->ring == &fc->ring)
+                               break;
+                       diff = (fc->last_exe_flush - fence->sequence) &
+                               driver->sequence_mask;
+                       if (diff > driver->wrap_diff)
+                               break;
+
+                       relevant = fence->submitted_flush & ~fence->signaled;
+                       fc->pending_flush |= relevant;
+               }
        }
 
        if (wake) {
@@ -114,9 +144,9 @@ void drm_fence_handler(drm_device_t * dev, uint32_t class,
 
 EXPORT_SYMBOL(drm_fence_handler);
 
-static void drm_fence_unring(drm_device_t * dev, struct list_head *ring)
+static void drm_fence_unring(struct drm_device * dev, struct list_head *ring)
 {
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
        unsigned long flags;
 
        write_lock_irqsave(&fm->lock, flags);
@@ -124,57 +154,83 @@ static void drm_fence_unring(drm_device_t * dev, struct list_head *ring)
        write_unlock_irqrestore(&fm->lock, flags);
 }
 
-void drm_fence_usage_deref_locked(drm_device_t * dev,
-                                 drm_fence_object_t * fence)
+void drm_fence_usage_deref_locked(struct drm_fence_object ** fence)
 {
-       drm_fence_manager_t *fm = &dev->fm;
-
-       if (atomic_dec_and_test(&fence->usage)) {
-               drm_fence_unring(dev, &fence->ring);
+       struct drm_fence_object *tmp_fence = *fence;
+       struct drm_device *dev = tmp_fence->dev;
+       struct drm_fence_manager *fm = &dev->fm;
+
+       DRM_ASSERT_LOCKED(&dev->struct_mutex);
+       *fence = NULL;
+       if (atomic_dec_and_test(&tmp_fence->usage)) {
+               drm_fence_unring(dev, &tmp_fence->ring);
                DRM_DEBUG("Destroyed a fence object 0x%08lx\n",
-                         fence->base.hash.key);
+                         tmp_fence->base.hash.key);
                atomic_dec(&fm->count);
-               drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
+               BUG_ON(!list_empty(&tmp_fence->base.list));
+               drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
        }
 }
+EXPORT_SYMBOL(drm_fence_usage_deref_locked);
 
-void drm_fence_usage_deref_unlocked(drm_device_t * dev,
-                                   drm_fence_object_t * fence)
+void drm_fence_usage_deref_unlocked(struct drm_fence_object ** fence)
 {
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_object *tmp_fence = *fence;
+       struct drm_device *dev = tmp_fence->dev;
+       struct drm_fence_manager *fm = &dev->fm;
 
-       if (atomic_dec_and_test(&fence->usage)) {
+       *fence = NULL;
+       if (atomic_dec_and_test(&tmp_fence->usage)) {
                mutex_lock(&dev->struct_mutex);
-               if (atomic_read(&fence->usage) == 0) {
-                       drm_fence_unring(dev, &fence->ring);
+               if (atomic_read(&tmp_fence->usage) == 0) {
+                       drm_fence_unring(dev, &tmp_fence->ring);
                        atomic_dec(&fm->count);
-                       drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
+                       BUG_ON(!list_empty(&tmp_fence->base.list));
+                       drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
                }
                mutex_unlock(&dev->struct_mutex);
        }
 }
+EXPORT_SYMBOL(drm_fence_usage_deref_unlocked);
 
-static void drm_fence_object_destroy(drm_file_t * priv,
-                                    drm_user_object_t * base)
+struct drm_fence_object
+*drm_fence_reference_locked(struct drm_fence_object *src)
 {
-       drm_device_t *dev = priv->head->dev;
-       drm_fence_object_t *fence =
-           drm_user_object_entry(base, drm_fence_object_t, base);
+       DRM_ASSERT_LOCKED(&src->dev->struct_mutex);
 
-       drm_fence_usage_deref_locked(dev, fence);
+       atomic_inc(&src->usage);
+       return src;
 }
 
-static int fence_signaled(drm_device_t * dev,
-                         drm_fence_object_t * fence,
-                         uint32_t mask, int poke_flush)
+void drm_fence_reference_unlocked(struct drm_fence_object **dst,
+                                 struct drm_fence_object *src)
+{
+       mutex_lock(&src->dev->struct_mutex);
+       *dst = src;
+       atomic_inc(&src->usage);
+       mutex_unlock(&src->dev->struct_mutex);
+}
+EXPORT_SYMBOL(drm_fence_reference_unlocked);
+
+static void drm_fence_object_destroy(struct drm_file *priv, struct drm_user_object * base)
+{
+       struct drm_fence_object *fence =
+           drm_user_object_entry(base, struct drm_fence_object, base);
+
+       drm_fence_usage_deref_locked(&fence);
+}
+
+int drm_fence_object_signaled(struct drm_fence_object * fence,
+                             uint32_t mask, int poke_flush)
 {
        unsigned long flags;
        int signaled;
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
+       struct drm_device *dev = fence->dev;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
 
        if (poke_flush)
-               driver->poke_flush(dev, fence->class);
+               driver->poke_flush(dev, fence->fence_class);
        read_lock_irqsave(&fm->lock, flags);
        signaled =
            (fence->type & mask & fence->signaled) == (fence->type & mask);
@@ -182,9 +238,10 @@ static int fence_signaled(drm_device_t * dev,
 
        return signaled;
 }
+EXPORT_SYMBOL(drm_fence_object_signaled);
 
-static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
-                               drm_fence_driver_t * driver, uint32_t sequence)
+static void drm_fence_flush_exe(struct drm_fence_class_manager * fc,
+                               struct drm_fence_driver * driver, uint32_t sequence)
 {
        uint32_t diff;
 
@@ -200,19 +257,13 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
        }
 }
 
-int drm_fence_object_signaled(drm_fence_object_t * fence,
-                             uint32_t type)
-{
-       return ((fence->signaled & type) == type);
-}
-
-int drm_fence_object_flush(drm_device_t * dev,
-                          drm_fence_object_t * fence,
+int drm_fence_object_flush(struct drm_fence_object * fence,
                           uint32_t type)
 {
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_class_manager_t *fc = &fm->class[fence->class];
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
+       struct drm_device *dev = fence->dev;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
        unsigned long flags;
 
        if (type & ~fence->type) {
@@ -223,7 +274,8 @@ int drm_fence_object_flush(drm_device_t * dev,
 
        write_lock_irqsave(&fm->lock, flags);
        fence->flush_mask |= type;
-       if (fence->submitted_flush == fence->signaled) {
+       if ((fence->submitted_flush & fence->signaled)
+           == fence->submitted_flush) {
                if ((fence->type & DRM_FENCE_TYPE_EXE) &&
                    !(fence->submitted_flush & DRM_FENCE_TYPE_EXE)) {
                        drm_fence_flush_exe(fc, driver, fence->sequence);
@@ -235,7 +287,7 @@ int drm_fence_object_flush(drm_device_t * dev,
                }
        }
        write_unlock_irqrestore(&fm->lock, flags);
-       driver->poke_flush(dev, fence->class);
+       driver->poke_flush(dev, fence->fence_class);
        return 0;
 }
 
@@ -244,14 +296,14 @@ int drm_fence_object_flush(drm_device_t * dev,
  * wrapped around and reused.
  */
 
-void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
+void drm_fence_flush_old(struct drm_device * dev, uint32_t fence_class, uint32_t sequence)
 {
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_class_manager_t *fc = &fm->class[class];
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_class_manager *fc = &fm->fence_class[fence_class];
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
        uint32_t old_sequence;
        unsigned long flags;
-       drm_fence_object_t *fence;
+       struct drm_fence_object *fence;
        uint32_t diff;
 
        write_lock_irqsave(&fm->lock, flags);
@@ -272,39 +324,38 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
                mutex_unlock(&dev->struct_mutex);
                return;
        }
-       fence = list_entry(fc->ring.next, drm_fence_object_t, ring);
-       atomic_inc(&fence->usage);
+       fence = drm_fence_reference_locked(list_entry(fc->ring.next, struct drm_fence_object, ring));
        mutex_unlock(&dev->struct_mutex);
        diff = (old_sequence - fence->sequence) & driver->sequence_mask;
        read_unlock_irqrestore(&fm->lock, flags);
        if (diff < driver->wrap_diff) {
-               drm_fence_object_flush(dev, fence, fence->type);
+               drm_fence_object_flush(fence, fence->type);
        }
-       drm_fence_usage_deref_unlocked(dev, fence);
+       drm_fence_usage_deref_unlocked(&fence);
 }
 
 EXPORT_SYMBOL(drm_fence_flush_old);
 
-static int drm_fence_lazy_wait(drm_device_t *dev,
-                              drm_fence_object_t *fence,
+static int drm_fence_lazy_wait(struct drm_fence_object *fence,
                               int ignore_signals,
                               uint32_t mask)
 {
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_class_manager_t *fc = &fm->class[fence->class];
+       struct drm_device *dev = fence->dev;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
        int signaled;
        unsigned long _end = jiffies + 3*DRM_HZ;
        int ret = 0;
 
        do {
                DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ,
-                           (signaled = fence_signaled(dev, fence, mask, 1)));
+                           (signaled = drm_fence_object_signaled(fence, mask, 1)));
                if (signaled)
                        return 0;
                if (time_after_eq(jiffies, _end))
                        break;
        } while (ret == -EINTR && ignore_signals);
-       if (fence_signaled(dev, fence, mask, 0))
+       if (drm_fence_object_signaled(fence, mask, 0))
                return 0;
        if (time_after_eq(jiffies, _end))
                ret = -EBUSY;
@@ -312,18 +363,26 @@ static int drm_fence_lazy_wait(drm_device_t *dev,
                if (ret == -EBUSY) {
                        DRM_ERROR("Fence timeout. "
                                  "GPU lockup or fence driver was "
-                                 "taken down.\n");
+                                 "taken down. %d 0x%08x 0x%02x 0x%02x 0x%02x\n",
+                                 fence->fence_class,
+                                 fence->sequence,
+                                 fence->type,
+                                 mask,
+                                 fence->signaled);
+                       DRM_ERROR("Pending exe flush %d 0x%08x\n",
+                                 fc->pending_exe_flush,
+                                 fc->exe_flush_sequence);
                }
                return ((ret == -EINTR) ? -EAGAIN : ret);
        }
        return 0;
 }
 
-int drm_fence_object_wait(drm_device_t * dev,
-                         drm_fence_object_t * fence,
+int drm_fence_object_wait(struct drm_fence_object * fence,
                          int lazy, int ignore_signals, uint32_t mask)
 {
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
+       struct drm_device *dev = fence->dev;
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
        int ret = 0;
        unsigned long _end;
        int signaled;
@@ -331,41 +390,42 @@ int drm_fence_object_wait(drm_device_t * dev,
        if (mask & ~fence->type) {
                DRM_ERROR("Wait trying to extend fence type"
                          " 0x%08x 0x%08x\n", mask, fence->type);
+               BUG();
                return -EINVAL;
        }
 
-       if (fence_signaled(dev, fence, mask, 0))
+       if (drm_fence_object_signaled(fence, mask, 0))
                return 0;
 
        _end = jiffies + 3 * DRM_HZ;
 
-       drm_fence_object_flush(dev, fence, mask);
+       drm_fence_object_flush(fence, mask);
 
        if (lazy && driver->lazy_capable) {
 
-               ret = drm_fence_lazy_wait(dev, fence, ignore_signals, mask);
+               ret = drm_fence_lazy_wait(fence, ignore_signals, mask);
                if (ret)
                        return ret;
 
        } else {
 
-               if (driver->has_irq(dev, fence->class,
+               if (driver->has_irq(dev, fence->fence_class,
                                    DRM_FENCE_TYPE_EXE)) {
-                       ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
+                       ret = drm_fence_lazy_wait(fence, ignore_signals,
                                                  DRM_FENCE_TYPE_EXE);
                        if (ret)
                                return ret;
                }
 
-               if (driver->has_irq(dev, fence->class,
+               if (driver->has_irq(dev, fence->fence_class,
                                    mask & ~DRM_FENCE_TYPE_EXE)) {
-                       ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
+                       ret = drm_fence_lazy_wait(fence, ignore_signals,
                                                  mask);
                        if (ret)
                                return ret;
                }
        }
-       if (drm_fence_object_signaled(fence, mask))
+       if (drm_fence_object_signaled(fence, mask, 0))
                return 0;
 
        /*
@@ -377,7 +437,7 @@ int drm_fence_object_wait(drm_device_t * dev,
 #endif
        do {
                schedule();
-               signaled = fence_signaled(dev, fence, mask, 1);
+               signaled = drm_fence_object_signaled(fence, mask, 1);
        } while (!signaled && !time_after_eq(jiffies, _end));
 
        if (!signaled)
@@ -385,25 +445,28 @@ int drm_fence_object_wait(drm_device_t * dev,
 
        return 0;
 }
+EXPORT_SYMBOL(drm_fence_object_wait);
 
-int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
-                         uint32_t fence_flags, uint32_t class, uint32_t type)
+
+int drm_fence_object_emit(struct drm_fence_object * fence,
+                         uint32_t fence_flags, uint32_t fence_class, uint32_t type)
 {
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
-       drm_fence_class_manager_t *fc = &fm->class[fence->class];
+       struct drm_device *dev = fence->dev;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
+       struct drm_fence_class_manager *fc = &fm->fence_class[fence->fence_class];
        unsigned long flags;
        uint32_t sequence;
        uint32_t native_type;
        int ret;
 
        drm_fence_unring(dev, &fence->ring);
-       ret = driver->emit(dev, class, fence_flags, &sequence, &native_type);
+       ret = driver->emit(dev, fence_class, fence_flags, &sequence, &native_type);
        if (ret)
                return ret;
 
        write_lock_irqsave(&fm->lock, flags);
-       fence->class = class;
+       fence->fence_class = fence_class;
        fence->type = type;
        fence->flush_mask = 0x00;
        fence->submitted_flush = 0x00;
@@ -416,15 +479,16 @@ int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
        write_unlock_irqrestore(&fm->lock, flags);
        return 0;
 }
+EXPORT_SYMBOL(drm_fence_object_emit);
 
-static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
+static int drm_fence_object_init(struct drm_device * dev, uint32_t fence_class,
                                 uint32_t type,
                                 uint32_t fence_flags,
-                                drm_fence_object_t * fence)
+                                struct drm_fence_object * fence)
 {
        int ret = 0;
        unsigned long flags;
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
 
        mutex_lock(&dev->struct_mutex);
        atomic_set(&fence->usage, 1);
@@ -432,52 +496,60 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
 
        write_lock_irqsave(&fm->lock, flags);
        INIT_LIST_HEAD(&fence->ring);
-       fence->class = class;
+
+       /* 
+        *  Avoid hitting BUG() for kernel-only fence objects.
+        */
+
+       INIT_LIST_HEAD(&fence->base.list);
+       fence->fence_class = fence_class;
        fence->type = type;
        fence->flush_mask = 0;
        fence->submitted_flush = 0;
        fence->signaled = 0;
        fence->sequence = 0;
+       fence->dev = dev;
        write_unlock_irqrestore(&fm->lock, flags);
        if (fence_flags & DRM_FENCE_FLAG_EMIT) {
-               ret = drm_fence_object_emit(dev, fence, fence_flags,
-                                           fence->class, type);
+               ret = drm_fence_object_emit(fence, fence_flags,
+                                           fence->fence_class, type);
        }
        return ret;
 }
 
-int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence,
+int drm_fence_add_user_object(struct drm_file * priv, struct drm_fence_object * fence,
                              int shareable)
 {
-       drm_device_t *dev = priv->head->dev;
+       struct drm_device *dev = priv->head->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
        ret = drm_add_user_object(priv, &fence->base, shareable);
-       mutex_unlock(&dev->struct_mutex);
        if (ret)
-               return ret;
+               goto out;
+       atomic_inc(&fence->usage);
        fence->base.type = drm_fence_type;
        fence->base.remove = &drm_fence_object_destroy;
        DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key);
-       return 0;
+out:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
 }
-
 EXPORT_SYMBOL(drm_fence_add_user_object);
 
-int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
-                           unsigned flags, drm_fence_object_t ** c_fence)
+int drm_fence_object_create(struct drm_device * dev, uint32_t fence_class, uint32_t type,
+                           unsigned flags, struct drm_fence_object ** c_fence)
 {
-       drm_fence_object_t *fence;
+       struct drm_fence_object *fence;
        int ret;
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
 
-       fence = drm_ctl_alloc(sizeof(*fence), DRM_MEM_FENCE);
+       fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
        if (!fence)
                return -ENOMEM;
-       ret = drm_fence_object_init(dev, class, type, flags, fence);
+       ret = drm_fence_object_init(dev, fence_class, type, flags, fence);
        if (ret) {
-               drm_fence_usage_deref_unlocked(dev, fence);
+               drm_fence_usage_deref_unlocked(&fence);
                return ret;
        }
        *c_fence = fence;
@@ -488,15 +560,16 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
 
 EXPORT_SYMBOL(drm_fence_object_create);
 
-void drm_fence_manager_init(drm_device_t * dev)
+void drm_fence_manager_init(struct drm_device * dev)
 {
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_class_manager_t *class;
-       drm_fence_driver_t *fed = dev->driver->fence_driver;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_class_manager *fence_class;
+       struct drm_fence_driver *fed = dev->driver->fence_driver;
        int i;
+       unsigned long flags;
 
        rwlock_init(&fm->lock);
-       write_lock(&fm->lock);
+       write_lock_irqsave(&fm->lock, flags);
        fm->initialized = 0;
        if (!fed)
            goto out_unlock;
@@ -506,27 +579,45 @@ void drm_fence_manager_init(drm_device_t * dev)
        BUG_ON(fm->num_classes > _DRM_FENCE_CLASSES);
 
        for (i=0; i<fm->num_classes; ++i) {
-           class = &fm->class[i];
+           fence_class = &fm->fence_class[i];
 
-           INIT_LIST_HEAD(&class->ring);
-           class->pending_flush = 0;
-           DRM_INIT_WAITQUEUE(&class->fence_queue);
+           INIT_LIST_HEAD(&fence_class->ring);
+           fence_class->pending_flush = 0;
+           DRM_INIT_WAITQUEUE(&fence_class->fence_queue);
        }
 
        atomic_set(&fm->count, 0);
  out_unlock:
-       write_unlock(&fm->lock);
+       write_unlock_irqrestore(&fm->lock, flags);
 }
 
-void drm_fence_manager_takedown(drm_device_t * dev)
+void drm_fence_fill_arg(struct drm_fence_object *fence, struct drm_fence_arg *arg)
 {
+       struct drm_device *dev = fence->dev;
+       struct drm_fence_manager *fm = &dev->fm;
+       unsigned long irq_flags;
+
+       read_lock_irqsave(&fm->lock, irq_flags);
+       arg->handle = fence->base.hash.key;
+       arg->fence_class = fence->fence_class;
+       arg->type = fence->type;
+       arg->signaled = fence->signaled;
+       arg->error = fence->error;
+       arg->sequence = fence->sequence;
+       read_unlock_irqrestore(&fm->lock, irq_flags);
 }
+EXPORT_SYMBOL(drm_fence_fill_arg);
 
-drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle)
+
+void drm_fence_manager_takedown(struct drm_device * dev)
+{
+}
+
+struct drm_fence_object *drm_lookup_fence_object(struct drm_file * priv, uint32_t handle)
 {
-       drm_device_t *dev = priv->head->dev;
-       drm_user_object_t *uo;
-       drm_fence_object_t *fence;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_user_object *uo;
+       struct drm_fence_object *fence;
 
        mutex_lock(&dev->struct_mutex);
        uo = drm_lookup_user_object(priv, handle);
@@ -534,21 +625,17 @@ drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle)
                mutex_unlock(&dev->struct_mutex);
                return NULL;
        }
-       fence = drm_user_object_entry(uo, drm_fence_object_t, base);
-       atomic_inc(&fence->usage);
+       fence = drm_fence_reference_locked(drm_user_object_entry(uo, struct drm_fence_object, base));
        mutex_unlock(&dev->struct_mutex);
        return fence;
 }
 
-int drm_fence_ioctl(DRM_IOCTL_ARGS)
+int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        int ret;
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_arg_t arg;
-       drm_fence_object_t *fence;
-       drm_user_object_t *uo;
-       unsigned long flags;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       struct drm_fence_object *fence;
        ret = 0;
 
        if (!fm->initialized) {
@@ -556,106 +643,209 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
                return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg));
-       switch (arg.op) {
-       case drm_fence_create:
-               if (arg.flags & DRM_FENCE_FLAG_EMIT)
-                       LOCK_TEST_WITH_RETURN(dev, filp);
-               ret = drm_fence_object_create(dev, arg.class,
-                                             arg.type, arg.flags, &fence);
-               if (ret)
-                       return ret;
-               ret = drm_fence_add_user_object(priv, fence,
-                                               arg.flags &
-                                               DRM_FENCE_FLAG_SHAREABLE);
-               if (ret) {
-                       drm_fence_usage_deref_unlocked(dev, fence);
-                       return ret;
-               }
+       if (arg->flags & DRM_FENCE_FLAG_EMIT)
+               LOCK_TEST_WITH_RETURN(dev, file_priv);
+       ret = drm_fence_object_create(dev, arg->fence_class,
+                                     arg->type, arg->flags, &fence);
+       if (ret)
+               return ret;
+       ret = drm_fence_add_user_object(file_priv, fence,
+                                       arg->flags &
+                                       DRM_FENCE_FLAG_SHAREABLE);
+       if (ret) {
+               drm_fence_usage_deref_unlocked(&fence);
+               return ret;
+       }
+       
+       /*
+        * usage > 0. No need to lock dev->struct_mutex;
+        */
 
-               /*
-                * usage > 0. No need to lock dev->struct_mutex;
-                */
+       arg->handle = fence->base.hash.key;
 
-               atomic_inc(&fence->usage);
-               arg.handle = fence->base.hash.key;
-               break;
-       case drm_fence_destroy:
-               mutex_lock(&dev->struct_mutex);
-               uo = drm_lookup_user_object(priv, arg.handle);
-               if (!uo || (uo->type != drm_fence_type) || uo->owner != priv) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return -EINVAL;
-               }
-               ret = drm_remove_user_object(priv, uo);
-               mutex_unlock(&dev->struct_mutex);
+
+       drm_fence_fill_arg(fence, arg);
+       drm_fence_usage_deref_unlocked(&fence);
+
+       return ret;
+}
+
+int drm_fence_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       int ret;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       struct drm_fence_object *fence;
+       struct drm_user_object *uo;
+       ret = 0;
+
+       if (!fm->initialized) {
+               DRM_ERROR("The DRM driver does not support fencing.\n");
+               return -EINVAL;
+       }
+
+       ret = drm_user_object_ref(file_priv, arg->handle, drm_fence_type, &uo);
+       if (ret)
                return ret;
-       case drm_fence_reference:
-               ret =
-                   drm_user_object_ref(priv, arg.handle, drm_fence_type, &uo);
-               if (ret)
-                       return ret;
-               fence = drm_lookup_fence_object(priv, arg.handle);
-               break;
-       case drm_fence_unreference:
-               ret = drm_user_object_unref(priv, arg.handle, drm_fence_type);
+       fence = drm_lookup_fence_object(file_priv, arg->handle);
+       drm_fence_fill_arg(fence, arg);
+       drm_fence_usage_deref_unlocked(&fence);
+
+       return ret;
+}
+
+
+int drm_fence_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       int ret;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       ret = 0;
+
+       if (!fm->initialized) {
+               DRM_ERROR("The DRM driver does not support fencing.\n");
+               return -EINVAL;
+       }
+
+       return drm_user_object_unref(file_priv, arg->handle, drm_fence_type);
+}
+
+int drm_fence_signaled_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       int ret;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       struct drm_fence_object *fence;
+       ret = 0;
+
+       if (!fm->initialized) {
+               DRM_ERROR("The DRM driver does not support fencing.\n");
+               return -EINVAL;
+       }
+
+       fence = drm_lookup_fence_object(file_priv, arg->handle);
+       if (!fence)
+               return -EINVAL;
+
+       drm_fence_fill_arg(fence, arg);
+       drm_fence_usage_deref_unlocked(&fence);
+
+       return ret;
+}
+
+int drm_fence_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       int ret;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       struct drm_fence_object *fence;
+       ret = 0;
+
+       if (!fm->initialized) {
+               DRM_ERROR("The DRM driver does not support fencing.\n");
+               return -EINVAL;
+       }
+
+       fence = drm_lookup_fence_object(file_priv, arg->handle);
+       if (!fence)
+               return -EINVAL;
+       ret = drm_fence_object_flush(fence, arg->type);
+
+       drm_fence_fill_arg(fence, arg);
+       drm_fence_usage_deref_unlocked(&fence);
+
+       return ret;
+}
+
+
+int drm_fence_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       int ret;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       struct drm_fence_object *fence;
+       ret = 0;
+
+       if (!fm->initialized) {
+               DRM_ERROR("The DRM driver does not support fencing.\n");
+               return -EINVAL;
+       }
+
+       fence = drm_lookup_fence_object(file_priv, arg->handle);
+       if (!fence)
+               return -EINVAL;
+       ret = drm_fence_object_wait(fence,
+                                   arg->flags & DRM_FENCE_FLAG_WAIT_LAZY,
+                                   0, arg->type);
+
+       drm_fence_fill_arg(fence, arg);
+       drm_fence_usage_deref_unlocked(&fence);
+
+       return ret;
+}
+
+
+int drm_fence_emit_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       int ret;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       struct drm_fence_object *fence;
+       ret = 0;
+
+       if (!fm->initialized) {
+               DRM_ERROR("The DRM driver does not support fencing.\n");
+               return -EINVAL;
+       }
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+       fence = drm_lookup_fence_object(file_priv, arg->handle);
+       if (!fence)
+               return -EINVAL;
+       ret = drm_fence_object_emit(fence, arg->flags, arg->fence_class,
+                                   arg->type);
+
+       drm_fence_fill_arg(fence, arg);
+       drm_fence_usage_deref_unlocked(&fence);
+
+       return ret;
+}
+
+int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       int ret;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_arg *arg = data;
+       struct drm_fence_object *fence;
+       ret = 0;
+
+       if (!fm->initialized) {
+               DRM_ERROR("The DRM driver does not support fencing.\n");
+               return -EINVAL;
+       }
+
+       if (!dev->bm.initialized) {
+               DRM_ERROR("Buffer object manager is not initialized\n");
+               return -EINVAL;
+       }
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+       ret = drm_fence_buffer_objects(dev, NULL, arg->flags,
+                                      NULL, &fence);
+       if (ret)
                return ret;
-       case drm_fence_signaled:
-               fence = drm_lookup_fence_object(priv, arg.handle);
-               if (!fence)
-                       return -EINVAL;
-               break;
-       case drm_fence_flush:
-               fence = drm_lookup_fence_object(priv, arg.handle);
-               if (!fence)
-                       return -EINVAL;
-               ret = drm_fence_object_flush(dev, fence, arg.type);
-               break;
-       case drm_fence_wait:
-               fence = drm_lookup_fence_object(priv, arg.handle);
-               if (!fence)
-                       return -EINVAL;
-               ret =
-                   drm_fence_object_wait(dev, fence,
-                                         arg.flags & DRM_FENCE_FLAG_WAIT_LAZY,
-                                         0, arg.type);
-               break;
-       case drm_fence_emit:
-               LOCK_TEST_WITH_RETURN(dev, filp);
-               fence = drm_lookup_fence_object(priv, arg.handle);
-               if (!fence)
-                       return -EINVAL;
-               ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class,
-                                           arg.type);
-               break;
-       case drm_fence_buffers:
-               if (!dev->bm.initialized) {
-                       DRM_ERROR("Buffer object manager is not initialized\n");
-                       return -EINVAL;
-               }
-               LOCK_TEST_WITH_RETURN(dev, filp);
-               ret = drm_fence_buffer_objects(priv, NULL, arg.flags,
-                                              NULL, &fence);
-               if (ret)
-                       return ret;
-               ret = drm_fence_add_user_object(priv, fence,
-                                               arg.flags &
+
+       if (!(arg->flags & DRM_FENCE_FLAG_NO_USER)) {
+               ret = drm_fence_add_user_object(file_priv, fence,
+                                               arg->flags &
                                                DRM_FENCE_FLAG_SHAREABLE);
                if (ret)
                        return ret;
-               atomic_inc(&fence->usage);
-               arg.handle = fence->base.hash.key;
-               break;
-       default:
-               return -EINVAL;
        }
-       read_lock_irqsave(&fm->lock, flags);
-       arg.class = fence->class;
-       arg.type = fence->type;
-       arg.signaled = fence->signaled;
-       read_unlock_irqrestore(&fm->lock, flags);
-       drm_fence_usage_deref_unlocked(dev, fence);
 
-       DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
+       arg->handle = fence->base.hash.key;
+
+       drm_fence_fill_arg(fence, arg);
+       drm_fence_usage_deref_unlocked(&fence);
+
        return ret;
 }
index e54d507..a622261 100644 (file)
@@ -39,9 +39,9 @@
 #include <linux/poll.h>
 
 static int drm_open_helper(struct inode *inode, struct file *filp,
-                          drm_device_t * dev);
+                          struct drm_device * dev);
 
-static int drm_setup(drm_device_t * dev)
+static int drm_setup(struct drm_device * dev)
 {
        drm_local_map_t *map;
        int i;
@@ -128,7 +128,7 @@ static int drm_setup(drm_device_t * dev)
  */
 int drm_open(struct inode *inode, struct file *filp)
 {
-       drm_device_t *dev = NULL;
+       struct drm_device *dev = NULL;
        int minor = iminor(inode);
        int retcode = 0;
 
@@ -176,7 +176,7 @@ EXPORT_SYMBOL(drm_open);
  */
 int drm_stub_open(struct inode *inode, struct file *filp)
 {
-       drm_device_t *dev = NULL;
+       struct drm_device *dev = NULL;
        int minor = iminor(inode);
        int err = -ENODEV;
        const struct file_operations *old_fops;
@@ -232,10 +232,10 @@ static int drm_cpu_valid(void)
  * filp and add it into the double linked list in \p dev.
  */
 static int drm_open_helper(struct inode *inode, struct file *filp,
-                          drm_device_t * dev)
+                          struct drm_device * dev)
 {
        int minor = iminor(inode);
-       drm_file_t *priv;
+       struct drm_file *priv;
        int ret;
        int i,j;
 
@@ -252,6 +252,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 
        memset(priv, 0, sizeof(*priv));
        filp->private_data = priv;
+       priv->filp = filp;
        priv->uid = current->euid;
        priv->pid = current->pid;
        priv->minor = minor;
@@ -262,8 +263,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        priv->lock_count = 0;
 
        INIT_LIST_HEAD(&priv->lhead);
-       INIT_LIST_HEAD(&priv->user_objects);
        INIT_LIST_HEAD(&priv->refd_objects);
+       INIT_LIST_HEAD(&priv->fbs);
 
        for (i=0; i<_DRM_NO_REF_TYPES; ++i) {
                ret = drm_ht_create(&priv->refd_object_hash[i], DRM_FILE_HASH_ORDER);
@@ -320,8 +321,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 /** No-op. */
 int drm_fasync(int fd, struct file *filp, int on)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->head->dev;
        int retcode;
 
        DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
@@ -335,10 +336,9 @@ EXPORT_SYMBOL(drm_fasync);
 
 static void drm_object_release(struct file *filp) {
 
-        drm_file_t *priv = filp->private_data;
+       struct drm_file *priv = filp->private_data;
        struct list_head *head;
-       drm_user_object_t *user_object;
-       drm_ref_object_t *ref_object;
+       struct drm_ref_object *ref_object;
        int i;
 
        /*
@@ -351,22 +351,11 @@ static void drm_object_release(struct file *filp) {
 
        head = &priv->refd_objects;
        while (head->next != head) {
-               ref_object = list_entry(head->next, drm_ref_object_t, list);
+               ref_object = list_entry(head->next, struct drm_ref_object, list);
                drm_remove_ref_object(priv, ref_object);
                head = &priv->refd_objects;
        }
 
-       /*
-        * Free leftover user objects created by me.
-        */
-
-       head = &priv->user_objects;
-       while (head->next != head) {
-               user_object = list_entry(head->next, drm_user_object_t, list);
-               drm_remove_user_object(priv, user_object);
-               head = &priv->user_objects;
-       }
-
        for(i=0; i<_DRM_NO_REF_TYPES; ++i) {
                drm_ht_remove(&priv->refd_object_hash[i]);
        }
@@ -376,7 +365,7 @@ static void drm_object_release(struct file *filp) {
  * Release file.
  *
  * \param inode device inode
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \return zero on success or a negative number on failure.
  *
  * If the hardware lock is held then free it, and take it again for the kernel
@@ -386,29 +375,28 @@ static void drm_object_release(struct file *filp) {
  */
 int drm_release(struct inode *inode, struct file *filp)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev;
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->head->dev;
        int retcode = 0;
 
        lock_kernel();
-       dev = priv->head->dev;
 
        DRM_DEBUG("open_count = %d\n", dev->open_count);
 
        if (dev->driver->preclose)
-               dev->driver->preclose(dev, filp);
+               dev->driver->preclose(dev, file_priv);
 
        /* ========================================================
         * Begin inline drm_release
         */
 
        DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
-                 current->pid, (long)old_encode_dev(priv->head->device),
+                 current->pid, (long)old_encode_dev(file_priv->head->device),
                  dev->open_count);
 
        if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
-               if (drm_i_have_hw_lock(filp)) {
-                       dev->driver->reclaim_buffers_locked(dev, filp);
+               if (drm_i_have_hw_lock(dev, file_priv)) {
+                       dev->driver->reclaim_buffers_locked(dev, file_priv);
                } else {
                        unsigned long _end=jiffies + 3*DRM_HZ;
                        int locked = 0;
@@ -434,7 +422,7 @@ int drm_release(struct inode *inode, struct file *filp)
                                          "\tI will go on reclaiming the buffers anyway.\n");
                        }
 
-                       dev->driver->reclaim_buffers_locked(dev, filp);
+                       dev->driver->reclaim_buffers_locked(dev, file_priv);
                        drm_idlelock_release(&dev->lock);
                }
        }
@@ -442,12 +430,12 @@ int drm_release(struct inode *inode, struct file *filp)
        if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) {
 
                drm_idlelock_take(&dev->lock);
-               dev->driver->reclaim_buffers_idlelocked(dev, filp);
+               dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
                drm_idlelock_release(&dev->lock);
 
        }
 
-       if (drm_i_have_hw_lock(filp)) {
+       if (drm_i_have_hw_lock(dev, file_priv)) {
                DRM_DEBUG("File %p released, freeing lock for context %d\n",
                          filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
 
@@ -458,7 +446,7 @@ int drm_release(struct inode *inode, struct file *filp)
 
        if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
            !dev->driver->reclaim_buffers_locked) {
-               dev->driver->reclaim_buffers(dev, filp);
+               dev->driver->reclaim_buffers(dev, file_priv);
        }
 
        drm_fasync(-1, filp, 0);
@@ -466,10 +454,10 @@ int drm_release(struct inode *inode, struct file *filp)
        mutex_lock(&dev->ctxlist_mutex);
 
        if (!list_empty(&dev->ctxlist)) {
-               drm_ctx_list_t *pos, *n;
+               struct drm_ctx_list *pos, *n;
 
                list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-                       if (pos->tag == priv &&
+                       if (pos->tag == file_priv &&
                            pos->handle != DRM_KERNEL_CONTEXT) {
                                if (dev->driver->context_dtor)
                                        dev->driver->context_dtor(dev,
@@ -486,19 +474,20 @@ int drm_release(struct inode *inode, struct file *filp)
        mutex_unlock(&dev->ctxlist_mutex);
 
        mutex_lock(&dev->struct_mutex);
+       drm_fb_release(filp);
        drm_object_release(filp);
-       if (priv->remove_auth_on_close == 1) {
-               drm_file_t *temp;
+       if (file_priv->remove_auth_on_close == 1) {
+               struct drm_file *temp;
 
                list_for_each_entry(temp, &dev->filelist, lhead)
                        temp->authenticated = 0;
        }
-       list_del(&priv->lhead);
+       list_del(&file_priv->lhead);
        mutex_unlock(&dev->struct_mutex);
 
        if (dev->driver->postclose)
-               dev->driver->postclose(dev, priv);
-       drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+               dev->driver->postclose(dev, file_priv);
+       drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES);
 
        /* ========================================================
         * End inline drm_release
index 6f17e11..a8ec846 100644 (file)
@@ -36,7 +36,7 @@
 #include "drm_hashtab.h"
 #include <linux/hash.h>
 
-int drm_ht_create(drm_open_hash_t * ht, unsigned int order)
+int drm_ht_create(struct drm_open_hash * ht, unsigned int order)
 {
        unsigned int i;
 
@@ -63,9 +63,9 @@ int drm_ht_create(drm_open_hash_t * ht, unsigned int order)
        return 0;
 }
 
-void drm_ht_verbose_list(drm_open_hash_t * ht, unsigned long key)
+void drm_ht_verbose_list(struct drm_open_hash * ht, unsigned long key)
 {
-       drm_hash_item_t *entry;
+       struct drm_hash_item *entry;
        struct hlist_head *h_list;
        struct hlist_node *list;
        unsigned int hashed_key;
@@ -75,15 +75,15 @@ void drm_ht_verbose_list(drm_open_hash_t * ht, unsigned long key)
        DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
        h_list = &ht->table[hashed_key];
        hlist_for_each(list, h_list) {
-               entry = hlist_entry(list, drm_hash_item_t, head);
+               entry = hlist_entry(list, struct drm_hash_item, head);
                DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
        }
 }
 
-static struct hlist_node *drm_ht_find_key(drm_open_hash_t * ht,
+static struct hlist_node *drm_ht_find_key(struct drm_open_hash * ht,
                                          unsigned long key)
 {
-       drm_hash_item_t *entry;
+       struct drm_hash_item *entry;
        struct hlist_head *h_list;
        struct hlist_node *list;
        unsigned int hashed_key;
@@ -91,7 +91,7 @@ static struct hlist_node *drm_ht_find_key(drm_open_hash_t * ht,
        hashed_key = hash_long(key, ht->order);
        h_list = &ht->table[hashed_key];
        hlist_for_each(list, h_list) {
-               entry = hlist_entry(list, drm_hash_item_t, head);
+               entry = hlist_entry(list, struct drm_hash_item, head);
                if (entry->key == key)
                        return list;
                if (entry->key > key)
@@ -100,9 +100,9 @@ static struct hlist_node *drm_ht_find_key(drm_open_hash_t * ht,
        return NULL;
 }
 
-int drm_ht_insert_item(drm_open_hash_t * ht, drm_hash_item_t * item)
+int drm_ht_insert_item(struct drm_open_hash * ht, struct drm_hash_item * item)
 {
-       drm_hash_item_t *entry;
+       struct drm_hash_item *entry;
        struct hlist_head *h_list;
        struct hlist_node *list, *parent;
        unsigned int hashed_key;
@@ -112,7 +112,7 @@ int drm_ht_insert_item(drm_open_hash_t * ht, drm_hash_item_t * item)
        h_list = &ht->table[hashed_key];
        parent = NULL;
        hlist_for_each(list, h_list) {
-               entry = hlist_entry(list, drm_hash_item_t, head);
+               entry = hlist_entry(list, struct drm_hash_item, head);
                if (entry->key == key)
                        return -EINVAL;
                if (entry->key > key)
@@ -131,7 +131,7 @@ int drm_ht_insert_item(drm_open_hash_t * ht, drm_hash_item_t * item)
  * Just insert an item and return any "bits" bit key that hasn't been 
  * used before.
  */
-int drm_ht_just_insert_please(drm_open_hash_t * ht, drm_hash_item_t * item,
+int drm_ht_just_insert_please(struct drm_open_hash * ht, struct drm_hash_item * item,
                              unsigned long seed, int bits, int shift,
                              unsigned long add)
 {
@@ -155,8 +155,8 @@ int drm_ht_just_insert_please(drm_open_hash_t * ht, drm_hash_item_t * item,
        return 0;
 }
 
-int drm_ht_find_item(drm_open_hash_t * ht, unsigned long key,
-                    drm_hash_item_t ** item)
+int drm_ht_find_item(struct drm_open_hash * ht, unsigned long key,
+                    struct drm_hash_item ** item)
 {
        struct hlist_node *list;
 
@@ -164,11 +164,11 @@ int drm_ht_find_item(drm_open_hash_t * ht, unsigned long key,
        if (!list)
                return -EINVAL;
 
-       *item = hlist_entry(list, drm_hash_item_t, head);
+       *item = hlist_entry(list, struct drm_hash_item, head);
        return 0;
 }
 
-int drm_ht_remove_key(drm_open_hash_t * ht, unsigned long key)
+int drm_ht_remove_key(struct drm_open_hash * ht, unsigned long key)
 {
        struct hlist_node *list;
 
@@ -181,14 +181,14 @@ int drm_ht_remove_key(drm_open_hash_t * ht, unsigned long key)
        return -EINVAL;
 }
 
-int drm_ht_remove_item(drm_open_hash_t * ht, drm_hash_item_t * item)
+int drm_ht_remove_item(struct drm_open_hash * ht, struct drm_hash_item * item)
 {
        hlist_del_init(&item->head);
        ht->fill--;
        return 0;
 }
 
-void drm_ht_remove(drm_open_hash_t * ht)
+void drm_ht_remove(struct drm_open_hash * ht)
 {
        if (ht->table) {
                if (ht->use_vmalloc)
index 613091c..0f13767 100644 (file)
 
 #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
 
-typedef struct drm_hash_item{
+struct drm_hash_item {
        struct hlist_node head;
        unsigned long key;
-} drm_hash_item_t;
+};
 
-typedef struct drm_open_hash{
+struct drm_open_hash {
        unsigned int size;
        unsigned int order;
        unsigned int fill;
        struct hlist_head *table;
        int use_vmalloc;
-} drm_open_hash_t;
+};
 
 
-extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order);
-extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item,
+extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
+extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
                                     unsigned long seed, int bits, int shift,
                                     unsigned long add);
-extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item);
+extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
 
-extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key);
-extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item);
-extern void drm_ht_remove(drm_open_hash_t *ht);
+extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern void drm_ht_remove(struct drm_open_hash *ht);
 
 
 #endif
index c112e81..0188154 100644 (file)
@@ -28,7 +28,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm_core.h"
@@ -83,7 +82,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
                              unsigned long arg)
 {
        drm_version32_t v32;
-       drm_version_t __user *version;
+       struct drm_version __user *version;
        int err;
 
        if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
@@ -130,7 +129,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
                                unsigned long arg)
 {
        drm_unique32_t uq32;
-       drm_unique_t __user *u;
+       struct drm_unique __user *u;
        int err;
 
        if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
@@ -160,7 +159,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
                                unsigned long arg)
 {
        drm_unique32_t uq32;
-       drm_unique_t __user *u;
+       struct drm_unique __user *u;
 
        if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
                return -EFAULT;
@@ -180,8 +179,8 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd,
 typedef struct drm_map32 {
        u32 offset;             /**< Requested physical address (0 for SAREA)*/
        u32 size;               /**< Requested physical size (bytes) */
-       drm_map_type_t type;    /**< Type of memory to map */
-       drm_map_flags_t flags;  /**< Flags */
+       enum drm_map_type type; /**< Type of memory to map */
+       enum drm_map_flags flags;       /**< Flags */
        u32 handle;             /**< User-space: "Handle" to pass to mmap() */
        int mtrr;               /**< MTRR slot used */
 } drm_map32_t;
@@ -191,7 +190,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd,
 {
        drm_map32_t __user *argp = (void __user *)arg;
        drm_map32_t m32;
-       drm_map_t __user *map;
+       struct drm_map __user *map;
        int idx, err;
        void *handle;
 
@@ -229,7 +228,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
 {
        drm_map32_t __user *argp = (void __user *)arg;
        drm_map32_t m32;
-       drm_map_t __user *map;
+       struct drm_map __user *map;
        int err;
        void *handle;
 
@@ -271,7 +270,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd,
                            unsigned long arg)
 {
        drm_map32_t __user *argp = (void __user *)arg;
-       drm_map_t __user *map;
+       struct drm_map __user *map;
        u32 handle;
 
        if (get_user(handle, &argp->handle))
@@ -301,7 +300,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
 {
        drm_client32_t c32;
        drm_client32_t __user *argp = (void __user *)arg;
-       drm_client_t __user *client;
+       struct drm_client __user *client;
        int idx, err;
 
        if (get_user(idx, &argp->idx))
@@ -334,7 +333,7 @@ typedef struct drm_stats32 {
        u32 count;
        struct {
                u32 value;
-               drm_stat_type_t type;
+               enum drm_stat_type type;
        } data[15];
 } drm_stats32_t;
 
@@ -343,7 +342,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
 {
        drm_stats32_t s32;
        drm_stats32_t __user *argp = (void __user *)arg;
-       drm_stats_t __user *stats;
+       struct drm_stats __user *stats;
        int i, err;
 
        stats = compat_alloc_user_space(sizeof(*stats));
@@ -380,7 +379,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd,
                              unsigned long arg)
 {
        drm_buf_desc32_t __user *argp = (void __user *)arg;
-       drm_buf_desc_t __user *buf;
+       struct drm_buf_desc __user *buf;
        int err;
        unsigned long agp_start;
 
@@ -412,7 +411,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd,
 {
        drm_buf_desc32_t b32;
        drm_buf_desc32_t __user *argp = (void __user *)arg;
-       drm_buf_desc_t __user *buf;
+       struct drm_buf_desc __user *buf;
 
        if (copy_from_user(&b32, argp, sizeof(b32)))
                return -EFAULT;
@@ -441,8 +440,8 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
        drm_buf_info32_t req32;
        drm_buf_info32_t __user *argp = (void __user *)arg;
        drm_buf_desc32_t __user *to;
-       drm_buf_info_t __user *request;
-       drm_buf_desc_t __user *list;
+       struct drm_buf_info __user *request;
+       struct drm_buf_desc __user *list;
        size_t nbytes;
        int i, err;
        int count, actual;
@@ -458,11 +457,11 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
            && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
                return -EFAULT;
 
-       nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t);
+       nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
        request = compat_alloc_user_space(nbytes);
        if (!access_ok(VERIFY_WRITE, request, nbytes))
                return -EFAULT;
-       list = (drm_buf_desc_t *) (request + 1);
+       list = (struct drm_buf_desc *) (request + 1);
 
        if (__put_user(count, &request->count)
            || __put_user(list, &request->list))
@@ -478,7 +477,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd,
        if (count >= actual)
                for (i = 0; i < actual; ++i)
                        if (__copy_in_user(&to[i], &list[i],
-                                          offsetof(drm_buf_desc_t, flags)))
+                                          offsetof(struct drm_buf_desc, flags)))
                                return -EFAULT;
 
        if (__put_user(actual, &argp->count))
@@ -506,8 +505,8 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
        drm_buf_map32_t __user *argp = (void __user *)arg;
        drm_buf_map32_t req32;
        drm_buf_pub32_t __user *list32;
-       drm_buf_map_t __user *request;
-       drm_buf_pub_t __user *list;
+       struct drm_buf_map __user *request;
+       struct drm_buf_pub __user *list;
        int i, err;
        int count, actual;
        size_t nbytes;
@@ -520,11 +519,11 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
 
        if (count < 0)
                return -EINVAL;
-       nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t);
+       nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
        request = compat_alloc_user_space(nbytes);
        if (!access_ok(VERIFY_WRITE, request, nbytes))
                return -EFAULT;
-       list = (drm_buf_pub_t *) (request + 1);
+       list = (struct drm_buf_pub *) (request + 1);
 
        if (__put_user(count, &request->count)
            || __put_user(list, &request->list))
@@ -540,7 +539,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
        if (count >= actual)
                for (i = 0; i < actual; ++i)
                        if (__copy_in_user(&list32[i], &list[i],
-                                          offsetof(drm_buf_pub_t, address))
+                                          offsetof(struct drm_buf_pub, address))
                            || __get_user(addr, &list[i].address)
                            || __put_user((unsigned long)addr,
                                          &list32[i].address))
@@ -563,7 +562,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd,
                               unsigned long arg)
 {
        drm_buf_free32_t req32;
-       drm_buf_free_t __user *request;
+       struct drm_buf_free __user *request;
        drm_buf_free32_t __user *argp = (void __user *)arg;
 
        if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -590,7 +589,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
                                  unsigned long arg)
 {
        drm_ctx_priv_map32_t req32;
-       drm_ctx_priv_map_t __user *request;
+       struct drm_ctx_priv_map __user *request;
        drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
 
        if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -611,7 +610,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
 static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
                                  unsigned long arg)
 {
-       drm_ctx_priv_map_t __user *request;
+       struct drm_ctx_priv_map __user *request;
        drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
        int err;
        unsigned int ctx_id;
@@ -649,7 +648,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
 {
        drm_ctx_res32_t __user *argp = (void __user *)arg;
        drm_ctx_res32_t res32;
-       drm_ctx_res_t __user *res;
+       struct drm_ctx_res __user *res;
        int err;
 
        if (copy_from_user(&res32, argp, sizeof(res32)))
@@ -659,7 +658,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd,
        if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
                return -EFAULT;
        if (__put_user(res32.count, &res->count)
-           || __put_user((drm_ctx_t __user *)(unsigned long)res32.contexts,
+           || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
                          &res->contexts))
                return -EFAULT;
 
@@ -680,7 +679,7 @@ typedef struct drm_dma32 {
        int send_count;           /**< Number of buffers to send */
        u32 send_indices;         /**< List of handles to buffers */
        u32 send_sizes;           /**< Lengths of data to send */
-       drm_dma_flags_t flags;    /**< Flags */
+       enum drm_dma_flags flags;                 /**< Flags */
        int request_count;        /**< Number of buffers requested */
        int request_size;         /**< Desired size for buffers */
        u32 request_indices;      /**< Buffer information */
@@ -693,7 +692,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd,
 {
        drm_dma32_t d32;
        drm_dma32_t __user *argp = (void __user *)arg;
-       drm_dma_t __user *d;
+       struct drm_dma __user *d;
        int err;
 
        if (copy_from_user(&d32, argp, sizeof(d32)))
@@ -741,7 +740,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
 {
        drm_agp_mode32_t __user *argp = (void __user *)arg;
        drm_agp_mode32_t m32;
-       drm_agp_mode_t __user *mode;
+       struct drm_agp_mode __user *mode;
 
        if (get_user(m32.mode, &argp->mode))
                return -EFAULT;
@@ -773,7 +772,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd,
 {
        drm_agp_info32_t __user *argp = (void __user *)arg;
        drm_agp_info32_t i32;
-       drm_agp_info_t __user *info;
+       struct drm_agp_info __user *info;
        int err;
 
        info = compat_alloc_user_space(sizeof(*info));
@@ -814,7 +813,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
 {
        drm_agp_buffer32_t __user *argp = (void __user *)arg;
        drm_agp_buffer32_t req32;
-       drm_agp_buffer_t __user *request;
+       struct drm_agp_buffer __user *request;
        int err;
 
        if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -846,7 +845,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd,
                               unsigned long arg)
 {
        drm_agp_buffer32_t __user *argp = (void __user *)arg;
-       drm_agp_buffer_t __user *request;
+       struct drm_agp_buffer __user *request;
        u32 handle;
 
        request = compat_alloc_user_space(sizeof(*request));
@@ -869,7 +868,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
 {
        drm_agp_binding32_t __user *argp = (void __user *)arg;
        drm_agp_binding32_t req32;
-       drm_agp_binding_t __user *request;
+       struct drm_agp_binding __user *request;
 
        if (copy_from_user(&req32, argp, sizeof(req32)))
                return -EFAULT;
@@ -888,7 +887,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
                                 unsigned long arg)
 {
        drm_agp_binding32_t __user *argp = (void __user *)arg;
-       drm_agp_binding_t __user *request;
+       struct drm_agp_binding __user *request;
        u32 handle;
 
        request = compat_alloc_user_space(sizeof(*request));
@@ -911,7 +910,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
                               unsigned long arg)
 {
        drm_scatter_gather32_t __user *argp = (void __user *)arg;
-       drm_scatter_gather_t __user *request;
+       struct drm_scatter_gather __user *request;
        int err;
        unsigned long x;
 
@@ -939,7 +938,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
                              unsigned long arg)
 {
        drm_scatter_gather32_t __user *argp = (void __user *)arg;
-       drm_scatter_gather_t __user *request;
+       struct drm_scatter_gather __user *request;
        unsigned long x;
 
        request = compat_alloc_user_space(sizeof(*request));
@@ -954,13 +953,13 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
 }
 
 struct drm_wait_vblank_request32 {
-       drm_vblank_seq_type_t type;
+       enum drm_vblank_seq_type type;
        unsigned int sequence;
        u32 signal;
 };
 
 struct drm_wait_vblank_reply32 {
-       drm_vblank_seq_type_t type;
+       enum drm_vblank_seq_type type;
        unsigned int sequence;
        s32 tval_sec;
        s32 tval_usec;
@@ -976,7 +975,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
 {
        drm_wait_vblank32_t __user *argp = (void __user *)arg;
        drm_wait_vblank32_t req32;
-       drm_wait_vblank_t __user *request;
+       union drm_wait_vblank __user *request;
        int err;
 
        if (copy_from_user(&req32, argp, sizeof(req32)))
@@ -1041,7 +1040,7 @@ drm_ioctl_compat_t *drm_compat_ioctls[] = {
  * Called whenever a 32-bit process running under a 64-bit kernel
  * performs an ioctl on /dev/drm.
  *
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument.
  * \return zero on success or negative number on failure.
@@ -1052,8 +1051,13 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        drm_ioctl_compat_t *fn;
        int ret;
 
+
+       /* Assume that ioctls without an explicit compat routine will "just
+        * work".  This may not always be a good assumption, but it's better
+        * than always failing.
+        */
        if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls))
-               return -ENOTTY;
+               return drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
 
        fn = drm_compat_ioctls[nr];
 
index 97df972..9d52fd8 100644 (file)
  * Get the bus id.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_unique structure.
  * \return zero on success or a negative number on failure.
  *
  * Copies the bus id from drm_device::unique into user space.
  */
-int drm_getunique(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int drm_getunique(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_unique_t __user *argp = (void __user *)arg;
-       drm_unique_t u;
+       struct drm_unique *u = data;
 
-       if (copy_from_user(&u, argp, sizeof(u)))
-               return -EFAULT;
-       if (u.unique_len >= dev->unique_len) {
-               if (copy_to_user(u.unique, dev->unique, dev->unique_len))
+       if (u->unique_len >= dev->unique_len) {
+               if (copy_to_user(u->unique, dev->unique, dev->unique_len))
                        return -EFAULT;
        }
-       u.unique_len = dev->unique_len;
-       if (copy_to_user(argp, &u, sizeof(u)))
-               return -EFAULT;
+       u->unique_len = dev->unique_len;
+
        return 0;
 }
 
@@ -73,7 +67,7 @@ int drm_getunique(struct inode *inode, struct file *filp,
  * Set the bus id.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_unique structure.
  * \return zero on success or a negative number on failure.
@@ -83,28 +77,23 @@ int drm_getunique(struct inode *inode, struct file *filp,
  * in interface version 1.1 and will return EBUSY when setversion has requested
  * version 1.1 or greater.
  */
-int drm_setunique(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int drm_setunique(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_unique_t u;
+       struct drm_unique *u = data;
        int domain, bus, slot, func, ret;
 
        if (dev->unique_len || dev->unique)
                return -EBUSY;
 
-       if (copy_from_user(&u, (drm_unique_t __user *) arg, sizeof(u)))
-               return -EFAULT;
-
-       if (!u.unique_len || u.unique_len > 1024)
+       if (!u->unique_len || u->unique_len > 1024)
                return -EINVAL;
 
-       dev->unique_len = u.unique_len;
-       dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
+       dev->unique_len = u->unique_len;
+       dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER);
        if (!dev->unique)
                return -ENOMEM;
-       if (copy_from_user(dev->unique, u.unique, dev->unique_len))
+       if (copy_from_user(dev->unique, u->unique, dev->unique_len))
                return -EFAULT;
 
        dev->unique[dev->unique_len] = '\0';
@@ -121,7 +110,7 @@ int drm_setunique(struct inode *inode, struct file *filp,
         */
        ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
        if (ret != 3)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        domain = bus >> 8;
        bus &= 0xff;
 
@@ -134,7 +123,7 @@ int drm_setunique(struct inode *inode, struct file *filp,
        return 0;
 }
 
-static int drm_set_busid(drm_device_t * dev)
+static int drm_set_busid(struct drm_device * dev)
 {
        int len;
        if (dev->unique != NULL)
@@ -167,7 +156,7 @@ static int drm_set_busid(drm_device_t * dev)
  * Get a mapping information.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_map structure.
  *
@@ -176,21 +165,16 @@ static int drm_set_busid(drm_device_t * dev)
  * Searches for the mapping with the specified offset and copies its information
  * into userspace
  */
-int drm_getmap(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_getmap(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_map_t __user *argp = (void __user *)arg;
-       drm_map_t map;
-       drm_map_list_t *r_list = NULL;
+       struct drm_map *map = data;
+       struct drm_map_list *r_list = NULL;
        struct list_head *list;
        int idx;
        int i;
 
-       if (copy_from_user(&map, argp, sizeof(map)))
-               return -EFAULT;
-       idx = map.offset;
+       idx = map->offset;
 
        mutex_lock(&dev->struct_mutex);
        if (idx < 0) {
@@ -201,7 +185,7 @@ int drm_getmap(struct inode *inode, struct file *filp,
        i = 0;
        list_for_each(list, &dev->maplist) {
                if (i == idx) {
-                       r_list = list_entry(list, drm_map_list_t, head);
+                       r_list = list_entry(list, struct drm_map_list, head);
                        break;
                }
                i++;
@@ -211,16 +195,14 @@ int drm_getmap(struct inode *inode, struct file *filp,
                return -EINVAL;
        }
 
-       map.offset = r_list->map->offset;
-       map.size = r_list->map->size;
-       map.type = r_list->map->type;
-       map.flags = r_list->map->flags;
-       map.handle = (void *)(unsigned long) r_list->user_token;
-       map.mtrr = r_list->map->mtrr;
+       map->offset = r_list->map->offset;
+       map->size = r_list->map->size;
+       map->type = r_list->map->type;
+       map->flags = r_list->map->flags;
+       map->handle = (void *)(unsigned long) r_list->user_token;
+       map->mtrr = r_list->map->mtrr;
        mutex_unlock(&dev->struct_mutex);
 
-       if (copy_to_user(argp, &map, sizeof(map)))
-               return -EFAULT;
        return 0;
 }
 
@@ -228,7 +210,7 @@ int drm_getmap(struct inode *inode, struct file *filp,
  * Get client information.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_client structure.
  *
@@ -237,82 +219,68 @@ int drm_getmap(struct inode *inode, struct file *filp,
  * Searches for the client with the specified index and copies its information
  * into userspace
  */
-int drm_getclient(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int drm_getclient(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_client_t __user *argp = (drm_client_t __user *)arg;
-       drm_client_t client;
-       drm_file_t *pt;
+       struct drm_client *client = data;
+       struct drm_file *pt;
        int idx;
        int i;
 
-       if (copy_from_user(&client, argp, sizeof(client)))
-               return -EFAULT;
-       idx = client.idx;
+       idx = client->idx;
        mutex_lock(&dev->struct_mutex);
-       
-       if (list_empty(&dev->filelist)) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
 
        i = 0;
        list_for_each_entry(pt, &dev->filelist, lhead) {
-               if (i++ >= idx)
-                       break;
+               if (i++ >= idx) {
+                       client->auth = pt->authenticated;
+                       client->pid = pt->pid;
+                       client->uid = pt->uid;
+                       client->magic = pt->magic;
+                       client->iocs = pt->ioctl_count;
+                       mutex_unlock(&dev->struct_mutex);
+
+                       return 0;
+               }
        }
-
-       client.auth = pt->authenticated;
-       client.pid = pt->pid;
-       client.uid = pt->uid;
-       client.magic = pt->magic;
-       client.iocs = pt->ioctl_count;
        mutex_unlock(&dev->struct_mutex);
 
-       if (copy_to_user(argp, &client, sizeof(client)))
-               return -EFAULT;
-       return 0;
+       return -EINVAL;
 }
 
 /**
  * Get statistics information.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_stats structure.
  *
  * \return zero on success or a negative number on failure.
  */
-int drm_getstats(struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+int drm_getstats(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_stats_t stats;
+       struct drm_stats *stats = data;
        int i;
 
-       memset(&stats, 0, sizeof(stats));
+       memset(stats, 0, sizeof(stats));
 
        mutex_lock(&dev->struct_mutex);
 
        for (i = 0; i < dev->counters; i++) {
                if (dev->types[i] == _DRM_STAT_LOCK)
-                       stats.data[i].value
-                           (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
+                       stats->data[i].value =
+                           (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
                else
-                       stats.data[i].value = atomic_read(&dev->counts[i]);
-               stats.data[i].type = dev->types[i];
+                       stats->data[i].value = atomic_read(&dev->counts[i]);
+               stats->data[i].type = dev->types[i];
        }
 
-       stats.count = dev->counters;
+       stats->count = dev->counters;
 
        mutex_unlock(&dev->struct_mutex);
 
-       if (copy_to_user((drm_stats_t __user *) arg, &stats, sizeof(stats)))
-               return -EFAULT;
        return 0;
 }
 
@@ -320,39 +288,28 @@ int drm_getstats(struct inode *inode, struct file *filp,
  * Setversion ioctl.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_lock structure.
  * \return zero on success or negative number on failure.
  *
  * Sets the requested interface version
  */
-int drm_setversion(DRM_IOCTL_ARGS)
+int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_set_version_t sv;
-       drm_set_version_t retv;
-       int if_version;
-       drm_set_version_t __user *argp = (void __user *)data;
-       if (copy_from_user(&sv, argp, sizeof(sv)))
-               return -EFAULT;
-
-       retv.drm_di_major = DRM_IF_MAJOR;
-       retv.drm_di_minor = DRM_IF_MINOR;
-       retv.drm_dd_major = dev->driver->major;
-       retv.drm_dd_minor = dev->driver->minor;
-
-       if (copy_to_user(argp, &retv, sizeof(retv)))
-               return -EFAULT;
-
-       if (sv.drm_di_major != -1) {
-               if (sv.drm_di_major != DRM_IF_MAJOR ||
-                   sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
-                       return -EINVAL;
-               if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor);
+       struct drm_set_version *sv = data;
+       int if_version, retcode = 0;
+
+       if (sv->drm_di_major != -1) {
+               if (sv->drm_di_major != DRM_IF_MAJOR ||
+                   sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) {
+                       retcode = -EINVAL;
+                       goto done;
+               }
+               if_version = DRM_IF_VERSION(sv->drm_di_major,
+                                           sv->drm_di_minor);
                dev->if_version = max(if_version, dev->if_version);
-               if (sv.drm_di_minor >= 1) {
+               if (sv->drm_di_minor >= 1) {
                        /*
                         * Version 1.1 includes tying of DRM to specific device
                         */
@@ -360,20 +317,30 @@ int drm_setversion(DRM_IOCTL_ARGS)
                }
        }
 
-       if (sv.drm_dd_major != -1) {
-               if (sv.drm_dd_major != dev->driver->major ||
-                   sv.drm_dd_minor < 0 || sv.drm_dd_minor > dev->driver->minor)
-                       return -EINVAL;
+       if (sv->drm_dd_major != -1) {
+               if (sv->drm_dd_major != dev->driver->major ||
+                   sv->drm_dd_minor < 0 || sv->drm_dd_minor >
+                   dev->driver->minor) {
+                       retcode = -EINVAL;
+                       goto done;
+               }
 
                if (dev->driver->set_version)
-                       dev->driver->set_version(dev, &sv);
+                       dev->driver->set_version(dev, sv);
        }
-       return 0;
+
+done:
+       sv->drm_di_major = DRM_IF_MAJOR;
+       sv->drm_di_minor = DRM_IF_MINOR;
+       sv->drm_dd_major = dev->driver->major;
+       sv->drm_dd_minor = dev->driver->minor;
+
+       return retcode;
 }
 
 /** No-op ioctl. */
-int drm_noop(struct inode *inode, struct file *filp, unsigned int cmd,
-            unsigned long arg)
+int drm_noop(struct drm_device *dev, void *data,
+            struct drm_file *file_priv)
 {
        DRM_DEBUG("\n");
        return 0;
index 8871671..25166b6 100644 (file)
@@ -41,7 +41,7 @@
  * Get interrupt from bus id.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_irq_busid structure.
  * \return zero on success or a negative number on failure.
  * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
  * to that of the device that this DRM instance attached to.
  */
-int drm_irq_by_busid(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+int drm_irq_by_busid(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_irq_busid_t __user *argp = (void __user *)arg;
-       drm_irq_busid_t p;
+       struct drm_irq_busid *p = data;
 
        if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
                return -EINVAL;
 
-       if (copy_from_user(&p, argp, sizeof(p)))
-               return -EFAULT;
-
-       if ((p.busnum >> 8) != drm_get_pci_domain(dev) ||
-           (p.busnum & 0xff) != dev->pdev->bus->number ||
-           p.devnum != PCI_SLOT(dev->pdev->devfn) || p.funcnum != PCI_FUNC(dev->pdev->devfn))
+       if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
+           (p->busnum & 0xff) != dev->pdev->bus->number ||
+           p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
                return -EINVAL;
 
-       p.irq = dev->irq;
+       p->irq = dev->irq;
+
+       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
+                 p->irq);
 
-       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq);
-       if (copy_to_user(argp, &p, sizeof(p)))
-               return -EFAULT;
        return 0;
 }
 
@@ -86,7 +80,7 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
  * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
  * before and after the installation.
  */
-static int drm_irq_install(drm_device_t * dev)
+int drm_irq_install(struct drm_device * dev)
 {
        int ret;
        unsigned long sh_flags = 0;
@@ -146,6 +140,7 @@ static int drm_irq_install(drm_device_t * dev)
 
        return 0;
 }
+EXPORT_SYMBOL(drm_irq_install);
 
 /**
  * Uninstall the IRQ handler.
@@ -154,7 +149,7 @@ static int drm_irq_install(drm_device_t * dev)
  *
  * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
  */
-int drm_irq_uninstall(drm_device_t * dev)
+int drm_irq_uninstall(struct drm_device * dev)
 {
        int irq_enabled;
 
@@ -185,31 +180,27 @@ EXPORT_SYMBOL(drm_irq_uninstall);
  * IRQ control ioctl.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_control structure.
  * \return zero on success or a negative number on failure.
  *
  * Calls irq_install() or irq_uninstall() according to \p arg.
  */
-int drm_control(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+int drm_control(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_control_t ctl;
+       struct drm_control *ctl = data;
 
        /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
 
-       if (copy_from_user(&ctl, (drm_control_t __user *) arg, sizeof(ctl)))
-               return -EFAULT;
 
-       switch (ctl.func) {
+       switch (ctl->func) {
        case DRM_INST_HANDLER:
                if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
                        return 0;
                if (dev->if_version < DRM_IF_VERSION(1, 2) &&
-                   ctl.irq != dev->irq)
+                   ctl->irq != dev->irq)
                        return -EINVAL;
                return drm_irq_install(dev);
        case DRM_UNINST_HANDLER:
@@ -225,7 +216,7 @@ int drm_control(struct inode *inode, struct file *filp,
  * Wait for VBLANK.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param data user argument, pointing to a drm_wait_vblank structure.
  * \return zero on success or a negative number on failure.
@@ -240,12 +231,9 @@ int drm_control(struct inode *inode, struct file *filp,
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-int drm_wait_vblank(DRM_IOCTL_ARGS)
+int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_wait_vblank_t __user *argp = (void __user *)data;
-       drm_wait_vblank_t vblwait;
+       union drm_wait_vblank *vblwait = data;
        struct timeval now;
        int ret = 0;
        unsigned int flags, seq;
@@ -253,18 +241,15 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        if ((!dev->irq) || (!dev->irq_enabled))
                return -EINVAL;
 
-       if (copy_from_user(&vblwait, argp, sizeof(vblwait)))
-               return -EFAULT;
-
-       if (vblwait.request.type &
+       if (vblwait->request.type &
            ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
                DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
-                         vblwait.request.type,
+                         vblwait->request.type,
                          (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
                return -EINVAL;
        }
 
-       flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+       flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
 
        if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
                                    DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
@@ -273,10 +258,10 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
                          : &dev->vbl_received);
 
-       switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
+       switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
        case _DRM_VBLANK_RELATIVE:
-               vblwait.request.sequence += seq;
-               vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+               vblwait->request.sequence += seq;
+               vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
        case _DRM_VBLANK_ABSOLUTE:
                break;
        default:
@@ -284,15 +269,15 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        }
 
        if ((flags & _DRM_VBLANK_NEXTONMISS) &&
-           (seq - vblwait.request.sequence) <= (1<<23)) {
-               vblwait.request.sequence = seq + 1;
+           (seq - vblwait->request.sequence) <= (1<<23)) {
+               vblwait->request.sequence = seq + 1;
        }
 
        if (flags & _DRM_VBLANK_SIGNAL) {
                unsigned long irqflags;
                struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
                                      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-               drm_vbl_sig_t *vbl_sig;
+               struct drm_vbl_sig *vbl_sig;
 
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
@@ -301,12 +286,13 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
                 * that case
                 */
                list_for_each_entry(vbl_sig, vbl_sigs, head) {
-                       if (vbl_sig->sequence == vblwait.request.sequence
-                           && vbl_sig->info.si_signo == vblwait.request.signal
+                       if (vbl_sig->sequence == vblwait->request.sequence
+                           && vbl_sig->info.si_signo ==
+                           vblwait->request.signal
                            && vbl_sig->task == current) {
                                spin_unlock_irqrestore(&dev->vbl_lock,
                                                       irqflags);
-                               vblwait.reply.sequence = seq;
+                               vblwait->reply.sequence = seq;
                                goto done;
                        }
                }
@@ -322,14 +308,14 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
 
                if (!
                    (vbl_sig =
-                    drm_alloc(sizeof(drm_vbl_sig_t), DRM_MEM_DRIVER))) {
+                    drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
                        return -ENOMEM;
                }
 
                memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
 
-               vbl_sig->sequence = vblwait.request.sequence;
-               vbl_sig->info.si_signo = vblwait.request.signal;
+               vbl_sig->sequence = vblwait->request.sequence;
+               vbl_sig->info.si_signo = vblwait->request.signal;
                vbl_sig->task = current;
 
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -338,25 +324,22 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
 
                spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
-               vblwait.reply.sequence = seq;
+               vblwait->reply.sequence = seq;
        } else {
                if (flags & _DRM_VBLANK_SECONDARY) {
                        if (dev->driver->vblank_wait2)
-                               ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence);
+                               ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
                } else if (dev->driver->vblank_wait)
                        ret =
                            dev->driver->vblank_wait(dev,
-                                                    &vblwait.request.sequence);
+                                                    &vblwait->request.sequence);
 
                do_gettimeofday(&now);
-               vblwait.reply.tval_sec = now.tv_sec;
-               vblwait.reply.tval_usec = now.tv_usec;
+               vblwait->reply.tval_sec = now.tv_sec;
+               vblwait->reply.tval_usec = now.tv_usec;
        }
 
       done:
-       if (copy_to_user(argp, &vblwait, sizeof(vblwait)))
-               return -EFAULT;
-
        return ret;
 }
 
@@ -369,7 +352,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
  *
  * If a signal is not requested, then calls vblank_wait().
  */
-void drm_vbl_send_signals(drm_device_t * dev)
+void drm_vbl_send_signals(struct drm_device * dev)
 {
        unsigned long flags;
        int i;
@@ -377,7 +360,7 @@ void drm_vbl_send_signals(drm_device_t * dev)
        spin_lock_irqsave(&dev->vbl_lock, flags);
 
        for (i = 0; i < 2; i++) {
-               drm_vbl_sig_t *vbl_sig, *tmp;
+               struct drm_vbl_sig *vbl_sig, *tmp;
                struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
                unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
                                                   &dev->vbl_received);
@@ -413,7 +396,7 @@ EXPORT_SYMBOL(drm_vbl_send_signals);
  */
 static void drm_locked_tasklet_func(unsigned long data)
 {
-       drm_device_t *dev = (drm_device_t*)data;
+       struct drm_device *dev = (struct drm_device*)data;
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev->tasklet_lock, irqflags);
@@ -450,7 +433,7 @@ static void drm_locked_tasklet_func(unsigned long data)
  * context, it must not make any assumptions about this. Also, the HW lock will
  * be held with the kernel context or any client context.
  */
-void drm_locked_tasklet(drm_device_t *dev, void (*func)(drm_device_t*))
+void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device*))
 {
        unsigned long irqflags;
        static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
index f02df36..b8e4a5d 100644 (file)
@@ -41,39 +41,33 @@ static int drm_notifier(void *priv);
  * Lock ioctl.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_lock structure.
  * \return zero on success or negative number on failure.
  *
  * Add the current task to the lock wait queue, and attempt to take to lock.
  */
-int drm_lock(struct inode *inode, struct file *filp,
-            unsigned int cmd, unsigned long arg)
+int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        DECLARE_WAITQUEUE(entry, current);
-       drm_lock_t lock;
+       struct drm_lock *lock = data;
        int ret = 0;
 
-       ++priv->lock_count;
+       ++file_priv->lock_count;
 
-       if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
-               return -EFAULT;
-
-       if (lock.context == DRM_KERNEL_CONTEXT) {
+       if (lock->context == DRM_KERNEL_CONTEXT) {
                DRM_ERROR("Process %d using kernel context %d\n",
-                         current->pid, lock.context);
+                         current->pid, lock->context);
                return -EINVAL;
        }
 
        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-                 lock.context, current->pid,
-                 dev->lock.hw_lock->lock, lock.flags);
+                 lock->context, current->pid,
+                 dev->lock.hw_lock->lock, lock->flags);
 
        if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
-               if (lock.context < 0)
+               if (lock->context < 0)
                        return -EINVAL;
 
        add_wait_queue(&dev->lock.lock_queue, &entry);
@@ -87,8 +81,8 @@ int drm_lock(struct inode *inode, struct file *filp,
                        ret = -EINTR;
                        break;
                }
-               if (drm_lock_take(&dev->lock, lock.context)) {
-                       dev->lock.filp = filp;
+               if (drm_lock_take(&dev->lock, lock->context)) {
+                       dev->lock.file_priv = file_priv;
                        dev->lock.lock_time = jiffies;
                        atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
                        break;  /* Got lock */
@@ -107,7 +101,8 @@ int drm_lock(struct inode *inode, struct file *filp,
        __set_current_state(TASK_RUNNING);
        remove_wait_queue(&dev->lock.lock_queue, &entry);
 
-       DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
+       DRM_DEBUG("%d %s\n", lock->context,
+                 ret ? "interrupted" : "has lock");
        if (ret) return ret;
 
        sigemptyset(&dev->sigmask);
@@ -115,24 +110,26 @@ int drm_lock(struct inode *inode, struct file *filp,
        sigaddset(&dev->sigmask, SIGTSTP);
        sigaddset(&dev->sigmask, SIGTTIN);
        sigaddset(&dev->sigmask, SIGTTOU);
-       dev->sigdata.context = lock.context;
+       dev->sigdata.context = lock->context;
        dev->sigdata.lock = dev->lock.hw_lock;
        block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
 
-       if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
+       if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY))
                dev->driver->dma_ready(dev);
 
-       if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) {
+       if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT))
+       {
                if (dev->driver->dma_quiescent(dev)) {
-                       DRM_DEBUG( "%d waiting for DMA quiescent\n", lock.context);
-                       return DRM_ERR(EBUSY);
+                       DRM_DEBUG("%d waiting for DMA quiescent\n",
+                                 lock->context);
+                       return -EBUSY;
                }
        }
 
        if (dev->driver->kernel_context_switch &&
-           dev->last_context != lock.context) {
+           dev->last_context != lock->context) {
                dev->driver->kernel_context_switch(dev, dev->last_context,
-                                                  lock.context);
+                                                  lock->context);
        }
 
        return 0;
@@ -142,27 +139,21 @@ int drm_lock(struct inode *inode, struct file *filp,
  * Unlock ioctl.
  *
  * \param inode device inode.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param cmd command.
  * \param arg user argument, pointing to a drm_lock structure.
  * \return zero on success or negative number on failure.
  *
  * Transfer and free the lock.
  */
-int drm_unlock(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_lock_t lock;
+       struct drm_lock *lock = data;
        unsigned long irqflags;
 
-       if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock)))
-               return -EFAULT;
-
-       if (lock.context == DRM_KERNEL_CONTEXT) {
+       if (lock->context == DRM_KERNEL_CONTEXT) {
                DRM_ERROR("Process %d using kernel context %d\n",
-                         current->pid, lock.context);
+                         current->pid, lock->context);
                return -EINVAL;
        }
 
@@ -184,7 +175,7 @@ int drm_unlock(struct inode *inode, struct file *filp,
        if (dev->driver->kernel_context_switch_unlock)
                dev->driver->kernel_context_switch_unlock(dev);
        else {
-               if (drm_lock_free(&dev->lock,lock.context)) {
+               if (drm_lock_free(&dev->lock,lock->context)) {
                        /* FIXME: Should really bail out here. */
                }
        }
@@ -202,7 +193,7 @@ int drm_unlock(struct inode *inode, struct file *filp,
  *
  * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
  */
-int drm_lock_take(drm_lock_data_t *lock_data,
+int drm_lock_take(struct drm_lock_data *lock_data,
                  unsigned int context)
 {
        unsigned int old, new, prev;
@@ -252,13 +243,13 @@ int drm_lock_take(drm_lock_data_t *lock_data,
  * Resets the lock file pointer.
  * Marks the lock as held by the given context, via the \p cmpxchg instruction.
  */
-static int drm_lock_transfer(drm_lock_data_t *lock_data,
+static int drm_lock_transfer(struct drm_lock_data *lock_data,
                             unsigned int context)
 {
        unsigned int old, new, prev;
        volatile unsigned int *lock = &lock_data->hw_lock->lock;
 
-       lock_data->filp = NULL;
+       lock_data->file_priv = NULL;
        do {
                old = *lock;
                new = context | _DRM_LOCK_HELD;
@@ -278,7 +269,7 @@ static int drm_lock_transfer(drm_lock_data_t *lock_data,
  * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
  * waiting on the lock queue.
  */
-int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context)
+int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
 {
        unsigned int old, new, prev;
        volatile unsigned int *lock = &lock_data->hw_lock->lock;
@@ -320,7 +311,7 @@ int drm_lock_free(drm_lock_data_t *lock_data, unsigned int context)
  */
 static int drm_notifier(void *priv)
 {
-       drm_sigdata_t *s = (drm_sigdata_t *) priv;
+       struct drm_sigdata *s = (struct drm_sigdata *) priv;
        unsigned int old, new, prev;
 
        /* Allow signal delivery if lock isn't held */
@@ -351,7 +342,7 @@ static int drm_notifier(void *priv)
  * having to worry about starvation.
  */
 
-void drm_idlelock_take(drm_lock_data_t *lock_data)
+void drm_idlelock_take(struct drm_lock_data *lock_data)
 {
        int ret = 0;
 
@@ -370,7 +361,7 @@ void drm_idlelock_take(drm_lock_data_t *lock_data)
 }
 EXPORT_SYMBOL(drm_idlelock_take);
 
-void drm_idlelock_release(drm_lock_data_t *lock_data)
+void drm_idlelock_release(struct drm_lock_data *lock_data)
 {
        unsigned int old, prev;
        volatile unsigned int *lock = &lock_data->hw_lock->lock;
@@ -391,13 +382,12 @@ void drm_idlelock_release(drm_lock_data_t *lock_data)
 EXPORT_SYMBOL(drm_idlelock_release);
 
 
-int drm_i_have_hw_lock(struct file *filp)
+int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
-       return (priv->lock_count && dev->lock.hw_lock &&
+       return (file_priv->lock_count && dev->lock.hw_lock &&
                _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
-               dev->lock.filp == filp);
+               dev->lock.file_priv == file_priv);
 }
 
 EXPORT_SYMBOL(drm_i_have_hw_lock);
index b1423c1..f68a3a3 100644 (file)
@@ -38,9 +38,9 @@
 
 static struct {
        spinlock_t lock;
-       drm_u64_t cur_used;
-       drm_u64_t low_threshold;
-       drm_u64_t high_threshold;
+       uint64_t cur_used;
+       uint64_t low_threshold;
+       uint64_t high_threshold;
 } drm_memctl = {
        .lock = SPIN_LOCK_UNLOCKED
 };
@@ -82,9 +82,9 @@ void drm_free_memctl(size_t size)
 }
 EXPORT_SYMBOL(drm_free_memctl);
 
-void drm_query_memctl(drm_u64_t *cur_used,
-                     drm_u64_t *low_threshold,
-                     drm_u64_t *high_threshold)
+void drm_query_memctl(uint64_t *cur_used,
+                     uint64_t *low_threshold,
+                     uint64_t *high_threshold)
 {
        spin_lock(&drm_memctl.lock);
        *cur_used = drm_memctl.cur_used;
@@ -214,7 +214,7 @@ void drm_free_pages(unsigned long address, int order, int area)
 
 #if __OS_HAS_AGP
 static void *agp_remap(unsigned long offset, unsigned long size,
-                             drm_device_t * dev)
+                             struct drm_device * dev)
 {
        unsigned long *phys_addr_map, i, num_pages =
            PAGE_ALIGN(size) / PAGE_SIZE;
@@ -258,12 +258,12 @@ static void *agp_remap(unsigned long offset, unsigned long size,
 
 /** Wrapper around agp_allocate_memory() */
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)
-DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type)
 {
        return drm_agp_allocate_memory(pages, type);
 }
 #else
-DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type)
 {
        return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
 }
@@ -289,7 +289,7 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
 
 #else  /* __OS_HAS_AGP*/
 static void *agp_remap(unsigned long offset, unsigned long size,
-                      drm_device_t * dev)
+                      struct drm_device * dev)
 {
        return NULL;
 }
index c124f8f..c196ee2 100644 (file)
@@ -291,7 +291,7 @@ void drm_free_pages(unsigned long address, int order, int area)
 
 #if __OS_HAS_AGP
 
-DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type)
 {
        DRM_AGP_MEM *handle;
 
index 9d0dedf..b055ac0 100644 (file)
@@ -277,7 +277,7 @@ void drm_free_pages (unsigned long address, int order, int area) {
 
 #if __OS_HAS_AGP
 
-DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) {
+DRM_AGP_MEM *drm_alloc_agp (struct drm_device *dev, int pages, u32 type) {
        DRM_AGP_MEM *handle;
 
        if (!pages) {
index 2caf596..cf0d92f 100644 (file)
 #include "drmP.h"
 #include <linux/slab.h>
 
-unsigned long drm_mm_tail_space(drm_mm_t *mm)
+unsigned long drm_mm_tail_space(struct drm_mm *mm)
 {
        struct list_head *tail_node;
-       drm_mm_node_t *entry;
+       struct drm_mm_node *entry;
 
        tail_node = mm->ml_entry.prev;
-       entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
        if (!entry->free)
                return 0;
 
        return entry->size;
 }
 
-int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
 {
        struct list_head *tail_node;
-       drm_mm_node_t *entry;
+       struct drm_mm_node *entry;
 
        tail_node = mm->ml_entry.prev;
-       entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
        if (!entry->free)
                return -ENOMEM;
 
@@ -75,13 +75,13 @@ int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size)
 }
 
 
-static int drm_mm_create_tail_node(drm_mm_t *mm,
+static int drm_mm_create_tail_node(struct drm_mm *mm,
                            unsigned long start,
                            unsigned long size)
 {
-       drm_mm_node_t *child;
+       struct drm_mm_node *child;
 
-       child = (drm_mm_node_t *)
+       child = (struct drm_mm_node *)
                drm_ctl_alloc(sizeof(*child), DRM_MEM_MM);
        if (!child)
                return -ENOMEM;
@@ -98,13 +98,13 @@ static int drm_mm_create_tail_node(drm_mm_t *mm,
 }
 
 
-int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size)
+int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
 {
        struct list_head *tail_node;
-       drm_mm_node_t *entry;
+       struct drm_mm_node *entry;
 
        tail_node = mm->ml_entry.prev;
-       entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
+       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
        if (!entry->free) {
                return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
        }
@@ -112,12 +112,12 @@ int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size)
        return 0;
 }
 
-static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent,
+static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
                                            unsigned long size)
 {
-       drm_mm_node_t *child;
+       struct drm_mm_node *child;
 
-       child = (drm_mm_node_t *)
+       child = (struct drm_mm_node *)
                drm_ctl_alloc(sizeof(*child), DRM_MEM_MM);
        if (!child)
                return NULL;
@@ -137,12 +137,12 @@ static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent,
        return child;
 }
 
-drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
+struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
                                unsigned long size, unsigned alignment)
 {
 
-       drm_mm_node_t *align_splitoff = NULL;
-       drm_mm_node_t *child;
+       struct drm_mm_node *align_splitoff = NULL;
+       struct drm_mm_node *child;
        unsigned tmp = 0;
 
        if (alignment)
@@ -173,26 +173,26 @@ drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
  * Otherwise add to the free stack.
  */
 
-void drm_mm_put_block(drm_mm_node_t * cur)
+void drm_mm_put_block(struct drm_mm_node * cur)
 {
 
-       drm_mm_t *mm = cur->mm;
+       struct drm_mm *mm = cur->mm;
        struct list_head *cur_head = &cur->ml_entry;
        struct list_head *root_head = &mm->ml_entry;
-       drm_mm_node_t *prev_node = NULL;
-       drm_mm_node_t *next_node;
+       struct drm_mm_node *prev_node = NULL;
+       struct drm_mm_node *next_node;
 
        int merged = 0;
 
        if (cur_head->prev != root_head) {
-               prev_node = list_entry(cur_head->prev, drm_mm_node_t, ml_entry);
+               prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
                if (prev_node->free) {
                        prev_node->size += cur->size;
                        merged = 1;
                }
        }
        if (cur_head->next != root_head) {
-               next_node = list_entry(cur_head->next, drm_mm_node_t, ml_entry);
+               next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
                if (next_node->free) {
                        if (merged) {
                                prev_node->size += next_node->size;
@@ -217,14 +217,14 @@ void drm_mm_put_block(drm_mm_node_t * cur)
 }
 EXPORT_SYMBOL(drm_mm_put_block);
 
-drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
+struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
                                  unsigned long size,
                                  unsigned alignment, int best_match)
 {
        struct list_head *list;
        const struct list_head *free_stack = &mm->fl_entry;
-       drm_mm_node_t *entry;
-       drm_mm_node_t *best;
+       struct drm_mm_node *entry;
+       struct drm_mm_node *best;
        unsigned long best_size;
        unsigned wasted;
 
@@ -232,7 +232,7 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
        best_size = ~0UL;
 
        list_for_each(list, free_stack) {
-               entry = list_entry(list, drm_mm_node_t, fl_entry);
+               entry = list_entry(list, struct drm_mm_node, fl_entry);
                wasted = 0;
 
                if (entry->size < size) 
@@ -258,14 +258,14 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
        return best;
 }
 
-int drm_mm_clean(drm_mm_t * mm)
+int drm_mm_clean(struct drm_mm * mm)
 {
        struct list_head *head = &mm->ml_entry;
 
        return (head->next->next == head);
 }
 
-int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
+int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
        INIT_LIST_HEAD(&mm->ml_entry);
        INIT_LIST_HEAD(&mm->fl_entry);
@@ -275,12 +275,12 @@ int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
 
 EXPORT_SYMBOL(drm_mm_init);
 
-void drm_mm_takedown(drm_mm_t * mm)
+void drm_mm_takedown(struct drm_mm * mm)
 {
        struct list_head *bnode = mm->fl_entry.next;
-       drm_mm_node_t *entry;
+       struct drm_mm_node *entry;
 
-       entry = list_entry(bnode, drm_mm_node_t, fl_entry);
+       entry = list_entry(bnode, struct drm_mm_node, fl_entry);
 
        if (entry->ml_entry.next != &mm->ml_entry ||
            entry->fl_entry.next != &mm->fl_entry) {
diff --git a/linux-core/drm_modes.c b/linux-core/drm_modes.c
new file mode 100644 (file)
index 0000000..fd00841
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * Copyright © 1997-2003 by The XFree86 Project, Inc.
+ *
+ * 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
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+/*
+ * Copyright © 2007 Dave Airlie
+ */
+
+#include <linux/list.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+
+/**
+ * drm_mode_debug_printmodeline - debug print a mode
+ * @dev: DRM device
+ * @mode: mode to print
+ *
+ * LOCKING:
+ * None.
+ *
+ * Describe @mode using DRM_DEBUG.
+ */
+void drm_mode_debug_printmodeline(struct drm_device *dev,
+                                 struct drm_display_mode *mode)
+{
+       DRM_DEBUG("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x\n",
+                 mode->mode_id, mode->name, mode->vrefresh, mode->clock,
+                 mode->hdisplay, mode->hsync_start,
+                 mode->hsync_end, mode->htotal,
+                 mode->vdisplay, mode->vsync_start,
+                 mode->vsync_end, mode->vtotal, mode->type);
+}
+EXPORT_SYMBOL(drm_mode_debug_printmodeline);
+
+/**
+ * drm_mode_set_name - set the name on a mode
+ * @mode: name will be set in this mode
+ *
+ * LOCKING:
+ * None.
+ *
+ * Set the name of @mode to a standard format.
+ */
+void drm_mode_set_name(struct drm_display_mode *mode)
+{
+       snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay,
+                mode->vdisplay);
+}
+EXPORT_SYMBOL(drm_mode_set_name);
+
+/**
+ * drm_mode_list_concat - move modes from one list to another
+ * @head: source list
+ * @new: dst list
+ *
+ * LOCKING:
+ * Caller must ensure both lists are locked.
+ *
+ * Move all the modes from @head to @new.
+ */
+void drm_mode_list_concat(struct list_head *head, struct list_head *new)
+{
+
+       struct list_head *entry, *tmp;
+
+       list_for_each_safe(entry, tmp, head) {
+               list_move_tail(entry, new);
+       }
+}
+
+/**
+ * drm_mode_width - get the width of a mode
+ * @mode: mode
+ *
+ * LOCKING:
+ * None.
+ *
+ * Return @mode's width (hdisplay) value.
+ *
+ * FIXME: is this needed?
+ *
+ * RETURNS:
+ * @mode->hdisplay
+ */
+int drm_mode_width(struct drm_display_mode *mode)
+{
+       return mode->hdisplay;
+
+}
+EXPORT_SYMBOL(drm_mode_width);
+
+/**
+ * drm_mode_height - get the height of a mode
+ * @mode: mode
+ *
+ * LOCKING:
+ * None.
+ *
+ * Return @mode's height (vdisplay) value.
+ *
+ * FIXME: is this needed?
+ *
+ * RETURNS:
+ * @mode->vdisplay
+ */
+int drm_mode_height(struct drm_display_mode *mode)
+{
+       return mode->vdisplay;
+}
+EXPORT_SYMBOL(drm_mode_height);
+
+/**
+ * drm_mode_vrefresh - get the vrefresh of a mode
+ * @mode: mode
+ *
+ * LOCKING:
+ * None.
+ *
+ * Return @mode's vrefresh rate or calculate it if necessary.
+ *
+ * FIXME: why is this needed?  shouldn't vrefresh be set already?
+ *
+ * RETURNS:
+ * Vertical refresh rate of @mode x 1000. For precision reasons.
+ */
+int drm_mode_vrefresh(struct drm_display_mode *mode)
+{
+       int refresh = 0;
+       unsigned int calc_val;
+
+       if (mode->vrefresh > 0)
+               refresh = mode->vrefresh;
+       else if (mode->htotal > 0 && mode->vtotal > 0) {
+               /* work out vrefresh the value will be x1000 */
+               calc_val = (mode->clock * 1000);
+
+               calc_val /= mode->htotal;
+               calc_val *= 1000;
+               calc_val /= mode->vtotal;
+
+               refresh = calc_val;
+               if (mode->flags & V_INTERLACE)
+                       refresh *= 2;
+               if (mode->flags & V_DBLSCAN)
+                       refresh /= 2;
+               if (mode->vscan > 1)
+                       refresh /= mode->vscan;
+       }
+       return refresh;
+}
+EXPORT_SYMBOL(drm_mode_vrefresh);
+       
+/**
+ * drm_mode_set_crtcinfo - set CRTC modesetting parameters
+ * @p: mode
+ * @adjust_flags: unused? (FIXME)
+ *
+ * LOCKING:
+ * None.
+ *
+ * Setup the CRTC modesetting parameters for @p, adjusting if necessary.
+ */
+void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
+{
+       if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
+               return;
+
+       p->crtc_hdisplay = p->hdisplay;
+       p->crtc_hsync_start = p->hsync_start;
+       p->crtc_hsync_end = p->hsync_end;
+       p->crtc_htotal = p->htotal;
+       p->crtc_hskew = p->hskew;
+       p->crtc_vdisplay = p->vdisplay;
+       p->crtc_vsync_start = p->vsync_start;
+       p->crtc_vsync_end = p->vsync_end;
+       p->crtc_vtotal = p->vtotal;
+
+       if (p->flags & V_INTERLACE) {
+               if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
+                       p->crtc_vdisplay /= 2;
+                       p->crtc_vsync_start /= 2;
+                       p->crtc_vsync_end /= 2;
+                       p->crtc_vtotal /= 2;
+               }
+
+               p->crtc_vtotal |= 1;
+       }
+
+       if (p->flags & V_DBLSCAN) {
+               p->crtc_vdisplay *= 2;
+               p->crtc_vsync_start *= 2;
+               p->crtc_vsync_end *= 2;
+               p->crtc_vtotal *= 2;
+       }
+
+       if (p->vscan > 1) {
+               p->crtc_vdisplay *= p->vscan;
+               p->crtc_vsync_start *= p->vscan;
+               p->crtc_vsync_end *= p->vscan;
+               p->crtc_vtotal *= p->vscan;
+       }
+
+       p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
+       p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
+       p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
+       p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
+
+       p->crtc_hadjusted = false;
+       p->crtc_vadjusted = false;
+}
+EXPORT_SYMBOL(drm_mode_set_crtcinfo);
+
+
+/**
+ * drm_mode_duplicate - allocate and duplicate an existing mode
+ * @m: mode to duplicate
+ *
+ * LOCKING:
+ * None.
+ *
+ * Just allocate a new mode, copy the existing mode into it, and return
+ * a pointer to it.  Used to create new instances of established modes.
+ */
+struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
+                                           struct drm_display_mode *mode)
+{
+       struct drm_display_mode *nmode;
+       int new_id;
+
+       nmode = drm_mode_create(dev);
+       if (!nmode)
+               return NULL;
+
+       new_id = nmode->mode_id;
+       *nmode = *mode;
+       nmode->mode_id = new_id;
+       INIT_LIST_HEAD(&nmode->head);
+       return nmode;
+}
+EXPORT_SYMBOL(drm_mode_duplicate);
+
+/**
+ * drm_mode_equal - test modes for equality
+ * @mode1: first mode
+ * @mode2: second mode
+ *
+ * LOCKING:
+ * None.
+ *
+ * Check to see if @mode1 and @mode2 are equivalent.
+ *
+ * RETURNS:
+ * True if the modes are equal, false otherwise.
+ */
+bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2)
+{
+       if (mode1->clock == mode2->clock &&
+           mode1->hdisplay == mode2->hdisplay &&
+           mode1->hsync_start == mode2->hsync_start &&
+           mode1->hsync_end == mode2->hsync_end &&
+           mode1->htotal == mode2->htotal &&
+           mode1->hskew == mode2->hskew &&
+           mode1->vdisplay == mode2->vdisplay &&
+           mode1->vsync_start == mode2->vsync_start &&
+           mode1->vsync_end == mode2->vsync_end &&
+           mode1->vtotal == mode2->vtotal &&
+           mode1->vscan == mode2->vscan &&
+           mode1->flags == mode2->flags)
+               return true;
+       
+       return false;
+}
+EXPORT_SYMBOL(drm_mode_equal);
+
+/**
+ * drm_mode_validate_size - make sure modes adhere to size constraints
+ * @dev: DRM device
+ * @mode_list: list of modes to check
+ * @maxX: maximum width
+ * @maxY: maximum height
+ * @maxPitch: max pitch
+ *
+ * LOCKING:
+ * Caller must hold a lock protecting @mode_list.
+ *
+ * The DRM device (@dev) has size and pitch limits.  Here we validate the
+ * modes we probed for @dev against those limits and set their status as
+ * necessary.
+ */
+void drm_mode_validate_size(struct drm_device *dev,
+                           struct list_head *mode_list,
+                           int maxX, int maxY, int maxPitch)
+{
+       struct drm_display_mode *mode;
+
+       list_for_each_entry(mode, mode_list, head) {
+               if (maxPitch > 0 && mode->hdisplay > maxPitch)
+                       mode->status = MODE_BAD_WIDTH;
+               
+               if (maxX > 0 && mode->hdisplay > maxX)
+                       mode->status = MODE_VIRTUAL_X;
+
+               if (maxY > 0 && mode->vdisplay > maxY)
+                       mode->status = MODE_VIRTUAL_Y;
+       }
+}
+EXPORT_SYMBOL(drm_mode_validate_size);
+
+/**
+ * drm_mode_validate_clocks - validate modes against clock limits
+ * @dev: DRM device
+ * @mode_list: list of modes to check
+ * @min: minimum clock rate array
+ * @max: maximum clock rate array
+ * @n_ranges: number of clock ranges (size of arrays)
+ *
+ * LOCKING:
+ * Caller must hold a lock protecting @mode_list.
+ *
+ * Some code may need to check a mode list against the clock limits of the
+ * device in question.  This function walks the mode list, testing to make
+ * sure each mode falls within a given range (defined by @min and @max
+ * arrays) and sets @mode->status as needed.
+ */
+void drm_mode_validate_clocks(struct drm_device *dev,
+                             struct list_head *mode_list,
+                             int *min, int *max, int n_ranges)
+{
+       struct drm_display_mode *mode;
+       int i;
+
+       list_for_each_entry(mode, mode_list, head) {
+               bool good = false;
+               for (i = 0; i < n_ranges; i++) {
+                       if (mode->clock >= min[i] && mode->clock <= max[i]) {
+                               good = true;
+                               break;
+                       }
+               }
+               if (!good)
+                       mode->status = MODE_CLOCK_RANGE;
+       }
+}
+EXPORT_SYMBOL(drm_mode_validate_clocks);
+
+/**
+ * drm_mode_prune_invalid - remove invalid modes from mode list
+ * @dev: DRM device
+ * @mode_list: list of modes to check
+ * @verbose: be verbose about it
+ *
+ * LOCKING:
+ * Caller must hold a lock protecting @mode_list.
+ *
+ * Once mode list generation is complete, a caller can use this routine to
+ * remove invalid modes from a mode list.  If any of the modes have a
+ * status other than %MODE_OK, they are removed from @mode_list and freed.
+ */
+void drm_mode_prune_invalid(struct drm_device *dev,
+                           struct list_head *mode_list, bool verbose)
+{
+       struct drm_display_mode *mode, *t;
+
+       list_for_each_entry_safe(mode, t, mode_list, head) {
+               if (mode->status != MODE_OK) {
+                       list_del(&mode->head);
+                       if (verbose) {
+                               drm_mode_debug_printmodeline(dev, mode);
+                               DRM_DEBUG("Not using %s mode %d\n", mode->name, mode->status);
+                       }
+                       kfree(mode);
+               }
+       }
+}
+
+/**
+ * drm_mode_compare - compare modes for favorability
+ * @lh_a: list_head for first mode
+ * @lh_b: list_head for second mode
+ *
+ * LOCKING:
+ * None.
+ *
+ * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
+ * which is better.
+ *
+ * RETURNS:
+ * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
+ * positive if @lh_b is better than @lh_a.
+ */
+static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b)
+{
+       struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
+       struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
+       int diff;
+
+       diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
+               ((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
+       if (diff)
+               return diff;
+       diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
+       if (diff)
+               return diff;
+       diff = b->clock - a->clock;
+       return diff;
+}
+
+/* FIXME: what we don't have a list sort function? */
+/* list sort from Mark J Roberts (mjr@znex.org) */
+void list_sort(struct list_head *head, int (*cmp)(struct list_head *a, struct list_head *b))
+{
+       struct list_head *p, *q, *e, *list, *tail, *oldhead;
+       int insize, nmerges, psize, qsize, i;
+       
+       list = head->next;
+       list_del(head);
+       insize = 1;
+       for (;;) {
+               p = oldhead = list;
+               list = tail = NULL;
+               nmerges = 0;
+               
+               while (p) {
+                       nmerges++;
+                       q = p;
+                       psize = 0;
+                       for (i = 0; i < insize; i++) {
+                               psize++;
+                               q = q->next == oldhead ? NULL : q->next;
+                               if (!q)
+                                       break;
+                       }
+                       
+                       qsize = insize;
+                       while (psize > 0 || (qsize > 0 && q)) {
+                               if (!psize) {
+                                       e = q;
+                                       q = q->next;
+                                       qsize--;
+                                       if (q == oldhead)
+                                               q = NULL;
+                               } else if (!qsize || !q) {
+                                       e = p;
+                                       p = p->next;
+                                       psize--;
+                                       if (p == oldhead)
+                                               p = NULL;
+                               } else if (cmp(p, q) <= 0) {
+                                       e = p;
+                                       p = p->next;
+                                       psize--;
+                                       if (p == oldhead)
+                                               p = NULL;
+                               } else {
+                                       e = q;
+                                       q = q->next;
+                                       qsize--;
+                                       if (q == oldhead)
+                                               q = NULL;
+                               }
+                               if (tail)
+                                       tail->next = e;
+                               else
+                                       list = e;
+                               e->prev = tail;
+                               tail = e;
+                       }
+                       p = q;
+               }
+               
+               tail->next = list;
+               list->prev = tail;
+               
+               if (nmerges <= 1)
+                       break;
+               
+               insize *= 2;
+       }
+       
+       head->next = list;
+       head->prev = list->prev;
+       list->prev->next = head;
+       list->prev = head;
+}
+
+/**
+ * drm_mode_sort - sort mode list
+ * @mode_list: list to sort
+ *
+ * LOCKING:
+ * Caller must hold a lock protecting @mode_list.
+ *
+ * Sort @mode_list by favorability, putting good modes first.
+ */
+void drm_mode_sort(struct list_head *mode_list)
+{
+       list_sort(mode_list, drm_mode_compare);
+}
+
+
+/**
+ * drm_mode_output_list_update - update the mode list for the output
+ * @output: the output to update
+ *
+ * LOCKING:
+ * Caller must hold a lock protecting @mode_list.
+ *
+ * This moves the modes from the @output probed_modes list
+ * to the actual mode list. It compares the probed mode against the current
+ * list and only adds different modes. All modes unverified after this point
+ * will be removed by the prune invalid modes.
+ */
+void drm_mode_output_list_update(struct drm_output *output)
+{
+       struct drm_display_mode *mode;
+       struct drm_display_mode *pmode, *pt;
+       int found_it;
+       list_for_each_entry_safe(pmode, pt, &output->probed_modes,
+                                head) {
+               found_it = 0;
+               /* go through current modes checking for the new probed mode */
+               list_for_each_entry(mode, &output->modes, head) {
+                       if (drm_mode_equal(pmode, mode)) {
+                               found_it = 1;
+                               /* if equal delete the probed mode */
+                               mode->status = pmode->status;
+                               list_del(&pmode->head);
+                               kfree(pmode);
+                               break;
+                       }
+               }
+
+               if (!found_it) {
+                       list_move_tail(&pmode->head, &output->modes);
+               }
+       }
+}
index 0390603..a6d6c0d 100644 (file)
 
 #include "drmP.h"
 
-int drm_add_user_object(drm_file_t * priv, drm_user_object_t * item,
+int drm_add_user_object(struct drm_file * priv, struct drm_user_object * item,
                        int shareable)
 {
-       drm_device_t *dev = priv->head->dev;
+       struct drm_device *dev = priv->head->dev;
        int ret;
 
-       atomic_set(&item->refcount, 1);
+       DRM_ASSERT_LOCKED(&dev->struct_mutex);
+
+       /* The refcount will be bumped to 1 when we add the ref object below. */
+       atomic_set(&item->refcount, 0);
        item->shareable = shareable;
        item->owner = priv;
 
@@ -45,25 +48,31 @@ int drm_add_user_object(drm_file_t * priv, drm_user_object_t * item,
        if (ret)
                return ret;
 
-       list_add_tail(&item->list, &priv->user_objects);
-       return 0;
+       ret = drm_add_ref_object(priv, item, _DRM_REF_USE);
+       if (ret)
+               ret = drm_ht_remove_item(&dev->object_hash, &item->hash);
+
+       return ret;
 }
+EXPORT_SYMBOL(drm_add_user_object);
 
-drm_user_object_t *drm_lookup_user_object(drm_file_t * priv, uint32_t key)
+struct drm_user_object *drm_lookup_user_object(struct drm_file * priv, uint32_t key)
 {
-       drm_device_t *dev = priv->head->dev;
-       drm_hash_item_t *hash;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_hash_item *hash;
        int ret;
-       drm_user_object_t *item;
+       struct drm_user_object *item;
+
+       DRM_ASSERT_LOCKED(&dev->struct_mutex);
 
        ret = drm_ht_find_item(&dev->object_hash, key, &hash);
        if (ret) {
                return NULL;
        }
-       item = drm_hash_entry(hash, drm_user_object_t, hash);
+       item = drm_hash_entry(hash, struct drm_user_object, hash);
 
        if (priv != item->owner) {
-               drm_open_hash_t *ht = &priv->refd_object_hash[_DRM_REF_USE];
+               struct drm_open_hash *ht = &priv->refd_object_hash[_DRM_REF_USE];
                ret = drm_ht_find_item(ht, (unsigned long)item, &hash);
                if (ret) {
                        DRM_ERROR("Object not registered for usage\n");
@@ -72,35 +81,22 @@ drm_user_object_t *drm_lookup_user_object(drm_file_t * priv, uint32_t key)
        }
        return item;
 }
+EXPORT_SYMBOL(drm_lookup_user_object);
 
-static void drm_deref_user_object(drm_file_t * priv, drm_user_object_t * item)
+static void drm_deref_user_object(struct drm_file * priv, struct drm_user_object * item)
 {
-       drm_device_t *dev = priv->head->dev;
+       struct drm_device *dev = priv->head->dev;
        int ret;
 
        if (atomic_dec_and_test(&item->refcount)) {
                ret = drm_ht_remove_item(&dev->object_hash, &item->hash);
                BUG_ON(ret);
-               list_del_init(&item->list);
                item->remove(priv, item);
        }
 }
 
-int drm_remove_user_object(drm_file_t * priv, drm_user_object_t * item)
-{
-       if (item->owner != priv) {
-               DRM_ERROR("Cannot destroy object not owned by you.\n");
-               return -EINVAL;
-       }
-       item->owner = 0;
-       item->shareable = 0;
-       list_del_init(&item->list);
-       drm_deref_user_object(priv, item);
-       return 0;
-}
-
-static int drm_object_ref_action(drm_file_t * priv, drm_user_object_t * ro,
-                                drm_ref_t action)
+static int drm_object_ref_action(struct drm_file * priv, struct drm_user_object * ro,
+                                enum drm_ref_type action)
 {
        int ret = 0;
 
@@ -118,13 +114,14 @@ static int drm_object_ref_action(drm_file_t * priv, drm_user_object_t * ro,
        return ret;
 }
 
-int drm_add_ref_object(drm_file_t * priv, drm_user_object_t * referenced_object,
-                      drm_ref_t ref_action)
+int drm_add_ref_object(struct drm_file * priv, struct drm_user_object * referenced_object,
+                      enum drm_ref_type ref_action)
 {
        int ret = 0;
-       drm_ref_object_t *item;
-       drm_open_hash_t *ht = &priv->refd_object_hash[ref_action];
+       struct drm_ref_object *item;
+       struct drm_open_hash *ht = &priv->refd_object_hash[ref_action];
 
+       DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
        if (!referenced_object->shareable && priv != referenced_object->owner) {
                DRM_ERROR("Not allowed to reference this object\n");
                return -EINVAL;
@@ -174,45 +171,48 @@ int drm_add_ref_object(drm_file_t * priv, drm_user_object_t * referenced_object,
        return ret;
 }
 
-drm_ref_object_t *drm_lookup_ref_object(drm_file_t * priv,
-                                       drm_user_object_t * referenced_object,
-                                       drm_ref_t ref_action)
+struct drm_ref_object *drm_lookup_ref_object(struct drm_file * priv,
+                                       struct drm_user_object * referenced_object,
+                                       enum drm_ref_type ref_action)
 {
-       drm_hash_item_t *hash;
+       struct drm_hash_item *hash;
        int ret;
 
+       DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
        ret = drm_ht_find_item(&priv->refd_object_hash[ref_action],
                               (unsigned long)referenced_object, &hash);
        if (ret)
                return NULL;
 
-       return drm_hash_entry(hash, drm_ref_object_t, hash);
+       return drm_hash_entry(hash, struct drm_ref_object, hash);
 }
+EXPORT_SYMBOL(drm_lookup_ref_object);
 
-static void drm_remove_other_references(drm_file_t * priv,
-                                       drm_user_object_t * ro)
+static void drm_remove_other_references(struct drm_file * priv,
+                                       struct drm_user_object * ro)
 {
        int i;
-       drm_open_hash_t *ht;
-       drm_hash_item_t *hash;
-       drm_ref_object_t *item;
+       struct drm_open_hash *ht;
+       struct drm_hash_item *hash;
+       struct drm_ref_object *item;
 
        for (i = _DRM_REF_USE + 1; i < _DRM_NO_REF_TYPES; ++i) {
                ht = &priv->refd_object_hash[i];
                while (!drm_ht_find_item(ht, (unsigned long)ro, &hash)) {
-                       item = drm_hash_entry(hash, drm_ref_object_t, hash);
+                       item = drm_hash_entry(hash, struct drm_ref_object, hash);
                        drm_remove_ref_object(priv, item);
                }
        }
 }
 
-void drm_remove_ref_object(drm_file_t * priv, drm_ref_object_t * item)
+void drm_remove_ref_object(struct drm_file * priv, struct drm_ref_object * item)
 {
        int ret;
-       drm_user_object_t *user_object = (drm_user_object_t *) item->hash.key;
-       drm_open_hash_t *ht = &priv->refd_object_hash[item->unref_action];
-       drm_ref_t unref_action;
+       struct drm_user_object *user_object = (struct drm_user_object *) item->hash.key;
+       struct drm_open_hash *ht = &priv->refd_object_hash[item->unref_action];
+       enum drm_ref_type unref_action;
 
+       DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
        unref_action = item->unref_action;
        if (atomic_dec_and_test(&item->refcount)) {
                ret = drm_ht_remove_item(ht, &item->hash);
@@ -235,12 +235,12 @@ void drm_remove_ref_object(drm_file_t * priv, drm_ref_object_t * item)
 
 }
 
-int drm_user_object_ref(drm_file_t * priv, uint32_t user_token,
-                       drm_object_type_t type, drm_user_object_t ** object)
+int drm_user_object_ref(struct drm_file * priv, uint32_t user_token,
+                       enum drm_object_type type, struct drm_user_object ** object)
 {
-       drm_device_t *dev = priv->head->dev;
-       drm_user_object_t *uo;
-       drm_hash_item_t *hash;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_user_object *uo;
+       struct drm_hash_item *hash;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -249,7 +249,7 @@ int drm_user_object_ref(drm_file_t * priv, uint32_t user_token,
                DRM_ERROR("Could not find user object to reference.\n");
                goto out_err;
        }
-       uo = drm_hash_entry(hash, drm_user_object_t, hash);
+       uo = drm_hash_entry(hash, struct drm_user_object, hash);
        if (uo->type != type) {
                ret = -EINVAL;
                goto out_err;
@@ -265,12 +265,12 @@ int drm_user_object_ref(drm_file_t * priv, uint32_t user_token,
        return ret;
 }
 
-int drm_user_object_unref(drm_file_t * priv, uint32_t user_token,
-                         drm_object_type_t type)
+int drm_user_object_unref(struct drm_file * priv, uint32_t user_token,
+                         enum drm_object_type type)
 {
-       drm_device_t *dev = priv->head->dev;
-       drm_user_object_t *uo;
-       drm_ref_object_t *ro;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_user_object *uo;
+       struct drm_ref_object *ro;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
index 03ea927..ed9a87a 100644 (file)
@@ -32,6 +32,7 @@
 #define _DRM_OBJECTS_H
 
 struct drm_device;
+struct drm_bo_mem_reg;
 
 /***************************************************
  * User space objects. (drm_object.c)
@@ -39,14 +40,19 @@ struct drm_device;
 
 #define drm_user_object_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
 
-typedef enum {
+enum drm_object_type {
        drm_fence_type,
        drm_buffer_type,
-       drm_ttm_type
+       drm_lock_type,
            /*
             * Add other user space object types here.
             */
-} drm_object_type_t;
+       drm_driver_type0 = 256,
+       drm_driver_type1,
+       drm_driver_type2,
+       drm_driver_type3,
+       drm_driver_type4
+};
 
 /*
  * A user object is a structure that helps the drm give out user handles
@@ -55,20 +61,20 @@ typedef enum {
  * Designed to be accessible using a user space 32-bit handle.
  */
 
-typedef struct drm_user_object {
-       drm_hash_item_t hash;
+struct drm_user_object {
+       struct drm_hash_item hash;
        struct list_head list;
-       drm_object_type_t type;
+       enum drm_object_type type;
        atomic_t refcount;
        int shareable;
-       drm_file_t *owner;
-       void (*ref_struct_locked) (drm_file_t * priv,
+       struct drm_file *owner;
+       void (*ref_struct_locked) (struct drm_file * priv,
                                   struct drm_user_object * obj,
-                                  drm_ref_t ref_action);
-       void (*unref) (drm_file_t * priv, struct drm_user_object * obj,
-                      drm_ref_t unref_action);
-       void (*remove) (drm_file_t * priv, struct drm_user_object * obj);
-} drm_user_object_t;
+                                  enum drm_ref_type ref_action);
+       void (*unref) (struct drm_file * priv, struct drm_user_object * obj,
+                      enum drm_ref_type unref_action);
+       void (*remove) (struct drm_file * priv, struct drm_user_object * obj);
+};
 
 /*
  * A ref object is a structure which is used to
@@ -77,50 +83,41 @@ typedef struct drm_user_object {
  * process exits. Designed to be accessible using a pointer to the _user_ object.
  */
 
-typedef struct drm_ref_object {
-       drm_hash_item_t hash;
+struct drm_ref_object {
+       struct drm_hash_item hash;
        struct list_head list;
        atomic_t refcount;
-       drm_ref_t unref_action;
-} drm_ref_object_t;
+       enum drm_ref_type unref_action;
+};
 
 /**
  * Must be called with the struct_mutex held.
  */
 
-extern int drm_add_user_object(drm_file_t * priv, drm_user_object_t * item,
+extern int drm_add_user_object(struct drm_file * priv, struct drm_user_object * item,
                               int shareable);
 /**
  * Must be called with the struct_mutex held.
  */
 
-extern drm_user_object_t *drm_lookup_user_object(drm_file_t * priv,
+extern struct drm_user_object *drm_lookup_user_object(struct drm_file * priv,
                                                 uint32_t key);
 
 /*
- * Must be called with the struct_mutex held.
- * If "item" has been obtained by a call to drm_lookup_user_object. You may not
- * release the struct_mutex before calling drm_remove_ref_object.
- * This function may temporarily release the struct_mutex.
- */
-
-extern int drm_remove_user_object(drm_file_t * priv, drm_user_object_t * item);
-
-/*
  * Must be called with the struct_mutex held. May temporarily release it.
  */
 
-extern int drm_add_ref_object(drm_file_t * priv,
-                             drm_user_object_t * referenced_object,
-                             drm_ref_t ref_action);
+extern int drm_add_ref_object(struct drm_file * priv,
+                             struct drm_user_object * referenced_object,
+                             enum drm_ref_type ref_action);
 
 /*
  * Must be called with the struct_mutex held.
  */
 
-drm_ref_object_t *drm_lookup_ref_object(drm_file_t * priv,
-                                       drm_user_object_t * referenced_object,
-                                       drm_ref_t ref_action);
+struct drm_ref_object *drm_lookup_ref_object(struct drm_file * priv,
+                                       struct drm_user_object * referenced_object,
+                                       enum drm_ref_type ref_action);
 /*
  * Must be called with the struct_mutex held.
  * If "item" has been obtained by a call to drm_lookup_ref_object. You may not
@@ -128,19 +125,20 @@ drm_ref_object_t *drm_lookup_ref_object(drm_file_t * priv,
  * This function may temporarily release the struct_mutex.
  */
 
-extern void drm_remove_ref_object(drm_file_t * priv, drm_ref_object_t * item);
-extern int drm_user_object_ref(drm_file_t * priv, uint32_t user_token,
-                              drm_object_type_t type,
-                              drm_user_object_t ** object);
-extern int drm_user_object_unref(drm_file_t * priv, uint32_t user_token,
-                                drm_object_type_t type);
+extern void drm_remove_ref_object(struct drm_file * priv, struct drm_ref_object * item);
+extern int drm_user_object_ref(struct drm_file * priv, uint32_t user_token,
+                              enum drm_object_type type,
+                              struct drm_user_object ** object);
+extern int drm_user_object_unref(struct drm_file * priv, uint32_t user_token,
+                                enum drm_object_type type);
 
 /***************************************************
  * Fence objects. (drm_fence.c)
  */
 
-typedef struct drm_fence_object {
-       drm_user_object_t base;
+struct drm_fence_object {
+       struct drm_user_object base;
+        struct drm_device *dev;
        atomic_t usage;
 
        /*
@@ -148,71 +146,95 @@ typedef struct drm_fence_object {
         */
 
        struct list_head ring;
-       int class;
+       int fence_class;
        uint32_t native_type;
        uint32_t type;
        uint32_t signaled;
        uint32_t sequence;
        uint32_t flush_mask;
        uint32_t submitted_flush;
-} drm_fence_object_t;
+        uint32_t error;
+};
 
 #define _DRM_FENCE_CLASSES 8
 #define _DRM_FENCE_TYPE_EXE 0x00
 
-typedef struct drm_fence_class_manager {
+struct drm_fence_class_manager {
        struct list_head ring;
        uint32_t pending_flush;
        wait_queue_head_t fence_queue;
        int pending_exe_flush;
        uint32_t last_exe_flush;
        uint32_t exe_flush_sequence;
-} drm_fence_class_manager_t;
+};
 
-typedef struct drm_fence_manager {
+struct drm_fence_manager {
        int initialized;
        rwlock_t lock;
-       drm_fence_class_manager_t class[_DRM_FENCE_CLASSES];
+       struct drm_fence_class_manager fence_class[_DRM_FENCE_CLASSES];
        uint32_t num_classes;
        atomic_t count;
-} drm_fence_manager_t;
+};
 
-typedef struct drm_fence_driver {
+struct drm_fence_driver {
        uint32_t num_classes;
        uint32_t wrap_diff;
        uint32_t flush_diff;
        uint32_t sequence_mask;
        int lazy_capable;
-       int (*has_irq) (struct drm_device * dev, uint32_t class,
+       int (*has_irq) (struct drm_device * dev, uint32_t fence_class,
                        uint32_t flags);
-       int (*emit) (struct drm_device * dev, uint32_t class, uint32_t flags,
+       int (*emit) (struct drm_device * dev, uint32_t fence_class, uint32_t flags,
                     uint32_t * breadcrumb, uint32_t * native_type);
-       void (*poke_flush) (struct drm_device * dev, uint32_t class);
-} drm_fence_driver_t;
+       void (*poke_flush) (struct drm_device * dev, uint32_t fence_class);
+};
 
-extern void drm_fence_handler(struct drm_device *dev, uint32_t class,
-                             uint32_t sequence, uint32_t type);
+extern void drm_fence_handler(struct drm_device *dev, uint32_t fence_class,
+                             uint32_t sequence, uint32_t type, uint32_t error);
 extern void drm_fence_manager_init(struct drm_device *dev);
 extern void drm_fence_manager_takedown(struct drm_device *dev);
-extern void drm_fence_flush_old(struct drm_device *dev, uint32_t class,
+extern void drm_fence_flush_old(struct drm_device *dev, uint32_t fence_class,
                                uint32_t sequence);
-extern int drm_fence_object_flush(struct drm_device *dev,
-                                 drm_fence_object_t * fence, uint32_t type);
-extern int drm_fence_object_signaled(drm_fence_object_t * fence, uint32_t type);
-extern void drm_fence_usage_deref_locked(struct drm_device *dev,
-                                        drm_fence_object_t * fence);
-extern void drm_fence_usage_deref_unlocked(struct drm_device *dev,
-                                          drm_fence_object_t * fence);
-extern int drm_fence_object_wait(struct drm_device *dev,
-                                drm_fence_object_t * fence,
+extern int drm_fence_object_flush(struct drm_fence_object * fence, uint32_t type);
+extern int drm_fence_object_signaled(struct drm_fence_object * fence,
+                                    uint32_t type, int flush);
+extern void drm_fence_usage_deref_locked(struct drm_fence_object ** fence);
+extern void drm_fence_usage_deref_unlocked(struct drm_fence_object ** fence);
+extern struct drm_fence_object *drm_fence_reference_locked(struct drm_fence_object *src);
+extern void drm_fence_reference_unlocked(struct drm_fence_object **dst,
+                                        struct drm_fence_object *src);
+extern int drm_fence_object_wait(struct drm_fence_object * fence,
                                 int lazy, int ignore_signals, uint32_t mask);
 extern int drm_fence_object_create(struct drm_device *dev, uint32_t type,
-                                  uint32_t fence_flags, uint32_t class,
-                                  drm_fence_object_t ** c_fence);
-extern int drm_fence_add_user_object(drm_file_t * priv,
-                                    drm_fence_object_t * fence, int shareable);
-extern int drm_fence_ioctl(DRM_IOCTL_ARGS);
-
+                                  uint32_t fence_flags, uint32_t fence_class,
+                                  struct drm_fence_object ** c_fence);
+extern int drm_fence_object_emit(struct drm_fence_object * fence,
+                                uint32_t fence_flags, uint32_t class,
+                                uint32_t type);
+extern void drm_fence_fill_arg(struct drm_fence_object *fence,
+                              struct drm_fence_arg *arg);
+
+extern int drm_fence_add_user_object(struct drm_file * priv,
+                                    struct drm_fence_object * fence, int shareable);
+
+extern int drm_fence_create_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv);
+extern int drm_fence_destroy_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv);
+extern int drm_fence_reference_ioctl(struct drm_device *dev, void *data,
+                                    struct drm_file *file_priv);
+extern int drm_fence_unreference_ioctl(struct drm_device *dev, void *data,
+                                      struct drm_file *file_priv);
+extern int drm_fence_signaled_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern int drm_fence_flush_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern int drm_fence_wait_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int drm_fence_emit_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int drm_fence_buffers_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv);
 /**************************************************
  *TTMs
  */
@@ -234,34 +256,33 @@ extern int drm_fence_ioctl(DRM_IOCTL_ARGS);
 #define DRM_BE_FLAG_BOUND_CACHED   0x00000002
 
 struct drm_ttm_backend;
-typedef struct drm_ttm_backend_func {
+struct drm_ttm_backend_func {
        int (*needs_ub_cache_adjust) (struct drm_ttm_backend * backend);
        int (*populate) (struct drm_ttm_backend * backend,
                         unsigned long num_pages, struct page ** pages);
        void (*clear) (struct drm_ttm_backend * backend);
        int (*bind) (struct drm_ttm_backend * backend,
-                    unsigned long offset, int cached);
+                    struct drm_bo_mem_reg * bo_mem);
        int (*unbind) (struct drm_ttm_backend * backend);
        void (*destroy) (struct drm_ttm_backend * backend);
-} drm_ttm_backend_func_t;
+};
 
 
 typedef struct drm_ttm_backend {
-       uint32_t flags;
-       int mem_type;
-       drm_ttm_backend_func_t *func;
+        struct drm_device *dev;
+        uint32_t flags;
+        struct drm_ttm_backend_func *func;
 } drm_ttm_backend_t;
 
-typedef struct drm_ttm {
+struct drm_ttm {
        struct page **pages;
        uint32_t page_flags;
        unsigned long num_pages;
-       unsigned long aper_offset;
        atomic_t vma_count;
        struct drm_device *dev;
        int destroy;
        uint32_t mapping_offset;
-       drm_ttm_backend_t *be;
+       struct drm_ttm_backend *be;
        enum {
                ttm_bound,
                ttm_evicted,
@@ -269,14 +290,16 @@ typedef struct drm_ttm {
                ttm_unpopulated,
        } state;
 
-} drm_ttm_t;
+};
 
-extern drm_ttm_t *drm_ttm_init(struct drm_device *dev, unsigned long size);
-extern int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset);
-extern void drm_ttm_unbind(drm_ttm_t * ttm);
-extern void drm_ttm_evict(drm_ttm_t * ttm);
-extern void drm_ttm_fixup_caching(drm_ttm_t * ttm);
-extern struct page *drm_ttm_get_page(drm_ttm_t * ttm, int index);
+extern struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size);
+extern int drm_bind_ttm(struct drm_ttm * ttm, struct drm_bo_mem_reg *bo_mem);
+extern void drm_ttm_unbind(struct drm_ttm * ttm);
+extern void drm_ttm_evict(struct drm_ttm * ttm);
+extern void drm_ttm_fixup_caching(struct drm_ttm * ttm);
+extern struct page *drm_ttm_get_page(struct drm_ttm * ttm, int index);
+extern void drm_ttm_cache_flush(void);
+extern int drm_ttm_populate(struct drm_ttm * ttm);
 
 /*
  * Destroy a ttm. The user normally calls drmRmMap or a similar IOCTL to do this,
@@ -284,7 +307,7 @@ extern struct page *drm_ttm_get_page(drm_ttm_t * ttm, int index);
  * when the last vma exits.
  */
 
-extern int drm_destroy_ttm(drm_ttm_t * ttm);
+extern int drm_destroy_ttm(struct drm_ttm * ttm);
 
 #define DRM_FLAG_MASKED(_old, _new, _mask) {\
 (_old) ^= (((_old) ^ (_new)) & (_mask)); \
@@ -307,19 +330,27 @@ extern int drm_destroy_ttm(drm_ttm_t * ttm);
  * Buffer objects. (drm_bo.c, drm_bo_move.c)
  */
 
-typedef struct drm_bo_mem_reg {
-       drm_mm_node_t *mm_node;
+struct drm_bo_mem_reg {
+       struct drm_mm_node *mm_node;
        unsigned long size;
        unsigned long num_pages;
        uint32_t page_alignment;
        uint32_t mem_type;
-       uint32_t flags;
-       uint32_t mask;
-} drm_bo_mem_reg_t;
-
-typedef struct drm_buffer_object {
+       uint64_t flags;
+       uint64_t mask;
+        uint32_t desired_tile_stride;
+        uint32_t hw_tile_stride;
+};
+
+enum drm_bo_type {
+       drm_bo_type_dc,
+       drm_bo_type_user,
+       drm_bo_type_kernel, /* for initial kernel allocations */
+};
+
+struct drm_buffer_object {
        struct drm_device *dev;
-       drm_user_object_t base;
+       struct drm_user_object base;
 
        /*
         * If there is a possibility that the usage variable is zero,
@@ -328,30 +359,32 @@ typedef struct drm_buffer_object {
 
        atomic_t usage;
        unsigned long buffer_start;
-       drm_bo_type_t type;
+       enum drm_bo_type type;
        unsigned long offset;
        atomic_t mapped;
-       drm_bo_mem_reg_t mem;
+       struct drm_bo_mem_reg mem;
 
        struct list_head lru;
        struct list_head ddestroy;
 
        uint32_t fence_type;
        uint32_t fence_class;
-       drm_fence_object_t *fence;
+        uint32_t new_fence_type;
+        uint32_t new_fence_class;
+       struct drm_fence_object *fence;
        uint32_t priv_flags;
        wait_queue_head_t event_queue;
        struct mutex mutex;
+       unsigned long num_pages;
 
        /* For pinned buffers */
-       drm_mm_node_t *pinned_node;
+       struct drm_mm_node *pinned_node;
        uint32_t pinned_mem_type;
        struct list_head pinned_lru;
 
        /* For vm */
-
-       drm_ttm_t *ttm;
-       drm_map_list_t map_list;
+       struct drm_ttm *ttm;
+       struct drm_map_list map_list;
        uint32_t memory_type;
        unsigned long bus_offset;
        uint32_t vm_flags;
@@ -363,23 +396,31 @@ typedef struct drm_buffer_object {
        struct list_head p_mm_list;
 #endif
 
-} drm_buffer_object_t;
+};
 
 #define _DRM_BO_FLAG_UNFENCED 0x00000001
 #define _DRM_BO_FLAG_EVICTED  0x00000002
 
-typedef struct drm_mem_type_manager {
+struct drm_mem_type_manager {
        int has_type;
        int use_type;
-       drm_mm_t manager;
+       struct drm_mm manager;
        struct list_head lru;
        struct list_head pinned;
        uint32_t flags;
        uint32_t drm_bus_maptype;
+        unsigned long gpu_offset;
        unsigned long io_offset;
        unsigned long io_size;
        void *io_addr;
-} drm_mem_type_manager_t;
+};
+
+struct drm_bo_lock {
+       struct drm_user_object base;
+       wait_queue_head_t queue;
+       atomic_t write_lock_pending;
+       atomic_t readers;
+};
 
 #define _DRM_FLAG_MEMTYPE_FIXED     0x00000001 /* Fixed (on-card) PCI memory */
 #define _DRM_FLAG_MEMTYPE_MAPPABLE  0x00000002 /* Memory mappable */
@@ -389,13 +430,13 @@ typedef struct drm_mem_type_manager {
 #define _DRM_FLAG_MEMTYPE_CMA       0x00000010 /* Can't map aperture */
 #define _DRM_FLAG_MEMTYPE_CSELECT   0x00000020 /* Select caching */
 
-typedef struct drm_buffer_manager {
-       struct mutex init_mutex;
-       struct mutex evict_mutex;
+struct drm_buffer_manager {
+        struct drm_bo_lock bm_lock;
+        struct mutex evict_mutex;
        int nice_mode;
        int initialized;
-       drm_file_t *last_to_validate;
-       drm_mem_type_manager_t man[DRM_BO_MEM_TYPES];
+       struct drm_file *last_to_validate;
+       struct drm_mem_type_manager man[DRM_BO_MEM_TYPES];
        struct list_head unfenced;
        struct list_head ddestroy;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
@@ -406,69 +447,196 @@ typedef struct drm_buffer_manager {
        uint32_t fence_type;
        unsigned long cur_pages;
        atomic_t count;
-} drm_buffer_manager_t;
+};
 
-typedef struct drm_bo_driver {
+struct drm_bo_driver {
        const uint32_t *mem_type_prio;
        const uint32_t *mem_busy_prio;
        uint32_t num_mem_type_prio;
        uint32_t num_mem_busy_prio;
-       drm_ttm_backend_t *(*create_ttm_backend_entry)
+       struct drm_ttm_backend *(*create_ttm_backend_entry)
         (struct drm_device * dev);
-       int (*fence_type) (struct drm_buffer_object *bo, uint32_t * class, uint32_t * type);
-       int (*invalidate_caches) (struct drm_device * dev, uint32_t flags);
+       int (*fence_type) (struct drm_buffer_object *bo, uint32_t *fclass,
+                    uint32_t * type);
+       int (*invalidate_caches) (struct drm_device * dev, uint64_t flags);
        int (*init_mem_type) (struct drm_device * dev, uint32_t type,
-                             drm_mem_type_manager_t * man);
+                             struct drm_mem_type_manager * man);
         uint32_t(*evict_mask) (struct drm_buffer_object *bo);
        int (*move) (struct drm_buffer_object * bo,
                     int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
-} drm_bo_driver_t;
+};
 
 /*
  * buffer objects (drm_bo.c)
  */
-
-extern int drm_bo_ioctl(DRM_IOCTL_ARGS);
-extern int drm_mm_init_ioctl(DRM_IOCTL_ARGS);
+extern int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, int pin);
+extern int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_setstatus_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int drm_bo_version_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
 extern int drm_bo_driver_finish(struct drm_device *dev);
 extern int drm_bo_driver_init(struct drm_device *dev);
 extern int drm_bo_pci_offset(struct drm_device *dev,
-                            drm_bo_mem_reg_t * mem,
+                            struct drm_bo_mem_reg * mem,
                             unsigned long *bus_base,
                             unsigned long *bus_offset,
                             unsigned long *bus_size);
-extern int drm_mem_reg_is_pci(struct drm_device *dev, drm_bo_mem_reg_t * mem);
+extern int drm_mem_reg_is_pci(struct drm_device *dev, struct drm_bo_mem_reg * mem);
 
-extern void drm_bo_usage_deref_locked(drm_buffer_object_t * bo);
-extern int drm_fence_buffer_objects(drm_file_t * priv,
+extern void drm_bo_usage_deref_locked(struct drm_buffer_object ** bo);
+extern void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo);
+extern void drm_putback_buffer_objects(struct drm_device *dev);
+extern int drm_fence_buffer_objects(struct drm_device * dev,
                                    struct list_head *list,
                                    uint32_t fence_flags,
-                                   drm_fence_object_t * fence,
-                                   drm_fence_object_t ** used_fence);
-extern void drm_bo_add_to_lru(drm_buffer_object_t * bo);
-extern int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
+                                   struct drm_fence_object * fence,
+                                   struct drm_fence_object ** used_fence);
+extern void drm_bo_add_to_lru(struct drm_buffer_object * bo);
+extern int drm_buffer_object_create(struct drm_device *dev, unsigned long size,
+                                   enum drm_bo_type type, uint64_t mask,
+                                   uint32_t hint, uint32_t page_alignment,
+                                   unsigned long buffer_start,
+                                   struct drm_buffer_object **bo);
+extern int drm_bo_wait(struct drm_buffer_object * bo, int lazy, int ignore_signals,
                       int no_wait);
-extern int drm_bo_mem_space(drm_buffer_object_t * bo,
-                           drm_bo_mem_reg_t * mem, int no_wait);
-extern int drm_bo_move_buffer(drm_buffer_object_t * bo, uint32_t new_mem_flags,
+extern int drm_bo_mem_space(struct drm_buffer_object * bo,
+                           struct drm_bo_mem_reg * mem, int no_wait);
+extern int drm_bo_move_buffer(struct drm_buffer_object * bo,
+                             uint64_t new_mem_flags,
                              int no_wait, int move_unfenced);
+extern int drm_bo_clean_mm(struct drm_device * dev, unsigned mem_type);
+extern int drm_bo_init_mm(struct drm_device * dev, unsigned type,
+                         unsigned long p_offset, unsigned long p_size);
+extern int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle,
+                                 uint32_t fence_class, uint64_t flags,
+                                 uint64_t mask, uint32_t hint,
+                                 int use_old_fence_class,
+                                 struct drm_bo_info_rep * rep,
+                                 struct drm_buffer_object **bo_rep);
+extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file * file_priv,
+                                                         uint32_t handle,
+                                                         int check_owner);
+extern int drm_bo_do_validate(struct drm_buffer_object *bo,
+                             uint64_t flags, uint64_t mask, uint32_t hint,
+                             uint32_t fence_class,
+                             int no_wait,
+                             struct drm_bo_info_rep *rep);
 
 /*
- * Buffer object memory move helpers.
+ * Buffer object memory move- and map helpers.
  * drm_bo_move.c
  */
 
-extern int drm_bo_move_ttm(drm_buffer_object_t * bo,
-                          int evict, int no_wait, drm_bo_mem_reg_t * new_mem);
-extern int drm_bo_move_memcpy(drm_buffer_object_t * bo,
+extern int drm_bo_move_ttm(struct drm_buffer_object * bo,
+                          int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
+extern int drm_bo_move_memcpy(struct drm_buffer_object * bo,
                              int evict,
-                             int no_wait, drm_bo_mem_reg_t * new_mem);
-extern int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
+                             int no_wait, struct drm_bo_mem_reg * new_mem);
+extern int drm_bo_move_accel_cleanup(struct drm_buffer_object * bo,
                                     int evict,
                                     int no_wait,
                                     uint32_t fence_class,
                                     uint32_t fence_type,
                                     uint32_t fence_flags,
-                                    drm_bo_mem_reg_t * new_mem);
+                                    struct drm_bo_mem_reg * new_mem);
+extern int drm_bo_same_page(unsigned long offset, unsigned long offset2);
+extern unsigned long drm_bo_offset_end(unsigned long offset,
+                                      unsigned long end);
+
+struct drm_bo_kmap_obj {
+       void *virtual;
+       struct page *page;
+       enum {
+               bo_map_iomap,
+               bo_map_vmap,
+               bo_map_kmap,
+               bo_map_premapped,
+       } bo_kmap_type;
+};
+
+static inline void *drm_bmo_virtual(struct drm_bo_kmap_obj *map, int *is_iomem)
+{
+       *is_iomem = (map->bo_kmap_type == bo_map_iomap ||
+                    map->bo_kmap_type == bo_map_premapped);
+       return map->virtual;
+}
+extern void drm_bo_kunmap(struct drm_bo_kmap_obj *map);
+extern int drm_bo_kmap(struct drm_buffer_object *bo, unsigned long start_page,
+                      unsigned long num_pages, struct drm_bo_kmap_obj *map);
 
+
+/*
+ * drm_regman.c
+ */
+
+struct drm_reg {
+       struct list_head head;
+       struct drm_fence_object *fence;
+       uint32_t fence_type;
+       uint32_t new_fence_type;
+};
+
+struct drm_reg_manager {
+       struct list_head free;
+       struct list_head lru;
+       struct list_head unfenced;
+
+       int (*reg_reusable)(const struct drm_reg *reg, const void *data);
+       void (*reg_destroy)(struct drm_reg *reg);
+};
+
+extern int drm_regs_alloc(struct drm_reg_manager *manager,
+                         const void *data,
+                         uint32_t fence_class,
+                         uint32_t fence_type,
+                         int interruptible,
+                         int no_wait,
+                         struct drm_reg **reg);
+
+extern void drm_regs_fence(struct drm_reg_manager *regs,
+                          struct drm_fence_object *fence);
+
+extern void drm_regs_free(struct drm_reg_manager *manager);
+extern void drm_regs_add(struct drm_reg_manager *manager, struct drm_reg *reg);
+extern void drm_regs_init(struct drm_reg_manager *manager,
+                         int (*reg_reusable)(const struct drm_reg *,
+                                             const void *),
+                         void (*reg_destroy)(struct drm_reg *));
+
+extern int drm_mem_reg_ioremap(struct drm_device *dev, struct drm_bo_mem_reg * mem,
+                              void **virtual);
+extern void drm_mem_reg_iounmap(struct drm_device *dev, struct drm_bo_mem_reg * mem,
+                               void *virtual);
+/*
+ * drm_bo_lock.c 
+ * Simple replacement for the hardware lock on buffer manager init and clean.
+ */
+
+
+extern void drm_bo_init_lock(struct drm_bo_lock *lock);
+extern void drm_bo_read_unlock(struct drm_bo_lock *lock);
+extern int drm_bo_read_lock(struct drm_bo_lock *lock);
+extern int drm_bo_write_lock(struct drm_bo_lock *lock, 
+                            struct drm_file *file_priv);
+
+extern int drm_bo_write_unlock(struct drm_bo_lock *lock, 
+                              struct drm_file *file_priv);
+
+#ifdef CONFIG_DEBUG_MUTEXES
+#define DRM_ASSERT_LOCKED(_mutex)                                      \
+       BUG_ON(!mutex_is_locked(_mutex) ||                              \
+              ((_mutex)->owner != current_thread_info()))
+#else
+#define DRM_ASSERT_LOCKED(_mutex)
+#endif
 #endif
index 2ea105c..2688479 100644 (file)
@@ -6,11 +6,6 @@
 #include <linux/interrupt.h>   /* For task queue support */
 #include <linux/delay.h>
 
-/** File pointer type */
-#define DRMFILE                         struct file *
-/** Ioctl arguments */
-#define DRM_IOCTL_ARGS                 struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data
-#define DRM_ERR(d)                     -(d)
 /** Current process ID */
 #define DRM_CURRENTPID                 current->pid
 #define DRM_SUSER(p)                   capable(CAP_SYS_ADMIN)
@@ -51,9 +46,6 @@
 #define DRM_WRITEMEMORYBARRIER()       wmb()
 /** Read/write memory barrier */
 #define DRM_MEMORYBARRIER()            mb()
-/** DRM device local declaration */
-#define DRM_DEVICE     drm_file_t      *priv   = filp->private_data; \
-                       drm_device_t    *dev    = priv->head->dev
 
 /** IRQ handler arguments and return type and values */
 #define DRM_IRQ_ARGS           int irq, void *arg
@@ -93,14 +85,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
 #define MTRR_TYPE_WRCOMB     1
 #endif
 
-/** For data going into the kernel through the ioctl argument */
-#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3)     \
-       if ( copy_from_user(&arg1, arg2, arg3) )        \
-               return -EFAULT
-/** For data going from the kernel through the ioctl argument */
-#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3)       \
-       if ( copy_to_user(arg1, &arg2, arg3) )          \
-               return -EFAULT
 /** Other copying of data to kernel space */
 #define DRM_COPY_FROM_USER(arg1, arg2, arg3)           \
        copy_from_user(arg1, arg2, arg3)
@@ -117,8 +101,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
 #define DRM_GET_USER_UNCHECKED(val, uaddr)             \
        __get_user(val, uaddr)
 
-#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
-
 #define DRM_HZ HZ
 
 #define DRM_WAIT_ON( ret, queue, timeout, condition )          \
index 7625220..a608eed 100644 (file)
@@ -47,7 +47,7 @@
 /**
  * \brief Allocate a PCI consistent memory block, for DMA.
  */
-drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
                                dma_addr_t maxaddr)
 {
        drm_dma_handle_t *dmah;
@@ -123,7 +123,7 @@ EXPORT_SYMBOL(drm_pci_alloc);
  *
  * This function is for internal use in the Linux-specific DRM core code.
  */
-void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
+void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t *dmah)
 {
        unsigned long addr;
        size_t sz;
@@ -167,7 +167,7 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
 /**
  * \brief Free a PCI consistent memory block
  */
-void drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
+void drm_pci_free(struct drm_device * dev, drm_dma_handle_t *dmah)
 {
        __drm_pci_free(dev, dmah);
        kfree(dmah);
index e93a040..08bf99d 100644 (file)
@@ -90,7 +90,7 @@ static struct drm_proc_list {
  * "/proc/dri/%minor%/", and each entry in proc_list as
  * "/proc/dri/%minor%/%name%".
  */
-int drm_proc_init(drm_device_t * dev, int minor,
+int drm_proc_init(struct drm_device * dev, int minor,
                  struct proc_dir_entry *root, struct proc_dir_entry **dev_root)
 {
        struct proc_dir_entry *ent;
@@ -165,7 +165,7 @@ int drm_proc_cleanup(int minor, struct proc_dir_entry *root,
 static int drm_name_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int len = 0;
 
        if (offset > DRM_PROC_LIMIT) {
@@ -207,10 +207,10 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
 static int drm__vm_info(char *buf, char **start, off_t offset, int request,
                        int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int len = 0;
-       drm_map_t *map;
-       drm_map_list_t *r_list;
+       struct drm_map *map;
+       struct drm_map_list *r_list;
 
        /* Hardcoded from _DRM_FRAME_BUFFER,
           _DRM_REGISTERS, _DRM_SHM, _DRM_AGP,
@@ -264,7 +264,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
                       int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -287,10 +287,10 @@ static int drm_vm_info(char *buf, char **start, off_t offset, int request,
 static int drm__queues_info(char *buf, char **start, off_t offset,
                            int request, int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int len = 0;
        int i;
-       drm_queue_t *q;
+       struct drm_queue *q;
 
        if (offset > DRM_PROC_LIMIT) {
                *eof = 1;
@@ -337,7 +337,7 @@ static int drm__queues_info(char *buf, char **start, off_t offset,
 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
                           int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -360,9 +360,9 @@ static int drm_queues_info(char *buf, char **start, off_t offset, int request,
 static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
                          int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int len = 0;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int i;
 
        if (!dma || offset > DRM_PROC_LIMIT) {
@@ -409,7 +409,7 @@ static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -432,13 +432,13 @@ static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
 static int drm__objects_info(char *buf, char **start, off_t offset, int request,
                          int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int len = 0;
-       drm_buffer_manager_t *bm = &dev->bm;
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_u64_t used_mem;
-       drm_u64_t low_mem;
-       drm_u64_t high_mem;
+       struct drm_buffer_manager *bm = &dev->bm;
+       struct drm_fence_manager *fm = &dev->fm;
+       uint64_t used_mem;
+       uint64_t low_mem;
+       uint64_t high_mem;
 
 
        if (offset > DRM_PROC_LIMIT) {
@@ -496,7 +496,7 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
 static int drm_objects_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -519,9 +519,9 @@ static int drm_objects_info(char *buf, char **start, off_t offset, int request,
 static int drm__clients_info(char *buf, char **start, off_t offset,
                             int request, int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int len = 0;
-       drm_file_t *priv;
+       struct drm_file *priv;
 
        if (offset > DRM_PROC_LIMIT) {
                *eof = 1;
@@ -552,7 +552,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
 static int drm_clients_info(char *buf, char **start, off_t offset,
                            int request, int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -566,9 +566,9 @@ static int drm_clients_info(char *buf, char **start, off_t offset,
 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int len = 0;
-       drm_vma_entry_t *pt;
+       struct drm_vma_entry *pt;
        struct vm_area_struct *vma;
 #if defined(__i386__)
        unsigned int pgprot;
@@ -625,7 +625,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
 static int drm_vma_info(char *buf, char **start, off_t offset, int request,
                        int *eof, void *data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
index e5c9f87..3c0f672 100644 (file)
@@ -36,7 +36,7 @@
 
 #define DEBUG_SCATTER 0
 
-void drm_sg_cleanup(drm_sg_mem_t * entry)
+void drm_sg_cleanup(struct drm_sg_mem *entry)
 {
        struct page *page;
        int i;
@@ -55,6 +55,7 @@ void drm_sg_cleanup(drm_sg_mem_t * entry)
                 entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
        drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
 }
+EXPORT_SYMBOL(drm_sg_cleanup);
 
 #ifdef _LP64
 # define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
@@ -62,14 +63,9 @@ void drm_sg_cleanup(drm_sg_mem_t * entry)
 # define ScatterHandle(x) (unsigned int)(x)
 #endif
 
-int drm_sg_alloc(struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_scatter_gather_t __user *argp = (void __user *)arg;
-       drm_scatter_gather_t request;
-       drm_sg_mem_t *entry;
+       struct drm_sg_mem *entry;
        unsigned long pages, i, j;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
@@ -80,17 +76,13 @@ int drm_sg_alloc(struct inode *inode, struct file *filp,
        if (dev->sg)
                return -EINVAL;
 
-       if (copy_from_user(&request, argp, sizeof(request)))
-               return -EFAULT;
-
        entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
        if (!entry)
                return -ENOMEM;
 
        memset(entry, 0, sizeof(*entry));
-
-       pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
-       DRM_DEBUG("sg size=%ld pages=%ld\n", request.size, pages);
+       pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
+       DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages);
 
        entry->pages = pages;
        entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
@@ -142,12 +134,7 @@ int drm_sg_alloc(struct inode *inode, struct file *filp,
                SetPageReserved(entry->pagelist[j]);
        }
 
-       request.handle = entry->handle;
-
-       if (copy_to_user(argp, &request, sizeof(request))) {
-               drm_sg_cleanup(entry);
-               return -EFAULT;
-       }
+       request->handle = entry->handle;
 
        dev->sg = entry;
 
@@ -196,28 +183,32 @@ int drm_sg_alloc(struct inode *inode, struct file *filp,
       failed:
        drm_sg_cleanup(entry);
        return -ENOMEM;
+
 }
+EXPORT_SYMBOL(drm_sg_alloc);
 
-int drm_sg_free(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_scatter_gather_t request;
-       drm_sg_mem_t *entry;
+       struct drm_scatter_gather *request = data;
+
+       return drm_sg_alloc(dev, request);
+
+}
+
+int drm_sg_free(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
+{
+       struct drm_scatter_gather *request = data;
+       struct drm_sg_mem *entry;
 
        if (!drm_core_check_feature(dev, DRIVER_SG))
                return -EINVAL;
 
-       if (copy_from_user(&request,
-                          (drm_scatter_gather_t __user *) arg,
-                          sizeof(request)))
-               return -EFAULT;
-
        entry = dev->sg;
        dev->sg = NULL;
 
-       if (!entry || entry->handle != request.handle)
+       if (!entry || entry->handle != request->handle)
                return -EINVAL;
 
        DRM_DEBUG("sg free virtual  = %p\n", entry->virtual);
index e15db6d..118e82a 100644 (file)
 
 #include "drm_sman.h"
 
-typedef struct drm_owner_item {
-       drm_hash_item_t owner_hash;
+struct drm_owner_item {
+       struct drm_hash_item owner_hash;
        struct list_head sman_list;
        struct list_head mem_blocks;
-} drm_owner_item_t;
+};
 
-void drm_sman_takedown(drm_sman_t * sman)
+void drm_sman_takedown(struct drm_sman * sman)
 {
        drm_ht_remove(&sman->user_hash_tab);
        drm_ht_remove(&sman->owner_hash_tab);
@@ -56,12 +56,12 @@ void drm_sman_takedown(drm_sman_t * sman)
 EXPORT_SYMBOL(drm_sman_takedown);
 
 int
-drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
              unsigned int user_order, unsigned int owner_order)
 {
        int ret = 0;
 
-       sman->mm = (drm_sman_mm_t *) drm_calloc(num_managers, sizeof(*sman->mm),
+       sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
                                                DRM_MEM_MM);
        if (!sman->mm) {
                ret = -ENOMEM;
@@ -88,8 +88,8 @@ EXPORT_SYMBOL(drm_sman_init);
 static void *drm_sman_mm_allocate(void *private, unsigned long size,
                                  unsigned alignment)
 {
-       drm_mm_t *mm = (drm_mm_t *) private;
-       drm_mm_node_t *tmp;
+       struct drm_mm *mm = (struct drm_mm *) private;
+       struct drm_mm_node *tmp;
 
        tmp = drm_mm_search_free(mm, size, alignment, 1);
        if (!tmp) {
@@ -101,30 +101,30 @@ static void *drm_sman_mm_allocate(void *private, unsigned long size,
 
 static void drm_sman_mm_free(void *private, void *ref)
 {
-       drm_mm_node_t *node = (drm_mm_node_t *) ref;
+       struct drm_mm_node *node = (struct drm_mm_node *) ref;
 
        drm_mm_put_block(node);
 }
 
 static void drm_sman_mm_destroy(void *private)
 {
-       drm_mm_t *mm = (drm_mm_t *) private;
+       struct drm_mm *mm = (struct drm_mm *) private;
        drm_mm_takedown(mm);
        drm_free(mm, sizeof(*mm), DRM_MEM_MM);
 }
 
 static unsigned long drm_sman_mm_offset(void *private, void *ref)
 {
-       drm_mm_node_t *node = (drm_mm_node_t *) ref;
+       struct drm_mm_node *node = (struct drm_mm_node *) ref;
        return node->start;
 }
 
 int
-drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
                   unsigned long start, unsigned long size)
 {
-       drm_sman_mm_t *sman_mm;
-       drm_mm_t *mm;
+       struct drm_sman_mm *sman_mm;
+       struct drm_mm *mm;
        int ret;
 
        BUG_ON(manager >= sman->num_managers);
@@ -153,8 +153,8 @@ drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
 EXPORT_SYMBOL(drm_sman_set_range);
 
 int
-drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
-                    drm_sman_mm_t * allocator)
+drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
+                    struct drm_sman_mm * allocator)
 {
        BUG_ON(manager >= sman->num_managers);
        sman->mm[manager] = *allocator;
@@ -163,16 +163,16 @@ drm_sman_set_manager(drm_sman_t * sman, unsigned int manager,
 }
 EXPORT_SYMBOL(drm_sman_set_manager);
 
-static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman,
+static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
                                                 unsigned long owner)
 {
        int ret;
-       drm_hash_item_t *owner_hash_item;
-       drm_owner_item_t *owner_item;
+       struct drm_hash_item *owner_hash_item;
+       struct drm_owner_item *owner_item;
 
        ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
        if (!ret) {
-               return drm_hash_entry(owner_hash_item, drm_owner_item_t,
+               return drm_hash_entry(owner_hash_item, struct drm_owner_item,
                                      owner_hash);
        }
 
@@ -194,14 +194,14 @@ out:
        return NULL;
 }
 
-drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager,
+struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
                                    unsigned long size, unsigned alignment,
                                    unsigned long owner)
 {
        void *tmp;
-       drm_sman_mm_t *sman_mm;
-       drm_owner_item_t *owner_item;
-       drm_memblock_item_t *memblock;
+       struct drm_sman_mm *sman_mm;
+       struct drm_owner_item *owner_item;
+       struct drm_memblock_item *memblock;
 
        BUG_ON(manager >= sman->num_managers);
 
@@ -246,9 +246,9 @@ out:
 
 EXPORT_SYMBOL(drm_sman_alloc);
 
-static void drm_sman_free(drm_memblock_item_t *item)
+static void drm_sman_free(struct drm_memblock_item *item)
 {
-       drm_sman_t *sman = item->sman;
+       struct drm_sman *sman = item->sman;
 
        list_del(&item->owner_list);
        drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
@@ -256,40 +256,40 @@ static void drm_sman_free(drm_memblock_item_t *item)
        drm_free(item, sizeof(*item), DRM_MEM_MM);
 }
 
-int drm_sman_free_key(drm_sman_t *sman, unsigned int key)
+int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
 {
-       drm_hash_item_t *hash_item;
-       drm_memblock_item_t *memblock_item;
+       struct drm_hash_item *hash_item;
+       struct drm_memblock_item *memblock_item;
 
        if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
                return -EINVAL;
 
-       memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash);
+       memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item, user_hash);
        drm_sman_free(memblock_item);
        return 0;
 }
 
 EXPORT_SYMBOL(drm_sman_free_key);
 
-static void drm_sman_remove_owner(drm_sman_t *sman,
-                                 drm_owner_item_t *owner_item)
+static void drm_sman_remove_owner(struct drm_sman *sman,
+                                 struct drm_owner_item *owner_item)
 {
        list_del(&owner_item->sman_list);
        drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
        drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
 }
 
-int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
+int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
 {
 
-       drm_hash_item_t *hash_item;
-       drm_owner_item_t *owner_item;
+       struct drm_hash_item *hash_item;
+       struct drm_owner_item *owner_item;
 
        if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
                return -1;
        }
 
-       owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+       owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
        if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
                drm_sman_remove_owner(sman, owner_item);
                return -1;
@@ -300,10 +300,10 @@ int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner)
 
 EXPORT_SYMBOL(drm_sman_owner_clean);
 
-static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
-                                     drm_owner_item_t *owner_item)
+static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
+                                     struct drm_owner_item *owner_item)
 {
-       drm_memblock_item_t *entry, *next;
+       struct drm_memblock_item *entry, *next;
 
        list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
                                 owner_list) {
@@ -312,28 +312,28 @@ static void drm_sman_do_owner_cleanup(drm_sman_t *sman,
        drm_sman_remove_owner(sman, owner_item);
 }
 
-void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner)
+void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
 {
 
-       drm_hash_item_t *hash_item;
-       drm_owner_item_t *owner_item;
+       struct drm_hash_item *hash_item;
+       struct drm_owner_item *owner_item;
 
        if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
 
                return;
        }
 
-       owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash);
+       owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
        drm_sman_do_owner_cleanup(sman, owner_item);
 }
 
 EXPORT_SYMBOL(drm_sman_owner_cleanup);
 
-void drm_sman_cleanup(drm_sman_t *sman)
+void drm_sman_cleanup(struct drm_sman *sman)
 {
-       drm_owner_item_t *entry, *next;
+       struct drm_owner_item *entry, *next;
        unsigned int i;
-       drm_sman_mm_t *sman_mm;
+       struct drm_sman_mm *sman_mm;
 
        list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
                drm_sman_do_owner_cleanup(sman, entry);
index ddc732a..39a39fe 100644 (file)
@@ -50,7 +50,7 @@
  * for memory management.
  */
 
-typedef struct drm_sman_mm {
+struct drm_sman_mm {
        /* private info. If allocated, needs to be destroyed by the destroy
           function */
        void *private;
@@ -74,30 +74,30 @@ typedef struct drm_sman_mm {
           "alloc" function */
 
        unsigned long (*offset) (void *private, void *ref);
-} drm_sman_mm_t;
+};
 
-typedef struct drm_memblock_item {
+struct drm_memblock_item {
        struct list_head owner_list;
-       drm_hash_item_t user_hash;
+       struct drm_hash_item user_hash;
        void *mm_info;
-       drm_sman_mm_t *mm;
+       struct drm_sman_mm *mm;
        struct drm_sman *sman;
-} drm_memblock_item_t;
+};
 
-typedef struct drm_sman {
-       drm_sman_mm_t *mm;
+struct drm_sman {
+       struct drm_sman_mm *mm;
        int num_managers;
-       drm_open_hash_t owner_hash_tab;
-       drm_open_hash_t user_hash_tab;
+       struct drm_open_hash owner_hash_tab;
+       struct drm_open_hash user_hash_tab;
        struct list_head owner_items;
-} drm_sman_t;
+};
 
 /*
  * Take down a memory manager. This function should only be called after a
  * successful init and after a call to drm_sman_cleanup.
  */
 
-extern void drm_sman_takedown(drm_sman_t * sman);
+extern void drm_sman_takedown(struct drm_sman * sman);
 
 /*
  * Allocate structures for a manager.
@@ -112,7 +112,7 @@ extern void drm_sman_takedown(drm_sman_t * sman);
  *
  */
 
-extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
+extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
                         unsigned int user_order, unsigned int owner_order);
 
 /*
@@ -120,7 +120,7 @@ extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers,
  * manager unless a customized allogator is used.
  */
 
-extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
+extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
                              unsigned long start, unsigned long size);
 
 /*
@@ -129,23 +129,23 @@ extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager,
  * so it can be destroyed after this call.
  */
 
-extern int drm_sman_set_manager(drm_sman_t * sman, unsigned int mananger,
-                               drm_sman_mm_t * allocator);
+extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
+                               struct drm_sman_mm * allocator);
 
 /*
  * Allocate a memory block. Aligment is not implemented yet.
  */
 
-extern drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman,
-                                          unsigned int manager,
-                                          unsigned long size,
-                                          unsigned alignment,
-                                          unsigned long owner);
+extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
+                                               unsigned int manager,
+                                               unsigned long size,
+                                               unsigned alignment,
+                                               unsigned long owner);
 /*
  * Free a memory block identified by its user hash key.
  */
 
-extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
+extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key);
 
 /*
  * returns 1 iff there are no stale memory blocks associated with this owner.
@@ -154,7 +154,7 @@ extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key);
  * resources associated with owner.
  */
 
-extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
+extern int drm_sman_owner_clean(struct drm_sman * sman, unsigned long owner);
 
 /*
  * Frees all stale memory blocks associated with this owner. Note that this
@@ -164,13 +164,13 @@ extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner);
  * is not going to be referenced anymore.
  */
 
-extern void drm_sman_owner_cleanup(drm_sman_t * sman, unsigned long owner);
+extern void drm_sman_owner_cleanup(struct drm_sman * sman, unsigned long owner);
 
 /*
  * Frees all stale memory blocks associated with the memory manager.
  * See idling above.
  */
 
-extern void drm_sman_cleanup(drm_sman_t * sman);
+extern void drm_sman_cleanup(struct drm_sman * sman);
 
 #endif
index 7b0a0f9..34e8d2b 100644 (file)
@@ -50,17 +50,16 @@ MODULE_PARM_DESC(debug, "Enable debug output");
 module_param_named(cards_limit, drm_cards_limit, int, 0444);
 module_param_named(debug, drm_debug, int, 0600);
 
-drm_head_t **drm_heads;
-struct drm_sysfs_class *drm_class;
+struct drm_head **drm_heads;
+struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
-static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
+static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
                       const struct pci_device_id *ent,
                       struct drm_driver *driver)
 {
        int retcode;
 
-       INIT_LIST_HEAD(&dev->drwlist);
        INIT_LIST_HEAD(&dev->filelist);
        INIT_LIST_HEAD(&dev->ctxlist);
        INIT_LIST_HEAD(&dev->vmalist);
@@ -73,7 +72,6 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
        init_timer(&dev->timer);
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->ctxlist_mutex);
-       mutex_init(&dev->bm.init_mutex);
        mutex_init(&dev->bm.evict_mutex);
 
        idr_init(&dev->drw_idr);
@@ -87,9 +85,9 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
 #endif
        dev->irq = pdev->irq;
 
-       if (drm_ht_create(&dev->map_hash, DRM_MAP_HASH_ORDER)) {
+       if (drm_ht_create(&dev->map_hash, DRM_MAP_HASH_ORDER))
                return -ENOMEM;
-       }
+
        if (drm_mm_init(&dev->offset_manager, DRM_FILE_PAGE_OFFSET_START,
                        DRM_FILE_PAGE_OFFSET_SIZE)) {
                drm_ht_remove(&dev->map_hash);
@@ -113,10 +111,6 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
 
        dev->driver = driver;
 
-       if (dev->driver->load)
-               if ((retcode = dev->driver->load(dev, ent->driver_data)))
-                       goto error_out_unreg;
-
        if (drm_core_has_AGP(dev)) {
                if (drm_device_is_agp(dev))
                        dev->agp = drm_agp_init(dev);
@@ -136,6 +130,10 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
                }
        }
 
+       if (dev->driver->load)
+               if ((retcode = dev->driver->load(dev, ent->driver_data)))
+                       goto error_out_unreg;
+
        retcode = drm_ctxbitmap_init(dev);
        if (retcode) {
                DRM_ERROR("Cannot allocate memory for context bitmap.\n");
@@ -161,9 +159,9 @@ error_out_unreg:
  * create the proc init entry via proc_init(). This routines assigns
  * minor numbers to secondary heads of multi-headed cards
  */
-static int drm_get_head(drm_device_t * dev, drm_head_t * head)
+static int drm_get_head(struct drm_device * dev, struct drm_head * head)
 {
-       drm_head_t **heads = drm_heads;
+       struct drm_head **heads = drm_heads;
        int ret;
        int minor;
 
@@ -172,7 +170,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head)
        for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
                if (!*heads) {
 
-                       *head = (drm_head_t) {
+                       *head = (struct drm_head) {
                                .dev = dev,
                                .device = MKDEV(DRM_MAJOR, minor),
                                .minor = minor,
@@ -203,7 +201,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head)
 err_g2:
        drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
 err_g1:
-       *head = (drm_head_t) {
+       *head = (struct drm_head) {
                .dev = NULL};
        return ret;
 }
@@ -222,7 +220,7 @@ err_g1:
 int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
              struct drm_driver *driver)
 {
-       drm_device_t *dev;
+       struct drm_device *dev;
        int ret;
 
        DRM_DEBUG("\n");
@@ -233,18 +231,22 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 
        if (!drm_fb_loaded) {
                pci_set_drvdata(pdev, dev);
-               pci_request_regions(pdev, driver->pci_driver.name);
+               ret = pci_request_regions(pdev, driver->pci_driver.name);
+               if (ret)
+                       goto err_g1;
        }
 
-       pci_enable_device(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret)
+               goto err_g2;
        pci_set_master(pdev);
 
        if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
                printk(KERN_ERR "DRM: fill_in_dev failed\n");
-               goto err_g1;
+               goto err_g3;
        }
        if ((ret = drm_get_head(dev, &dev->primary)))
-               goto err_g1;
+               goto err_g3;
 
        DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
@@ -252,12 +254,16 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
 
        return 0;
 
-err_g1:
-       if (!drm_fb_loaded) {
-               pci_set_drvdata(pdev, NULL);
-               pci_release_regions(pdev);
+ err_g3:
+       if (!drm_fb_loaded)
                pci_disable_device(pdev);
-       }
+ err_g2:
+       if (!drm_fb_loaded)
+               pci_release_regions(pdev);
+ err_g1:
+       if (!drm_fb_loaded)
+               pci_set_drvdata(pdev, NULL);
+
        drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
        printk(KERN_ERR "DRM: drm_get_dev failed.\n");
        return ret;
@@ -275,7 +281,7 @@ EXPORT_SYMBOL(drm_get_dev);
  * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
  * unregisters the character device.
  */
-int drm_put_dev(drm_device_t * dev)
+int drm_put_dev(struct drm_device * dev)
 {
        DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
 
@@ -303,7 +309,7 @@ int drm_put_dev(drm_device_t * dev)
  * last minor released.
  *
  */
-int drm_put_head(drm_head_t * head)
+int drm_put_head(struct drm_head * head)
 {
        int minor = head->minor;
 
@@ -312,7 +318,7 @@ int drm_put_head(drm_head_t * head)
        drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
        drm_sysfs_device_remove(head->dev_class);
 
-       *head = (drm_head_t){.dev = NULL};
+       *head = (struct drm_head){.dev = NULL};
 
        drm_heads[minor] = NULL;
        return 0;
index ace0778..cf4349b 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
  *               extra sysfs attribute from DRM. Normal drm_sysfs_class
 #include <linux/kdev_t.h>
 #include <linux/err.h>
 
-#include "drmP.h"
 #include "drm_core.h"
-
-struct drm_sysfs_class {
-       struct class_device_attribute attr;
-       struct class class;
-};
-#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
-
-struct simple_dev {
-       dev_t dev;
-       struct class_device class_dev;
-};
-#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-
-static void release_simple_dev(struct class_device *class_dev)
-{
-       struct simple_dev *s_dev = to_simple_dev(class_dev);
-       kfree(s_dev);
-}
-
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-       struct simple_dev *s_dev = to_simple_dev(class_dev);
-       return print_dev_t(buf, s_dev->dev);
-}
-
-static void drm_sysfs_class_release(struct class *class)
-{
-       struct drm_sysfs_class *cs = to_drm_sysfs_class(class);
-       kfree(cs);
-}
+#include "drmP.h"
 
 /* Display the version of drm_core. This doesn't work right in current design */
 static ssize_t version_show(struct class *dev, char *buf)
@@ -68,38 +39,27 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
  * Note, the pointer created here is to be destroyed when finished by making a
  * call to drm_sysfs_destroy().
  */
-struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
+struct class *drm_sysfs_create(struct module *owner, char *name)
 {
-       struct drm_sysfs_class *cs;
-       int retval;
+       struct class *class;
+       int err;
 
-       cs = kmalloc(sizeof(*cs), GFP_KERNEL);
-       if (!cs) {
-               retval = -ENOMEM;
-               goto error;
+       class = class_create(owner, name);
+       if (IS_ERR(class)) {
+               err = PTR_ERR(class);
+               goto err_out;
        }
-       memset(cs, 0x00, sizeof(*cs));
-
-       cs->class.name = name;
-       cs->class.class_release = drm_sysfs_class_release;
-       cs->class.release = release_simple_dev;
 
-       cs->attr.attr.name = "dev";
-       cs->attr.attr.mode = S_IRUGO;
-       cs->attr.attr.owner = owner;
-       cs->attr.show = show_dev;
-       cs->attr.store = NULL;
+       err = class_create_file(class, &class_attr_version);
+       if (err)
+               goto err_out_class;
 
-       retval = class_register(&cs->class);
-       if (retval)
-               goto error;
-       class_create_file(&cs->class, &class_attr_version);
+       return class;
 
-       return cs;
-
-      error:
-       kfree(cs);
-       return ERR_PTR(retval);
+err_out_class:
+       class_destroy(class);
+err_out:
+       return ERR_PTR(err);
 }
 
 /**
@@ -109,17 +69,18 @@ struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
  * Note, the pointer to be destroyed must have been created with a call to
  * drm_sysfs_create().
  */
-void drm_sysfs_destroy(struct drm_sysfs_class *cs)
+void drm_sysfs_destroy(struct class *class)
 {
-       if ((cs == NULL) || (IS_ERR(cs)))
+       if ((class == NULL) || (IS_ERR(class)))
                return;
 
-       class_unregister(&cs->class);
+       class_remove_file(class, &class_attr_version);
+       class_destroy(class);
 }
 
 static ssize_t show_dri(struct class_device *class_device, char *buf)
 {
-       drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev;
+       struct drm_device * dev = ((struct drm_head *)class_get_devdata(class_device))->dev;
        if (dev->driver->dri_library_name)
                return dev->driver->dri_library_name(dev, buf);
        return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
@@ -131,7 +92,7 @@ static struct class_device_attribute class_device_attrs[] = {
 
 /**
  * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
+ * @cs: pointer to the struct class that this device should be registered to.
  * @dev: the dev_t for the device to be added.
  * @device: a pointer to a struct device that is assiociated with this class device.
  * @fmt: string for the class device's name
@@ -140,47 +101,42 @@ static struct class_device_attribute class_device_attrs[] = {
  * class.  A "dev" file will be created, showing the dev_t for the device.  The
  * pointer to the struct class_device will be returned from the call.  Any further
  * sysfs files that might be required can be created using this pointer.
- * Note: the struct drm_sysfs_class passed to this function must have previously been
+ * Note: the struct class passed to this function must have previously been
  * created with a call to drm_sysfs_create().
  */
-struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
-                                         drm_head_t * head)
+struct class_device *drm_sysfs_device_add(struct class *cs, struct drm_head *head)
 {
-       struct simple_dev *s_dev = NULL;
-       int i, retval;
-
-       if ((cs == NULL) || (IS_ERR(cs))) {
-               retval = -ENODEV;
-               goto error;
+       struct class_device *class_dev;
+       int i, j, err;
+
+       class_dev = class_device_create(cs, NULL,
+                                       MKDEV(DRM_MAJOR, head->minor),
+                                       &(head->dev->pdev)->dev,
+                                       "card%d", head->minor);
+       if (IS_ERR(class_dev)) {
+               err = PTR_ERR(class_dev);
+               goto err_out;
        }
 
-       s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
-       if (!s_dev) {
-               retval = -ENOMEM;
-               goto error;
-       }
-       memset(s_dev, 0x00, sizeof(*s_dev));
+       class_set_devdata(class_dev, head);
 
-       s_dev->dev = MKDEV(DRM_MAJOR, head->minor);
-       s_dev->class_dev.dev = &head->dev->pdev->dev;
-       s_dev->class_dev.class = &cs->class;
-
-       snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);
-       retval = class_device_register(&s_dev->class_dev);
-       if (retval)
-               goto error;
-
-       class_device_create_file(&s_dev->class_dev, &cs->attr);
-       class_set_devdata(&s_dev->class_dev, head);
-
-       for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-               class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);
+       for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
+               err = class_device_create_file(class_dev,
+                                              &class_device_attrs[i]);
+               if (err)
+                       goto err_out_files;
+       }
 
-       return &s_dev->class_dev;
+       return class_dev;
 
-error:
-       kfree(s_dev);
-       return ERR_PTR(retval);
+err_out_files:
+       if (i > 0)
+               for (j = 0; j < i; j++)
+                       class_device_remove_file(class_dev,
+                                                &class_device_attrs[i]);
+       class_device_unregister(class_dev);
+err_out:
+       return ERR_PTR(err);
 }
 
 /**
@@ -192,11 +148,9 @@ error:
  */
 void drm_sysfs_device_remove(struct class_device *class_dev)
 {
-       struct simple_dev *s_dev = to_simple_dev(class_dev);
        int i;
 
        for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-               class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);
-
-       class_device_unregister(&s_dev->class_dev);
+               class_device_remove_file(class_dev, &class_device_attrs[i]);
+       class_device_unregister(class_dev);
 }
index 31503c9..33bbe1d 100644 (file)
@@ -35,17 +35,18 @@ static void drm_ttm_ipi_handler(void *null)
        flush_agp_cache();
 }
 
-static void drm_ttm_cache_flush(void)
+void drm_ttm_cache_flush(void)
 {
        if (on_each_cpu(drm_ttm_ipi_handler, NULL, 1, 1) != 0)
                DRM_ERROR("Timed out waiting for drm cache flush.\n");
 }
+EXPORT_SYMBOL(drm_ttm_cache_flush);
 
 /*
  * Use kmalloc if possible. Otherwise fall back to vmalloc.
  */
 
-static void ttm_alloc_pages(drm_ttm_t * ttm)
+static void ttm_alloc_pages(struct drm_ttm * ttm)
 {
        unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
        ttm->pages = NULL;
@@ -66,7 +67,7 @@ static void ttm_alloc_pages(drm_ttm_t * ttm)
        }
 }
 
-static void ttm_free_pages(drm_ttm_t * ttm)
+static void ttm_free_pages(struct drm_ttm * ttm)
 {
        unsigned long size = ttm->num_pages * sizeof(*ttm->pages);
 
@@ -105,7 +106,7 @@ static struct page *drm_ttm_alloc_page(void)
  * for range of pages in a ttm.
  */
 
-static int drm_set_caching(drm_ttm_t * ttm, int noncached)
+static int drm_set_caching(struct drm_ttm * ttm, int noncached)
 {
        int i;
        struct page **cur_page;
@@ -142,12 +143,12 @@ static int drm_set_caching(drm_ttm_t * ttm, int noncached)
  * Free all resources associated with a ttm.
  */
 
-int drm_destroy_ttm(drm_ttm_t * ttm)
+int drm_destroy_ttm(struct drm_ttm * ttm)
 {
 
        int i;
        struct page **cur_page;
-       drm_ttm_backend_t *be;
+       struct drm_ttm_backend *be;
 
        if (!ttm)
                return 0;
@@ -159,7 +160,7 @@ int drm_destroy_ttm(drm_ttm_t * ttm)
        }
 
        if (ttm->pages) {
-               drm_buffer_manager_t *bm = &ttm->dev->bm;
+               struct drm_buffer_manager *bm = &ttm->dev->bm;
                if (ttm->page_flags & DRM_TTM_PAGE_UNCACHED)
                        drm_set_caching(ttm, 0);
 
@@ -191,10 +192,10 @@ int drm_destroy_ttm(drm_ttm_t * ttm)
        return 0;
 }
 
-struct page *drm_ttm_get_page(drm_ttm_t * ttm, int index)
+struct page *drm_ttm_get_page(struct drm_ttm * ttm, int index)
 {
        struct page *p;
-       drm_buffer_manager_t *bm = &ttm->dev->bm;
+       struct drm_buffer_manager *bm = &ttm->dev->bm;
 
        p = ttm->pages[index];
        if (!p) {
@@ -207,11 +208,11 @@ struct page *drm_ttm_get_page(drm_ttm_t * ttm, int index)
        return p;
 }
 
-static int drm_ttm_populate(drm_ttm_t * ttm)
+int drm_ttm_populate(struct drm_ttm * ttm)
 {
        struct page *page;
        unsigned long i;
-       drm_ttm_backend_t *be;
+       struct drm_ttm_backend *be;
 
        if (ttm->state != ttm_unpopulated)
                return 0;
@@ -231,10 +232,10 @@ static int drm_ttm_populate(drm_ttm_t * ttm)
  * Initialize a ttm.
  */
 
-drm_ttm_t *drm_ttm_init(struct drm_device * dev, unsigned long size)
+struct drm_ttm *drm_ttm_init(struct drm_device * dev, unsigned long size)
 {
-       drm_bo_driver_t *bo_driver = dev->driver->bo_driver;
-       drm_ttm_t *ttm;
+       struct drm_bo_driver *bo_driver = dev->driver->bo_driver;
+       struct drm_ttm *ttm;
 
        if (!bo_driver)
                return NULL;
@@ -275,9 +276,9 @@ drm_ttm_t *drm_ttm_init(struct drm_device * dev, unsigned long size)
  * Unbind a ttm region from the aperture.
  */
 
-void drm_ttm_evict(drm_ttm_t * ttm)
+void drm_ttm_evict(struct drm_ttm * ttm)
 {
-       drm_ttm_backend_t *be = ttm->be;
+       struct drm_ttm_backend *be = ttm->be;
        int ret;
 
        if (ttm->state == ttm_bound) {
@@ -288,11 +289,11 @@ void drm_ttm_evict(drm_ttm_t * ttm)
        ttm->state = ttm_evicted;
 }
 
-void drm_ttm_fixup_caching(drm_ttm_t * ttm)
+void drm_ttm_fixup_caching(struct drm_ttm * ttm)
 {
 
        if (ttm->state == ttm_evicted) {
-               drm_ttm_backend_t *be = ttm->be;
+               struct drm_ttm_backend *be = ttm->be;
                if (be->func->needs_ub_cache_adjust(be)) {
                        drm_set_caching(ttm, 0);
                }
@@ -300,7 +301,7 @@ void drm_ttm_fixup_caching(drm_ttm_t * ttm)
        }
 }
 
-void drm_ttm_unbind(drm_ttm_t * ttm)
+void drm_ttm_unbind(struct drm_ttm * ttm)
 {
        if (ttm->state == ttm_bound)
                drm_ttm_evict(ttm);
@@ -308,11 +309,11 @@ void drm_ttm_unbind(drm_ttm_t * ttm)
        drm_ttm_fixup_caching(ttm);
 }
 
-int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset)
+int drm_bind_ttm(struct drm_ttm * ttm, struct drm_bo_mem_reg *bo_mem)
 {
 
        int ret = 0;
-       drm_ttm_backend_t *be;
+       struct drm_ttm_backend *be;
 
        if (!ttm)
                return -EINVAL;
@@ -325,17 +326,16 @@ int drm_bind_ttm(drm_ttm_t * ttm, int cached, unsigned long aper_offset)
        if (ret)
                return ret;
 
-       if (ttm->state == ttm_unbound && !cached) {
+       if (ttm->state == ttm_unbound && !(bo_mem->flags & DRM_BO_FLAG_CACHED)) {
                drm_set_caching(ttm, DRM_TTM_PAGE_UNCACHED);
        }
 
-       if ((ret = be->func->bind(be, aper_offset, cached))) {
+       if ((ret = be->func->bind(be, bo_mem))) {
                ttm->state = ttm_evicted;
                DRM_ERROR("Couldn't bind backend.\n");
                return ret;
        }
 
-       ttm->aper_offset = aper_offset;
        ttm->state = ttm_bound;
 
        return 0;
index f2c4350..d2554f3 100644 (file)
@@ -85,11 +85,11 @@ pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
 static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
                                                unsigned long address)
 {
-       drm_file_t *priv = vma->vm_file->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_map_t *map = NULL;
-       drm_map_list_t *r_list;
-       drm_hash_item_t *hash;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_map *map = NULL;
+       struct drm_map_list *r_list;
+       struct drm_hash_item *hash;
 
        /*
         * Find the right map
@@ -103,7 +103,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
        if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
                goto vm_nopage_error;
 
-       r_list = drm_hash_entry(hash, drm_map_list_t, hash);
+       r_list = drm_hash_entry(hash, struct drm_map_list, hash);
        map = r_list->map;
 
        if (map && map->type == _DRM_AGP) {
@@ -172,7 +172,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
 static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
                                                    unsigned long address)
 {
-       drm_map_t *map = (drm_map_t *) vma->vm_private_data;
+       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
        unsigned long offset;
        unsigned long i;
        struct page *page;
@@ -203,11 +203,11 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
  */
 static void drm_vm_shm_close(struct vm_area_struct *vma)
 {
-       drm_file_t *priv = vma->vm_file->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_vma_entry_t *pt, *temp;
-       drm_map_t *map;
-       drm_map_list_t *r_list;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_vma_entry *pt, *temp;
+       struct drm_map *map;
+       struct drm_map_list *r_list;
        int found_maps = 0;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -285,9 +285,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
 static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
                                                    unsigned long address)
 {
-       drm_file_t *priv = vma->vm_file->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_device_dma *dma = dev->dma;
        unsigned long offset;
        unsigned long page_nr;
        struct page *page;
@@ -321,10 +321,10 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
 static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
                                                   unsigned long address)
 {
-       drm_map_t *map = (drm_map_t *) vma->vm_private_data;
-       drm_file_t *priv = vma->vm_file->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_sg_mem_t *entry = dev->sg;
+       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_sg_mem *entry = dev->sg;
        unsigned long offset;
        unsigned long map_offset;
        unsigned long page_offset;
@@ -418,9 +418,9 @@ static struct vm_operations_struct drm_vm_sg_ops = {
  */
 static void drm_vm_open_locked(struct vm_area_struct *vma)
 {
-       drm_file_t *priv = vma->vm_file->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_vma_entry_t *vma_entry;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_vma_entry *vma_entry;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
@@ -436,8 +436,8 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
 
 static void drm_vm_open(struct vm_area_struct *vma)
 {
-       drm_file_t *priv = vma->vm_file->private_data;
-       drm_device_t *dev = priv->head->dev;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->head->dev;
 
        mutex_lock(&dev->struct_mutex);
        drm_vm_open_locked(vma);
@@ -454,9 +454,9 @@ static void drm_vm_open(struct vm_area_struct *vma)
  */
 static void drm_vm_close(struct vm_area_struct *vma)
 {
-       drm_file_t *priv = vma->vm_file->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_vma_entry_t *pt, *temp;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_vma_entry *pt, *temp;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
@@ -477,7 +477,7 @@ static void drm_vm_close(struct vm_area_struct *vma)
 /**
  * mmap DMA memory.
  *
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param vma virtual memory area.
  * \return zero on success or a negative number on failure.
  *
@@ -486,9 +486,9 @@ static void drm_vm_close(struct vm_area_struct *vma)
  */
 static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev;
-       drm_device_dma_t *dma;
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev;
+       struct drm_device_dma *dma;
        unsigned long length = vma->vm_end - vma->vm_start;
 
        dev = priv->head->dev;
@@ -524,7 +524,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        return 0;
 }
 
-unsigned long drm_core_get_map_ofs(drm_map_t * map)
+unsigned long drm_core_get_map_ofs(struct drm_map * map)
 {
        return map->offset;
 }
@@ -543,7 +543,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
 /**
  * mmap DMA memory.
  *
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param vma virtual memory area.
  * \return zero on success or a negative number on failure.
  *
@@ -555,11 +555,11 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
  */
 static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_map_t *map = NULL;
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->head->dev;
+       struct drm_map *map = NULL;
        unsigned long offset = 0;
-       drm_hash_item_t *hash;
+       struct drm_hash_item *hash;
 
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
                  vma->vm_start, vma->vm_end, vma->vm_pgoff);
@@ -585,7 +585,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
                return -EINVAL;
        }
 
-       map = drm_hash_entry(hash, drm_map_list_t, hash)->map;
+       map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
        if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
                return -EPERM;
 
@@ -676,8 +676,8 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 
 int drm_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->head->dev;
        int ret;
 
        mutex_lock(&dev->struct_mutex);
@@ -713,11 +713,11 @@ EXPORT_SYMBOL(drm_mmap);
 static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma,
                                     unsigned long address)
 {
-       drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
+       struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
        unsigned long page_offset;
        struct page *page = NULL;
-       drm_ttm_t *ttm;
-       drm_device_t *dev;
+       struct drm_ttm *ttm;
+       struct drm_device *dev;
        unsigned long pfn;
        int err;
        unsigned long bus_base;
@@ -728,10 +728,17 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma,
        if (address > vma->vm_end)
                return NOPFN_SIGBUS;
 
-       err = mutex_lock_interruptible(&bo->mutex);
+       dev = bo->dev;
+       err = drm_bo_read_lock(&dev->bm.bm_lock);
        if (err)
                return NOPFN_REFAULT;
 
+       err = mutex_lock_interruptible(&bo->mutex);
+       if (err) {
+               drm_bo_read_unlock(&dev->bm.bm_lock);
+               return NOPFN_REFAULT;
+       }
+
        err = drm_bo_wait(bo, 0, 0, 0);
        if (err) {
                ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT;
@@ -754,7 +761,6 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma,
                }
        }
 
-       dev = bo->dev;
        err = drm_bo_pci_offset(dev, &bo->mem, &bus_base, &bus_offset,
                                &bus_size);
 
@@ -766,7 +772,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma,
        page_offset = (address - vma->vm_start) >> PAGE_SHIFT;
 
        if (bus_size) {
-               drm_mem_type_manager_t *man = &dev->bm.man[bo->mem.mem_type];
+               struct drm_mem_type_manager *man = &dev->bm.man[bo->mem.mem_type];
 
                pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) + page_offset;
                vma->vm_page_prot = drm_io_prot(man->drm_bus_maptype, vma);
@@ -792,13 +798,14 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma,
        }
 out_unlock:
        mutex_unlock(&bo->mutex);
+       drm_bo_read_unlock(&dev->bm.bm_lock);
        return ret;
 }
 #endif
 
 static void drm_bo_vm_open_locked(struct vm_area_struct *vma)
 {
-       drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
+       struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
 
        drm_vm_open_locked(vma);
        atomic_inc(&bo->usage);
@@ -815,8 +822,8 @@ static void drm_bo_vm_open_locked(struct vm_area_struct *vma)
 
 static void drm_bo_vm_open(struct vm_area_struct *vma)
 {
-       drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
-       drm_device_t *dev = bo->dev;
+       struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
+       struct drm_device *dev = bo->dev;
 
        mutex_lock(&dev->struct_mutex);
        drm_bo_vm_open_locked(vma);
@@ -831,8 +838,8 @@ static void drm_bo_vm_open(struct vm_area_struct *vma)
 
 static void drm_bo_vm_close(struct vm_area_struct *vma)
 {
-       drm_buffer_object_t *bo = (drm_buffer_object_t *) vma->vm_private_data;
-       drm_device_t *dev = bo->dev;
+       struct drm_buffer_object *bo = (struct drm_buffer_object *) vma->vm_private_data;
+       struct drm_device *dev = bo->dev;
 
        drm_vm_close(vma);
        if (bo) {
@@ -840,7 +847,8 @@ static void drm_bo_vm_close(struct vm_area_struct *vma)
 #ifdef DRM_ODD_MM_COMPAT
                drm_bo_delete_vma(bo, vma);
 #endif
-               drm_bo_usage_deref_locked(bo);
+               drm_bo_usage_deref_locked((struct drm_buffer_object **)
+                                         &vma->vm_private_data);
                mutex_unlock(&dev->struct_mutex);
        }
        return;
@@ -864,7 +872,7 @@ static struct vm_operations_struct drm_bo_vm_ops = {
  * mmap buffer object memory.
  *
  * \param vma virtual memory area.
- * \param filp file pointer.
+ * \param file_priv DRM file private.
  * \param map The buffer object drm map.
  * \return zero on success or a negative number on failure.
  */
index e6ae60c..586c350 100644 (file)
@@ -13,7 +13,7 @@
 #include "drmP.h"
 #include "ffb_drv.h"
 
-static int ffb_alloc_queue(drm_device_t * dev, int is_2d_only) {
+static int ffb_alloc_queue(struct drm_device * dev, int is_2d_only) {
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
        int i;
 
@@ -351,7 +351,7 @@ static void FFBWait(ffb_fbcPtr ffb)
        } while (--limit);
 }
 
-int ffb_context_switch(drm_device_t * dev, int old, int new) {
+int ffb_context_switch(struct drm_device * dev, int old, int new) {
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
 
 #if DRM_DMA_HISTOGRAM
@@ -401,7 +401,7 @@ int ffb_resctx(struct inode * inode, struct file * filp, unsigned int cmd,
 int ffb_addctx(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;
+       struct drm_device *dev = priv->dev;
        drm_ctx_t ctx;
        int idx;
 
@@ -421,7 +421,7 @@ int ffb_addctx(struct inode * inode, struct file * filp, unsigned int cmd,
 int ffb_modctx(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;
+       struct drm_device *dev = priv->dev;
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
        struct ffb_hw_context *hwctx;
        drm_ctx_t ctx;
@@ -449,7 +449,7 @@ int ffb_modctx(struct inode * inode, struct file * filp, unsigned int cmd,
 int ffb_getctx(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;
+       struct drm_device *dev = priv->dev;
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
        struct ffb_hw_context *hwctx;
        drm_ctx_t ctx;
@@ -480,7 +480,7 @@ int ffb_getctx(struct inode * inode, struct file * filp, unsigned int cmd,
 int ffb_switchctx(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;
+       struct drm_device *dev = priv->dev;
        drm_ctx_t ctx;
 
        if (copy_from_user(&ctx, (drm_ctx_t __user *) arg, sizeof(ctx)))
@@ -504,7 +504,7 @@ int ffb_rmctx(struct inode * inode, struct file * filp, unsigned int cmd,
                unsigned long arg) {
        drm_ctx_t ctx;
        drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->dev;
+       struct drm_device *dev = priv->dev;
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
        int idx;
 
@@ -523,7 +523,7 @@ int ffb_rmctx(struct inode * inode, struct file * filp, unsigned int cmd,
        return 0;
 }
 
-static void ffb_driver_reclaim_buffers_locked(drm_device_t * dev)
+static void ffb_driver_reclaim_buffers_locked(struct drm_device * dev)
 {
        ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
        int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
@@ -537,13 +537,13 @@ static void ffb_driver_reclaim_buffers_locked(drm_device_t * dev)
        }
 }
 
-static void ffb_driver_lastclose(drm_device_t * dev)
+static void ffb_driver_lastclose(struct drm_device * dev)
 {
        if (dev->dev_private)
                kfree(dev->dev_private);
 }
 
-static void ffb_driver_unload(drm_device_t * dev)
+static void ffb_driver_unload(struct drm_device * dev)
 {
        if (ffb_position != NULL)
                kfree(ffb_position);
@@ -571,7 +571,7 @@ unsigned long ffb_driver_get_map_ofs(drm_map_t * map)
        return (map->offset & 0xffffffff);
 }
 
-unsigned long ffb_driver_get_reg_ofs(drm_device_t * dev)
+unsigned long ffb_driver_get_reg_ofs(struct drm_device * dev)
 {
        ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *) dev->dev_private;
 
index 9c88f06..f2b4cc7 100644 (file)
@@ -114,7 +114,7 @@ static void ffb_apply_upa_parent_ranges(int parent,
        return;
 }
 
-static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
+static int ffb_init_one(struct drm_device *dev, int prom_node, int parent_node,
                        int instance)
 {
        struct linux_prom64_registers regs[2*PROMREG_MAX];
@@ -167,7 +167,7 @@ static int __init ffb_scan_siblings(int root, int instance)
 static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
 {
        drm_file_t      *priv   = filp->private_data;
-       drm_device_t    *dev;
+       struct drm_device       *dev;
        drm_map_list_t  *r_list;
        struct list_head *list;
        drm_map_t       *map;
@@ -237,10 +237,10 @@ unsigned long ffb_get_unmapped_area(struct file *filp,
 /* This functions must be here since it references drm_numdevs)
  * which drm_drv.h declares.
  */
-static int ffb_driver_firstopen(drm_device_t *dev)
+static int ffb_driver_firstopen(struct drm_device *dev)
 {
        ffb_dev_priv_t  *ffb_priv;
-       drm_device_t *temp_dev;
+       struct drm_device *temp_dev;
        int ret = 0;
        int i;
 
index f76b0d9..bad3c94 100644 (file)
@@ -281,4 +281,4 @@ extern unsigned long ffb_get_unmapped_area(struct file *filp,
                                           unsigned long pgoff,
                                           unsigned long flags);
 extern unsigned long ffb_driver_get_map_ofs(drm_map_t *map)
-extern unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev)
+extern unsigned long ffb_driver_get_reg_ofs(struct drm_device *dev)
index 4937943..7c37b4b 100644 (file)
@@ -46,9 +46,9 @@
 #define I810_BUF_UNMAPPED 0
 #define I810_BUF_MAPPED   1
 
-static inline void i810_print_status_page(drm_device_t * dev)
+static inline void i810_print_status_page(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_i810_private_t *dev_priv = dev->dev_private;
        u32 *temp = dev_priv->hw_status_page;
        int i;
@@ -64,16 +64,16 @@ static inline void i810_print_status_page(drm_device_t * dev)
        }
 }
 
-static drm_buf_t *i810_freelist_get(drm_device_t * dev)
+static struct drm_buf *i810_freelist_get(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *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];
+               struct drm_buf *buf = dma->buflist[i];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
                /* In use is already a pointer */
                used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
@@ -89,7 +89,7 @@ static drm_buf_t *i810_freelist_get(drm_device_t * dev)
  * yet, the hardware updates in use for us once its on the ring buffer.
  */
 
-static int i810_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+static int i810_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
        int used;
@@ -106,10 +106,10 @@ static int i810_freelist_put(drm_device_t * dev, drm_buf_t * buf)
 
 static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev;
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev;
        drm_i810_private_t *dev_priv;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        drm_i810_buf_priv_t *buf_priv;
 
        lock_kernel();
@@ -139,10 +139,9 @@ static const struct file_operations i810_buffer_fops = {
        .fasync = drm_fasync,
 };
 
-static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
+static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
+       struct drm_device *dev = file_priv->head->dev;
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
        drm_i810_private_t *dev_priv = dev->dev_private;
        const struct file_operations *old_fops;
@@ -152,14 +151,14 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
                return -EINVAL;
 
        down_write(&current->mm->mmap_sem);
-       old_fops = filp->f_op;
-       filp->f_op = &i810_buffer_fops;
+       old_fops = file_priv->filp->f_op;
+       file_priv->filp->f_op = &i810_buffer_fops;
        dev_priv->mmap_buffer = buf;
-       buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
+       buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total,
                                            PROT_READ | PROT_WRITE,
                                            MAP_SHARED, buf->bus_address);
        dev_priv->mmap_buffer = NULL;
-       filp->f_op = old_fops;
+       file_priv->filp->f_op = old_fops;
        if (IS_ERR(buf_priv->virtual)) {
                /* Real error */
                DRM_ERROR("mmap error\n");
@@ -171,7 +170,7 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp)
        return retcode;
 }
 
-static int i810_unmap_buffer(drm_buf_t * buf)
+static int i810_unmap_buffer(struct drm_buf * buf)
 {
        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
        int retcode = 0;
@@ -191,10 +190,10 @@ static int i810_unmap_buffer(drm_buf_t * buf)
        return retcode;
 }
 
-static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
-                              struct file *filp)
+static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
+                              struct drm_file *file_priv)
 {
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        drm_i810_buf_priv_t *buf_priv;
        int retcode = 0;
 
@@ -205,13 +204,13 @@ static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
                return retcode;
        }
 
-       retcode = i810_map_buffer(buf, filp);
+       retcode = i810_map_buffer(buf, file_priv);
        if (retcode) {
                i810_freelist_put(dev, buf);
                DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
                return retcode;
        }
-       buf->filp = filp;
+       buf->file_priv = file_priv;
        buf_priv = buf->dev_private;
        d->granted = 1;
        d->request_idx = buf->idx;
@@ -221,9 +220,9 @@ static int i810_dma_get_buffer(drm_device_t * dev, drm_i810_dma_t * d,
        return retcode;
 }
 
-static int i810_dma_cleanup(drm_device_t * dev)
+static int i810_dma_cleanup(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
 
        /* Make sure interrupts are disabled here because the uninstall ioctl
         * may not have been called from userspace and after dev_private
@@ -252,7 +251,7 @@ static int i810_dma_cleanup(drm_device_t * dev)
                dev->dev_private = NULL;
 
                for (i = 0; i < dma->buf_count; i++) {
-                       drm_buf_t *buf = dma->buflist[i];
+                       struct drm_buf *buf = dma->buflist[i];
                        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
                        if (buf_priv->kernel_virtual && buf->total)
@@ -262,7 +261,7 @@ static int i810_dma_cleanup(drm_device_t * dev)
        return 0;
 }
 
-static int i810_wait_ring(drm_device_t * dev, int n)
+static int i810_wait_ring(struct drm_device * dev, int n)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -295,7 +294,7 @@ static int i810_wait_ring(drm_device_t * dev, int n)
        return iters;
 }
 
-static void i810_kernel_lost_context(drm_device_t * dev)
+static void i810_kernel_lost_context(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -307,9 +306,9 @@ static void i810_kernel_lost_context(drm_device_t * dev)
                ring->space += ring->Size;
 }
 
-static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
+static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int my_idx = 24;
        u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
        int i;
@@ -320,7 +319,7 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
        }
 
        for (i = 0; i < dma->buf_count; i++) {
-               drm_buf_t *buf = dma->buflist[i];
+               struct drm_buf *buf = dma->buflist[i];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
                buf_priv->in_use = hw_status++;
@@ -342,11 +341,11 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
        return 0;
 }
 
-static int i810_dma_initialize(drm_device_t * dev,
+static int i810_dma_initialize(struct drm_device * dev,
                               drm_i810_private_t * dev_priv,
                               drm_i810_init_t * init)
 {
-       drm_map_list_t *r_list;
+       struct drm_map_list *r_list;
        memset(dev_priv, 0, sizeof(drm_i810_private_t));
 
        list_for_each_entry(r_list, &dev->maplist, head) {
@@ -399,7 +398,7 @@ static int i810_dma_initialize(drm_device_t * dev,
                i810_dma_cleanup(dev);
                DRM_ERROR("can not ioremap virtual address for"
                          " ring buffer\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
@@ -449,99 +448,29 @@ static int i810_dma_initialize(drm_device_t * dev,
        return 0;
 }
 
-/* i810 DRM version 1.1 used a smaller init structure with different
- * ordering of values than is currently used (drm >= 1.2). There is
- * no defined way to detect the XFree version to correct this problem,
- * however by checking using this procedure we can detect the correct
- * thing to do.
- *
- * #1 Read the Smaller init structure from user-space
- * #2 Verify the overlay_physical is a valid physical address, or NULL
- *    If it isn't then we have a v1.1 client. Fix up params.
- *    If it is, then we have a 1.2 client... get the rest of the data.
- */
-static int i810_dma_init_compat(drm_i810_init_t * init, unsigned long arg)
+static int i810_dma_init(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-
-       /* Get v1.1 init data */
-       if (copy_from_user(init, (drm_i810_pre12_init_t __user *) arg,
-                          sizeof(drm_i810_pre12_init_t))) {
-               return -EFAULT;
-       }
-
-       if ((!init->overlay_physical) || (init->overlay_physical > 4096)) {
-
-               /* This is a v1.2 client, just get the v1.2 init data */
-               DRM_INFO("Using POST v1.2 init.\n");
-               if (copy_from_user(init, (drm_i810_init_t __user *) arg,
-                                  sizeof(drm_i810_init_t))) {
-                       return -EFAULT;
-               }
-       } else {
-
-               /* This is a v1.1 client, fix the params */
-               DRM_INFO("Using PRE v1.2 init.\n");
-               init->pitch_bits = init->h;
-               init->pitch = init->w;
-               init->h = init->overlay_physical;
-               init->w = init->overlay_offset;
-               init->overlay_physical = 0;
-               init->overlay_offset = 0;
-       }
-
-       return 0;
-}
-
-static int i810_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->head->dev;
        drm_i810_private_t *dev_priv;
-       drm_i810_init_t init;
+       drm_i810_init_t *init = data;
        int retcode = 0;
 
-       /* Get only the init func */
-       if (copy_from_user
-           (&init, (void __user *)arg, sizeof(drm_i810_init_func_t)))
-               return -EFAULT;
-
-       switch (init.func) {
-       case I810_INIT_DMA:
-               /* This case is for backward compatibility. It
-                * handles XFree 4.1.0 and 4.2.0, and has to
-                * do some parameter checking as described below.
-                * It will someday go away.
-                */
-               retcode = i810_dma_init_compat(&init, arg);
-               if (retcode)
-                       return retcode;
-
-               dev_priv = drm_alloc(sizeof(drm_i810_private_t),
-                                    DRM_MEM_DRIVER);
-               if (dev_priv == NULL)
-                       return -ENOMEM;
-               retcode = i810_dma_initialize(dev, dev_priv, &init);
-               break;
-
-       default:
+       switch (init->func) {
        case I810_INIT_DMA_1_4:
                DRM_INFO("Using v1.4 init.\n");
-               if (copy_from_user(&init, (drm_i810_init_t __user *) arg,
-                                  sizeof(drm_i810_init_t))) {
-                       return -EFAULT;
-               }
                dev_priv = drm_alloc(sizeof(drm_i810_private_t),
                                     DRM_MEM_DRIVER);
                if (dev_priv == NULL)
                        return -ENOMEM;
-               retcode = i810_dma_initialize(dev, dev_priv, &init);
+               retcode = i810_dma_initialize(dev, dev_priv, init);
                break;
 
        case I810_CLEANUP_DMA:
                DRM_INFO("DMA Cleanup\n");
                retcode = i810_dma_cleanup(dev);
                break;
+       default:
+               return -EINVAL;
        }
 
        return retcode;
@@ -553,7 +482,7 @@ static int i810_dma_init(struct inode *inode, struct file *filp,
  * Use 'volatile' & local var tmp to force the emitted values to be
  * identical to the verified ones.
  */
-static void i810EmitContextVerified(drm_device_t * dev,
+static void i810EmitContextVerified(struct drm_device * dev,
                                    volatile unsigned int *code)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
@@ -586,7 +515,7 @@ static void i810EmitContextVerified(drm_device_t * dev,
        ADVANCE_LP_RING();
 }
 
-static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
+static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        int i, j = 0;
@@ -619,7 +548,7 @@ static void i810EmitTexVerified(drm_device_t * dev, volatile unsigned int *code)
 
 /* Need to do some additional checking when setting the dest buffer.
  */
-static void i810EmitDestVerified(drm_device_t * dev,
+static void i810EmitDestVerified(struct drm_device * dev,
                                 volatile unsigned int *code)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
@@ -654,7 +583,7 @@ static void i810EmitDestVerified(drm_device_t * dev,
        ADVANCE_LP_RING();
 }
 
-static void i810EmitState(drm_device_t * dev)
+static void i810EmitState(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -685,14 +614,14 @@ static void i810EmitState(drm_device_t * dev)
 
 /* need to verify
  */
-static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
+static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
                                    unsigned int clear_color,
                                    unsigned int clear_zval)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int pitch = dev_priv->pitch;
        int cpp = 2;
        int i;
@@ -760,12 +689,12 @@ static void i810_dma_dispatch_clear(drm_device_t * dev, int flags,
        }
 }
 
-static void i810_dma_dispatch_swap(drm_device_t * dev)
+static void i810_dma_dispatch_swap(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int pitch = dev_priv->pitch;
        int cpp = 2;
        int i;
@@ -806,13 +735,13 @@ static void i810_dma_dispatch_swap(drm_device_t * dev)
        }
 }
 
-static void i810_dma_dispatch_vertex(drm_device_t * dev,
-                                    drm_buf_t * buf, int discard, int used)
+static void i810_dma_dispatch_vertex(struct drm_device * dev,
+                                    struct drm_buf * buf, int discard, int used)
 {
        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;
-       drm_clip_rect_t *box = sarea_priv->boxes;
+       struct drm_clip_rect *box = sarea_priv->boxes;
        int nbox = sarea_priv->nbox;
        unsigned long address = (unsigned long)buf->bus_address;
        unsigned long start = address - dev->agp->base;
@@ -886,7 +815,7 @@ static void i810_dma_dispatch_vertex(drm_device_t * dev,
        }
 }
 
-static void i810_dma_dispatch_flip(drm_device_t * dev)
+static void i810_dma_dispatch_flip(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        int pitch = dev_priv->pitch;
@@ -933,7 +862,7 @@ static void i810_dma_dispatch_flip(drm_device_t * dev)
 
 }
 
-static void i810_dma_quiescent(drm_device_t * dev)
+static void i810_dma_quiescent(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -952,10 +881,10 @@ static void i810_dma_quiescent(drm_device_t * dev)
        i810_wait_ring(dev, dev_priv->ring.Size - 8);
 }
 
-static int i810_flush_queue(drm_device_t * dev)
+static int i810_flush_queue(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int i, ret = 0;
        RING_LOCALS;
 
@@ -971,7 +900,7 @@ static int i810_flush_queue(drm_device_t * dev)
        i810_wait_ring(dev, dev_priv->ring.Size - 8);
 
        for (i = 0; i < dma->buf_count; i++) {
-               drm_buf_t *buf = dma->buflist[i];
+               struct drm_buf *buf = dma->buflist[i];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
                int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
@@ -987,9 +916,10 @@ static int i810_flush_queue(drm_device_t * dev)
 }
 
 /* Must be called with the lock held */
-static void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
+static void i810_reclaim_buffers(struct drm_device *dev,
+                                struct drm_file *file_priv)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int i;
 
        if (!dma)
@@ -1002,10 +932,10 @@ static void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
        i810_flush_queue(dev);
 
        for (i = 0; i < dma->buf_count; i++) {
-               drm_buf_t *buf = dma->buflist[i];
+               struct drm_buf *buf = dma->buflist[i];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 
-               if (buf->filp == filp && buf_priv) {
+               if (buf->file_priv == file_priv && buf_priv) {
                        int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
                                           I810_BUF_FREE);
 
@@ -1017,47 +947,38 @@ static void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
        }
 }
 
-static int i810_flush_ioctl(struct inode *inode, struct file *filp,
-                           unsigned int cmd, unsigned long arg)
+static int i810_flush_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        i810_flush_queue(dev);
        return 0;
 }
 
-static int i810_dma_vertex(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg)
+static int i810_dma_vertex(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
        u32 *hw_status = dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
            dev_priv->sarea_priv;
-       drm_i810_vertex_t vertex;
+       drm_i810_vertex_t *vertex = data;
 
-       if (copy_from_user
-           (&vertex, (drm_i810_vertex_t __user *) arg, sizeof(vertex)))
-               return -EFAULT;
-
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
-                 vertex.idx, vertex.used, vertex.discard);
+                 vertex->idx, vertex->used, vertex->discard);
 
-       if (vertex.idx < 0 || vertex.idx > dma->buf_count)
+       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
                return -EINVAL;
 
        i810_dma_dispatch_vertex(dev,
-                                dma->buflist[vertex.idx],
-                                vertex.discard, vertex.used);
+                                dma->buflist[vertex->idx],
+                                vertex->discard, vertex->used);
 
-       atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
+       atomic_add(vertex->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];
@@ -1065,48 +986,37 @@ static int i810_dma_vertex(struct inode *inode, struct file *filp,
        return 0;
 }
 
-static int i810_clear_bufs(struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg)
+static int i810_clear_bufs(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_i810_clear_t clear;
-
-       if (copy_from_user
-           (&clear, (drm_i810_clear_t __user *) arg, sizeof(clear)))
-               return -EFAULT;
+       drm_i810_clear_t *clear = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        /* GH: Someone's doing nasty things... */
        if (!dev->dev_private) {
                return -EINVAL;
        }
 
-       i810_dma_dispatch_clear(dev, clear.flags,
-                               clear.clear_color, clear.clear_depth);
+       i810_dma_dispatch_clear(dev, clear->flags,
+                               clear->clear_color, clear->clear_depth);
        return 0;
 }
 
-static int i810_swap_bufs(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg)
+static int i810_swap_bufs(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-
        DRM_DEBUG("i810_swap_bufs\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        i810_dma_dispatch_swap(dev);
        return 0;
 }
 
-static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
-                      unsigned long arg)
+static int i810_getage(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
        u32 *hw_status = dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1116,52 +1026,45 @@ static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
-                      unsigned long arg)
+static int i810_getbuf(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        int retcode = 0;
-       drm_i810_dma_t d;
+       drm_i810_dma_t *d = data;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
        u32 *hw_status = dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
            dev_priv->sarea_priv;
 
-       if (copy_from_user(&d, (drm_i810_dma_t __user *) arg, sizeof(d)))
-               return -EFAULT;
-
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       d.granted = 0;
+       d->granted = 0;
 
-       retcode = i810_dma_get_buffer(dev, &d, filp);
+       retcode = i810_dma_get_buffer(dev, d, file_priv);
 
        DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
-                 current->pid, retcode, d.granted);
+                 current->pid, retcode, d->granted);
 
-       if (copy_to_user((drm_dma_t __user *) arg, &d, sizeof(d)))
-               return -EFAULT;
        sarea_priv->last_dispatch = (int)hw_status[5];
 
        return retcode;
 }
 
-static int i810_copybuf(struct inode *inode,
-                       struct file *filp, unsigned int cmd, unsigned long arg)
+static int i810_copybuf(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
 {
        /* Never copy - 2.4.x doesn't need it */
        return 0;
 }
 
-static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
-                      unsigned long arg)
+static int i810_docopy(struct drm_device *dev, void *data,
+                       struct drm_file *file_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,
+static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
                                 unsigned int last_render)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1221,30 +1124,25 @@ static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used,
        ADVANCE_LP_RING();
 }
 
-static int i810_dma_mc(struct inode *inode, struct file *filp,
-                      unsigned int cmd, unsigned long arg)
+static int i810_dma_mc(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
        u32 *hw_status = dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
            dev_priv->sarea_priv;
-       drm_i810_mc_t mc;
+       drm_i810_mc_t *mc = data;
 
-       if (copy_from_user(&mc, (drm_i810_mc_t __user *) arg, sizeof(mc)))
-               return -EFAULT;
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       if (mc.idx >= dma->buf_count || mc.idx < 0)
+       if (mc->idx >= dma->buf_count || mc->idx < 0)
                return -EINVAL;
 
-       i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
-                            mc.last_render);
+       i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used,
+                            mc->last_render);
 
-       atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);
+       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];
@@ -1252,51 +1150,41 @@ static int i810_dma_mc(struct inode *inode, struct file *filp,
        return 0;
 }
 
-static int i810_rstatus(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg)
+static int i810_rstatus(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
        return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
 }
 
-static int i810_ov0_info(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg)
+static int i810_ov0_info(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-       drm_i810_overlay_t data;
+       drm_i810_overlay_t *ov = data;
+
+       ov->offset = dev_priv->overlay_offset;
+       ov->physical = dev_priv->overlay_physical;
 
-       data.offset = dev_priv->overlay_offset;
-       data.physical = dev_priv->overlay_physical;
-       if (copy_to_user
-           ((drm_i810_overlay_t __user *) arg, &data, sizeof(data)))
-               return -EFAULT;
        return 0;
 }
 
-static int i810_fstatus(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg)
+static int i810_fstatus(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
        return I810_READ(0x30008);
 }
 
-static int i810_ov0_flip(struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg)
+static int i810_ov0_flip(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
        //Tell the overlay to update
        I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
 
@@ -1305,7 +1193,7 @@ static int i810_ov0_flip(struct inode *inode, struct file *filp,
 
 /* Not sure why this isn't set all the time:
  */
-static void i810_do_init_pageflip(drm_device_t * dev)
+static void i810_do_init_pageflip(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
 
@@ -1315,7 +1203,7 @@ static void i810_do_init_pageflip(drm_device_t * dev)
        dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 
-static int i810_do_cleanup_pageflip(drm_device_t * dev)
+static int i810_do_cleanup_pageflip(struct drm_device * dev)
 {
        drm_i810_private_t *dev_priv = dev->dev_private;
 
@@ -1327,16 +1215,14 @@ static int i810_do_cleanup_pageflip(drm_device_t * dev)
        return 0;
 }
 
-static int i810_flip_bufs(struct inode *inode, struct file *filp,
-                         unsigned int cmd, unsigned long arg)
+static int i810_flip_bufs(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        drm_i810_private_t *dev_priv = dev->dev_private;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv->page_flipping)
                i810_do_init_pageflip(dev);
@@ -1345,7 +1231,7 @@ static int i810_flip_bufs(struct inode *inode, struct file *filp,
        return 0;
 }
 
-int i810_driver_load(drm_device_t *dev, unsigned long flags)
+int i810_driver_load(struct drm_device *dev, unsigned long flags)
 {
        /* i810 has 4 more counters */
        dev->counters += 4;
@@ -1357,12 +1243,12 @@ int i810_driver_load(drm_device_t *dev, unsigned long flags)
        return 0;
 }
 
-void i810_driver_lastclose(drm_device_t * dev)
+void i810_driver_lastclose(struct drm_device * dev)
 {
        i810_dma_cleanup(dev);
 }
 
-void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
        if (dev->dev_private) {
                drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1372,33 +1258,34 @@ void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
        }
 }
 
-void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+                                       struct drm_file *file_priv)
 {
-       i810_reclaim_buffers(dev, filp);
+       i810_reclaim_buffers(dev, file_priv);
 }
 
-int i810_driver_dma_quiescent(drm_device_t * dev)
+int i810_driver_dma_quiescent(struct drm_device * dev)
 {
        i810_dma_quiescent(dev);
        return 0;
 }
 
-drm_ioctl_desc_t i810_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, DRM_AUTH}
+struct drm_ioctl_desc i810_ioctls[] = {
+  DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH)
 };
 
 int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
@@ -1414,7 +1301,7 @@ int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
  * \returns
  * A value of 1 is always retured to indictate every i810 is AGP.
  */
-int i810_driver_device_is_agp(drm_device_t * dev)
+int i810_driver_device_is_agp(struct drm_device * dev)
 {
        return 1;
 }
index beec4a2..d803aec 100644 (file)
@@ -102,13 +102,8 @@ typedef enum _drm_i810_init_func {
 /* This is the init structure after v1.2 */
 typedef struct _drm_i810_init {
        drm_i810_init_func_t func;
-#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
-       int ring_map_idx;
-       int buffer_map_idx;
-#else
        unsigned int mmio_offset;
        unsigned int buffers_offset;
-#endif
        int sarea_priv_offset;
        unsigned int ring_start;
        unsigned int ring_end;
@@ -124,29 +119,6 @@ typedef struct _drm_i810_init {
        unsigned int pitch_bits;
 } drm_i810_init_t;
 
-/* This is the init structure prior to v1.2 */
-typedef struct _drm_i810_pre12_init {
-       drm_i810_init_func_t func;
-#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
-       int ring_map_idx;
-       int buffer_map_idx;
-#else
-       unsigned int mmio_offset;
-       unsigned int buffers_offset;
-#endif
-       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;
-} drm_i810_pre12_init_t;
-
 /* Warning: If you change the SAREA structure you must change the Xserver
  * structure as well */
 
@@ -163,7 +135,7 @@ typedef struct _drm_i810_sarea {
        unsigned int dirty;
 
        unsigned int nbox;
-       drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
+       struct drm_clip_rect boxes[I810_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
index 69d7949..c525e16 100644 (file)
@@ -77,8 +77,8 @@ typedef struct _drm_i810_ring_buffer {
 } drm_i810_ring_buffer_t;
 
 typedef struct drm_i810_private {
-       drm_map_t *sarea_map;
-       drm_map_t *mmio_map;
+       struct drm_map *sarea_map;
+       struct drm_map *mmio_map;
 
        drm_i810_sarea_t *sarea_priv;
        drm_i810_ring_buffer_t ring;
@@ -88,7 +88,7 @@ typedef struct drm_i810_private {
 
        dma_addr_t dma_status_page;
 
-       drm_buf_t *mmap_buffer;
+       struct drm_buf *mmap_buffer;
 
        u32 front_di1, back_di1, zi1;
 
@@ -115,17 +115,18 @@ typedef struct drm_i810_private {
 } drm_i810_private_t;
 
                                /* i810_dma.c */
-extern int i810_driver_dma_quiescent(drm_device_t * dev);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
-                                              struct file *filp);
+extern int i810_driver_dma_quiescent(struct drm_device * dev);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+                                              struct drm_file *file_priv);
 extern int i810_driver_load(struct drm_device *, unsigned long flags);
-extern void i810_driver_lastclose(drm_device_t * dev);
-extern void i810_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
-                                              struct file *filp);
-extern int i810_driver_device_is_agp(drm_device_t * dev);
-
-extern drm_ioctl_desc_t i810_ioctls[];
+extern void i810_driver_lastclose(struct drm_device * dev);
+extern void i810_driver_preclose(struct drm_device * dev,
+                                struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+                                              struct drm_file *file_priv);
+extern int i810_driver_device_is_agp(struct drm_device * dev);
+
+extern struct drm_ioctl_desc i810_ioctls[];
 extern int i810_max_ioctl;
 
 #define I810_BASE(reg)         ((unsigned long) \
index 8589f46..01fae64 100644 (file)
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-drm_ttm_backend_t *i915_create_ttm_backend_entry(drm_device_t * dev)
+struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device * dev)
 {
        return drm_agp_init_ttm(dev);
 }
 
-int i915_fence_types(drm_buffer_object_t *bo, uint32_t * class, uint32_t * type)
+int i915_fence_types(struct drm_buffer_object *bo,
+                    uint32_t * fclass,
+                    uint32_t * type)
 {
-       *class = 0;
-       if (bo->mem.flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
+       if (bo->mem.mask & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
                *type = 3;
        else
                *type = 1;
        return 0;
 }
 
-int i915_invalidate_caches(drm_device_t * dev, uint32_t flags)
+int i915_invalidate_caches(struct drm_device * dev, uint64_t flags)
 {
        /*
         * FIXME: Only emit once per batchbuffer submission.
@@ -64,14 +65,15 @@ int i915_invalidate_caches(drm_device_t * dev, uint32_t flags)
        return i915_emit_mi_flush(dev, flush_cmd);
 }
 
-int i915_init_mem_type(drm_device_t * dev, uint32_t type,
-                      drm_mem_type_manager_t * man)
+int i915_init_mem_type(struct drm_device * dev, uint32_t type,
+                      struct drm_mem_type_manager * man)
 {
        switch (type) {
        case DRM_BO_MEM_LOCAL:
                man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
                    _DRM_FLAG_MEMTYPE_CACHED;
                man->drm_bus_maptype = 0;
+               man->gpu_offset = 0;
                break;
        case DRM_BO_MEM_TT:
                if (!(drm_core_has_AGP(dev) && dev->agp)) {
@@ -85,8 +87,9 @@ int i915_init_mem_type(drm_device_t * dev, uint32_t type,
                man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
                    _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP;
                man->drm_bus_maptype = _DRM_AGP;
+               man->gpu_offset = 0;
                break;
-       case DRM_BO_MEM_PRIV0:
+       case DRM_BO_MEM_VRAM:
                if (!(drm_core_has_AGP(dev) && dev->agp)) {
                        DRM_ERROR("AGP is not enabled for memory type %u\n",
                                  (unsigned)type);
@@ -98,6 +101,10 @@ int i915_init_mem_type(drm_device_t * dev, uint32_t type,
                man->flags =  _DRM_FLAG_MEMTYPE_MAPPABLE |
                    _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_NEEDS_IOREMAP;
                man->drm_bus_maptype = _DRM_AGP;
+               man->gpu_offset = 0;
+               break;
+       case DRM_BO_MEM_PRIV0: /* for OS preallocated space */
+               DRM_ERROR("PRIV0 not used yet.\n");
                break;
        default:
                DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
@@ -106,7 +113,7 @@ int i915_init_mem_type(drm_device_t * dev, uint32_t type,
        return 0;
 }
 
-uint32_t i915_evict_mask(drm_buffer_object_t *bo)
+uint32_t i915_evict_mask(struct drm_buffer_object *bo)
 {
        switch (bo->mem.mem_type) {
        case DRM_BO_MEM_LOCAL:
@@ -117,14 +124,16 @@ uint32_t i915_evict_mask(drm_buffer_object_t *bo)
        }
 }
 
-static void i915_emit_copy_blit(drm_device_t * dev,
+#if 0 /* See comment below */
+
+static void i915_emit_copy_blit(struct drm_device * dev,
                                uint32_t src_offset,
                                uint32_t dst_offset,
                                uint32_t pages, int direction)
 {
        uint32_t cur_pages;
        uint32_t stride = PAGE_SIZE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        RING_LOCALS;
 
        if (!dev_priv)
@@ -151,10 +160,10 @@ static void i915_emit_copy_blit(drm_device_t * dev,
        return;
 }
 
-static int i915_move_blit(drm_buffer_object_t * bo,
-                         int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
+static int i915_move_blit(struct drm_buffer_object * bo,
+                         int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
 {
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
        int dir = 0;
 
        if ((old_mem->mem_type == new_mem->mem_type) &&
@@ -181,11 +190,11 @@ static int i915_move_blit(drm_buffer_object_t * bo,
  * then blit and subsequently move out again.
  */
 
-static int i915_move_flip(drm_buffer_object_t * bo,
-                         int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
+static int i915_move_flip(struct drm_buffer_object * bo,
+                         int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
 {
-       drm_device_t *dev = bo->dev;
-       drm_bo_mem_reg_t tmp_mem;
+       struct drm_device *dev = bo->dev;
+       struct drm_bo_mem_reg tmp_mem;
        int ret;
 
        tmp_mem = *new_mem;
@@ -197,7 +206,7 @@ static int i915_move_flip(drm_buffer_object_t * bo,
        if (ret)
                return ret;
 
-       ret = drm_bind_ttm(bo->ttm, 1, tmp_mem.mm_node->start);
+       ret = drm_bind_ttm(bo->ttm, &tmp_mem);
        if (ret)
                goto out_cleanup;
 
@@ -217,18 +226,28 @@ out_cleanup:
        return ret;
 }
 
-int i915_move(drm_buffer_object_t * bo,
-             int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
+#endif
+
+/*
+ * Disable i915_move_flip for now, since we can't guarantee that the hardware lock
+ * is held here. To re-enable we need to make sure either
+ * a) The X server is using DRM to submit commands to the ring, or
+ * b) DRM can use the HP ring for these blits. This means i915 needs to implement
+ *    a new ring submission mechanism and fence class.
+ */
+
+int i915_move(struct drm_buffer_object * bo,
+             int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
 {
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
 
        if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
                return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
        } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
-               if (i915_move_flip(bo, evict, no_wait, new_mem))
+               if (0 /*i915_move_flip(bo, evict, no_wait, new_mem)*/)
                        return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
        } else {
-               if (i915_move_blit(bo, evict, no_wait, new_mem))
+               if (0 /*i915_move_blit(bo, evict, no_wait, new_mem)*/)
                        return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
        }
        return 0;
index 7fdb083..27e95d6 100644 (file)
@@ -30,6 +30,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
+#include "intel_drv.h"
 #include "i915_drv.h"
 
 #include "drm_pciids.h"
@@ -39,11 +40,11 @@ static struct pci_device_id pciidlist[] = {
 };
 
 #ifdef I915_HAVE_FENCE
-static drm_fence_driver_t i915_fence_driver = {
+static struct drm_fence_driver i915_fence_driver = {
        .num_classes = 1,
-       .wrap_diff = (1 << 30),
-       .flush_diff = (1 << 29),
-       .sequence_mask = 0xffffffffU,
+       .wrap_diff = (1U << (BREADCRUMB_BITS - 1)),
+       .flush_diff = (1U << (BREADCRUMB_BITS - 2)),
+       .sequence_mask = BREADCRUMB_MASK,
        .lazy_capable = 1,
        .emit = i915_fence_emit_sequence,
        .poke_flush = i915_poke_flush,
@@ -52,10 +53,10 @@ static drm_fence_driver_t i915_fence_driver = {
 #endif
 #ifdef I915_HAVE_BUFFER
 
-static uint32_t i915_mem_prios[] = {DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
-static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_LOCAL};
+static uint32_t i915_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_PRIV0, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
+static uint32_t i915_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
 
-static drm_bo_driver_t i915_bo_driver = {
+static struct drm_bo_driver i915_bo_driver = {
        .mem_type_prio = i915_mem_prios,
        .mem_busy_prio = i915_busy_prios,
        .num_mem_type_prio = sizeof(i915_mem_prios)/sizeof(uint32_t),
@@ -69,6 +70,234 @@ static drm_bo_driver_t i915_bo_driver = {
 };
 #endif
 
+static int i915_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_output *output;
+       int i;
+
+       pci_save_state(pdev);
+
+       /* Save video mode information for native mode-setting. */
+       dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
+       dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
+       dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+       dev_priv->saveFPA0 = I915_READ(FPA0);
+       dev_priv->saveFPA1 = I915_READ(FPA1);
+       dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+       if (IS_I965G(dev))
+               dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
+       dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
+       dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
+       dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
+       dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
+       dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
+       dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+       dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
+       dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
+       dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
+       dev_priv->saveDSPABASE = I915_READ(DSPABASE);
+
+       for(i= 0; i < 256; i++)
+               dev_priv->savePaletteA[i] = I915_READ(PALETTE_A + (i << 2));
+
+       if(dev->mode_config.num_crtc == 2) {
+               dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
+               dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+               dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
+               dev_priv->saveFPB0 = I915_READ(FPB0);
+               dev_priv->saveFPB1 = I915_READ(FPB1);
+               dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+               if (IS_I965G(dev))
+                       dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
+               dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
+               dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
+               dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
+               dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
+               dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
+               dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+               dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
+               dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
+               dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
+               dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
+               for(i= 0; i < 256; i++)
+                       dev_priv->savePaletteB[i] =
+                               I915_READ(PALETTE_B + (i << 2));
+       }
+
+       if (IS_I965G(dev)) {
+               dev_priv->saveDSPASURF = I915_READ(DSPASURF);
+               dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
+       }
+
+       dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
+       dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
+       dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
+       dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+
+       for(i = 0; i < 7; i++) {
+               dev_priv->saveSWF[i] = I915_READ(SWF0 + (i << 2));
+               dev_priv->saveSWF[i+7] = I915_READ(SWF00 + (i << 2));
+       }
+       dev_priv->saveSWF[14] = I915_READ(SWF30);
+       dev_priv->saveSWF[15] = I915_READ(SWF31);
+       dev_priv->saveSWF[16] = I915_READ(SWF32);
+
+       if (IS_MOBILE(dev) && !IS_I830(dev))
+               dev_priv->saveLVDS = I915_READ(LVDS);
+       dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head)
+               if (output->funcs->save)
+                       (*output->funcs->save) (output);
+
+#if 0 /* FIXME: save VGA bits */
+       vgaHWUnlock(hwp);
+       vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
+#endif
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       return 0;
+}
+
+static int i915_resume(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_output *output;
+       struct drm_crtc *crtc;
+       int i;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       if (pci_enable_device(pdev))
+               return -1;
+
+       /* Disable outputs */
+       list_for_each_entry(output, &dev->mode_config.output_list, head)
+               output->funcs->dpms(output, DPMSModeOff);
+
+       i915_driver_wait_next_vblank(dev, 0);
+   
+       /* Disable pipes */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+               crtc->funcs->dpms(crtc, DPMSModeOff);
+
+       /* FIXME: wait for vblank on each pipe? */
+       i915_driver_wait_next_vblank(dev, 0);
+
+       if (IS_MOBILE(dev) && !IS_I830(dev))
+               I915_WRITE(LVDS, dev_priv->saveLVDS);
+
+       if (!IS_I830(dev) && !IS_845G(dev))
+               I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
+
+       if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+               I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE);
+               udelay(150);
+       }
+       I915_WRITE(FPA0, dev_priv->saveFPA0);
+       I915_WRITE(FPA1, dev_priv->saveFPA1);
+       I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+       udelay(150);
+       if (IS_I965G(dev))
+               I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+       else
+               I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+       udelay(150);
+
+       I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+       I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+       I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+       I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+       I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+       I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+   
+       I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+       I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+       I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+       I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+       I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
+       if (IS_I965G(dev))
+               I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+       I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+       i915_driver_wait_next_vblank(dev, 0);
+       I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+       I915_WRITE(DSPABASE, I915_READ(DSPABASE));
+       i915_driver_wait_next_vblank(dev, 0);
+   
+       if(dev->mode_config.num_crtc == 2) {
+               if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+                       I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE);
+                       udelay(150);
+               }
+               I915_WRITE(FPB0, dev_priv->saveFPB0);
+               I915_WRITE(FPB1, dev_priv->saveFPB1);
+               I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+               udelay(150);
+               if (IS_I965G(dev))
+                       I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+               else
+                       I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+               udelay(150);
+   
+               I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+               I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+               I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+               I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+               I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+               I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+               I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+               I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+               I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+               I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+               I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
+               if (IS_I965G(dev))
+                       I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+               I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+               i915_driver_wait_next_vblank(dev, 0);
+               I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+               I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
+               i915_driver_wait_next_vblank(dev, 0);
+       }
+
+       /* Restore outputs */
+       list_for_each_entry(output, &dev->mode_config.output_list, head)
+               if (output->funcs->restore)
+                       output->funcs->restore(output);
+    
+       I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+
+       I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
+       I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
+       I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
+
+       for(i = 0; i < 256; i++)
+               I915_WRITE(PALETTE_A + (i << 2), dev_priv->savePaletteA[i]);
+   
+       if(dev->mode_config.num_crtc == 2)
+               for(i= 0; i < 256; i++)
+                       I915_WRITE(PALETTE_B + (i << 2), dev_priv->savePaletteB[i]);
+
+       for(i = 0; i < 7; i++) {
+               I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF[i]);
+               I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF[i+7]);
+       }
+
+       I915_WRITE(SWF30, dev_priv->saveSWF[14]);
+       I915_WRITE(SWF31, dev_priv->saveSWF[15]);
+       I915_WRITE(SWF32, dev_priv->saveSWF[16]);
+
+#if 0 /* FIXME: restore VGA bits */
+       vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
+       vgaHWLock(hwp);
+#endif
+
+       return 0;
+}
+
 static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static struct drm_driver driver = {
        /* don't use mtrr's here, the Xserver or user space app should
@@ -79,7 +308,7 @@ static struct drm_driver driver = {
            DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
            DRIVER_IRQ_VBL2,
        .load = i915_driver_load,
-       .firstopen = i915_driver_firstopen,
+       .unload = i915_driver_unload,
        .lastclose = i915_driver_lastclose,
        .preclose = i915_driver_preclose,
        .device_is_agp = i915_driver_device_is_agp,
@@ -92,6 +321,8 @@ static struct drm_driver driver = {
        .reclaim_buffers = drm_core_reclaim_buffers,
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
+       .fb_probe = intelfb_probe,
+       .fb_remove = intelfb_remove,
        .ioctls = i915_ioctls,
        .fops = {
                .owner = THIS_MODULE,
@@ -110,6 +341,8 @@ static struct drm_driver driver = {
                .id_table = pciidlist,
                .probe = probe,
                .remove = __devexit_p(drm_cleanup_pci),
+               .suspend = i915_suspend,
+               .resume = i915_resume,
                },
 #ifdef I915_HAVE_FENCE
        .fence_driver = &i915_fence_driver,
index 88daa57..330c870 100644 (file)
  * Implements an intel sync flush operation.
  */
 
-static void i915_perform_flush(drm_device_t * dev)
+static void i915_perform_flush(struct drm_device * dev)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_class_manager_t *fc = &fm->class[0];
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_class_manager *fc = &fm->fence_class[0];
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
        uint32_t flush_flags = 0;
        uint32_t flush_sequence = 0;
        uint32_t i_status;
@@ -61,9 +61,10 @@ static void i915_perform_flush(drm_device_t * dev)
                 * First update fences with the current breadcrumb.
                 */
 
-               diff = sequence - fc->last_exe_flush;
+               diff = (sequence - fc->last_exe_flush) & BREADCRUMB_MASK;
                if (diff < driver->wrap_diff && diff != 0) {
-                       drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE);
+                       drm_fence_handler(dev, 0, sequence,
+                                         DRM_FENCE_TYPE_EXE, 0);
                }
 
                if (dev_priv->fence_irq_on && !fc->pending_exe_flush) {
@@ -82,7 +83,7 @@ static void i915_perform_flush(drm_device_t * dev)
                        flush_flags = dev_priv->flush_flags;
                        flush_sequence = dev_priv->flush_sequence;
                        dev_priv->flush_pending = 0;
-                       drm_fence_handler(dev, 0, flush_sequence, flush_flags);
+                       drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
                }
        }
 
@@ -103,15 +104,15 @@ static void i915_perform_flush(drm_device_t * dev)
                        flush_flags = dev_priv->flush_flags;
                        flush_sequence = dev_priv->flush_sequence;
                        dev_priv->flush_pending = 0;
-                       drm_fence_handler(dev, 0, flush_sequence, flush_flags);
+                       drm_fence_handler(dev, 0, flush_sequence, flush_flags, 0);
                }
        }
 
 }
 
-void i915_poke_flush(drm_device_t * dev, uint32_t class)
+void i915_poke_flush(struct drm_device * dev, uint32_t class)
 {
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
        unsigned long flags;
 
        write_lock_irqsave(&fm->lock, flags);
@@ -119,10 +120,10 @@ void i915_poke_flush(drm_device_t * dev, uint32_t class)
        write_unlock_irqrestore(&fm->lock, flags);
 }
 
-int i915_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags,
+int i915_fence_emit_sequence(struct drm_device * dev, uint32_t class, uint32_t flags,
                             uint32_t * sequence, uint32_t * native_type)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        if (!dev_priv)
                return -EINVAL;
 
@@ -135,16 +136,16 @@ int i915_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags,
        return 0;
 }
 
-void i915_fence_handler(drm_device_t * dev)
+void i915_fence_handler(struct drm_device * dev)
 {
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
 
        write_lock(&fm->lock);
        i915_perform_flush(dev);
        write_unlock(&fm->lock);
 }
 
-int i915_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags)
+int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags)
 {
        /*
         * We have an irq that tells us when we have a new breadcrumb.
diff --git a/linux-core/i915_init.c b/linux-core/i915_init.c
new file mode 120000 (symlink)
index 0000000..473ddf7
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/i915_init.c
\ No newline at end of file
index 396f5c2..c1e776b 100644 (file)
@@ -30,7 +30,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
diff --git a/linux-core/intel_crt.c b/linux-core/intel_crt.c
new file mode 100644 (file)
index 0000000..d2e1f95
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static void intel_crt_dpms(struct drm_output *output, int mode)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 temp;
+       
+       temp = I915_READ(ADPA);
+       temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+       temp &= ~ADPA_DAC_ENABLE;
+       
+       switch(mode) {
+       case DPMSModeOn:
+               temp |= ADPA_DAC_ENABLE;
+               break;
+       case DPMSModeStandby:
+               temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
+               break;
+       case DPMSModeSuspend:
+               temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
+               break;
+       case DPMSModeOff:
+               temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
+               break;
+       }
+       
+       I915_WRITE(ADPA, temp);
+}
+
+static void intel_crt_save(struct drm_output *output)
+{
+       
+}
+
+static void intel_crt_restore(struct drm_output *output)
+{
+
+}
+
+static int intel_crt_mode_valid(struct drm_output *output,
+                               struct drm_display_mode *mode)
+{
+       if (mode->flags & V_DBLSCAN)
+               return MODE_NO_DBLESCAN;
+
+       if (mode->clock > 400000 || mode->clock < 25000)
+               return MODE_CLOCK_RANGE;
+
+       return MODE_OK;
+}
+
+static bool intel_crt_mode_fixup(struct drm_output *output,
+                                struct drm_display_mode *mode,
+                                struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void intel_crt_mode_set(struct drm_output *output,
+                              struct drm_display_mode *mode,
+                              struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_crtc *crtc = output->crtc;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int dpll_md_reg;
+       u32 adpa, dpll_md;
+
+       if (intel_crtc->pipe == 0) 
+               dpll_md_reg = DPLL_A_MD;
+       else
+               dpll_md_reg = DPLL_B_MD;
+
+       /*
+        * Disable separate mode multiplier used when cloning SDVO to CRT
+        * XXX this needs to be adjusted when we really are cloning
+        */
+       if (IS_I965G(dev)) {
+               dpll_md = I915_READ(dpll_md_reg);
+               I915_WRITE(dpll_md_reg,
+                          dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
+       }
+       
+       adpa = 0;
+       if (adjusted_mode->flags & V_PHSYNC)
+               adpa |= ADPA_HSYNC_ACTIVE_HIGH;
+       if (adjusted_mode->flags & V_PVSYNC)
+               adpa |= ADPA_VSYNC_ACTIVE_HIGH;
+       
+       if (intel_crtc->pipe == 0)
+               adpa |= ADPA_PIPE_A_SELECT;
+       else
+               adpa |= ADPA_PIPE_B_SELECT;
+       
+       I915_WRITE(ADPA, adpa);
+}
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
+ *
+ * Only for I945G/GM.
+ *
+ * \return TRUE if CRT is connected.
+ * \return FALSE if CRT is disconnected.
+ */
+static bool intel_crt_detect_hotplug(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 temp;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+       temp = I915_READ(PORT_HOTPLUG_EN);
+
+       I915_WRITE(PORT_HOTPLUG_EN,
+                  temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
+
+       do {
+               if (!(I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT))
+                       break;
+               msleep(1);
+       } while (time_after(timeout, jiffies));
+
+       if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
+           CRT_HOTPLUG_MONITOR_COLOR)
+               return true;
+
+       return false;
+}
+
+static bool intel_crt_detect_ddc(struct drm_output *output)
+{
+       struct intel_output *intel_output = output->driver_private;
+
+       /* CRT should always be at 0, but check anyway */
+       if (intel_output->type != INTEL_OUTPUT_ANALOG)
+               return false;
+       
+       return intel_ddc_probe(output);
+}
+
+static enum drm_output_status intel_crt_detect(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       
+       if (IS_I945G(dev)| IS_I945GM(dev) || IS_I965G(dev)) {
+               if (intel_crt_detect_hotplug(output))
+                       return output_status_connected;
+               else
+                       return output_status_disconnected;
+       }
+
+       if (intel_crt_detect_ddc(output))
+               return output_status_connected;
+
+       /* TODO use load detect */
+       return output_status_unknown;
+}
+
+static void intel_crt_destroy(struct drm_output *output)
+{
+       struct intel_output *intel_output = output->driver_private;
+
+       intel_i2c_destroy(intel_output->ddc_bus);
+       kfree(output->driver_private);
+}
+
+static int intel_crt_get_modes(struct drm_output *output)
+{
+       return intel_ddc_get_modes(output);
+}
+
+/*
+ * Routines for controlling stuff on the analog port
+ */
+static const struct drm_output_funcs intel_crt_output_funcs = {
+       .dpms = intel_crt_dpms,
+       .save = intel_crt_save,
+       .restore = intel_crt_restore,
+       .mode_valid = intel_crt_mode_valid,
+       .mode_fixup = intel_crt_mode_fixup,
+       .prepare = intel_output_prepare,
+       .mode_set = intel_crt_mode_set,
+       .commit = intel_output_commit,
+       .detect = intel_crt_detect,
+       .get_modes = intel_crt_get_modes,
+       .cleanup = intel_crt_destroy,
+};
+
+void intel_crt_init(struct drm_device *dev)
+{
+       struct drm_output *output;
+       struct intel_output *intel_output;
+
+       output = drm_output_create(dev, &intel_crt_output_funcs, "VGA");
+
+       intel_output = kmalloc(sizeof(struct intel_output), GFP_KERNEL);
+       if (!intel_output) {
+               drm_output_destroy(output);
+               return;
+       }
+       /* Set up the DDC bus. */
+       intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
+       if (!intel_output->ddc_bus) {
+               dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
+                          "failed.\n");
+               return;
+       }
+
+       intel_output->type = INTEL_OUTPUT_ANALOG;
+       output->driver_private = intel_output;
+       output->interlace_allowed = 0;
+       output->doublescan_allowed = 0;
+}
diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c
new file mode 100644 (file)
index 0000000..a81cfe6
--- /dev/null
@@ -0,0 +1,1235 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include "drmP.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
+
+typedef struct {
+    /* given values */    
+    int n;
+    int m1, m2;
+    int p1, p2;
+    /* derived values */
+    int        dot;
+    int        vco;
+    int        m;
+    int        p;
+} intel_clock_t;
+
+typedef struct {
+    int        min, max;
+} intel_range_t;
+
+typedef struct {
+    int        dot_limit;
+    int        p2_slow, p2_fast;
+} intel_p2_t;
+
+#define INTEL_P2_NUM                 2
+
+typedef struct {
+    intel_range_t   dot, vco, n, m, m1, m2, p, p1;
+    intel_p2_t     p2;
+} intel_limit_t;
+
+#define I8XX_DOT_MIN             25000
+#define I8XX_DOT_MAX            350000
+#define I8XX_VCO_MIN            930000
+#define I8XX_VCO_MAX           1400000
+#define I8XX_N_MIN                   3
+#define I8XX_N_MAX                  16
+#define I8XX_M_MIN                  96
+#define I8XX_M_MAX                 140
+#define I8XX_M1_MIN                 18
+#define I8XX_M1_MAX                 26
+#define I8XX_M2_MIN                  6
+#define I8XX_M2_MAX                 16
+#define I8XX_P_MIN                   4
+#define I8XX_P_MAX                 128
+#define I8XX_P1_MIN                  2
+#define I8XX_P1_MAX                 33
+#define I8XX_P1_LVDS_MIN             1
+#define I8XX_P1_LVDS_MAX             6
+#define I8XX_P2_SLOW                 4
+#define I8XX_P2_FAST                 2
+#define I8XX_P2_LVDS_SLOW            14
+#define I8XX_P2_LVDS_FAST            14 /* No fast option */
+#define I8XX_P2_SLOW_LIMIT      165000
+
+#define I9XX_DOT_MIN             20000
+#define I9XX_DOT_MAX            400000
+#define I9XX_VCO_MIN           1400000
+#define I9XX_VCO_MAX           2800000
+#define I9XX_N_MIN                   3
+#define I9XX_N_MAX                   8
+#define I9XX_M_MIN                  70
+#define I9XX_M_MAX                 120
+#define I9XX_M1_MIN                 10
+#define I9XX_M1_MAX                 20
+#define I9XX_M2_MIN                  5
+#define I9XX_M2_MAX                  9
+#define I9XX_P_SDVO_DAC_MIN          5
+#define I9XX_P_SDVO_DAC_MAX         80
+#define I9XX_P_LVDS_MIN                      7
+#define I9XX_P_LVDS_MAX                     98
+#define I9XX_P1_MIN                  1
+#define I9XX_P1_MAX                  8
+#define I9XX_P2_SDVO_DAC_SLOW               10
+#define I9XX_P2_SDVO_DAC_FAST                5
+#define I9XX_P2_SDVO_DAC_SLOW_LIMIT     200000
+#define I9XX_P2_LVDS_SLOW                   14
+#define I9XX_P2_LVDS_FAST                    7
+#define I9XX_P2_LVDS_SLOW_LIMIT                 112000
+
+#define INTEL_LIMIT_I8XX_DVO_DAC    0
+#define INTEL_LIMIT_I8XX_LVDS      1
+#define INTEL_LIMIT_I9XX_SDVO_DAC   2
+#define INTEL_LIMIT_I9XX_LVDS      3
+
+static const intel_limit_t intel_limits[] = {
+    { /* INTEL_LIMIT_I8XX_DVO_DAC */
+        .dot = { .min = I8XX_DOT_MIN,          .max = I8XX_DOT_MAX },
+        .vco = { .min = I8XX_VCO_MIN,          .max = I8XX_VCO_MAX },
+        .n   = { .min = I8XX_N_MIN,            .max = I8XX_N_MAX },
+        .m   = { .min = I8XX_M_MIN,            .max = I8XX_M_MAX },
+        .m1  = { .min = I8XX_M1_MIN,           .max = I8XX_M1_MAX },
+        .m2  = { .min = I8XX_M2_MIN,           .max = I8XX_M2_MAX },
+        .p   = { .min = I8XX_P_MIN,            .max = I8XX_P_MAX },
+        .p1  = { .min = I8XX_P1_MIN,           .max = I8XX_P1_MAX },
+       .p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
+                .p2_slow = I8XX_P2_SLOW,       .p2_fast = I8XX_P2_FAST },
+    },
+    { /* INTEL_LIMIT_I8XX_LVDS */
+        .dot = { .min = I8XX_DOT_MIN,          .max = I8XX_DOT_MAX },
+        .vco = { .min = I8XX_VCO_MIN,          .max = I8XX_VCO_MAX },
+        .n   = { .min = I8XX_N_MIN,            .max = I8XX_N_MAX },
+        .m   = { .min = I8XX_M_MIN,            .max = I8XX_M_MAX },
+        .m1  = { .min = I8XX_M1_MIN,           .max = I8XX_M1_MAX },
+        .m2  = { .min = I8XX_M2_MIN,           .max = I8XX_M2_MAX },
+        .p   = { .min = I8XX_P_MIN,            .max = I8XX_P_MAX },
+        .p1  = { .min = I8XX_P1_LVDS_MIN,      .max = I8XX_P1_LVDS_MAX },
+       .p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
+                .p2_slow = I8XX_P2_LVDS_SLOW,  .p2_fast = I8XX_P2_LVDS_FAST },
+    },
+    { /* INTEL_LIMIT_I9XX_SDVO_DAC */
+        .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX },
+        .vco = { .min = I9XX_VCO_MIN,          .max = I9XX_VCO_MAX },
+        .n   = { .min = I9XX_N_MIN,            .max = I9XX_N_MAX },
+        .m   = { .min = I9XX_M_MIN,            .max = I9XX_M_MAX },
+        .m1  = { .min = I9XX_M1_MIN,           .max = I9XX_M1_MAX },
+        .m2  = { .min = I9XX_M2_MIN,           .max = I9XX_M2_MAX },
+        .p   = { .min = I9XX_P_SDVO_DAC_MIN,   .max = I9XX_P_SDVO_DAC_MAX },
+        .p1  = { .min = I9XX_P1_MIN,           .max = I9XX_P1_MAX },
+       .p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
+                .p2_slow = I9XX_P2_SDVO_DAC_SLOW,      .p2_fast = I9XX_P2_SDVO_DAC_FAST },
+    },
+    { /* INTEL_LIMIT_I9XX_LVDS */
+        .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX },
+        .vco = { .min = I9XX_VCO_MIN,          .max = I9XX_VCO_MAX },
+        .n   = { .min = I9XX_N_MIN,            .max = I9XX_N_MAX },
+        .m   = { .min = I9XX_M_MIN,            .max = I9XX_M_MAX },
+        .m1  = { .min = I9XX_M1_MIN,           .max = I9XX_M1_MAX },
+        .m2  = { .min = I9XX_M2_MIN,           .max = I9XX_M2_MAX },
+        .p   = { .min = I9XX_P_LVDS_MIN,       .max = I9XX_P_LVDS_MAX },
+        .p1  = { .min = I9XX_P1_MIN,           .max = I9XX_P1_MAX },
+       /* The single-channel range is 25-112Mhz, and dual-channel
+        * is 80-224Mhz.  Prefer single channel as much as possible.
+        */
+       .p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
+                .p2_slow = I9XX_P2_LVDS_SLOW,  .p2_fast = I9XX_P2_LVDS_FAST },
+    },
+};
+
+static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       const intel_limit_t *limit;
+       
+       if (IS_I9XX(dev)) {
+               if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+                       limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
+               else
+                       limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+       } else {
+               if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+                       limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
+               else
+                       limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
+       }
+       return limit;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+
+static void i8xx_clock(int refclk, intel_clock_t *clock)
+{
+       clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+       clock->p = clock->p1 * clock->p2;
+       clock->vco = refclk * clock->m / (clock->n + 2);
+       clock->dot = clock->vco / clock->p;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
+
+static void i9xx_clock(int refclk, intel_clock_t *clock)
+{
+       clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+       clock->p = clock->p1 * clock->p2;
+       clock->vco = refclk * clock->m / (clock->n + 2);
+       clock->dot = clock->vco / clock->p;
+}
+
+static void intel_clock(struct drm_device *dev, int refclk,
+                       intel_clock_t *clock)
+{
+       if (IS_I9XX(dev))
+               return i9xx_clock (refclk, clock);
+       else
+               return i8xx_clock (refclk, clock);
+}
+
+/**
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
+{
+    struct drm_device *dev = crtc->dev;
+    struct drm_mode_config *mode_config = &dev->mode_config;
+    struct drm_output *l_entry;
+
+    list_for_each_entry(l_entry, &mode_config->output_list, head) {
+           if (l_entry->crtc == crtc) {
+                   struct intel_output *intel_output = l_entry->driver_private;
+                   if (intel_output->type == type)
+                           return true;
+           }
+    }
+    return false;
+}
+
+#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
+/**
+ * Returns whether the given set of divisors are valid for a given refclk with
+ * the given outputs.
+ */
+
+static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
+{
+       const intel_limit_t *limit = intel_limit (crtc);
+       
+       if (clock->p1  < limit->p1.min  || limit->p1.max  < clock->p1)
+               INTELPllInvalid ("p1 out of range\n");
+       if (clock->p   < limit->p.min   || limit->p.max   < clock->p)
+               INTELPllInvalid ("p out of range\n");
+       if (clock->m2  < limit->m2.min  || limit->m2.max  < clock->m2)
+               INTELPllInvalid ("m2 out of range\n");
+       if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
+               INTELPllInvalid ("m1 out of range\n");
+       if (clock->m1 <= clock->m2)
+               INTELPllInvalid ("m1 <= m2\n");
+       if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
+               INTELPllInvalid ("m out of range\n");
+       if (clock->n   < limit->n.min   || limit->n.max   < clock->n)
+               INTELPllInvalid ("n out of range\n");
+       if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+               INTELPllInvalid ("vco out of range\n");
+       /* XXX: We may need to be checking "Dot clock" depending on the multiplier,
+        * output, etc., rather than just a single range.
+        */
+       if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+               INTELPllInvalid ("dot out of range\n");
+       
+       return true;
+}
+
+/**
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
+static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
+                               int refclk, intel_clock_t *best_clock)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       intel_clock_t clock;
+       const intel_limit_t *limit = intel_limit(crtc);
+       int err = target;
+
+       if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+           (I915_READ(LVDS) & LVDS_PORT_EN) != 0) {
+               /*
+                * For LVDS, if the panel is on, just rely on its current
+                * settings for dual-channel.  We haven't figured out how to
+                * reliably set up different single/dual channel state, if we
+                * even can.
+                */
+               if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+                   LVDS_CLKB_POWER_UP)
+                       clock.p2 = limit->p2.p2_fast;
+               else
+                       clock.p2 = limit->p2.p2_slow;
+       } else {
+               if (target < limit->p2.dot_limit)
+                       clock.p2 = limit->p2.p2_slow;
+               else
+                       clock.p2 = limit->p2.p2_fast;
+       }
+       
+       memset (best_clock, 0, sizeof (*best_clock));
+       
+       for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
+               for (clock.m2 = limit->m2.min; clock.m2 < clock.m1 &&
+                            clock.m2 <= limit->m2.max; clock.m2++) {
+                       for (clock.n = limit->n.min; clock.n <= limit->n.max;
+                            clock.n++) {
+                               for (clock.p1 = limit->p1.min;
+                                    clock.p1 <= limit->p1.max; clock.p1++) {
+                                       int this_err;
+                                       
+                                       intel_clock(dev, refclk, &clock);
+                                       
+                                       if (!intel_PLL_is_valid(crtc, &clock))
+                                               continue;
+                                       
+                                       this_err = abs(clock.dot - target);
+                                       if (this_err < err) {
+                                               *best_clock = clock;
+                                               err = this_err;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return (err != target);
+}
+
+void
+intel_set_vblank(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
+       struct intel_crtc *intel_crtc;
+       int vbl_pipe = 0;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               intel_crtc = crtc->driver_private;
+
+               if (crtc->enabled)
+                       vbl_pipe |= (1<<intel_crtc->pipe);
+       }
+
+       dev_priv->vblank_pipe = vbl_pipe;
+       i915_enable_interrupt(dev);
+}
+void
+intel_wait_for_vblank(struct drm_device *dev)
+{
+       /* Wait for 20ms, i.e. one cycle at 50hz. */
+       udelay(20000);
+}
+
+void
+intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       int pipe = intel_crtc->pipe;
+       unsigned long Start, Offset;
+       int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
+       int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
+
+       Start = crtc->fb->offset;
+       Offset = y * crtc->fb->pitch + x;
+
+       DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+       if (IS_I965G(dev)) {
+               I915_WRITE(dspbase, Offset);
+               I915_READ(dspbase);
+               I915_WRITE(dspsurf, Start);
+               I915_READ(dspsurf);
+       } else {
+               I915_WRITE(dspbase, Start + Offset);
+               I915_READ(dspbase);
+       }
+       
+
+       if (!dev_priv->sarea_priv) 
+               return;
+               
+       switch (pipe) {
+       case 0:
+               dev_priv->sarea_priv->planeA_x = x;
+               dev_priv->sarea_priv->planeA_y = y;
+               break;
+       case 1:
+               dev_priv->sarea_priv->planeB_x = x;
+               dev_priv->sarea_priv->planeB_y = y;
+               break;
+       default:
+               DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+               break;
+       }
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       int pipe = intel_crtc->pipe;
+       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+       int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
+       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+       u32 temp;
+       bool enabled;
+
+       /* XXX: When our outputs are all unaware of DPMS modes other than off
+        * and on, we should map those modes to DPMSModeOff in the CRTC.
+        */
+       switch (mode) {
+       case DPMSModeOn:
+       case DPMSModeStandby:
+       case DPMSModeSuspend:
+               /* Enable the DPLL */
+               temp = I915_READ(dpll_reg);
+               if ((temp & DPLL_VCO_ENABLE) == 0) {
+                       I915_WRITE(dpll_reg, temp);
+                       I915_READ(dpll_reg);
+                       /* Wait for the clocks to stabilize. */
+                       udelay(150);
+                       I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+                       I915_READ(dpll_reg);
+                       /* Wait for the clocks to stabilize. */
+                       udelay(150);
+                       I915_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+                       I915_READ(dpll_reg);
+                       /* Wait for the clocks to stabilize. */
+                       udelay(150);
+               }
+               
+               /* Enable the pipe */
+               temp = I915_READ(pipeconf_reg);
+               if ((temp & PIPEACONF_ENABLE) == 0)
+                       I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+               
+               /* Enable the plane */
+               temp = I915_READ(dspcntr_reg);
+               if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+                       I915_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+                       /* Flush the plane changes */
+                       I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
+               }
+               
+               intel_crtc_load_lut(crtc);
+               
+               /* Give the overlay scaler a chance to enable if it's on this pipe */
+               //intel_crtc_dpms_video(crtc, TRUE); TODO
+       break;
+       case DPMSModeOff:
+               /* Give the overlay scaler a chance to disable if it's on this pipe */
+               //intel_crtc_dpms_video(crtc, FALSE); TODO
+               
+               /* Disable the VGA plane that we never use */
+               I915_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+               
+               /* Disable display plane */
+               temp = I915_READ(dspcntr_reg);
+               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+                       I915_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+                       /* Flush the plane changes */
+                       I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
+                       I915_READ(dspbase_reg);
+               }
+               
+               if (!IS_I9XX(dev)) {
+                       /* Wait for vblank for the disable to take effect */
+                       intel_wait_for_vblank(dev);
+               }
+               
+               /* Next, disable display pipes */
+               temp = I915_READ(pipeconf_reg);
+               if ((temp & PIPEACONF_ENABLE) != 0) {
+                       I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+                       I915_READ(pipeconf_reg);
+               }
+               
+               /* Wait for vblank for the disable to take effect. */
+               intel_wait_for_vblank(dev);
+               
+               temp = I915_READ(dpll_reg);
+               if ((temp & DPLL_VCO_ENABLE) != 0) {
+                       I915_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+                       I915_READ(dpll_reg);
+               }
+               
+               /* Wait for the clocks to turn off. */
+               udelay(150);
+               break;
+       }
+       
+
+       if (!dev_priv->sarea_priv)
+               return;
+
+       enabled = crtc->enabled && mode != DPMSModeOff;
+       
+       switch (pipe) {
+       case 0:
+               dev_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0;
+               dev_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0;
+               break;
+       case 1:
+               dev_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0;
+               dev_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0;
+               break;
+       default:
+               DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+               break;
+       }
+}
+
+static bool intel_crtc_lock(struct drm_crtc *crtc)
+{
+   /* Sync the engine before mode switch */
+//   i830WaitSync(crtc->scrn);
+
+#if 0 // TODO def XF86DRI
+    return I830DRILock(crtc->scrn);
+#else
+    return FALSE;
+#endif
+}
+
+static void intel_crtc_unlock (struct drm_crtc *crtc)
+{
+#if 0 // TODO def XF86DRI
+    I830DRIUnlock (crtc->scrn);
+#endif
+}
+
+static void intel_crtc_prepare (struct drm_crtc *crtc)
+{
+       crtc->funcs->dpms(crtc, DPMSModeOff);
+}
+
+static void intel_crtc_commit (struct drm_crtc *crtc)
+{
+       crtc->funcs->dpms(crtc, DPMSModeOn);
+}
+
+void intel_output_prepare (struct drm_output *output)
+{
+       /* lvds has its own version of prepare see intel_lvds_prepare */
+       output->funcs->dpms(output, DPMSModeOff);
+}
+
+void intel_output_commit (struct drm_output *output)
+{
+       /* lvds has its own version of commit see intel_lvds_commit */
+       output->funcs->dpms(output, DPMSModeOn);
+}
+
+static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+
+/** Returns the core display clock speed for i830 - i945 */
+static int intel_get_core_clock_speed(struct drm_device *dev)
+{
+
+       /* Core clock values taken from the published datasheets.
+        * The 830 may go up to 166 Mhz, which we should check.
+        */
+       if (IS_I945G(dev))
+               return 400000;
+       else if (IS_I915G(dev))
+               return 333000;
+       else if (IS_I945GM(dev) || IS_845G(dev))
+               return 200000;
+       else if (IS_I915GM(dev)) {
+               u16 gcfgc = 0;
+
+               pci_read_config_word(dev->pdev, I915_GCFGC, &gcfgc);
+               
+               if (gcfgc & I915_LOW_FREQUENCY_ENABLE)
+                       return 133000;
+               else {
+                       switch (gcfgc & I915_DISPLAY_CLOCK_MASK) {
+                       case I915_DISPLAY_CLOCK_333_MHZ:
+                               return 333000;
+                       default:
+                       case I915_DISPLAY_CLOCK_190_200_MHZ:
+                               return 190000;
+                       }
+               }
+       } else if (IS_I865G(dev))
+               return 266000;
+       else if (IS_I855(dev)) {
+#if 0
+               PCITAG bridge = pciTag(0, 0, 0); /* This is always the host bridge */
+               u16 hpllcc = pciReadWord(bridge, I855_HPLLCC);
+               
+#endif
+               u16 hpllcc = 0;
+               /* Assume that the hardware is in the high speed state.  This
+                * should be the default.
+                */
+               switch (hpllcc & I855_CLOCK_CONTROL_MASK) {
+               case I855_CLOCK_133_200:
+               case I855_CLOCK_100_200:
+                       return 200000;
+               case I855_CLOCK_166_250:
+                       return 250000;
+               case I855_CLOCK_100_133:
+                       return 133000;
+               }
+       } else /* 852, 830 */
+               return 133000;
+       
+       return 0; /* Silence gcc warning */
+}
+
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int intel_panel_fitter_pipe (struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32  pfit_control;
+    
+       /* i830 doesn't have a panel fitter */
+       if (IS_I830(dev))
+               return -1;
+    
+       pfit_control = I915_READ(PFIT_CONTROL);
+    
+       /* See if the panel fitter is in use */
+       if ((pfit_control & PFIT_ENABLE) == 0)
+               return -1;
+       
+       /* 965 can place panel fitter on either pipe */
+       if (IS_I965G(dev))
+               return (pfit_control >> 29) & 0x3;
+       
+       /* older chips can only use pipe 1 */
+       return 1;
+}
+
+static void intel_crtc_mode_set(struct drm_crtc *crtc,
+                               struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode,
+                               int x, int y)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       int pipe = intel_crtc->pipe;
+       int fp_reg = (pipe == 0) ? FPA0 : FPB0;
+       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+       int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
+       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+       int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+       int dspstride_reg = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
+       int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+       int refclk;
+       intel_clock_t clock;
+       u32 dpll = 0, fp = 0, dspcntr, pipeconf;
+       bool ok, is_sdvo = false, is_dvo = false;
+       bool is_crt = false, is_lvds = false, is_tv = false;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_output *output;
+
+       list_for_each_entry(output, &mode_config->output_list, head) {
+               struct intel_output *intel_output = output->driver_private;
+
+               if (output->crtc != crtc)
+                       continue;
+
+               switch (intel_output->type) {
+               case INTEL_OUTPUT_LVDS:
+                       is_lvds = TRUE;
+                       break;
+               case INTEL_OUTPUT_SDVO:
+                       is_sdvo = TRUE;
+                       break;
+               case INTEL_OUTPUT_DVO:
+                       is_dvo = TRUE;
+                       break;
+               case INTEL_OUTPUT_TVOUT:
+                       is_tv = TRUE;
+                       break;
+               case INTEL_OUTPUT_ANALOG:
+                       is_crt = TRUE;
+                       break;
+               }
+       }
+       
+       if (IS_I9XX(dev)) {
+               refclk = 96000;
+       } else {
+               refclk = 48000;
+       }
+
+       ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
+       if (!ok) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return;
+       }
+
+       fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+       
+       dpll = DPLL_VGA_MODE_DIS;
+       if (IS_I9XX(dev)) {
+               if (is_lvds)
+                       dpll |= DPLLB_MODE_LVDS;
+               else
+                       dpll |= DPLLB_MODE_DAC_SERIAL;
+               if (is_sdvo) {
+                       dpll |= DPLL_DVO_HIGH_SPEED;
+                       if (IS_I945G(dev) || IS_I945GM(dev)) {
+                               int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
+                               dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+                       }
+               }
+               
+               /* compute bitmask from p1 value */
+               dpll |= (1 << (clock.p1 - 1)) << 16;
+               switch (clock.p2) {
+               case 5:
+                       dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+                       break;
+               case 7:
+                       dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+                       break;
+               case 10:
+                       dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+                       break;
+               case 14:
+                       dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+                       break;
+               }
+               if (IS_I965G(dev))
+                       dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
+       } else {
+               if (is_lvds) {
+                       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+               } else {
+                       if (clock.p1 == 2)
+                               dpll |= PLL_P1_DIVIDE_BY_TWO;
+                       else
+                               dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+                       if (clock.p2 == 4)
+                               dpll |= PLL_P2_DIVIDE_BY_4;
+               }
+       }
+       
+       if (is_tv) {
+               /* XXX: just matching BIOS for now */
+/*     dpll |= PLL_REF_INPUT_TVCLKINBC; */
+               dpll |= 3;
+       }
+#if 0
+       else if (is_lvds)
+               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+#endif
+       else
+               dpll |= PLL_REF_INPUT_DREFCLK;
+       
+       /* setup pipeconf */
+       pipeconf = I915_READ(pipeconf_reg);
+
+       /* Set up the display plane register */
+       dspcntr = DISPPLANE_GAMMA_ENABLE;
+
+       switch (crtc->fb->bits_per_pixel) {
+       case 8:
+               dspcntr |= DISPPLANE_8BPP;
+               break;
+       case 16:
+               if (crtc->fb->depth == 15)
+                       dspcntr |= DISPPLANE_15_16BPP;
+               else
+                       dspcntr |= DISPPLANE_16BPP;
+               break;
+       case 32:
+               dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+               break;
+       default:
+               DRM_ERROR("Unknown color depth\n");
+               return;
+       }
+       
+
+       if (pipe == 0)
+               dspcntr |= DISPPLANE_SEL_PIPE_A;
+       else
+               dspcntr |= DISPPLANE_SEL_PIPE_B;
+       
+       if (pipe == 0 && !IS_I965G(dev)) {
+               /* Enable pixel doubling when the dot clock is > 90% of the (display)
+                * core speed.
+                *
+                * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
+                * pipe == 0 check?
+                */
+               if (mode->clock > intel_get_core_clock_speed(dev) * 9 / 10)
+                       pipeconf |= PIPEACONF_DOUBLE_WIDE;
+               else
+                       pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
+       }
+
+       dspcntr |= DISPLAY_PLANE_ENABLE;
+       pipeconf |= PIPEACONF_ENABLE;
+       dpll |= DPLL_VCO_ENABLE;
+
+       
+       /* Disable the panel fitter if it was on our pipe */
+       if (intel_panel_fitter_pipe(dev) == pipe)
+               I915_WRITE(PFIT_CONTROL, 0);
+
+       DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+       drm_mode_debug_printmodeline(dev, mode);
+       
+#if 0
+       if (!xf86ModesEqual(mode, adjusted_mode)) {
+               xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+                          "Adjusted mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+               xf86PrintModeline(pScrn->scrnIndex, mode);
+       }
+       i830PrintPll("chosen", &clock);
+#endif
+
+       if (dpll & DPLL_VCO_ENABLE) {
+               I915_WRITE(fp_reg, fp);
+               I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
+               I915_READ(dpll_reg);
+               udelay(150);
+       }
+       
+       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
+        * This is an exception to the general rule that mode_set doesn't turn
+        * things on.
+        */
+       if (is_lvds) {
+               u32 lvds = I915_READ(LVDS);
+               
+               lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
+               /* Set the B0-B3 data pairs corresponding to whether we're going to
+                * set the DPLLs for dual-channel mode or not.
+                */
+               if (clock.p2 == 7)
+                       lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+               else
+                       lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+               
+               /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+                * appropriately here, but we need to look more thoroughly into how
+                * panels behave in the two modes.
+                */
+               
+               I915_WRITE(LVDS, lvds);
+               I915_READ(LVDS);
+       }
+       
+       I915_WRITE(fp_reg, fp);
+       I915_WRITE(dpll_reg, dpll);
+       I915_READ(dpll_reg);
+       /* Wait for the clocks to stabilize. */
+       udelay(150);
+       
+       if (IS_I965G(dev)) {
+               int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
+               I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+                          ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+       } else {
+               /* write it again -- the BIOS does, after all */
+               I915_WRITE(dpll_reg, dpll);
+       }
+       I915_READ(dpll_reg);
+       /* Wait for the clocks to stabilize. */
+       udelay(150);
+       
+       I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+                  ((adjusted_mode->crtc_htotal - 1) << 16));
+       I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+                  ((adjusted_mode->crtc_hblank_end - 1) << 16));
+       I915_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+                  ((adjusted_mode->crtc_hsync_end - 1) << 16));
+       I915_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+                  ((adjusted_mode->crtc_vtotal - 1) << 16));
+       I915_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+                  ((adjusted_mode->crtc_vblank_end - 1) << 16));
+       I915_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+                  ((adjusted_mode->crtc_vsync_end - 1) << 16));
+       I915_WRITE(dspstride_reg, crtc->fb->pitch);
+       /* pipesrc and dspsize control the size that is scaled from, which should
+        * always be the user's requested size.
+        */
+       I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+       I915_WRITE(dsppos_reg, 0);
+       I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+       I915_WRITE(pipeconf_reg, pipeconf);
+       I915_READ(pipeconf_reg);
+       
+       intel_wait_for_vblank(dev);
+       
+       I915_WRITE(dspcntr_reg, dspcntr);
+       
+       /* Flush the plane changes */
+       intel_pipe_set_base(crtc, x, y);
+       
+       intel_set_vblank(dev);
+
+       intel_wait_for_vblank(dev);    
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
+       int i;
+
+       /* The clocks have to be on to load the palette. */
+       if (!crtc->enabled)
+               return;
+
+       for (i = 0; i < 256; i++) {
+               I915_WRITE(palreg + 4 * i,
+                          (intel_crtc->lut_r[i] << 16) |
+                          (intel_crtc->lut_g[i] << 8) |
+                          intel_crtc->lut_b[i]);
+       }
+}
+
+/** Sets the color ramps on behalf of RandR */
+static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+                                u16 blue, int regno)
+{
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       
+       intel_crtc->lut_r[regno] = red >> 8;
+       intel_crtc->lut_g[regno] = green >> 8;
+       intel_crtc->lut_b[regno] = blue >> 8;
+}
+
+/* Returns the clock of the currently programmed mode of the given pipe. */
+static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       int pipe = intel_crtc->pipe;
+       u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B);
+       u32 fp;
+       intel_clock_t clock;
+
+       if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+               fp = I915_READ((pipe == 0) ? FPA0 : FPB0);
+       else
+               fp = I915_READ((pipe == 0) ? FPA1 : FPB1);
+
+       clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
+       clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+       clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
+       if (IS_I9XX(dev)) {
+               clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
+                              DPLL_FPA01_P1_POST_DIV_SHIFT);
+
+               switch (dpll & DPLL_MODE_MASK) {
+               case DPLLB_MODE_DAC_SERIAL:
+                       clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ?
+                               5 : 10;
+                       break;
+               case DPLLB_MODE_LVDS:
+                       clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ?
+                               7 : 14;
+                       break;
+               default:
+                       DRM_DEBUG("Unknown DPLL mode %08x in programmed "
+                                 "mode\n", (int)(dpll & DPLL_MODE_MASK));
+                       return 0;
+               }
+
+               /* XXX: Handle the 100Mhz refclk */
+               i9xx_clock(96000, &clock);
+       } else {
+               bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
+
+               if (is_lvds) {
+                       clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+                                      DPLL_FPA01_P1_POST_DIV_SHIFT);
+                       clock.p2 = 14;
+
+                       if ((dpll & PLL_REF_INPUT_MASK) ==
+                           PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+                               /* XXX: might not be 66MHz */
+                               i8xx_clock(66000, &clock);
+                       } else
+                               i8xx_clock(48000, &clock);              
+               } else {
+                       if (dpll & PLL_P1_DIVIDE_BY_TWO)
+                               clock.p1 = 2;
+                       else {
+                               clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+                                           DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+                       }
+                       if (dpll & PLL_P2_DIVIDE_BY_4)
+                               clock.p2 = 4;
+                       else
+                               clock.p2 = 2;
+
+                       i8xx_clock(48000, &clock);
+               }
+       }
+
+       /* XXX: It would be nice to validate the clocks, but we can't reuse
+        * i830PllIsValid() because it relies on the xf86_config output
+        * configuration being accurate, which it isn't necessarily.
+        */
+
+       return clock.dot;
+}
+
+/** Returns the currently programmed mode of the given pipe. */
+struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
+                                            struct drm_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       int pipe = intel_crtc->pipe;
+       struct drm_display_mode *mode;
+       int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
+       int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
+       int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
+       int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+
+       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+       if (!mode)
+               return NULL;
+
+       mode->clock = intel_crtc_clock_get(dev, crtc);
+       mode->hdisplay = (htot & 0xffff) + 1;
+       mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
+       mode->hsync_start = (hsync & 0xffff) + 1;
+       mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
+       mode->vdisplay = (vtot & 0xffff) + 1;
+       mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
+       mode->vsync_start = (vsync & 0xffff) + 1;
+       mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
+
+       drm_mode_set_name(mode);
+       drm_mode_set_crtcinfo(mode, 0);
+
+       return mode;
+}
+
+static const struct drm_crtc_funcs intel_crtc_funcs = {
+       .dpms = intel_crtc_dpms,
+       .lock = intel_crtc_lock,
+       .unlock = intel_crtc_unlock,
+       .mode_fixup = intel_crtc_mode_fixup,
+       .mode_set = intel_crtc_mode_set,
+       .gamma_set = intel_crtc_gamma_set,
+       .prepare = intel_crtc_prepare,
+       .commit = intel_crtc_commit,
+};
+
+
+void intel_crtc_init(struct drm_device *dev, int pipe)
+{
+       struct drm_crtc *crtc;
+       struct intel_crtc *intel_crtc;
+       int i;
+
+       crtc = drm_crtc_create(dev, &intel_crtc_funcs);
+       if (crtc == NULL)
+               return;
+
+       intel_crtc = kzalloc(sizeof(struct intel_crtc), GFP_KERNEL);
+       if (intel_crtc == NULL) {
+               kfree(crtc);
+               return;
+       }
+
+       intel_crtc->pipe = pipe;
+       for (i = 0; i < 256; i++) {
+               intel_crtc->lut_r[i] = i;
+               intel_crtc->lut_g[i] = i;
+               intel_crtc->lut_b[i] = i;
+       }
+
+       crtc->driver_private = intel_crtc;
+}
+
+struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
+{
+       struct drm_crtc *crtc = NULL;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct intel_crtc *intel_crtc = crtc->driver_private;
+               if (intel_crtc->pipe == pipe)
+                       break;
+       }
+       return crtc;
+}
+
+int intel_output_clones(struct drm_device *dev, int type_mask)
+{
+       int index_mask = 0;
+       struct drm_output *output;
+       int entry = 0;
+
+        list_for_each_entry(output, &dev->mode_config.output_list, head) {
+               struct intel_output *intel_output = output->driver_private;
+               if (type_mask & (1 << intel_output->type))
+                       index_mask |= (1 << entry);
+               entry++;
+       }
+       return index_mask;
+}
+
+
+static void intel_setup_outputs(struct drm_device *dev)
+{
+       struct drm_output *output;
+
+       intel_crt_init(dev);
+
+       /* Set up integrated LVDS */
+       if (IS_MOBILE(dev) && !IS_I830(dev))
+               intel_lvds_init(dev);
+
+       if (IS_I9XX(dev)) {
+               intel_sdvo_init(dev, SDVOB);
+               intel_sdvo_init(dev, SDVOC);
+       }
+
+       list_for_each_entry(output, &dev->mode_config.output_list, head) {
+               struct intel_output *intel_output = output->driver_private;
+               int crtc_mask = 0, clone_mask = 0;
+               
+               /* valid crtcs */
+               switch(intel_output->type) {
+               case INTEL_OUTPUT_DVO:
+               case INTEL_OUTPUT_SDVO:
+                       crtc_mask = ((1 << 0)|
+                                    (1 << 1));
+                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
+                                     (1 << INTEL_OUTPUT_DVO) |
+                                     (1 << INTEL_OUTPUT_SDVO));
+                       break;
+               case INTEL_OUTPUT_ANALOG:
+                       crtc_mask = ((1 << 0)|
+                                    (1 << 1));
+                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
+                                     (1 << INTEL_OUTPUT_DVO) |
+                                     (1 << INTEL_OUTPUT_SDVO));
+                       break;
+               case INTEL_OUTPUT_LVDS:
+                       crtc_mask = (1 << 1);
+                       clone_mask = (1 << INTEL_OUTPUT_LVDS);
+                       break;
+               case INTEL_OUTPUT_TVOUT:
+                       crtc_mask = ((1 << 0) |
+                                    (1 << 1));
+                       clone_mask = (1 << INTEL_OUTPUT_TVOUT);
+                       break;
+               }
+               output->possible_crtcs = crtc_mask;
+               output->possible_clones = intel_output_clones(dev, clone_mask);
+       }
+}
+
+void intel_modeset_init(struct drm_device *dev)
+{
+       int num_pipe;
+       int i;
+
+       drm_mode_config_init(dev);
+
+       dev->mode_config.min_width = 0;
+       dev->mode_config.min_height = 0;
+
+       dev->mode_config.max_width = 4096;
+       dev->mode_config.max_height = 4096;
+
+       /* set memory base */
+       if (IS_I9XX(dev))
+               dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2);
+       else
+               dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
+
+       if (IS_MOBILE(dev) || IS_I9XX(dev))
+               num_pipe = 2;
+       else
+               num_pipe = 1;
+       DRM_DEBUG("%d display pipe%s available.\n",
+                 num_pipe, num_pipe > 1 ? "s" : "");
+
+       for (i = 0; i < num_pipe; i++) {
+               intel_crtc_init(dev, i);
+       }
+
+       intel_setup_outputs(dev);
+
+       //drm_initial_config(dev, false);
+}
+
+void intel_modeset_cleanup(struct drm_device *dev)
+{
+       drm_mode_config_cleanup(dev);
+}
diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h
new file mode 100644 (file)
index 0000000..7de4b92
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
+ * Copyright (c) 2007 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ */
+#ifndef __INTEL_DRV_H__
+#define __INTEL_DRV_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+#include "drm_crtc.h"
+
+/*
+ * Display related stuff
+ */
+
+/* store information about an Ixxx DVO */
+/* The i830->i865 use multiple DVOs with multiple i2cs */
+/* the i915, i945 have a single sDVO i2c bus - which is different */
+#define MAX_OUTPUTS 6
+
+#define INTEL_I2C_BUS_DVO 1
+#define INTEL_I2C_BUS_SDVO 2
+
+/* these are outputs from the chip - integrated only 
+   external chips are via DVO or SDVO output */
+#define INTEL_OUTPUT_UNUSED 0
+#define INTEL_OUTPUT_ANALOG 1
+#define INTEL_OUTPUT_DVO 2
+#define INTEL_OUTPUT_SDVO 3
+#define INTEL_OUTPUT_LVDS 4
+#define INTEL_OUTPUT_TVOUT 5
+
+#define INTEL_DVO_CHIP_NONE 0
+#define INTEL_DVO_CHIP_LVDS 1
+#define INTEL_DVO_CHIP_TMDS 2
+#define INTEL_DVO_CHIP_TVOUT 4
+
+struct intel_i2c_chan {
+       struct drm_device *drm_dev; /* for getting at dev. private (mmio etc.) */
+       u32 reg; /* GPIO reg */
+       struct i2c_adapter adapter;
+       struct i2c_algo_bit_data algo;
+        u8 slave_addr;
+};
+
+struct intel_output {
+       int type;
+       struct intel_i2c_chan *i2c_bus; /* for control functions */
+       struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */
+       bool load_detect_tmp;
+       void *dev_priv;
+};
+
+struct intel_crtc {
+       int pipe;
+       u8 lut_r[256], lut_g[256], lut_b[256];
+};
+
+struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
+                                       const char *name);
+void intel_i2c_destroy(struct intel_i2c_chan *chan);
+int intel_ddc_get_modes(struct drm_output *output);
+extern bool intel_ddc_probe(struct drm_output *output);
+
+extern void intel_crt_init(struct drm_device *dev);
+extern void intel_sdvo_init(struct drm_device *dev, int output_device);
+extern void intel_lvds_init(struct drm_device *dev);
+
+extern void intel_crtc_load_lut(struct drm_crtc *crtc);
+extern void intel_output_prepare (struct drm_output *output);
+extern void intel_output_commit (struct drm_output *output);
+extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
+                                                   struct drm_crtc *crtc);
+extern void intel_wait_for_vblank(struct drm_device *dev);
+extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
+
+extern int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
+extern int intelfb_remove(struct drm_device *dev, struct drm_crtc *crtc);
+
+#endif /* __INTEL_DRV_H__ */
diff --git a/linux-core/intel_fb.c b/linux-core/intel_fb.c
new file mode 100644 (file)
index 0000000..564a913
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * Copyright © 2007 David Airlie
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     David Airlie
+ */
+    /*
+     *  Modularization
+     */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+struct intelfb_par {
+       struct drm_device *dev;
+       struct drm_crtc *crtc;
+};
+
+static int
+var_to_refresh(const struct fb_var_screeninfo *var)
+{
+       int xtot = var->xres + var->left_margin + var->right_margin +
+                  var->hsync_len;
+       int ytot = var->yres + var->upper_margin + var->lower_margin +
+                  var->vsync_len;
+
+       return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
+}
+
+static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       struct intelfb_par *par = info->par;
+       struct drm_framebuffer *fb = par->crtc->fb;
+       struct drm_crtc *crtc = par->crtc;
+
+       if (regno > 255)
+               return 1;
+
+       if (fb->depth == 8) {
+               if (crtc->funcs->gamma_set)
+                       crtc->funcs->gamma_set(crtc, red, green, blue, regno);
+               return 0;
+       }
+
+       if (regno < 16) {
+               switch (fb->depth) {
+               case 15:
+                       fb->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
+                               ((green & 0xf800) >>  6) |
+                               ((blue & 0xf800) >> 11);
+                       break;
+               case 16:
+                       fb->pseudo_palette[regno] = (red & 0xf800) |
+                               ((green & 0xfc00) >>  5) |
+                               ((blue  & 0xf800) >> 11);
+                       break;
+               case 24:
+               case 32:
+                       fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
+                               (green & 0xff00) |
+                               ((blue  & 0xff00) >> 8);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int intelfb_check_var(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
+{
+        struct intelfb_par *par = info->par;
+        struct drm_device *dev = par->dev;
+       struct drm_framebuffer *fb = par->crtc->fb;
+        struct drm_display_mode *drm_mode;
+        struct drm_output *output;
+        int depth, found = 0;
+
+        if (!var->pixclock)
+                return -EINVAL;
+
+        /* Need to resize the fb object !!! */
+        if (var->xres > fb->width || var->yres > fb->height) {
+                DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
+                DRM_ERROR("Need resizing code.\n");
+                return -EINVAL;
+        }
+
+        switch (var->bits_per_pixel) {
+        case 16:
+                depth = (var->green.length == 6) ? 16 : 15;
+                break;
+        case 32:
+                depth = (var->transp.length > 0) ? 32 : 24;
+                break;
+        default:
+                depth = var->bits_per_pixel;
+                break;
+        }
+                
+        switch (depth) {
+        case 8:
+                var->red.offset = 0;
+                var->green.offset = 0;
+                var->blue.offset = 0;
+                var->red.length = 8;
+                var->green.length = 8;
+                var->blue.length = 8;
+                var->transp.length = 0;
+                var->transp.offset = 0;
+                break;
+        case 15:
+                var->red.offset = 10;
+                var->green.offset = 5;
+                var->blue.offset = 0;
+                var->red.length = 5;
+                var->green.length = 5;
+                var->blue.length = 5;
+                var->transp.length = 1;
+                var->transp.offset = 15;
+                break;
+        case 16:
+                var->red.offset = 11;
+                var->green.offset = 6;
+                var->blue.offset = 0;
+                var->red.length = 5;
+                var->green.length = 6;
+                var->blue.length = 5;
+                var->transp.length = 0;
+                var->transp.offset = 0;
+                break;
+        case 24:
+                var->red.offset = 16;
+                var->green.offset = 8;
+                var->blue.offset = 0;
+                var->red.length = 8;
+                var->green.length = 8;
+                var->blue.length = 8;
+                var->transp.length = 0;
+                var->transp.offset = 0;
+                break;
+        case 32:
+                var->red.offset = 16;
+                var->green.offset = 8;
+                var->blue.offset = 0;
+                var->red.length = 8;
+                var->green.length = 8;
+                var->blue.length = 8;
+                var->transp.length = 8;
+                var->transp.offset = 24;
+                break;
+        default:
+                return -EINVAL; 
+        }
+
+#if 0
+        /* Here we walk the output mode list and look for modes. If we haven't
+         * got it, then bail. Not very nice, so this is disabled.
+         * In the set_par code, we create our mode based on the incoming
+         * parameters. Nicer, but may not be desired by some.
+         */
+        list_for_each_entry(output, &dev->mode_config.output_list, head) {
+                if (output->crtc == par->crtc)
+                        break;
+        }
+    
+        list_for_each_entry(drm_mode, &output->modes, head) {
+                if (drm_mode->hdisplay == var->xres &&
+                    drm_mode->vdisplay == var->yres &&
+                    (((PICOS2KHZ(var->pixclock))/1000) >= ((drm_mode->clock/1000)-1)) &&
+                    (((PICOS2KHZ(var->pixclock))/1000) <= ((drm_mode->clock/1000)+1))) {
+                       found = 1;
+                       break;
+               }
+       }
+        if (!found)
+                return -EINVAL;
+#endif
+
+       return 0;
+}
+
+/* this will let fbcon do the mode init */
+/* FIXME: take mode config lock? */
+static int intelfb_set_par(struct fb_info *info)
+{
+       struct intelfb_par *par = info->par;
+       struct drm_framebuffer *fb = par->crtc->fb;
+       struct drm_device *dev = par->dev;
+        struct drm_display_mode *drm_mode;
+        struct drm_output *output;
+        struct fb_var_screeninfo *var = &info->var;
+       int found = 0;
+
+        switch (var->bits_per_pixel) {
+        case 16:
+                fb->depth = (var->green.length == 6) ? 16 : 15;
+                break;
+        case 32:
+                fb->depth = (var->transp.length > 0) ? 32 : 24;
+                break;
+        default:
+                fb->depth = var->bits_per_pixel;
+                break;
+        }
+
+        fb->bits_per_pixel = var->bits_per_pixel;
+
+        info->fix.line_length = fb->pitch;
+        info->fix.smem_len = info->fix.line_length * fb->height;
+        info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+
+        info->screen_size = info->fix.smem_len; /* ??? */
+
+        /* Should we walk the output's modelist or just create our own ???
+         * For now, we create and destroy a mode based on the incoming 
+         * parameters. But there's commented out code below which scans 
+         * the output list too.
+         */
+#if 0
+        list_for_each_entry(output, &dev->mode_config.output_list, head) {
+                if (output->crtc == par->crtc)
+                        break;
+        }
+    
+        list_for_each_entry(drm_mode, &output->modes, head) {
+                if (drm_mode->hdisplay == var->xres &&
+                    drm_mode->vdisplay == var->yres &&
+                    (((PICOS2KHZ(var->pixclock))/1000) >= ((drm_mode->clock/1000)-1)) &&
+                    (((PICOS2KHZ(var->pixclock))/1000) <= ((drm_mode->clock/1000)+1))) {
+                       found = 1;
+                       break;
+               }
+        }
+
+       if (!found) {
+               DRM_ERROR("Couldn't find a mode for requested %dx%d-%d\n",
+                       var->xres,var->yres,var_to_refresh(var));
+               return -EINVAL;
+       }
+#else
+        drm_mode = drm_mode_create(dev);
+        drm_mode->hdisplay = var->xres;
+        drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
+        drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len;
+        drm_mode->htotal = drm_mode->hsync_end + var->left_margin;
+        drm_mode->vdisplay = var->yres;
+        drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin;
+        drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len;
+        drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin;
+        drm_mode->clock = PICOS2KHZ(var->pixclock);
+        drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
+        drm_mode_set_name(drm_mode);
+       drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V);
+#endif
+
+       drm_mode_debug_printmodeline(dev, drm_mode);
+
+        if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0))
+                return -EINVAL;
+
+        /* Have to destroy our created mode if we're not searching the mode
+         * list for it.
+         */
+#if 1
+        drm_mode_destroy(dev, drm_mode);
+#endif
+
+       return 0;
+}
+
+#if 0
+static void intelfb_copyarea(struct fb_info *info,
+                            const struct fb_copyarea *region)
+{
+        struct intelfb_par *par = info->par;
+       struct drm_device *dev = par->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 src_x1, src_y1, dst_x1, dst_y1, dst_x2, dst_y2, offset;
+       u32 cmd, rop_depth_pitch, src_pitch;
+       RING_LOCALS;
+
+       cmd = XY_SRC_COPY_BLT_CMD;
+       src_x1 = region->sx;
+       src_y1 = region->sy;
+       dst_x1 = region->dx;
+       dst_y1 = region->dy;
+       dst_x2 = region->dx + region->width;
+       dst_y2 = region->dy + region->height;
+       offset = par->fb->offset;
+       rop_depth_pitch = BLT_ROP_GXCOPY | par->fb->pitch;
+       src_pitch = par->fb->pitch;
+
+       switch (par->fb->bits_per_pixel) {
+       case 16:
+               rop_depth_pitch |= BLT_DEPTH_16_565;
+               break;
+       case 32:
+               rop_depth_pitch |= BLT_DEPTH_32;
+               cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
+               break;
+       }
+
+       BEGIN_LP_RING(8);
+       OUT_RING(cmd);
+       OUT_RING(rop_depth_pitch);
+       OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
+       OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
+       OUT_RING(offset);
+       OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
+       OUT_RING(src_pitch);
+       OUT_RING(offset);
+       ADVANCE_LP_RING();
+}
+
+#define ROUND_UP_TO(x, y)      (((x) + (y) - 1) / (y) * (y))
+#define ROUND_DOWN_TO(x, y)    ((x) / (y) * (y))
+
+void intelfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+        struct intelfb_par *par = info->par;
+       struct drm_device *dev = par->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 cmd, rop_pitch_depth, tmp;
+       int nbytes, ndwords, pad;
+       u32 dst_x1, dst_y1, dst_x2, dst_y2, offset, bg, fg;
+       int dat, ix, iy, iw;
+       int i, j;
+       RING_LOCALS;
+
+       /* size in bytes of a padded scanline */
+       nbytes = ROUND_UP_TO(image->width, 16) / 8;
+
+       /* Total bytes of padded scanline data to write out. */
+       nbytes *= image->height;
+
+       /*
+        * Check if the glyph data exceeds the immediate mode limit.
+        * It would take a large font (1K pixels) to hit this limit.
+        */
+       if (nbytes > 128 || image->depth != 1)
+               return cfb_imageblit(info, image);
+
+       /* Src data is packaged a dword (32-bit) at a time. */
+       ndwords = ROUND_UP_TO(nbytes, 4) / 4;
+
+       /*
+        * Ring has to be padded to a quad word. But because the command starts
+          with 7 bytes, pad only if there is an even number of ndwords
+        */
+       pad = !(ndwords % 2);
+
+       DRM_DEBUG("imageblit %dx%dx%d to (%d,%d)\n", image->width,
+                 image->height, image->depth, image->dx, image->dy);
+       DRM_DEBUG("nbytes: %d, ndwords: %d, pad: %d\n", nbytes, ndwords, pad);
+
+       tmp = (XY_MONO_SRC_COPY_IMM_BLT & 0xff) + ndwords;
+       cmd = (XY_MONO_SRC_COPY_IMM_BLT & ~0xff) | tmp;
+       offset = par->fb->offset;
+       dst_x1 = image->dx;
+       dst_y1 = image->dy;
+       dst_x2 = image->dx + image->width;
+       dst_y2 = image->dy + image->height;
+       rop_pitch_depth = BLT_ROP_GXCOPY | par->fb->pitch;
+
+       switch (par->fb->bits_per_pixel) {
+       case 8:
+               rop_pitch_depth |= BLT_DEPTH_8;
+               fg = image->fg_color;
+               bg = image->bg_color;
+               break;
+       case 16:
+               rop_pitch_depth |= BLT_DEPTH_16_565;
+               fg = par->fb->pseudo_palette[image->fg_color];
+               bg = par->fb->pseudo_palette[image->bg_color];
+               break;
+       case 32:
+               rop_pitch_depth |= BLT_DEPTH_32;
+               cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
+               fg = par->fb->pseudo_palette[image->fg_color];
+               bg = par->fb->pseudo_palette[image->bg_color];
+               break;
+       default:
+               DRM_ERROR("unknown depth %d\n", par->fb->bits_per_pixel);
+               break;
+       }
+       
+       BEGIN_LP_RING(8 + ndwords);
+       OUT_RING(cmd);
+       OUT_RING(rop_pitch_depth);
+       OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
+       OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
+       OUT_RING(offset);
+       OUT_RING(bg);
+       OUT_RING(fg);
+       ix = iy = 0;
+       iw = ROUND_UP_TO(image->width, 8) / 8;
+       while (ndwords--) {
+               dat = 0;
+               for (j = 0; j < 2; ++j) {
+                       for (i = 0; i < 2; ++i) {
+                               if (ix != iw || i == 0)
+                                       dat |= image->data[iy*iw + ix++] << (i+j*2)*8;
+                       }
+                       if (ix == iw && iy != (image->height - 1)) {
+                               ix = 0;
+                               ++iy;
+                       }
+               }
+               OUT_RING(dat);
+       }
+       if (pad)
+               OUT_RING(MI_NOOP);
+       ADVANCE_LP_RING();
+}
+#endif
+
+static struct fb_ops intelfb_ops = {
+       .owner = THIS_MODULE,
+       //      .fb_open = intelfb_open,
+       //      .fb_read = intelfb_read,
+       //      .fb_write = intelfb_write,
+       //      .fb_release = intelfb_release,
+       //      .fb_ioctl = intelfb_ioctl,
+       .fb_check_var = intelfb_check_var,
+       .fb_set_par = intelfb_set_par,
+       .fb_setcolreg = intelfb_setcolreg,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea, //intelfb_copyarea,
+       .fb_imageblit = cfb_imageblit, //intelfb_imageblit,
+};
+
+int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc)
+{
+       struct fb_info *info;
+       struct intelfb_par *par;
+       struct device *device = &dev->pdev->dev; 
+       struct drm_framebuffer *fb;
+       struct drm_display_mode *mode = crtc->desired_mode;
+       struct drm_buffer_object *fbo = NULL;
+       int ret;
+
+       info = framebuffer_alloc(sizeof(struct intelfb_par), device);
+       if (!info){
+               return -EINVAL;
+       }
+
+       fb = drm_framebuffer_create(dev);
+       if (!fb) {
+               framebuffer_release(info);
+               DRM_ERROR("failed to allocate fb.\n");
+               return -EINVAL;
+       }
+       crtc->fb = fb;
+
+       fb->width = crtc->desired_mode->hdisplay;
+       fb->height = crtc->desired_mode->vdisplay;
+
+       fb->bits_per_pixel = 32;
+       fb->pitch = fb->width * ((fb->bits_per_pixel + 1) / 8);
+       fb->depth = 24;
+       ret = drm_buffer_object_create(dev, fb->width * fb->height * 4, 
+                                      drm_bo_type_kernel,
+                                      DRM_BO_FLAG_READ |
+                                      DRM_BO_FLAG_WRITE |
+                                      DRM_BO_FLAG_MEM_TT |
+                                      DRM_BO_FLAG_MEM_VRAM |
+                                      DRM_BO_FLAG_NO_EVICT,
+                                      DRM_BO_HINT_DONT_FENCE, 0, 0,
+                                      &fbo);
+       if (ret || !fbo) {
+               printk(KERN_ERR "failed to allocate framebuffer\n");
+               drm_framebuffer_destroy(fb);
+               framebuffer_release(info);
+               return -EINVAL;
+       }
+
+       fb->offset = fbo->offset;
+       fb->bo = fbo;
+       printk("allocated %dx%d fb: 0x%08lx, bo %p\n", fb->width,
+                      fb->height, fbo->offset, fbo);
+
+
+       fb->fbdev = info;
+               
+       par = info->par;
+
+       par->dev = dev;
+       par->crtc = crtc;
+
+       info->fbops = &intelfb_ops;
+
+       strcpy(info->fix.id, "intelfb");
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_TRUECOLOR;
+       info->fix.type_aux = 0;
+       info->fix.xpanstep = 8;
+       info->fix.ypanstep = 1;
+       info->fix.ywrapstep = 0;
+       info->fix.accel = FB_ACCEL_I830;
+       info->fix.type_aux = 0;
+       info->fix.mmio_start = 0;
+       info->fix.mmio_len = 0;
+       info->fix.line_length = fb->pitch;
+       info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
+       info->fix.smem_len = info->fix.line_length * fb->height;
+
+       info->flags = FBINFO_DEFAULT;
+
+       ret = drm_mem_reg_ioremap(dev, &fb->bo->mem, &fb->virtual_base);
+       if (ret)
+               DRM_ERROR("error mapping fb: %d\n", ret);
+
+       info->screen_base = fb->virtual_base;
+       info->screen_size = info->fix.smem_len; /* FIXME */
+       info->pseudo_palette = fb->pseudo_palette;
+       info->var.xres_virtual = fb->width;
+       info->var.yres_virtual = fb->height;
+       info->var.bits_per_pixel = fb->bits_per_pixel;
+       info->var.xoffset = 0;
+       info->var.yoffset = 0;
+       info->var.activate = FB_ACTIVATE_NOW;
+       info->var.height = -1;
+       info->var.width = -1;
+       info->var.vmode = FB_VMODE_NONINTERLACED;
+
+        info->var.xres = mode->hdisplay;
+        info->var.right_margin = mode->hsync_start - mode->hdisplay;
+        info->var.hsync_len = mode->hsync_end - mode->hsync_start;
+        info->var.left_margin = mode->htotal - mode->hsync_end;
+        info->var.yres = mode->vdisplay;
+        info->var.lower_margin = mode->vsync_start - mode->vdisplay;
+        info->var.vsync_len = mode->vsync_end - mode->vsync_start;
+       info->var.upper_margin = mode->vtotal - mode->vsync_end;
+        info->var.pixclock = 10000000 / mode->htotal * 1000 /
+               mode->vtotal * 100;
+       /* avoid overflow */
+       info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
+
+       info->pixmap.size = 64*1024;
+       info->pixmap.buf_align = 8;
+       info->pixmap.access_align = 32;
+       info->pixmap.flags = FB_PIXMAP_SYSTEM;
+       info->pixmap.scan_align = 1;
+
+       DRM_DEBUG("fb depth is %d\n", fb->depth);
+       DRM_DEBUG("   pitch is %d\n", fb->pitch);
+       switch(fb->depth) {
+       case 8:
+                info->var.red.offset = 0;
+                info->var.green.offset = 0;
+                info->var.blue.offset = 0;
+                info->var.red.length = 8; /* 8bit DAC */
+                info->var.green.length = 8;
+                info->var.blue.length = 8;
+                info->var.transp.offset = 0;
+                info->var.transp.length = 0;
+                break;
+       case 15:
+                info->var.red.offset = 10;
+                info->var.green.offset = 5;
+                info->var.blue.offset = 0;
+                info->var.red.length = info->var.green.length =
+                        info->var.blue.length = 5;
+                info->var.transp.offset = 15;
+                info->var.transp.length = 1;
+                break;
+       case 16:
+                info->var.red.offset = 11;
+                info->var.green.offset = 5;
+                info->var.blue.offset = 0;
+                info->var.red.length = 5;
+                info->var.green.length = 6;
+                info->var.blue.length = 5;
+                info->var.transp.offset = 0;
+               break;
+       case 24:
+                info->var.red.offset = 16;
+                info->var.green.offset = 8;
+                info->var.blue.offset = 0;
+                info->var.red.length = info->var.green.length =
+                        info->var.blue.length = 8;
+                info->var.transp.offset = 0;
+                info->var.transp.length = 0;
+                break;
+       case 32:
+               info->var.red.offset = 16;
+               info->var.green.offset = 8;
+               info->var.blue.offset = 0;
+               info->var.red.length = info->var.green.length =
+                       info->var.blue.length = 8;
+               info->var.transp.offset = 24;
+               info->var.transp.length = 8;
+               break;
+       default:
+               break;
+       }
+
+       if (register_framebuffer(info) < 0)
+               return -EINVAL;
+
+       printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+              info->fix.id);
+       return 0;
+}
+EXPORT_SYMBOL(intelfb_probe);
+
+int intelfb_remove(struct drm_device *dev, struct drm_crtc *crtc)
+{
+       struct drm_framebuffer *fb = crtc->fb;
+       struct fb_info *info = fb->fbdev;
+       
+       if (info) {
+               unregister_framebuffer(info);
+               framebuffer_release(info);
+               drm_mem_reg_iounmap(dev, &fb->bo->mem, fb->virtual_base);
+               drm_bo_usage_deref_unlocked(&fb->bo);
+               drm_framebuffer_destroy(fb);
+       }
+       return 0;
+}
+EXPORT_SYMBOL(intelfb_remove);
+MODULE_LICENSE("GPL");
diff --git a/linux-core/intel_i2c.c b/linux-core/intel_i2c.c
new file mode 100644 (file)
index 0000000..efcbf65
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     Eric Anholt <eric@anholt.net>
+ */
+/*
+ * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+#include "drmP.h"
+#include "drm.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/*
+ * Intel GPIO access functions
+ */
+
+#define I2C_RISEFALL_TIME 20
+
+static int get_clock(void *data)
+{
+       struct intel_i2c_chan *chan = data;
+       struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+       u32 val;
+
+       val = I915_READ(chan->reg);
+       return ((val & GPIO_CLOCK_VAL_IN) != 0);
+}
+
+static int get_data(void *data)
+{
+       struct intel_i2c_chan *chan = data;
+       struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+       u32 val;
+
+       val = I915_READ(chan->reg);
+       return ((val & GPIO_DATA_VAL_IN) != 0);
+}
+
+static void set_clock(void *data, int state_high)
+{
+       struct intel_i2c_chan *chan = data;
+       struct drm_device *dev = chan->drm_dev;
+       struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+       u32 reserved = 0, clock_bits;
+
+       /* On most chips, these bits must be preserved in software. */
+       if (!IS_I830(dev) && !IS_845G(dev))
+               reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+                                                  GPIO_CLOCK_PULLUP_DISABLE);
+
+       if (state_high)
+               clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
+       else
+               clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
+                       GPIO_CLOCK_VAL_MASK;
+       I915_WRITE(chan->reg, reserved | clock_bits);
+       udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
+}
+
+static void set_data(void *data, int state_high)
+{
+       struct intel_i2c_chan *chan = data;
+       struct drm_device *dev = chan->drm_dev;
+       struct drm_i915_private *dev_priv = chan->drm_dev->dev_private;
+       u32 reserved = 0, data_bits;
+
+       /* On most chips, these bits must be preserved in software. */
+       if (!IS_I830(dev) && !IS_845G(dev))
+               reserved = I915_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+                                                  GPIO_CLOCK_PULLUP_DISABLE);
+
+       if (state_high)
+               data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
+       else
+               data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
+                       GPIO_DATA_VAL_MASK;
+
+       I915_WRITE(chan->reg, reserved | data_bits);
+       udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
+}
+
+/**
+ * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
+ * @dev: DRM device
+ * @output: driver specific output device
+ * @reg: GPIO reg to use
+ * @name: name for this bus
+ *
+ * Creates and registers a new i2c bus with the Linux i2c layer, for use
+ * in output probing and control (e.g. DDC or SDVO control functions).
+ *
+ * Possible values for @reg include:
+ *   %GPIOA
+ *   %GPIOB
+ *   %GPIOC
+ *   %GPIOD
+ *   %GPIOE
+ *   %GPIOF
+ *   %GPIOG
+ *   %GPIOH
+ * see PRM for details on how these different busses are used.
+ */
+struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
+                                       const char *name)
+{
+       struct intel_i2c_chan *chan;
+
+       chan = kzalloc(sizeof(struct intel_i2c_chan), GFP_KERNEL);
+       if (!chan)
+               goto out_free;
+
+       chan->drm_dev = dev;
+       chan->reg = reg;
+       snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
+       chan->adapter.owner = THIS_MODULE;
+#ifndef I2C_HW_B_INTELFB
+#define I2C_HW_B_INTELFB I2C_HW_B_I810
+#endif
+       chan->adapter.id = I2C_HW_B_INTELFB;
+       chan->adapter.algo_data = &chan->algo;
+       chan->adapter.dev.parent = &dev->pdev->dev;
+       chan->algo.setsda = set_data;
+       chan->algo.setscl = set_clock;
+       chan->algo.getsda = get_data;
+       chan->algo.getscl = get_clock;
+       chan->algo.udelay = 20;
+       chan->algo.timeout = usecs_to_jiffies(2200);
+       chan->algo.data = chan;
+
+       i2c_set_adapdata(&chan->adapter, chan);
+
+       if(i2c_bit_add_bus(&chan->adapter))
+               goto out_free;
+
+       /* JJJ:  raise SCL and SDA? */
+       set_data(chan, 1);
+       set_clock(chan, 1);
+       udelay(20);
+
+       return chan;
+
+out_free:
+       kfree(chan);
+       return NULL;
+}
+
+/**
+ * intel_i2c_destroy - unregister and free i2c bus resources
+ * @output: channel to free
+ *
+ * Unregister the adapter from the i2c layer, then free the structure.
+ */
+void intel_i2c_destroy(struct intel_i2c_chan *chan)
+{
+       if (!chan)
+               return;
+
+       i2c_del_adapter(&chan->adapter);
+       kfree(chan);
+}
+
+       
+       
diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c
new file mode 100644 (file)
index 0000000..4f15c13
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     Eric Anholt <eric@anholt.net>
+ *      Dave Airlie <airlied@linux.ie>
+ *      Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "drm_edid.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/**
+ * Sets the backlight level.
+ *
+ * \param level backlight level, from 0 to intel_lvds_get_max_backlight().
+ */
+static void intel_lvds_set_backlight(struct drm_device *dev, int level)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 blc_pwm_ctl;
+
+       blc_pwm_ctl = I915_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
+                                (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
+}
+
+/**
+ * Returns the maximum level of the backlight duty cycle field.
+ */
+static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+    
+       return ((I915_READ(BLC_PWM_CTL) & BACKLIGHT_MODULATION_FREQ_MASK) >>
+               BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+}
+
+/**
+ * Sets the power state for the panel.
+ */
+static void intel_lvds_set_power(struct drm_device *dev, bool on)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp_status;
+
+       if (on) {
+               I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
+                          POWER_TARGET_ON);
+               do {
+                       pp_status = I915_READ(PP_STATUS);
+               } while ((pp_status & PP_ON) == 0);
+
+               intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle);
+       } else {
+               intel_lvds_set_backlight(dev, 0);
+
+               I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) &
+                          ~POWER_TARGET_ON);
+               do {
+                       pp_status = I915_READ(PP_STATUS);
+               } while (pp_status & PP_ON);
+       }
+}
+
+static void intel_lvds_dpms(struct drm_output *output, int mode)
+{
+       struct drm_device *dev = output->dev;
+
+       if (mode == DPMSModeOn)
+               intel_lvds_set_power(dev, true);
+       else
+               intel_lvds_set_power(dev, false);
+
+       /* XXX: We never power down the LVDS pairs. */
+}
+
+static void intel_lvds_save(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       dev_priv->savePP_ON = I915_READ(LVDSPP_ON);
+       dev_priv->savePP_OFF = I915_READ(LVDSPP_OFF);
+       dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
+       dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
+       dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+       dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
+                                      BACKLIGHT_DUTY_CYCLE_MASK);
+
+       /*
+        * If the light is off at server startup, just make it full brightness
+        */
+       if (dev_priv->backlight_duty_cycle == 0)
+               dev_priv->backlight_duty_cycle =
+                       intel_lvds_get_max_backlight(dev);
+}
+
+static void intel_lvds_restore(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+       I915_WRITE(LVDSPP_ON, dev_priv->savePP_ON);
+       I915_WRITE(LVDSPP_OFF, dev_priv->savePP_OFF);
+       I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
+       I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+       if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
+               intel_lvds_set_power(dev, true);
+       else
+               intel_lvds_set_power(dev, false);
+}
+
+static int intel_lvds_mode_valid(struct drm_output *output,
+                                struct drm_display_mode *mode)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
+
+       if (fixed_mode) {
+               if (mode->hdisplay > fixed_mode->hdisplay)
+                       return MODE_PANEL;
+               if (mode->vdisplay > fixed_mode->vdisplay)
+                       return MODE_PANEL;
+       }
+
+       return MODE_OK;
+}
+
+static bool intel_lvds_mode_fixup(struct drm_output *output,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = output->crtc->driver_private;
+       struct drm_output *tmp_output;
+
+       /* Should never happen!! */
+       if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
+               printk(KERN_ERR "Can't support LVDS on pipe A\n");
+               return false;
+       }
+
+       /* Should never happen!! */
+       list_for_each_entry(tmp_output, &dev->mode_config.output_list, head) {
+               if (tmp_output != output && tmp_output->crtc == output->crtc) {
+                       printk(KERN_ERR "Can't enable LVDS and another "
+                              "output on the same pipe\n");
+                       return false;
+               }
+       }
+
+       /*
+        * If we have timings from the BIOS for the panel, put them in
+        * to the adjusted mode.  The CRTC will be set up for this mode,
+        * with the panel scaling set up to source from the H/VDisplay
+        * of the original mode.
+        */
+       if (dev_priv->panel_fixed_mode != NULL) {
+               adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
+               adjusted_mode->hsync_start =
+                       dev_priv->panel_fixed_mode->hsync_start;
+               adjusted_mode->hsync_end =
+                       dev_priv->panel_fixed_mode->hsync_end;
+               adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
+               adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
+               adjusted_mode->vsync_start =
+                       dev_priv->panel_fixed_mode->vsync_start;
+               adjusted_mode->vsync_end =
+                       dev_priv->panel_fixed_mode->vsync_end;
+               adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
+               adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
+               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+       }
+
+       /*
+        * XXX: It would be nice to support lower refresh rates on the
+        * panels to reduce power consumption, and perhaps match the
+        * user's requested refresh rate.
+        */
+
+       return true;
+}
+
+static void intel_lvds_prepare(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+       dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
+                                      BACKLIGHT_DUTY_CYCLE_MASK);
+
+       intel_lvds_set_power(dev, false);
+}
+
+static void intel_lvds_commit( struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->backlight_duty_cycle == 0)
+               dev_priv->backlight_duty_cycle =
+                       intel_lvds_get_max_backlight(dev);
+
+       intel_lvds_set_power(dev, true);
+}
+
+static void intel_lvds_mode_set(struct drm_output *output,
+                               struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = output->crtc->driver_private;
+       u32 pfit_control;
+
+       /*
+        * The LVDS pin pair will already have been turned on in the
+        * intel_crtc_mode_set since it has a large impact on the DPLL
+        * settings.
+        */
+
+       /*
+        * Enable automatic panel scaling so that non-native modes fill the
+        * screen.  Should be enabled before the pipe is enabled, according to
+        * register description and PRM.
+        */
+       pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+                       VERT_INTERP_BILINEAR | HORIZ_INTERP_BILINEAR);
+
+       if (!IS_I965G(dev)) {
+               if (dev_priv->panel_wants_dither)
+                       pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+       }
+       else
+               pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
+
+       I915_WRITE(PFIT_CONTROL, pfit_control);
+}
+
+/**
+ * Detect the LVDS connection.
+ *
+ * This always returns OUTPUT_STATUS_CONNECTED.  This output should only have
+ * been set up if the LVDS was actually connected anyway.
+ */
+static enum drm_output_status intel_lvds_detect(struct drm_output *output)
+{
+       return output_status_connected;
+}
+
+/**
+ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
+ */
+static int intel_lvds_get_modes(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret = 0;
+
+       ret = intel_ddc_get_modes(output);
+
+       if (ret)
+               return ret;
+
+       /* Didn't get an EDID */
+       if (!output->monitor_info) {
+               struct drm_display_info *dspinfo;
+               dspinfo = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL);
+               if (!dspinfo)
+                       goto out;
+
+               /* Set wide sync ranges so we get all modes
+                * handed to valid_mode for checking
+                */
+               dspinfo->min_vfreq = 0;
+               dspinfo->max_vfreq = 200;
+               dspinfo->min_hfreq = 0;
+               dspinfo->max_hfreq = 200;
+               output->monitor_info = dspinfo;
+       }
+
+out:
+       if (dev_priv->panel_fixed_mode != NULL) {
+               struct drm_display_mode *mode =
+                       drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
+               drm_mode_probed_add(output, mode);
+               return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * intel_lvds_destroy - unregister and free LVDS structures
+ * @output: output to free
+ *
+ * Unregister the DDC bus for this output then free the driver private
+ * structure.
+ */
+static void intel_lvds_destroy(struct drm_output *output)
+{
+       struct intel_output *intel_output = output->driver_private;
+
+       intel_i2c_destroy(intel_output->ddc_bus);
+       kfree(output->driver_private);
+}
+
+static const struct drm_output_funcs intel_lvds_output_funcs = {
+       .dpms = intel_lvds_dpms,
+       .save = intel_lvds_save,
+       .restore = intel_lvds_restore,
+       .mode_valid = intel_lvds_mode_valid,
+       .mode_fixup = intel_lvds_mode_fixup,
+       .prepare = intel_lvds_prepare,
+       .mode_set = intel_lvds_mode_set,
+       .commit = intel_lvds_commit,
+       .detect = intel_lvds_detect,
+       .get_modes = intel_lvds_get_modes,
+       .cleanup = intel_lvds_destroy
+};
+
+/**
+ * intel_lvds_init - setup LVDS outputs on this device
+ * @dev: drm device
+ *
+ * Create the output, register the LVDS DDC bus, and try to figure out what
+ * modes we can display on the LVDS panel (if present).
+ */
+void intel_lvds_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_output *output;
+       struct intel_output *intel_output;
+       struct drm_display_mode *scan; /* *modes, *bios_mode; */
+       struct drm_crtc *crtc;
+       u32 lvds;
+       int pipe;
+
+       output = drm_output_create(dev, &intel_lvds_output_funcs, "LVDS");
+       if (!output)
+               return;
+
+       intel_output = kmalloc(sizeof(struct intel_output), GFP_KERNEL);
+       if (!intel_output) {
+               drm_output_destroy(output);
+               return;
+       }
+
+       intel_output->type = INTEL_OUTPUT_LVDS;
+       output->driver_private = intel_output;
+       output->subpixel_order = SubPixelHorizontalRGB;
+       output->interlace_allowed = FALSE;
+       output->doublescan_allowed = FALSE;
+
+       /* Set up the DDC bus. */
+       intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
+       if (!intel_output->ddc_bus) {
+               dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
+                          "failed.\n");
+               return;
+       }
+
+       /*
+        * Attempt to get the fixed panel mode from DDC.  Assume that the
+        * preferred mode is the right one.
+        */
+       intel_ddc_get_modes(output);
+
+       list_for_each_entry(scan, &output->probed_modes, head) {
+               if (scan->type & DRM_MODE_TYPE_PREFERRED) {
+                       dev_priv->panel_fixed_mode = 
+                               drm_mode_duplicate(dev, scan);
+                       goto out; /* FIXME: check for quirks */
+               }
+       }
+
+       /*
+        * If we didn't get EDID, try checking if the panel is already turned
+        * on.  If so, assume that whatever is currently programmed is the
+        * correct mode.
+        */
+       lvds = I915_READ(LVDS);
+       pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
+       crtc = intel_get_crtc_from_pipe(dev, pipe);
+               
+       if (crtc && (lvds & LVDS_PORT_EN)) {
+               dev_priv->panel_fixed_mode = intel_crtc_mode_get(dev, crtc);
+               if (dev_priv->panel_fixed_mode) {
+                       dev_priv->panel_fixed_mode->type |=
+                               DRM_MODE_TYPE_PREFERRED;
+                       goto out; /* FIXME: check for quirks */
+               }
+       }
+
+       /* If we still don't have a mode after all that, give up. */
+       if (!dev_priv->panel_fixed_mode)
+               goto failed;
+
+       /* FIXME: probe the BIOS for modes and check for LVDS quirks */
+#if 0
+       /* Get the LVDS fixed mode out of the BIOS.  We should support LVDS
+        * with the BIOS being unavailable or broken, but lack the
+        * configuration options for now.
+        */
+       bios_mode = intel_bios_get_panel_mode(pScrn);
+       if (bios_mode != NULL) {
+               if (dev_priv->panel_fixed_mode != NULL) {
+                       if (dev_priv->debug_modes &&
+                           !xf86ModesEqual(dev_priv->panel_fixed_mode,
+                                           bios_mode))
+                       {
+                               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+                                          "BIOS panel mode data doesn't match probed data, "
+                                          "continuing with probed.\n");
+                               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS mode:\n");
+                               xf86PrintModeline(pScrn->scrnIndex, bios_mode);
+                               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "probed mode:\n");
+                               xf86PrintModeline(pScrn->scrnIndex, dev_priv->panel_fixed_mode);
+                               xfree(bios_mode->name);
+                               xfree(bios_mode);
+                       }
+               }  else {
+                       dev_priv->panel_fixed_mode = bios_mode;
+               }
+       } else {
+               xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+                          "Couldn't detect panel mode.  Disabling panel\n");
+               goto disable_exit;
+       }
+
+       /*
+        * Blacklist machines with BIOSes that list an LVDS panel without
+        * actually having one.
+        */
+       if (dev_priv->PciInfo->chipType == PCI_CHIP_I945_GM) {
+               /* aopen mini pc */
+               if (dev_priv->PciInfo->subsysVendor == 0xa0a0)
+                       goto disable_exit;
+
+               if ((dev_priv->PciInfo->subsysVendor == 0x8086) &&
+                   (dev_priv->PciInfo->subsysCard == 0x7270)) {
+                       /* It's a Mac Mini or Macbook Pro.
+                        *
+                        * Apple hardware is out to get us.  The macbook pro
+                        * has a real LVDS panel, but the mac mini does not,
+                        * and they have the same device IDs.  We'll
+                        * distinguish by panel size, on the assumption
+                        * that Apple isn't about to make any machines with an
+                        * 800x600 display.
+                        */
+
+                       if (dev_priv->panel_fixed_mode != NULL &&
+                           dev_priv->panel_fixed_mode->HDisplay == 800 &&
+                           dev_priv->panel_fixed_mode->VDisplay == 600)
+                       {
+                               xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+                                          "Suspected Mac Mini, ignoring the LVDS\n");
+                               goto disable_exit;
+                       }
+               }
+       }
+
+#endif
+
+out:
+       return;
+
+failed:
+        DRM_DEBUG("No LVDS modes found, disabling.\n");
+       drm_output_destroy(output); /* calls intel_lvds_destroy above */
+}
diff --git a/linux-core/intel_modes.c b/linux-core/intel_modes.c
new file mode 100644 (file)
index 0000000..601770e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
+ * Copyright (c) 2007 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include "drmP.h"
+#include "intel_drv.h"
+
+/**
+ * intel_ddc_probe
+ *
+ */
+bool intel_ddc_probe(struct drm_output *output)
+{
+       struct intel_output *intel_output = output->driver_private;
+       u8 out_buf[] = { 0x0, 0x0};
+       u8 buf[2];
+       int ret;
+       struct i2c_msg msgs[] = {
+               {
+                       .addr = 0x50,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = out_buf,
+               },
+               {
+                       .addr = 0x50,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = buf,
+               }
+       };
+
+       ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
+       if (ret == 2)
+               return true;
+
+       return false;
+}
+
+/**
+ * intel_ddc_get_modes - get modelist from monitor
+ * @output: DRM output device to use
+ *
+ * Fetch the EDID information from @output using the DDC bus.
+ */
+int intel_ddc_get_modes(struct drm_output *output)
+{
+       struct intel_output *intel_output = output->driver_private;
+
+       return drm_add_edid_modes(output, &intel_output->ddc_bus->adapter);
+}
diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c
new file mode 100644 (file)
index 0000000..51fe43c
--- /dev/null
@@ -0,0 +1,1087 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     Eric Anholt <eric@anholt.net>
+ */
+/*
+ * Copyright 2006 Dave Airlie <airlied@linux.ie>
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "intel_sdvo_regs.h"
+
+struct intel_sdvo_priv {
+       struct intel_i2c_chan *i2c_bus;
+       int slaveaddr;
+       int output_device;
+
+       u16 active_outputs;
+
+       struct intel_sdvo_caps caps;
+       int pixel_clock_min, pixel_clock_max;
+
+       int save_sdvo_mult;
+       u16 save_active_outputs;
+       struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
+       struct intel_sdvo_dtd save_output_dtd[16];
+       u32 save_SDVOX;
+};
+
+/**
+ * Writes the SDVOB or SDVOC with the given value, but always writes both
+ * SDVOB and SDVOC to work around apparent hardware issues (according to
+ * comments in the BIOS).
+ */
+static void intel_sdvo_write_sdvox(struct drm_output *output, u32 val)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv   *sdvo_priv = intel_output->dev_priv;
+       u32 bval = val, cval = val;
+       int i;
+
+       if (sdvo_priv->output_device == SDVOB)
+               cval = I915_READ(SDVOC);
+       else
+               bval = I915_READ(SDVOB);
+       /*
+        * Write the registers twice for luck. Sometimes,
+        * writing them only once doesn't appear to 'stick'.
+        * The BIOS does this too. Yay, magic
+        */
+       for (i = 0; i < 2; i++)
+       {
+               I915_WRITE(SDVOB, bval);
+               I915_READ(SDVOB);
+               I915_WRITE(SDVOC, cval);
+               I915_READ(SDVOC);
+       }
+}
+
+static bool intel_sdvo_read_byte(struct drm_output *output, u8 addr,
+                                u8 *ch)
+{
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       u8 out_buf[2];
+       u8 buf[2];
+       int ret;
+
+       struct i2c_msg msgs[] = {
+               { 
+                       .addr = sdvo_priv->i2c_bus->slave_addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = out_buf,
+               }, 
+               {
+                       .addr = sdvo_priv->i2c_bus->slave_addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = buf,
+               }
+       };
+
+       out_buf[0] = addr;
+       out_buf[1] = 0;
+
+       if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2)
+       {
+//             DRM_DEBUG("got back from addr %02X = %02x\n", out_buf[0], buf[0]); 
+               *ch = buf[0];
+               return true;
+       }
+
+       DRM_DEBUG("i2c transfer returned %d\n", ret);
+       return false;
+}
+
+
+static bool intel_sdvo_read_byte_quiet(struct drm_output *output, int addr,
+                                      u8 *ch)
+{
+       return true;
+
+}
+
+static bool intel_sdvo_write_byte(struct drm_output *output, int addr,
+                                 u8 ch)
+{
+       struct intel_output *intel_output = output->driver_private;
+       u8 out_buf[2];
+       struct i2c_msg msgs[] = {
+               { 
+                       .addr = intel_output->i2c_bus->slave_addr,
+                       .flags = 0,
+                       .len = 2,
+                       .buf = out_buf,
+               }
+       };
+
+       out_buf[0] = addr;
+       out_buf[1] = ch;
+
+       if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1)
+       {
+               return true;
+       }
+       return false;
+}
+
+#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
+/** Mapping of command numbers to names, for debug output */
+const static struct _sdvo_cmd_name {
+    u8 cmd;
+    char *name;
+} sdvo_cmd_names[] = {
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
+};
+
+#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
+#define SDVO_PRIV(output)   ((struct intel_sdvo_priv *) (output)->dev_priv)
+
+static void intel_sdvo_write_cmd(struct drm_output *output, u8 cmd,
+                                void *args, int args_len)
+{
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       int i;
+
+        if (1) {
+                DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
+                for (i = 0; i < args_len; i++)
+                        printk("%02X ", ((u8 *)args)[i]);
+                for (; i < 8; i++)
+                        printk("   ");
+                for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) {
+                        if (cmd == sdvo_cmd_names[i].cmd) {
+                                printk("(%s)", sdvo_cmd_names[i].name);
+                                break;
+                        }
+                }
+                if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0]))
+                        printk("(%02X)",cmd);
+                printk("\n");
+        }
+                        
+       for (i = 0; i < args_len; i++) {
+               intel_sdvo_write_byte(output, SDVO_I2C_ARG_0 - i, ((u8*)args)[i]);
+       }
+
+       intel_sdvo_write_byte(output, SDVO_I2C_OPCODE, cmd);
+}
+
+static const char *cmd_status_names[] = {
+       "Power on",
+       "Success",
+       "Not supported",
+       "Invalid arg",
+       "Pending",
+       "Target not specified",
+       "Scaling not supported"
+};
+
+static u8 intel_sdvo_read_response(struct drm_output *output, void *response,
+                                  int response_len)
+{
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       int i;
+       u8 status;
+       u8 retry = 50;
+
+       while (retry--) {
+               /* Read the command response */
+               for (i = 0; i < response_len; i++) {
+                       intel_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i,
+                                    &((u8 *)response)[i]);
+               }
+
+               /* read the return status */
+               intel_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
+
+               if (1) {
+                       DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv));
+                               for (i = 0; i < response_len; i++)
+                               printk("%02X ", ((u8 *)response)[i]);
+                       for (; i < 8; i++)
+                               printk("   ");
+                       if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
+                               printk("(%s)", cmd_status_names[status]);
+                       else
+                               printk("(??? %d)", status);
+                       printk("\n");
+               }
+
+               if (status != SDVO_CMD_STATUS_PENDING)
+                       return status;
+
+               mdelay(50);
+       }
+
+       return status;
+}
+
+int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
+{
+       if (mode->clock >= 100000)
+               return 1;
+       else if (mode->clock >= 50000)
+               return 2;
+       else
+               return 4;
+}
+
+/**
+ * Don't check status code from this as it switches the bus back to the
+ * SDVO chips which defeats the purpose of doing a bus switch in the first
+ * place.
+ */
+void intel_sdvo_set_control_bus_switch(struct drm_output *output, u8 target)
+{
+       intel_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
+}
+
+static bool intel_sdvo_set_target_input(struct drm_output *output, bool target_0, bool target_1)
+{
+       struct intel_sdvo_set_target_input_args targets = {0};
+       u8 status;
+
+       if (target_0 && target_1)
+               return SDVO_CMD_STATUS_NOTSUPP;
+
+       if (target_1)
+               targets.target_1 = 1;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets,
+                            sizeof(targets));
+
+       status = intel_sdvo_read_response(output, NULL, 0);
+
+       return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+/**
+ * Return whether each input is trained.
+ *
+ * This function is making an assumption about the layout of the response,
+ * which should be checked against the docs.
+ */
+static bool intel_sdvo_get_trained_inputs(struct drm_output *output, bool *input_1, bool *input_2)
+{
+       struct intel_sdvo_get_trained_inputs_response response;
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
+       status = intel_sdvo_read_response(output, &response, sizeof(response));
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       *input_1 = response.input0_trained;
+       *input_2 = response.input1_trained;
+       return true;
+}
+
+static bool intel_sdvo_get_active_outputs(struct drm_output *output,
+                                         u16 *outputs)
+{
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0);
+       status = intel_sdvo_read_response(output, outputs, sizeof(*outputs));
+
+       return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static bool intel_sdvo_set_active_outputs(struct drm_output *output,
+                                         u16 outputs)
+{
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
+                            sizeof(outputs));
+       status = intel_sdvo_read_response(output, NULL, 0);
+       return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static bool intel_sdvo_set_encoder_power_state(struct drm_output *output,
+                                              int mode)
+{
+       u8 status, state = SDVO_ENCODER_STATE_ON;
+
+       switch (mode) {
+       case DPMSModeOn:
+               state = SDVO_ENCODER_STATE_ON;
+               break;
+       case DPMSModeStandby:
+               state = SDVO_ENCODER_STATE_STANDBY;
+               break;
+       case DPMSModeSuspend:
+               state = SDVO_ENCODER_STATE_SUSPEND;
+               break;
+       case DPMSModeOff:
+               state = SDVO_ENCODER_STATE_OFF;
+               break;
+       }
+       
+       intel_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
+                            sizeof(state));
+       status = intel_sdvo_read_response(output, NULL, 0);
+
+       return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static bool intel_sdvo_get_input_pixel_clock_range(struct drm_output *output,
+                                                  int *clock_min,
+                                                  int *clock_max)
+{
+       struct intel_sdvo_pixel_clock_range clocks;
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE,
+                            NULL, 0);
+
+       status = intel_sdvo_read_response(output, &clocks, sizeof(clocks));
+
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       /* Convert the values from units of 10 kHz to kHz. */
+       *clock_min = clocks.min * 10;
+       *clock_max = clocks.max * 10;
+
+       return true;
+}
+
+static bool intel_sdvo_set_target_output(struct drm_output *output,
+                                        u16 outputs)
+{
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
+                            sizeof(outputs));
+
+       status = intel_sdvo_read_response(output, NULL, 0);
+       return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
+static bool intel_sdvo_get_timing(struct drm_output *output, u8 cmd,
+                                 struct intel_sdvo_dtd *dtd)
+{
+       u8 status;
+
+       intel_sdvo_write_cmd(output, cmd, NULL, 0);
+       status = intel_sdvo_read_response(output, &dtd->part1,
+                                         sizeof(dtd->part1));
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       intel_sdvo_write_cmd(output, cmd + 1, NULL, 0);
+       status = intel_sdvo_read_response(output, &dtd->part2,
+                                         sizeof(dtd->part2));
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       return true;
+}
+
+static bool intel_sdvo_get_input_timing(struct drm_output *output,
+                                        struct intel_sdvo_dtd *dtd)
+{
+       return intel_sdvo_get_timing(output,
+                                    SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
+}
+
+static bool intel_sdvo_get_output_timing(struct drm_output *output,
+                                        struct intel_sdvo_dtd *dtd)
+{
+       return intel_sdvo_get_timing(output,
+                                    SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd);
+}
+
+static bool intel_sdvo_set_timing(struct drm_output *output, u8 cmd,
+                                 struct intel_sdvo_dtd *dtd)
+{
+       u8 status;
+
+       intel_sdvo_write_cmd(output, cmd, &dtd->part1, sizeof(dtd->part1));
+       status = intel_sdvo_read_response(output, NULL, 0);
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       intel_sdvo_write_cmd(output, cmd + 1, &dtd->part2, sizeof(dtd->part2));
+       status = intel_sdvo_read_response(output, NULL, 0);
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       return true;
+}
+
+static bool intel_sdvo_set_input_timing(struct drm_output *output,
+                                        struct intel_sdvo_dtd *dtd)
+{
+       return intel_sdvo_set_timing(output,
+                                    SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
+}
+
+static bool intel_sdvo_set_output_timing(struct drm_output *output,
+                                        struct intel_sdvo_dtd *dtd)
+{
+       return intel_sdvo_set_timing(output,
+                                    SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
+}
+
+#if 0
+static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output,
+                                                 struct intel_sdvo_dtd *dtd)
+{
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
+                            NULL, 0);
+
+       status = intel_sdvo_read_response(output, &dtd->part1,
+                                         sizeof(dtd->part1));
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
+                            NULL, 0);
+       status = intel_sdvo_read_response(output, &dtd->part2,
+                                         sizeof(dtd->part2));
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       return true;
+}
+#endif
+
+static int intel_sdvo_get_clock_rate_mult(struct drm_output *output)
+{
+       u8 response, status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0);
+       status = intel_sdvo_read_response(output, &response, 1);
+
+       if (status != SDVO_CMD_STATUS_SUCCESS) {
+               DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n");
+               return SDVO_CLOCK_RATE_MULT_1X;
+       } else {
+               DRM_DEBUG("Current clock rate multiplier: %d\n", response);
+       }
+
+       return response;
+}
+
+static bool intel_sdvo_set_clock_rate_mult(struct drm_output *output, u8 val)
+{
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1);
+       status = intel_sdvo_read_response(output, NULL, 0);
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       return true;
+}
+
+static bool intel_sdvo_mode_fixup(struct drm_output *output,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       /* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO
+        * device will be told of the multiplier during mode_set.
+        */
+       adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode);
+       return true;
+}
+
+static void intel_sdvo_mode_set(struct drm_output *output,
+                               struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = output->crtc;
+       struct intel_crtc *intel_crtc = crtc->driver_private;
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       u16 width, height;
+       u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+       u16 h_sync_offset, v_sync_offset;
+       u32 sdvox;
+       struct intel_sdvo_dtd output_dtd;
+       int sdvo_pixel_multiply;
+
+       if (!mode)
+               return;
+
+       width = mode->crtc_hdisplay;
+       height = mode->crtc_vdisplay;
+
+       /* do some mode translations */
+       h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
+       h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+
+       v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
+       v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+
+       h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
+       v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
+
+       output_dtd.part1.clock = mode->clock / 10;
+       output_dtd.part1.h_active = width & 0xff;
+       output_dtd.part1.h_blank = h_blank_len & 0xff;
+       output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
+               ((h_blank_len >> 8) & 0xf);
+       output_dtd.part1.v_active = height & 0xff;
+       output_dtd.part1.v_blank = v_blank_len & 0xff;
+       output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
+               ((v_blank_len >> 8) & 0xf);
+       
+       output_dtd.part2.h_sync_off = h_sync_offset;
+       output_dtd.part2.h_sync_width = h_sync_len & 0xff;
+       output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
+               (v_sync_len & 0xf);
+       output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) |
+               ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) |
+               ((v_sync_len & 0x30) >> 4);
+       
+       output_dtd.part2.dtd_flags = 0x18;
+       if (mode->flags & V_PHSYNC)
+               output_dtd.part2.dtd_flags |= 0x2;
+       if (mode->flags & V_PVSYNC)
+               output_dtd.part2.dtd_flags |= 0x4;
+
+       output_dtd.part2.sdvo_flags = 0;
+       output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
+       output_dtd.part2.reserved = 0;
+
+       /* Set the output timing to the screen */
+       intel_sdvo_set_target_output(output, sdvo_priv->active_outputs);
+       intel_sdvo_set_output_timing(output, &output_dtd);
+
+       /* Set the input timing to the screen. Assume always input 0. */
+       intel_sdvo_set_target_input(output, true, false);
+
+       /* We would like to use i830_sdvo_create_preferred_input_timing() to
+        * provide the device with a timing it can support, if it supports that
+        * feature.  However, presumably we would need to adjust the CRTC to
+        * output the preferred timing, and we don't support that currently.
+        */
+#if 0
+       success = intel_sdvo_create_preferred_input_timing(output, clock,
+                                                          width, height);
+       if (success) {
+               struct intel_sdvo_dtd *input_dtd;
+               
+               intel_sdvo_get_preferred_input_timing(output, &input_dtd);
+               intel_sdvo_set_input_timing(output, &input_dtd);
+       }
+#else
+       intel_sdvo_set_input_timing(output, &output_dtd);
+#endif 
+
+       switch (intel_sdvo_get_pixel_multiplier(mode)) {
+       case 1:
+               intel_sdvo_set_clock_rate_mult(output,
+                                              SDVO_CLOCK_RATE_MULT_1X);
+               break;
+       case 2:
+               intel_sdvo_set_clock_rate_mult(output,
+                                              SDVO_CLOCK_RATE_MULT_2X);
+               break;
+       case 4:
+               intel_sdvo_set_clock_rate_mult(output,
+                                              SDVO_CLOCK_RATE_MULT_4X);
+               break;
+       }       
+
+       /* Set the SDVO control regs. */
+        if (0/*IS_I965GM(dev)*/) {
+                sdvox = SDVO_BORDER_ENABLE;
+        } else {
+                sdvox = I915_READ(sdvo_priv->output_device);
+                switch (sdvo_priv->output_device) {
+                case SDVOB:
+                        sdvox &= SDVOB_PRESERVE_MASK;
+                        break;
+                case SDVOC:
+                        sdvox &= SDVOC_PRESERVE_MASK;
+                        break;
+                }
+                sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
+        }
+       if (intel_crtc->pipe == 1)
+               sdvox |= SDVO_PIPE_B_SELECT;
+
+       sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode);
+       if (IS_I965G(dev)) {
+               /* done in crtc_mode_set as the dpll_md reg must be written 
+                  early */
+       } else if (IS_I945G(dev) || IS_I945GM(dev)) {
+               /* done in crtc_mode_set as it lives inside the 
+                  dpll register */
+       } else {
+               sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+       }
+
+       intel_sdvo_write_sdvox(output, sdvox);
+}
+
+static void intel_sdvo_dpms(struct drm_output *output, int mode)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       u32 temp;
+
+       if (mode != DPMSModeOn) {
+               intel_sdvo_set_active_outputs(output, 0);
+               if (0)
+                       intel_sdvo_set_encoder_power_state(output, mode);
+
+               if (mode == DPMSModeOff) {
+                       temp = I915_READ(sdvo_priv->output_device);
+                       if ((temp & SDVO_ENABLE) != 0) {
+                               intel_sdvo_write_sdvox(output, temp & ~SDVO_ENABLE);
+                       }
+               }
+       } else {
+               bool input1, input2;
+               int i;
+               u8 status;
+               
+               temp = I915_READ(sdvo_priv->output_device);
+               if ((temp & SDVO_ENABLE) == 0)
+                       intel_sdvo_write_sdvox(output, temp | SDVO_ENABLE);
+               for (i = 0; i < 2; i++)
+                 intel_wait_for_vblank(dev);
+               
+               status = intel_sdvo_get_trained_inputs(output, &input1,
+                                                      &input2);
+
+               
+               /* Warn if the device reported failure to sync. 
+                * A lot of SDVO devices fail to notify of sync, but it's
+                * a given it the status is a success, we succeeded.
+                */
+               if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+                       DRM_DEBUG("First %s output reported failure to sync\n",
+                                  SDVO_NAME(sdvo_priv));
+               }
+               
+               if (0)
+                       intel_sdvo_set_encoder_power_state(output, mode);
+               intel_sdvo_set_active_outputs(output, sdvo_priv->active_outputs);
+       }       
+       return;
+}
+
+static void intel_sdvo_save(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       int o;
+
+       sdvo_priv->save_sdvo_mult = intel_sdvo_get_clock_rate_mult(output);
+       intel_sdvo_get_active_outputs(output, &sdvo_priv->save_active_outputs);
+
+       if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
+               intel_sdvo_set_target_input(output, true, false);
+               intel_sdvo_get_input_timing(output,
+                                           &sdvo_priv->save_input_dtd_1);
+       }
+
+       if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
+               intel_sdvo_set_target_input(output, false, true);
+               intel_sdvo_get_input_timing(output,
+                                           &sdvo_priv->save_input_dtd_2);
+       }
+
+       for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+       {
+               u16  this_output = (1 << o);
+               if (sdvo_priv->caps.output_flags & this_output)
+               {
+                       intel_sdvo_set_target_output(output, this_output);
+                       intel_sdvo_get_output_timing(output,
+                                                    &sdvo_priv->save_output_dtd[o]);
+               }
+       }
+
+       sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device);
+}
+
+static void intel_sdvo_restore(struct drm_output *output)
+{
+       struct drm_device *dev = output->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       int o;
+       int i;
+       bool input1, input2;
+       u8 status;
+
+       intel_sdvo_set_active_outputs(output, 0);
+
+       for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+       {
+               u16  this_output = (1 << o);
+               if (sdvo_priv->caps.output_flags & this_output) {
+                       intel_sdvo_set_target_output(output, this_output);
+                       intel_sdvo_set_output_timing(output, &sdvo_priv->save_output_dtd[o]);
+               }
+       }
+
+       if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
+               intel_sdvo_set_target_input(output, true, false);
+               intel_sdvo_set_input_timing(output, &sdvo_priv->save_input_dtd_1);
+       }
+
+       if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
+               intel_sdvo_set_target_input(output, false, true);
+               intel_sdvo_set_input_timing(output, &sdvo_priv->save_input_dtd_2);
+       }
+       
+       intel_sdvo_set_clock_rate_mult(output, sdvo_priv->save_sdvo_mult);
+       
+       I915_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX);
+       
+       if (sdvo_priv->save_SDVOX & SDVO_ENABLE)
+       {
+               for (i = 0; i < 2; i++)
+                       intel_wait_for_vblank(dev);
+               status = intel_sdvo_get_trained_inputs(output, &input1, &input2);
+               if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
+                       DRM_DEBUG("First %s output reported failure to sync\n",
+                                  SDVO_NAME(sdvo_priv));
+       }
+       
+       intel_sdvo_set_active_outputs(output, sdvo_priv->save_active_outputs);
+}
+
+static int intel_sdvo_mode_valid(struct drm_output *output,
+                                struct drm_display_mode *mode)
+{
+       struct intel_output *intel_output = output->driver_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+
+       if (mode->flags & V_DBLSCAN)
+               return MODE_NO_DBLESCAN;
+
+       if (sdvo_priv->pixel_clock_min > mode->clock)
+               return MODE_CLOCK_LOW;
+
+       if (sdvo_priv->pixel_clock_max < mode->clock)
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
+}
+
+static bool intel_sdvo_get_capabilities(struct drm_output *output, struct intel_sdvo_caps *caps)
+{
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0);
+       status = intel_sdvo_read_response(output, caps, sizeof(*caps));
+       if (status != SDVO_CMD_STATUS_SUCCESS)
+               return false;
+
+       return true;
+}
+
+
+static void intel_sdvo_dump_cmd(struct drm_output *output, int opcode)
+{
+
+
+}
+
+static void intel_sdvo_dump_device(struct drm_output *output)
+{
+
+}
+
+void intel_sdvo_dump(void)
+{
+
+}
+
+
+static enum drm_output_status intel_sdvo_detect(struct drm_output *output)
+{
+       u8 response[2];
+       u8 status;
+
+       intel_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+       status = intel_sdvo_read_response(output, &response, 2);
+
+       DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
+       if ((response[0] != 0) || (response[1] != 0))
+               return output_status_connected;
+       else
+               return output_status_disconnected;
+}
+
+static int intel_sdvo_get_modes(struct drm_output *output)
+{
+       /* set the bus switch and get the modes */
+       intel_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2);
+       intel_ddc_get_modes(output);
+
+       if (list_empty(&output->probed_modes))
+               return 0;
+       return 1;
+#if 0
+       /* Mac mini hack.  On this device, I get DDC through the analog, which
+        * load-detects as disconnected.  I fail to DDC through the SDVO DDC,
+        * but it does load-detect as connected.  So, just steal the DDC bits 
+        * from analog when we fail at finding it the right way.
+        */
+       /* TODO */
+       return NULL;
+
+       return NULL;
+#endif
+}
+
+static void intel_sdvo_destroy(struct drm_output *output)
+{
+       struct intel_output *intel_output = output->driver_private;
+
+       if (intel_output->i2c_bus)
+               intel_i2c_destroy(intel_output->i2c_bus);
+
+       if (intel_output) {
+               kfree(intel_output);
+               output->driver_private = NULL;
+       }
+}
+
+static const struct drm_output_funcs intel_sdvo_output_funcs = {
+       .dpms = intel_sdvo_dpms,
+       .save = intel_sdvo_save,
+       .restore = intel_sdvo_restore,
+       .mode_valid = intel_sdvo_mode_valid,
+       .mode_fixup = intel_sdvo_mode_fixup,
+       .prepare = intel_output_prepare,
+       .mode_set = intel_sdvo_mode_set,
+       .commit = intel_output_commit,
+       .detect = intel_sdvo_detect,
+       .get_modes = intel_sdvo_get_modes,
+       .cleanup = intel_sdvo_destroy
+};
+
+void intel_sdvo_init(struct drm_device *dev, int output_device)
+{
+       struct drm_output *output;
+       struct intel_output *intel_output;
+       struct intel_sdvo_priv *sdvo_priv;
+       struct intel_i2c_chan *i2cbus = NULL;
+       u8 ch[0x40];
+       int i;
+       char name[DRM_OUTPUT_LEN];
+       char *name_prefix;
+       char *name_suffix;
+       
+
+       output = drm_output_create(dev, &intel_sdvo_output_funcs, NULL);
+       if (!output)
+               return;
+
+       intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
+       if (!intel_output) {
+               drm_output_destroy(output);
+               return;
+       }
+
+       sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
+       intel_output->type = INTEL_OUTPUT_SDVO;
+       output->driver_private = intel_output;
+       output->interlace_allowed = 0;
+       output->doublescan_allowed = 0;
+
+       /* setup the DDC bus. */
+       if (output_device == SDVOB)
+               i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
+       else
+               i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
+
+       if (i2cbus == NULL) {
+               drm_output_destroy(output);
+               return;
+       }
+
+       sdvo_priv->i2c_bus = i2cbus;
+
+       if (output_device == SDVOB) {
+               name_suffix = "-1";
+               sdvo_priv->i2c_bus->slave_addr = 0x38;
+       } else {
+               name_suffix = "-2";
+               sdvo_priv->i2c_bus->slave_addr = 0x39;
+       }
+
+       sdvo_priv->output_device = output_device;
+       intel_output->i2c_bus = i2cbus;
+       intel_output->dev_priv = sdvo_priv;
+
+
+       /* Read the regs to test if we can talk to the device */
+       for (i = 0; i < 0x40; i++) {
+               if (!intel_sdvo_read_byte(output, i, &ch[i])) {
+                       DRM_DEBUG("No SDVO device found on SDVO%c\n",
+                                 output_device == SDVOB ? 'B' : 'C');
+                       drm_output_destroy(output);
+                       return;
+               }
+       }
+
+       intel_sdvo_get_capabilities(output, &sdvo_priv->caps);
+
+       memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs));
+
+       /* TODO, CVBS, SVID, YPRPB & SCART outputs. */
+       if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
+       {
+               sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
+               output->subpixel_order = SubPixelHorizontalRGB;
+               name_prefix="RGB";
+       }
+       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
+       {
+               sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
+               output->subpixel_order = SubPixelHorizontalRGB;
+               name_prefix="RGB";
+       }
+       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
+       {
+               sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0;
+               output->subpixel_order = SubPixelHorizontalRGB;
+               name_prefix="TMDS";
+       }
+       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
+       {
+               sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1;
+               output->subpixel_order = SubPixelHorizontalRGB;
+               name_prefix="TMDS";
+       }
+       else
+       {
+               unsigned char bytes[2];
+               
+               memcpy (bytes, &sdvo_priv->caps.output_flags, 2);
+               DRM_DEBUG("%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
+                         SDVO_NAME(sdvo_priv),
+                         bytes[0], bytes[1]);
+               drm_output_destroy(output);
+               return;
+       }
+       strcpy (name, name_prefix);
+       strcat (name, name_suffix);
+       if (!drm_output_rename(output, name))
+       {
+               drm_output_destroy(output);
+               return;
+       }
+               
+
+       /* Set the input timing to the screen. Assume always input 0. */
+       intel_sdvo_set_target_input(output, true, false);
+       
+       intel_sdvo_get_input_pixel_clock_range(output,
+                                              &sdvo_priv->pixel_clock_min,
+                                              &sdvo_priv->pixel_clock_max);
+
+
+       DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, "
+                 "clock range %dMHz - %dMHz, "
+                 "input 1: %c, input 2: %c, "
+                 "output 1: %c, output 2: %c\n",
+                 SDVO_NAME(sdvo_priv),
+                 sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
+                 sdvo_priv->caps.device_rev_id,
+                 sdvo_priv->pixel_clock_min / 1000,
+                 sdvo_priv->pixel_clock_max / 1000,
+                 (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
+                 (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
+                 /* check currently supported outputs */
+                 sdvo_priv->caps.output_flags & 
+                       (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
+                 sdvo_priv->caps.output_flags & 
+                       (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
+
+       intel_output->ddc_bus = i2cbus; 
+}
diff --git a/linux-core/intel_sdvo_regs.h b/linux-core/intel_sdvo_regs.h
new file mode 100644 (file)
index 0000000..a9d1671
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *     Eric Anholt <eric@anholt.net>
+ */
+
+/**
+ * @file SDVO command definitions and structures.
+ */
+
+#define SDVO_OUTPUT_FIRST   (0)
+#define SDVO_OUTPUT_TMDS0   (1 << 0)
+#define SDVO_OUTPUT_RGB0    (1 << 1)
+#define SDVO_OUTPUT_CVBS0   (1 << 2)
+#define SDVO_OUTPUT_SVID0   (1 << 3)
+#define SDVO_OUTPUT_YPRPB0  (1 << 4)
+#define SDVO_OUTPUT_SCART0  (1 << 5)
+#define SDVO_OUTPUT_LVDS0   (1 << 6)
+#define SDVO_OUTPUT_TMDS1   (1 << 8)
+#define SDVO_OUTPUT_RGB1    (1 << 9)
+#define SDVO_OUTPUT_CVBS1   (1 << 10)
+#define SDVO_OUTPUT_SVID1   (1 << 11)
+#define SDVO_OUTPUT_YPRPB1  (1 << 12)
+#define SDVO_OUTPUT_SCART1  (1 << 13)
+#define SDVO_OUTPUT_LVDS1   (1 << 14)
+#define SDVO_OUTPUT_LAST    (14)
+
+struct intel_sdvo_caps {
+    u8 vendor_id;
+    u8 device_id;
+    u8 device_rev_id;
+    u8 sdvo_version_major;
+    u8 sdvo_version_minor;
+    unsigned int sdvo_inputs_mask:2;
+    unsigned int smooth_scaling:1;
+    unsigned int sharp_scaling:1;
+    unsigned int up_scaling:1;
+    unsigned int down_scaling:1;
+    unsigned int stall_support:1;
+    unsigned int pad:1;
+    u16 output_flags;
+} __attribute__((packed));
+
+/** This matches the EDID DTD structure, more or less */
+struct intel_sdvo_dtd {
+    struct {
+       u16 clock;              /**< pixel clock, in 10kHz units */
+       u8 h_active;            /**< lower 8 bits (pixels) */
+       u8 h_blank;             /**< lower 8 bits (pixels) */
+       u8 h_high;              /**< upper 4 bits each h_active, h_blank */
+       u8 v_active;            /**< lower 8 bits (lines) */
+       u8 v_blank;             /**< lower 8 bits (lines) */
+       u8 v_high;              /**< upper 4 bits each v_active, v_blank */
+    } part1;
+
+    struct {
+       u8 h_sync_off;  /**< lower 8 bits, from hblank start */
+       u8 h_sync_width;        /**< lower 8 bits (pixels) */
+       /** lower 4 bits each vsync offset, vsync width */
+       u8 v_sync_off_width;
+       /**
+        * 2 high bits of hsync offset, 2 high bits of hsync width,
+        * bits 4-5 of vsync offset, and 2 high bits of vsync width.
+        */
+       u8 sync_off_width_high;
+       u8 dtd_flags;
+       u8 sdvo_flags;
+       /** bits 6-7 of vsync offset at bits 6-7 */
+       u8 v_sync_off_high;
+       u8 reserved;
+    } part2;
+} __attribute__((packed));
+
+struct intel_sdvo_pixel_clock_range {
+    u16 min;                   /**< pixel clock, in 10kHz units */
+    u16 max;                   /**< pixel clock, in 10kHz units */
+} __attribute__((packed));
+
+struct intel_sdvo_preferred_input_timing_args {
+    u16 clock;
+    u16 width;
+    u16 height;
+} __attribute__((packed));
+
+/* I2C registers for SDVO */
+#define SDVO_I2C_ARG_0                         0x07
+#define SDVO_I2C_ARG_1                         0x06
+#define SDVO_I2C_ARG_2                         0x05
+#define SDVO_I2C_ARG_3                         0x04
+#define SDVO_I2C_ARG_4                         0x03
+#define SDVO_I2C_ARG_5                         0x02
+#define SDVO_I2C_ARG_6                         0x01
+#define SDVO_I2C_ARG_7                         0x00
+#define SDVO_I2C_OPCODE                                0x08
+#define SDVO_I2C_CMD_STATUS                    0x09
+#define SDVO_I2C_RETURN_0                      0x0a
+#define SDVO_I2C_RETURN_1                      0x0b
+#define SDVO_I2C_RETURN_2                      0x0c
+#define SDVO_I2C_RETURN_3                      0x0d
+#define SDVO_I2C_RETURN_4                      0x0e
+#define SDVO_I2C_RETURN_5                      0x0f
+#define SDVO_I2C_RETURN_6                      0x10
+#define SDVO_I2C_RETURN_7                      0x11
+#define SDVO_I2C_VENDOR_BEGIN                  0x20
+
+/* Status results */
+#define SDVO_CMD_STATUS_POWER_ON               0x0
+#define SDVO_CMD_STATUS_SUCCESS                        0x1
+#define SDVO_CMD_STATUS_NOTSUPP                        0x2
+#define SDVO_CMD_STATUS_INVALID_ARG            0x3
+#define SDVO_CMD_STATUS_PENDING                        0x4
+#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED   0x5
+#define SDVO_CMD_STATUS_SCALING_NOT_SUPP       0x6
+
+/* SDVO commands, argument/result registers */
+
+#define SDVO_CMD_RESET                                 0x01
+
+/** Returns a struct intel_sdvo_caps */
+#define SDVO_CMD_GET_DEVICE_CAPS                       0x02
+
+#define SDVO_CMD_GET_FIRMWARE_REV                      0x86
+# define SDVO_DEVICE_FIRMWARE_MINOR                    SDVO_I2C_RETURN_0
+# define SDVO_DEVICE_FIRMWARE_MAJOR                    SDVO_I2C_RETURN_1
+# define SDVO_DEVICE_FIRMWARE_PATCH                    SDVO_I2C_RETURN_2
+
+/**
+ * Reports which inputs are trained (managed to sync).
+ *
+ * Devices must have trained within 2 vsyncs of a mode change.
+ */
+#define SDVO_CMD_GET_TRAINED_INPUTS                    0x03
+struct intel_sdvo_get_trained_inputs_response {
+    unsigned int input0_trained:1;
+    unsigned int input1_trained:1;
+    unsigned int pad:6;
+} __attribute__((packed));
+
+/** Returns a struct intel_sdvo_output_flags of active outputs. */
+#define SDVO_CMD_GET_ACTIVE_OUTPUTS                    0x04
+
+/**
+ * Sets the current set of active outputs.
+ *
+ * Takes a struct intel_sdvo_output_flags.  Must be preceded by a SET_IN_OUT_MAP
+ * on multi-output devices.
+ */
+#define SDVO_CMD_SET_ACTIVE_OUTPUTS                    0x05
+
+/**
+ * Returns the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Returns two struct intel_sdvo_output_flags structures.
+ */
+#define SDVO_CMD_GET_IN_OUT_MAP                                0x06
+
+/**
+ * Sets the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Takes two struct i380_sdvo_output_flags structures.
+ */
+#define SDVO_CMD_SET_IN_OUT_MAP                                0x07
+
+/**
+ * Returns a struct intel_sdvo_output_flags of attached displays.
+ */
+#define SDVO_CMD_GET_ATTACHED_DISPLAYS                 0x0b
+
+/**
+ * Returns a struct intel_sdvo_ouptut_flags of displays supporting hot plugging.
+ */
+#define SDVO_CMD_GET_HOT_PLUG_SUPPORT                  0x0c
+
+/**
+ * Takes a struct intel_sdvo_output_flags.
+ */
+#define SDVO_CMD_SET_ACTIVE_HOT_PLUG                   0x0d
+
+/**
+ * Returns a struct intel_sdvo_output_flags of displays with hot plug
+ * interrupts enabled.
+ */
+#define SDVO_CMD_GET_ACTIVE_HOT_PLUG                   0x0e
+
+#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE            0x0f
+struct intel_sdvo_get_interrupt_event_source_response {
+    u16 interrupt_status;
+    unsigned int ambient_light_interrupt:1;
+    unsigned int pad:7;
+} __attribute__((packed));
+
+/**
+ * Selects which input is affected by future input commands.
+ *
+ * Commands affected include SET_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
+ */
+#define SDVO_CMD_SET_TARGET_INPUT                      0x10
+struct intel_sdvo_set_target_input_args {
+    unsigned int target_1:1;
+    unsigned int pad:7;
+} __attribute__((packed));
+
+/**
+ * Takes a struct intel_sdvo_output_flags of which outputs are targetted by
+ * future output commands.
+ *
+ * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
+ * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
+ */
+#define SDVO_CMD_SET_TARGET_OUTPUT                     0x11
+
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART1               0x12
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART2               0x13
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART1               0x14
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART2               0x15
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1              0x16
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2              0x17
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1              0x18
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2              0x19
+/* Part 1 */
+# define SDVO_DTD_CLOCK_LOW                            SDVO_I2C_ARG_0
+# define SDVO_DTD_CLOCK_HIGH                           SDVO_I2C_ARG_1
+# define SDVO_DTD_H_ACTIVE                             SDVO_I2C_ARG_2
+# define SDVO_DTD_H_BLANK                              SDVO_I2C_ARG_3
+# define SDVO_DTD_H_HIGH                               SDVO_I2C_ARG_4
+# define SDVO_DTD_V_ACTIVE                             SDVO_I2C_ARG_5
+# define SDVO_DTD_V_BLANK                              SDVO_I2C_ARG_6
+# define SDVO_DTD_V_HIGH                               SDVO_I2C_ARG_7
+/* Part 2 */
+# define SDVO_DTD_HSYNC_OFF                            SDVO_I2C_ARG_0
+# define SDVO_DTD_HSYNC_WIDTH                          SDVO_I2C_ARG_1
+# define SDVO_DTD_VSYNC_OFF_WIDTH                      SDVO_I2C_ARG_2
+# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH                  SDVO_I2C_ARG_3
+# define SDVO_DTD_DTD_FLAGS                            SDVO_I2C_ARG_4
+# define SDVO_DTD_DTD_FLAG_INTERLACED                          (1 << 7)
+# define SDVO_DTD_DTD_FLAG_STEREO_MASK                         (3 << 5)
+# define SDVO_DTD_DTD_FLAG_INPUT_MASK                          (3 << 3)
+# define SDVO_DTD_DTD_FLAG_SYNC_MASK                           (3 << 1)
+# define SDVO_DTD_SDVO_FLAS                            SDVO_I2C_ARG_5
+# define SDVO_DTD_SDVO_FLAG_STALL                              (1 << 7)
+# define SDVO_DTD_SDVO_FLAG_CENTERED                           (0 << 6)
+# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT                         (1 << 6)
+# define SDVO_DTD_SDVO_FLAG_SCALING_MASK                       (3 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_NONE                       (0 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP                      (1 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH                     (2 << 4)
+# define SDVO_DTD_VSYNC_OFF_HIGH                       SDVO_I2C_ARG_6
+
+/**
+ * Generates a DTD based on the given width, height, and flags.
+ *
+ * This will be supported by any device supporting scaling or interlaced
+ * modes.
+ */
+#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING         0x1a
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW         SDVO_I2C_ARG_0
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH                SDVO_I2C_ARG_1
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW         SDVO_I2C_ARG_2
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH                SDVO_I2C_ARG_3
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW                SDVO_I2C_ARG_4
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH       SDVO_I2C_ARG_5
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS             SDVO_I2C_ARG_6
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED          (1 << 0)
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED              (1 << 1)
+
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1      0x1b
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2      0x1c
+
+/** Returns a struct intel_sdvo_pixel_clock_range */
+#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE           0x1d
+/** Returns a struct intel_sdvo_pixel_clock_range */
+#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE          0x1e
+
+/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
+#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS                0x1f
+
+/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
+#define SDVO_CMD_GET_CLOCK_RATE_MULT                   0x20
+/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
+#define SDVO_CMD_SET_CLOCK_RATE_MULT                   0x21
+# define SDVO_CLOCK_RATE_MULT_1X                               (1 << 0)
+# define SDVO_CLOCK_RATE_MULT_2X                               (1 << 1)
+# define SDVO_CLOCK_RATE_MULT_4X                               (1 << 3)
+
+#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS              0x27
+
+#define SDVO_CMD_GET_TV_FORMAT                         0x28
+
+#define SDVO_CMD_SET_TV_FORMAT                         0x29
+
+#define SDVO_CMD_GET_SUPPORTED_POWER_STATES            0x2a
+#define SDVO_CMD_GET_ENCODER_POWER_STATE               0x2b
+#define SDVO_CMD_SET_ENCODER_POWER_STATE               0x2c
+# define SDVO_ENCODER_STATE_ON                                 (1 << 0)
+# define SDVO_ENCODER_STATE_STANDBY                            (1 << 1)
+# define SDVO_ENCODER_STATE_SUSPEND                            (1 << 2)
+# define SDVO_ENCODER_STATE_OFF                                        (1 << 3)
+
+#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT             0x93
+
+#define SDVO_CMD_SET_CONTROL_BUS_SWITCH                        0x7a
+# define SDVO_CONTROL_BUS_PROM                         0x0
+# define SDVO_CONTROL_BUS_DDC1                         0x1
+# define SDVO_CONTROL_BUS_DDC2                         0x2
+# define SDVO_CONTROL_BUS_DDC3                         0x3
+
index ef6f1e4..1eb6d9e 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "drm_pciids.h"
 
-static int mga_driver_device_is_agp(drm_device_t * dev);
+static int mga_driver_device_is_agp(struct drm_device * dev);
 
 static struct pci_device_id pciidlist[] = {
        mga_PCI_IDS
@@ -127,7 +127,7 @@ MODULE_LICENSE("GPL and additional rights");
  * \returns
  * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
  */
-static int mga_driver_device_is_agp(drm_device_t * dev)
+static int mga_driver_device_is_agp(struct drm_device * dev)
 {
        const struct pci_dev * const pdev = dev->pdev;
 
index 5775cd6..75f2a23 100644 (file)
@@ -32,7 +32,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
diff --git a/linux-core/nouveau_dma.c b/linux-core/nouveau_dma.c
new file mode 120000 (symlink)
index 0000000..f8e0bdc
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nouveau_dma.c
\ No newline at end of file
diff --git a/linux-core/nouveau_dma.h b/linux-core/nouveau_dma.h
new file mode 120000 (symlink)
index 0000000..a545e38
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nouveau_dma.h
\ No newline at end of file
index ac030d8..01de67d 100644 (file)
 #include "drm_pciids.h"
 
 static struct pci_device_id pciidlist[] = {
-       nouveau_PCI_IDS
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
+               .class = PCI_BASE_CLASS_DISPLAY << 16,
+               .class_mask  = 0xff << 16,
+       },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA_SGS, PCI_ANY_ID),
+               .class = PCI_BASE_CLASS_DISPLAY << 16,
+               .class_mask  = 0xff << 16,
+       }
 };
 
-extern drm_ioctl_desc_t nouveau_ioctls[];
+extern struct drm_ioctl_desc nouveau_ioctls[];
 extern int nouveau_max_ioctl;
 
 static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
index a752a58..f55ae7a 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
diff --git a/linux-core/nouveau_notifier.c b/linux-core/nouveau_notifier.c
new file mode 120000 (symlink)
index 0000000..285469c
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nouveau_notifier.c
\ No newline at end of file
diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c
new file mode 100644 (file)
index 0000000..b86c5d7
--- /dev/null
@@ -0,0 +1,339 @@
+#include "drmP.h"
+#include "nouveau_drv.h"
+
+#define NV_CTXDMA_PAGE_SHIFT 12
+#define NV_CTXDMA_PAGE_SIZE  (1 << NV_CTXDMA_PAGE_SHIFT)
+#define NV_CTXDMA_PAGE_MASK  (NV_CTXDMA_PAGE_SIZE - 1)
+
+struct nouveau_sgdma_be {
+       struct drm_ttm_backend backend;
+       struct drm_device *dev;
+
+       int         pages;
+       int         pages_populated;
+       dma_addr_t *pagelist;
+       int         is_bound;
+
+       unsigned int pte_start;
+};
+
+static int
+nouveau_sgdma_needs_ub_cache_adjust(struct drm_ttm_backend *be)
+{
+       return ((be->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
+}
+
+static int
+nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
+                      struct page **pages)
+{
+       struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+       int p, d, o;
+
+       DRM_DEBUG("num_pages = %ld\n", num_pages);
+
+       if (nvbe->pagelist)
+               return -EINVAL;
+       nvbe->pages    = (num_pages << PAGE_SHIFT) >> NV_CTXDMA_PAGE_SHIFT;
+       nvbe->pagelist = drm_alloc(nvbe->pages*sizeof(dma_addr_t),
+                                  DRM_MEM_PAGES);
+
+       nvbe->pages_populated = d = 0;
+       for (p = 0; p < num_pages; p++) {
+               for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) {
+                       nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev,
+                                                        pages[p], o,
+                                                        NV_CTXDMA_PAGE_SIZE,
+                                                        PCI_DMA_BIDIRECTIONAL);
+                       if (pci_dma_mapping_error(nvbe->pagelist[d])) {
+                               be->func->clear(be);
+                               DRM_ERROR("pci_map_page failed\n");
+                               return -EINVAL;
+                       }
+                       nvbe->pages_populated = ++d;
+               }
+       }
+
+       return 0;
+}
+
+static void
+nouveau_sgdma_clear(struct drm_ttm_backend *be)
+{
+       struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+       int d;
+
+       DRM_DEBUG("\n");
+
+       if (nvbe && nvbe->pagelist) {
+               if (nvbe->is_bound)
+                       be->func->unbind(be);
+
+               for (d = 0; d < nvbe->pages_populated; d++) {
+                       pci_unmap_page(nvbe->dev->pdev, nvbe->pagelist[d],
+                                      NV_CTXDMA_PAGE_SIZE,
+                                      PCI_DMA_BIDIRECTIONAL);
+               }
+               drm_free(nvbe->pagelist, nvbe->pages*sizeof(dma_addr_t),
+                        DRM_MEM_PAGES);
+       }
+}
+
+static int
+nouveau_sgdma_bind(struct drm_ttm_backend *be, struct drm_bo_mem_reg *mem)
+{
+       struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+       struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+       struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+       uint64_t offset = (mem->mm_node->start << PAGE_SHIFT);
+       uint32_t i;
+
+       DRM_DEBUG("pg=0x%lx (0x%llx), cached=%d\n", mem->mm_node->start,
+                 offset, (mem->flags & DRM_BO_FLAG_CACHED) == 1);
+
+       if (offset & NV_CTXDMA_PAGE_MASK)
+               return -EINVAL;
+       nvbe->pte_start = (offset >> NV_CTXDMA_PAGE_SHIFT);
+       if (dev_priv->card_type < NV_50)
+               nvbe->pte_start += 2; /* skip ctxdma header */
+
+       for (i = nvbe->pte_start; i < nvbe->pte_start + nvbe->pages; i++) {
+               uint64_t pteval = nvbe->pagelist[i - nvbe->pte_start];
+
+               if (pteval & NV_CTXDMA_PAGE_MASK) {
+                       DRM_ERROR("Bad pteval 0x%llx\n", pteval);
+                       return -EINVAL;
+               }
+
+               if (dev_priv->card_type < NV_50) {
+                       INSTANCE_WR(gpuobj, i, pteval | 3);
+               } else {
+                       INSTANCE_WR(gpuobj, (i<<1)+0, pteval | 0x21);
+                       INSTANCE_WR(gpuobj, (i<<1)+1, 0x00000000);
+               }
+       }
+
+       nvbe->is_bound  = 1;
+       return 0;
+}
+
+static int
+nouveau_sgdma_unbind(struct drm_ttm_backend *be)
+{
+       struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+       struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       if (nvbe->is_bound) {
+               struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+               unsigned int pte;
+               
+               pte = nvbe->pte_start;
+               while (pte < (nvbe->pte_start + nvbe->pages)) {
+                       uint64_t pteval = dev_priv->gart_info.sg_dummy_bus;
+
+                       if (dev_priv->card_type < NV_50) {
+                               INSTANCE_WR(gpuobj, pte, pteval | 3);
+                       } else {
+                               INSTANCE_WR(gpuobj, (pte<<1)+0, 0x00000010);
+                               INSTANCE_WR(gpuobj, (pte<<1)+1, 0x00000004);
+                       }
+
+                       pte++;
+               }
+
+               nvbe->is_bound = 0;
+       }
+
+       return 0;
+}
+
+static void
+nouveau_sgdma_destroy(struct drm_ttm_backend *be)
+{
+       DRM_DEBUG("\n");
+       if (be) {
+               struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+               if (nvbe) {
+                       if (nvbe->pagelist)
+                               be->func->clear(be);
+                       drm_ctl_free(nvbe, sizeof(*nvbe), DRM_MEM_TTM);
+               }
+       }
+}
+
+static struct drm_ttm_backend_func nouveau_sgdma_backend = {
+       .needs_ub_cache_adjust  = nouveau_sgdma_needs_ub_cache_adjust,
+       .populate               = nouveau_sgdma_populate,
+       .clear                  = nouveau_sgdma_clear,
+       .bind                   = nouveau_sgdma_bind,
+       .unbind                 = nouveau_sgdma_unbind,
+       .destroy                = nouveau_sgdma_destroy
+};
+
+struct drm_ttm_backend *
+nouveau_sgdma_init_ttm(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_sgdma_be *nvbe;
+
+       if (!dev_priv->gart_info.sg_ctxdma)
+               return NULL;
+
+       nvbe = drm_ctl_calloc(1, sizeof(*nvbe), DRM_MEM_TTM);
+       if (!nvbe)
+               return NULL;
+
+       nvbe->dev = dev;
+
+       nvbe->backend.func      = &nouveau_sgdma_backend;
+
+       return &nvbe->backend;
+}
+
+int
+nouveau_sgdma_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *gpuobj = NULL;
+       uint32_t aper_size, obj_size;
+       int i, ret;
+
+       if (dev_priv->card_type < NV_50) {
+               aper_size = (64 * 1024 * 1024);
+               obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
+               obj_size += 8; /* ctxdma header */
+       } else {
+               /* 1 entire VM page table */
+               aper_size = (512 * 1024 * 1024);
+               obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8;
+       }
+
+       if ((ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
+                                     NVOBJ_FLAG_ALLOW_NO_REFS |
+                                     NVOBJ_FLAG_ZERO_ALLOC |
+                                     NVOBJ_FLAG_ZERO_FREE, &gpuobj)))  {
+               DRM_ERROR("Error creating sgdma object: %d\n", ret);
+               return ret;
+       }
+
+       if (dev_priv->card_type < NV_50) {
+               dev_priv->gart_info.sg_dummy_page =
+                       alloc_page(GFP_KERNEL|__GFP_DMA32);
+               SetPageLocked(dev_priv->gart_info.sg_dummy_page);
+               dev_priv->gart_info.sg_dummy_bus =
+                       pci_map_page(dev->pdev,
+                                    dev_priv->gart_info.sg_dummy_page, 0,
+                                    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+
+               /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
+                * confirmed to work on c51.  Perhaps means NV_DMA_TARGET_PCIE
+                * on those cards? */
+               INSTANCE_WR(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY |
+                                      (1 << 12) /* PT present */ |
+                                      (0 << 13) /* PT *not* linear */ |
+                                      (NV_DMA_ACCESS_RW  << 14) |
+                                      (NV_DMA_TARGET_PCI << 16));
+               INSTANCE_WR(gpuobj, 1, aper_size - 1);
+               for (i=2; i<2+(aper_size>>12); i++) {
+                       INSTANCE_WR(gpuobj, i,
+                                   dev_priv->gart_info.sg_dummy_bus | 3);
+               }
+       } else {
+               for (i=0; i<obj_size; i+=8) {
+                       INSTANCE_WR(gpuobj, (i+0)/4, 0); //x00000010);
+                       INSTANCE_WR(gpuobj, (i+4)/4, 0); //0x00000004);
+               }
+       }
+
+       dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
+       dev_priv->gart_info.aper_base = 0;
+       dev_priv->gart_info.aper_size = aper_size;
+       dev_priv->gart_info.sg_ctxdma = gpuobj;
+       return 0;
+}
+
+void
+nouveau_sgdma_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->gart_info.sg_dummy_page) {
+               pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus,
+                              NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+               unlock_page(dev_priv->gart_info.sg_dummy_page);
+               __free_page(dev_priv->gart_info.sg_dummy_page);
+               dev_priv->gart_info.sg_dummy_page = NULL;
+               dev_priv->gart_info.sg_dummy_bus = 0;
+       }
+
+       nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma);
+}
+
+int
+nouveau_sgdma_nottm_hack_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct drm_ttm_backend *be;
+       struct drm_scatter_gather sgreq;
+       struct drm_mm_node mm_node;
+       struct drm_bo_mem_reg mem;
+       int ret;
+
+       dev_priv->gart_info.sg_be = nouveau_sgdma_init_ttm(dev);
+       if (!dev_priv->gart_info.sg_be)
+               return -ENOMEM;
+       be = dev_priv->gart_info.sg_be;
+
+       /* Hack the aperture size down to the amount of system memory
+        * we're going to bind into it.
+        */
+       if (dev_priv->gart_info.aper_size > 32*1024*1024)
+               dev_priv->gart_info.aper_size = 32*1024*1024;
+
+       sgreq.size = dev_priv->gart_info.aper_size;
+       if ((ret = drm_sg_alloc(dev, &sgreq))) {
+               DRM_ERROR("drm_sg_alloc failed: %d\n", ret);
+               return ret;
+       }
+       dev_priv->gart_info.sg_handle = sgreq.handle;
+
+       if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist))) {
+               DRM_ERROR("failed populate: %d\n", ret);
+               return ret;
+       }
+
+       mm_node.start = 0;
+       mem.mm_node = &mm_node;
+
+       if ((ret = be->func->bind(be, &mem))) {
+               DRM_ERROR("failed bind: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+void
+nouveau_sgdma_nottm_hack_takedown(struct drm_device *dev)
+{
+}
+
+int
+nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+       int pte;
+
+       pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
+       if (dev_priv->card_type < NV_50) {
+               *page = INSTANCE_RD(gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
+               return 0;
+       }
+
+       DRM_ERROR("Unimplemented on NV50\n");
+       return -EINVAL;
+}
+
diff --git a/linux-core/nouveau_swmthd.c b/linux-core/nouveau_swmthd.c
new file mode 120000 (symlink)
index 0000000..c539080
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nouveau_swmthd.c
\ No newline at end of file
diff --git a/linux-core/nouveau_swmthd.h b/linux-core/nouveau_swmthd.h
new file mode 120000 (symlink)
index 0000000..33425dc
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nouveau_swmthd.h
\ No newline at end of file
diff --git a/linux-core/nv04_fifo.c b/linux-core/nv04_fifo.c
new file mode 120000 (symlink)
index 0000000..d10beb1
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv04_fifo.c
\ No newline at end of file
diff --git a/linux-core/nv04_instmem.c b/linux-core/nv04_instmem.c
new file mode 120000 (symlink)
index 0000000..e720fb5
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv04_instmem.c
\ No newline at end of file
diff --git a/linux-core/nv10_fifo.c b/linux-core/nv10_fifo.c
new file mode 120000 (symlink)
index 0000000..8630ad0
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv10_fifo.c
\ No newline at end of file
diff --git a/linux-core/nv30_graph.c b/linux-core/nv30_graph.c
deleted file mode 120000 (symlink)
index 25568ec..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../shared-core/nv30_graph.c
\ No newline at end of file
diff --git a/linux-core/nv40_fifo.c b/linux-core/nv40_fifo.c
new file mode 120000 (symlink)
index 0000000..cc71e7a
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv40_fifo.c
\ No newline at end of file
diff --git a/linux-core/nv50_fifo.c b/linux-core/nv50_fifo.c
new file mode 120000 (symlink)
index 0000000..4c9990a
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv50_fifo.c
\ No newline at end of file
diff --git a/linux-core/nv50_graph.c b/linux-core/nv50_graph.c
new file mode 120000 (symlink)
index 0000000..03f69e6
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv50_graph.c
\ No newline at end of file
diff --git a/linux-core/nv50_instmem.c b/linux-core/nv50_instmem.c
new file mode 120000 (symlink)
index 0000000..4e45344
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv50_instmem.c
\ No newline at end of file
diff --git a/linux-core/nv50_mc.c b/linux-core/nv50_mc.c
new file mode 120000 (symlink)
index 0000000..f4bb369
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/nv50_mc.c
\ No newline at end of file
index 7363054..6b75757 100644 (file)
@@ -30,7 +30,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
index 3afc17e..8e2b20b 100644 (file)
@@ -33,7 +33,7 @@
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-drm_ttm_backend_t *radeon_create_ttm_backend_entry(drm_device_t * dev)
+struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -43,7 +43,7 @@ drm_ttm_backend_t *radeon_create_ttm_backend_entry(drm_device_t * dev)
                return ati_pcigart_init_ttm(dev, &dev_priv->gart_info, radeon_gart_flush);
 }
 
-int radeon_fence_types(drm_buffer_object_t *bo, uint32_t * class, uint32_t * type)
+int radeon_fence_types(struct drm_buffer_object *bo, uint32_t * class, uint32_t * type)
 {
        *class = 0;
        if (bo->mem.flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE))
@@ -53,7 +53,7 @@ int radeon_fence_types(drm_buffer_object_t *bo, uint32_t * class, uint32_t * typ
        return 0;
 }
 
-int radeon_invalidate_caches(drm_device_t * dev, uint32_t flags)
+int radeon_invalidate_caches(struct drm_device * dev, uint64_t flags)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -65,7 +65,7 @@ int radeon_invalidate_caches(drm_device_t * dev, uint32_t flags)
        return 0;
 }
 
-uint32_t radeon_evict_mask(drm_buffer_object_t *bo)
+uint32_t radeon_evict_mask(struct drm_buffer_object *bo)
 {
        switch (bo->mem.mem_type) {
        case DRM_BO_MEM_LOCAL:
@@ -81,8 +81,8 @@ uint32_t radeon_evict_mask(drm_buffer_object_t *bo)
        }
 }
 
-int radeon_init_mem_type(drm_device_t * dev, uint32_t type,
-                        drm_mem_type_manager_t * man)
+int radeon_init_mem_type(struct drm_device * dev, uint32_t type,
+                        struct drm_mem_type_manager * man)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -127,7 +127,7 @@ int radeon_init_mem_type(drm_device_t * dev, uint32_t type,
        return 0;
 }
 
-static void radeon_emit_copy_blit(drm_device_t * dev,
+static void radeon_emit_copy_blit(struct drm_device * dev,
                                  uint32_t src_offset,
                                  uint32_t dst_offset,
                                  uint32_t pages, int direction)
@@ -183,10 +183,10 @@ static void radeon_emit_copy_blit(drm_device_t * dev,
        return;
 }
 
-static int radeon_move_blit(drm_buffer_object_t * bo,
-                           int evict, int no_wait, drm_bo_mem_reg_t *new_mem)
+static int radeon_move_blit(struct drm_buffer_object * bo,
+                           int evict, int no_wait, struct drm_bo_mem_reg *new_mem)
 {
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
        int dir = 0;
 
        if ((old_mem->mem_type == new_mem->mem_type) &&
@@ -207,11 +207,11 @@ static int radeon_move_blit(drm_buffer_object_t * bo,
                                         DRM_RADEON_FENCE_FLAG_FLUSHED, new_mem);
 }
 
-static int radeon_move_flip(drm_buffer_object_t * bo,
-                           int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
+static int radeon_move_flip(struct drm_buffer_object * bo,
+                           int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
 {
-       drm_device_t *dev = bo->dev;
-       drm_bo_mem_reg_t tmp_mem;
+       struct drm_device *dev = bo->dev;
+       struct drm_bo_mem_reg tmp_mem;
        int ret;
 
        tmp_mem = *new_mem;
@@ -223,7 +223,7 @@ static int radeon_move_flip(drm_buffer_object_t * bo,
        if (ret)
                return ret;
 
-       ret = drm_bind_ttm(bo->ttm, 1, tmp_mem.mm_node->start);
+       ret = drm_bind_ttm(bo->ttm, &tmp_mem);
        if (ret)
                goto out_cleanup;
 
@@ -243,10 +243,10 @@ out_cleanup:
        return ret;
 }
 
-int radeon_move(drm_buffer_object_t * bo,
-               int evict, int no_wait, drm_bo_mem_reg_t * new_mem)
+int radeon_move(struct drm_buffer_object * bo,
+               int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
 {
-       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       struct drm_bo_mem_reg *old_mem = &bo->mem;
 
        DRM_DEBUG("\n");
        if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
index 079971d..107d71a 100644 (file)
@@ -58,7 +58,7 @@ static struct pci_device_id pciidlist[] = {
 
 
 #ifdef RADEON_HAVE_FENCE
-static drm_fence_driver_t radeon_fence_driver = {
+static struct drm_fence_driver radeon_fence_driver = {
        .num_classes = 1,
        .wrap_diff = (1 << 30),
        .flush_diff = (1 << 29),
@@ -74,7 +74,7 @@ static drm_fence_driver_t radeon_fence_driver = {
 static uint32_t radeon_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
 static uint32_t radeon_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
 
-static drm_bo_driver_t radeon_bo_driver = {
+static struct drm_bo_driver radeon_bo_driver = {
        .mem_type_prio = radeon_mem_prios,
        .mem_busy_prio = radeon_busy_prios,
        .num_mem_type_prio = sizeof(radeon_mem_prios)/sizeof(uint32_t),
index 7de3650..682f0be 100644 (file)
  * Implements an intel sync flush operation.
  */
 
-static void radeon_perform_flush(drm_device_t * dev)
+static void radeon_perform_flush(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-       drm_fence_manager_t *fm = &dev->fm;
-       drm_fence_class_manager_t *fc = &dev->fm.class[0];
-       drm_fence_driver_t *driver = dev->driver->fence_driver;
+       struct drm_fence_manager *fm = &dev->fm;
+       struct drm_fence_class_manager *fc = &dev->fm.fence_class[0];
+       struct drm_fence_driver *driver = dev->driver->fence_driver;
        uint32_t pending_flush_types = 0;
        uint32_t sequence;
 
@@ -56,15 +56,15 @@ static void radeon_perform_flush(drm_device_t * dev)
        if (pending_flush_types) {
                sequence = READ_BREADCRUMB(dev_priv);
                                             
-               drm_fence_handler(dev, 0, sequence, pending_flush_types);
+               drm_fence_handler(dev, 0, sequence, pending_flush_types, 0);
        }
 
        return;
 }
 
-void radeon_poke_flush(drm_device_t * dev, uint32_t class)
+void radeon_poke_flush(struct drm_device * dev, uint32_t class)
 {
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
        unsigned long flags;
 
        if (class != 0)
@@ -75,7 +75,7 @@ void radeon_poke_flush(drm_device_t * dev, uint32_t class)
        write_unlock_irqrestore(&fm->lock, flags);
 }
 
-int radeon_fence_emit_sequence(drm_device_t *dev, uint32_t class,
+int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class,
                               uint32_t flags, uint32_t *sequence,
                               uint32_t *native_type)
 {
@@ -103,16 +103,16 @@ int radeon_fence_emit_sequence(drm_device_t *dev, uint32_t class,
        return 0;
 }
 
-void radeon_fence_handler(drm_device_t * dev)
+void radeon_fence_handler(struct drm_device * dev)
 {
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
 
        write_lock(&fm->lock);
        radeon_perform_flush(dev);
        write_unlock(&fm->lock);
 }
 
-int radeon_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags)
+int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags)
 {
        /*
         * We have an irq that tells us when we have a new breadcrumb.
index b980bed..bc8aa35 100644 (file)
@@ -28,7 +28,6 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
-#include <linux/ioctl32.h>
 
 #include "drmP.h"
 #include "drm.h"
@@ -350,6 +349,36 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
                         DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
 }
 
+/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
+#if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
+typedef struct drm_radeon_setparam32 {
+       int param;
+       u64 value;
+} __attribute__((packed)) drm_radeon_setparam32_t;
+
+static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd,
+                                    unsigned long arg)
+{
+       drm_radeon_setparam32_t req32;
+       drm_radeon_setparam_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.param, &request->param)
+           || __put_user((void __user *)(unsigned long)req32.value,
+                         &request->value))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
+}
+#else
+#define compat_radeon_cp_setparam NULL
+#endif /* X86_64 || IA64 */
+
 drm_ioctl_compat_t *radeon_compat_ioctls[] = {
        [DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
        [DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
@@ -358,6 +387,7 @@ drm_ioctl_compat_t *radeon_compat_ioctls[] = {
        [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
        [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
        [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
+       [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam,
        [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
        [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
 };
index 114ec8f..c9112c6 100644 (file)
@@ -36,14 +36,14 @@ static struct pci_device_id pciidlist[] = {
 };
 
 
-static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
+static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
 {
        drm_sis_private_t *dev_priv;
        int ret;
 
        dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER);
        if (dev_priv == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        dev->dev_private = (void *)dev_priv;
        dev_priv->chipset = chipset;
@@ -55,7 +55,7 @@ static int sis_driver_load(drm_device_t *dev, unsigned long chipset)
        return ret;
 }
 
-static int sis_driver_unload(drm_device_t *dev)
+static int sis_driver_unload(struct drm_device *dev)
 {
        drm_sis_private_t *dev_priv = dev->dev_private;
 
index 21c1f2d..9222b08 100644 (file)
@@ -81,19 +81,16 @@ unsigned long sis_sman_mm_offset(void *private, void *ref)
 
 #endif
 
-static int sis_fb_init(DRM_IOCTL_ARGS)
+static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_fb_t fb;
+       drm_sis_fb_t *fb = data;
        int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
-
        mutex_lock(&dev->struct_mutex);
 #if defined(__linux__) && defined(CONFIG_FB_SIS)
        {
-               drm_sman_mm_t sman_mm;
+               struct drm_sman_mm sman_mm;
                sman_mm.private = (void *)0xFFFFFFFF;
                sman_mm.allocate = sis_sman_mm_allocate;
                sman_mm.free = sis_sman_mm_free;
@@ -104,7 +101,7 @@ static int sis_fb_init(DRM_IOCTL_ARGS)
        }
 #else
        ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
-                                fb.size >> SIS_MM_ALIGN_SHIFT);
+                                fb->size >> SIS_MM_ALIGN_SHIFT);
 #endif
 
        if (ret) {
@@ -114,24 +111,21 @@ static int sis_fb_init(DRM_IOCTL_ARGS)
        }
 
        dev_priv->vram_initialized = 1;
-       dev_priv->vram_offset = fb.offset;
+       dev_priv->vram_offset = fb->offset;
 
        mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
+       DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size);
 
        return 0;
 }
 
-static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
-                        unsigned long data, int pool)
+static int sis_drm_alloc(struct drm_device * dev, struct drm_file *file_priv,
+                        void *data, int pool)
 {
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data;
-       drm_sis_mem_t mem;
+       drm_sis_mem_t *mem = data;
        int retval = 0;
-       drm_memblock_item_t *item;
-
-       DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem));
+       struct drm_memblock_item *item;
 
        mutex_lock(&dev->struct_mutex);
 
@@ -139,73 +133,66 @@ static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
                      dev_priv->agp_initialized)) {
                DRM_ERROR
                    ("Attempt to allocate from uninitialized memory manager.\n");
-               return DRM_ERR(EINVAL);
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
        }
 
-       mem.size = (mem.size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
-       item = drm_sman_alloc(&dev_priv->sman, pool, mem.size, 0,
-                             (unsigned long)priv);
+       mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
+       item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0,
+                             (unsigned long)file_priv);
 
        mutex_unlock(&dev->struct_mutex);
        if (item) {
-               mem.offset = ((pool == 0) ?
+               mem->offset = ((pool == 0) ?
                              dev_priv->vram_offset : dev_priv->agp_offset) +
                    (item->mm->
                     offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
-               mem.free = item->user_hash.key;
-               mem.size = mem.size << SIS_MM_ALIGN_SHIFT;
+               mem->free = item->user_hash.key;
+               mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
        } else {
-               mem.offset = 0;
-               mem.size = 0;
-               mem.free = 0;
-               retval = DRM_ERR(ENOMEM);
+               mem->offset = 0;
+               mem->size = 0;
+               mem->free = 0;
+               retval = -ENOMEM;
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, mem, sizeof(mem));
-
-       DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem.size,
-                 mem.offset);
+       DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size,
+                 mem->offset);
 
        return retval;
 }
 
-static int sis_drm_free(DRM_IOCTL_ARGS)
+static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t mem;
+       drm_sis_mem_t *mem = data;
        int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(mem, (drm_sis_mem_t __user *) data,
-                                sizeof(mem));
-
        mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_free_key(&dev_priv->sman, mem.free);
+       ret = drm_sman_free_key(&dev_priv->sman, mem->free);
        mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("free = 0x%lx\n", mem.free);
+       DRM_DEBUG("free = 0x%lx\n", mem->free);
 
        return ret;
 }
 
-static int sis_fb_alloc(DRM_IOCTL_ARGS)
+static int sis_fb_alloc(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       return sis_drm_alloc(dev, priv, data, VIDEO_TYPE);
+       return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
 }
 
-static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
+static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_agp_t agp;
+       drm_sis_agp_t *agp = data;
        int ret;
        dev_priv = dev->dev_private;
 
-       DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
-                                sizeof(agp));
        mutex_lock(&dev->struct_mutex);
        ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
-                                agp.size >> SIS_MM_ALIGN_SHIFT);
+                                agp->size >> SIS_MM_ALIGN_SHIFT);
 
        if (ret) {
                DRM_ERROR("AGP memory manager initialisation error\n");
@@ -214,23 +201,23 @@ static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
        }
 
        dev_priv->agp_initialized = 1;
-       dev_priv->agp_offset = agp.offset;
+       dev_priv->agp_offset = agp->offset;
        mutex_unlock(&dev->struct_mutex);
 
-       DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+       DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size);
        return 0;
 }
 
-static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
+static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
-       return sis_drm_alloc(dev, priv, data, AGP_TYPE);
+       return sis_drm_alloc(dev, file_priv, data, AGP_TYPE);
 }
 
-static drm_local_map_t *sis_reg_init(drm_device_t *dev)
+static drm_local_map_t *sis_reg_init(struct drm_device *dev)
 {
-       drm_map_list_t *entry;
+       struct drm_map_list *entry;
        drm_local_map_t *map;
 
        list_for_each_entry(entry, &dev->maplist, head) {
@@ -245,7 +232,7 @@ static drm_local_map_t *sis_reg_init(drm_device_t *dev)
 }
 
 int
-sis_idle(drm_device_t *dev)
+sis_idle(struct drm_device *dev)
 {
        drm_sis_private_t *dev_priv = dev->dev_private;
        uint32_t idle_reg;
@@ -314,13 +301,13 @@ void sis_lastclose(struct drm_device *dev)
        mutex_unlock(&dev->struct_mutex);
 }
 
-void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void sis_reclaim_buffers_locked(struct drm_device * dev,
+                               struct drm_file *file_priv)
 {
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_file_t *priv = filp->private_data;
 
        mutex_lock(&dev->struct_mutex);
-       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
+       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
                mutex_unlock(&dev->struct_mutex);
                return;
        }
@@ -329,20 +316,18 @@ void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
                dev->driver->dma_quiescent(dev);
        }
 
-       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
+       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
        mutex_unlock(&dev->struct_mutex);
        return;
 }
 
-drm_ioctl_desc_t sis_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_drm_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] =
-           {sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_drm_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] =
-           {sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY}
+struct drm_ioctl_desc sis_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_drm_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
 };
 
 int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
index ebc8c37..a6c5983 100644 (file)
 #include "via_drm.h"
 #include "via_drv.h"
 
-drm_ttm_backend_t *via_create_ttm_backend_entry(drm_device_t * dev)
+struct drm_ttm_backend *via_create_ttm_backend_entry(struct drm_device * dev)
 {
        return drm_agp_init_ttm(dev);
 }
 
-int via_fence_types(drm_buffer_object_t *bo, uint32_t * class, uint32_t * type)
+int via_fence_types(struct drm_buffer_object *bo, uint32_t * fclass,
+                   uint32_t * type)
 {
-       *class = 0;
        *type = 3;
        return 0;
 }
 
-int via_invalidate_caches(drm_device_t * dev, uint32_t flags)
+int via_invalidate_caches(struct drm_device * dev, uint64_t flags)
 {
        /*
         * FIXME: Invalidate texture caches here.
@@ -54,14 +54,14 @@ int via_invalidate_caches(drm_device_t * dev, uint32_t flags)
 }
 
 
-static int via_vram_info(drm_device_t *dev,
+static int via_vram_info(struct drm_device *dev,
                         unsigned long *offset,
                         unsigned long *size)
 {
        struct pci_dev *pdev = dev->pdev;
        unsigned long flags;
 
-       int ret = DRM_ERR(EINVAL);
+       int ret = -EINVAL;
        int i;
        for (i=0; i<6; ++i) {
                flags = pci_resource_flags(pdev, i);
@@ -82,8 +82,8 @@ static int via_vram_info(drm_device_t *dev,
        return 0;
 }
 
-int via_init_mem_type(drm_device_t * dev, uint32_t type,
-                      drm_mem_type_manager_t * man)
+int via_init_mem_type(struct drm_device * dev, uint32_t type,
+                      struct drm_mem_type_manager * man)
 {
        switch (type) {
        case DRM_BO_MEM_LOCAL:
@@ -144,7 +144,7 @@ int via_init_mem_type(drm_device_t * dev, uint32_t type,
        return 0;
 }
 
-uint32_t via_evict_mask(drm_buffer_object_t *bo)
+uint32_t via_evict_mask(struct drm_buffer_object *bo)
 {
        switch (bo->mem.mem_type) {
        case DRM_BO_MEM_LOCAL:
index 2f50837..d44c26f 100644 (file)
@@ -206,7 +206,7 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
  */
 
 static void
-via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)
+via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -236,7 +236,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
                first_pfn + 1;
        
        if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages)))
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);
        down_read(&current->mm->mmap_sem);
        ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr,
@@ -248,7 +248,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
                if (ret < 0) 
                        return ret;
                vsg->state = dr_via_pages_locked;
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        vsg->state = dr_via_pages_locked;
        DRM_DEBUG("DMA pages locked\n");
@@ -271,14 +271,14 @@ via_alloc_desc_pages(drm_via_sg_info_t *vsg)
                vsg->descriptors_per_page;
 
        if (NULL ==  (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL))) 
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        
        memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages);
        vsg->state = dr_via_desc_pages_alloc;
        for (i=0; i<vsg->num_desc_pages; ++i) {
                if (NULL == (vsg->desc_pages[i] = 
                             (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
        }
        DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,
                  vsg->num_desc);
@@ -286,7 +286,7 @@ via_alloc_desc_pages(drm_via_sg_info_t *vsg)
 }
                        
 static void
-via_abort_dmablit(drm_device_t *dev, int engine)
+via_abort_dmablit(struct drm_device *dev, int engine)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -294,7 +294,7 @@ via_abort_dmablit(drm_device_t *dev, int engine)
 }
 
 static void
-via_dmablit_engine_off(drm_device_t *dev, int engine)
+via_dmablit_engine_off(struct drm_device *dev, int engine)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
 
@@ -311,7 +311,7 @@ via_dmablit_engine_off(drm_device_t *dev, int engine)
  */
                
 void
-via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)
+via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
        drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
@@ -432,7 +432,7 @@ via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_que
  */
 
 static int
-via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine) 
+via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine) 
 {
 
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -465,7 +465,7 @@ static void
 via_dmablit_timer(unsigned long data)
 {
        drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
-       drm_device_t *dev = blitq->dev;
+       struct drm_device *dev = blitq->dev;
        int engine = (int)
                (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
                
@@ -509,7 +509,7 @@ via_dmablit_workqueue(struct work_struct *work)
 #else
        drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
 #endif
-        drm_device_t *dev = blitq->dev;
+        struct drm_device *dev = blitq->dev;
        unsigned long irqsave;
        drm_via_sg_info_t *cur_sg;
        int cur_released;
@@ -552,7 +552,7 @@ via_dmablit_workqueue(struct work_struct *work)
 
 
 void
-via_init_dmablit(drm_device_t *dev)
+via_init_dmablit(struct drm_device *dev)
 {
        int i,j;
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
@@ -568,7 +568,7 @@ via_init_dmablit(drm_device_t *dev)
                blitq->head = 0;
                blitq->cur = 0;
                blitq->serviced = 0;
-               blitq->num_free = VIA_NUM_BLIT_SLOTS;
+               blitq->num_free = VIA_NUM_BLIT_SLOTS - 1;
                blitq->num_outstanding = 0;
                blitq->is_active = 0;
                blitq->aborting = 0;
@@ -594,7 +594,7 @@ via_init_dmablit(drm_device_t *dev)
                
 
 static int
-via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
 {
        int draw = xfer->to_fb;
        int ret = 0;
@@ -606,7 +606,7 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
 
        if (xfer->num_lines <= 0 || xfer->line_length <= 0) {
                DRM_ERROR("Zero size bitblt.\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /*
@@ -619,7 +619,7 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
        if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) {
                DRM_ERROR("Too large system memory stride. Stride: %d, "
                          "Length: %d\n", xfer->mem_stride, xfer->line_length);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if ((xfer->mem_stride == xfer->line_length) &&
@@ -637,7 +637,7 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
 
        if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) {
                DRM_ERROR("Too large PCI DMA bitblt.\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }               
 
        /* 
@@ -648,7 +648,7 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
        if (xfer->mem_stride < xfer->line_length ||
            abs(xfer->fb_stride) < xfer->line_length) {
                DRM_ERROR("Invalid frame-buffer / memory stride.\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /*
@@ -661,13 +661,13 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *
        if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
            ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) {
                DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 #else
        if ((((unsigned long)xfer->mem_addr & 15) || ((unsigned long)xfer->fb_addr & 3)) ||
            ((xfer->num_lines > 1) && ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) {
                DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }       
 #endif
 
@@ -707,7 +707,7 @@ via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
 
                DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);
                if (ret) {
-                       return (DRM_ERR(EINTR) == ret) ? DRM_ERR(EAGAIN) : ret;
+                       return (-EINTR == ret) ? -EAGAIN : ret;
                }
                
                spin_lock_irqsave(&blitq->blit_lock, irqsave);
@@ -740,7 +740,7 @@ via_dmablit_release_slot(drm_via_blitq_t *blitq)
 
 
 static int 
-via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)         
+via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)    
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
        drm_via_sg_info_t *vsg;
@@ -751,7 +751,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
 
        if (dev_priv == NULL) {
                DRM_ERROR("Called without initialization.\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        engine = (xfer->to_fb) ? 0 : 1;
@@ -761,7 +761,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
        }
        if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {
                via_dmablit_release_slot(blitq);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
        if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {
                via_dmablit_release_slot(blitq);
@@ -792,21 +792,18 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
  */
 
 int
-via_dma_blit_sync( DRM_IOCTL_ARGS )
+via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv )
 {
-       drm_via_blitsync_t sync;
+       drm_via_blitsync_t *sync = data;
        int err;
-       DRM_DEVICE;
 
-       DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync));
-       
-       if (sync.engine >= VIA_NUM_BLIT_ENGINES) 
-               return DRM_ERR(EINVAL);
+       if (sync->engine >= VIA_NUM_BLIT_ENGINES) 
+               return -EINVAL;
 
-       err = via_dmablit_sync(dev, sync.sync_handle, sync.engine);
+       err = via_dmablit_sync(dev, sync->sync_handle, sync->engine);
 
-       if (DRM_ERR(EINTR) == err)
-               err = DRM_ERR(EAGAIN);
+       if (-EINTR == err)
+               err = -EAGAIN;
 
        return err;
 }
@@ -819,17 +816,12 @@ via_dma_blit_sync( DRM_IOCTL_ARGS )
  */
 
 int 
-via_dma_blit( DRM_IOCTL_ARGS )
+via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv )
 {
-       drm_via_dmablit_t xfer;
+       drm_via_dmablit_t *xfer = data;
        int err;
-       DRM_DEVICE;
-
-       DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer));
-
-       err = via_dmablit(dev, &xfer);
 
-       DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer));
+       err = via_dmablit(dev, xfer);
 
        return err;
 }
index f6ae03e..726ad25 100644 (file)
@@ -59,7 +59,7 @@ typedef struct _drm_via_sg_info {
 } drm_via_sg_info_t;
 
 typedef struct _drm_via_blitq {
-       drm_device_t *dev;
+       struct drm_device *dev;
        uint32_t cur_blit_handle;
        uint32_t done_blit_handle;
        unsigned serviced;
index 0224993..9af1bf3 100644 (file)
  */
 
 
-static uint32_t via_perform_flush(drm_device_t *dev, uint32_t class)
+static uint32_t via_perform_flush(struct drm_device *dev, uint32_t class)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_fence_class_manager_t *fc = &dev->fm.class[class];
+       struct drm_fence_class_manager *fc = &dev->fm.fence_class[class];
        uint32_t pending_flush_types = 0;
        uint32_t signaled_flush_types = 0;
        uint32_t status;
@@ -98,7 +98,8 @@ static uint32_t via_perform_flush(drm_device_t *dev, uint32_t class)
                                drm_idlelock_release(&dev->lock);
                                dev_priv->have_idlelock = 0;
                        }
-                       drm_fence_handler(dev, 0, dev_priv->emit_0_sequence, signaled_flush_types);
+                       drm_fence_handler(dev, 0, dev_priv->emit_0_sequence,
+                                         signaled_flush_types, 0);
                }
        }
 
@@ -113,7 +114,7 @@ static uint32_t via_perform_flush(drm_device_t *dev, uint32_t class)
  * Emit a fence sequence.
  */
 
-int via_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags,
+int via_fence_emit_sequence(struct drm_device * dev, uint32_t class, uint32_t flags,
                             uint32_t * sequence, uint32_t * native_type)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -142,7 +143,7 @@ int via_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags,
                *native_type = DRM_FENCE_TYPE_EXE;
                break;
        default:
-               ret = DRM_ERR(EINVAL);
+               ret = -EINVAL;
                break;
        }
        return ret;
@@ -152,10 +153,10 @@ int via_fence_emit_sequence(drm_device_t * dev, uint32_t class, uint32_t flags,
  * Manual poll (from the fence manager).
  */
 
-void via_poke_flush(drm_device_t * dev, uint32_t class)
+void via_poke_flush(struct drm_device * dev, uint32_t class)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
        unsigned long flags;
        uint32_t pending_flush;
 
@@ -200,11 +201,11 @@ int via_fence_has_irq(struct drm_device * dev, uint32_t class,
 
 void via_fence_timer(unsigned long data)
 {
-       drm_device_t *dev = (drm_device_t *) data;
+       struct drm_device *dev = (struct drm_device *) data;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_fence_manager_t *fm = &dev->fm;
+       struct drm_fence_manager *fm = &dev->fm;
        uint32_t pending_flush;
-       drm_fence_class_manager_t *fc = &dev->fm.class[0];
+       struct drm_fence_class_manager *fc = &dev->fm.fence_class[0];
 
        if (!dev_priv)
                return;
index d97269f..35ca6bf 100644 (file)
 #define VIA_MM_ALIGN_SHIFT 4
 #define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
 
-int via_agp_init(DRM_IOCTL_ARGS)
+int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_agp_t agp;
+       drm_via_agp_t *agp = data;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
-                                sizeof(agp));
        mutex_lock(&dev->struct_mutex);
        ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0,
-                                agp.size >> VIA_MM_ALIGN_SHIFT);
+                                agp->size >> VIA_MM_ALIGN_SHIFT);
 
        if (ret) {
                DRM_ERROR("AGP memory manager initialisation error\n");
@@ -53,25 +50,22 @@ int via_agp_init(DRM_IOCTL_ARGS)
        }
 
        dev_priv->agp_initialized = 1;
-       dev_priv->agp_offset = agp.offset;
+       dev_priv->agp_offset = agp->offset;
        mutex_unlock(&dev->struct_mutex);
 
-       DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+       DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size);
        return 0;
 }
 
-int via_fb_init(DRM_IOCTL_ARGS)
+int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_fb_t fb;
+       drm_via_fb_t *fb = data;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
-
        mutex_lock(&dev->struct_mutex);
        ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0,
-                                fb.size >> VIA_MM_ALIGN_SHIFT);
+                                fb->size >> VIA_MM_ALIGN_SHIFT);
 
        if (ret) {
                DRM_ERROR("VRAM memory manager initialisation error\n");
@@ -80,10 +74,10 @@ int via_fb_init(DRM_IOCTL_ARGS)
        }
 
        dev_priv->vram_initialized = 1;
-       dev_priv->vram_offset = fb.offset;
+       dev_priv->vram_offset = fb->offset;
 
        mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
+       DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size);
 
        return 0;
 
@@ -123,80 +117,71 @@ void via_lastclose(struct drm_device *dev)
        mutex_unlock(&dev->struct_mutex);
 }      
 
-int via_mem_alloc(DRM_IOCTL_ARGS)
+int via_mem_alloc(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-
-       drm_via_mem_t mem;
+       drm_via_mem_t *mem = data;
        int retval = 0;
-       drm_memblock_item_t *item;
+       struct drm_memblock_item *item;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        unsigned long tmpSize;
 
-       DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
-                                sizeof(mem));
-
-       if (mem.type > VIA_MEM_AGP) {
+       if (mem->type > VIA_MEM_AGP) {
                DRM_ERROR("Unknown memory type allocation\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        mutex_lock(&dev->struct_mutex);
-       if (0 == ((mem.type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
+       if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
                      dev_priv->agp_initialized)) {
                DRM_ERROR
                    ("Attempt to allocate from uninitialized memory manager.\n");
                mutex_unlock(&dev->struct_mutex);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       tmpSize = (mem.size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
-       item = drm_sman_alloc(&dev_priv->sman, mem.type, tmpSize, 0,
-                             (unsigned long)priv);
+       tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
+       item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0,
+                             (unsigned long)file_priv);
        mutex_unlock(&dev->struct_mutex);
        if (item) {
-               mem.offset = ((mem.type == VIA_MEM_VIDEO) ?
+               mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
                              dev_priv->vram_offset : dev_priv->agp_offset) +
                    (item->mm->
                     offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
-               mem.index = item->user_hash.key;
+               mem->index = item->user_hash.key;
        } else {
-               mem.offset = 0;
-               mem.size = 0;
-               mem.index = 0;
+               mem->offset = 0;
+               mem->size = 0;
+               mem->index = 0;
                DRM_DEBUG("Video memory allocation failed\n");
-               retval = DRM_ERR(ENOMEM);
+               retval = -ENOMEM;
        }
-       DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, sizeof(mem));
 
        return retval;
 }
 
-int via_mem_free(DRM_IOCTL_ARGS)
+int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_via_private_t *dev_priv = dev->dev_private;
-       drm_via_mem_t mem;
+       drm_via_mem_t *mem = data;
        int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
-                                sizeof(mem));
-
        mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_free_key(&dev_priv->sman, mem.index);
+       ret = drm_sman_free_key(&dev_priv->sman, mem->index);
        mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("free = 0x%lx\n", mem.index);
+       DRM_DEBUG("free = 0x%lx\n", mem->index);
 
        return ret;
 }
 
 
-void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
+void via_reclaim_buffers_locked(struct drm_device * dev,
+                               struct drm_file *file_priv)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
-       drm_file_t *priv = filp->private_data;
 
        mutex_lock(&dev->struct_mutex);
-       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
+       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
                mutex_unlock(&dev->struct_mutex);
                return;
        }
@@ -205,7 +190,7 @@ void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
                dev->driver->dma_quiescent(dev);
        }
 
-       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
+       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
        mutex_unlock(&dev->struct_mutex);
        return;
 }
diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c
new file mode 100644 (file)
index 0000000..d7b23c8
--- /dev/null
@@ -0,0 +1,326 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 "xgi_drv.h"
+#include "xgi_regs.h"
+#include "xgi_misc.h"
+#include "xgi_cmdlist.h"
+
+static void xgi_emit_flush(struct xgi_info * info, bool stop);
+static void xgi_emit_nop(struct xgi_info * info);
+static unsigned int get_batch_command(enum xgi_batch_type type);
+static void triggerHWCommandList(struct xgi_info * info);
+static void xgi_cmdlist_reset(struct xgi_info * info);
+
+
+/**
+ * Graphic engine register (2d/3d) acessing interface
+ */
+static inline void dwWriteReg(struct drm_map * map, u32 addr, u32 data)
+{
+#ifdef XGI_MMIO_DEBUG
+       DRM_INFO("mmio_map->handle = 0x%p, addr = 0x%x, data = 0x%x\n",
+                map->handle, addr, data);
+#endif
+       DRM_WRITE32(map, addr, data);
+}
+
+
+int xgi_cmdlist_initialize(struct xgi_info * info, size_t size,
+                          struct drm_file * filp)
+{
+       struct xgi_mem_alloc mem_alloc = {
+               .location = XGI_MEMLOC_NON_LOCAL,
+               .size = size,
+       };
+       int err;
+
+       err = xgi_alloc(info, &mem_alloc, filp);
+       if (err) {
+               return err;
+       }
+
+       info->cmdring.ptr = xgi_find_pcie_virt(info, mem_alloc.hw_addr);
+       info->cmdring.size = mem_alloc.size;
+       info->cmdring.ring_hw_base = mem_alloc.hw_addr;
+       info->cmdring.last_ptr = NULL;
+       info->cmdring.ring_offset = 0;
+
+       return 0;
+}
+
+
+/**
+ * get_batch_command - Get the command ID for the current begin type.
+ * @type: Type of the current batch
+ *
+ * See section 3.2.2 "Begin" (page 15) of the 3D SPG.
+ * 
+ * This function assumes that @type is on the range [0,3].
+ */
+unsigned int get_batch_command(enum xgi_batch_type type)
+{
+       static const unsigned int ports[4] = {
+               0x30 >> 2, 0x40 >> 2, 0x50 >> 2, 0x20 >> 2
+       };
+       
+       return ports[type];
+}
+
+
+int xgi_submit_cmdlist(struct drm_device * dev, void * data,
+                      struct drm_file * filp)
+{
+       struct xgi_info *const info = dev->dev_private;
+       const struct xgi_cmd_info *const pCmdInfo =
+               (struct xgi_cmd_info *) data;
+       const unsigned int cmd = get_batch_command(pCmdInfo->type);
+       u32 begin[4];
+
+
+       begin[0] = (cmd << 24) | BEGIN_VALID_MASK
+               | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence);
+       begin[1] = BEGIN_LINK_ENABLE_MASK | pCmdInfo->size;
+       begin[2] = pCmdInfo->hw_addr >> 4;
+       begin[3] = 0;
+
+       if (info->cmdring.last_ptr == NULL) {
+               const unsigned int portOffset = BASE_3D_ENG + (cmd << 2);
+
+
+               /* Enable PCI Trigger Mode
+                */
+               dwWriteReg(info->mmio_map,
+                          BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS,
+                          (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) |
+                          M2REG_CLEAR_COUNTERS_MASK | 0x08 |
+                          M2REG_PCI_TRIGGER_MODE_MASK);
+
+               dwWriteReg(info->mmio_map,
+                          BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS,
+                          (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | 0x08 |
+                          M2REG_PCI_TRIGGER_MODE_MASK);
+
+
+               /* Send PCI begin command
+                */
+               dwWriteReg(info->mmio_map, portOffset,      begin[0]);
+               dwWriteReg(info->mmio_map, portOffset +  4, begin[1]);
+               dwWriteReg(info->mmio_map, portOffset +  8, begin[2]);
+               dwWriteReg(info->mmio_map, portOffset + 12, begin[3]);
+       } else {
+               DRM_DEBUG("info->cmdring.last_ptr != NULL\n");
+
+               if (pCmdInfo->type == BTYPE_3D) {
+                       xgi_emit_flush(info, FALSE);
+               }
+
+               info->cmdring.last_ptr[1] = cpu_to_le32(begin[1]);
+               info->cmdring.last_ptr[2] = cpu_to_le32(begin[2]);
+               info->cmdring.last_ptr[3] = cpu_to_le32(begin[3]);
+               DRM_WRITEMEMORYBARRIER();
+               info->cmdring.last_ptr[0] = cpu_to_le32(begin[0]);
+
+               triggerHWCommandList(info);
+       }
+
+       info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr);
+       drm_fence_flush_old(info->dev, 0, info->next_sequence);
+       return 0;
+}
+
+
+/*
+    state:      0 - console
+                1 - graphic
+                2 - fb
+                3 - logout
+*/
+int xgi_state_change(struct xgi_info * info, unsigned int to, 
+                    unsigned int from)
+{
+#define STATE_CONSOLE   0
+#define STATE_GRAPHIC   1
+#define STATE_FBTERM    2
+#define STATE_LOGOUT    3
+#define STATE_REBOOT    4
+#define STATE_SHUTDOWN  5
+
+       if ((from == STATE_GRAPHIC) && (to == STATE_CONSOLE)) {
+               DRM_INFO("Leaving graphical mode (probably VT switch)\n");
+       } else if ((from == STATE_CONSOLE) && (to == STATE_GRAPHIC)) {
+               DRM_INFO("Entering graphical mode (probably VT switch)\n");
+               xgi_cmdlist_reset(info);
+       } else if ((from == STATE_GRAPHIC)
+                  && ((to == STATE_LOGOUT)
+                      || (to == STATE_REBOOT)
+                      || (to == STATE_SHUTDOWN))) {
+               DRM_INFO("Leaving graphical mode (probably X shutting down)\n");
+       } else {
+               DRM_ERROR("Invalid state change.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+int xgi_state_change_ioctl(struct drm_device * dev, void * data,
+                          struct drm_file * filp)
+{
+       struct xgi_state_info *const state =
+               (struct xgi_state_info *) data;
+       struct xgi_info *info = dev->dev_private;
+
+
+       return xgi_state_change(info, state->_toState, state->_fromState);
+}
+
+
+void xgi_cmdlist_reset(struct xgi_info * info)
+{
+       info->cmdring.last_ptr = NULL;
+       info->cmdring.ring_offset = 0;
+}
+
+
+void xgi_cmdlist_cleanup(struct xgi_info * info)
+{
+       if (info->cmdring.ring_hw_base != 0) {
+               /* If command lists have been issued, terminate the command
+                * list chain with a flush command.
+                */
+               if (info->cmdring.last_ptr != NULL) {
+                       xgi_emit_flush(info, FALSE);
+                       xgi_emit_nop(info);
+               }
+
+               xgi_waitfor_pci_idle(info);
+               
+               (void) memset(&info->cmdring, 0, sizeof(info->cmdring));
+       }
+}
+
+static void triggerHWCommandList(struct xgi_info * info)
+{
+       static unsigned int s_triggerID = 1;
+
+       dwWriteReg(info->mmio_map,
+                  BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS,
+                  0x05000000 + (0x0ffff & s_triggerID++));
+}
+
+
+/**
+ * Emit a flush to the CRTL command stream.
+ * @info XGI info structure
+ *
+ * This function assumes info->cmdring.ptr is non-NULL.
+ */
+void xgi_emit_flush(struct xgi_info * info, bool stop)
+{
+       const u32 flush_command[8] = {
+               ((0x10 << 24) 
+                | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence)),
+               BEGIN_LINK_ENABLE_MASK | (0x00004),
+               0x00000000, 0x00000000,
+
+               /* Flush the 2D engine with the default 32 clock delay.
+                */
+               M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK,
+               M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK,
+               M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK,
+               M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK,
+       };
+       const unsigned int flush_size = sizeof(flush_command);
+       u32 *batch_addr;
+       u32 hw_addr;
+       unsigned int i;
+
+
+       /* check buf is large enough to contain a new flush batch */
+       if ((info->cmdring.ring_offset + flush_size) >= info->cmdring.size) {
+               info->cmdring.ring_offset = 0;
+       }
+
+       hw_addr = info->cmdring.ring_hw_base 
+               + info->cmdring.ring_offset;
+       batch_addr = info->cmdring.ptr 
+               + (info->cmdring.ring_offset / 4);
+
+       for (i = 0; i < (flush_size / 4); i++) {
+               batch_addr[i] = cpu_to_le32(flush_command[i]);
+       }
+
+       if (stop) {
+               *batch_addr |= cpu_to_le32(BEGIN_STOP_STORE_CURRENT_POINTER_MASK);
+       }
+
+       info->cmdring.last_ptr[1] = cpu_to_le32(BEGIN_LINK_ENABLE_MASK | (flush_size / 4));
+       info->cmdring.last_ptr[2] = cpu_to_le32(hw_addr >> 4);
+       info->cmdring.last_ptr[3] = 0;
+       DRM_WRITEMEMORYBARRIER();
+       info->cmdring.last_ptr[0] = cpu_to_le32((get_batch_command(BTYPE_CTRL) << 24)
+               | (BEGIN_VALID_MASK));
+
+       triggerHWCommandList(info);
+
+       info->cmdring.ring_offset += flush_size;
+       info->cmdring.last_ptr = batch_addr;
+}
+
+
+/**
+ * Emit an empty command to the CRTL command stream.
+ * @info XGI info structure
+ *
+ * This function assumes info->cmdring.ptr is non-NULL.  In addition, since
+ * this function emits a command that does not have linkage information,
+ * it sets info->cmdring.ptr to NULL.
+ */
+void xgi_emit_nop(struct xgi_info * info)
+{
+       info->cmdring.last_ptr[1] = cpu_to_le32(BEGIN_LINK_ENABLE_MASK
+               | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence));
+       info->cmdring.last_ptr[2] = 0;
+       info->cmdring.last_ptr[3] = 0;
+       DRM_WRITEMEMORYBARRIER();
+       info->cmdring.last_ptr[0] = cpu_to_le32((get_batch_command(BTYPE_CTRL) << 24)
+               | (BEGIN_VALID_MASK));
+
+       triggerHWCommandList(info);
+
+       info->cmdring.last_ptr = NULL;
+}
+
+
+void xgi_emit_irq(struct xgi_info * info)
+{
+       if (info->cmdring.last_ptr == NULL)
+               return;
+
+       xgi_emit_flush(info, TRUE);
+}
diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h
new file mode 100644 (file)
index 0000000..f6f1c1e
--- /dev/null
@@ -0,0 +1,66 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 _XGI_CMDLIST_H_
+#define _XGI_CMDLIST_H_
+
+struct xgi_cmdring_info {
+       /**
+        * Kernel space pointer to the base of the command ring.
+        */
+       u32 * ptr;
+
+       /**
+        * Size, in bytes, of the command ring.
+        */
+       unsigned int size;
+
+       /**
+        * Base address of the command ring from the hardware's PoV.
+        */
+       unsigned int ring_hw_base;
+
+       u32 * last_ptr;
+
+       /**
+        * Offset, in bytes, from the start of the ring to the next available
+        * location to store a command.
+        */
+       unsigned int ring_offset;
+};
+
+struct xgi_info;
+extern int xgi_cmdlist_initialize(struct xgi_info * info, size_t size,
+       struct drm_file * filp);
+
+extern int xgi_state_change(struct xgi_info * info, unsigned int to,
+       unsigned int from);
+
+extern void xgi_cmdlist_cleanup(struct xgi_info * info);
+
+extern void xgi_emit_irq(struct xgi_info * info);
+
+#endif                         /* _XGI_CMDLIST_H_ */
diff --git a/linux-core/xgi_drm.h b/linux-core/xgi_drm.h
new file mode 120000 (symlink)
index 0000000..677586d
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/xgi_drm.h
\ No newline at end of file
diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c
new file mode 100644 (file)
index 0000000..4e66197
--- /dev/null
@@ -0,0 +1,431 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 "drmP.h"
+#include "drm.h"
+#include "xgi_drv.h"
+#include "xgi_regs.h"
+#include "xgi_misc.h"
+#include "xgi_cmdlist.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       xgi_PCI_IDS
+};
+
+static struct drm_fence_driver xgi_fence_driver = {
+       .num_classes = 1,
+       .wrap_diff = BEGIN_BEGIN_IDENTIFICATION_MASK,
+       .flush_diff = BEGIN_BEGIN_IDENTIFICATION_MASK - 1,
+       .sequence_mask = BEGIN_BEGIN_IDENTIFICATION_MASK,
+       .lazy_capable = 1,
+       .emit = xgi_fence_emit_sequence,
+       .poke_flush = xgi_poke_flush,
+       .has_irq = xgi_fence_has_irq
+};
+
+int xgi_bootstrap(struct drm_device *, void *, struct drm_file *);
+
+static struct drm_ioctl_desc xgi_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_XGI_BOOTSTRAP, xgi_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_XGI_ALLOC, xgi_alloc_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_XGI_FREE, xgi_free_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_XGI_SUBMIT_CMDLIST, xgi_submit_cmdlist, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_XGI_STATE_CHANGE, xgi_state_change_ioctl, DRM_AUTH|DRM_MASTER),
+};
+
+static const int xgi_max_ioctl = DRM_ARRAY_SIZE(xgi_ioctls);
+
+static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int xgi_driver_load(struct drm_device *dev, unsigned long flags);
+static int xgi_driver_unload(struct drm_device *dev);
+static void xgi_driver_lastclose(struct drm_device * dev);
+static void xgi_reclaim_buffers_locked(struct drm_device * dev,
+       struct drm_file * filp);
+static irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS);
+
+
+static struct drm_driver driver = {
+       .driver_features =
+               DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ |
+               DRIVER_IRQ_SHARED | DRIVER_SG,
+       .dev_priv_size = sizeof(struct xgi_info),
+       .load = xgi_driver_load,
+       .unload = xgi_driver_unload,
+       .lastclose = xgi_driver_lastclose,
+       .dma_quiescent = NULL,
+       .irq_preinstall = NULL,
+       .irq_postinstall = NULL,
+       .irq_uninstall = NULL,
+       .irq_handler = xgi_kern_isr,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .reclaim_buffers_idlelocked = xgi_reclaim_buffers_locked,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = xgi_ioctls,
+       .dma_ioctl = NULL,
+
+       .fops = {
+               .owner = THIS_MODULE,
+               .open = drm_open,
+               .release = drm_release,
+               .ioctl = drm_ioctl,
+               .mmap = drm_mmap,
+               .poll = drm_poll,
+               .fasync = drm_fasync,
+#if defined(CONFIG_COMPAT) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
+               .compat_ioctl = xgi_compat_ioctl,
+#endif
+       },
+
+       .pci_driver = {
+               .name = DRIVER_NAME,
+               .id_table = pciidlist,
+               .probe = probe,
+               .remove = __devexit_p(drm_cleanup_pci),
+       },
+
+       .fence_driver = &xgi_fence_driver,
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+
+};
+
+static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       return drm_get_dev(pdev, ent, &driver);
+}
+
+
+static int __init xgi_init(void)
+{
+       driver.num_ioctls = xgi_max_ioctl;
+       return drm_init(&driver, pciidlist);
+}
+
+static void __exit xgi_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(xgi_init);
+module_exit(xgi_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
+
+
+void xgi_engine_init(struct xgi_info * info)
+{
+       u8 temp;
+
+
+       OUT3C5B(info->mmio_map, 0x11, 0x92);
+
+       /* -------> copy from OT2D
+        * PCI Retry Control Register.
+        * disable PCI read retry & enable write retry in mem. (10xx xxxx)b
+        */
+       temp = IN3X5B(info->mmio_map, 0x55);
+       OUT3X5B(info->mmio_map, 0x55, (temp & 0xbf) | 0x80);
+
+       xgi_enable_ge(info);
+
+       /* Enable linear addressing of the card. */
+       temp = IN3X5B(info->mmio_map, 0x21);
+       OUT3X5B(info->mmio_map, 0x21, temp | 0x20);
+
+       /* Enable 32-bit internal data path */
+       temp = IN3X5B(info->mmio_map, 0x2A);
+       OUT3X5B(info->mmio_map, 0x2A, temp | 0x40);
+
+       /* Enable PCI burst write ,disable burst read and enable MMIO. */
+       /*
+        * 0x3D4.39 Enable PCI burst write, disable burst read and enable MMIO.
+        * 7 ---- Pixel Data Format 1:  big endian 0:  little endian
+        * 6 5 4 3---- Memory Data with Big Endian Format, BE[3:0]#  with Big Endian Format
+        * 2 ---- PCI Burst Write Enable
+        * 1 ---- PCI Burst Read Enable
+        * 0 ---- MMIO Control
+        */
+       temp = IN3X5B(info->mmio_map, 0x39);
+       OUT3X5B(info->mmio_map, 0x39, (temp | 0x05) & 0xfd);
+
+       /* enable GEIO decode */
+       /* temp = IN3X5B(info->mmio_map, 0x29);
+        * OUT3X5B(info->mmio_map, 0x29, temp | 0x08);
+        */
+
+       /* Enable graphic engine I/O PCI retry function*/
+       /* temp = IN3X5B(info->mmio_map, 0x62);
+        * OUT3X5B(info->mmio_map, 0x62, temp | 0x50);
+        */
+
+       /* protect all register except which protected by 3c5.0e.7 */
+        /* OUT3C5B(info->mmio_map, 0x11, 0x87); */
+}
+
+
+int xgi_bootstrap(struct drm_device * dev, void * data,
+                 struct drm_file * filp)
+{
+       struct xgi_info *info = dev->dev_private;
+       struct xgi_bootstrap * bs = (struct xgi_bootstrap *) data;
+       struct drm_map_list *maplist;
+       int err;
+
+
+       DRM_SPININIT(&info->fence_lock, "fence lock");
+       info->next_sequence = 0;
+       info->complete_sequence = 0;
+
+       if (info->mmio_map == NULL) {
+               err = drm_addmap(dev, info->mmio.base, info->mmio.size,
+                                _DRM_REGISTERS, _DRM_KERNEL,
+                                &info->mmio_map);
+               if (err) {
+                       DRM_ERROR("Unable to map MMIO region: %d\n", err);
+                       return err;
+               }
+
+               xgi_enable_mmio(info);
+               xgi_engine_init(info);
+       }
+
+
+       info->fb.size = IN3CFB(info->mmio_map, 0x54) * 8 * 1024 * 1024;
+
+       DRM_INFO("fb   base: 0x%lx, size: 0x%x (probed)\n",
+                (unsigned long) info->fb.base, info->fb.size);
+
+
+       if ((info->fb.base == 0) || (info->fb.size == 0)) {
+               DRM_ERROR("framebuffer appears to be wrong: 0x%lx 0x%x\n",
+                         (unsigned long) info->fb.base, info->fb.size);
+               return -EINVAL;
+       }
+
+
+       /* Init the resource manager */
+       if (!info->fb_heap_initialized) {
+               err = xgi_fb_heap_init(info);
+               if (err) {
+                       DRM_ERROR("Unable to initialize FB heap.\n");
+                       return err;
+               }
+       }
+
+
+       info->pcie.size = bs->gart.size;
+
+       /* Init the resource manager */
+       if (!info->pcie_heap_initialized) {
+               err = xgi_pcie_heap_init(info);
+               if (err) {
+                       DRM_ERROR("Unable to initialize GART heap.\n");
+                       return err;
+               }
+
+               /* Alloc 1M bytes for cmdbuffer which is flush2D batch array */
+               err = xgi_cmdlist_initialize(info, 0x100000, filp);
+               if (err) {
+                       DRM_ERROR("xgi_cmdlist_initialize() failed\n");
+                       return err;
+               }
+       }
+
+
+       if (info->pcie_map == NULL) {
+               err = drm_addmap(info->dev, 0, info->pcie.size,
+                                _DRM_SCATTER_GATHER, _DRM_LOCKED,
+                                & info->pcie_map);
+               if (err) {
+                       DRM_ERROR("Could not add map for GART backing "
+                                 "store.\n");
+                       return err;
+               }
+       }
+
+
+       maplist = drm_find_matching_map(dev, info->pcie_map);
+       if (maplist == NULL) {
+               DRM_ERROR("Could not find GART backing store map.\n");
+               return -EINVAL;
+       }
+
+       bs->gart = *info->pcie_map;
+       bs->gart.handle = (void *)(unsigned long) maplist->user_token;
+       return 0;
+}
+
+
+void xgi_driver_lastclose(struct drm_device * dev)
+{
+       struct xgi_info * info = dev->dev_private;
+
+       if (info != NULL) {
+               if (info->mmio_map != NULL) {
+                       xgi_cmdlist_cleanup(info);
+                       xgi_disable_ge(info);
+                       xgi_disable_mmio(info);
+               }
+
+               /* The core DRM lastclose routine will destroy all of our
+                * mappings for us.  NULL out the pointers here so that
+                * xgi_bootstrap can do the right thing.
+                */
+               info->pcie_map = NULL;
+               info->mmio_map = NULL;
+               info->fb_map = NULL;
+
+               if (info->pcie_heap_initialized) {
+                       drm_ati_pcigart_cleanup(dev, &info->gart_info);
+               }
+
+               if (info->fb_heap_initialized
+                   || info->pcie_heap_initialized) {
+                       drm_sman_cleanup(&info->sman);
+
+                       info->fb_heap_initialized = FALSE;
+                       info->pcie_heap_initialized = FALSE;
+               }
+       }
+}
+
+
+void xgi_reclaim_buffers_locked(struct drm_device * dev,
+                               struct drm_file * filp)
+{
+       struct xgi_info * info = dev->dev_private;
+
+       mutex_lock(&info->dev->struct_mutex);
+       if (drm_sman_owner_clean(&info->sman, (unsigned long) filp)) {
+               mutex_unlock(&info->dev->struct_mutex);
+               return;
+       }
+
+       if (dev->driver->dma_quiescent) {
+               dev->driver->dma_quiescent(dev);
+       }
+
+       drm_sman_owner_cleanup(&info->sman, (unsigned long) filp);
+       mutex_unlock(&info->dev->struct_mutex);
+       return;
+}
+
+
+/*
+ * driver receives an interrupt if someone waiting, then hand it off.
+ */
+irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       struct xgi_info *info = dev->dev_private;
+       const u32 irq_bits = le32_to_cpu(DRM_READ32(info->mmio_map,
+                                       (0x2800 
+                                        + M2REG_AUTO_LINK_STATUS_ADDRESS)))
+               & (M2REG_ACTIVE_TIMER_INTERRUPT_MASK
+                  | M2REG_ACTIVE_INTERRUPT_0_MASK
+                  | M2REG_ACTIVE_INTERRUPT_2_MASK
+                  | M2REG_ACTIVE_INTERRUPT_3_MASK);
+
+
+       if (irq_bits != 0) {
+               DRM_WRITE32(info->mmio_map, 
+                           0x2800 + M2REG_AUTO_LINK_SETTING_ADDRESS,
+                           cpu_to_le32(M2REG_AUTO_LINK_SETTING_COMMAND | irq_bits));
+               xgi_fence_handler(dev);
+               return IRQ_HANDLED;
+       } else {
+               return IRQ_NONE;
+       }
+}
+
+
+int xgi_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       struct xgi_info *info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER);
+       int err;
+
+       if (!info)
+               return -ENOMEM;
+
+       (void) memset(info, 0, sizeof(*info));
+       dev->dev_private = info;
+       info->dev = dev;
+
+       info->mmio.base = drm_get_resource_start(dev, 1);
+       info->mmio.size = drm_get_resource_len(dev, 1);
+
+       DRM_INFO("mmio base: 0x%lx, size: 0x%x\n",
+                (unsigned long) info->mmio.base, info->mmio.size);
+
+
+       if ((info->mmio.base == 0) || (info->mmio.size == 0)) {
+               DRM_ERROR("mmio appears to be wrong: 0x%lx 0x%x\n",
+                         (unsigned long) info->mmio.base, info->mmio.size);
+               err = -EINVAL;
+               goto fail;
+       }
+
+
+       info->fb.base = drm_get_resource_start(dev, 0);
+       info->fb.size = drm_get_resource_len(dev, 0);
+
+       DRM_INFO("fb   base: 0x%lx, size: 0x%x\n",
+                (unsigned long) info->fb.base, info->fb.size);
+
+
+       err = drm_sman_init(&info->sman, 2, 12, 8);
+       if (err) {
+               goto fail;
+       }
+
+
+       return 0;
+       
+fail:
+       drm_free(info, sizeof(*info), DRM_MEM_DRIVER);
+       return err;
+}
+
+int xgi_driver_unload(struct drm_device *dev)
+{
+       struct xgi_info * info = dev->dev_private;
+
+       drm_sman_takedown(&info->sman);
+       drm_free(info, sizeof(*info), DRM_MEM_DRIVER);
+       dev->dev_private = NULL;
+
+       return 0;
+}
diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h
new file mode 100644 (file)
index 0000000..d9a94f5
--- /dev/null
@@ -0,0 +1,117 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 _XGI_DRV_H_
+#define _XGI_DRV_H_
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sman.h"
+
+#define DRIVER_AUTHOR          "Andrea Zhang <andrea_zhang@macrosynergy.com>"
+
+#define DRIVER_NAME            "xgi"
+#define DRIVER_DESC            "XGI XP5 / XP10 / XG47"
+#define DRIVER_DATE            "20071003"
+
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           1
+#define DRIVER_PATCHLEVEL      3
+
+#include "xgi_cmdlist.h"
+#include "xgi_drm.h"
+
+struct xgi_aperture {
+       dma_addr_t base;
+       unsigned int size;
+};
+
+struct xgi_info {
+       struct drm_device *dev;
+
+       bool bootstrap_done;
+
+       /* physical characteristics */
+       struct xgi_aperture mmio;
+       struct xgi_aperture fb;
+       struct xgi_aperture pcie;
+
+       struct drm_map *mmio_map;
+       struct drm_map *pcie_map;
+       struct drm_map *fb_map;
+
+       /* look up table parameters */
+       struct ati_pcigart_info gart_info;
+       unsigned int lutPageSize;
+
+       struct drm_sman sman;
+       bool fb_heap_initialized;
+       bool pcie_heap_initialized;
+
+       struct xgi_cmdring_info cmdring;
+
+       DRM_SPINTYPE fence_lock;
+       unsigned complete_sequence;
+       unsigned next_sequence;
+};
+
+extern long xgi_compat_ioctl(struct file *filp, unsigned int cmd,
+       unsigned long arg);
+
+extern int xgi_fb_heap_init(struct xgi_info * info);
+
+extern int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,
+       struct drm_file * filp);
+
+extern int xgi_free(struct xgi_info * info, unsigned long index,
+       struct drm_file * filp);
+
+extern int xgi_pcie_heap_init(struct xgi_info * info);
+
+extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address);
+
+extern void xgi_enable_mmio(struct xgi_info * info);
+extern void xgi_disable_mmio(struct xgi_info * info);
+extern void xgi_enable_ge(struct xgi_info * info);
+extern void xgi_disable_ge(struct xgi_info * info);
+
+extern void xgi_poke_flush(struct drm_device * dev, uint32_t class);
+extern int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class,
+       uint32_t flags, uint32_t * sequence, uint32_t * native_type);
+extern void xgi_fence_handler(struct drm_device * dev);
+extern int xgi_fence_has_irq(struct drm_device *dev, uint32_t class,
+       uint32_t flags);
+
+extern int xgi_alloc_ioctl(struct drm_device * dev, void * data,
+       struct drm_file * filp);
+extern int xgi_free_ioctl(struct drm_device * dev, void * data,
+       struct drm_file * filp);
+extern int xgi_submit_cmdlist(struct drm_device * dev, void * data,
+       struct drm_file * filp);
+extern int xgi_state_change_ioctl(struct drm_device * dev, void * data,
+       struct drm_file * filp);
+
+#endif
diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c
new file mode 100644 (file)
index 0000000..2e2d009
--- /dev/null
@@ -0,0 +1,130 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 "xgi_drv.h"
+
+#define XGI_FB_HEAP_START 0x1000000
+
+int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,
+             struct drm_file * filp)
+{
+       struct drm_memblock_item *block;
+       const char *const mem_name = (alloc->location == XGI_MEMLOC_LOCAL) 
+               ? "on-card" : "GART";
+
+
+       if ((alloc->location != XGI_MEMLOC_LOCAL)
+           && (alloc->location != XGI_MEMLOC_NON_LOCAL)) {
+               DRM_ERROR("Invalid memory pool (0x%08x) specified.\n",
+                         alloc->location);
+               return -EINVAL;
+       }
+
+       if ((alloc->location == XGI_MEMLOC_LOCAL) 
+           ? !info->fb_heap_initialized : !info->pcie_heap_initialized) {
+               DRM_ERROR("Attempt to allocate from uninitialized memory "
+                         "pool (0x%08x).\n", alloc->location);
+               return -EINVAL;
+       }
+
+       mutex_lock(&info->dev->struct_mutex);
+       block = drm_sman_alloc(&info->sman, alloc->location, alloc->size,
+                              0, (unsigned long) filp);
+       mutex_unlock(&info->dev->struct_mutex);
+
+       if (block == NULL) {
+               alloc->size = 0;
+               DRM_ERROR("%s memory allocation failed\n", mem_name);
+               return -ENOMEM;
+       } else {
+               alloc->offset = (*block->mm->offset)(block->mm,
+                                                    block->mm_info);
+               alloc->hw_addr = alloc->offset;
+               alloc->index = block->user_hash.key;
+
+               if (block->user_hash.key != (unsigned long) alloc->index) {
+                       DRM_ERROR("%s truncated handle %lx for pool %d "
+                                 "offset %x\n",
+                                 __func__, block->user_hash.key,
+                                 alloc->location, alloc->offset);
+               }
+
+               if (alloc->location == XGI_MEMLOC_NON_LOCAL) {
+                       alloc->hw_addr += info->pcie.base;
+               }
+
+               DRM_DEBUG("%s memory allocation succeeded: 0x%x\n",
+                         mem_name, alloc->offset);
+       }
+
+       return 0;
+}
+
+
+int xgi_alloc_ioctl(struct drm_device * dev, void * data,
+                   struct drm_file * filp)
+{
+       struct xgi_info *info = dev->dev_private;
+
+       return xgi_alloc(info, (struct xgi_mem_alloc *) data, filp);
+}
+
+
+int xgi_free(struct xgi_info * info, unsigned long index,
+            struct drm_file * filp)
+{
+       int err;
+
+       mutex_lock(&info->dev->struct_mutex);
+       err = drm_sman_free_key(&info->sman, index);
+       mutex_unlock(&info->dev->struct_mutex);
+
+       return err;
+}
+
+
+int xgi_free_ioctl(struct drm_device * dev, void * data,
+                  struct drm_file * filp)
+{
+       struct xgi_info *info = dev->dev_private;
+
+       return xgi_free(info, *(unsigned long *) data, filp);
+}
+
+
+int xgi_fb_heap_init(struct xgi_info * info)
+{
+       int err;
+       
+       mutex_lock(&info->dev->struct_mutex);
+       err = drm_sman_set_range(&info->sman, XGI_MEMLOC_LOCAL,
+                                XGI_FB_HEAP_START,
+                                info->fb.size - XGI_FB_HEAP_START);
+       mutex_unlock(&info->dev->struct_mutex);
+
+       info->fb_heap_initialized = (err == 0);
+       return err;
+}
diff --git a/linux-core/xgi_fence.c b/linux-core/xgi_fence.c
new file mode 100644 (file)
index 0000000..526bc5d
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright IBM Corporation 2007
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS AND/OR THEIR 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:
+ *    Ian Romanick <idr@us.ibm.com>
+ */
+
+#include "xgi_drv.h"
+#include "xgi_regs.h"
+#include "xgi_misc.h"
+#include "xgi_cmdlist.h"
+
+static uint32_t xgi_do_flush(struct drm_device * dev, uint32_t class)
+{
+       struct xgi_info * info = dev->dev_private;
+       struct drm_fence_class_manager * fc = &dev->fm.fence_class[class];
+       uint32_t pending_flush_types = 0;
+       uint32_t signaled_flush_types = 0;
+
+
+       if ((info == NULL) || (class != 0))
+               return 0;
+
+       DRM_SPINLOCK(&info->fence_lock);
+
+       pending_flush_types = fc->pending_flush |
+               ((fc->pending_exe_flush) ? DRM_FENCE_TYPE_EXE : 0);
+
+       if (pending_flush_types) {
+               if (pending_flush_types & DRM_FENCE_TYPE_EXE) {
+                       const u32 begin_id = le32_to_cpu(DRM_READ32(info->mmio_map,
+                                                       0x2820))
+                               & BEGIN_BEGIN_IDENTIFICATION_MASK;
+
+                       if (begin_id != info->complete_sequence) {
+                               info->complete_sequence = begin_id;
+                               signaled_flush_types |= DRM_FENCE_TYPE_EXE;
+                       }
+               }
+
+               if (signaled_flush_types) {
+                       drm_fence_handler(dev, 0, info->complete_sequence,
+                                         signaled_flush_types, 0);
+               }
+       }
+
+       DRM_SPINUNLOCK(&info->fence_lock);
+
+       return fc->pending_flush |
+               ((fc->pending_exe_flush) ? DRM_FENCE_TYPE_EXE : 0);
+}
+
+
+int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class,
+                           uint32_t flags, uint32_t * sequence, 
+                           uint32_t * native_type)
+{
+       struct xgi_info * info = dev->dev_private;
+
+       if ((info == NULL) || (class != 0))
+               return -EINVAL;
+
+
+       DRM_SPINLOCK(&info->fence_lock);
+       info->next_sequence++;
+       if (info->next_sequence > BEGIN_BEGIN_IDENTIFICATION_MASK) {
+               info->next_sequence = 1;
+       }
+       DRM_SPINUNLOCK(&info->fence_lock);
+
+
+       xgi_emit_irq(info);
+
+       *sequence = (uint32_t) info->next_sequence;
+       *native_type = DRM_FENCE_TYPE_EXE;
+
+       return 0;
+}
+
+
+void xgi_poke_flush(struct drm_device * dev, uint32_t class)
+{
+       struct drm_fence_manager * fm = &dev->fm;
+       unsigned long flags;
+
+
+       write_lock_irqsave(&fm->lock, flags);
+       xgi_do_flush(dev, class);
+       write_unlock_irqrestore(&fm->lock, flags);
+}
+
+
+void xgi_fence_handler(struct drm_device * dev)
+{
+       struct drm_fence_manager * fm = &dev->fm;
+
+
+       write_lock(&fm->lock);
+       xgi_do_flush(dev, 0);
+       write_unlock(&fm->lock);
+}
+
+
+int xgi_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags)
+{
+       return ((class == 0) && (flags == DRM_FENCE_TYPE_EXE)) ? 1 : 0;
+}
diff --git a/linux-core/xgi_ioc32.c b/linux-core/xgi_ioc32.c
new file mode 100644 (file)
index 0000000..c54044f
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright IBM Corporation 2007
+ * Copyright (C) Paul Mackerras 2005.
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS AND/OR THEIR 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:
+ *    Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <linux/compat.h>
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "xgi_drm.h"
+
+/* This is copied from drm_ioc32.c.
+ */
+struct drm_map32 {
+       u32 offset;             /**< Requested physical address (0 for SAREA)*/
+       u32 size;               /**< Requested physical size (bytes) */
+       enum drm_map_type type; /**< Type of memory to map */
+       enum drm_map_flags flags;       /**< Flags */
+       u32 handle;             /**< User-space: "Handle" to pass to mmap() */
+       int mtrr;               /**< MTRR slot used */
+};
+       
+struct drm32_xgi_bootstrap {
+       struct drm_map32 gart;
+};
+
+
+extern int xgi_bootstrap(struct drm_device *, void *, struct drm_file *);
+
+static int compat_xgi_bootstrap(struct file *filp, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct drm32_xgi_bootstrap __user *const argp = (void __user *)arg;
+       struct drm32_xgi_bootstrap bs32;
+       struct xgi_bootstrap __user *bs;
+       int err;
+       void *handle;
+
+
+       if (copy_from_user(&bs32, argp, sizeof(bs32))) {
+               return -EFAULT;
+       }
+
+       bs = compat_alloc_user_space(sizeof(*bs));
+       if (!access_ok(VERIFY_WRITE, bs, sizeof(*bs))) {
+               return -EFAULT;
+       }
+
+       if (__put_user(bs32.gart.offset, &bs->gart.offset)
+           || __put_user(bs32.gart.size, &bs->gart.size)
+           || __put_user(bs32.gart.type, &bs->gart.type)
+           || __put_user(bs32.gart.flags, &bs->gart.flags)) {
+               return -EFAULT;
+       }
+
+       err = drm_ioctl(filp->f_dentry->d_inode, filp, XGI_IOCTL_BOOTSTRAP,
+                       (unsigned long)bs);
+       if (err) {
+               return err;
+       }
+
+       if (__get_user(bs32.gart.offset, &bs->gart.offset)
+           || __get_user(bs32.gart.mtrr, &bs->gart.mtrr)
+           || __get_user(handle, &bs->gart.handle)) {
+               return -EFAULT;
+       }
+
+       bs32.gart.handle = (unsigned long)handle;
+       if (bs32.gart.handle != (unsigned long)handle && printk_ratelimit()) {
+               printk(KERN_ERR "%s truncated handle %p for type %d "
+                      "offset %x\n",
+                      __func__, handle, bs32.gart.type, bs32.gart.offset);
+       }
+
+       if (copy_to_user(argp, &bs32, sizeof(bs32))) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+
+drm_ioctl_compat_t *xgi_compat_ioctls[] = {
+       [DRM_XGI_BOOTSTRAP] = compat_xgi_bootstrap,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long xgi_compat_ioctl(struct file *filp, unsigned int cmd,
+                     unsigned long arg)
+{
+       const unsigned int nr = DRM_IOCTL_NR(cmd);
+       drm_ioctl_compat_t *fn = NULL;
+       int ret;
+
+       if (nr < DRM_COMMAND_BASE)
+               return drm_compat_ioctl(filp, cmd, arg);
+
+       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(xgi_compat_ioctls))
+               fn = xgi_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+       lock_kernel();
+       ret = (fn != NULL)
+               ? (*fn)(filp, cmd, arg)
+               : drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c
new file mode 100644 (file)
index 0000000..4a4a984
--- /dev/null
@@ -0,0 +1,477 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 "xgi_drv.h"
+#include "xgi_regs.h"
+
+#include <linux/delay.h>
+
+/*
+ * irq functions
+ */
+#define STALL_INTERRUPT_RESET_THRESHOLD 0xffff
+
+static unsigned int s_invalid_begin = 0;
+
+static bool xgi_validate_signal(struct drm_map * map)
+{
+       if (le32_to_cpu(DRM_READ32(map, 0x2800) & 0x001c0000)) {
+               u16 check;
+
+               /* Check Read back status */
+               DRM_WRITE8(map, 0x235c, 0x80);
+               check = le16_to_cpu(DRM_READ16(map, 0x2360));
+
+               if ((check & 0x3f) != ((check & 0x3f00) >> 8)) {
+                       return FALSE;
+               }
+
+               /* Check RO channel */
+               DRM_WRITE8(map, 0x235c, 0x83);
+               check = le16_to_cpu(DRM_READ16(map, 0x2360));
+               if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
+                       return FALSE;
+               }
+
+               /* Check RW channel */
+               DRM_WRITE8(map, 0x235c, 0x88);
+               check = le16_to_cpu(DRM_READ16(map, 0x2360));
+               if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
+                       return FALSE;
+               }
+
+               /* Check RO channel outstanding */
+               DRM_WRITE8(map, 0x235c, 0x8f);
+               check = le16_to_cpu(DRM_READ16(map, 0x2360));
+               if (0 != (check & 0x3ff)) {
+                       return FALSE;
+               }
+
+               /* Check RW channel outstanding */
+               DRM_WRITE8(map, 0x235c, 0x90);
+               check = le16_to_cpu(DRM_READ16(map, 0x2360));
+               if (0 != (check & 0x3ff)) {
+                       return FALSE;
+               }
+
+               /* No pending PCIE request. GE stall. */
+       }
+
+       return TRUE;
+}
+
+
+static void xgi_ge_hang_reset(struct drm_map * map)
+{
+       int time_out = 0xffff;
+
+       DRM_WRITE8(map, 0xb057, 8);
+       while (0 != le32_to_cpu(DRM_READ32(map, 0x2800) & 0xf0000000)) {
+               while (0 != ((--time_out) & 0xfff)) 
+                       /* empty */ ;
+
+               if (0 == time_out) {
+                       u8 old_3ce;
+                       u8 old_3cf;
+                       u8 old_index;
+                       u8 old_36;
+
+                       DRM_INFO("Can not reset back 0x%x!\n",
+                                le32_to_cpu(DRM_READ32(map, 0x2800)));
+
+                       DRM_WRITE8(map, 0xb057, 0);
+
+                       /* Have to use 3x5.36 to reset. */
+                       /* Save and close dynamic gating */
+
+                       old_3ce = DRM_READ8(map, 0x3ce);
+                       DRM_WRITE8(map, 0x3ce, 0x2a);
+                       old_3cf = DRM_READ8(map, 0x3cf);
+                       DRM_WRITE8(map, 0x3cf, old_3cf & 0xfe);
+
+                       /* Reset GE */
+                       old_index = DRM_READ8(map, 0x3d4);
+                       DRM_WRITE8(map, 0x3d4, 0x36);
+                       old_36 = DRM_READ8(map, 0x3d5);
+                       DRM_WRITE8(map, 0x3d5, old_36 | 0x10);
+                       
+                       while (0 != ((--time_out) & 0xfff)) 
+                               /* empty */ ;
+
+                       DRM_WRITE8(map, 0x3d5, old_36);
+                       DRM_WRITE8(map, 0x3d4, old_index);
+
+                       /* Restore dynamic gating */
+                       DRM_WRITE8(map, 0x3cf, old_3cf);
+                       DRM_WRITE8(map, 0x3ce, old_3ce);
+                       break;
+               }
+       }
+
+       DRM_WRITE8(map, 0xb057, 0);
+}
+
+       
+bool xgi_ge_irq_handler(struct xgi_info * info)
+{
+       const u32 int_status = le32_to_cpu(DRM_READ32(info->mmio_map, 0x2810));
+       bool is_support_auto_reset = FALSE;
+
+       /* Check GE on/off */
+       if (0 == (0xffffc0f0 & int_status)) {
+               if (0 != (0x1000 & int_status)) {
+                       /* We got GE stall interrupt. 
+                        */
+                       DRM_WRITE32(info->mmio_map, 0x2810,
+                                   cpu_to_le32(int_status | 0x04000000));
+
+                       if (is_support_auto_reset) {
+                               static cycles_t last_tick;
+                               static unsigned continue_int_count = 0;
+
+                               /* OE II is busy. */
+
+                               if (!xgi_validate_signal(info->mmio_map)) {
+                                       /* Nothing but skip. */
+                               } else if (0 == continue_int_count++) {
+                                       last_tick = get_cycles();
+                               } else {
+                                       const cycles_t new_tick = get_cycles();
+                                       if ((new_tick - last_tick) >
+                                           STALL_INTERRUPT_RESET_THRESHOLD) {
+                                               continue_int_count = 0;
+                                       } else if (continue_int_count >= 3) {
+                                               continue_int_count = 0;
+
+                                               /* GE Hung up, need reset. */
+                                               DRM_INFO("Reset GE!\n");
+
+                                               xgi_ge_hang_reset(info->mmio_map);
+                                       }
+                               }
+                       }
+               } else if (0 != (0x1 & int_status)) {
+                       s_invalid_begin++;
+                       DRM_WRITE32(info->mmio_map, 0x2810,
+                                   cpu_to_le32((int_status & ~0x01) | 0x04000000));
+               }
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+bool xgi_crt_irq_handler(struct xgi_info * info)
+{
+       bool ret = FALSE;
+       u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
+
+       /* CRT1 interrupt just happened
+        */
+       if (IN3CFB(info->mmio_map, 0x37) & 0x01) {
+               u8 op3cf_3d;
+               u8 op3cf_37;
+
+               /* What happened?
+                */
+               op3cf_37 = IN3CFB(info->mmio_map, 0x37);
+
+               /* Clear CRT interrupt
+                */
+               op3cf_3d = IN3CFB(info->mmio_map, 0x3d);
+               OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d | 0x04));
+               OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d & ~0x04));
+               ret = TRUE;
+       }
+       DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
+
+       return (ret);
+}
+
+bool xgi_dvi_irq_handler(struct xgi_info * info)
+{
+       bool ret = FALSE;
+       const u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
+
+       /* DVI interrupt just happened
+        */
+       if (IN3CFB(info->mmio_map, 0x38) & 0x20) {
+               const u8 save_3x4 = DRM_READ8(info->mmio_map, 0x3d4);
+               u8 op3cf_39;
+               u8 op3cf_37;
+               u8 op3x5_5a;
+
+               /* What happened?
+                */
+               op3cf_37 = IN3CFB(info->mmio_map, 0x37);
+
+               /* Notify BIOS that DVI plug/unplug happened
+                */
+               op3x5_5a = IN3X5B(info->mmio_map, 0x5a);
+               OUT3X5B(info->mmio_map, 0x5a, op3x5_5a & 0xf7);
+
+               DRM_WRITE8(info->mmio_map, 0x3d4, save_3x4);
+
+               /* Clear DVI interrupt
+                */
+               op3cf_39 = IN3CFB(info->mmio_map, 0x39);
+               OUT3C5B(info->mmio_map, 0x39, (op3cf_39 & ~0x01));
+               OUT3C5B(info->mmio_map, 0x39, (op3cf_39 | 0x01));
+
+               ret = TRUE;
+       }
+       DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
+
+       return (ret);
+}
+
+
+static void dump_reg_header(unsigned regbase)
+{
+       printk("\n=====xgi_dump_register========0x%x===============\n",
+              regbase);
+       printk("    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
+}
+
+
+static void dump_indexed_reg(struct xgi_info * info, unsigned regbase)
+{
+       unsigned i, j;
+       u8 temp;
+
+
+       dump_reg_header(regbase);
+       for (i = 0; i < 0x10; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       DRM_WRITE8(info->mmio_map, regbase - 1,
+                                  (i * 0x10) + j);
+                       temp = DRM_READ8(info->mmio_map, regbase);
+                       printk("%3x", temp);
+               }
+               printk("\n");
+       }
+}
+
+
+static void dump_reg(struct xgi_info * info, unsigned regbase, unsigned range)
+{
+       unsigned i, j;
+
+
+       dump_reg_header(regbase);
+       for (i = 0; i < range; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       u8 temp = DRM_READ8(info->mmio_map, 
+                                           regbase + (i * 0x10) + j);
+                       printk("%3x", temp);
+               }
+               printk("\n");
+       }
+}
+
+
+void xgi_dump_register(struct xgi_info * info)
+{
+       dump_indexed_reg(info, 0x3c5);
+       dump_indexed_reg(info, 0x3d5);
+       dump_indexed_reg(info, 0x3cf);
+
+       dump_reg(info, 0xB000, 0x05);
+       dump_reg(info, 0x2200, 0x0B);
+       dump_reg(info, 0x2300, 0x07);
+       dump_reg(info, 0x2400, 0x10);
+       dump_reg(info, 0x2800, 0x10);
+}
+
+
+#define WHOLD_GE_STATUS             0x2800
+
+/* Test everything except the "whole GE busy" bit, the "master engine busy"
+ * bit, and the reserved bits [26:21].
+ */
+#define IDLE_MASK                   ~((1U<<31) | (1U<<28) | (0x3f<<21))
+
+void xgi_waitfor_pci_idle(struct xgi_info * info)
+{
+       unsigned int idleCount = 0;
+       u32 old_status = 0;
+       unsigned int same_count = 0;
+
+       while (idleCount < 5) {
+               const u32 status = DRM_READ32(info->mmio_map, WHOLD_GE_STATUS)
+                       & IDLE_MASK;
+
+               if (status == old_status) {
+                       same_count++;
+
+                       if ((same_count % 100) == 0) {
+                               DRM_ERROR("GE status stuck at 0x%08x for %u iterations!\n",
+                                         old_status, same_count);
+                       }
+               } else {
+                       old_status = status;
+                       same_count = 0;
+               }
+
+               if (status != 0) {
+                       msleep(1);
+                       idleCount = 0;
+               } else {
+                       idleCount++;
+               }
+       }
+}
+
+
+void xgi_enable_mmio(struct xgi_info * info)
+{
+       u8 protect = 0;
+       u8 temp;
+
+       /* Unprotect registers */
+       DRM_WRITE8(info->mmio_map, 0x3C4, 0x11);
+       protect = DRM_READ8(info->mmio_map, 0x3C5);
+       DRM_WRITE8(info->mmio_map, 0x3C5, 0x92);
+
+       DRM_WRITE8(info->mmio_map, 0x3D4, 0x3A);
+       temp = DRM_READ8(info->mmio_map, 0x3D5);
+       DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x20);
+
+       /* Enable MMIO */
+       DRM_WRITE8(info->mmio_map, 0x3D4, 0x39);
+       temp = DRM_READ8(info->mmio_map, 0x3D5);
+       DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x01);
+
+       /* Protect registers */
+       OUT3C5B(info->mmio_map, 0x11, protect);
+}
+
+
+void xgi_disable_mmio(struct xgi_info * info)
+{
+       u8 protect = 0;
+       u8 temp;
+
+       /* Unprotect registers */
+       DRM_WRITE8(info->mmio_map, 0x3C4, 0x11);
+       protect = DRM_READ8(info->mmio_map, 0x3C5);
+       DRM_WRITE8(info->mmio_map, 0x3C5, 0x92);
+
+       /* Disable MMIO access */
+       DRM_WRITE8(info->mmio_map, 0x3D4, 0x39);
+       temp = DRM_READ8(info->mmio_map, 0x3D5);
+       DRM_WRITE8(info->mmio_map, 0x3D5, temp & 0xFE);
+
+       /* Protect registers */
+       OUT3C5B(info->mmio_map, 0x11, protect);
+}
+
+
+void xgi_enable_ge(struct xgi_info * info)
+{
+       u8 bOld3cf2a;
+       int wait = 0;
+
+       OUT3C5B(info->mmio_map, 0x11, 0x92);
+
+       /* Save and close dynamic gating
+        */
+       bOld3cf2a = IN3CFB(info->mmio_map, XGI_MISC_CTRL);
+       OUT3CFB(info->mmio_map, XGI_MISC_CTRL, bOld3cf2a & ~EN_GEPWM);
+
+       /* Enable 2D and 3D GE
+        */
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D));
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+
+       /* Reset both 3D and 2D engine
+        */
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL,
+               (GE_ENABLE | GE_RESET | GE_ENABLE_3D));
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D));
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+
+       /* Enable 2D engine only
+        */
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL, GE_ENABLE);
+
+       /* Enable 2D+3D engine
+        */
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D));
+
+       /* Restore dynamic gating
+        */
+       OUT3CFB(info->mmio_map, XGI_MISC_CTRL, bOld3cf2a);
+}
+
+
+void xgi_disable_ge(struct xgi_info * info)
+{
+       int wait = 0;
+
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D));
+
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+
+       /* Reset both 3D and 2D engine
+        */
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL,
+               (GE_ENABLE | GE_RESET | GE_ENABLE_3D));
+
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D));
+
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+
+       /* Disable 2D engine and 3D engine.
+        */
+       OUT3X5B(info->mmio_map, XGI_GE_CNTL, 0);
+}
diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h
new file mode 100644 (file)
index 0000000..af19a11
--- /dev/null
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 _XGI_MISC_H_
+#define _XGI_MISC_H_
+
+extern void xgi_dump_register(struct xgi_info * info);
+
+extern bool xgi_ge_irq_handler(struct xgi_info * info);
+extern bool xgi_crt_irq_handler(struct xgi_info * info);
+extern bool xgi_dvi_irq_handler(struct xgi_info * info);
+extern void xgi_waitfor_pci_idle(struct xgi_info * info);
+
+#endif
diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c
new file mode 100644 (file)
index 0000000..a7d3ea2
--- /dev/null
@@ -0,0 +1,126 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 "xgi_drv.h"
+#include "xgi_regs.h"
+#include "xgi_misc.h"
+
+void xgi_gart_flush(struct drm_device *dev)
+{
+       struct xgi_info *const info = dev->dev_private;
+       u8 temp;
+
+       DRM_MEMORYBARRIER();
+
+       /* Set GART in SFB */
+       temp = DRM_READ8(info->mmio_map, 0xB00C);
+       DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02);
+
+       /* Set GART base address to HW */
+       DRM_WRITE32(info->mmio_map, 0xB034, info->gart_info.bus_addr);
+
+       /* Flush GART table. */
+       DRM_WRITE8(info->mmio_map, 0xB03F, 0x40);
+       DRM_WRITE8(info->mmio_map, 0xB03F, 0x00);
+}
+
+
+int xgi_pcie_heap_init(struct xgi_info * info)
+{
+       u8 temp = 0;
+       int err;
+       struct drm_scatter_gather request;
+
+       /* Get current FB aperture size */
+       temp = IN3X5B(info->mmio_map, 0x27);
+       DRM_INFO("In3x5(0x27): 0x%x \n", temp);
+
+       if (temp & 0x01) {      /* 256MB; Jong 06/05/2006; 0x10000000 */
+               info->pcie.base = 256 * 1024 * 1024;
+       } else {                /* 128MB; Jong 06/05/2006; 0x08000000 */
+               info->pcie.base = 128 * 1024 * 1024;
+       }
+
+
+       DRM_INFO("info->pcie.base: 0x%lx\n", (unsigned long) info->pcie.base);
+
+       /* Get current lookup table page size */
+       temp = DRM_READ8(info->mmio_map, 0xB00C);
+       if (temp & 0x04) {      /* 8KB */
+               info->lutPageSize = 8 * 1024;
+       } else {                /* 4KB */
+               info->lutPageSize = 4 * 1024;
+       }
+
+       DRM_INFO("info->lutPageSize: 0x%x \n", info->lutPageSize);
+
+
+       request.size = info->pcie.size;
+       err = drm_sg_alloc(info->dev, & request);
+       if (err) {
+               DRM_ERROR("cannot allocate PCIE GART backing store!  "
+                         "size = %d\n", info->pcie.size);
+               return err;
+       }
+
+       info->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
+       info->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
+       info->gart_info.table_size = info->dev->sg->pages * sizeof(u32);
+
+       if (!drm_ati_pcigart_init(info->dev, &info->gart_info)) {
+               DRM_ERROR("failed to init PCI GART!\n");
+               return -ENOMEM;
+       }
+
+
+       xgi_gart_flush(info->dev);
+
+       mutex_lock(&info->dev->struct_mutex);
+       err = drm_sman_set_range(&info->sman, XGI_MEMLOC_NON_LOCAL,
+                                0, info->pcie.size);
+       mutex_unlock(&info->dev->struct_mutex);
+       if (err) {
+               drm_ati_pcigart_cleanup(info->dev, &info->gart_info);
+       }
+
+       info->pcie_heap_initialized = (err == 0);
+       return err;
+}
+
+
+/**
+ * xgi_find_pcie_virt
+ * @address: GE HW address
+ *
+ * Returns CPU virtual address.  Assumes the CPU VAddr is continuous in not
+ * the same block
+ */
+void *xgi_find_pcie_virt(struct xgi_info * info, u32 address)
+{
+       const unsigned long offset = address - info->pcie.base;
+
+       return ((u8 *) info->dev->sg->virtual) + offset;
+}
diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h
new file mode 100644 (file)
index 0000000..5c0100a
--- /dev/null
@@ -0,0 +1,169 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI 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 _XGI_REGS_H_
+#define _XGI_REGS_H_
+
+#include "drmP.h"
+#include "drm.h"
+
+#define MAKE_MASK(bits)  ((1U << (bits)) - 1)
+
+#define ONE_BIT_MASK        MAKE_MASK(1)
+#define TWENTY_BIT_MASK     MAKE_MASK(20)
+#define TWENTYONE_BIT_MASK  MAKE_MASK(21)
+#define TWENTYTWO_BIT_MASK  MAKE_MASK(22)
+
+
+/* Port 0x3d4/0x3d5, index 0x2a */
+#define XGI_INTERFACE_SEL 0x2a
+#define DUAL_64BIT        (1U<<7)
+#define INTERNAL_32BIT    (1U<<6)
+#define EN_SEP_WR         (1U<<5)
+#define POWER_DOWN_SEL    (1U<<4)
+/*#define RESERVED_3      (1U<<3) */
+#define SUBS_MCLK_PCICLK  (1U<<2)
+#define MEM_SIZE_MASK     (3<<0)
+#define MEM_SIZE_32MB     (0<<0)
+#define MEM_SIZE_64MB     (1<<0)
+#define MEM_SIZE_128MB    (2<<0)
+#define MEM_SIZE_256MB    (3<<0)
+
+/* Port 0x3d4/0x3d5, index 0x36 */
+#define XGI_GE_CNTL 0x36
+#define GE_ENABLE        (1U<<7)
+/*#define RESERVED_6     (1U<<6) */
+/*#define RESERVED_5     (1U<<5) */
+#define GE_RESET         (1U<<4)
+/*#define RESERVED_3     (1U<<3) */
+#define GE_ENABLE_3D     (1U<<2)
+/*#define RESERVED_1     (1U<<1) */
+/*#define RESERVED_0     (1U<<0) */
+
+/* Port 0x3ce/0x3cf, index 0x2a */
+#define XGI_MISC_CTRL 0x2a
+#define MOTION_VID_SUSPEND   (1U<<7)
+#define DVI_CRTC_TIMING_SEL  (1U<<6)
+#define LCD_SEL_CTL_NEW      (1U<<5)
+#define LCD_SEL_EXT_DELYCTRL (1U<<4)
+#define REG_LCDDPARST        (1U<<3)
+#define LCD2DPAOFF           (1U<<2)
+/*#define RESERVED_1         (1U<<1) */
+#define EN_GEPWM             (1U<<0)  /* Enable GE power management */
+
+
+#define BASE_3D_ENG 0x2800
+
+#define M2REG_FLUSH_ENGINE_ADDRESS 0x000
+#define M2REG_FLUSH_ENGINE_COMMAND 0x00
+#define M2REG_FLUSH_FLIP_ENGINE_MASK              (ONE_BIT_MASK<<21)
+#define M2REG_FLUSH_2D_ENGINE_MASK                (ONE_BIT_MASK<<20)
+#define M2REG_FLUSH_3D_ENGINE_MASK                TWENTY_BIT_MASK
+
+#define M2REG_RESET_ADDRESS 0x004
+#define M2REG_RESET_COMMAND 0x01
+#define M2REG_RESET_STATUS2_MASK                  (ONE_BIT_MASK<<10)
+#define M2REG_RESET_STATUS1_MASK                  (ONE_BIT_MASK<<9)
+#define M2REG_RESET_STATUS0_MASK                  (ONE_BIT_MASK<<8)
+#define M2REG_RESET_3DENG_MASK                    (ONE_BIT_MASK<<4)
+#define M2REG_RESET_2DENG_MASK                    (ONE_BIT_MASK<<2)
+
+/* Write register */
+#define M2REG_AUTO_LINK_SETTING_ADDRESS 0x010
+#define M2REG_AUTO_LINK_SETTING_COMMAND 0x04
+#define M2REG_CLEAR_TIMER_INTERRUPT_MASK          (ONE_BIT_MASK<<11)
+#define M2REG_CLEAR_INTERRUPT_3_MASK              (ONE_BIT_MASK<<10)
+#define M2REG_CLEAR_INTERRUPT_2_MASK              (ONE_BIT_MASK<<9)
+#define M2REG_CLEAR_INTERRUPT_0_MASK              (ONE_BIT_MASK<<8)
+#define M2REG_CLEAR_COUNTERS_MASK                 (ONE_BIT_MASK<<4)
+#define M2REG_PCI_TRIGGER_MODE_MASK               (ONE_BIT_MASK<<1)
+#define M2REG_INVALID_LIST_AUTO_INTERRUPT_MASK    (ONE_BIT_MASK<<0)
+
+/* Read register */
+#define M2REG_AUTO_LINK_STATUS_ADDRESS 0x010
+#define M2REG_AUTO_LINK_STATUS_COMMAND 0x04
+#define M2REG_ACTIVE_TIMER_INTERRUPT_MASK          (ONE_BIT_MASK<<11)
+#define M2REG_ACTIVE_INTERRUPT_3_MASK              (ONE_BIT_MASK<<10)
+#define M2REG_ACTIVE_INTERRUPT_2_MASK              (ONE_BIT_MASK<<9)
+#define M2REG_ACTIVE_INTERRUPT_0_MASK              (ONE_BIT_MASK<<8)
+#define M2REG_INVALID_LIST_AUTO_INTERRUPTED_MODE_MASK    (ONE_BIT_MASK<<0)
+
+#define     M2REG_PCI_TRIGGER_REGISTER_ADDRESS 0x014
+#define     M2REG_PCI_TRIGGER_REGISTER_COMMAND 0x05
+
+
+/**
+ * Begin instruction, double-word 0
+ */
+#define BEGIN_STOP_STORE_CURRENT_POINTER_MASK   (ONE_BIT_MASK<<22)
+#define BEGIN_VALID_MASK                        (ONE_BIT_MASK<<20)
+#define BEGIN_BEGIN_IDENTIFICATION_MASK         TWENTY_BIT_MASK
+
+/**
+ * Begin instruction, double-word 1
+ */
+#define BEGIN_LINK_ENABLE_MASK                  (ONE_BIT_MASK<<31)
+#define BEGIN_COMMAND_LIST_LENGTH_MASK          TWENTYTWO_BIT_MASK
+
+
+/* Hardware access functions */
+static inline void OUT3C5B(struct drm_map * map, u8 index, u8 data)
+{
+       DRM_WRITE8(map, 0x3C4, index);
+       DRM_WRITE8(map, 0x3C5, data);
+}
+
+static inline void OUT3X5B(struct drm_map * map, u8 index, u8 data)
+{
+       DRM_WRITE8(map, 0x3D4, index);
+       DRM_WRITE8(map, 0x3D5, data);
+}
+
+static inline void OUT3CFB(struct drm_map * map, u8 index, u8 data)
+{
+       DRM_WRITE8(map, 0x3CE, index);
+       DRM_WRITE8(map, 0x3CF, data);
+}
+
+static inline u8 IN3C5B(struct drm_map * map, u8 index)
+{
+       DRM_WRITE8(map, 0x3C4, index);
+       return DRM_READ8(map, 0x3C5);
+}
+
+static inline u8 IN3X5B(struct drm_map * map, u8 index)
+{
+       DRM_WRITE8(map, 0x3D4, index);
+       return DRM_READ8(map, 0x3D5);
+}
+
+static inline u8 IN3CFB(struct drm_map * map, u8 index)
+{
+       DRM_WRITE8(map, 0x3CE, index);
+       return DRM_READ8(map, 0x3CF);
+}
+
+#endif
index f0ebf2a..7193e52 100644 (file)
@@ -36,4 +36,5 @@ klibdrminclude_HEADERS = \
                          sis_drm.h \
                          via_drm.h \
                          r300_reg.h \
-                         via_3d_reg.h
+                         via_3d_reg.h \
+                        xgi_drm.h
index b419541..5c8acfa 100644 (file)
 #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
 #endif
 
-#define XFREE86_VERSION(major,minor,patch,snap) \
-               ((major << 16) | (minor << 8) | patch)
-
-#ifndef CONFIG_XFREE86_VERSION
-#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0)
-#endif
-
-#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
-#define DRM_PROC_DEVICES "/proc/devices"
-#define DRM_PROC_MISC   "/proc/misc"
-#define DRM_PROC_DRM    "/proc/drm"
-#define DRM_DEV_DRM     "/dev/drm"
-#define DRM_DEV_MODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
-#define DRM_DEV_UID     0
-#define DRM_DEV_GID     0
-#endif
-
-#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
 #ifdef __OpenBSD__
 #define DRM_MAJOR       81
 #endif
 #define DRM_MAJOR       226
 #endif
 #define DRM_MAX_MINOR   15
-#endif
+
 #define DRM_NAME       "drm"     /**< Name in kernel, /dev, and /proc */
 #define DRM_MIN_ORDER  5         /**< At least 2^5 bytes = 32 bytes */
 #define DRM_MAX_ORDER  22        /**< Up to 2^22 bytes = 4MB */
 #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
 
 #if defined(__linux__)
-#if defined(__KERNEL__)
-typedef __u64 drm_u64_t;
-#else
-typedef unsigned long long drm_u64_t;
-#endif
-
 typedef unsigned int drm_handle_t;
 #else
 #include <sys/types.h>
-typedef u_int64_t drm_u64_t;
 typedef unsigned long drm_handle_t;    /**< To mapped regions */
 #endif
 typedef unsigned int drm_context_t;    /**< GLXContext handle */
@@ -152,31 +127,31 @@ typedef unsigned int drm_magic_t; /**< Magic for authentication */
  * \note KW: Actually it's illegal to change either for
  * backwards-compatibility reasons.
  */
-typedef struct drm_clip_rect {
+struct drm_clip_rect {
        unsigned short x1;
        unsigned short y1;
        unsigned short x2;
        unsigned short y2;
-} drm_clip_rect_t;
+};
 
 /**
  * Drawable information.
  */
-typedef struct drm_drawable_info {
+struct drm_drawable_info {
        unsigned int num_rects;
-       drm_clip_rect_t *rects;
-} drm_drawable_info_t;
+       struct drm_clip_rect *rects;
+};
 
 /**
  * Texture region,
  */
-typedef struct drm_tex_region {
+struct drm_tex_region {
        unsigned char next;
        unsigned char prev;
        unsigned char in_use;
        unsigned char padding;
        unsigned int age;
-} drm_tex_region_t;
+};
 
 /**
  * Hardware lock.
@@ -185,10 +160,10 @@ typedef struct drm_tex_region {
  * processor bus contention on a multiprocessor system, there should not be any
  * other data stored in the same cache line.
  */
-typedef struct drm_hw_lock {
+struct drm_hw_lock {
        __volatile__ unsigned int lock;         /**< lock variable */
        char padding[60];                       /**< Pad to cache line */
-} drm_hw_lock_t;
+};
 
 /* This is beyond ugly, and only works on GCC.  However, it allows me to use
  * drm.h in places (i.e., in the X-server) where I can't use size_t.  The real
@@ -211,7 +186,7 @@ typedef struct drm_hw_lock {
  *
  * \sa drmGetVersion().
  */
-typedef struct drm_version {
+struct drm_version {
        int version_major;        /**< Major version */
        int version_minor;        /**< Minor version */
        int version_patchlevel;   /**< Patch level */
@@ -221,35 +196,35 @@ typedef struct drm_version {
        char __user *date;                /**< User-space buffer to hold date */
        DRM_SIZE_T desc_len;      /**< Length of desc buffer */
        char __user *desc;                /**< User-space buffer to hold desc */
-} drm_version_t;
+};
 
 /**
  * DRM_IOCTL_GET_UNIQUE ioctl argument type.
  *
  * \sa drmGetBusid() and drmSetBusId().
  */
-typedef struct drm_unique {
+struct drm_unique {
        DRM_SIZE_T unique_len;    /**< Length of unique */
        char __user *unique;              /**< Unique name for driver instantiation */
-} drm_unique_t;
+};
 
 #undef DRM_SIZE_T
 
-typedef struct drm_list {
+struct drm_list {
        int count;                /**< Length of user-space structures */
-       drm_version_t __user *version;
-} drm_list_t;
+       struct drm_version __user *version;
+};
 
-typedef struct drm_block {
+struct drm_block {
        int unused;
-} drm_block_t;
+};
 
 /**
  * DRM_IOCTL_CONTROL ioctl argument type.
  *
  * \sa drmCtlInstHandler() and drmCtlUninstHandler().
  */
-typedef struct drm_control {
+struct drm_control {
        enum {
                DRM_ADD_COMMAND,
                DRM_RM_COMMAND,
@@ -257,12 +232,12 @@ typedef struct drm_control {
                DRM_UNINST_HANDLER
        } func;
        int irq;
-} drm_control_t;
+};
 
 /**
  * Type of memory to map.
  */
-typedef enum drm_map_type {
+enum drm_map_type {
        _DRM_FRAME_BUFFER = 0,    /**< WC (no caching), no core dump */
        _DRM_REGISTERS = 1,       /**< no caching, no core dump */
        _DRM_SHM = 2,             /**< shared, cached */
@@ -270,25 +245,26 @@ typedef enum drm_map_type {
        _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
        _DRM_CONSISTENT = 5,      /**< Consistent memory for PCI DMA */
        _DRM_TTM = 6
-} drm_map_type_t;
+};
 
 /**
  * Memory mapping flags.
  */
-typedef enum drm_map_flags {
+enum drm_map_flags {
        _DRM_RESTRICTED = 0x01,      /**< Cannot be mapped to user-virtual */
        _DRM_READ_ONLY = 0x02,
        _DRM_LOCKED = 0x04,          /**< shared, cached, locked */
        _DRM_KERNEL = 0x08,          /**< kernel requires access */
        _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
        _DRM_CONTAINS_LOCK = 0x20,   /**< SHM page that contains lock */
-       _DRM_REMOVABLE = 0x40        /**< Removable mapping */
-} drm_map_flags_t;
+       _DRM_REMOVABLE = 0x40,       /**< Removable mapping */
+        _DRM_DRIVER = 0x80           /**< Driver will take care of it */
+};
 
-typedef struct drm_ctx_priv_map {
+struct drm_ctx_priv_map {
        unsigned int ctx_id;     /**< Context requesting private mapping */
        void *handle;            /**< Handle of map */
-} drm_ctx_priv_map_t;
+};
 
 /**
  * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
@@ -296,30 +272,30 @@ typedef struct drm_ctx_priv_map {
  *
  * \sa drmAddMap().
  */
-typedef struct drm_map {
+struct drm_map {
        unsigned long offset;    /**< Requested physical address (0 for SAREA)*/
        unsigned long size;      /**< Requested physical size (bytes) */
-       drm_map_type_t type;     /**< Type of memory to map */
-       drm_map_flags_t flags;   /**< Flags */
+       enum drm_map_type type;  /**< Type of memory to map */
+       enum drm_map_flags flags;        /**< Flags */
        void *handle;            /**< User-space: "Handle" to pass to mmap() */
                                 /**< Kernel-space: kernel-virtual address */
        int mtrr;                /**< MTRR slot used */
        /*   Private data */
-} drm_map_t;
+};
 
 /**
  * DRM_IOCTL_GET_CLIENT ioctl argument type.
  */
-typedef struct drm_client {
+struct drm_client {
        int idx;                /**< Which client desired? */
        int auth;               /**< Is client authenticated? */
        unsigned long pid;      /**< Process ID */
        unsigned long uid;      /**< User ID */
        unsigned long magic;    /**< Magic */
        unsigned long iocs;     /**< Ioctl count */
-} drm_client_t;
+};
 
-typedef enum {
+enum drm_stat_type {
        _DRM_STAT_LOCK,
        _DRM_STAT_OPENS,
        _DRM_STAT_CLOSES,
@@ -337,23 +313,23 @@ typedef enum {
        _DRM_STAT_SPECIAL,      /**< Special DMA (e.g., priority or polled) */
        _DRM_STAT_MISSED        /**< Missed DMA opportunity */
            /* Add to the *END* of the list */
-} drm_stat_type_t;
+};
 
 /**
  * DRM_IOCTL_GET_STATS ioctl argument type.
  */
-typedef struct drm_stats {
+struct drm_stats {
        unsigned long count;
        struct {
                unsigned long value;
-               drm_stat_type_t type;
+               enum drm_stat_type type;
        } data[15];
-} drm_stats_t;
+};
 
 /**
  * Hardware locking flags.
  */
-typedef enum drm_lock_flags {
+enum drm_lock_flags {
        _DRM_LOCK_READY = 0x01,      /**< Wait until hardware is ready for DMA */
        _DRM_LOCK_QUIESCENT = 0x02,  /**< Wait until hardware quiescent */
        _DRM_LOCK_FLUSH = 0x04,      /**< Flush this context's DMA queue first */
@@ -363,17 +339,17 @@ typedef enum drm_lock_flags {
           full-screen DGA-like mode. */
        _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
        _DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
-} drm_lock_flags_t;
+};
 
 /**
  * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
  *
  * \sa drmGetLock() and drmUnlock().
  */
-typedef struct drm_lock {
+struct drm_lock {
        int context;
-       drm_lock_flags_t flags;
-} drm_lock_t;
+       enum drm_lock_flags flags;
+};
 
 /**
  * DMA flags
@@ -383,7 +359,7 @@ typedef struct drm_lock {
  *
  * \sa drm_dma.
  */
-typedef enum drm_dma_flags {
+enum drm_dma_flags {
        /* Flags for DMA buffer dispatch */
        _DRM_DMA_BLOCK = 0x01,        /**<
                                       * Block until buffer dispatched.
@@ -402,14 +378,14 @@ typedef enum drm_dma_flags {
        _DRM_DMA_WAIT = 0x10,         /**< Wait for free buffers */
        _DRM_DMA_SMALLER_OK = 0x20,   /**< Smaller-than-requested buffers OK */
        _DRM_DMA_LARGER_OK = 0x40     /**< Larger-than-requested buffers OK */
-} drm_dma_flags_t;
+};
 
 /**
  * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
  *
  * \sa drmAddBufs().
  */
-typedef struct drm_buf_desc {
+struct drm_buf_desc {
        int count;               /**< Number of buffers of this size */
        int size;                /**< Size in bytes */
        int low_mark;            /**< Low water mark */
@@ -425,48 +401,48 @@ typedef struct drm_buf_desc {
                                  * Start address of where the AGP buffers are
                                  * in the AGP aperture
                                  */
-} drm_buf_desc_t;
+};
 
 /**
  * DRM_IOCTL_INFO_BUFS ioctl argument type.
  */
-typedef struct drm_buf_info {
+struct drm_buf_info {
        int count;                /**< Number of buffers described in list */
-       drm_buf_desc_t __user *list;      /**< List of buffer descriptions */
-} drm_buf_info_t;
+       struct drm_buf_desc __user *list; /**< List of buffer descriptions */
+};
 
 /**
  * DRM_IOCTL_FREE_BUFS ioctl argument type.
  */
-typedef struct drm_buf_free {
+struct drm_buf_free {
        int count;
        int __user *list;
-} drm_buf_free_t;
+};
 
 /**
  * Buffer information
  *
  * \sa drm_buf_map.
  */
-typedef struct drm_buf_pub {
+struct drm_buf_pub {
        int idx;                       /**< Index into the master buffer list */
        int total;                     /**< Buffer size */
        int used;                      /**< Amount of buffer in use (for DMA) */
        void __user *address;          /**< Address of buffer */
-} drm_buf_pub_t;
+};
 
 /**
  * DRM_IOCTL_MAP_BUFS ioctl argument type.
  */
-typedef struct drm_buf_map {
+struct drm_buf_map {
        int count;              /**< Length of the buffer list */
 #if defined(__cplusplus)
        void __user *c_virtual;
 #else
        void __user *virtual;           /**< Mmap'd area in user-virtual */
 #endif
-       drm_buf_pub_t __user *list;     /**< Buffer information */
-} drm_buf_map_t;
+       struct drm_buf_pub __user *list;        /**< Buffer information */
+};
 
 /**
  * DRM_IOCTL_DMA ioctl argument type.
@@ -475,48 +451,48 @@ typedef struct drm_buf_map {
  *
  * \sa drmDMA().
  */
-typedef struct drm_dma {
+struct drm_dma {
        int context;                      /**< Context handle */
        int send_count;                   /**< Number of buffers to send */
        int __user *send_indices;         /**< List of handles to buffers */
        int __user *send_sizes;           /**< Lengths of data to send */
-       drm_dma_flags_t flags;            /**< Flags */
+       enum drm_dma_flags flags;         /**< Flags */
        int request_count;                /**< Number of buffers requested */
        int request_size;                 /**< Desired size for buffers */
        int __user *request_indices;     /**< Buffer information */
        int __user *request_sizes;
        int granted_count;                /**< Number of buffers granted */
-} drm_dma_t;
+};
 
-typedef enum {
+enum drm_ctx_flags {
        _DRM_CONTEXT_PRESERVED = 0x01,
        _DRM_CONTEXT_2DONLY = 0x02
-} drm_ctx_flags_t;
+};
 
 /**
  * DRM_IOCTL_ADD_CTX ioctl argument type.
  *
  * \sa drmCreateContext() and drmDestroyContext().
  */
-typedef struct drm_ctx {
+struct drm_ctx {
        drm_context_t handle;
-       drm_ctx_flags_t flags;
-} drm_ctx_t;
+       enum drm_ctx_flags flags;
+};
 
 /**
  * DRM_IOCTL_RES_CTX ioctl argument type.
  */
-typedef struct drm_ctx_res {
+struct drm_ctx_res {
        int count;
-       drm_ctx_t __user *contexts;
-} drm_ctx_res_t;
+       struct drm_ctx __user *contexts;
+};
 
 /**
  * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
  */
-typedef struct drm_draw {
+struct drm_draw {
        drm_drawable_t handle;
-} drm_draw_t;
+};
 
 /**
  * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
@@ -525,53 +501,53 @@ typedef enum {
        DRM_DRAWABLE_CLIPRECTS,
 } drm_drawable_info_type_t;
 
-typedef struct drm_update_draw {
+struct drm_update_draw {
        drm_drawable_t handle;
        unsigned int type;
        unsigned int num;
        unsigned long long data;
-} drm_update_draw_t;
+};
 
 /**
  * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
  */
-typedef struct drm_auth {
+struct drm_auth {
        drm_magic_t magic;
-} drm_auth_t;
+};
 
 /**
  * DRM_IOCTL_IRQ_BUSID ioctl argument type.
  *
  * \sa drmGetInterruptFromBusID().
  */
-typedef struct drm_irq_busid {
+struct drm_irq_busid {
        int irq;        /**< IRQ number */
        int busnum;     /**< bus number */
        int devnum;     /**< device number */
        int funcnum;    /**< function number */
-} drm_irq_busid_t;
+};
 
-typedef enum {
+enum drm_vblank_seq_type {
        _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
        _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
        _DRM_VBLANK_FLIP = 0x8000000,   /**< Scheduled buffer swap should flip */
        _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
        _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
        _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
-} drm_vblank_seq_type_t;
+};
 
 #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
 #define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
                                _DRM_VBLANK_NEXTONMISS)
 
 struct drm_wait_vblank_request {
-       drm_vblank_seq_type_t type;
+       enum drm_vblank_seq_type type;
        unsigned int sequence;
        unsigned long signal;
 };
 
 struct drm_wait_vblank_reply {
-       drm_vblank_seq_type_t type;
+       enum drm_vblank_seq_type type;
        unsigned int sequence;
        long tval_sec;
        long tval_usec;
@@ -582,41 +558,41 @@ struct drm_wait_vblank_reply {
  *
  * \sa drmWaitVBlank().
  */
-typedef union drm_wait_vblank {
+union drm_wait_vblank {
        struct drm_wait_vblank_request request;
        struct drm_wait_vblank_reply reply;
-} drm_wait_vblank_t;
+};
 
 /**
  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
  *
  * \sa drmAgpEnable().
  */
-typedef struct drm_agp_mode {
+struct drm_agp_mode {
        unsigned long mode;     /**< AGP mode */
-} drm_agp_mode_t;
+};
 
 /**
  * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
  *
  * \sa drmAgpAlloc() and drmAgpFree().
  */
-typedef struct drm_agp_buffer {
+struct drm_agp_buffer {
        unsigned long size;     /**< In bytes -- will round to page boundary */
        unsigned long handle;   /**< Used for binding / unbinding */
        unsigned long type;     /**< Type of memory to allocate */
        unsigned long physical; /**< Physical used by i810 */
-} drm_agp_buffer_t;
+};
 
 /**
  * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
  *
  * \sa drmAgpBind() and drmAgpUnbind().
  */
-typedef struct drm_agp_binding {
+struct drm_agp_binding {
        unsigned long handle;   /**< From drm_agp_buffer */
        unsigned long offset;   /**< In bytes -- will round to page boundary */
-} drm_agp_binding_t;
+};
 
 /**
  * DRM_IOCTL_AGP_INFO ioctl argument type.
@@ -625,7 +601,7 @@ typedef struct drm_agp_binding {
  * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
  * drmAgpVendorId() and drmAgpDeviceId().
  */
-typedef struct drm_agp_info {
+struct drm_agp_info {
        int agp_version_major;
        int agp_version_minor;
        unsigned long mode;
@@ -639,56 +615,49 @@ typedef struct drm_agp_info {
        unsigned short id_vendor;
        unsigned short id_device;
        /*@} */
-} drm_agp_info_t;
+};
 
 /**
  * DRM_IOCTL_SG_ALLOC ioctl argument type.
  */
-typedef struct drm_scatter_gather {
+struct drm_scatter_gather {
        unsigned long size;     /**< In bytes -- will round to page boundary */
        unsigned long handle;   /**< Used for mapping / unmapping */
-} drm_scatter_gather_t;
+};
 
 /**
  * DRM_IOCTL_SET_VERSION ioctl argument type.
  */
-typedef struct drm_set_version {
+struct drm_set_version {
        int drm_di_major;
        int drm_di_minor;
        int drm_dd_major;
        int drm_dd_minor;
-} drm_set_version_t;
+};
 
 
 #define DRM_FENCE_FLAG_EMIT                0x00000001
 #define DRM_FENCE_FLAG_SHAREABLE           0x00000002
 #define DRM_FENCE_FLAG_WAIT_LAZY           0x00000004
 #define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008
+#define DRM_FENCE_FLAG_NO_USER             0x00000010
 
 /* Reserved for driver use */
 #define DRM_FENCE_MASK_DRIVER              0xFF000000
 
 #define DRM_FENCE_TYPE_EXE                 0x00000001
 
-typedef struct drm_fence_arg {
-       unsigned handle;
-       int class;
-       unsigned type;
-       unsigned flags;
-       unsigned signaled;
-       unsigned expand_pad[4]; /*Future expansion */
-       enum {
-               drm_fence_create,
-               drm_fence_destroy,
-               drm_fence_reference,
-               drm_fence_unreference,
-               drm_fence_signaled,
-               drm_fence_flush,
-               drm_fence_wait,
-               drm_fence_emit,
-               drm_fence_buffers
-       } op;
-} drm_fence_arg_t;
+struct drm_fence_arg {
+       unsigned int handle;
+       unsigned int fence_class;
+       unsigned int type;
+       unsigned int flags;
+       unsigned int signaled;
+       unsigned int error;
+       unsigned int sequence;
+        unsigned int pad64;
+       uint64_t expand_pad[2]; /*Future expansion */
+};
 
 /* Buffer permissions, referring to how the GPU uses the buffers.
  * these translate to fence types used for the buffers.
@@ -696,9 +665,9 @@ typedef struct drm_fence_arg {
  *  a command (batch-) buffer is exe. Can be or-ed together.
  */
 
-#define DRM_BO_FLAG_READ        0x00000001
-#define DRM_BO_FLAG_WRITE       0x00000002
-#define DRM_BO_FLAG_EXE         0x00000004
+#define DRM_BO_FLAG_READ        (1ULL << 0)
+#define DRM_BO_FLAG_WRITE       (1ULL << 1)
+#define DRM_BO_FLAG_EXE         (1ULL << 2)
 
 /*
  * Status flags. Can be read to determine the actual state of a buffer.
@@ -711,25 +680,25 @@ typedef struct drm_fence_arg {
  * or lock.
  * Flags: Acknowledge
  */
-#define DRM_BO_FLAG_NO_EVICT    0x00000010
+#define DRM_BO_FLAG_NO_EVICT    (1ULL << 4)
 
 /*
  * Mask: Require that the buffer is placed in mappable memory when validated.
  *       If not set the buffer may or may not be in mappable memory when validated.
  * Flags: If set, the buffer is in mappable memory.
  */
-#define DRM_BO_FLAG_MAPPABLE 0x00000020
+#define DRM_BO_FLAG_MAPPABLE    (1ULL << 5)
 
 /* Mask: The buffer should be shareable with other processes.
  * Flags: The buffer is shareable with other processes.
  */
-#define DRM_BO_FLAG_SHAREABLE   0x00000040
+#define DRM_BO_FLAG_SHAREABLE   (1ULL << 6)
 
 /* Mask: If set, place the buffer in cache-coherent memory if available.
  *       If clear, never place the buffer in cache coherent memory if validated.
  * Flags: The buffer is currently in cache-coherent memory.
  */
-#define DRM_BO_FLAG_CACHED      0x00000080
+#define DRM_BO_FLAG_CACHED      (1ULL << 7)
 
 /* Mask: Make sure that every time this buffer is validated,
  *       it ends up on the same location provided that the memory mask is the same.
@@ -738,23 +707,24 @@ typedef struct drm_fence_arg {
  *       part of buffer manager shutdown or locking.
  * Flags: Acknowledge.
  */
-#define DRM_BO_FLAG_NO_MOVE     0x00000100
+#define DRM_BO_FLAG_NO_MOVE     (1ULL << 8)
 
 /* Mask: Make sure the buffer is in cached memory when mapped for reading.
  * Flags: Acknowledge.
  */
-#define DRM_BO_FLAG_READ_CACHED    0x00080000
+#define DRM_BO_FLAG_READ_CACHED    (1ULL << 19)
 
 /* Mask: Force DRM_BO_FLAG_CACHED flag strictly also if it is set.
  * Flags: Acknowledge.
  */
-#define DRM_BO_FLAG_FORCE_CACHING  0x00002000
+#define DRM_BO_FLAG_FORCE_CACHING  (1ULL << 13)
 
 /*
  * Mask: Force DRM_BO_FLAG_MAPPABLE flag strictly also if it is clear.
  * Flags: Acknowledge.
  */
-#define DRM_BO_FLAG_FORCE_MAPPABLE 0x00004000
+#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14)
+#define DRM_BO_FLAG_TILE           (1ULL << 15)
 
 /*
  * Memory type flags that can be or'ed together in the mask, but only
@@ -762,62 +732,56 @@ typedef struct drm_fence_arg {
  */
 
 /* System memory */
-#define DRM_BO_FLAG_MEM_LOCAL  0x01000000
+#define DRM_BO_FLAG_MEM_LOCAL  (1ULL << 24)
 /* Translation table memory */
-#define DRM_BO_FLAG_MEM_TT     0x02000000
+#define DRM_BO_FLAG_MEM_TT     (1ULL << 25)
 /* Vram memory */
-#define DRM_BO_FLAG_MEM_VRAM   0x04000000
+#define DRM_BO_FLAG_MEM_VRAM   (1ULL << 26)
 /* Up to the driver to define. */
-#define DRM_BO_FLAG_MEM_PRIV0  0x08000000
-#define DRM_BO_FLAG_MEM_PRIV1  0x10000000
-#define DRM_BO_FLAG_MEM_PRIV2  0x20000000
-#define DRM_BO_FLAG_MEM_PRIV3  0x40000000
-#define DRM_BO_FLAG_MEM_PRIV4  0x80000000
+#define DRM_BO_FLAG_MEM_PRIV0  (1ULL << 27)
+#define DRM_BO_FLAG_MEM_PRIV1  (1ULL << 28)
+#define DRM_BO_FLAG_MEM_PRIV2  (1ULL << 29)
+#define DRM_BO_FLAG_MEM_PRIV3  (1ULL << 30)
+#define DRM_BO_FLAG_MEM_PRIV4  (1ULL << 31)
+/* We can add more of these now with a 64-bit flag type */
 
 /* Memory flag mask */
-#define DRM_BO_MASK_MEM         0xFF000000
-#define DRM_BO_MASK_MEMTYPE     0xFF0000A0
+#define DRM_BO_MASK_MEM         0x00000000FF000000ULL
+#define DRM_BO_MASK_MEMTYPE     0x00000000FF0000A0ULL
+
+/* Driver-private flags */
+#define DRM_BO_MASK_DRIVER      0xFFFF000000000000ULL
 
 /* Don't block on validate and map */
 #define DRM_BO_HINT_DONT_BLOCK  0x00000002
 /* Don't place this buffer on the unfenced list.*/
 #define DRM_BO_HINT_DONT_FENCE  0x00000004
 #define DRM_BO_HINT_WAIT_LAZY   0x00000008
-#define DRM_BO_HINT_ALLOW_UNFENCED_MAP 0x00000010
 
+#define DRM_BO_INIT_MAGIC 0xfe769812
+#define DRM_BO_INIT_MAJOR 1
+#define DRM_BO_INIT_MINOR 0
+#define DRM_BO_INIT_PATCH 0
+
+
+struct drm_bo_info_req {
+       uint64_t mask;
+       uint64_t flags;
+       unsigned int handle;
+       unsigned int hint;
+       unsigned int fence_class;
+       unsigned int desired_tile_stride;
+       unsigned int tile_info;
+       unsigned int pad64;
+};
 
-typedef enum {
-       drm_bo_type_dc,
-       drm_bo_type_user,
-       drm_bo_type_fake,
-       drm_bo_type_kernel, /* for initial kernel allocations */
-}drm_bo_type_t;
-
-
-typedef struct drm_bo_arg_request {
-       unsigned handle; /* User space handle */
-       unsigned mask;
-       unsigned hint;
-       drm_u64_t size;
-       drm_bo_type_t type;
-       unsigned arg_handle;
-       drm_u64_t buffer_start;
-       unsigned page_alignment;
-       unsigned expand_pad[4]; /*Future expansion */
-       enum {
-               drm_bo_create,
-               drm_bo_validate,
-               drm_bo_map,
-               drm_bo_unmap,
-               drm_bo_fence,
-               drm_bo_destroy,
-               drm_bo_reference,
-               drm_bo_unreference,
-               drm_bo_info,
-               drm_bo_wait_idle,
-               drm_bo_ref_fence
-       } op;
-} drm_bo_arg_request_t;
+struct drm_bo_create_req {
+       uint64_t mask;
+       uint64_t size;
+       uint64_t buffer_start;
+       unsigned int hint;
+       unsigned int page_alignment;
+};
 
 
 /*
@@ -826,30 +790,76 @@ typedef struct drm_bo_arg_request {
 
 #define DRM_BO_REP_BUSY 0x00000001
 
-typedef struct drm_bo_arg_reply {
+struct drm_bo_info_rep {
+       uint64_t flags;
+       uint64_t mask;
+       uint64_t size;
+       uint64_t offset;
+       uint64_t arg_handle;
+       uint64_t buffer_start;
+       unsigned int handle;
+       unsigned int fence_flags;
+       unsigned int rep_flags;
+       unsigned int page_alignment;
+       unsigned int desired_tile_stride;
+       unsigned int hw_tile_stride;
+       unsigned int tile_info;
+       unsigned int pad64;
+       uint64_t expand_pad[4]; /*Future expansion */
+};
+
+struct drm_bo_arg_rep {
+       struct drm_bo_info_rep bo_info;
        int ret;
-       unsigned handle;
-       unsigned flags;
-       drm_u64_t size;
-       drm_u64_t offset;
-       drm_u64_t arg_handle;
-       unsigned mask;
-       drm_u64_t buffer_start;
-       unsigned fence_flags;
-       unsigned rep_flags;
-       unsigned page_alignment;
-       unsigned expand_pad[4]; /*Future expansion */
-}drm_bo_arg_reply_t;
-
-
-typedef struct drm_bo_arg{
-       int handled;
-       drm_u64_t next;
+       unsigned int pad64;
+};
+
+struct drm_bo_create_arg {
+       union {
+               struct drm_bo_create_req req;
+               struct drm_bo_info_rep rep;
+       } d;
+};
+
+struct drm_bo_handle_arg {
+       unsigned int handle;
+};
+
+struct drm_bo_reference_info_arg {
+       union {
+               struct drm_bo_handle_arg req;
+               struct drm_bo_info_rep rep;
+       } d;
+};
+
+struct drm_bo_map_wait_idle_arg {
        union {
-               drm_bo_arg_request_t req;
-               drm_bo_arg_reply_t rep;
+               struct drm_bo_info_req req;
+               struct drm_bo_info_rep rep;
        } d;
-} drm_bo_arg_t;
+};
+
+struct drm_bo_op_req {
+       enum {
+               drm_bo_validate,
+               drm_bo_fence,
+               drm_bo_ref_fence,
+       } op;
+       unsigned int arg_handle;
+       struct drm_bo_info_req bo_req;
+};
+
+
+struct drm_bo_op_arg {
+       uint64_t next;
+       union {
+               struct drm_bo_op_req req;
+               struct drm_bo_arg_rep rep;
+       } d;
+       int handled;
+       unsigned int pad64;
+};
+
 
 #define DRM_BO_MEM_LOCAL 0
 #define DRM_BO_MEM_TT 1
@@ -862,25 +872,121 @@ typedef struct drm_bo_arg{
 
 #define DRM_BO_MEM_TYPES 8 /* For now. */
 
-typedef union drm_mm_init_arg{
-       struct {
-               enum {
-                       mm_init,
-                       mm_takedown,
-                       mm_query,
-                       mm_lock,
-                       mm_unlock
-               } op;
-               drm_u64_t p_offset;
-               drm_u64_t p_size;
-               unsigned mem_type;
-               unsigned expand_pad[8]; /*Future expansion */
-       } req;
-       struct {
-               drm_handle_t mm_sarea;
-               unsigned expand_pad[8]; /*Future expansion */
-       } rep;
-} drm_mm_init_arg_t;
+#define DRM_BO_LOCK_UNLOCK_BM       (1 << 0)
+#define DRM_BO_LOCK_IGNORE_NO_EVICT (1 << 1)
+
+struct drm_bo_version_arg {
+       uint32_t major;
+       uint32_t minor;
+       uint32_t patchlevel;
+};
+
+struct drm_mm_type_arg {
+       unsigned int mem_type;
+        unsigned int lock_flags;
+};
+
+struct drm_mm_init_arg {
+       unsigned int magic;
+       unsigned int major;
+       unsigned int minor;
+       unsigned int mem_type;
+       uint64_t p_offset;
+       uint64_t p_size;
+};
+
+/*
+ * Drm mode setting
+ */
+#define DRM_DISPLAY_INFO_LEN 32
+#define DRM_OUTPUT_NAME_LEN 32
+#define DRM_DISPLAY_MODE_LEN 32
+
+struct drm_mode_modeinfo {
+
+       unsigned int id;
+
+       unsigned int clock;
+       unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew;
+       unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan;
+
+       unsigned int vrefresh; /* vertical refresh * 1000 */
+
+       unsigned int flags;
+
+       char name[DRM_DISPLAY_MODE_LEN];
+};
+
+struct drm_mode_card_res {
+
+       int count_fbs;
+       unsigned int __user *fb_id;
+
+       int count_crtcs;
+       unsigned int __user *crtc_id;
+
+       int count_outputs;
+       unsigned int __user *output_id;
+
+       int count_modes;
+        struct drm_mode_modeinfo __user *modes;
+
+};
+
+struct drm_mode_crtc {
+       unsigned int crtc_id; /**< Id */
+       unsigned int fb_id; /**< Id of framebuffer */
+
+       int x, y; /**< Position on the frameuffer */
+
+       unsigned int mode; /**< Current mode used */
+
+       int count_outputs;
+       unsigned int outputs; /**< Outputs that are connected */
+
+       int count_possibles;
+       unsigned int possibles; /**< Outputs that can be connected */
+
+       unsigned int __user *set_outputs; /**< Outputs to be connected */
+
+       int gamma_size;
+
+};
+
+struct drm_mode_get_output {
+
+       unsigned int output; /**< Id */
+       unsigned int crtc; /**< Id of crtc */
+       unsigned char name[DRM_OUTPUT_NAME_LEN];
+
+       unsigned int connection;
+       unsigned int mm_width, mm_height; /**< HxW in millimeters */
+       unsigned int subpixel;
+
+       int count_crtcs;
+       unsigned int crtcs; /**< possible crtc to connect to */
+
+       int count_clones;
+       unsigned int clones; /**< list of clones */
+
+       int count_modes;
+       unsigned int __user *modes; /**< list of modes it supports */
+
+};
+
+struct drm_mode_fb_cmd {
+        unsigned int buffer_id;
+        unsigned int width, height;
+        unsigned int pitch;
+        unsigned int bpp;
+        unsigned int handle;
+       unsigned int depth;
+};
+
+struct drm_mode_mode_cmd {
+       unsigned int output_id;
+       unsigned int mode_id;
+};
 
 /**
  * \name Ioctls Definitions
@@ -893,66 +999,99 @@ typedef union drm_mm_init_arg{
 #define DRM_IOW(nr,type)               _IOW(DRM_IOCTL_BASE,nr,type)
 #define DRM_IOWR(nr,type)              _IOWR(DRM_IOCTL_BASE,nr,type)
 
-#define DRM_IOCTL_VERSION              DRM_IOWR(0x00, drm_version_t)
-#define DRM_IOCTL_GET_UNIQUE           DRM_IOWR(0x01, drm_unique_t)
-#define DRM_IOCTL_GET_MAGIC            DRM_IOR( 0x02, drm_auth_t)
-#define DRM_IOCTL_IRQ_BUSID            DRM_IOWR(0x03, drm_irq_busid_t)
-#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
-#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
-#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
-#define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, drm_set_version_t)
-
-#define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, drm_unique_t)
-#define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, drm_auth_t)
-#define DRM_IOCTL_BLOCK                        DRM_IOWR(0x12, drm_block_t)
-#define DRM_IOCTL_UNBLOCK              DRM_IOWR(0x13, drm_block_t)
-#define DRM_IOCTL_CONTROL              DRM_IOW( 0x14, drm_control_t)
-#define DRM_IOCTL_ADD_MAP              DRM_IOWR(0x15, drm_map_t)
-#define DRM_IOCTL_ADD_BUFS             DRM_IOWR(0x16, drm_buf_desc_t)
-#define DRM_IOCTL_MARK_BUFS            DRM_IOW( 0x17, drm_buf_desc_t)
-#define DRM_IOCTL_INFO_BUFS            DRM_IOWR(0x18, drm_buf_info_t)
-#define DRM_IOCTL_MAP_BUFS             DRM_IOWR(0x19, drm_buf_map_t)
-#define DRM_IOCTL_FREE_BUFS            DRM_IOW( 0x1a, drm_buf_free_t)
-
-#define DRM_IOCTL_RM_MAP               DRM_IOW( 0x1b, drm_map_t)
-
-#define DRM_IOCTL_SET_SAREA_CTX                DRM_IOW( 0x1c, drm_ctx_priv_map_t)
-#define DRM_IOCTL_GET_SAREA_CTX        DRM_IOWR(0x1d, drm_ctx_priv_map_t)
-
-#define DRM_IOCTL_ADD_CTX              DRM_IOWR(0x20, drm_ctx_t)
-#define DRM_IOCTL_RM_CTX               DRM_IOWR(0x21, drm_ctx_t)
-#define DRM_IOCTL_MOD_CTX              DRM_IOW( 0x22, drm_ctx_t)
-#define DRM_IOCTL_GET_CTX              DRM_IOWR(0x23, drm_ctx_t)
-#define DRM_IOCTL_SWITCH_CTX           DRM_IOW( 0x24, drm_ctx_t)
-#define DRM_IOCTL_NEW_CTX              DRM_IOW( 0x25, drm_ctx_t)
-#define DRM_IOCTL_RES_CTX              DRM_IOWR(0x26, drm_ctx_res_t)
-#define DRM_IOCTL_ADD_DRAW             DRM_IOWR(0x27, drm_draw_t)
-#define DRM_IOCTL_RM_DRAW              DRM_IOWR(0x28, drm_draw_t)
-#define DRM_IOCTL_DMA                  DRM_IOWR(0x29, drm_dma_t)
-#define DRM_IOCTL_LOCK                 DRM_IOW( 0x2a, drm_lock_t)
-#define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, drm_lock_t)
-#define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, drm_lock_t)
+#define DRM_IOCTL_VERSION              DRM_IOWR(0x00, struct drm_version)
+#define DRM_IOCTL_GET_UNIQUE           DRM_IOWR(0x01, struct drm_unique)
+#define DRM_IOCTL_GET_MAGIC            DRM_IOR( 0x02, struct drm_auth)
+#define DRM_IOCTL_IRQ_BUSID            DRM_IOWR(0x03, struct drm_irq_busid)
+#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, struct drm_map)
+#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
+#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
+#define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, struct drm_set_version)
+
+#define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, struct drm_unique)
+#define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, struct drm_auth)
+#define DRM_IOCTL_BLOCK                        DRM_IOWR(0x12, struct drm_block)
+#define DRM_IOCTL_UNBLOCK              DRM_IOWR(0x13, struct drm_block)
+#define DRM_IOCTL_CONTROL              DRM_IOW( 0x14, struct drm_control)
+#define DRM_IOCTL_ADD_MAP              DRM_IOWR(0x15, struct drm_map)
+#define DRM_IOCTL_ADD_BUFS             DRM_IOWR(0x16, struct drm_buf_desc)
+#define DRM_IOCTL_MARK_BUFS            DRM_IOW( 0x17, struct drm_buf_desc)
+#define DRM_IOCTL_INFO_BUFS            DRM_IOWR(0x18, struct drm_buf_info)
+#define DRM_IOCTL_MAP_BUFS             DRM_IOWR(0x19, struct drm_buf_map)
+#define DRM_IOCTL_FREE_BUFS            DRM_IOW( 0x1a, struct drm_buf_free)
+
+#define DRM_IOCTL_RM_MAP               DRM_IOW( 0x1b, struct drm_map)
+
+#define DRM_IOCTL_SET_SAREA_CTX                DRM_IOW( 0x1c, struct drm_ctx_priv_map)
+#define DRM_IOCTL_GET_SAREA_CTX        DRM_IOWR(0x1d, struct drm_ctx_priv_map)
+
+#define DRM_IOCTL_ADD_CTX              DRM_IOWR(0x20, struct drm_ctx)
+#define DRM_IOCTL_RM_CTX               DRM_IOWR(0x21, struct drm_ctx)
+#define DRM_IOCTL_MOD_CTX              DRM_IOW( 0x22, struct drm_ctx)
+#define DRM_IOCTL_GET_CTX              DRM_IOWR(0x23, struct drm_ctx)
+#define DRM_IOCTL_SWITCH_CTX           DRM_IOW( 0x24, struct drm_ctx)
+#define DRM_IOCTL_NEW_CTX              DRM_IOW( 0x25, struct drm_ctx)
+#define DRM_IOCTL_RES_CTX              DRM_IOWR(0x26, struct drm_ctx_res)
+#define DRM_IOCTL_ADD_DRAW             DRM_IOWR(0x27, struct drm_draw)
+#define DRM_IOCTL_RM_DRAW              DRM_IOWR(0x28, struct drm_draw)
+#define DRM_IOCTL_DMA                  DRM_IOWR(0x29, struct drm_dma)
+#define DRM_IOCTL_LOCK                 DRM_IOW( 0x2a, struct drm_lock)
+#define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, struct drm_lock)
+#define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, struct drm_lock)
 
 #define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
 #define DRM_IOCTL_AGP_RELEASE          DRM_IO(  0x31)
-#define DRM_IOCTL_AGP_ENABLE           DRM_IOW( 0x32, drm_agp_mode_t)
-#define DRM_IOCTL_AGP_INFO             DRM_IOR( 0x33, drm_agp_info_t)
-#define DRM_IOCTL_AGP_ALLOC            DRM_IOWR(0x34, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_FREE             DRM_IOW( 0x35, drm_agp_buffer_t)
-#define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, drm_agp_binding_t)
-#define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, drm_agp_binding_t)
-
-#define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, drm_scatter_gather_t)
-#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, drm_scatter_gather_t)
-
-#define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, drm_wait_vblank_t)
-
-#define DRM_IOCTL_FENCE                 DRM_IOWR(0x3b, drm_fence_arg_t)
-#define DRM_IOCTL_BUFOBJ                DRM_IOWR(0x3d, drm_bo_arg_t)
-#define DRM_IOCTL_MM_INIT               DRM_IOWR(0x3e, drm_mm_init_arg_t)
-
-#define DRM_IOCTL_UPDATE_DRAW           DRM_IOW(0x3f, drm_update_draw_t)
-
+#define DRM_IOCTL_AGP_ENABLE           DRM_IOW( 0x32, struct drm_agp_mode)
+#define DRM_IOCTL_AGP_INFO             DRM_IOR( 0x33, struct drm_agp_info)
+#define DRM_IOCTL_AGP_ALLOC            DRM_IOWR(0x34, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_FREE             DRM_IOW( 0x35, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, struct drm_agp_binding)
+#define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, struct drm_agp_binding)
+
+#define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, struct drm_scatter_gather)
+#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, struct drm_scatter_gather)
+
+#define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, union drm_wait_vblank)
+
+#define DRM_IOCTL_UPDATE_DRAW           DRM_IOW(0x3f, struct drm_update_draw)
+
+#define DRM_IOCTL_MM_INIT               DRM_IOWR(0xc0, struct drm_mm_init_arg)
+#define DRM_IOCTL_MM_TAKEDOWN           DRM_IOWR(0xc1, struct drm_mm_type_arg)
+#define DRM_IOCTL_MM_LOCK               DRM_IOWR(0xc2, struct drm_mm_type_arg)
+#define DRM_IOCTL_MM_UNLOCK             DRM_IOWR(0xc3, struct drm_mm_type_arg)
+
+#define DRM_IOCTL_FENCE_CREATE          DRM_IOWR(0xc4, struct drm_fence_arg)
+#define DRM_IOCTL_FENCE_REFERENCE       DRM_IOWR(0xc6, struct drm_fence_arg)
+#define DRM_IOCTL_FENCE_UNREFERENCE     DRM_IOWR(0xc7, struct drm_fence_arg)
+#define DRM_IOCTL_FENCE_SIGNALED        DRM_IOWR(0xc8, struct drm_fence_arg)
+#define DRM_IOCTL_FENCE_FLUSH           DRM_IOWR(0xc9, struct drm_fence_arg)
+#define DRM_IOCTL_FENCE_WAIT            DRM_IOWR(0xca, struct drm_fence_arg)
+#define DRM_IOCTL_FENCE_EMIT            DRM_IOWR(0xcb, struct drm_fence_arg)
+#define DRM_IOCTL_FENCE_BUFFERS         DRM_IOWR(0xcc, struct drm_fence_arg)
+
+#define DRM_IOCTL_BO_CREATE             DRM_IOWR(0xcd, struct drm_bo_create_arg)
+#define DRM_IOCTL_BO_MAP                DRM_IOWR(0xcf, struct drm_bo_map_wait_idle_arg)
+#define DRM_IOCTL_BO_UNMAP              DRM_IOWR(0xd0, struct drm_bo_handle_arg)
+#define DRM_IOCTL_BO_REFERENCE          DRM_IOWR(0xd1, struct drm_bo_reference_info_arg)
+#define DRM_IOCTL_BO_UNREFERENCE        DRM_IOWR(0xd2, struct drm_bo_handle_arg)
+#define DRM_IOCTL_BO_SETSTATUS          DRM_IOWR(0xd3, struct drm_bo_map_wait_idle_arg)
+#define DRM_IOCTL_BO_INFO               DRM_IOWR(0xd4, struct drm_bo_reference_info_arg)
+#define DRM_IOCTL_BO_WAIT_IDLE          DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg)
+#define DRM_IOCTL_BO_VERSION          DRM_IOR(0xd6, struct drm_bo_version_arg)
+
+
+#define DRM_IOCTL_MODE_GETRESOURCES     DRM_IOWR(0xA0, struct drm_mode_card_res)
+#define DRM_IOCTL_MODE_GETCRTC          DRM_IOWR(0xA1, struct drm_mode_crtc)
+#define DRM_IOCTL_MODE_GETOUTPUT        DRM_IOWR(0xA2, struct drm_mode_get_output)
+#define DRM_IOCTL_MODE_SETCRTC          DRM_IOWR(0xA3, struct drm_mode_crtc)
+#define DRM_IOCTL_MODE_ADDFB            DRM_IOWR(0xA4, struct drm_mode_fb_cmd)
+#define DRM_IOCTL_MODE_RMFB             DRM_IOWR(0xA5, unsigned int)
+#define DRM_IOCTL_MODE_GETFB            DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
+
+#define DRM_IOCTL_MODE_ADDMODE         DRM_IOWR(0xA7, struct drm_mode_modeinfo)
+#define DRM_IOCTL_MODE_RMMODE          DRM_IOWR(0xA8, unsigned int)
+#define DRM_IOCTL_MODE_ATTACHMODE      DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
+#define DRM_IOCTL_MODE_DETACHMODE      DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
 /*@}*/
 
 /**
@@ -966,4 +1105,53 @@ typedef union drm_mm_init_arg{
 #define DRM_COMMAND_BASE                0x40
 #define DRM_COMMAND_END                 0xA0
 
+/* typedef area */
+#if !defined(__KERNEL__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+typedef struct drm_clip_rect drm_clip_rect_t;
+typedef struct drm_drawable_info drm_drawable_info_t;
+typedef struct drm_tex_region drm_tex_region_t;
+typedef struct drm_hw_lock drm_hw_lock_t;
+typedef struct drm_version drm_version_t;
+typedef struct drm_unique drm_unique_t;
+typedef struct drm_list drm_list_t;
+typedef struct drm_block drm_block_t;
+typedef struct drm_control drm_control_t;
+typedef enum drm_map_type drm_map_type_t;
+typedef enum drm_map_flags drm_map_flags_t;
+typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
+typedef struct drm_map drm_map_t;
+typedef struct drm_client drm_client_t;
+typedef enum drm_stat_type drm_stat_type_t;
+typedef struct drm_stats drm_stats_t;
+typedef enum drm_lock_flags drm_lock_flags_t;
+typedef struct drm_lock drm_lock_t;
+typedef enum drm_dma_flags drm_dma_flags_t;
+typedef struct drm_buf_desc drm_buf_desc_t;
+typedef struct drm_buf_info drm_buf_info_t;
+typedef struct drm_buf_free drm_buf_free_t;
+typedef struct drm_buf_pub drm_buf_pub_t;
+typedef struct drm_buf_map drm_buf_map_t;
+typedef struct drm_dma drm_dma_t;
+typedef union drm_wait_vblank drm_wait_vblank_t;
+typedef struct drm_agp_mode drm_agp_mode_t;
+typedef enum drm_ctx_flags drm_ctx_flags_t;
+typedef struct drm_ctx drm_ctx_t;
+typedef struct drm_ctx_res drm_ctx_res_t;
+typedef struct drm_draw drm_draw_t;
+typedef struct drm_update_draw drm_update_draw_t;
+typedef struct drm_auth drm_auth_t;
+typedef struct drm_irq_busid drm_irq_busid_t;
+typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
+typedef struct drm_agp_buffer drm_agp_buffer_t;
+typedef struct drm_agp_binding drm_agp_binding_t;
+typedef struct drm_agp_info drm_agp_info_t;
+typedef struct drm_scatter_gather drm_scatter_gather_t;
+typedef struct drm_set_version drm_set_version_t;
+
+typedef struct drm_fence_arg drm_fence_arg_t;
+typedef struct drm_mm_type_arg drm_mm_type_arg_t;
+typedef struct drm_mm_init_arg drm_mm_init_arg_t;
+typedef enum drm_bo_type drm_bo_type_t;
+#endif
+
 #endif
index 4b07e4f..05d32f2 100644 (file)
 0x1039 0x6300 0 "SiS 630"
 0x1039 0x6330 SIS_CHIP_315 "SiS 661"
 0x1039 0x7300 0 "SiS 730"
+0x18CA 0x0040 SIS_CHIP_315 "Volari V3XT/V5/V8"
+0x18CA 0x0042 SIS_CHIP_315 "Volari Unknown"
 
 [tdfx]
 0x121a 0x0003 0 "3dfx Voodoo Banshee"
 0x8086 0x29A2 CHIP_I9XX|CHIP_I965 "Intel i965G"
 0x8086 0x2A02 CHIP_I9XX|CHIP_I965 "Intel i965GM"
 0x8086 0x2A12 CHIP_I9XX|CHIP_I965 "Intel i965GME/GLE"
+0x8086 0x29C2 CHIP_I9XX|CHIP_I915 "Intel G33"
+0x8086 0x29B2 CHIP_I9XX|CHIP_I915 "Intel Q35"
+0x8086 0x29D2 CHIP_I9XX|CHIP_I915 "Intel Q33"
 
 [imagine]
 0x105d 0x2309 IMAGINE_128 "Imagine 128"
 0x10DE 0x009D NV40 "NVidia Quadro FX 4500"
 0x10DE 0x009E NV40 "NVidia 0x009E"
 
-[nouveau]
-0x10de 0x0008 NV_03 "EDGE 3D"
-0x10de 0x0009 NV_03 "EDGE 3D"
-0x10de 0x0010 NV_03 "Mutara V08"
-0x10de 0x0020 NV_04 "RIVA TNT"
-0x10de 0x0028 NV_04 "RIVA TNT2/TNT2 Pro"
-0x10de 0x0029 NV_04 "RIVA TNT2 Ultra"
-0x10de 0x002a NV_04 "Riva TnT2"
-0x10de 0x002b NV_04 "Riva TnT2"
-0x10de 0x002c NV_04 "Vanta/Vanta LT"
-0x10de 0x002d NV_04 "RIVA TNT2 Model 64/Model 64 Pro"
-0x10de 0x002e NV_04 "Vanta"
-0x10de 0x002f NV_04 "Vanta"
-0x10de 0x0040 NV_40 "GeForce 6800 Ultra"
-0x10de 0x0041 NV_40 "GeForce 6800"
-0x10de 0x0042 NV_40 "GeForce 6800 LE"
-0x10de 0x0043 NV_40 "NV40.3"
-0x10de 0x0044 NV_40 "GeForce 6800 XT"
-0x10de 0x0045 NV_40 "GeForce 6800 GT"
-0x10de 0x0046 NV_40 "GeForce 6800 GT"
-0x10de 0x0047 NV_40 "GeForce 6800 GS"
-0x10de 0x0048 NV_40 "GeForce 6800 XT"
-0x10de 0x0049 NV_40 "NV40GL"
-0x10de 0x004d NV_40 "Quadro FX 4000"
-0x10de 0x004e NV_40 "Quadro FX 4000"
-0x10de 0x0090 NV_40 "GeForce 7800 GTX"
-0x10de 0x0091 NV_40 "GeForce 7800 GTX"
-0x10de 0x0092 NV_40 "GeForce 7800 GT"
-0x10de 0x0093 NV_40 "GeForce 7800 GS"
-0x10de 0x0098 NV_40 "GeForce Go 7800"
-0x10de 0x0099 NV_40 "GE Force Go 7800 GTX"
-0x10de 0x009d NV_40 "Quadro FX4500"
-0x10de 0x00a0 NV_04 "Aladdin TNT2"
-0x10de 0x00c0 NV_40 "GeForce 6800 GS"
-0x10de 0x00c1 NV_40 "GeForce 6800"
-0x10de 0x00c2 NV_40 "GeForce 6800 LE"
-0x10de 0x00c3 NV_40 "Geforce 6800 XT"
-0x10de 0x00c8 NV_40 "GeForce Go 6800"
-0x10de 0x00c9 NV_40 "GeForce Go 6800 Ultra"
-0x10de 0x00cc NV_40 "Quadro FX Go1400"
-0x10de 0x00cd NV_40 "Quadro FX 3450/4000 SDI"
-0x10de 0x00ce NV_40 "Quadro FX 1400"
-0x10de 0x00f0 NV_40 "GeForce 6800/GeForce 6800 Ultra"
-0x10de 0x00f1 NV_40 "GeForce 6600/GeForce 6600 GT"
-0x10de 0x00f2 NV_40 "GeForce 6600/GeForce 6600 GT"
-0x10de 0x00f3 NV_40 "GeForce 6200"
-0x10de 0x00f4 NV_40 "GeForce 6600 LE"
-0x10de 0x00f5 NV_40 "GeForce 7800 GS"
-0x10de 0x00f6 NV_40 "GeForce 6600 GS"
-0x10de 0x00f8 NV_40 "Quadro FX 3400/4400"
-0x10de 0x00f9 NV_40 "GeForce 6800 Ultra/GeForce 6800 GT"
-0x10de 0x00fa NV_30 "GeForce PCX 5750"
-0x10de 0x00fb NV_30 "GeForce PCX 5900"
-0x10de 0x00fc NV_30 "Quadro FX 330/GeForce PCX 5300"
-0x10de 0x00fd NV_30 "Quadro FX 330/Quadro NVS280"
-0x10de 0x00fe NV_30 "Quadro FX 1300"
-0x10de 0x00ff NV_17 "GeForce PCX 4300"
-0x10de 0x0100 NV_10 "GeForce 256 SDR"
-0x10de 0x0101 NV_10 "GeForce 256 DDR"
-0x10de 0x0103 NV_10 "Quadro"
-0x10de 0x0110 NV_11 "GeForce2 MX/MX 400"
-0x10de 0x0111 NV_11 "GeForce2 MX 100 DDR/200 DDR"
-0x10de 0x0112 NV_11 "GeForce2 Go"
-0x10de 0x0113 NV_11 "Quadro2 MXR/EX/Go"
-0x10de 0x0140 NV_40 "GeForce 6600 GT"
-0x10de 0x0141 NV_40 "GeForce 6600"
-0x10de 0x0142 NV_40 "GeForce 6600 PCIe"
-0x10de 0x0144 NV_40 "GeForce Go 6600"
-0x10de 0x0145 NV_40 "GeForce 6610 XL"
-0x10de 0x0146 NV_40 "Geforce Go 6600TE/6200TE"
-0x10de 0x0148 NV_40 "GeForce Go 6600"
-0x10de 0x0149 NV_40 "GeForce Go 6600 GT"
-0x10de 0x014a NV_40 "Quadro NVS 440"
-0x10de 0x014d NV_17 "Quadro FX 550"
-0x10de 0x014e NV_40 "Quadro FX 540"
-0x10de 0x014f NV_40 "GeForce 6200"
-0x10de 0x0150 NV_15 "GeForce2 GTS/Pro"
-0x10de 0x0151 NV_15 "GeForce2 Ti"
-0x10de 0x0152 NV_15 "GeForce2 Ultra, Bladerunner"
-0x10de 0x0153 NV_15 "Quadro2 Pro"
-0x10de 0x0161 NV_44 "GeForce 6200 TurboCache(TM)"
-0x10de 0x0162 NV_44 "GeForce 6200 SE TurboCache (TM)"
-0x10de 0x0163 NV_44 "GeForce 6200 LE"
-0x10de 0x0164 NV_44 "GeForce Go 6200"
-0x10de 0x0165 NV_44 "Quadro NVS 285"
-0x10de 0x0166 NV_44 "GeForce Go 6400"
-0x10de 0x0167 NV_44 "GeForce Go 6200 TurboCache"
-0x10de 0x0168 NV_44 "GeForce Go 6200 TurboCache"
-0x10de 0x0170 NV_17 "GeForce4 MX 460"
-0x10de 0x0171 NV_17 "GeForce4 MX 440"
-0x10de 0x0172 NV_17 "GeForce4 MX 420"
-0x10de 0x0173 NV_17 "GeForce4 MX 440-SE"
-0x10de 0x0174 NV_17 "GeForce4 440 Go"
-0x10de 0x0175 NV_17 "GeForce4 420 Go"
-0x10de 0x0176 NV_17 "GeForce4 420 Go 32M"
-0x10de 0x0177 NV_17 "GeForce4 460 Go"
-0x10de 0x0178 NV_17 "Quadro4 550 XGL"
-0x10de 0x0179 NV_17 "GeForce4 420 Go 32M"
-0x10de 0x017a NV_17 "Quadro4 200/400 NVS"
-0x10de 0x017b NV_17 "Quadro4 550 XGL"
-0x10de 0x017c NV_17 "Quadro4 500 GoGL"
-0x10de 0x017d NV_17 "GeForce4 410 Go 16M"
-0x10de 0x0181 NV_17 "GeForce4 MX 440 AGP 8x"
-0x10de 0x0182 NV_17 "GeForce4 MX 440SE AGP 8x"
-0x10de 0x0183 NV_17 "GeForce4 MX 420 AGP 8x"
-0x10de 0x0185 NV_17 "GeForce4 MX 4000 AGP 8x"
-0x10de 0x0186 NV_17 "GeForce4 448 Go"
-0x10de 0x0187 NV_17 "GeForce4 488 Go"
-0x10de 0x0188 NV_17 "Quadro4 580 XGL"
-0x10de 0x018a NV_17 "Quadro4 NVS AGP 8x"
-0x10de 0x018b NV_17 "Quadro4 380 XGL"
-0x10de 0x018c NV_17 "Quadro NVS 50 PCI"
-0x10de 0x018d NV_17 "GeForce4 448 Go"
-0x10de 0x0191 NV_50 "GeForce 8800 GTX"
-0x10de 0x0193 NV_50 "GeForce 8800 GTS"
-0x10de 0x01a0 NV_11|NV_NFORCE "GeForce2 MX Integrated Graphics"
-0x10de 0x01d1 NV_44 "GeForce 7300 LE"
-0x10de 0x01d6 NV_44 "GeForce Go 7200"
-0x10de 0x01d7 NV_44 "Quadro NVS 110M / GeForce Go 7300"
-0x10de 0x01d8 NV_44 "GeForce Go 7400"
-0x10de 0x01da NV_44 "Quadro NVS 110M"
-0x10de 0x01dc NV_44 "Quadro FX 350M"
-0x10de 0x01df NV_44 "GeForce 7300 GS"
-0x10de 0x01f0 NV_17|NV_NFORCE2 "GeForce4 MX - nForce GPU"
-0x10de 0x0200 NV_20 "GeForce3"
-0x10de 0x0201 NV_20 "GeForce3 Ti 200"
-0x10de 0x0202 NV_20 "GeForce3 Ti 500"
-0x10de 0x0203 NV_20 "Quadro DCC"
-0x10de 0x0211 NV_40 "GeForce 6800"
-0x10de 0x0212 NV_40 "GeForce 6800 LE"
-0x10de 0x0215 NV_40 "GeForce 6800 GT"
-0x10de 0x0218 NV_40 "GeForce 6800 XT"
-0x10de 0x0221 NV_44 "GeForce 6200"
-0x10de 0x0240 NV_44 "GeForce 6150"
-0x10de 0x0242 NV_44 "GeForce 6100"
-0x10de 0x0244 NV_44 "GeForce 6150 Go"
-0x10de 0x0250 NV_25 "GeForce4 Ti 4600"
-0x10de 0x0251 NV_25 "GeForce4 Ti 4400"
-0x10de 0x0252 NV_25 "GeForce4 Ti"
-0x10de 0x0253 NV_25 "GeForce4 Ti 4200"
-0x10de 0x0258 NV_25 "Quadro4 900 XGL"
-0x10de 0x0259 NV_25 "Quadro4 750 XGL"
-0x10de 0x025b NV_25 "Quadro4 700 XGL"
-0x10de 0x0280 NV_25 "GeForce4 Ti 4800"
-0x10de 0x0281 NV_25 "GeForce4 Ti 4200 AGP 8x"
-0x10de 0x0282 NV_25 "GeForce4 Ti 4800 SE"
-0x10de 0x0286 NV_25 "GeForce4 Ti 4200 Go AGP 8x"
-0x10de 0x0288 NV_25 "Quadro4 980 XGL"
-0x10de 0x0289 NV_25 "Quadro4 780 XGL"
-0x10de 0x028c NV_25 "Quadro4 700 GoGL"
-0x10de 0x0290 NV_40 "GeForce 7900 GTX"
-0x10de 0x0291 NV_40 "GeForce 7900 GT"
-0x10de 0x0292 NV_40 "GeForce 7900 GS"
-0x10de 0x0298 NV_40 "GeForce Go 7900 GS"
-0x10de 0x0299 NV_40 "GeForce Go 7900 GTX"
-0x10de 0x029a NV_40 "Quadro FX 2500M"
-0x10de 0x029b NV_40 "Quadro FX 1500M"
-0x10de 0x029c NV_40 "Quadro FX 5500"
-0x10de 0x029d NV_40 "Quadro FX 3500"
-0x10de 0x029e NV_40 "Quadro FX 1500"
-0x10de 0x029f NV_40 "Quadro FX 4500 X2"
-0x10de 0x02a0 NV_20 "XGPU"
-0x10de 0x02e1 NV_40 "GeForce 7600 GS"
-0x10de 0x0300 NV_30 "GeForce FX"
-0x10de 0x0301 NV_30 "GeForce FX 5800 Ultra"
-0x10de 0x0302 NV_30 "GeForce FX 5800"
-0x10de 0x0308 NV_30 "Quadro FX 2000"
-0x10de 0x0309 NV_30 "Quadro FX 1000"
-0x10de 0x0311 NV_30 "GeForce FX 5600 Ultra"
-0x10de 0x0312 NV_30 "GeForce FX 5600"
-0x10de 0x0313 NV_30 "NV31"
-0x10de 0x0314 NV_30 "GeForce FX 5600XT"
-0x10de 0x0316 NV_30 "NV31M"
-0x10de 0x0317 NV_30 "NV31M Pro"
-0x10de 0x031a NV_30 "GeForce FX Go5600"
-0x10de 0x031b NV_30 "GeForce FX Go5650"
-0x10de 0x031d NV_30 "NV31GLM"
-0x10de 0x031e NV_30 "NV31GLM Pro"
-0x10de 0x031f NV_30 "NV31GLM Pro"
-0x10de 0x0320 NV_34 "GeForce FX 5200"
-0x10de 0x0321 NV_34 "GeForce FX 5200 Ultra"
-0x10de 0x0322 NV_34 "GeForce FX 5200"
-0x10de 0x0323 NV_34 "GeForce FX 5200LE"
-0x10de 0x0324 NV_34 "GeForce FX Go5200"
-0x10de 0x0325 NV_34 "GeForce FX Go5250"
-0x10de 0x0326 NV_34 "GeForce FX 5500"
-0x10de 0x0327 NV_34 "GeForce FX 5100"
-0x10de 0x0328 NV_34 "GeForce FX Go5200 32M/64M"
-0x10de 0x0329 NV_34 "GeForce FX Go5200"
-0x10de 0x032a NV_34 "Quadro NVS 280 PCI"
-0x10de 0x032b NV_34 "Quadro FX 500/600 PCI"
-0x10de 0x032c NV_34 "GeForce FX Go 5300"
-0x10de 0x032d NV_34 "GeForce FX Go5100"
-0x10de 0x032f NV_34 "NV34GL"
-0x10de 0x0330 NV_30 "GeForce FX 5900 Ultra"
-0x10de 0x0331 NV_30 "GeForce FX 5900"
-0x10de 0x0332 NV_30 "GeForce FX 5900XT"
-0x10de 0x0333 NV_30 "GeForce FX 5950 Ultra"
-0x10de 0x0334 NV_30 "GeForce FX 5900ZT"
-0x10de 0x0338 NV_30 "Quadro FX 3000"
-0x10de 0x033f NV_30 "Quadro FX 700"
-0x10de 0x0341 NV_30 "GeForce FX 5700 Ultra"
-0x10de 0x0342 NV_30 "GeForce FX 5700"
-0x10de 0x0343 NV_30 "GeForce FX 5700LE"
-0x10de 0x0344 NV_30 "GeForce FX 5700VE"
-0x10de 0x0345 NV_30 "NV36.5"
-0x10de 0x0347 NV_30 "GeForce FX Go5700"
-0x10de 0x0348 NV_30 "GeForce FX Go5700"
-0x10de 0x0349 NV_30 "NV36M Pro"
-0x10de 0x034b NV_30 "NV36MAP"
-0x10de 0x034c NV_30 "Quadro FX Go1000"
-0x10de 0x034e NV_30 "Quadro FX 1100"
-0x10de 0x034f NV_30 "NV36GL"
-0x10de 0x0391 NV_40 "GeForce 7600 GT"
-0x10de 0x0392 NV_40 "GeForce 7600 GS"
-0x10de 0x0393 NV_40 "GeForce 7300 GT"
-0x10de 0x0398 NV_40 "GeForce Go 7600"
-0x10de 0x03d0 NV_44 "GeForce 6100 nForce 430"
-0x10de 0x03d1 NV_44 "GeForce 6100 nForce 405"
-0x10de 0x03d2 NV_44 "GeForce 6100 nForce 400"
-0x10de 0x03d5 NV_44 "GeForce 6100 nForce 420"
-0x12d2 0x0008 NV_03 "NV1"
-0x12d2 0x0009 NV_03 "DAC64"
-0x12d2 0x0018 NV_03 "Riva128"
-0x12d2 0x0019 NV_03 "Riva128ZX"
-0x12d2 0x0020 NV_04 "TNT"
-0x12d2 0x0028 NV_04 "TNT2"
-0x12d2 0x0029 NV_04 "UTNT2"
-0x12d2 0x002c NV_04 "VTNT2"
-0x12d2 0x00a0 NV_04 "ITNT2"
-
+[xgi]
+0x18ca 0x2200 0 "XP5"
+0x18ca 0x0047 0 "XP10 / XG47"
index 43d1114..34050a6 100644 (file)
 #define SAREA_DRAWABLE_CLAIMED_ENTRY    0x80000000
 
 /** SAREA drawable */
-typedef struct drm_sarea_drawable {
+struct drm_sarea_drawable {
        unsigned int stamp;
        unsigned int flags;
-} drm_sarea_drawable_t;
+};
 
 /** SAREA frame */
-typedef struct drm_sarea_frame {
+struct drm_sarea_frame {
        unsigned int x;
        unsigned int y;
        unsigned int width;
        unsigned int height;
        unsigned int fullscreen;
-} drm_sarea_frame_t;
+};
 
 /** SAREA */
-typedef struct drm_sarea {
+struct drm_sarea {
     /** first thing is always the DRM locking structure */
-       drm_hw_lock_t lock;
+       struct drm_hw_lock lock;
     /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
-       drm_hw_lock_t drawable_lock;
-       drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES];        /**< drawables */
-       drm_sarea_frame_t frame;        /**< frame */
+       struct drm_hw_lock drawable_lock;
+       struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES];   /**< drawables */
+       struct drm_sarea_frame frame;   /**< frame */
        drm_context_t dummy_context;
-} drm_sarea_t;
+};
+
+#ifndef __KERNEL__
+typedef struct drm_sarea_drawable drm_sarea_drawable_t;
+typedef struct drm_sarea_frame drm_sarea_frame_t;
+typedef struct drm_sarea drm_sarea_t;
+#endif
 
 #endif                         /* _DRM_SAREA_H_ */
index c6a80f1..07b3a35 100644 (file)
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#define IS_I965G(dev)  (dev->pci_device == 0x2972 || \
-                       dev->pci_device == 0x2982 || \
-                       dev->pci_device == 0x2992 || \
-                       dev->pci_device == 0x29A2 || \
-                       dev->pci_device == 0x2A02 || \
-                       dev->pci_device == 0x2A12)
-
-
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
  * the head pointer changes, so that EBUSY only happens if the ring
  * actually stalls for (eg) 3 seconds.
  */
-int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
+int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_ring_buffer *ring = &(dev_priv->ring);
        u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
        int i;
 
@@ -68,13 +60,13 @@ int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
                DRM_UDELAY(1);
        }
 
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
-void i915_kernel_lost_context(drm_device_t * dev)
+void i915_kernel_lost_context(struct drm_device * dev)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_ring_buffer *ring = &(dev_priv->ring);
 
        ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
        ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
@@ -86,8 +78,10 @@ void i915_kernel_lost_context(drm_device_t * dev)
                dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
 }
 
-static int i915_dma_cleanup(drm_device_t * dev)
+int i915_dma_cleanup(struct drm_device * dev)
 {
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+
        /* Make sure interrupts are disabled here because the uninstall ioctl
         * may not have been called from userspace and after dev_private
         * is freed, it's too late.
@@ -95,41 +89,21 @@ static int i915_dma_cleanup(drm_device_t * dev)
        if (dev->irq)
                drm_irq_uninstall(dev);
 
-       if (dev->dev_private) {
-               drm_i915_private_t *dev_priv =
-                   (drm_i915_private_t *) dev->dev_private;
-
-               if (dev_priv->ring.virtual_start) {
-                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
-               }
-
-               if (dev_priv->status_page_dmah) {
-                       drm_pci_free(dev, dev_priv->status_page_dmah);
-                       /* Need to rewrite hardware status page */
-                       I915_WRITE(0x02080, 0x1ffff000);
-               }
-
-               drm_free(dev->dev_private, sizeof(drm_i915_private_t),
-                        DRM_MEM_DRIVER);
-
-               dev->dev_private = NULL;
-       }
-
        return 0;
 }
 
-static int i915_initialize(drm_device_t * dev,
-                          drm_i915_private_t * dev_priv,
-                          drm_i915_init_t * init)
+static int i915_initialize(struct drm_device * dev,
+                          struct drm_i915_private * dev_priv,
+                          struct drm_i915_init * init)
 {
-       memset(dev_priv, 0, sizeof(drm_i915_private_t));
+       memset(dev_priv, 0, sizeof(struct drm_i915_private));
 
        dev_priv->sarea = drm_getsarea(dev);
        if (!dev_priv->sarea) {
                DRM_ERROR("can not find sarea!\n");
                dev->dev_private = (void *)dev_priv;
                i915_dma_cleanup(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
@@ -137,9 +111,13 @@ static int i915_initialize(drm_device_t * dev,
                dev->dev_private = (void *)dev_priv;
                i915_dma_cleanup(dev);
                DRM_ERROR("can not find mmio map!\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
+#ifdef I915_HAVE_BUFFER
+       dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
+#endif
+
        dev_priv->sarea_priv = (drm_i915_sarea_t *)
            ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
 
@@ -161,7 +139,7 @@ static int i915_initialize(drm_device_t * dev,
                i915_dma_cleanup(dev);
                DRM_ERROR("can not ioremap virtual address for"
                          " ring buffer\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
@@ -183,79 +161,81 @@ static int i915_initialize(drm_device_t * dev,
        dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
 
        /* Program Hardware Status Page */
-       dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 
-           0xffffffff);
+       if (!IS_G33(dev)) {
+               dev_priv->status_page_dmah = 
+                       drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+               if (!dev_priv->status_page_dmah) {
+                       dev->dev_private = (void *)dev_priv;
+                       i915_dma_cleanup(dev);
+                       DRM_ERROR("Can not allocate hardware status page\n");
+                       return -ENOMEM;
+               }
+               dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+               dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
 
-       if (!dev_priv->status_page_dmah) {
-               dev->dev_private = (void *)dev_priv;
-               i915_dma_cleanup(dev);
-               DRM_ERROR("Can not allocate hardware status page\n");
-               return DRM_ERR(ENOMEM);
-       }
-       dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-       dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-       
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+               memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 
-       I915_WRITE(0x02080, dev_priv->dma_status_page);
+               I915_WRITE(0x02080, dev_priv->dma_status_page);
+       }
        DRM_DEBUG("Enabled hardware status page\n");
        dev->dev_private = (void *)dev_priv;
+       mutex_init(&dev_priv->cmdbuf_mutex);
        return 0;
 }
 
-static int i915_dma_resume(drm_device_t * dev)
+static int i915_dma_resume(struct drm_device * dev)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
        if (!dev_priv->sarea) {
                DRM_ERROR("can not find sarea!\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (!dev_priv->mmio_map) {
                DRM_ERROR("can not find mmio map!\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (dev_priv->ring.map.handle == NULL) {
                DRM_ERROR("can not ioremap virtual address for"
                          " ring buffer\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        /* Program Hardware Status Page */
        if (!dev_priv->hw_status_page) {
                DRM_ERROR("Can not find hardware status page\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
 
-       I915_WRITE(0x02080, dev_priv->dma_status_page);
+       if (dev_priv->status_gfx_addr != 0)
+               I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+       else
+               I915_WRITE(0x02080, dev_priv->dma_status_page);
        DRM_DEBUG("Enabled hardware status page\n");
 
        return 0;
 }
 
-static int i915_dma_init(DRM_IOCTL_ARGS)
+static int i915_dma_init(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv;
-       drm_i915_init_t init;
+       struct drm_i915_private *dev_priv;
+       struct drm_i915_init *init = data;
        int retcode = 0;
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data,
-                                sizeof(init));
-
-       switch (init.func) {
+       switch (init->func) {
        case I915_INIT_DMA:
-               dev_priv = drm_alloc(sizeof(drm_i915_private_t),
+               dev_priv = drm_alloc(sizeof(struct drm_i915_private),
                                     DRM_MEM_DRIVER);
                if (dev_priv == NULL)
-                       return DRM_ERR(ENOMEM);
-               retcode = i915_initialize(dev, dev_priv, &init);
+                       return -ENOMEM;
+               retcode = i915_initialize(dev, dev_priv, init);
                break;
        case I915_CLEANUP_DMA:
                retcode = i915_dma_cleanup(dev);
@@ -264,7 +244,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
                retcode = i915_dma_resume(dev);
                break;
        default:
-               retcode = DRM_ERR(EINVAL);
+               retcode = -EINVAL;
                break;
        }
 
@@ -347,14 +327,15 @@ static int validate_cmd(int cmd)
        return ret;
 }
 
-static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
+static int i915_emit_cmds(struct drm_device * dev, int __user * buffer,
+                         int dwords)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
        RING_LOCALS;
 
        if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        BEGIN_LP_RING((dwords+1)&~1);
 
@@ -362,17 +343,17 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
                int cmd, sz;
 
                if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
 
                if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
 
                OUT_RING(cmd);
 
                while (++i, --sz) {
                        if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
                                                         sizeof(cmd))) {
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        OUT_RING(cmd);
                }
@@ -386,22 +367,22 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
        return 0;
 }
 
-static int i915_emit_box(drm_device_t * dev,
-                        drm_clip_rect_t __user * boxes,
+static int i915_emit_box(struct drm_device * dev,
+                        struct drm_clip_rect __user * boxes,
                         int i, int DR1, int DR4)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_clip_rect_t box;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_clip_rect box;
        RING_LOCALS;
 
        if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
                DRM_ERROR("Bad box %d,%d..%d,%d\n",
                          box.x1, box.y1, box.x2, box.y2);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (IS_I965G(dev)) {
@@ -429,15 +410,17 @@ static int i915_emit_box(drm_device_t * dev,
  * emit.  For now, do it in both places:
  */
 
-void i915_emit_breadcrumb(drm_device_t *dev)
+void i915_emit_breadcrumb(struct drm_device *dev)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        RING_LOCALS;
 
-       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+       if (++dev_priv->counter > BREADCRUMB_MASK) {
+                dev_priv->counter = 1;
+                DRM_DEBUG("Breadcrumb counter wrapped around\n");
+       }
 
-       if (dev_priv->counter > 0x7FFFFFFFUL)
-                dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+       dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
        BEGIN_LP_RING(4);
        OUT_RING(CMD_STORE_DWORD_IDX);
@@ -448,9 +431,9 @@ void i915_emit_breadcrumb(drm_device_t *dev)
 }
 
 
-int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush)
+int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t flush_cmd = CMD_MI_FLUSH;
        RING_LOCALS;
 
@@ -469,18 +452,18 @@ int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush)
 }
 
 
-static int i915_dispatch_cmdbuffer(drm_device_t * dev,
-                                  drm_i915_cmdbuffer_t * cmd)
+static int i915_dispatch_cmdbuffer(struct drm_device * dev,
+                                  struct drm_i915_cmdbuffer * cmd)
 {
 #ifdef I915_HAVE_FENCE
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 #endif
        int nbox = cmd->num_cliprects;
        int i = 0, count, ret;
 
        if (cmd->sz & 0x3) {
-               DRM_ERROR("alignment");
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("alignment\n");
+               return -EINVAL;
        }
 
        i915_kernel_lost_context(dev);
@@ -507,18 +490,18 @@ static int i915_dispatch_cmdbuffer(drm_device_t * dev,
        return 0;
 }
 
-static int i915_dispatch_batchbuffer(drm_device_t * dev,
+static int i915_dispatch_batchbuffer(struct drm_device * dev,
                                     drm_i915_batchbuffer_t * batch)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_clip_rect_t __user *boxes = batch->cliprects;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_clip_rect __user *boxes = batch->cliprects;
        int nbox = batch->num_cliprects;
        int i = 0, count;
        RING_LOCALS;
 
        if ((batch->start | batch->used) & 0x7) {
-               DRM_ERROR("alignment");
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("alignment\n");
+               return -EINVAL;
        }
 
        i915_kernel_lost_context(dev);
@@ -535,9 +518,15 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev,
 
                if (dev_priv->use_mi_batchbuffer_start) {
                        BEGIN_LP_RING(2);
-                       OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-                       OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+                       if (IS_I965G(dev)) {
+                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
+                               OUT_RING(batch->start);
+                       } else {
+                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+                               OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+                       }
                        ADVANCE_LP_RING();
+
                } else {
                        BEGIN_LP_RING(4);
                        OUT_RING(MI_BATCH_BUFFER);
@@ -555,11 +544,11 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev,
        return 0;
 }
 
-static void i915_do_dispatch_flip(drm_device_t * dev, int pipe, int sync)
+static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        u32 num_pages, current_page, next_page, dspbase;
-       int shift = 2 * pipe, x, y;
+       int shift = 2 * plane, x, y;
        RING_LOCALS;
 
        /* Calculate display base offset */
@@ -580,25 +569,25 @@ static void i915_do_dispatch_flip(drm_device_t * dev, int pipe, int sync)
                break;
        }
 
-       if (pipe == 0) {
-               x = dev_priv->sarea_priv->pipeA_x;
-               y = dev_priv->sarea_priv->pipeA_y;
+       if (plane == 0) {
+               x = dev_priv->sarea_priv->planeA_x;
+               y = dev_priv->sarea_priv->planeA_y;
        } else {
-               x = dev_priv->sarea_priv->pipeB_x;
-               y = dev_priv->sarea_priv->pipeB_y;
+               x = dev_priv->sarea_priv->planeB_x;
+               y = dev_priv->sarea_priv->planeB_y;
        }
 
        dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
 
-       DRM_DEBUG("pipe=%d current_page=%d dspbase=0x%x\n", pipe, current_page,
+       DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
                  dspbase);
 
        BEGIN_LP_RING(4);
        OUT_RING(sync ? 0 :
-                (MI_WAIT_FOR_EVENT | (pipe ? MI_WAIT_FOR_PLANE_B_FLIP :
+                (MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
                                       MI_WAIT_FOR_PLANE_A_FLIP)));
        OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
-                (pipe ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
+                (plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
        OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
        OUT_RING(dspbase);
        ADVANCE_LP_RING();
@@ -607,19 +596,19 @@ static void i915_do_dispatch_flip(drm_device_t * dev, int pipe, int sync)
        dev_priv->sarea_priv->pf_current_page |= next_page << shift;
 }
 
-void i915_dispatch_flip(drm_device_t * dev, int pipes, int sync)
+void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
 
-       DRM_DEBUG("%s: pipes=0x%x pfCurrentPage=%d\n",
+       DRM_DEBUG("%s: planes=0x%x pfCurrentPage=%d\n",
                  __FUNCTION__,
-                 pipes, dev_priv->sarea_priv->pf_current_page);
+                 planes, dev_priv->sarea_priv->pf_current_page);
 
        i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
 
        for (i = 0; i < 2; i++)
-               if (pipes & (1 << i))
+               if (planes & (1 << i))
                        i915_do_dispatch_flip(dev, i, sync);
 
        i915_emit_breadcrumb(dev);
@@ -629,82 +618,76 @@ void i915_dispatch_flip(drm_device_t * dev, int pipes, int sync)
 #endif
 }
 
-static int i915_quiescent(drm_device_t * dev)
+static int i915_quiescent(struct drm_device * dev)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
        i915_kernel_lost_context(dev);
        return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
 }
 
-static int i915_flush_ioctl(DRM_IOCTL_ARGS)
+static int i915_flush_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return i915_quiescent(dev);
 }
 
-static int i915_batchbuffer(DRM_IOCTL_ARGS)
+static int i915_batchbuffer(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
            dev_priv->sarea_priv;
-       drm_i915_batchbuffer_t batch;
+       drm_i915_batchbuffer_t *batch = data;
        int ret;
 
        if (!dev_priv->allow_batchbuffer) {
                DRM_ERROR("Batchbuffer ioctl disabled\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data,
-                                sizeof(batch));
-
        DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
-                 batch.start, batch.used, batch.num_cliprects);
+                 batch->start, batch->used, batch->num_cliprects);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
-                                                      batch.num_cliprects *
-                                                      sizeof(drm_clip_rect_t)))
-               return DRM_ERR(EFAULT);
+       if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
+                                                       batch->num_cliprects *
+                                                       sizeof(struct drm_clip_rect)))
+               return -EFAULT;
 
-       ret = i915_dispatch_batchbuffer(dev, &batch);
+       ret = i915_dispatch_batchbuffer(dev, batch);
 
        sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
        return ret;
 }
 
-static int i915_cmdbuffer(DRM_IOCTL_ARGS)
+static int i915_cmdbuffer(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+       struct drm_i915_sarea *sarea_priv = (struct drm_i915_sarea *)
            dev_priv->sarea_priv;
-       drm_i915_cmdbuffer_t cmdbuf;
+       struct drm_i915_cmdbuffer *cmdbuf = data;
        int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
-                                sizeof(cmdbuf));
-
        DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
-                 cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
+                 cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (cmdbuf.num_cliprects &&
-           DRM_VERIFYAREA_READ(cmdbuf.cliprects,
-                               cmdbuf.num_cliprects *
-                               sizeof(drm_clip_rect_t))) {
+       if (cmdbuf->num_cliprects &&
+           DRM_VERIFYAREA_READ(cmdbuf->cliprects,
+                               cmdbuf->num_cliprects *
+                               sizeof(struct drm_clip_rect))) {
                DRM_ERROR("Fault accessing cliprects\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
-       ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
+       ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
        if (ret) {
                DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
                return ret;
@@ -714,68 +697,446 @@ static int i915_cmdbuffer(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int i915_do_cleanup_pageflip(drm_device_t * dev)
+#ifdef I915_HAVE_BUFFER
+struct i915_relocatee_info {
+       struct drm_buffer_object *buf;
+       unsigned long offset;
+       u32 *data_page;
+       unsigned page_offset;
+       struct drm_bo_kmap_obj kmap;
+       int is_iomem;
+};
+
+static void i915_dereference_buffers_locked(struct drm_buffer_object **buffers,
+                                           unsigned num_buffers)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       int i, pipes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
+       while (num_buffers--)
+               drm_bo_usage_deref_locked(&buffers[num_buffers]);
+}
+
+int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
+                    struct drm_buffer_object **buffers,
+                    struct i915_relocatee_info *relocatee,
+                    uint32_t *reloc)
+{
+       unsigned index;
+       unsigned long new_cmd_offset;
+       u32 val;
+       int ret;
+
+       if (reloc[2] >= num_buffers) {
+               DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]);
+               return -EINVAL;
+       }
+
+       new_cmd_offset = reloc[0];
+       if (!relocatee->data_page ||
+           !drm_bo_same_page(relocatee->offset, new_cmd_offset)) {
+               drm_bo_kunmap(&relocatee->kmap);
+               relocatee->offset = new_cmd_offset;
+               ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT,
+                                 1, &relocatee->kmap);
+               if (ret) {
+                       DRM_ERROR("Could not map command buffer to apply relocs\n %08lx", new_cmd_offset);
+                       return ret;
+               }
+
+               relocatee->data_page = drm_bmo_virtual(&relocatee->kmap,
+                                                      &relocatee->is_iomem);
+               relocatee->page_offset = (relocatee->offset & PAGE_MASK);
+       }
+
+       val = buffers[reloc[2]]->offset;
+       index = (reloc[0] - relocatee->page_offset) >> 2;
+
+       /* add in validate */
+       val = val + reloc[1];
+
+       relocatee->data_page[index] = val;
+       return 0;
+}
+
+int i915_process_relocs(struct drm_file *file_priv,
+                       uint32_t buf_handle,
+                       uint32_t *reloc_buf_handle,
+                       struct i915_relocatee_info *relocatee,
+                       struct drm_buffer_object **buffers,
+                       uint32_t num_buffers)
+{
+       struct drm_device *dev = file_priv->head->dev;
+       struct drm_buffer_object *reloc_list_object;
+       uint32_t cur_handle = *reloc_buf_handle;
+       uint32_t *reloc_page;
+       int ret, reloc_is_iomem, reloc_stride;
+       uint32_t num_relocs, reloc_offset, reloc_end, reloc_page_offset, next_offset, cur_offset;
+       struct drm_bo_kmap_obj reloc_kmap;
+
+       memset(&reloc_kmap, 0, sizeof(reloc_kmap));
+
+       mutex_lock(&dev->struct_mutex);
+       reloc_list_object = drm_lookup_buffer_object(file_priv, cur_handle, 1);
+       mutex_unlock(&dev->struct_mutex);
+       if (!reloc_list_object)
+               return -EINVAL;
+
+       ret = drm_bo_kmap(reloc_list_object, 0, 1, &reloc_kmap);
+       if (ret) {
+               DRM_ERROR("Could not map relocation buffer.\n");
+               goto out;
+       }
+
+       reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
+       num_relocs = reloc_page[0] & 0xffff;
+
+       if ((reloc_page[0] >> 16) & 0xffff) {
+               DRM_ERROR("Unsupported relocation type requested\n");
+               goto out;
+       }
+
+       /* get next relocate buffer handle */
+       *reloc_buf_handle = reloc_page[1];
+       reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */
+
+       DRM_DEBUG("num relocs is %d, next is %08X\n", num_relocs, reloc_page[1]);
+
+       reloc_page_offset = 0;
+       reloc_offset = I915_RELOC_HEADER * sizeof(uint32_t);
+       reloc_end = reloc_offset + (num_relocs * reloc_stride);
+
+       do {
+               next_offset = drm_bo_offset_end(reloc_offset, reloc_end);
+
+               do {
+                       cur_offset = ((reloc_offset + reloc_page_offset) & ~PAGE_MASK) / sizeof(uint32_t);
+                       ret = i915_apply_reloc(file_priv, num_buffers,
+                                        buffers, relocatee, &reloc_page[cur_offset]);
+                       if (ret)
+                               goto out;
+
+                       reloc_offset += reloc_stride;
+               } while (reloc_offset < next_offset);
+
+               drm_bo_kunmap(&reloc_kmap);
+
+               reloc_offset = next_offset;
+               if (reloc_offset != reloc_end) {
+                       ret = drm_bo_kmap(reloc_list_object, reloc_offset >> PAGE_SHIFT, 1, &reloc_kmap);
+                       if (ret) {
+                               DRM_ERROR("Could not map relocation buffer.\n");
+                               goto out;
+                       }
+
+                       reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
+                       reloc_page_offset = reloc_offset & ~PAGE_MASK;
+               }
+
+       } while (reloc_offset != reloc_end);
+out:
+       drm_bo_kunmap(&relocatee->kmap);
+       relocatee->data_page = NULL;
+
+       drm_bo_kunmap(&reloc_kmap);
+
+       mutex_lock(&dev->struct_mutex);
+       drm_bo_usage_deref_locked(&reloc_list_object);
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+
+static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle,
+                          drm_handle_t buf_reloc_handle,
+                          struct drm_buffer_object **buffers,
+                          uint32_t buf_count)
+{
+       struct drm_device *dev = file_priv->head->dev;
+       struct i915_relocatee_info relocatee;
+       int ret = 0;
+
+       memset(&relocatee, 0, sizeof(relocatee));
+       
+       mutex_lock(&dev->struct_mutex);
+       relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1);
+       mutex_unlock(&dev->struct_mutex);
+       if (!relocatee.buf) {
+               DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle);
+               ret = -EINVAL;
+               goto out_err;
+       }
+       
+       while (buf_reloc_handle) {
+               ret = i915_process_relocs(file_priv, buf_handle, &buf_reloc_handle, &relocatee, buffers, buf_count);
+               if (ret) {
+                       DRM_ERROR("process relocs failed\n");
+                       break;
+               }
+       }
+       
+       mutex_lock(&dev->struct_mutex);
+       drm_bo_usage_deref_locked(&relocatee.buf);
+       mutex_unlock(&dev->struct_mutex);
+       
+out_err:
+       return ret;
+}
+
+/*
+ * Validate, add fence and relocate a block of bos from a userspace list
+ */
+int i915_validate_buffer_list(struct drm_file *file_priv,
+                             unsigned int fence_class, uint64_t data,
+                             struct drm_buffer_object **buffers,
+                             uint32_t *num_buffers)
+{
+       struct drm_i915_op_arg arg;
+       struct drm_bo_op_req *req = &arg.d.req;
+       struct drm_bo_arg_rep rep;
+       unsigned long next = 0;
+       int ret = 0;
+       unsigned buf_count = 0;
+       struct drm_device *dev = file_priv->head->dev;
+       uint32_t buf_reloc_handle, buf_handle;
+
+
+       do {
+               if (buf_count >= *num_buffers) {
+                       DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers);
+                       ret = -EINVAL;
+                       goto out_err;
+               }
+
+               buffers[buf_count] = NULL;
+
+               if (copy_from_user(&arg, (void __user *)(unsigned)data, sizeof(arg))) {
+                       ret = -EFAULT;
+                       goto out_err;
+               }
+
+               if (arg.handled) {
+                       data = arg.next;
+                       mutex_lock(&dev->struct_mutex);
+                       buffers[buf_count] = drm_lookup_buffer_object(file_priv, req->arg_handle, 1);
+                       mutex_unlock(&dev->struct_mutex);
+                       buf_count++;
+                       continue;
+               }
+
+               rep.ret = 0;
+               if (req->op != drm_bo_validate) {
+                       DRM_ERROR
+                           ("Buffer object operation wasn't \"validate\".\n");
+                       rep.ret = -EINVAL;
+                       goto out_err;
+               }
+
+               buf_handle = req->bo_req.handle;
+               buf_reloc_handle = arg.reloc_handle;
+
+               if (buf_reloc_handle) {
+                       ret = i915_exec_reloc(file_priv, buf_handle, buf_reloc_handle, buffers, buf_count);
+                       if (ret)
+                               goto out_err;
+                       DRM_MEMORYBARRIER();
+               }
+
+               rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle,
+                                                req->bo_req.fence_class,
+                                                req->bo_req.flags,
+                                                req->bo_req.mask,
+                                                req->bo_req.hint,
+                                                0,
+                                                &rep.bo_info,
+                                                &buffers[buf_count]);
+
+               if (rep.ret) {
+                       DRM_ERROR("error on handle validate %d\n", rep.ret);
+                       goto out_err;
+               }
+
+
+               next = arg.next;
+               arg.handled = 1;
+               arg.d.rep = rep;
+
+               if (copy_to_user((void __user *)(unsigned)data, &arg, sizeof(arg)))
+                       return -EFAULT;
+
+               data = next;
+               buf_count++;
+
+       } while (next != 0);
+       *num_buffers = buf_count;
+       return 0;
+out_err:
+       mutex_lock(&dev->struct_mutex);
+       i915_dereference_buffers_locked(buffers, buf_count);
+       mutex_unlock(&dev->struct_mutex);
+       *num_buffers = 0;
+       return (ret) ? ret : rep.ret;
+}
+
+static int i915_execbuffer(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+               dev_priv->sarea_priv;
+       struct drm_i915_execbuffer *exec_buf = data;
+       struct drm_i915_batchbuffer *batch = &exec_buf->batch;
+       struct drm_fence_arg *fence_arg = &exec_buf->fence_arg;
+       int num_buffers;
+       int ret;
+       struct drm_buffer_object **buffers;
+       struct drm_fence_object *fence;
+
+       if (!dev_priv->allow_batchbuffer) {
+               DRM_ERROR("Batchbuffer ioctl disabled\n");
+               return -EINVAL;
+       }
+
+
+       if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
+                                                       batch->num_cliprects *
+                                                       sizeof(struct drm_clip_rect)))
+               return -EFAULT;
+
+       if (exec_buf->num_buffers > dev_priv->max_validate_buffers)
+               return -EINVAL;
+
+
+       ret = drm_bo_read_lock(&dev->bm.bm_lock);
+       if (ret) 
+               return ret;
+
+       /*
+        * The cmdbuf_mutex makes sure the validate-submit-fence
+        * operation is atomic. 
+        */
+
+       ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+       if (ret) {
+               drm_bo_read_unlock(&dev->bm.bm_lock);
+               return -EAGAIN;
+       }
+
+       num_buffers = exec_buf->num_buffers;
+
+       buffers = drm_calloc(num_buffers, sizeof(struct drm_buffer_object *), DRM_MEM_DRIVER);
+       if (!buffers) {
+               drm_bo_read_unlock(&dev->bm.bm_lock);
+               mutex_unlock(&dev_priv->cmdbuf_mutex);
+               return -ENOMEM;
+        }
+
+       /* validate buffer list + fixup relocations */
+       ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list,
+                                       buffers, &num_buffers);
+       if (ret)
+               goto out_free;
+
+       /* make sure all previous memory operations have passed */
+       DRM_MEMORYBARRIER();
+
+       /* submit buffer */
+       batch->start = buffers[num_buffers-1]->offset;
+
+       DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n",
+                 batch->start, batch->used, batch->num_cliprects);
+
+       ret = i915_dispatch_batchbuffer(dev, batch);
+       if (ret)
+               goto out_err0;
+
+       sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
+       /* fence */
+       ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence);
+       if (ret)
+               goto out_err0;
+
+       if (!(fence_arg->flags & DRM_FENCE_FLAG_NO_USER)) {
+               ret = drm_fence_add_user_object(file_priv, fence, fence_arg->flags & DRM_FENCE_FLAG_SHAREABLE);
+               if (!ret) {
+                       fence_arg->handle = fence->base.hash.key;
+                       fence_arg->fence_class = fence->fence_class;
+                       fence_arg->type = fence->type;
+                       fence_arg->signaled = fence->signaled;
+               }
+       }
+       drm_fence_usage_deref_unlocked(&fence);
+out_err0:
+
+       /* handle errors */
+       mutex_lock(&dev->struct_mutex);
+       i915_dereference_buffers_locked(buffers, num_buffers);
+       mutex_unlock(&dev->struct_mutex);
+
+out_free:
+       drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER);
+
+       mutex_unlock(&dev_priv->cmdbuf_mutex);
+       drm_bo_read_unlock(&dev->bm.bm_lock);
+       return ret;
+}
+#endif
+
+int i915_do_cleanup_pageflip(struct drm_device * dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       for (i = 0, pipes = 0; i < 2; i++)
+       for (i = 0, planes = 0; i < 2; i++) {
                if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
                        dev_priv->sarea_priv->pf_current_page =
                                (dev_priv->sarea_priv->pf_current_page &
                                 ~(0x3 << (2 * i))) | (num_pages - 1) << (2 * i);
 
-                       pipes |= 1 << i;
+                       planes |= 1 << i;
                }
+       }
 
-       if (pipes)
-               i915_dispatch_flip(dev, pipes, 0);
+       if (planes)
+               i915_dispatch_flip(dev, planes, 0);
 
        return 0;
 }
 
-static int i915_flip_bufs(DRM_IOCTL_ARGS)
+static int i915_flip_bufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_flip_t param;
+       struct drm_i915_flip *param = data;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_flip_t __user *) data,
-                                sizeof(param));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (param.pipes & ~0x3) {
-               DRM_ERROR("Invalid pipes 0x%x, only <= 0x3 is valid\n",
-                         param.pipes);
-               return DRM_ERR(EINVAL);
+       /* This is really planes */
+       if (param->pipes & ~0x3) {
+               DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
+                         param->pipes);
+               return -EINVAL;
        }
 
-       i915_dispatch_flip(dev, param.pipes, 0);
+       i915_dispatch_flip(dev, param->pipes, 0);
 
        return 0;
 }
 
 
-static int i915_getparam(DRM_IOCTL_ARGS)
+static int i915_getparam(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_getparam_t param;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_getparam *param = data;
        int value;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data,
-                                sizeof(param));
-
-       switch (param.param) {
+       switch (param->param) {
        case I915_PARAM_IRQ_ACTIVE:
                value = dev->irq ? 1 : 0;
                break;
@@ -786,45 +1147,42 @@ static int i915_getparam(DRM_IOCTL_ARGS)
                value = READ_BREADCRUMB(dev_priv);
                break;
        default:
-               DRM_ERROR("Unknown parameter %d\n", param.param);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("Unknown parameter %d\n", param->param);
+               return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
                DRM_ERROR("DRM_COPY_TO_USER failed\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
 }
 
-static int i915_setparam(DRM_IOCTL_ARGS)
+static int i915_setparam(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_setparam_t param;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       drm_i915_setparam_t *param = data;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data,
-                                sizeof(param));
-
-       switch (param.param) {
+       switch (param->param) {
        case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
-               dev_priv->use_mi_batchbuffer_start = param.value;
+               dev_priv->use_mi_batchbuffer_start = param->value;
                break;
        case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
-               dev_priv->tex_lru_log_granularity = param.value;
+               dev_priv->tex_lru_log_granularity = param->value;
                break;
        case I915_SETPARAM_ALLOW_BATCHBUFFER:
-               dev_priv->allow_batchbuffer = param.value;
+               dev_priv->allow_batchbuffer = param->value;
                break;
        default:
-               DRM_ERROR("unknown parameter %d\n", param.param);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("unknown parameter %d\n", param->param);
+               return -EINVAL;
        }
 
        return 0;
@@ -840,99 +1198,114 @@ drm_i915_mmio_entry_t mmio_table[] = {
 
 static int mmio_table_size = sizeof(mmio_table)/sizeof(drm_i915_mmio_entry_t);
 
-static int i915_mmio(DRM_IOCTL_ARGS)
+static int i915_mmio(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
 {
-       char buf[32];
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       uint32_t buf[8];
+       struct drm_i915_private *dev_priv = dev->dev_private;
        drm_i915_mmio_entry_t *e;        
-       drm_i915_mmio_t mmio;
+       drm_i915_mmio_t *mmio = data;
        void __iomem *base;
+       int i;
+
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
-       DRM_COPY_FROM_USER_IOCTL(mmio, (drm_i915_mmio_t __user *) data,
-                                sizeof(mmio));
 
-       if (mmio.reg >= mmio_table_size)
-               return DRM_ERR(EINVAL);
+       if (mmio->reg >= mmio_table_size)
+               return -EINVAL;
 
-       e = &mmio_table[mmio.reg];
+       e = &mmio_table[mmio->reg];
        base = (u8 *) dev_priv->mmio_map->handle + e->offset;
 
-        switch (mmio.read_write) {
+       switch (mmio->read_write) {
                case I915_MMIO_READ:
                        if (!(e->flag & I915_MMIO_MAY_READ))
-                               return DRM_ERR(EINVAL);
-                       memcpy_fromio(buf, base, e->size);
-                       if (DRM_COPY_TO_USER(mmio.data, buf, e->size)) {
+                               return -EINVAL;
+                       for (i = 0; i < e->size / 4; i++)
+                               buf[i] = I915_READ(e->offset + i * 4);
+                       if (DRM_COPY_TO_USER(mmio->data, buf, e->size)) {
                                DRM_ERROR("DRM_COPY_TO_USER failed\n");
-                               return DRM_ERR(EFAULT);
+                               return -EFAULT;
                        }
                        break;
 
                case I915_MMIO_WRITE:
                        if (!(e->flag & I915_MMIO_MAY_WRITE))
-                               return DRM_ERR(EINVAL);
-                       if(DRM_COPY_FROM_USER(buf, mmio.data, e->size)) {
+                               return -EINVAL;
+                       if(DRM_COPY_FROM_USER(buf, mmio->data, e->size)) {
                                DRM_ERROR("DRM_COPY_TO_USER failed\n");
-                               return DRM_ERR(EFAULT);
+                               return -EFAULT;
                        }
-                       memcpy_toio(base, buf, e->size);
+                       for (i = 0; i < e->size / 4; i++)
+                               I915_WRITE(e->offset + i * 4, buf[i]);
                        break;
        }
        return 0;
 }
 
-int i915_driver_load(drm_device_t *dev, unsigned long flags)
+static int i915_set_status_page(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
 {
-       /* i915 has 4 more counters */
-       dev->counters += 4;
-       dev->types[6] = _DRM_STAT_IRQ;
-       dev->types[7] = _DRM_STAT_PRIMARY;
-       dev->types[8] = _DRM_STAT_SECONDARY;
-       dev->types[9] = _DRM_STAT_DMA;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       drm_i915_hws_addr_t *hws = data;
 
-       return 0;
-}
-
-void i915_driver_lastclose(drm_device_t * dev)
-{
-       if (dev->dev_private) {
-               drm_i915_private_t *dev_priv = dev->dev_private;
-               i915_do_cleanup_pageflip(dev);
-               i915_mem_takedown(&(dev_priv->agp_heap));
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return -EINVAL;
        }
-       i915_dma_cleanup(dev);
-}
+       DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
 
-void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
-{
-       if (dev->dev_private) {
-               drm_i915_private_t *dev_priv = dev->dev_private;
-               i915_mem_release(dev, filp, dev_priv->agp_heap);
+       dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
+
+       dev_priv->hws_map.offset = dev->agp->base + hws->addr;
+       dev_priv->hws_map.size = 4*1024;
+       dev_priv->hws_map.type = 0;
+       dev_priv->hws_map.flags = 0;
+       dev_priv->hws_map.mtrr = 0;
+
+       drm_core_ioremap(&dev_priv->hws_map, dev);
+       if (dev_priv->hws_map.handle == NULL) {
+               dev->dev_private = (void *)dev_priv;
+               i915_dma_cleanup(dev);
+               dev_priv->status_gfx_addr = 0;
+               DRM_ERROR("can not ioremap virtual address for"
+                               " G33 hw status page\n");
+               return -ENOMEM;
        }
+       dev_priv->hw_status_page = dev_priv->hws_map.handle;
+
+       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+       I915_WRITE(I915REG_HWS_PGA, dev_priv->status_gfx_addr);
+       DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
+                       dev_priv->status_gfx_addr);
+       DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
+       return 0;
 }
 
-drm_ioctl_desc_t i915_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
-       [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
-       [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_I915_MMIO)] = {i915_mmio, DRM_AUTH},
+struct drm_ioctl_desc i915_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
+       DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
+       DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
+       DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_MMIO, i915_mmio, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
+#ifdef I915_HAVE_BUFFER
+       DRM_IOCTL_DEF(DRM_I915_EXECBUFFER, i915_execbuffer, DRM_AUTH),
+#endif
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
@@ -948,15 +1321,9 @@ int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
  * \returns
  * A value of 1 is always retured to indictate every i9x5 is AGP.
  */
-int i915_driver_device_is_agp(drm_device_t * dev)
+int i915_driver_device_is_agp(struct drm_device * dev)
 {
        return 1;
 }
 
-int i915_driver_firstopen(struct drm_device *dev)
-{
-#ifdef I915_HAVE_BUFFER
-       drm_bo_driver_init(dev);
-#endif
-       return 0;
-}
+
index 1f32313..e517fac 100644 (file)
@@ -39,7 +39,7 @@
                                 * of chars for next/prev indices */
 #define I915_LOG_MIN_TEX_REGION_SIZE 14
 
-typedef struct _drm_i915_init {
+typedef struct drm_i915_init {
        enum {
                I915_INIT_DMA = 0x01,
                I915_CLEANUP_DMA = 0x02,
@@ -63,8 +63,8 @@ typedef struct _drm_i915_init {
        unsigned int chipset;
 } drm_i915_init_t;
 
-typedef struct _drm_i915_sarea {
-       drm_tex_region_t texList[I915_NR_TEX_REGIONS + 1];
+typedef struct drm_i915_sarea {
+       struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
        int last_upload;        /* last time texture was uploaded */
        int last_enqueue;       /* last time a buffer was enqueued */
        int last_dispatch;      /* age of the most recently dispatched buffer */
@@ -105,14 +105,14 @@ typedef struct _drm_i915_sarea {
        unsigned int rotated_tiled;
        unsigned int rotated2_tiled;
 
-       int pipeA_x;
-       int pipeA_y;
-       int pipeA_w;
-       int pipeA_h;
-       int pipeB_x;
-       int pipeB_y;
-       int pipeB_w;
-       int pipeB_h;
+       int planeA_x;
+       int planeA_y;
+       int planeA_w;
+       int planeA_h;
+       int planeB_x;
+       int planeB_y;
+       int planeB_w;
+       int planeB_h;
 
        /* Triple buffering */
        drm_handle_t third_handle;
@@ -159,6 +159,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GET_VBLANK_PIPE       0x0e
 #define DRM_I915_VBLANK_SWAP   0x0f
 #define DRM_I915_MMIO          0x10
+#define DRM_I915_HWS_ADDR      0x11
+#define DRM_I915_EXECBUFFER    0x12
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -176,36 +178,42 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 #define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
-
+#define DRM_IOCTL_I915_EXECBUFFER      DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer)
 
 /* Asynchronous page flipping:
  */
 typedef struct drm_i915_flip {
+       /*
+        * This is really talking about planes, and we could rename it
+        * except for the fact that some of the duplicated i915_drm.h files
+        * out there check for HAVE_I915_FLIP and so might pick up this
+        * version.
+        */
        int pipes;
 } drm_i915_flip_t;
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
  */
-typedef struct _drm_i915_batchbuffer {
+typedef struct drm_i915_batchbuffer {
        int start;              /* agp offset */
        int used;               /* nr bytes in use */
        int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
        int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
        int num_cliprects;      /* mulitpass with multiple cliprects? */
-       drm_clip_rect_t __user *cliprects;      /* pointer to userspace cliprects */
+       struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
 } drm_i915_batchbuffer_t;
 
 /* As above, but pass a pointer to userspace buffer which can be
  * validated by the kernel prior to sending to hardware.
  */
-typedef struct _drm_i915_cmdbuffer {
+typedef struct drm_i915_cmdbuffer {
        char __user *buf;       /* pointer to userspace command buffer */
        int sz;                 /* nr bytes in buf */
        int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
        int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
        int num_cliprects;      /* mulitpass with multiple cliprects? */
-       drm_clip_rect_t __user *cliprects;      /* pointer to userspace cliprects */
+       struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
 } drm_i915_cmdbuffer_t;
 
 /* Userspace can request & wait on irq's:
@@ -282,7 +290,7 @@ typedef struct drm_i915_vblank_pipe {
  */
 typedef struct drm_i915_vblank_swap {
        drm_drawable_t drawable;
-       drm_vblank_seq_type_t seqtype;
+       enum drm_vblank_seq_type seqtype;
        unsigned int sequence;
 } drm_i915_vblank_swap_t;
 
@@ -314,4 +322,44 @@ typedef struct drm_i915_mmio {
        void __user *data;      
 } drm_i915_mmio_t;
 
+typedef struct drm_i915_hws_addr {
+       uint64_t addr;
+} drm_i915_hws_addr_t;
+
+/*
+ * Relocation header is 4 uint32_ts
+ * 0 - (16-bit relocation type << 16)| 16 bit reloc count
+ * 1 - buffer handle for another list of relocs
+ * 2-3 - spare.
+ */
+#define I915_RELOC_HEADER 4
+
+/*
+ * type 0 relocation has 4-uint32_t stride
+ * 0 - offset into buffer
+ * 1 - delta to add in
+ * 2 - index into buffer list
+ * 3 - reserved (for optimisations later).
+ */
+#define I915_RELOC_TYPE_0 0
+#define I915_RELOC0_STRIDE 4
+
+struct drm_i915_op_arg {
+       uint64_t next;
+       uint32_t reloc_handle;
+       int handled;
+       union {
+               struct drm_bo_op_req req;
+               struct drm_bo_arg_rep rep;
+       } d;
+
+};
+
+struct drm_i915_execbuffer {
+       uint64_t ops_list;
+       uint32_t num_buffers;
+       struct drm_i915_batchbuffer batch;
+       struct drm_fence_arg fence_arg;
+};
+
 #endif                         /* _I915_DRM_H_ */
index e8a7be2..be3212d 100644 (file)
 #define DRIVER_DESC            "Intel Graphics"
 #define DRIVER_DATE            "20070209"
 
+#if defined(__linux__)
+#define I915_HAVE_FENCE
+#define I915_HAVE_BUFFER
+#endif
+
 /* Interface history:
  *
  * 1.1: Original.
  *      - Support vertical blank on secondary display pipe
  * 1.8: New ioctl for ARB_Occlusion_Query
  * 1.9: Usable page flipping and triple buffering
+ * 1.10: Plane/pipe disentangling
+ * 1.11: TTM superioctl
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           9
+#if defined(I915_HAVE_FENCE) && defined(I915_HAVE_BUFFER)
+#define DRIVER_MINOR           11
+#else
+#define DRIVER_MINOR           6
+#endif
 #define DRIVER_PATCHLEVEL      0
 
-#if defined(__linux__)
-#define I915_HAVE_FENCE
-#define I915_HAVE_BUFFER
+#ifdef I915_HAVE_BUFFER
+#define I915_MAX_VALIDATE_BUFFERS 4096
 #endif
 
-typedef struct _drm_i915_ring_buffer {
+struct drm_i915_ring_buffer {
        int tail_mask;
        unsigned long Start;
        unsigned long End;
@@ -70,35 +80,41 @@ typedef struct _drm_i915_ring_buffer {
        int tail;
        int space;
        drm_local_map_t map;
-} drm_i915_ring_buffer_t;
+};
 
 struct mem_block {
        struct mem_block *next;
        struct mem_block *prev;
        int start;
        int size;
-       DRMFILE filp;           /* 0: free, -1: heap, other: real files */
+       struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
 };
 
-typedef struct _drm_i915_vbl_swap {
+struct drm_i915_vbl_swap {
        struct list_head head;
        drm_drawable_t drw_id;
-       unsigned int pipe;
+       unsigned int plane;
        unsigned int sequence;
        int flip;
-} drm_i915_vbl_swap_t;
+};
 
-typedef struct drm_i915_private {
+struct drm_i915_private {
+       struct drm_buffer_object *ring_buffer;
        drm_local_map_t *sarea;
        drm_local_map_t *mmio_map;
 
-       drm_i915_sarea_t *sarea_priv;
-       drm_i915_ring_buffer_t ring;
+       unsigned long mmiobase;
+       unsigned long mmiolen;
+
+       struct drm_i915_sarea *sarea_priv;
+       struct drm_i915_ring_buffer ring;
 
-       drm_dma_handle_t *status_page_dmah;
+       struct drm_dma_handle *status_page_dmah;
        void *hw_status_page;
        dma_addr_t dma_status_page;
        uint32_t counter;
+       unsigned int status_gfx_addr;
+       drm_local_map_t hws_map;
 
        unsigned int cpp;
        int use_mi_batchbuffer_start;
@@ -112,7 +128,7 @@ typedef struct drm_i915_private {
        struct mem_block *agp_heap;
        unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
        int vblank_pipe;
-       spinlock_t user_irq_lock;
+       DRM_SPINTYPE user_irq_lock;
        int user_irq_refcount;
        int fence_irq_on;
        uint32_t irq_enable_reg;
@@ -126,11 +142,75 @@ typedef struct drm_i915_private {
 #endif
 #ifdef I915_HAVE_BUFFER
        void *agp_iomap;
+       unsigned int max_validate_buffers;
+       struct mutex cmdbuf_mutex;
 #endif
-       spinlock_t swaps_lock;
-       drm_i915_vbl_swap_t vbl_swaps;
+
+       DRM_SPINTYPE swaps_lock;
+       struct drm_i915_vbl_swap vbl_swaps;
        unsigned int swaps_pending;
-} drm_i915_private_t;
+
+       /* LVDS info */
+       int backlight_duty_cycle;  /* restore backlight to this value */
+       bool panel_wants_dither;
+       struct drm_display_mode *panel_fixed_mode;
+
+       /* Register state */
+       u32 saveDSPACNTR;
+       u32 saveDSPBCNTR;
+       u32 savePIPEACONF;
+       u32 savePIPEBCONF;
+       u32 savePIPEASRC;
+       u32 savePIPEBSRC;
+       u32 saveFPA0;
+       u32 saveFPA1;
+       u32 saveDPLL_A;
+       u32 saveDPLL_A_MD;
+       u32 saveHTOTAL_A;
+       u32 saveHBLANK_A;
+       u32 saveHSYNC_A;
+       u32 saveVTOTAL_A;
+       u32 saveVBLANK_A;
+       u32 saveVSYNC_A;
+       u32 saveDSPASTRIDE;
+       u32 saveDSPASIZE;
+       u32 saveDSPAPOS;
+       u32 saveDSPABASE;
+       u32 saveDSPASURF;
+       u32 saveFPB0;
+       u32 saveFPB1;
+       u32 saveDPLL_B;
+       u32 saveDPLL_B_MD;
+       u32 saveHTOTAL_B;
+       u32 saveHBLANK_B;
+       u32 saveHSYNC_B;
+       u32 saveVTOTAL_B;
+       u32 saveVBLANK_B;
+       u32 saveVSYNC_B;
+       u32 saveDSPBSTRIDE;
+       u32 saveDSPBSIZE;
+       u32 saveDSPBPOS;
+       u32 saveDSPBBASE;
+       u32 saveDSPBSURF;
+       u32 saveVCLK_DIVISOR_VGA0;
+       u32 saveVCLK_DIVISOR_VGA1;
+       u32 saveVCLK_POST_DIV;
+       u32 saveVGACNTRL;
+       u32 saveADPA;
+       u32 saveLVDS;
+       u32 saveDVOA;
+       u32 saveDVOB;
+       u32 saveDVOC;
+       u32 savePP_ON;
+       u32 savePP_OFF;
+       u32 savePP_CONTROL;
+       u32 savePP_CYCLE;
+       u32 savePFIT_CONTROL;
+       u32 savePaletteA[256];
+       u32 savePaletteB[256];
+       u32 saveSWF[17];
+       u32 saveBLC_PWM_CTL;
+};
 
 enum intel_chip_family {
        CHIP_I8XX = 0x01,
@@ -139,73 +219,96 @@ enum intel_chip_family {
        CHIP_I965 = 0x08,
 };
 
-extern drm_ioctl_desc_t i915_ioctls[];
+extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 
                                /* i915_dma.c */
-extern void i915_kernel_lost_context(drm_device_t * dev);
+extern void i915_kernel_lost_context(struct drm_device * dev);
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
-extern void i915_driver_lastclose(drm_device_t * dev);
-extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern int i915_driver_device_is_agp(drm_device_t * dev);
+extern int i915_driver_unload(struct drm_device *dev);
+extern void i915_driver_lastclose(struct drm_device * dev);
+extern void i915_driver_preclose(struct drm_device *dev,
+                                struct drm_file *file_priv);
+extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
-extern void i915_emit_breadcrumb(drm_device_t *dev);
-extern void i915_dispatch_flip(drm_device_t * dev, int pipes, int sync);
-extern int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush);
+extern void i915_emit_breadcrumb(struct drm_device *dev);
+extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
+extern int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush);
 extern int i915_driver_firstopen(struct drm_device *dev);
+extern int i915_do_cleanup_pageflip(struct drm_device *dev);
+extern int i915_dma_cleanup(struct drm_device *dev);
 
 /* i915_irq.c */
-extern int i915_irq_emit(DRM_IOCTL_ARGS);
-extern int i915_irq_wait(DRM_IOCTL_ARGS);
+extern int i915_irq_emit(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int i915_irq_wait(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
 
-extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
+extern void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe);
+extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i915_driver_irq_preinstall(drm_device_t * dev);
-extern void i915_driver_irq_postinstall(drm_device_t * dev);
-extern void i915_driver_irq_uninstall(drm_device_t * dev);
-extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
-extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
-extern int i915_emit_irq(drm_device_t * dev);
-extern void i915_user_irq_on(drm_i915_private_t *dev_priv);
-extern void i915_user_irq_off(drm_i915_private_t *dev_priv);
-extern int i915_vblank_swap(DRM_IOCTL_ARGS);
+extern void i915_driver_irq_preinstall(struct drm_device * dev);
+extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern void i915_driver_irq_uninstall(struct drm_device * dev);
+extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int i915_emit_irq(struct drm_device * dev);
+extern void i915_user_irq_on(struct drm_i915_private *dev_priv);
+extern void i915_user_irq_off(struct drm_i915_private *dev_priv);
+extern void i915_enable_interrupt (struct drm_device *dev);
+extern int i915_vblank_swap(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
 
 /* i915_mem.c */
-extern int i915_mem_alloc(DRM_IOCTL_ARGS);
-extern int i915_mem_free(DRM_IOCTL_ARGS);
-extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
-extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
+extern int i915_mem_alloc(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+extern int i915_mem_free(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int i915_mem_init_heap(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+extern int i915_mem_destroy_heap(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
 extern void i915_mem_takedown(struct mem_block **heap);
-extern void i915_mem_release(drm_device_t * dev,
-                            DRMFILE filp, struct mem_block *heap);
+extern void i915_mem_release(struct drm_device * dev,
+                            struct drm_file *file_priv,
+                            struct mem_block *heap);
 #ifdef I915_HAVE_FENCE
 /* i915_fence.c */
 
 
-extern void i915_fence_handler(drm_device_t *dev);
-extern int i915_fence_emit_sequence(drm_device_t *dev, uint32_t class,
+extern void i915_fence_handler(struct drm_device *dev);
+extern int i915_fence_emit_sequence(struct drm_device *dev, uint32_t class,
                                    uint32_t flags,
                                    uint32_t *sequence, 
                                    uint32_t *native_type);
-extern void i915_poke_flush(drm_device_t *dev, uint32_t class);
-extern int i915_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags);
+extern void i915_poke_flush(struct drm_device *dev, uint32_t class);
+extern int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags);
 #endif
 
 #ifdef I915_HAVE_BUFFER
 /* i915_buffer.c */
-extern drm_ttm_backend_t *i915_create_ttm_backend_entry(drm_device_t *dev);
-extern int i915_fence_types(drm_buffer_object_t *bo, uint32_t *class, uint32_t *type);
-extern int i915_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags);
-extern int i915_init_mem_type(drm_device_t *dev, uint32_t type,
-                              drm_mem_type_manager_t *man);
-extern uint32_t i915_evict_mask(drm_buffer_object_t *bo);
-extern int i915_move(drm_buffer_object_t *bo, int evict,
-               int no_wait, drm_bo_mem_reg_t *new_mem);
+extern struct drm_ttm_backend *i915_create_ttm_backend_entry(struct drm_device *dev);
+extern int i915_fence_types(struct drm_buffer_object *bo, uint32_t *fclass,
+                           uint32_t *type);
+extern int i915_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
+extern int i915_init_mem_type(struct drm_device *dev, uint32_t type,
+                              struct drm_mem_type_manager *man);
+extern uint32_t i915_evict_mask(struct drm_buffer_object *bo);
+extern int i915_move(struct drm_buffer_object *bo, int evict,
+               int no_wait, struct drm_bo_mem_reg *new_mem);
 
 #endif
 
+
+/* modesetting */
+extern void intel_modeset_init(struct drm_device *dev);
+extern void intel_modeset_cleanup(struct drm_device *dev);
+
+
 #define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
 #define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
 #define I915_READ16(reg)       DRM_READ16(dev_priv->mmio_map, (reg))
@@ -243,7 +346,30 @@ extern int i915_move(drm_buffer_object_t *bo, int evict,
        I915_WRITE(LP_RING + RING_TAIL, outring);                       \
 } while(0)
 
-extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+#define MI_NOOP        (0x00 << 23)
+
+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
+
+/*
+ * The Bridge device's PCI config space has information about the
+ * fb aperture size and the amount of pre-reserved memory.
+ */
+#define INTEL_GMCH_CTRL                0x52
+#define INTEL_GMCH_ENABLED     0x4
+#define INTEL_GMCH_MEM_MASK    0x1
+#define INTEL_GMCH_MEM_64M     0x1
+#define INTEL_GMCH_MEM_128M    0
+
+#define INTEL_855_GMCH_GMS_MASK                (0x7 << 4)
+#define INTEL_855_GMCH_GMS_DISABLED    (0x0 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_1M   (0x1 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_4M   (0x2 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_8M   (0x3 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_16M  (0x4 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_32M  (0x5 << 4)
+
+#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
 
 #define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
@@ -255,12 +381,27 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 #define MI_NO_WRITE_FLUSH    (1 << 2)
 #define MI_READ_FLUSH        (1 << 0)
 #define MI_EXE_FLUSH         (1 << 1)
+#define MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
+#define MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
+
+/* Packet to load a register value from the ring/batch command stream:
+ */
+#define CMD_MI_LOAD_REGISTER_IMM       ((0x22 << 23)|0x1)
 
 #define BB1_START_ADDR_MASK   (~0x7)
 #define BB1_PROTECTED         (1<<0)
 #define BB1_UNPROTECTED       (0<<0)
 #define BB2_END_ADDR_MASK     (~0x7)
 
+#define I915REG_HWS_PGA                0x02080
+
+/* Interrupt bits:
+ */
+#define USER_INT_FLAG    (1<<1)
+#define VSYNC_PIPEB_FLAG (1<<5)
+#define VSYNC_PIPEA_FLAG (1<<7)
+#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
+
 #define I915REG_HWSTAM         0x02098
 #define I915REG_INT_IDENTITY_R 0x020a4
 #define I915REG_INT_MASK_R     0x020a8
@@ -273,6 +414,63 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 #define I915_VBLANK_INTERRUPT_ENABLE   (1UL<<17)
 #define I915_VBLANK_CLEAR              (1UL<<1)
 
+#define GPIOA                  0x5010
+#define GPIOB                  0x5014
+#define GPIOC                  0x5018
+#define GPIOD                  0x501c
+#define GPIOE                  0x5020
+#define GPIOF                  0x5024
+#define GPIOG                  0x5028
+#define GPIOH                  0x502c
+# define GPIO_CLOCK_DIR_MASK           (1 << 0)
+# define GPIO_CLOCK_DIR_IN             (0 << 1)
+# define GPIO_CLOCK_DIR_OUT            (1 << 1)
+# define GPIO_CLOCK_VAL_MASK           (1 << 2)
+# define GPIO_CLOCK_VAL_OUT            (1 << 3)
+# define GPIO_CLOCK_VAL_IN             (1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE     (1 << 5)
+# define GPIO_DATA_DIR_MASK            (1 << 8)
+# define GPIO_DATA_DIR_IN              (0 << 9)
+# define GPIO_DATA_DIR_OUT             (1 << 9)
+# define GPIO_DATA_VAL_MASK            (1 << 10)
+# define GPIO_DATA_VAL_OUT             (1 << 11)
+# define GPIO_DATA_VAL_IN              (1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE      (1 << 13)
+
+/* p317, 319
+ */
+#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
+#define VCLK2_VCO_N        0x600a
+#define VCLK2_VCO_DIV_SEL  0x6012
+
+#define VCLK_DIVISOR_VGA0   0x6000
+#define VCLK_DIVISOR_VGA1   0x6004
+#define VCLK_POST_DIV      0x6010
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA1_PD_P2_DIV_4      (1 << 15)
+/** Overrides the p2 post divisor field */
+# define VGA1_PD_P1_DIV_2      (1 << 13)
+# define VGA1_PD_P1_SHIFT      8
+/** P1 value is 2 greater than this field */
+# define VGA1_PD_P1_MASK       (0x1f << 8)
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA0_PD_P2_DIV_4      (1 << 7)
+/** Overrides the p2 post divisor field */
+# define VGA0_PD_P1_DIV_2      (1 << 5)
+# define VGA0_PD_P1_SHIFT      0
+/** P1 value is 2 greater than this field */
+# define VGA0_PD_P1_MASK       (0x1f << 0)
+
+#define POST_DIV_SELECT        0x70
+#define POST_DIV_1             0x00
+#define POST_DIV_2             0x10
+#define POST_DIV_4             0x20
+#define POST_DIV_8             0x30
+#define POST_DIV_16            0x40
+#define POST_DIV_32            0x50
+#define VCO_LOOP_DIV_BY_4M     0x00
+#define VCO_LOOP_DIV_BY_16M    0x04
+
 #define SRX_INDEX              0x3c4
 #define SRX_DATA               0x3c5
 #define SR01                   1
@@ -281,6 +479,8 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 #define PPCR                   0x61204
 #define PPCR_ON                        (1<<0)
 
+#define DVOA                   0x61120
+#define DVOA_ON                        (1<<31)
 #define DVOB                   0x61140
 #define DVOB_ON                        (1<<31)
 #define DVOC                   0x61160
@@ -298,6 +498,10 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 #define NOPID                   0x2094
 #define LP_RING                0x2030
 #define HP_RING                0x2040
+/* The binner has its own ring buffer:
+ */
+#define HWB_RING               0x2400
+
 #define RING_TAIL                      0x00
 #define TAIL_ADDR              0x001FFFF8
 #define RING_HEAD                      0x04
@@ -316,11 +520,105 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 #define RING_VALID             0x00000001
 #define RING_INVALID           0x00000000
 
+/* Instruction parser error reg:
+ */
+#define IPEIR                  0x2088
+
+/* Scratch pad debug 0 reg:
+ */
+#define SCPD0                  0x209c
+
+/* Error status reg:
+ */
+#define ESR                    0x20b8
+
+/* Secondary DMA fetch address debug reg:
+ */
+#define DMA_FADD_S             0x20d4
+
+/* Cache mode 0 reg.  
+ *  - Manipulating render cache behaviour is central
+ *    to the concept of zone rendering, tuning this reg can help avoid
+ *    unnecessary render cache reads and even writes (for z/stencil)
+ *    at beginning and end of scene.
+ *
+ * - To change a bit, write to this reg with a mask bit set and the
+ * bit of interest either set or cleared.  EG: (BIT<<16) | BIT to set.
+ */
+#define Cache_Mode_0           0x2120
+#define CM0_MASK_SHIFT          16
+#define CM0_IZ_OPT_DISABLE      (1<<6)
+#define CM0_ZR_OPT_DISABLE      (1<<5)
+#define CM0_DEPTH_EVICT_DISABLE (1<<4)
+#define CM0_COLOR_EVICT_DISABLE (1<<3)
+#define CM0_DEPTH_WRITE_DISABLE (1<<1)
+#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
+
+
+/* Graphics flush control.  A CPU write flushes the GWB of all writes.
+ * The data is discarded.
+ */
+#define GFX_FLSH_CNTL          0x2170
+
+/* Binner control.  Defines the location of the bin pointer list:
+ */
+#define BINCTL                 0x2420
+#define BC_MASK                        (1 << 9)
+
+/* Binned scene info.  
+ */
+#define BINSCENE               0x2428
+#define BS_OP_LOAD             (1 << 8)
+#define BS_MASK                        (1 << 22)
+
+/* Bin command parser debug reg:
+ */
+#define BCPD                   0x2480
+
+/* Bin memory control debug reg:
+ */
+#define BMCD                   0x2484
+
+/* Bin data cache debug reg:
+ */
+#define BDCD                   0x2488
+
+/* Binner pointer cache debug reg: 
+ */
+#define BPCD                   0x248c
+
+/* Binner scratch pad debug reg:
+ */
+#define BINSKPD                        0x24f0
+
+/* HWB scratch pad debug reg:
+ */
+#define HWBSKPD                        0x24f4
+
+/* Binner memory pool reg:
+ */
+#define BMP_BUFFER             0x2430
+#define BMP_PAGE_SIZE_4K       (0 << 10)
+#define BMP_BUFFER_SIZE_SHIFT  1
+#define BMP_ENABLE             (1 << 0)
+
+/* Get/put memory from the binner memory pool:
+ */
+#define BMP_GET                        0x2438
+#define BMP_PUT                        0x2440
+#define BMP_OFFSET_SHIFT       5
+
+/* 3D state packets:
+ */
+#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
+
 #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_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
+
 #define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
 #define SCI_YMIN_MASK      (0xffff<<16)
 #define SCI_XMIN_MASK      (0xffff<<0)
@@ -339,14 +637,22 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 
 #define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
 #define XY_SRC_COPY_BLT_CMD            ((2<<29)|(0x53<<22)|6)
+#define XY_MONO_SRC_COPY_IMM_BLT       ((2<<29)|(0x71<<22)|5)
 #define XY_SRC_COPY_BLT_WRITE_ALPHA    (1<<21)
 #define XY_SRC_COPY_BLT_WRITE_RGB      (1<<20)
+#define   BLT_DEPTH_8                  (0<<24)
+#define   BLT_DEPTH_16_565             (1<<24)
+#define   BLT_DEPTH_16_1555            (2<<24)
+#define   BLT_DEPTH_32                 (3<<24)
+#define   BLT_ROP_GXCOPY               (0xcc<<16)
 
 #define MI_BATCH_BUFFER        ((0x30<<23)|1)
 #define MI_BATCH_BUFFER_START  (0x31<<23)
 #define MI_BATCH_BUFFER_END    (0xA<<23)
 #define MI_BATCH_NON_SECURE    (1)
 
+#define MI_BATCH_NON_SECURE_I965 (1<<8)
+
 #define MI_WAIT_FOR_EVENT       ((0x3<<23))
 #define MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
 #define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
@@ -359,8 +665,522 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
 #define DISPLAY_PLANE_A           (0<<20)
 #define DISPLAY_PLANE_B           (1<<20)
 
+/* Display regs */
+#define DSPACNTR                0x70180
+#define DSPBCNTR                0x71180
+#define DISPPLANE_SEL_PIPE_MASK                 (1<<24)
+
+/* Define the region of interest for the binner:
+ */
+#define CMD_OP_BIN_CONTROL      ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
+
 #define CMD_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
 
+#define BREADCRUMB_BITS 31
+#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
+
 #define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
 #define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
+
+#define BLC_PWM_CTL            0x61254
+#define BACKLIGHT_MODULATION_FREQ_SHIFT                (17)
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK         (0x7fff << 17)
+#define BLM_LEGACY_MODE                                (1 << 16)
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT             (0)
+#define BACKLIGHT_DUTY_CYCLE_MASK              (0xffff)
+
+#define I915_GCFGC                     0xf0
+#define I915_LOW_FREQUENCY_ENABLE              (1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ         (0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ             (4 << 4)
+#define I915_DISPLAY_CLOCK_MASK                        (7 << 4)
+
+#define I855_HPLLCC                    0xc0
+#define I855_CLOCK_CONTROL_MASK                        (3 << 0)
+#define I855_CLOCK_133_200                     (0 << 0)
+#define I855_CLOCK_100_200                     (1 << 0)
+#define I855_CLOCK_100_133                     (2 << 0)
+#define I855_CLOCK_166_250                     (3 << 0)
+
+/* I830 CRTC registers */
+#define HTOTAL_A       0x60000
+#define HBLANK_A       0x60004
+#define HSYNC_A        0x60008
+#define VTOTAL_A       0x6000c
+#define VBLANK_A       0x60010
+#define VSYNC_A        0x60014
+#define PIPEASRC       0x6001c
+#define BCLRPAT_A      0x60020
+#define VSYNCSHIFT_A   0x60028
+
+#define HTOTAL_B       0x61000
+#define HBLANK_B       0x61004
+#define HSYNC_B        0x61008
+#define VTOTAL_B       0x6100c
+#define VBLANK_B       0x61010
+#define VSYNC_B        0x61014
+#define PIPEBSRC       0x6101c
+#define BCLRPAT_B      0x61020
+#define VSYNCSHIFT_B   0x61028
+
+#define PP_STATUS      0x61200
+# define PP_ON                                 (1 << 31)
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY                              (1 << 30)
+# define PP_SEQUENCE_NONE                      (0 << 28)
+# define PP_SEQUENCE_ON                                (1 << 28)
+# define PP_SEQUENCE_OFF                       (2 << 28)
+# define PP_SEQUENCE_MASK                      0x30000000
+#define PP_CONTROL     0x61204
+# define POWER_TARGET_ON                       (1 << 0)
+
+#define LVDSPP_ON       0x61208
+#define LVDSPP_OFF      0x6120c
+#define PP_CYCLE        0x61210
+
+#define PFIT_CONTROL   0x61230
+# define PFIT_ENABLE                           (1 << 31)
+# define PFIT_PIPE_MASK                                (3 << 29)
+# define PFIT_PIPE_SHIFT                       29
+# define VERT_INTERP_DISABLE                   (0 << 10)
+# define VERT_INTERP_BILINEAR                  (1 << 10)
+# define VERT_INTERP_MASK                      (3 << 10)
+# define VERT_AUTO_SCALE                       (1 << 9)
+# define HORIZ_INTERP_DISABLE                  (0 << 6)
+# define HORIZ_INTERP_BILINEAR                 (1 << 6)
+# define HORIZ_INTERP_MASK                     (3 << 6)
+# define HORIZ_AUTO_SCALE                      (1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE              (1 << 3)
+
+#define PFIT_PGM_RATIOS        0x61234
+# define PFIT_VERT_SCALE_MASK                  0xfff00000
+# define PFIT_HORIZ_SCALE_MASK                 0x0000fff0
+
+#define PFIT_AUTO_RATIOS       0x61238
+
+
+#define DPLL_A         0x06014
+#define DPLL_B         0x06018
+# define DPLL_VCO_ENABLE                       (1 << 31)
+# define DPLL_DVO_HIGH_SPEED                   (1 << 30)
+# define DPLL_SYNCLOCK_ENABLE                  (1 << 29)
+# define DPLL_VGA_MODE_DIS                     (1 << 28)
+# define DPLLB_MODE_DAC_SERIAL                 (1 << 26) /* i915 */
+# define DPLLB_MODE_LVDS                       (2 << 26) /* i915 */
+# define DPLL_MODE_MASK                                (3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10       (0 << 24) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5                (1 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14            (0 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7             (1 << 24) /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK                        0x03000000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK           0x00ff0000 /* i915 */
+/**
+ *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830      0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+# define DPLL_FPA01_P1_POST_DIV_SHIFT          16
+# define PLL_P2_DIVIDE_BY_4                    (1 << 23) /* i830, required in DVO non-gang */
+# define PLL_P1_DIVIDE_BY_TWO                  (1 << 21) /* i830 */
+# define PLL_REF_INPUT_DREFCLK                 (0 << 13)
+# define PLL_REF_INPUT_TVCLKINA                        (1 << 13) /* i830 */
+# define PLL_REF_INPUT_TVCLKINBC               (2 << 13) /* SDVO TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN       (3 << 13)
+# define PLL_REF_INPUT_MASK                    (3 << 13)
+# define PLL_LOAD_PULSE_PHASE_SHIFT            9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK             (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1              (1 << 8)
+
+/**
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK                  0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES           4
+# define SDVO_MULTIPLIER_SHIFT_VGA             0
+
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD              0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD              0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK              0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT             24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK          0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT         16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK           0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT          8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. 
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK       0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT      0
+/** @} */
+
+#define DPLL_TEST              0x606c
+# define DPLLB_TEST_SDVO_DIV_1                 (0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2                 (1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4                 (2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK              (3 << 22)
+# define DPLLB_TEST_N_BYPASS                   (1 << 19)
+# define DPLLB_TEST_M_BYPASS                   (1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE             (1 << 16)
+# define DPLLA_TEST_N_BYPASS                   (1 << 3)
+# define DPLLA_TEST_M_BYPASS                   (1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE             (1 << 0)
+
+#define ADPA                   0x61100
+#define ADPA_DAC_ENABLE        (1<<31)
+#define ADPA_DAC_DISABLE       0
+#define ADPA_PIPE_SELECT_MASK  (1<<30)
+#define ADPA_PIPE_A_SELECT     0
+#define ADPA_PIPE_B_SELECT     (1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY   0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE 0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE 0
+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW  0
+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW  0
+
+#define FPA0           0x06040
+#define FPA1           0x06044
+#define FPB0           0x06048
+#define FPB1           0x0604c
+# define FP_N_DIV_MASK                         0x003f0000
+# define FP_N_DIV_SHIFT                                16
+# define FP_M1_DIV_MASK                                0x00003f00
+# define FP_M1_DIV_SHIFT                       8
+# define FP_M2_DIV_MASK                                0x0000003f
+# define FP_M2_DIV_SHIFT                       0
+
+
+#define PORT_HOTPLUG_EN                0x61110
+# define SDVOB_HOTPLUG_INT_EN                  (1 << 26)
+# define SDVOC_HOTPLUG_INT_EN                  (1 << 25)
+# define TV_HOTPLUG_INT_EN                     (1 << 18)
+# define CRT_HOTPLUG_INT_EN                    (1 << 9)
+# define CRT_HOTPLUG_FORCE_DETECT              (1 << 3)
+
+#define PORT_HOTPLUG_STAT      0x61114
+# define CRT_HOTPLUG_INT_STATUS                        (1 << 11)
+# define TV_HOTPLUG_INT_STATUS                 (1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK              (3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR             (3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO              (2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE              (0 << 8)
+# define SDVOC_HOTPLUG_INT_STATUS              (1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS              (1 << 6)
+
+#define SDVOB                  0x61140
+#define SDVOC                  0x61160
+#define SDVO_ENABLE                            (1 << 31)
+#define SDVO_PIPE_B_SELECT                     (1 << 30)
+#define SDVO_STALL_SELECT                      (1 << 29)
+#define SDVO_INTERRUPT_ENABLE                  (1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK                        (7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT               23
+#define SDVO_PHASE_SELECT_MASK                 (15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT              (6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT               (1 << 18)
+#define SDVOC_GANG_MODE                                (1 << 16)
+#define SDVO_BORDER_ENABLE                     (1 << 7)
+#define SDVOB_PCIE_CONCURRENCY                 (1 << 3)
+#define SDVO_DETECTED                          (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK                    ((1 << 17) | (1 << 16) | (1 << 14))
+#define SDVOC_PRESERVE_MASK                    (1 << 17)
+
+/** @defgroup LVDS
+ * @{
+ */
+/**
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
+#define LVDS                   0x61180
+/**
+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+# define LVDS_PORT_EN                  (1 << 31)
+/** Selects pipe B for LVDS data.  Must be set on pre-965. */
+# define LVDS_PIPEB_SELECT             (1 << 30)
+
+/**
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK     (3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN     (0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP       (3 << 8)
+/**
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK            (3 << 6)
+# define LVDS_A3_POWER_DOWN            (0 << 6)
+# define LVDS_A3_POWER_UP              (3 << 6)
+/**
+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK          (3 << 4)
+# define LVDS_CLKB_POWER_DOWN          (0 << 4)
+# define LVDS_CLKB_POWER_UP            (3 << 4)
+
+/**
+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode.  The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK          (3 << 2)
+# define LVDS_B0B3_POWER_DOWN          (0 << 2)
+# define LVDS_B0B3_POWER_UP            (3 << 2)
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE       (1<<31)
+#define PIPEACONF_DISABLE      0
+#define PIPEACONF_DOUBLE_WIDE  (1<<30)
+#define I965_PIPECONF_ACTIVE   (1<<30)
+#define PIPEACONF_SINGLE_WIDE  0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_PIPE_LOCKED  (1<<25)
+#define PIPEACONF_PALETTE      0
+#define PIPEACONF_GAMMA        (1<<24)
+#define PIPECONF_FORCE_BORDER  (1<<25)
+#define PIPECONF_PROGRESSIVE   (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION  (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY                (7 << 21)
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE       (1<<31)
+#define PIPEBCONF_DISABLE      0
+#define PIPEBCONF_DOUBLE_WIDE  (1<<30)
+#define PIPEBCONF_DISABLE      0
+#define PIPEBCONF_GAMMA        (1<<24)
+#define PIPEBCONF_PALETTE      0
+
+#define PIPEBGCMAXRED          0x71010
+#define PIPEBGCMAXGREEN                0x71014
+#define PIPEBGCMAXBLUE         0x71018
+#define PIPEBSTAT              0x71024
+#define PIPEBFRAMEHIGH         0x71040
+#define PIPEBFRAMEPIXEL                0x71044
+
+#define DSPACNTR               0x70180
+#define DSPBCNTR               0x71180
+#define DISPLAY_PLANE_ENABLE                   (1<<31)
+#define DISPLAY_PLANE_DISABLE                  0
+#define DISPPLANE_GAMMA_ENABLE                 (1<<30)
+#define DISPPLANE_GAMMA_DISABLE                        0
+#define DISPPLANE_PIXFORMAT_MASK               (0xf<<26)
+#define DISPPLANE_8BPP                         (0x2<<26)
+#define DISPPLANE_15_16BPP                     (0x4<<26)
+#define DISPPLANE_16BPP                                (0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA               (0x6<<26)
+#define DISPPLANE_32BPP                                (0x7<<26)
+#define DISPPLANE_STEREO_ENABLE                        (1<<25)
+#define DISPPLANE_STEREO_DISABLE               0
+#define DISPPLANE_SEL_PIPE_MASK                        (1<<24)
+#define DISPPLANE_SEL_PIPE_A                   0
+#define DISPPLANE_SEL_PIPE_B                   (1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE               (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE              0
+#define DISPPLANE_LINE_DOUBLE                  (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE               0
+#define DISPPLANE_STEREO_POLARITY_FIRST                0
+#define DISPPLANE_STEREO_POLARITY_SECOND       (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE           (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE          0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA                0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY         (1)
+
+#define DSPABASE               0x70184
+#define DSPASTRIDE             0x70188
+
+#define DSPBBASE               0x71184
+#define DSPBADDR               DSPBBASE
+#define DSPBSTRIDE             0x71188
+
+#define DSPAKEYVAL             0x70194
+#define DSPAKEYMASK            0x70198
+
+#define DSPAPOS                        0x7018C /* reserved */
+#define DSPASIZE               0x70190
+#define DSPBPOS                        0x7118C
+#define DSPBSIZE               0x71190
+
+#define DSPASURF               0x7019C
+#define DSPATILEOFF            0x701A4
+
+#define DSPBSURF               0x7119C
+#define DSPBTILEOFF            0x711A4
+
+#define VGACNTRL               0x71400
+# define VGA_DISP_DISABLE                      (1 << 31)
+# define VGA_2X_MODE                           (1 << 30)
+# define VGA_PIPE_B_SELECT                     (1 << 29)
+
+/*
+ * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */
+
+#define SWF0                   0x71410
+#define SWF1                   0x71414
+#define SWF2                   0x71418
+#define SWF3                   0x7141c
+#define SWF4                   0x71420
+#define SWF5                   0x71424
+#define SWF6                   0x71428
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF00                  0x70410
+#define SWF01                  0x70414
+#define SWF02                  0x70418
+#define SWF03                  0x7041c
+#define SWF04                  0x70420
+#define SWF05                  0x70424
+#define SWF06                  0x70428
+
+#define SWF10                  SWF0
+#define SWF11                  SWF1
+#define SWF12                  SWF2
+#define SWF13                  SWF3
+#define SWF14                  SWF4
+#define SWF15                  SWF5
+#define SWF16                  SWF6
+
+#define SWF30                  0x72414
+#define SWF31                  0x72418
+#define SWF32                  0x7241c
+
+/*
+ * Overlay registers.  These are overlay registers accessed via MMIO.
+ * Those loaded via the overlay register page are defined in i830_video.c.
+ */
+#define OVADD                  0x30000
+
+#define DOVSTA                 0x30008
+#define OC_BUF                 (0x3<<20)
+
+#define OGAMC5                 0x30010
+#define OGAMC4                 0x30014
+#define OGAMC3                 0x30018
+#define OGAMC2                 0x3001c
+#define OGAMC1                 0x30020
+#define OGAMC0                 0x30024
+
+/*
+ * Palette registers
+ */
+#define PALETTE_A              0x0a000
+#define PALETTE_B              0x0a800
+
+#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC)
+#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG)
+#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG)
+
+#define IS_I915G(dev) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG)/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G)*/
+#define IS_I915GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG)
+#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG)
+#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG)
+
+#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
+                      (dev)->pci_device == 0x2982 || \
+                      (dev)->pci_device == 0x2992 || \
+                      (dev)->pci_device == 0x29A2 || \
+                      (dev)->pci_device == 0x2A02 || \
+                      (dev)->pci_device == 0x2A12)
+
+#define IS_I965GM(dev) (((dev)->pci_device == 0x2A02))
+
+#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
+                     IS_I945GM(dev) || IS_I965G(dev))
+
+#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 || \
+                       (dev)->pci_device == 0x29B2 || \
+                       (dev)->pci_device == 0x29D2) 
+
+#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
+                       IS_I945GM(dev) || IS_I965GM(dev))
+
+#define PRIMARY_RINGBUFFER_SIZE         (128*1024)
+
 #endif
diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c
new file mode 100644 (file)
index 0000000..3b43c72
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2007 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+ *                   2004 Sylvain Meyer
+ *
+ * GPL/BSD dual license
+ */
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/**
+ * i915_probe_agp - get AGP bootup configuration
+ * @pdev: PCI device
+ * @aperture_size: returns AGP aperture configured size
+ * @preallocated_size: returns size of BIOS preallocated AGP space
+ *
+ * Since Intel integrated graphics are UMA, the BIOS has to set aside
+ * some RAM for the framebuffer at early boot.  This code figures out
+ * how much was set aside so we can use it for our own purposes.
+ */
+int i915_probe_agp(struct pci_dev *pdev, unsigned long *aperture_size,
+                  unsigned long *preallocated_size)
+{
+       struct pci_dev *bridge_dev;
+       u16 tmp = 0;
+       unsigned long overhead;
+
+       bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+       if (!bridge_dev) {
+               DRM_ERROR("bridge device not found\n");
+               return -1;
+       }
+
+       /* Get the fb aperture size and "stolen" memory amount. */
+       pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
+       pci_dev_put(bridge_dev);
+
+       *aperture_size = 1024 * 1024;
+       *preallocated_size = 1024 * 1024;
+
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_INTEL_82830_CGC:
+       case PCI_DEVICE_ID_INTEL_82845G_IG:
+       case PCI_DEVICE_ID_INTEL_82855GM_IG:
+       case PCI_DEVICE_ID_INTEL_82865_IG:
+               if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
+                       *aperture_size *= 64;
+               else
+                       *aperture_size *= 128;
+               break;
+       default:
+               /* 9xx supports large sizes, just look at the length */
+               *aperture_size = pci_resource_len(pdev, 2);
+               break;
+       }
+
+       /*
+        * Some of the preallocated space is taken by the GTT
+        * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
+        */
+       overhead = (*aperture_size / 1024) + 4096;
+       switch (tmp & INTEL_855_GMCH_GMS_MASK) {
+       case INTEL_855_GMCH_GMS_STOLEN_1M:
+               break; /* 1M already */
+       case INTEL_855_GMCH_GMS_STOLEN_4M:
+               *preallocated_size *= 4;
+               break;
+       case INTEL_855_GMCH_GMS_STOLEN_8M:
+               *preallocated_size *= 8;
+               break;
+       case INTEL_855_GMCH_GMS_STOLEN_16M:
+               *preallocated_size *= 16;
+               break;
+       case INTEL_855_GMCH_GMS_STOLEN_32M:
+               *preallocated_size *= 32;
+               break;
+       case INTEL_915G_GMCH_GMS_STOLEN_48M:
+               *preallocated_size *= 48;
+               break;
+       case INTEL_915G_GMCH_GMS_STOLEN_64M:
+               *preallocated_size *= 64;
+               break;
+       case INTEL_855_GMCH_GMS_DISABLED:
+               DRM_ERROR("video memory is disabled\n");
+               return -1;
+       default:
+               DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
+                       tmp & INTEL_855_GMCH_GMS_MASK);
+               return -1;
+       }
+       *preallocated_size -= overhead;
+
+       return 0;
+}
+
+/**
+ * i915_driver_load - setup chip and create an initial config
+ * @dev: DRM device
+ * @flags: startup flags
+ *
+ * The driver load routine has to do several things:
+ *   - drive output discovery via intel_modeset_init()
+ *   - initialize the memory manager
+ *   - allocate initial config memory
+ *   - setup the DRM framebuffer with the allocated memory
+ */
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       struct drm_i915_private *dev_priv;
+       unsigned long agp_size, prealloc_size;
+       unsigned long sareapage;
+       int size, ret;
+
+       dev_priv = drm_alloc(sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv, 0, sizeof(struct drm_i915_private));
+       dev->dev_private = (void *)dev_priv;
+//     dev_priv->flags = flags;
+
+       /* i915 has 4 more counters */
+       dev->counters += 4;
+       dev->types[6] = _DRM_STAT_IRQ;
+       dev->types[7] = _DRM_STAT_PRIMARY;
+       dev->types[8] = _DRM_STAT_SECONDARY;
+       dev->types[9] = _DRM_STAT_DMA;
+
+       if (IS_I9XX(dev)) {
+               dev_priv->mmiobase = drm_get_resource_start(dev, 0);
+               dev_priv->mmiolen = drm_get_resource_len(dev, 0);
+               dev->mode_config.fb_base =
+                       drm_get_resource_start(dev, 2) & 0xff000000;
+       } else if (drm_get_resource_start(dev, 1)) {
+               dev_priv->mmiobase = drm_get_resource_start(dev, 1);
+               dev_priv->mmiolen = drm_get_resource_len(dev, 1);
+               dev->mode_config.fb_base =
+                       drm_get_resource_start(dev, 0) & 0xff000000;
+       } else {
+               DRM_ERROR("Unable to find MMIO registers\n");
+               return -ENODEV;
+       }
+
+       DRM_DEBUG("fb_base: 0x%08lx\n", dev->mode_config.fb_base);
+
+       ret = drm_addmap(dev, dev_priv->mmiobase, dev_priv->mmiolen,
+                        _DRM_REGISTERS, _DRM_READ_ONLY|_DRM_DRIVER, &dev_priv->mmio_map);
+       if (ret != 0) {
+               DRM_ERROR("Cannot add mapping for MMIO registers\n");
+               return ret;
+       }
+
+       /* prebuild the SAREA */
+       sareapage = max(SAREA_MAX, PAGE_SIZE);
+       ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
+                        &dev_priv->sarea);
+       if (ret) {
+               DRM_ERROR("SAREA setup failed\n");
+               return ret;
+       }
+
+       init_waitqueue_head(&dev->lock.lock_queue);
+
+       /* FIXME: assume sarea_priv is right after SAREA */
+        dev_priv->sarea_priv = dev_priv->sarea->handle + sizeof(struct drm_sarea);
+
+       /*
+        * Initialize the memory manager for local and AGP space
+        */
+       drm_bo_driver_init(dev);
+
+       i915_probe_agp(dev->pdev, &agp_size, &prealloc_size);
+       printk("setting up %ld bytes of VRAM space\n", prealloc_size);
+       printk("setting up %ld bytes of TT space\n", (agp_size - prealloc_size));
+       drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, prealloc_size >> PAGE_SHIFT);
+       drm_bo_init_mm(dev, DRM_BO_MEM_TT, prealloc_size >> PAGE_SHIFT, (agp_size - prealloc_size) >> PAGE_SHIFT);
+
+       I915_WRITE(LP_RING + RING_LEN, 0);
+       I915_WRITE(LP_RING + RING_HEAD, 0);
+       I915_WRITE(LP_RING + RING_TAIL, 0);
+
+       size = PRIMARY_RINGBUFFER_SIZE;
+       ret = drm_buffer_object_create(dev, size, drm_bo_type_kernel,
+                                      DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
+                                      DRM_BO_FLAG_MEM_VRAM |
+                                      DRM_BO_FLAG_NO_EVICT |
+                                      DRM_BO_HINT_DONT_FENCE, 0, 0x1, 0,
+                                      &dev_priv->ring_buffer);
+       if (ret < 0) {
+               DRM_ERROR("Unable to allocate or pin ring buffer\n");
+               return -EINVAL;
+       }
+
+       /* remap the buffer object properly */
+       dev_priv->ring.Start = dev_priv->ring_buffer->offset;
+       dev_priv->ring.End = dev_priv->ring.Start + size;
+       dev_priv->ring.Size = size;
+       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+       /* FIXME: need wrapper with PCI mem checks */
+       ret = drm_mem_reg_ioremap(dev, &dev_priv->ring_buffer->mem,
+                                 (void **) &dev_priv->ring.virtual_start);
+       if (ret)
+               DRM_ERROR("error mapping ring buffer: %d\n", ret);
+
+       DRM_DEBUG("ring start %08lX, %p, %08lX\n", dev_priv->ring.Start,
+                 dev_priv->ring.virtual_start, dev_priv->ring.Size);
+
+       dev_priv->sarea_priv->pf_current_page = 0;
+
+       memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size);
+
+       I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start);
+       I915_WRITE(LP_RING + RING_LEN,
+                  ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) |
+                  (RING_NO_REPORT | RING_VALID));
+
+       /* We are using separate values as placeholders for mechanisms for
+        * private backbuffer/depthbuffer usage.
+        */
+       dev_priv->use_mi_batchbuffer_start = 0;
+
+       /* Allow hardware batchbuffers unless told otherwise.
+        */
+       dev_priv->allow_batchbuffer = 1;
+
+       /* Program Hardware Status Page */
+       if (!IS_G33(dev)) {
+               dev_priv->status_page_dmah = 
+                       drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+               if (!dev_priv->status_page_dmah) {
+                       dev->dev_private = (void *)dev_priv;
+                       i915_dma_cleanup(dev);
+                       DRM_ERROR("Can not allocate hardware status page\n");
+                       return -ENOMEM;
+               }
+               dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+               dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
+               memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+
+               I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page);
+       }
+       DRM_DEBUG("Enabled hardware status page\n");
+
+       intel_modeset_init(dev);
+       drm_initial_config(dev, false);
+
+       return 0;
+}
+
+int i915_driver_unload(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->ring.virtual_start) {
+               drm_core_ioremapfree(&dev_priv->ring.map, dev);
+       }
+
+       if (dev_priv->status_page_dmah) {
+               drm_pci_free(dev, dev_priv->status_page_dmah);
+               dev_priv->status_page_dmah = NULL;
+               dev_priv->hw_status_page = NULL;
+               dev_priv->dma_status_page = 0;
+               /* Need to rewrite hardware status page */
+               I915_WRITE(I915REG_HWS_PGA, 0x1ffff000);
+       }
+
+       if (dev_priv->status_gfx_addr) {
+               dev_priv->status_gfx_addr = 0;
+               drm_core_ioremapfree(&dev_priv->hws_map, dev);
+               I915_WRITE(I915REG_HWS_PGA, 0x1ffff000);
+       }
+
+       I915_WRITE(LP_RING + RING_LEN, 0);
+
+       intel_modeset_cleanup(dev);
+
+       drm_mem_reg_iounmap(dev, &dev_priv->ring_buffer->mem,
+                           dev_priv->ring.virtual_start);
+
+       DRM_DEBUG("usage is %d\n", atomic_read(&dev_priv->ring_buffer->usage));
+       mutex_lock(&dev->struct_mutex);
+       drm_bo_usage_deref_locked(&dev_priv->ring_buffer);
+
+       if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT)) {
+               DRM_ERROR("Memory manager type 3 not clean. "
+                         "Delaying takedown\n");
+       }
+       if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM)) {
+               DRM_ERROR("Memory manager type 3 not clean. "
+                         "Delaying takedown\n");
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       drm_bo_driver_finish(dev);
+
+        DRM_DEBUG("%p, %p\n", dev_priv->mmio_map, dev_priv->sarea);
+        drm_rmmap(dev, dev_priv->mmio_map);
+        drm_rmmap(dev, dev_priv->sarea);
+
+       drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+
+       dev->dev_private = NULL;
+       return 0;
+}
+
+void i915_driver_lastclose(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       i915_do_cleanup_pageflip(dev);
+       //i915_mem_takedown(&(dev_priv->agp_heap));
+       i915_dma_cleanup(dev);
+}
+
+void i915_driver_preclose(struct drm_device *dev, struct drm_file *filp)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       //i915_mem_release(dev, filp, dev_priv->agp_heap);
+}
+
index dc00f98..11cb20a 100644 (file)
 #define MAX_NOPID ((u32)~0)
 
 /**
+ * i915_get_pipe - return the the pipe associated with a given plane
+ * @dev: DRM device
+ * @plane: plane to look for
+ *
+ * We need to get the pipe associated with a given plane to correctly perform
+ * vblank driven swapping, and they may not always be equal.  So look up the
+ * pipe associated with @plane here.
+ */
+static int
+i915_get_pipe(struct drm_device *dev, int plane)
+{
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+       u32 dspcntr;
+
+       dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
+
+       return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
+}
+
+/**
  * Emit a synchronous flip.
  *
  * This function must be called with the drawable spinlock held.
  */
 static void
-i915_dispatch_vsync_flip(drm_device_t *dev, drm_drawable_info_t *drw, int pipe)
+i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
+                        int plane)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+       struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv;
        u16 x1, y1, x2, y2;
-       int pf_pipes = 1 << pipe;
+       int pf_planes = 1 << plane;
+
+       DRM_SPINLOCK_ASSERT(&dev->drw_lock);
 
-       /* If the window is visible on the other pipe, we have to flip on that
-        * pipe as well.
+       /* If the window is visible on the other plane, we have to flip on that
+        * plane as well.
         */
-       if (pipe == 1) {
-               x1 = sarea_priv->pipeA_x;
-               y1 = sarea_priv->pipeA_y;
-               x2 = x1 + sarea_priv->pipeA_w;
-               y2 = y1 + sarea_priv->pipeA_h;
+       if (plane == 1) {
+               x1 = sarea_priv->planeA_x;
+               y1 = sarea_priv->planeA_y;
+               x2 = x1 + sarea_priv->planeA_w;
+               y2 = y1 + sarea_priv->planeA_h;
        } else {
-               x1 = sarea_priv->pipeB_x;
-               y1 = sarea_priv->pipeB_y;
-               x2 = x1 + sarea_priv->pipeB_w;
-               y2 = y1 + sarea_priv->pipeB_h;
+               x1 = sarea_priv->planeB_x;
+               y1 = sarea_priv->planeB_y;
+               x2 = x1 + sarea_priv->planeB_w;
+               y2 = y1 + sarea_priv->planeB_h;
        }
 
        if (x2 > 0 && y2 > 0) {
                int i, num_rects = drw->num_rects;
-               drm_clip_rect_t *rect = drw->rects;
+               struct drm_clip_rect *rect = drw->rects;
 
                for (i = 0; i < num_rects; i++)
                        if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 ||
                              rect[i].x2 <= x1 || rect[i].y2 <= y1)) {
-                               pf_pipes = 0x3;
+                               pf_planes = 0x3;
 
                                break;
                        }
        }
 
-       i915_dispatch_flip(dev, pf_pipes, 1);
+       i915_dispatch_flip(dev, pf_planes, 1);
 }
 
 /**
@@ -86,16 +109,15 @@ i915_dispatch_vsync_flip(drm_device_t *dev, drm_drawable_info_t *drw, int pipe)
  *
  * This function will be called with the HW lock held.
  */
-static void i915_vblank_tasklet(drm_device_t *dev)
+static void i915_vblank_tasklet(struct drm_device *dev)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        struct list_head *list, *tmp, hits, *hit;
        int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
        unsigned counter[2] = { atomic_read(&dev->vbl_received),
                                atomic_read(&dev->vbl_received2) };
-       drm_drawable_info_t *drw;
-       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_drawable_info *drw;
+       struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv;
        u32 cpp = dev_priv->cpp,  offsets[3];
        u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
                                XY_SRC_COPY_BLT_WRITE_ALPHA |
@@ -111,35 +133,41 @@ static void i915_vblank_tasklet(drm_device_t *dev)
 
        nhits = nrects = 0;
 
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+       /* No irqsave/restore necessary.  This tasklet may be run in an
+        * interrupt context or normal context, but we don't have to worry
+        * about getting interrupted by something acquiring the lock, because
+        * we are the interrupt context thing that acquires the lock.
+        */
+       DRM_SPINLOCK(&dev_priv->swaps_lock);
 
        /* Find buffer swaps scheduled for this vertical blank */
        list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
-               drm_i915_vbl_swap_t *vbl_swap =
-                       list_entry(list, drm_i915_vbl_swap_t, head);
+               struct drm_i915_vbl_swap *vbl_swap =
+                       list_entry(list, struct drm_i915_vbl_swap, head);
+               int pipe = i915_get_pipe(dev, vbl_swap->plane);
 
-               if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
+               if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
                        continue;
 
                list_del(list);
                dev_priv->swaps_pending--;
 
-               spin_unlock(&dev_priv->swaps_lock);
-               spin_lock(&dev->drw_lock);
+               DRM_SPINUNLOCK(&dev_priv->swaps_lock);
+               DRM_SPINLOCK(&dev->drw_lock);
 
                drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
 
                if (!drw) {
-                       spin_unlock(&dev->drw_lock);
+                       DRM_SPINUNLOCK(&dev->drw_lock);
                        drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
-                       spin_lock(&dev_priv->swaps_lock);
+                       DRM_SPINLOCK(&dev_priv->swaps_lock);
                        continue;
                }
 
                list_for_each(hit, &hits) {
-                       drm_i915_vbl_swap_t *swap_cmp =
-                               list_entry(hit, drm_i915_vbl_swap_t, head);
-                       drm_drawable_info_t *drw_cmp =
+                       struct drm_i915_vbl_swap *swap_cmp =
+                               list_entry(hit, struct drm_i915_vbl_swap, head);
+                       struct drm_drawable_info *drw_cmp =
                                drm_get_drawable_info(dev, swap_cmp->drw_id);
 
                        if (drw_cmp &&
@@ -149,7 +177,7 @@ static void i915_vblank_tasklet(drm_device_t *dev)
                        }
                }
 
-               spin_unlock(&dev->drw_lock);
+               DRM_SPINUNLOCK(&dev->drw_lock);
 
                /* List of hits was empty, or we reached the end of it */
                if (hit == &hits)
@@ -157,30 +185,29 @@ static void i915_vblank_tasklet(drm_device_t *dev)
 
                nhits++;
 
-               spin_lock(&dev_priv->swaps_lock);
+               DRM_SPINLOCK(&dev_priv->swaps_lock);
        }
 
+       DRM_SPINUNLOCK(&dev_priv->swaps_lock);
+
        if (nhits == 0) {
-               spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
                return;
        }
 
-       spin_unlock(&dev_priv->swaps_lock);
-
        i915_kernel_lost_context(dev);
 
        upper[0] = upper[1] = 0;
-       slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
-       slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
-       lower[0] = sarea_priv->pipeA_y + slice[0];
-       lower[1] = sarea_priv->pipeB_y + slice[0];
+       slice[0] = max(sarea_priv->planeA_h / nhits, 1);
+       slice[1] = max(sarea_priv->planeB_h / nhits, 1);
+       lower[0] = sarea_priv->planeA_y + slice[0];
+       lower[1] = sarea_priv->planeB_y + slice[0];
 
        offsets[0] = sarea_priv->front_offset;
        offsets[1] = sarea_priv->back_offset;
        offsets[2] = sarea_priv->third_offset;
        num_pages = sarea_priv->third_handle ? 3 : 2;
 
-       spin_lock(&dev->drw_lock);
+       DRM_SPINLOCK(&dev->drw_lock);
 
        /* Emit blits for buffer swaps, partitioning both outputs into as many
         * slices as there are buffer swaps scheduled in order to avoid tearing
@@ -196,10 +223,10 @@ static void i915_vblank_tasklet(drm_device_t *dev)
                        lower[0] = lower[1] = sarea_priv->height;
 
                list_for_each(hit, &hits) {
-                       drm_i915_vbl_swap_t *swap_hit =
-                               list_entry(hit, drm_i915_vbl_swap_t, head);
-                       drm_clip_rect_t *rect;
-                       int num_rects, pipe, front, back;
+                       struct drm_i915_vbl_swap *swap_hit =
+                               list_entry(hit, struct drm_i915_vbl_swap, head);
+                       struct drm_clip_rect *rect;
+                       int num_rects, plane, front, back;
                        unsigned short top, bottom;
 
                        drw = drm_get_drawable_info(dev, swap_hit->drw_id);
@@ -207,10 +234,10 @@ static void i915_vblank_tasklet(drm_device_t *dev)
                        if (!drw)
                                continue;
 
-                       pipe = swap_hit->pipe;
+                       plane = swap_hit->plane;
 
                        if (swap_hit->flip) {
-                               i915_dispatch_vsync_flip(dev, drw, pipe);
+                               i915_dispatch_vsync_flip(dev, drw, plane);
                                continue;
                        }
 
@@ -232,11 +259,11 @@ static void i915_vblank_tasklet(drm_device_t *dev)
                        }
 
                        rect = drw->rects;
-                       top = upper[pipe];
-                       bottom = lower[pipe];
+                       top = upper[plane];
+                       bottom = lower[plane];
 
                        front = (dev_priv->sarea_priv->pf_current_page >>
-                                (2 * pipe)) & 0x3;
+                                (2 * plane)) & 0x3;
                        back = (front + 1) % num_pages;
 
                        for (num_rects = drw->num_rects; num_rects--; rect++) {
@@ -262,11 +289,11 @@ static void i915_vblank_tasklet(drm_device_t *dev)
                }
        }
 
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+       DRM_SPINUNLOCK(&dev->drw_lock);
 
        list_for_each_safe(hit, tmp, &hits) {
-               drm_i915_vbl_swap_t *swap_hit =
-                       list_entry(hit, drm_i915_vbl_swap_t, head);
+               struct drm_i915_vbl_swap *swap_hit =
+                       list_entry(hit, struct drm_i915_vbl_swap, head);
 
                list_del(hit);
 
@@ -276,8 +303,8 @@ static void i915_vblank_tasklet(drm_device_t *dev)
 
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
-       drm_device_t *dev = (drm_device_t *) arg;
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_device *dev = (struct drm_device *) arg;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        u16 temp;
        u32 pipea_stats, pipeb_stats;
 
@@ -338,10 +365,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
        return IRQ_HANDLED;
 }
 
-int i915_emit_irq(drm_device_t * dev)
+int i915_emit_irq(struct drm_device * dev)
 {
        
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        RING_LOCALS;
 
        i915_kernel_lost_context(dev);
@@ -360,31 +387,31 @@ int i915_emit_irq(drm_device_t * dev)
 
 }
 
-void i915_user_irq_on(drm_i915_private_t *dev_priv)
+void i915_user_irq_on(struct drm_i915_private *dev_priv)
 {
-       spin_lock(&dev_priv->user_irq_lock);
+       DRM_SPINLOCK(&dev_priv->user_irq_lock);
        if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
                dev_priv->irq_enable_reg |= USER_INT_FLAG;
                I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
        }
-       spin_unlock(&dev_priv->user_irq_lock);
+       DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
 
 }
                
-void i915_user_irq_off(drm_i915_private_t *dev_priv)
+void i915_user_irq_off(struct drm_i915_private *dev_priv)
 {
-       spin_lock(&dev_priv->user_irq_lock);
+       DRM_SPINLOCK(&dev_priv->user_irq_lock);
        if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
                //              dev_priv->irq_enable_reg &= ~USER_INT_FLAG;
                //              I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
        }
-       spin_unlock(&dev_priv->user_irq_lock);
+       DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
 }
                
 
-static int i915_wait_irq(drm_device_t * dev, int irq_nr)
+static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        int ret = 0;
 
        DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
@@ -400,7 +427,7 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
                    READ_BREADCRUMB(dev_priv) >= irq_nr);
        i915_user_irq_off(dev_priv);
 
-       if (ret == DRM_ERR(EBUSY)) {
+       if (ret == -EBUSY) {
                DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
                          __FUNCTION__,
                          READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
@@ -410,16 +437,17 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
        return ret;
 }
 
-static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+static int i915_driver_vblank_do_wait(struct drm_device *dev,
+                                     unsigned int *sequence,
                                      atomic_t *counter)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned int cur_vblank;
        int ret = 0;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
@@ -431,40 +459,49 @@ static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
        return ret;
 }
 
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+void i915_driver_wait_next_vblank(struct drm_device *dev, int pipe)
+{
+       unsigned int seq;
+
+       seq = pipe ? atomic_read(&dev->vbl_received2) + 1 :
+               atomic_read(&dev->vbl_received) + 1;
+
+       if (!pipe)
+               i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received);
+       else
+               i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received2);
+}
+
+int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
 {
        return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
 }
 
-int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
 {
        return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
 }
 
 /* Needs the lock as it touches the ring.
  */
-int i915_irq_emit(DRM_IOCTL_ARGS)
+int i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_irq_emit_t emit;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_irq_emit *emit = data;
        int result;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
-                                sizeof(emit));
-
        result = i915_emit_irq(dev);
 
-       if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
+       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
@@ -472,26 +509,23 @@ int i915_irq_emit(DRM_IOCTL_ARGS)
 
 /* Doesn't need the hardware lock.
  */
-int i915_irq_wait(DRM_IOCTL_ARGS)
+int i915_irq_wait(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_irq_wait_t irqwait;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_irq_wait *irqwait = data;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
-                                sizeof(irqwait));
-
-       return i915_wait_irq(dev, irqwait.irq_seq);
+       return i915_wait_irq(dev, irqwait->irq_seq);
 }
 
-static void i915_enable_interrupt (drm_device_t *dev)
+void i915_enable_interrupt (struct drm_device *dev)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        
        dev_priv->irq_enable_reg = USER_INT_FLAG; 
        if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
@@ -505,221 +539,218 @@ static void i915_enable_interrupt (drm_device_t *dev)
 
 /* Set the vblank monitor pipe
  */
-int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
+int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t pipe;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_vblank_pipe *pipe = data;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data,
-                                sizeof(pipe));
-
-       if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
+       if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
                DRM_ERROR("%s called with invalid pipe 0x%x\n", 
-                         __FUNCTION__, pipe.pipe);
-               return DRM_ERR(EINVAL);
+                         __FUNCTION__, pipe->pipe);
+               return -EINVAL;
        }
 
-       dev_priv->vblank_pipe = pipe.pipe;
+       dev_priv->vblank_pipe = pipe->pipe;
 
        i915_enable_interrupt (dev);
 
        return 0;
 }
 
-int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
+int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t pipe;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_vblank_pipe *pipe = data;
        u16 flag;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        flag = I915_READ(I915REG_INT_ENABLE_R);
-       pipe.pipe = 0;
+       pipe->pipe = 0;
        if (flag & VSYNC_PIPEA_FLAG)
-               pipe.pipe |= DRM_I915_VBLANK_PIPE_A;
+               pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
        if (flag & VSYNC_PIPEB_FLAG)
-               pipe.pipe |= DRM_I915_VBLANK_PIPE_B;
-       DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe,
-                                sizeof(pipe));
+               pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
+
        return 0;
 }
 
 /**
  * Schedule buffer swap at given vertical blank.
  */
-int i915_vblank_swap(DRM_IOCTL_ARGS)
+int i915_vblank_swap(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_swap_t swap;
-       drm_i915_vbl_swap_t *vbl_swap;
-       unsigned int pipe, seqtype, curseq;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_vblank_swap *swap = data;
+       struct drm_i915_vbl_swap *vbl_swap;
+       unsigned int pipe, seqtype, curseq, plane;
        unsigned long irqflags;
        struct list_head *list;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __func__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (dev_priv->sarea_priv->rotation) {
                DRM_DEBUG("Rotation not supported\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data,
-                                sizeof(swap));
-
-       if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
+       if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
                             _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS |
                             _DRM_VBLANK_FLIP)) {
-               DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
+               return -EINVAL;
        }
 
-       pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+       plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+       pipe = i915_get_pipe(dev, plane);
 
-       seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
+       seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
 
        if (!(dev_priv->vblank_pipe & (1 << pipe))) {
                DRM_ERROR("Invalid pipe %d\n", pipe);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       spin_lock_irqsave(&dev->drw_lock, irqflags);
+       DRM_SPINLOCK_IRQSAVE(&dev->drw_lock, irqflags);
 
-       if (!drm_get_drawable_info(dev, swap.drawable)) {
-               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-               DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable);
-               return DRM_ERR(EINVAL);
+       /* It makes no sense to schedule a swap for a drawable that doesn't have
+        * valid information at this point. E.g. this could mean that the X
+        * server is too old to push drawable information to the DRM, in which
+        * case all such swaps would become ineffective.
+        */
+       if (!drm_get_drawable_info(dev, swap->drawable)) {
+               DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
+               DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
+               return -EINVAL;
        }
 
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+       DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
 
        curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
 
        if (seqtype == _DRM_VBLANK_RELATIVE)
-               swap.sequence += curseq;
+               swap->sequence += curseq;
 
-       if ((curseq - swap.sequence) <= (1<<23)) {
-               if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
-                       swap.sequence = curseq + 1;
+       if ((curseq - swap->sequence) <= (1<<23)) {
+               if (swap->seqtype & _DRM_VBLANK_NEXTONMISS) {
+                       swap->sequence = curseq + 1;
                } else {
                        DRM_DEBUG("Missed target sequence\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
-       if (swap.seqtype & _DRM_VBLANK_FLIP) {
-               swap.sequence--;
+       if (swap->seqtype & _DRM_VBLANK_FLIP) {
+               swap->sequence--;
 
-               if ((curseq - swap.sequence) <= (1<<23)) {
-                       drm_drawable_info_t *drw;
+               if ((curseq - swap->sequence) <= (1<<23)) {
+                       struct drm_drawable_info *drw;
 
-                       LOCK_TEST_WITH_RETURN(dev, filp);
+                       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-                       spin_lock_irqsave(&dev->drw_lock, irqflags);
+                       DRM_SPINLOCK_IRQSAVE(&dev->drw_lock, irqflags);
 
-                       drw = drm_get_drawable_info(dev, swap.drawable);
+                       drw = drm_get_drawable_info(dev, swap->drawable);
 
                        if (!drw) {
-                               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+                               DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock,
+                                   irqflags);
                                DRM_DEBUG("Invalid drawable ID %d\n",
-                                         swap.drawable);
-                               return DRM_ERR(EINVAL);
+                                         swap->drawable);
+                               return -EINVAL;
                        }
 
-                       i915_dispatch_vsync_flip(dev, drw, pipe);
+                       i915_dispatch_vsync_flip(dev, drw, plane);
 
-                       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+                       DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
 
                        return 0;
                }
        }
 
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+       DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags);
 
        list_for_each(list, &dev_priv->vbl_swaps.head) {
-               vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+               vbl_swap = list_entry(list, struct drm_i915_vbl_swap, head);
 
-               if (vbl_swap->drw_id == swap.drawable &&
-                   vbl_swap->pipe == pipe &&
-                   vbl_swap->sequence == swap.sequence) {
-                       vbl_swap->flip = (swap.seqtype & _DRM_VBLANK_FLIP);
-                       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+               if (vbl_swap->drw_id == swap->drawable &&
+                   vbl_swap->plane == plane &&
+                   vbl_swap->sequence == swap->sequence) {
+                       vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
+                       DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags);
                        DRM_DEBUG("Already scheduled\n");
                        return 0;
                }
        }
 
-       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+       DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags);
 
        if (dev_priv->swaps_pending >= 100) {
                DRM_DEBUG("Too many swaps queued\n");
-               return DRM_ERR(EBUSY);
+               return -EBUSY;
        }
 
-       vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER);
+       vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER);
 
        if (!vbl_swap) {
                DRM_ERROR("Failed to allocate memory to queue swap\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        DRM_DEBUG("\n");
 
-       vbl_swap->drw_id = swap.drawable;
-       vbl_swap->pipe = pipe;
-       vbl_swap->sequence = swap.sequence;
-       vbl_swap->flip = (swap.seqtype & _DRM_VBLANK_FLIP);
+       vbl_swap->drw_id = swap->drawable;
+       vbl_swap->plane = plane;
+       vbl_swap->sequence = swap->sequence;
+       vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
 
        if (vbl_swap->flip)
-               swap.sequence++;
+               swap->sequence++;
 
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+       DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags);
 
        list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head);
        dev_priv->swaps_pending++;
 
-       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-
-       DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap,
-                              sizeof(swap));
+       DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags);
 
        return 0;
 }
 
 /* drm_dma.h hooks
 */
-void i915_driver_irq_preinstall(drm_device_t * dev)
+void i915_driver_irq_preinstall(struct drm_device * dev)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 
        I915_WRITE16(I915REG_HWSTAM, 0xeffe);
        I915_WRITE16(I915REG_INT_MASK_R, 0x0);
        I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
 }
 
-void i915_driver_irq_postinstall(drm_device_t * dev)
+void i915_driver_irq_postinstall(struct drm_device * dev)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
 
-       spin_lock_init(&dev_priv->swaps_lock);
+       DRM_SPININIT(&dev_priv->swaps_lock, "swap");
        INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
        dev_priv->swaps_pending = 0;
 
-       dev_priv->user_irq_lock = SPIN_LOCK_UNLOCKED;
+       DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
        dev_priv->user_irq_refcount = 0;
 
        i915_enable_interrupt(dev);
@@ -732,9 +763,9 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
        I915_WRITE(I915REG_INSTPM, ( 1 << 5) | ( 1 << 21));
 }
 
-void i915_driver_irq_uninstall(drm_device_t * dev)
+void i915_driver_irq_uninstall(struct drm_device * dev)
 {
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
        u16 temp;
        if (!dev_priv)
                return;
index 13f19f3..2916d5a 100644 (file)
  * block to allocate, and the ring is drained prior to allocations --
  * in other words allocation is expensive.
  */
-static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
+static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_tex_region_t *list;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_sarea *sarea_priv = dev_priv->sarea_priv;
+       struct drm_tex_region *list;
        unsigned shift, nr;
        unsigned start;
        unsigned end;
@@ -89,7 +89,7 @@ static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
  */
 
 static struct mem_block *split_block(struct mem_block *p, int start, int size,
-                                    DRMFILE filp)
+                                    struct drm_file *file_priv)
 {
        /* Maybe cut off the start of an existing block */
        if (start > p->start) {
@@ -99,7 +99,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
                        goto out;
                newblock->start = start;
                newblock->size = p->size - (start - p->start);
-               newblock->filp = NULL;
+               newblock->file_priv = NULL;
                newblock->next = p->next;
                newblock->prev = p;
                p->next->prev = newblock;
@@ -116,7 +116,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
                        goto out;
                newblock->start = start + size;
                newblock->size = p->size - size;
-               newblock->filp = NULL;
+               newblock->file_priv = NULL;
                newblock->next = p->next;
                newblock->prev = p;
                p->next->prev = newblock;
@@ -126,20 +126,20 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
 
       out:
        /* Our block is in the middle */
-       p->filp = filp;
+       p->file_priv = file_priv;
        return p;
 }
 
 static struct mem_block *alloc_block(struct mem_block *heap, int size,
-                                    int align2, DRMFILE filp)
+                                    int align2, struct drm_file *file_priv)
 {
        struct mem_block *p;
        int mask = (1 << align2) - 1;
 
        for (p = heap->next; p != heap; p = p->next) {
                int start = (p->start + mask) & ~mask;
-               if (p->filp == NULL && start + size <= p->start + p->size)
-                       return split_block(p, start, size, filp);
+               if (p->file_priv == NULL && start + size <= p->start + p->size)
+                       return split_block(p, start, size, file_priv);
        }
 
        return NULL;
@@ -158,12 +158,12 @@ static struct mem_block *find_block(struct mem_block *heap, int start)
 
 static void free_block(struct mem_block *p)
 {
-       p->filp = NULL;
+       p->file_priv = NULL;
 
-       /* Assumes a single contiguous range.  Needs a special filp in
+       /* Assumes a single contiguous range.  Needs a special file_priv in
         * 'heap' to stop it being subsumed.
         */
-       if (p->next->filp == NULL) {
+       if (p->next->file_priv == NULL) {
                struct mem_block *q = p->next;
                p->size += q->size;
                p->next = q->next;
@@ -171,7 +171,7 @@ static void free_block(struct mem_block *p)
                drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
        }
 
-       if (p->prev->filp == NULL) {
+       if (p->prev->file_priv == NULL) {
                struct mem_block *q = p->prev;
                q->size += p->size;
                q->next = p->next;
@@ -197,18 +197,19 @@ static int init_heap(struct mem_block **heap, int start, int size)
 
        blocks->start = start;
        blocks->size = size;
-       blocks->filp = NULL;
+       blocks->file_priv = NULL;
        blocks->next = blocks->prev = *heap;
 
        memset(*heap, 0, sizeof(**heap));
-       (*heap)->filp = (DRMFILE) - 1;
+       (*heap)->file_priv = (struct drm_file *) - 1;
        (*heap)->next = (*heap)->prev = blocks;
        return 0;
 }
 
 /* Free all blocks associated with the releasing file.
  */
-void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
+void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv,
+                     struct mem_block *heap)
 {
        struct mem_block *p;
 
@@ -216,17 +217,17 @@ void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
                return;
 
        for (p = heap->next; p != heap; p = p->next) {
-               if (p->filp == filp) {
-                       p->filp = NULL;
+               if (p->file_priv == file_priv) {
+                       p->file_priv = NULL;
                        mark_block(dev, p, 0);
                }
        }
 
-       /* Assumes a single contiguous range.  Needs a special filp in
+       /* Assumes a single contiguous range.  Needs a special file_priv in
         * 'heap' to stop it being subsumed.
         */
        for (p = heap->next; p != heap; p = p->next) {
-               while (p->filp == NULL && p->next->filp == NULL) {
+               while (p->file_priv == NULL && p->next->file_priv == NULL) {
                        struct mem_block *q = p->next;
                        p->size += q->size;
                        p->next = q->next;
@@ -255,7 +256,7 @@ void i915_mem_takedown(struct mem_block **heap)
        *heap = NULL;
 }
 
-static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
+static struct mem_block **get_heap(struct drm_i915_private * dev_priv, int region)
 {
        switch (region) {
        case I915_MEM_REGION_AGP:
@@ -267,129 +268,117 @@ static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
 
 /* IOCTL HANDLERS */
 
-int i915_mem_alloc(DRM_IOCTL_ARGS)
+int i915_mem_alloc(struct drm_device *dev, void *data,
+                  struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_alloc_t alloc;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_mem_alloc *alloc = data;
        struct mem_block *block, **heap;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data,
-                                sizeof(alloc));
-
-       heap = get_heap(dev_priv, alloc.region);
+       heap = get_heap(dev_priv, alloc->region);
        if (!heap || !*heap)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
        /* Make things easier on ourselves: all allocations at least
         * 4k aligned.
         */
-       if (alloc.alignment < 12)
-               alloc.alignment = 12;
+       if (alloc->alignment < 12)
+               alloc->alignment = 12;
 
-       block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
+       block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
 
        if (!block)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        mark_block(dev, block, 1);
 
-       if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
+       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
+                            sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
 }
 
-int i915_mem_free(DRM_IOCTL_ARGS)
+int i915_mem_free(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_free_t memfree;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_mem_free *memfree = data;
        struct mem_block *block, **heap;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data,
-                                sizeof(memfree));
-
-       heap = get_heap(dev_priv, memfree.region);
+       heap = get_heap(dev_priv, memfree->region);
        if (!heap || !*heap)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
-       block = find_block(*heap, memfree.region_offset);
+       block = find_block(*heap, memfree->region_offset);
        if (!block)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
-       if (block->filp != filp)
-               return DRM_ERR(EPERM);
+       if (block->file_priv != file_priv)
+               return -EPERM;
 
        mark_block(dev, block, 0);
        free_block(block);
        return 0;
 }
 
-int i915_mem_init_heap(DRM_IOCTL_ARGS)
+int i915_mem_init_heap(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_init_heap_t initheap;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_mem_init_heap *initheap = data;
        struct mem_block **heap;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(initheap,
-                                (drm_i915_mem_init_heap_t __user *) data,
-                                sizeof(initheap));
-
-       heap = get_heap(dev_priv, initheap.region);
+       heap = get_heap(dev_priv, initheap->region);
        if (!heap)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
        if (*heap) {
                DRM_ERROR("heap already initialized?");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
-       return init_heap(heap, initheap.start, initheap.size);
+       return init_heap(heap, initheap->start, initheap->size);
 }
 
-int i915_mem_destroy_heap( DRM_IOCTL_ARGS )
+int i915_mem_destroy_heap( struct drm_device *dev, void *data,
+                          struct drm_file *file_priv )
 {
-       DRM_DEVICE;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_destroy_heap_t destroyheap;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_mem_destroy_heap *destroyheap = data;
        struct mem_block **heap;
 
        if ( !dev_priv ) {
                DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data,
-                                 sizeof(destroyheap) );
-
-       heap = get_heap( dev_priv, destroyheap.region );
+       heap = get_heap( dev_priv, destroyheap->region );
        if (!heap) {
                DRM_ERROR("get_heap failed");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
        
        if (!*heap) {
                DRM_ERROR("heap not initialized?");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        i915_mem_takedown( heap );
index 60f5590..e0a6745 100644 (file)
@@ -70,7 +70,7 @@ int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries)
 
        DRM_INFO("%s failed! slots=%d entries=%d\n", __FUNCTION__, slots,
                 entries);
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /**
@@ -94,7 +94,7 @@ int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv)
        DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__,
                 MACH64_READ(MACH64_GUI_STAT));
        mach64_dump_ring_info(dev_priv);
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /**
@@ -135,7 +135,7 @@ int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n)
        /* FIXME: This is being ignored... */
        DRM_ERROR("failed!\n");
        mach64_dump_ring_info(dev_priv);
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /**
@@ -172,7 +172,7 @@ static int mach64_ring_idle(drm_mach64_private_t * dev_priv)
        DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__,
                 MACH64_READ(MACH64_GUI_STAT));
        mach64_dump_ring_info(dev_priv);
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /**
@@ -418,7 +418,7 @@ void mach64_dump_engine_info(drm_mach64_private_t * dev_priv)
  * pointed by the ring head.
  */
 static void mach64_dump_buf_info(drm_mach64_private_t * dev_priv,
-                                drm_buf_t * buf)
+                                struct drm_buf * buf)
 {
        u32 addr = GETBUFADDR(buf);
        u32 used = buf->used >> 2;
@@ -522,7 +522,7 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv)
                list_for_each(ptr, &dev_priv->pending) {
                        drm_mach64_freelist_t *entry =
                            list_entry(ptr, drm_mach64_freelist_t, list);
-                       drm_buf_t *buf = entry->buf;
+                       struct drm_buf *buf = entry->buf;
 
                        u32 buf_addr = GETBUFADDR(buf);
 
@@ -572,7 +572,7 @@ void mach64_dump_ring_info(drm_mach64_private_t * dev_priv)
  * DMA operation. It is left here since it so tricky to get DMA operating
  * properly in some architectures and hardware.
  */
-static int mach64_bm_dma_test(drm_device_t * dev)
+static int mach64_bm_dma_test(struct drm_device * dev)
 {
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_dma_handle_t *cpu_addr_dmah;
@@ -592,7 +592,7 @@ static int mach64_bm_dma_test(drm_device_t * dev)
            drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful);
        if (!cpu_addr_dmah) {
                DRM_INFO("data-memory allocation failed!\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        } else {
                data = (u32 *) cpu_addr_dmah->vaddr;
                data_addr = (u32) cpu_addr_dmah->busaddr;
@@ -624,7 +624,7 @@ static int mach64_bm_dma_test(drm_device_t * dev)
                        mach64_do_engine_reset(dev_priv);
                        DRM_INFO("freeing data buffer memory.\n");
                        drm_pci_free(dev, cpu_addr_dmah);
-                       return DRM_ERR(EIO);
+                       return -EIO;
                }
        }
 
@@ -752,7 +752,7 @@ static int mach64_bm_dma_test(drm_device_t * dev)
  * Called during the DMA initialization ioctl to initialize all the necessary
  * software and hardware state for DMA operation.
  */
-static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
+static int mach64_do_dma_init(struct drm_device * dev, drm_mach64_init_t * init)
 {
        drm_mach64_private_t *dev_priv;
        u32 tmp;
@@ -762,7 +762,7 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
 
        dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER);
        if (dev_priv == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        memset(dev_priv, 0, sizeof(drm_mach64_private_t));
 
@@ -797,21 +797,21 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
                DRM_ERROR("can not find sarea!\n");
                dev->dev_private = (void *)dev_priv;
                mach64_do_cleanup_dma(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
        if (!dev_priv->fb) {
                DRM_ERROR("can not find frame buffer map!\n");
                dev->dev_private = (void *)dev_priv;
                mach64_do_cleanup_dma(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
        if (!dev_priv->mmio) {
                DRM_ERROR("can not find mmio map!\n");
                dev->dev_private = (void *)dev_priv;
                mach64_do_cleanup_dma(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset);
@@ -819,7 +819,7 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
                DRM_ERROR("can not find ring map!\n");
                dev->dev_private = (void *)dev_priv;
                mach64_do_cleanup_dma(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->sarea_priv = (drm_mach64_sarea_t *)
@@ -832,7 +832,7 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
                                  " descriptor ring\n");
                        dev->dev_private = (void *)dev_priv;
                        mach64_do_cleanup_dma(dev);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
                dev->agp_buffer_token = init->buffers_offset;
                dev->agp_buffer_map =
@@ -841,7 +841,7 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
                        DRM_ERROR("can not find dma buffer map!\n");
                        dev->dev_private = (void *)dev_priv;
                        mach64_do_cleanup_dma(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                /* there might be a nicer way to do this -
                   dev isn't passed all the way though the mach64 - DA */
@@ -853,7 +853,7 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
                                  " dma buffer\n");
                        dev->dev_private = (void *)dev_priv;
                        mach64_do_cleanup_dma(dev);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
                dev_priv->agp_textures =
                    drm_core_findmap(dev, init->agp_textures_offset);
@@ -861,7 +861,7 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
                        DRM_ERROR("can not find agp texture region!\n");
                        dev->dev_private = (void *)dev_priv;
                        mach64_do_cleanup_dma(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
@@ -974,7 +974,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
        volatile u32 *ring_read;
        struct list_head *ptr;
        drm_mach64_freelist_t *entry;
-       drm_buf_t *buf = NULL;
+       struct drm_buf *buf = NULL;
        u32 *buf_ptr;
        u32 used, reg, target;
        int fifo, count, found, ret, no_idle_wait;
@@ -1035,7 +1035,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
                             head, ring->tail, buf_addr, (eol ? "eol" : ""));
                        mach64_dump_ring_info(dev_priv);
                        mach64_do_engine_reset(dev_priv);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                /* Hand feed the buffer to the card via MMIO, waiting for the fifo
@@ -1117,7 +1117,7 @@ int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
 /** \name DMA cleanup */
 /*@{*/
 
-int mach64_do_cleanup_dma(drm_device_t * dev)
+int mach64_do_cleanup_dma(struct drm_device * dev)
 {
        DRM_DEBUG("%s\n", __FUNCTION__);
 
@@ -1158,60 +1158,57 @@ int mach64_do_cleanup_dma(drm_device_t * dev)
 /** \name IOCTL handlers */
 /*@{*/
 
-int mach64_dma_init(DRM_IOCTL_ARGS)
+int mach64_dma_init(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_mach64_init_t init;
+       drm_mach64_init_t *init = data;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_mach64_init_t *) data,
-                                sizeof(init));
-
-       switch (init.func) {
+       switch (init->func) {
        case DRM_MACH64_INIT_DMA:
-               return mach64_do_dma_init(dev, &init);
+               return mach64_do_dma_init(dev, init);
        case DRM_MACH64_CLEANUP_DMA:
                return mach64_do_cleanup_dma(dev);
        }
 
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
-int mach64_dma_idle(DRM_IOCTL_ARGS)
+int mach64_dma_idle(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return mach64_do_dma_idle(dev_priv);
 }
 
-int mach64_dma_flush(DRM_IOCTL_ARGS)
+int mach64_dma_flush(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return mach64_do_dma_flush(dev_priv);
 }
 
-int mach64_engine_reset(DRM_IOCTL_ARGS)
+int mach64_engine_reset(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return mach64_do_engine_reset(dev_priv);
 }
@@ -1223,9 +1220,9 @@ int mach64_engine_reset(DRM_IOCTL_ARGS)
 /** \name Freelist management */
 /*@{*/
 
-int mach64_init_freelist(drm_device_t * dev)
+int mach64_init_freelist(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_freelist_t *entry;
        struct list_head *ptr;
@@ -1239,7 +1236,7 @@ int mach64_init_freelist(drm_device_t * dev)
                     (drm_mach64_freelist_t *)
                     drm_alloc(sizeof(drm_mach64_freelist_t),
                               DRM_MEM_BUFLISTS)) == NULL)
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                memset(entry, 0, sizeof(drm_mach64_freelist_t));
                entry->buf = dma->buflist[i];
                ptr = &entry->list;
@@ -1249,7 +1246,7 @@ int mach64_init_freelist(drm_device_t * dev)
        return 0;
 }
 
-void mach64_destroy_freelist(drm_device_t * dev)
+void mach64_destroy_freelist(struct drm_device * dev)
 {
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_freelist_t *entry;
@@ -1381,7 +1378,7 @@ static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv)
        return 1;
 }
 
-drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv)
+struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv)
 {
        drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
        drm_mach64_freelist_t *entry;
@@ -1427,7 +1424,7 @@ drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv)
        return entry->buf;
 }
 
-int mach64_freelist_put(drm_mach64_private_t * dev_priv, drm_buf_t * copy_buf)
+int mach64_freelist_put(drm_mach64_private_t * dev_priv, struct drm_buf * copy_buf)
 {
        struct list_head *ptr;
        drm_mach64_freelist_t *entry;
@@ -1438,7 +1435,7 @@ int mach64_freelist_put(drm_mach64_private_t * dev_priv, drm_buf_t * copy_buf)
                if (copy_buf == entry->buf) {
                        DRM_ERROR("%s: Trying to release a pending buf\n",
                             __FUNCTION__);
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                }
        }
 #endif
@@ -1461,76 +1458,73 @@ int mach64_freelist_put(drm_mach64_private_t * dev_priv, drm_buf_t * copy_buf)
 /** \name DMA buffer request and submission IOCTL handler */
 /*@{*/
 
-static int mach64_dma_get_buffers(DRMFILE filp, drm_device_t * dev,
-                                 drm_dma_t * d)
+static int mach64_dma_get_buffers(struct drm_device *dev,
+                                 struct drm_file *file_priv,
+                                 struct drm_dma * d)
 {
        int i;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        drm_mach64_private_t *dev_priv = dev->dev_private;
 
        for (i = d->granted_count; i < d->request_count; i++) {
                buf = mach64_freelist_get(dev_priv);
 #if MACH64_EXTRA_CHECKING
                if (!buf)
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
 #else
                if (!buf)
-                       return DRM_ERR(EAGAIN);
+                       return -EAGAIN;
 #endif
 
-               buf->filp = filp;
+               buf->file_priv = file_priv;
 
                if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
                                     sizeof(buf->idx)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
                                     sizeof(buf->total)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
 
                d->granted_count++;
        }
        return 0;
 }
 
-int mach64_dma_buffers(DRM_IOCTL_ARGS)
+int mach64_dma_buffers(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_device_dma_t *dma = dev->dma;
-       drm_dma_t d;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_dma *d = data;
        int ret = 0;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t *) data, sizeof(d));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        /* Please don't send us buffers.
         */
-       if (d.send_count != 0) {
+       if (d->send_count != 0) {
                DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d.send_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
        }
 
        /* We'll send you buffers.
         */
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
                DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d.request_count, dma->buf_count);
-               ret = DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               ret = -EINVAL;
        }
 
-       d.granted_count = 0;
+       d->granted_count = 0;
 
-       if (d.request_count) {
-               ret = mach64_dma_get_buffers(filp, dev, &d);
+       if (d->request_count) {
+               ret = mach64_dma_get_buffers(dev, file_priv, d);
        }
 
-       DRM_COPY_TO_USER_IOCTL((drm_dma_t *) data, d, sizeof(d));
-
        return ret;
 }
 
-void mach64_driver_lastclose(drm_device_t * dev)
+void mach64_driver_lastclose(struct drm_device * dev)
 {
        mach64_do_cleanup_dma(dev);
 }
index 083f959..1f5fd84 100644 (file)
@@ -130,7 +130,7 @@ typedef struct drm_mach64_sarea {
 
        /* The current cliprects, or a subset thereof.
         */
-       drm_clip_rect_t boxes[MACH64_NR_SAREA_CLIPRECTS];
+       struct drm_clip_rect boxes[MACH64_NR_SAREA_CLIPRECTS];
        unsigned int nbox;
 
        /* Counters for client-side throttling of rendering clients.
@@ -139,7 +139,7 @@ typedef struct drm_mach64_sarea {
 
        /* Texture memory LRU.
         */
-       drm_tex_region_t tex_list[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS +
+       struct drm_tex_region tex_list[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS +
                                                       1];
        unsigned int tex_age[MACH64_NR_TEX_HEAPS];
        int ctx_owner;
index bb8b309..cebd4c6 100644 (file)
@@ -55,7 +55,7 @@
 
 typedef struct drm_mach64_freelist {
        struct list_head list;  /* List pointers for free_list, placeholders, or pending list */
-       drm_buf_t *buf;         /* Pointer to the buffer */
+       struct drm_buf *buf;            /* Pointer to the buffer */
        int discard;            /* This flag is set when we're done (re)using a buffer */
        u32 ring_ofs;           /* dword offset in ring of last descriptor for this buffer */
 } drm_mach64_freelist_t;
@@ -108,22 +108,27 @@ typedef struct drm_mach64_private {
        drm_local_map_t *agp_textures;
 } drm_mach64_private_t;
 
-extern drm_ioctl_desc_t mach64_ioctls[];
+extern struct drm_ioctl_desc mach64_ioctls[];
 extern int mach64_max_ioctl;
 
                                /* mach64_dma.c */
-extern int mach64_dma_init(DRM_IOCTL_ARGS);
-extern int mach64_dma_idle(DRM_IOCTL_ARGS);
-extern int mach64_dma_flush(DRM_IOCTL_ARGS);
-extern int mach64_engine_reset(DRM_IOCTL_ARGS);
-extern int mach64_dma_buffers(DRM_IOCTL_ARGS);
-extern void mach64_driver_lastclose(drm_device_t * dev);
-
-extern int mach64_init_freelist(drm_device_t * dev);
-extern void mach64_destroy_freelist(drm_device_t * dev);
-extern drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv);
+extern int mach64_dma_init(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int mach64_dma_idle(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int mach64_dma_flush(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int mach64_engine_reset(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
+extern int mach64_dma_buffers(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+extern void mach64_driver_lastclose(struct drm_device * dev);
+
+extern int mach64_init_freelist(struct drm_device * dev);
+extern void mach64_destroy_freelist(struct drm_device * dev);
+extern struct drm_buf *mach64_freelist_get(drm_mach64_private_t * dev_priv);
 extern int mach64_freelist_put(drm_mach64_private_t * dev_priv,
-                              drm_buf_t * copy_buf);
+                              struct drm_buf * copy_buf);
 
 extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv,
                                   int entries);
@@ -137,21 +142,26 @@ extern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv);
 
 extern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv);
 extern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv);
-extern int mach64_do_cleanup_dma(drm_device_t * dev);
+extern int mach64_do_cleanup_dma(struct drm_device * dev);
 
                                /* mach64_state.c */
-extern int mach64_dma_clear(DRM_IOCTL_ARGS);
-extern int mach64_dma_swap(DRM_IOCTL_ARGS);
-extern int mach64_dma_vertex(DRM_IOCTL_ARGS);
-extern int mach64_dma_blit(DRM_IOCTL_ARGS);
-extern int mach64_get_param(DRM_IOCTL_ARGS);
-extern int mach64_driver_vblank_wait(drm_device_t * dev,
+extern int mach64_dma_clear(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int mach64_dma_swap(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int mach64_dma_vertex(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv);
+extern int mach64_dma_blit(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int mach64_get_param(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int mach64_driver_vblank_wait(struct drm_device * dev,
                                     unsigned int *sequence);
 
 extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mach64_driver_irq_preinstall(drm_device_t * dev);
-extern void mach64_driver_irq_postinstall(drm_device_t * dev);
-extern void mach64_driver_irq_uninstall(drm_device_t * dev);
+extern void mach64_driver_irq_preinstall(struct drm_device * dev);
+extern void mach64_driver_irq_postinstall(struct drm_device * dev);
+extern void mach64_driver_irq_uninstall(struct drm_device * dev);
 
 /* ================================================================
  * Registers
@@ -798,7 +808,7 @@ do {                                                                        \
 
 #define DMALOCALS                              \
        drm_mach64_freelist_t *_entry = NULL;   \
-       drm_buf_t *_buf = NULL;                 \
+       struct drm_buf *_buf = NULL;            \
        u32 *_buf_wptr; int _outcount
 
 #define GETBUFPTR( __buf )                                             \
@@ -813,20 +823,20 @@ do {                                                                      \
 static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t *
                                                    dev_priv,
                                                    drm_mach64_freelist_t **
-                                                   entry, drm_buf_t * buf)
+                                                   entry, struct drm_buf * buf)
 {
        struct list_head *ptr;
 #if MACH64_EXTRA_CHECKING
        if (list_empty(&dev_priv->pending)) {
                DRM_ERROR("Empty pending list in %s\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 #endif
        ptr = dev_priv->pending.prev;
        *entry = list_entry(ptr, drm_mach64_freelist_t, list);
        while ((*entry)->buf != buf) {
                if (ptr == &dev_priv->pending) {
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                }
                ptr = ptr->prev;
                *entry = list_entry(ptr, drm_mach64_freelist_t, list);
@@ -842,7 +852,7 @@ do {                                                \
 } while(0)
 
 /* FIXME: use a private set of smaller buffers for state emits, clears, and swaps? */
-#define DMAGETPTR( filp, dev_priv, n )                                 \
+#define DMAGETPTR( file_priv, dev_priv, n )                            \
 do {                                                                   \
        if ( MACH64_VERBOSE ) {                                         \
                DRM_INFO( "DMAGETPTR( %d ) in %s\n",                    \
@@ -852,14 +862,14 @@ do {                                                                      \
        if (_buf == NULL) {                                             \
                DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n",     \
                           __FUNCTION__ );                              \
-               return DRM_ERR(EAGAIN);                                 \
+               return -EAGAIN;                                 \
        }                                                               \
        if (_buf->pending) {                                            \
                DRM_ERROR("%s: pending buf in DMAGETPTR\n",             \
                           __FUNCTION__ );                              \
-               return DRM_ERR(EFAULT);                                 \
+               return -EFAULT;                                 \
        }                                                               \
-       _buf->filp = filp;                                              \
+       _buf->file_priv = file_priv;                                    \
        _outcount = 0;                                                  \
                                                                        \
         _buf_wptr = GETBUFPTR( _buf );                                 \
@@ -888,7 +898,7 @@ do {                                                                                             \
        if (_buf->used <= 0) {                                                               \
                DRM_ERROR( "DMAADVANCE() in %s: sending empty buf %d\n",                     \
                                   __FUNCTION__, _buf->idx );                                \
-               return DRM_ERR(EFAULT);                                                      \
+               return -EFAULT;                                                      \
        }                                                                                    \
        if (_buf->pending) {                                                                 \
                 /* This is a resued buffer, so we need to find it in the pending list */     \
@@ -901,13 +911,13 @@ do {                                                                                           \
                if (_entry->discard) {                                                       \
                        DRM_ERROR( "DMAADVANCE() in %s: sending discarded pending buf %d\n", \
                                   __FUNCTION__, _buf->idx );                                \
-                       return DRM_ERR(EFAULT);                                              \
+                       return -EFAULT;                                              \
                }                                                                            \
        } else {                                                                             \
                if (list_empty(&dev_priv->placeholders)) {                                   \
                        DRM_ERROR( "DMAADVANCE() in %s: empty placeholder list\n",           \
                                __FUNCTION__ );                                              \
-                       return DRM_ERR(EFAULT);                                              \
+                       return -EFAULT;                                              \
                }                                                                            \
                ptr = dev_priv->placeholders.next;                                           \
                list_del(ptr);                                                               \
@@ -983,12 +993,12 @@ do {                                                                                      \
        if (_buf->used <= 0) {                                                          \
                DRM_ERROR( "DMAADVANCEHOSTDATA() in %s: sending empty buf %d\n",        \
                                   __FUNCTION__, _buf->idx );                           \
-               return DRM_ERR(EFAULT);                                                 \
+               return -EFAULT;                                                 \
        }                                                                               \
        if (list_empty(&dev_priv->placeholders)) {                                      \
                DRM_ERROR( "%s: empty placeholder list in DMAADVANCEHOSTDATA()\n",      \
                           __FUNCTION__ );                                              \
-               return DRM_ERR(EFAULT);                                                 \
+               return -EFAULT;                                                 \
        }                                                                               \
                                                                                        \
         ptr = dev_priv->placeholders.next;                                             \
index 663642d..4122dd9 100644 (file)
@@ -42,7 +42,7 @@
 
 irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS)
 {
-       drm_device_t *dev = (drm_device_t *) arg;
+       struct drm_device *dev = (struct drm_device *) arg;
        drm_mach64_private_t *dev_priv =
            (drm_mach64_private_t *) dev->dev_private;
        int status;
@@ -70,7 +70,7 @@ irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS)
        return IRQ_NONE;
 }
 
-int mach64_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int mach64_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
        unsigned int cur_vblank;
        int ret = 0;
@@ -90,7 +90,7 @@ int mach64_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
 
 /* drm_dma.h hooks
 */
-void mach64_driver_irq_preinstall(drm_device_t * dev)
+void mach64_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_mach64_private_t *dev_priv =
            (drm_mach64_private_t *) dev->dev_private;
@@ -104,7 +104,7 @@ void mach64_driver_irq_preinstall(drm_device_t * dev)
                     | MACH64_CRTC_VBLANK_INT);
 }
 
-void mach64_driver_irq_postinstall(drm_device_t * dev)
+void mach64_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_mach64_private_t *dev_priv =
            (drm_mach64_private_t *) dev->dev_private;
@@ -118,7 +118,7 @@ void mach64_driver_irq_postinstall(drm_device_t * dev)
 
 }
 
-void mach64_driver_irq_uninstall(drm_device_t * dev)
+void mach64_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_mach64_private_t *dev_priv =
            (drm_mach64_private_t *) dev->dev_private;
index 38cefca..89b6c6c 100644 (file)
  * 1.0 - Initial mach64 DRM
  *
  */
-drm_ioctl_desc_t mach64_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_MACH64_INIT)] = {mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_MACH64_CLEAR)] = {mach64_dma_clear, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MACH64_SWAP)] = {mach64_dma_swap, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MACH64_IDLE)] = {mach64_dma_idle, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MACH64_RESET)] = {mach64_engine_reset, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MACH64_VERTEX)] = {mach64_dma_vertex, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MACH64_BLIT)] = {mach64_dma_blit, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MACH64_FLUSH)] = {mach64_dma_flush, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MACH64_GETPARAM)] = {mach64_get_param, DRM_AUTH},
+struct drm_ioctl_desc mach64_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_MACH64_INIT, mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_MACH64_CLEAR, mach64_dma_clear, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MACH64_SWAP, mach64_dma_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MACH64_IDLE, mach64_dma_idle, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MACH64_RESET, mach64_engine_reset, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MACH64_VERTEX, mach64_dma_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MACH64_BLIT, mach64_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MACH64_FLUSH, mach64_dma_flush, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MACH64_GETPARAM, mach64_get_param, DRM_AUTH),
 };
 
 int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls);
@@ -85,11 +85,12 @@ static void mach64_print_dirty(const char *msg, unsigned int flags)
 /* This function returns 0 on success, 1 for no intersection, and
  * negative for an error
  */
-static int mach64_emit_cliprect(DRMFILE filp, drm_mach64_private_t * dev_priv,
-                               drm_clip_rect_t * box)
+static int mach64_emit_cliprect(struct drm_file *file_priv,
+                               drm_mach64_private_t * dev_priv,
+                               struct drm_clip_rect * box)
 {
        u32 sc_left_right, sc_top_bottom;
-       drm_clip_rect_t scissor;
+       struct drm_clip_rect scissor;
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_mach64_context_regs_t *regs = &sarea_priv->context_state;
        DMALOCALS;
@@ -120,7 +121,7 @@ static int mach64_emit_cliprect(DRMFILE filp, drm_mach64_private_t * dev_priv,
        if (scissor.y1 >= scissor.y2)
                return 1;
 
-       DMAGETPTR(filp, dev_priv, 2);   /* returns on failure to get buffer */
+       DMAGETPTR(file_priv, dev_priv, 2);      /* returns on failure to get buffer */
 
        sc_left_right = ((scissor.x1 << 0) | (scissor.x2 << 16));
        sc_top_bottom = ((scissor.y1 << 0) | (scissor.y2 << 16));
@@ -133,7 +134,7 @@ static int mach64_emit_cliprect(DRMFILE filp, drm_mach64_private_t * dev_priv,
        return 0;
 }
 
-static __inline__ int mach64_emit_state(DRMFILE filp,
+static __inline__ int mach64_emit_state(struct drm_file *file_priv,
                                        drm_mach64_private_t * dev_priv)
 {
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -148,7 +149,7 @@ static __inline__ int mach64_emit_state(DRMFILE filp,
                DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
        }
 
-       DMAGETPTR(filp, dev_priv, 17);  /* returns on failure to get buffer */
+       DMAGETPTR(file_priv, dev_priv, 17);     /* returns on failure to get buffer */
 
        if (dirty & MACH64_UPLOAD_MISC) {
                DMAOUTREG(MACH64_DP_MIX, regs->dp_mix);
@@ -212,7 +213,8 @@ static __inline__ int mach64_emit_state(DRMFILE filp,
  * DMA command dispatch functions
  */
 
-static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev,
+static int mach64_dma_dispatch_clear(struct drm_device * dev,
+                                    struct drm_file *file_priv,
                                     unsigned int flags,
                                     int cx, int cy, int cw, int ch,
                                     unsigned int clear_color,
@@ -222,7 +224,7 @@ static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev,
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_mach64_context_regs_t *ctx = &sarea_priv->context_state;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        u32 fb_bpp, depth_bpp;
        int i;
        DMALOCALS;
@@ -237,7 +239,7 @@ static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev,
                fb_bpp = MACH64_DATATYPE_ARGB8888;
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        switch (dev_priv->depth_bpp) {
        case 16:
@@ -248,13 +250,13 @@ static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev,
                depth_bpp = MACH64_DATATYPE_ARGB8888;
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (!nbox)
                return 0;
 
-       DMAGETPTR(filp, dev_priv, nbox * 31);   /* returns on failure to get buffer */
+       DMAGETPTR(file_priv, dev_priv, nbox * 31);      /* returns on failure to get buffer */
 
        for (i = 0; i < nbox; i++) {
                int x = pbox[i].x1;
@@ -355,12 +357,13 @@ static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev,
        return 0;
 }
 
-static int mach64_dma_dispatch_swap(DRMFILE filp, drm_device_t * dev)
+static int mach64_dma_dispatch_swap(struct drm_device * dev,
+                                   struct drm_file *file_priv)
 {
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        u32 fb_bpp;
        int i;
        DMALOCALS;
@@ -380,7 +383,7 @@ static int mach64_dma_dispatch_swap(DRMFILE filp, drm_device_t * dev)
        if (!nbox)
                return 0;
 
-       DMAGETPTR(filp, dev_priv, 13 + nbox * 4);       /* returns on failure to get buffer */
+       DMAGETPTR(file_priv, dev_priv, 13 + nbox * 4);  /* returns on failure to get buffer */
 
        DMAOUTREG(MACH64_Z_CNTL, 0);
        DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
@@ -489,11 +492,11 @@ static __inline__ int copy_from_user_vertex(u32 *to,
 
        from = drm_alloc(bytes, DRM_MEM_DRIVER);
        if (from == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        if (DRM_COPY_FROM_USER(from, ufrom, bytes)) {
                drm_free(from, bytes, DRM_MEM_DRIVER);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
        orig_from = from; /* we'll be modifying the "from" ptr, so save it */
 
@@ -525,14 +528,14 @@ static __inline__ int copy_from_user_vertex(u32 *to,
                                DRM_ERROR("%s: Got bad command: 0x%04x\n",
                                          __FUNCTION__, reg);
                                drm_free(orig_from, bytes, DRM_MEM_DRIVER);
-                               return DRM_ERR(EACCES);
+                               return -EACCES;
                        }
                } else {
                        DRM_ERROR
                            ("%s: Got bad command count(=%u) dwords remaining=%lu\n",
                             __FUNCTION__, count, n);
                        drm_free(orig_from, bytes, DRM_MEM_DRIVER);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
@@ -541,16 +544,17 @@ static __inline__ int copy_from_user_vertex(u32 *to,
                return 0;
        else {
                DRM_ERROR("%s: Bad buf->used(=%lu)\n", __FUNCTION__, bytes);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 }
 
-static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev,
+static int mach64_dma_dispatch_vertex(struct drm_device * dev,
+                                     struct drm_file *file_priv,
                                      drm_mach64_vertex_t * vertex)
 {
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_buf_t *copy_buf;
+       struct drm_buf *copy_buf;
        void *buf = vertex->buf;
        unsigned long used = vertex->used;
        int ret = 0;
@@ -568,7 +572,7 @@ static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev,
        copy_buf = mach64_freelist_get(dev_priv);
        if (copy_buf == NULL) {
                DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__);
-               return DRM_ERR(EAGAIN);
+               return -EAGAIN;
        }
 
        verify_ret = copy_from_user_vertex(GETBUFPTR(copy_buf), buf, used);
@@ -583,7 +587,7 @@ static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev,
        DMASETPTR(copy_buf);
 
        if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) {
-               ret = mach64_emit_state(filp, dev_priv);
+               ret = mach64_emit_state(file_priv, dev_priv);
                if (ret < 0)
                        return ret;
        }
@@ -591,7 +595,7 @@ static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev,
        do {
                /* Emit the next cliprect */
                if (i < sarea_priv->nbox) {
-                       ret = mach64_emit_cliprect(filp, dev_priv,
+                       ret = mach64_emit_cliprect(file_priv, dev_priv,
                                                   &sarea_priv->boxes[i]);
                        if (ret < 0) {
                                /* failed to get buffer */
@@ -634,19 +638,20 @@ static __inline__ int copy_from_user_blit(u32 *to,
        to = (u32 *)((char *)to + MACH64_HOSTDATA_BLIT_OFFSET);
 
        if (DRM_COPY_FROM_USER(to, ufrom, bytes)) {
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
 }
 
-static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev,
+static int mach64_dma_dispatch_blit(struct drm_device * dev,
+                                   struct drm_file *file_priv,
                                    drm_mach64_blit_t * blit)
 {
        drm_mach64_private_t *dev_priv = dev->dev_private;
        int dword_shift, dwords;
        unsigned long used;
-       drm_buf_t *copy_buf;
+       struct drm_buf *copy_buf;
        int verify_ret = 0;
        DMALOCALS;
 
@@ -671,7 +676,7 @@ static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev,
                break;
        default:
                DRM_ERROR("invalid blit format %d\n", blit->format);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /* Set buf->used to the bytes of blit data based on the blit dimensions
@@ -684,13 +689,13 @@ static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev,
        if (used <= 0 ||
            used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) {
                DRM_ERROR("Invalid blit size: %lu bytes\n", used);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        copy_buf = mach64_freelist_get(dev_priv);
        if (copy_buf == NULL) {
                DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__);
-               return DRM_ERR(EAGAIN);
+               return -EAGAIN;
        }
 
        verify_ret = copy_from_user_blit(GETBUFPTR(copy_buf), blit->buf, used);
@@ -753,27 +758,25 @@ _blit_done:
  * IOCTL functions
  */
 
-int mach64_dma_clear(DRM_IOCTL_ARGS)
+int mach64_dma_clear(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mach64_clear_t clear;
+       drm_mach64_clear_t *clear = data;
        int ret;
 
        DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(clear, (drm_mach64_clear_t *) data,
-                                sizeof(clear));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
 
-       ret = mach64_dma_dispatch_clear(filp, dev, clear.flags,
-                                       clear.x, clear.y, clear.w, clear.h,
-                                       clear.clear_color, clear.clear_depth);
+       ret = mach64_dma_dispatch_clear(dev, file_priv, clear->flags,
+                                       clear->x, clear->y, clear->w, clear->h,
+                                       clear->clear_color,
+                                       clear->clear_depth);
 
        /* Make sure we restore the 3D state next time.
         */
@@ -781,21 +784,21 @@ int mach64_dma_clear(DRM_IOCTL_ARGS)
        return ret;
 }
 
-int mach64_dma_swap(DRM_IOCTL_ARGS)
+int mach64_dma_swap(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int ret;
 
        DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
 
-       ret = mach64_dma_dispatch_swap(filp, dev);
+       ret = mach64_dma_dispatch_swap(dev, file_priv);
 
        /* Make sure we restore the 3D state next time.
         */
@@ -803,58 +806,52 @@ int mach64_dma_swap(DRM_IOCTL_ARGS)
        return ret;
 }
 
-int mach64_dma_vertex(DRM_IOCTL_ARGS)
+int mach64_dma_vertex(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mach64_vertex_t vertex;
+       drm_mach64_vertex_t *vertex = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(vertex, (drm_mach64_vertex_t *) data,
-                                sizeof(vertex));
-
        DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n",
                  __FUNCTION__, DRM_CURRENTPID,
-                 vertex.buf, vertex.used, vertex.discard);
+                 vertex->buf, vertex->used, vertex->discard);
 
-       if (vertex.prim < 0 || vertex.prim > MACH64_PRIM_POLYGON) {
-               DRM_ERROR("buffer prim %d\n", vertex.prim);
-               return DRM_ERR(EINVAL);
+       if (vertex->prim < 0 || vertex->prim > MACH64_PRIM_POLYGON) {
+               DRM_ERROR("buffer prim %d\n", vertex->prim);
+               return -EINVAL;
        }
 
-       if (vertex.used > MACH64_BUFFER_SIZE || (vertex.used & 3) != 0) {
+       if (vertex->used > MACH64_BUFFER_SIZE || (vertex->used & 3) != 0) {
                DRM_ERROR("Invalid vertex buffer size: %lu bytes\n",
-                         vertex.used);
-               return DRM_ERR(EINVAL);
+                         vertex->used);
+               return -EINVAL;
        }
 
        if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
 
-       return mach64_dma_dispatch_vertex(filp, dev, &vertex);
+       return mach64_dma_dispatch_vertex(dev, file_priv, vertex);
 }
 
-int mach64_dma_blit(DRM_IOCTL_ARGS)
+int mach64_dma_blit(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
        drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mach64_blit_t blit;
+       drm_mach64_blit_t *blit = data;
        int ret;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_COPY_FROM_USER_IOCTL(blit, (drm_mach64_blit_t *) data,
-                                sizeof(blit));
-
-       ret = mach64_dma_dispatch_blit(filp, dev, &blit);
+       ret = mach64_dma_dispatch_blit(dev, file_priv, blit);
 
        /* Make sure we restore the 3D state next time.
         */
@@ -864,39 +861,36 @@ int mach64_dma_blit(DRM_IOCTL_ARGS)
        return ret;
 }
 
-int mach64_get_param(DRM_IOCTL_ARGS)
+int mach64_get_param(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mach64_private_t *dev_priv = dev->dev_private;
-       drm_mach64_getparam_t param;
+       drm_mach64_getparam_t *param = data;
        int value;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(param, (drm_mach64_getparam_t *) data,
-                                sizeof(param));
-
-       switch (param.param) {
+       switch (param->param) {
        case MACH64_PARAM_FRAMES_QUEUED:
                /* Needs lock since it calls mach64_ring_tick() */
-               LOCK_TEST_WITH_RETURN(dev, filp);
+               LOCK_TEST_WITH_RETURN(dev, file_priv);
                value = mach64_do_get_frames_queued(dev_priv);
                break;
        case MACH64_PARAM_IRQ_NR:
                value = dev->irq;
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
index d48313c..a86dd31 100644 (file)
@@ -46,7 +46,7 @@
 
 #define MINIMAL_CLEANUP    0
 #define FULL_CLEANUP       1
-static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup);
+static int mga_do_cleanup_dma(struct drm_device * dev, int full_cleanup);
 
 /* ================================================================
  * Engine control
@@ -71,7 +71,7 @@ int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
        DRM_ERROR("failed!\n");
        DRM_INFO("   status=0x%08x\n", status);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
@@ -224,7 +224,7 @@ void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
 #define MGA_BUFFER_FREE                0
 
 #if MGA_FREELIST_DEBUG
-static void mga_freelist_print(drm_device_t * dev)
+static void mga_freelist_print(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_freelist_t *entry;
@@ -245,10 +245,10 @@ static void mga_freelist_print(drm_device_t * dev)
 }
 #endif
 
-static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
+static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
 {
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_mga_buf_priv_t *buf_priv;
        drm_mga_freelist_t *entry;
        int i;
@@ -256,7 +256,7 @@ static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
 
        dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
        if (dev_priv->head == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
        SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
@@ -267,7 +267,7 @@ static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
 
                entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
                if (entry == NULL)
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
 
                memset(entry, 0, sizeof(drm_mga_freelist_t));
 
@@ -291,7 +291,7 @@ static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
        return 0;
 }
 
-static void mga_freelist_cleanup(drm_device_t * dev)
+static void mga_freelist_cleanup(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_freelist_t *entry;
@@ -311,10 +311,10 @@ static void mga_freelist_cleanup(drm_device_t * dev)
 #if 0
 /* FIXME: Still needed?
  */
-static void mga_freelist_reset(drm_device_t * dev)
+static void mga_freelist_reset(struct drm_device * dev)
 {
        drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        drm_mga_buf_priv_t *buf_priv;
        int i;
 
@@ -326,7 +326,7 @@ static void mga_freelist_reset(drm_device_t * dev)
 }
 #endif
 
-static drm_buf_t *mga_freelist_get(drm_device_t * dev)
+static struct drm_buf *mga_freelist_get(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_freelist_t *next;
@@ -359,7 +359,7 @@ static drm_buf_t *mga_freelist_get(drm_device_t * dev)
        return NULL;
 }
 
-int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -393,13 +393,13 @@ int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
  * DMA initialization, cleanup
  */
 
-int mga_driver_load(drm_device_t *dev, unsigned long flags)
+int mga_driver_load(struct drm_device *dev, unsigned long flags)
 {
        drm_mga_private_t * dev_priv;
 
        dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
        if (!dev_priv)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        dev->dev_private = (void *)dev_priv;
        memset(dev_priv, 0, sizeof(drm_mga_private_t));
@@ -433,7 +433,7 @@ int mga_driver_load(drm_device_t *dev, unsigned long flags)
  *
  * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
  */
-static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+static int mga_do_agp_dma_bootstrap(struct drm_device *dev,
                                    drm_mga_dma_bootstrap_t * dma_bs)
 {
        drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
@@ -443,11 +443,11 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
        const unsigned secondary_size = dma_bs->secondary_bin_count
                * dma_bs->secondary_bin_size;
        const unsigned agp_size = (dma_bs->agp_size << 20);
-       drm_buf_desc_t req;
-       drm_agp_mode_t mode;
-       drm_agp_info_t info;
-       drm_agp_buffer_t agp_req;
-       drm_agp_binding_t bind_req;
+       struct drm_buf_desc req;
+       struct drm_agp_mode mode;
+       struct drm_agp_info info;
+       struct drm_agp_buffer agp_req;
+       struct drm_agp_binding bind_req;
 
        /* Acquire AGP. */
        err = drm_agp_acquire(dev);
@@ -548,7 +548,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
 
 #ifdef __linux__
        {
-               drm_map_list_t *_entry;
+               struct drm_map_list *_entry;
                unsigned long agp_token = 0;
 
                list_for_each_entry(_entry, &dev->maplist, head) {
@@ -579,7 +579,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
                DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
                          dev_priv->warp->handle, dev_priv->primary->handle,
                          dev->agp_buffer_map->handle);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        dev_priv->dma_access = MGA_PAGPXFER;
@@ -603,7 +603,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
  * 
  * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
  */
-static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
                                    drm_mga_dma_bootstrap_t * dma_bs)
 {
        drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
@@ -611,12 +611,12 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
        unsigned int primary_size;
        unsigned int bin_count;
        int err;
-       drm_buf_desc_t req;
+       struct drm_buf_desc req;
 
        
        if (dev->dma == NULL) {
                DRM_ERROR("dev->dma is NULL\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        /* Make drm_addbufs happy by not trying to create a mapping for less
@@ -651,7 +651,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
 
        if (err != 0) {
                DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        if (dev_priv->primary->size != dma_bs->primary_size) {
@@ -696,7 +696,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
 }
 
 
-static int mga_do_dma_bootstrap(drm_device_t * dev,
+static int mga_do_dma_bootstrap(struct drm_device * dev,
                                drm_mga_dma_bootstrap_t * dma_bs)
 {
        const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
@@ -762,44 +762,37 @@ static int mga_do_dma_bootstrap(drm_device_t * dev,
        return err;
 }
 
-int mga_dma_bootstrap(DRM_IOCTL_ARGS)
+int mga_dma_bootstrap(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_mga_dma_bootstrap_t bootstrap;
+       drm_mga_dma_bootstrap_t *bootstrap = data;
        int err;
        static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
        const drm_mga_private_t * const dev_priv = 
                (drm_mga_private_t *) dev->dev_private;
 
 
-       DRM_COPY_FROM_USER_IOCTL(bootstrap,
-                                (drm_mga_dma_bootstrap_t __user *) data,
-                                sizeof(bootstrap));
-
-       err = mga_do_dma_bootstrap(dev, & bootstrap);
+       err = mga_do_dma_bootstrap(dev, bootstrap);
        if (err) {
                mga_do_cleanup_dma(dev, FULL_CLEANUP);
                return err;
        }
 
        if (dev_priv->agp_textures != NULL) {
-               bootstrap.texture_handle = dev_priv->agp_textures->offset;
-               bootstrap.texture_size = dev_priv->agp_textures->size;
+               bootstrap->texture_handle = dev_priv->agp_textures->offset;
+               bootstrap->texture_size = dev_priv->agp_textures->size;
        } else {
-               bootstrap.texture_handle = 0;
-               bootstrap.texture_size = 0;
+               bootstrap->texture_handle = 0;
+               bootstrap->texture_size = 0;
        }
 
-       bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
-
-       DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data,
-                              bootstrap, sizeof(bootstrap));
+       bootstrap->agp_mode = modes[bootstrap->agp_mode & 0x07];
 
        return 0;
 }
 
 
-static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
+static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
 {
        drm_mga_private_t *dev_priv;
        int ret;
@@ -833,7 +826,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
        dev_priv->sarea = drm_getsarea(dev);
        if (!dev_priv->sarea) {
                DRM_ERROR("failed to find sarea!\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (! dev_priv->used_new_dma_init) {
@@ -844,28 +837,28 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
                dev_priv->status = drm_core_findmap(dev, init->status_offset);
                if (!dev_priv->status) {
                        DRM_ERROR("failed to find status page!\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
                if (!dev_priv->mmio) {
                        DRM_ERROR("failed to find mmio region!\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
                if (!dev_priv->warp) {
                        DRM_ERROR("failed to find warp microcode region!\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
                if (!dev_priv->primary) {
                        DRM_ERROR("failed to find primary dma region!\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                dev->agp_buffer_token = init->buffers_offset;
                dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
                if (!dev->agp_buffer_map) {
                        DRM_ERROR("failed to find dma buffer region!\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                drm_core_ioremap(dev_priv->warp, dev);
@@ -883,7 +876,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
             ((dev->agp_buffer_map == NULL) ||
              (dev->agp_buffer_map->handle == NULL)))) {
                DRM_ERROR("failed to ioremap agp regions!\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        ret = mga_warp_install_microcode(dev_priv);
@@ -933,13 +926,13 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
 
        if (mga_freelist_init(dev, dev_priv) < 0) {
                DRM_ERROR("could not initialize freelist\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        return 0;
 }
 
-static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup)
+static int mga_do_cleanup_dma(struct drm_device * dev, int full_cleanup)
 {
        int err = 0;
        DRM_DEBUG("\n");
@@ -967,8 +960,8 @@ static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup)
 
                if (dev_priv->used_new_dma_init) {
                        if (dev_priv->agp_handle != 0) {
-                               drm_agp_binding_t unbind_req;
-                               drm_agp_buffer_t free_req;
+                               struct drm_agp_binding unbind_req;
+                               struct drm_agp_buffer free_req;
 
                                unbind_req.handle = dev_priv->agp_handle;
                                drm_agp_unbind(dev, &unbind_req);
@@ -1010,20 +1003,17 @@ static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup)
        return 0;
 }
 
-int mga_dma_init(DRM_IOCTL_ARGS)
+int mga_dma_init(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_mga_init_t init;
+       drm_mga_init_t *init = data;
        int err;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
-                                sizeof(init));
-
-       switch (init.func) {
+       switch (init->func) {
        case MGA_INIT_DMA:
-               err = mga_do_init_dma(dev, &init);
+               err = mga_do_init_dma(dev, init);
                if (err) {
                        (void) mga_do_cleanup_dma(dev, FULL_CLEANUP);
                }
@@ -1032,36 +1022,33 @@ int mga_dma_init(DRM_IOCTL_ARGS)
                return mga_do_cleanup_dma(dev, FULL_CLEANUP);
        }
 
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
 /* ================================================================
  * Primary DMA stream management
  */
 
-int mga_dma_flush(DRM_IOCTL_ARGS)
+int mga_dma_flush(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-       drm_lock_t lock;
-
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       struct drm_lock *lock = data;
 
-       DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
-                                sizeof(lock));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        DRM_DEBUG("%s%s%s\n",
-                 (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
-                 (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
-                 (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
+                 (lock->flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
+                 (lock->flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
+                 (lock->flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
 
        WRAP_WAIT_WITH_RETURN(dev_priv);
 
-       if (lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
+       if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
                mga_do_dma_flush(dev_priv);
        }
 
-       if (lock.flags & _DRM_LOCK_QUIESCENT) {
+       if (lock->flags & _DRM_LOCK_QUIESCENT) {
 #if MGA_DMA_DEBUG
                int ret = mga_do_wait_for_idle(dev_priv);
                if (ret < 0)
@@ -1075,12 +1062,12 @@ int mga_dma_flush(DRM_IOCTL_ARGS)
        }
 }
 
-int mga_dma_reset(DRM_IOCTL_ARGS)
+int mga_dma_reset(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return mga_do_dma_reset(dev_priv);
 }
@@ -1089,76 +1076,72 @@ int mga_dma_reset(DRM_IOCTL_ARGS)
  * DMA buffer management
  */
 
-static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+static int mga_dma_get_buffers(struct drm_device * dev,
+                              struct drm_file *file_priv, struct drm_dma * d)
 {
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        int i;
 
        for (i = d->granted_count; i < d->request_count; i++) {
                buf = mga_freelist_get(dev);
                if (!buf)
-                       return DRM_ERR(EAGAIN);
+                       return -EAGAIN;
 
-               buf->filp = filp;
+               buf->file_priv = file_priv;
 
                if (DRM_COPY_TO_USER(&d->request_indices[i],
                                     &buf->idx, sizeof(buf->idx)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                if (DRM_COPY_TO_USER(&d->request_sizes[i],
                                     &buf->total, sizeof(buf->total)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
 
                d->granted_count++;
        }
        return 0;
 }
 
-int mga_dma_buffers(DRM_IOCTL_ARGS)
+int mga_dma_buffers(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-       drm_dma_t __user *argp = (void __user *)data;
-       drm_dma_t d;
+       struct drm_dma *d = data;
        int ret = 0;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        /* Please don't send us buffers.
         */
-       if (d.send_count != 0) {
+       if (d->send_count != 0) {
                DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d.send_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
        }
 
        /* We'll send you buffers.
         */
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
                DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d.request_count, dma->buf_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
        }
 
        WRAP_TEST_WITH_RETURN(dev_priv);
 
-       d.granted_count = 0;
+       d->granted_count = 0;
 
-       if (d.request_count) {
-               ret = mga_dma_get_buffers(filp, dev, &d);
+       if (d->request_count) {
+               ret = mga_dma_get_buffers(dev, file_priv, d);
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
-
        return ret;
 }
 
 /**
  * Called just before the module is unloaded.
  */
-int mga_driver_unload(drm_device_t * dev)
+int mga_driver_unload(struct drm_device * dev)
 {
        drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
        dev->dev_private = NULL;
@@ -1169,12 +1152,12 @@ int mga_driver_unload(drm_device_t * dev)
 /**
  * Called when the last opener of the device is closed.
  */
-void mga_driver_lastclose(drm_device_t * dev)
+void mga_driver_lastclose(struct drm_device * dev)
 {
        mga_do_cleanup_dma(dev, FULL_CLEANUP);
 }
 
-int mga_driver_dma_quiescent(drm_device_t * dev)
+int mga_driver_dma_quiescent(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        return mga_do_wait_for_idle(dev_priv);
index 5bcdbfa..15c2dea 100644 (file)
@@ -181,7 +181,7 @@ typedef struct _drm_mga_sarea {
 
        /* The current cliprects, or a subset thereof.
         */
-       drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
+       struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS];
        unsigned int nbox;
 
        /* Information about the most recently used 3d drawable.  The
@@ -202,7 +202,7 @@ typedef struct _drm_mga_sarea {
        unsigned int exported_nback;
        int exported_back_x, exported_front_x, exported_w;
        int exported_back_y, exported_front_y, exported_h;
-       drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+       struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS];
 
        /* Counters for aging textures and for client-side throttling.
         */
@@ -216,7 +216,7 @@ typedef struct _drm_mga_sarea {
 
        /* LRU lists for texture memory in agp space and on the card.
         */
-       drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
+       struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
        unsigned int texAge[MGA_NR_TEX_HEAPS];
 
        /* Mechanism to validate card state.
index bce8213..8254c3f 100644 (file)
@@ -65,7 +65,7 @@ typedef struct drm_mga_freelist {
        struct drm_mga_freelist *next;
        struct drm_mga_freelist *prev;
        drm_mga_age_t age;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
 } drm_mga_freelist_t;
 
 typedef struct {
@@ -148,19 +148,24 @@ typedef struct drm_mga_private {
        unsigned int agp_size;
 } drm_mga_private_t;
 
-extern drm_ioctl_desc_t mga_ioctls[];
+extern struct drm_ioctl_desc mga_ioctls[];
 extern int mga_max_ioctl;
 
                                /* mga_dma.c */
-extern int mga_dma_bootstrap(DRM_IOCTL_ARGS);
-extern int mga_dma_init(DRM_IOCTL_ARGS);
-extern int mga_dma_flush(DRM_IOCTL_ARGS);
-extern int mga_dma_reset(DRM_IOCTL_ARGS);
-extern int mga_dma_buffers(DRM_IOCTL_ARGS);
-extern int mga_driver_load(drm_device_t *dev, unsigned long flags);
-extern int mga_driver_unload(drm_device_t * dev);
-extern void mga_driver_lastclose(drm_device_t * dev);
-extern int mga_driver_dma_quiescent(drm_device_t * dev);
+extern int mga_dma_bootstrap(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv);
+extern int mga_dma_init(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int mga_dma_flush(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int mga_dma_reset(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int mga_dma_buffers(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
+extern int mga_driver_unload(struct drm_device * dev);
+extern void mga_driver_lastclose(struct drm_device * dev);
+extern int mga_driver_dma_quiescent(struct drm_device * dev);
 
 extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
 
@@ -168,7 +173,7 @@ extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
 extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
 extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
 
-extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
 
                                /* mga_warp.c */
 extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
@@ -176,12 +181,12 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
 extern int mga_warp_init(drm_mga_private_t * dev_priv);
 
                                /* mga_irq.c */
-extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
-extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mga_driver_irq_preinstall(drm_device_t * dev);
-extern void mga_driver_irq_postinstall(drm_device_t * dev);
-extern void mga_driver_irq_uninstall(drm_device_t * dev);
+extern void mga_driver_irq_preinstall(struct drm_device * dev);
+extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern void mga_driver_irq_uninstall(struct drm_device * dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
 
@@ -245,7 +250,7 @@ do {                                                                        \
                            dev_priv->prim.high_mark ) {                \
                        if ( MGA_DMA_DEBUG )                            \
                                DRM_INFO( "%s: wrap...\n", __FUNCTION__ );      \
-                       return DRM_ERR(EBUSY);                  \
+                       return -EBUSY;                  \
                }                                                       \
        }                                                               \
 } while (0)
@@ -256,7 +261,7 @@ do {                                                                        \
                if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {           \
                        if ( MGA_DMA_DEBUG )                            \
                                DRM_INFO( "%s: wrap...\n", __FUNCTION__ );      \
-                       return DRM_ERR(EBUSY);                  \
+                       return -EBUSY;                  \
                }                                                       \
                mga_do_dma_wrap_end( dev_priv );                        \
        }                                                               \
index 490d1fb..8b555e2 100644 (file)
@@ -38,7 +38,7 @@
 
 irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 {
-       drm_device_t *dev = (drm_device_t *) arg;
+       struct drm_device *dev = (struct drm_device *) arg;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
        int status;
        int handled = 0;
@@ -80,7 +80,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
        return IRQ_NONE;
 }
 
-int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
        unsigned int cur_vblank;
        int ret = 0;
@@ -98,7 +98,7 @@ int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
        return ret;
 }
 
-int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
        unsigned int cur_fence;
@@ -117,7 +117,7 @@ int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
        return ret;
 }
 
-void mga_driver_irq_preinstall(drm_device_t * dev)
+void mga_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
@@ -127,7 +127,7 @@ void mga_driver_irq_preinstall(drm_device_t * dev)
        MGA_WRITE(MGA_ICLEAR, ~0);
 }
 
-void mga_driver_irq_postinstall(drm_device_t * dev)
+void mga_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
@@ -137,7 +137,7 @@ void mga_driver_irq_postinstall(drm_device_t * dev)
        MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
 }
 
-void mga_driver_irq_uninstall(drm_device_t * dev)
+void mga_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
        if (!dev_priv)
index 8e5cb33..70b7caa 100644 (file)
@@ -43,7 +43,7 @@
  */
 
 static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
-                              drm_clip_rect_t * box)
+                              struct drm_clip_rect * box)
 {
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -416,7 +416,7 @@ static int mga_verify_context(drm_mga_private_t * dev_priv)
                          ctx->dstorg, dev_priv->front_offset,
                          dev_priv->back_offset);
                ctx->dstorg = 0;
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
@@ -435,7 +435,7 @@ static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
        if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
                DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
                tex->texorg = 0;
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
@@ -477,13 +477,13 @@ static int mga_verify_iload(drm_mga_private_t * dev_priv,
            dstorg + length > (dev_priv->texture_offset +
                               dev_priv->texture_size)) {
                DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (length & MGA_ILOAD_MASK) {
                DRM_ERROR("*** bad iload length: 0x%x\n",
                          length & MGA_ILOAD_MASK);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
@@ -495,7 +495,7 @@ static int mga_verify_blit(drm_mga_private_t * dev_priv,
        if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
            (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
                DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        return 0;
 }
@@ -504,12 +504,12 @@ static int mga_verify_blit(drm_mga_private_t * dev_priv,
  *
  */
 
-static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
+static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int nbox = sarea_priv->nbox;
        int i;
        DMA_LOCALS;
@@ -525,7 +525,7 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
        ADVANCE_DMA();
 
        for (i = 0; i < nbox; i++) {
-               drm_clip_rect_t *box = &pbox[i];
+               struct drm_clip_rect *box = &pbox[i];
                u32 height = box->y2 - box->y1;
 
                DRM_DEBUG("   from=%d,%d to=%d,%d\n",
@@ -594,12 +594,12 @@ static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
        FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_swap(drm_device_t * dev)
+static void mga_dma_dispatch_swap(struct drm_device * dev)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int nbox = sarea_priv->nbox;
        int i;
        DMA_LOCALS;
@@ -626,7 +626,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev)
                  MGA_DWGCTL, MGA_DWGCTL_COPY);
 
        for (i = 0; i < nbox; i++) {
-               drm_clip_rect_t *box = &pbox[i];
+               struct drm_clip_rect *box = &pbox[i];
                u32 height = box->y2 - box->y1;
                u32 start = box->y1 * dev_priv->front_pitch;
 
@@ -651,7 +651,7 @@ static void mga_dma_dispatch_swap(drm_device_t * dev)
        DRM_DEBUG("%s... done.\n", __FUNCTION__);
 }
 
-static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -698,7 +698,7 @@ static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
        FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
+static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
                                     unsigned int start, unsigned int end)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
@@ -747,7 +747,7 @@ static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
 /* This copies a 64 byte aligned agp region to the frambuffer with a
  * standard blit, the ioctl needs to do checking.
  */
-static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
+static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
                                   unsigned int dstorg, unsigned int length)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
@@ -800,12 +800,12 @@ static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
        FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
+static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int nbox = sarea_priv->nbox;
        u32 scandir = 0, i;
        DMA_LOCALS;
@@ -865,24 +865,20 @@ static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
  *
  */
 
-static int mga_dma_clear(DRM_IOCTL_ARGS)
+static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_clear_t clear;
+       drm_mga_clear_t *clear = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data,
-                                sizeof(clear));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
        WRAP_TEST_WITH_RETURN(dev_priv);
 
-       mga_dma_dispatch_clear(dev, &clear);
+       mga_dma_dispatch_clear(dev, clear);
 
        /* Make sure we restore the 3D state next time.
         */
@@ -891,13 +887,12 @@ static int mga_dma_clear(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int mga_dma_swap(DRM_IOCTL_ARGS)
+static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
@@ -913,37 +908,32 @@ static int mga_dma_swap(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int mga_dma_vertex(DRM_IOCTL_ARGS)
+static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_mga_buf_priv_t *buf_priv;
-       drm_mga_vertex_t vertex;
-
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       drm_mga_vertex_t *vertex = data;
 
-       DRM_COPY_FROM_USER_IOCTL(vertex,
-                                (drm_mga_vertex_t __user *) data,
-                                sizeof(vertex));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (vertex.idx < 0 || vertex.idx > dma->buf_count)
-               return DRM_ERR(EINVAL);
-       buf = dma->buflist[vertex.idx];
+       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
+               return -EINVAL;
+       buf = dma->buflist[vertex->idx];
        buf_priv = buf->dev_private;
 
-       buf->used = vertex.used;
-       buf_priv->discard = vertex.discard;
+       buf->used = vertex->used;
+       buf_priv->discard = vertex->discard;
 
        if (!mga_verify_state(dev_priv)) {
-               if (vertex.discard) {
+               if (vertex->discard) {
                        if (buf_priv->dispatched == 1)
                                AGE_BUFFER(buf_priv);
                        buf_priv->dispatched = 0;
                        mga_freelist_put(dev, buf);
                }
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        WRAP_TEST_WITH_RETURN(dev_priv);
@@ -953,82 +943,73 @@ static int mga_dma_vertex(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int mga_dma_indices(DRM_IOCTL_ARGS)
+static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_mga_buf_priv_t *buf_priv;
-       drm_mga_indices_t indices;
-
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       drm_mga_indices_t *indices = data;
 
-       DRM_COPY_FROM_USER_IOCTL(indices,
-                                (drm_mga_indices_t __user *) data,
-                                sizeof(indices));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (indices.idx < 0 || indices.idx > dma->buf_count)
-               return DRM_ERR(EINVAL);
+       if (indices->idx < 0 || indices->idx > dma->buf_count)
+               return -EINVAL;
 
-       buf = dma->buflist[indices.idx];
+       buf = dma->buflist[indices->idx];
        buf_priv = buf->dev_private;
 
-       buf_priv->discard = indices.discard;
+       buf_priv->discard = indices->discard;
 
        if (!mga_verify_state(dev_priv)) {
-               if (indices.discard) {
+               if (indices->discard) {
                        if (buf_priv->dispatched == 1)
                                AGE_BUFFER(buf_priv);
                        buf_priv->dispatched = 0;
                        mga_freelist_put(dev, buf);
                }
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        WRAP_TEST_WITH_RETURN(dev_priv);
 
-       mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
+       mga_dma_dispatch_indices(dev, buf, indices->start, indices->end);
 
        return 0;
 }
 
-static int mga_dma_iload(DRM_IOCTL_ARGS)
+static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        drm_mga_buf_priv_t *buf_priv;
-       drm_mga_iload_t iload;
+       drm_mga_iload_t *iload = data;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data,
-                                sizeof(iload));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 #if 0
        if (mga_do_wait_for_idle(dev_priv) < 0) {
                if (MGA_DMA_DEBUG)
                        DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
-               return DRM_ERR(EBUSY);
+               return -EBUSY;
        }
 #endif
-       if (iload.idx < 0 || iload.idx > dma->buf_count)
-               return DRM_ERR(EINVAL);
+       if (iload->idx < 0 || iload->idx > dma->buf_count)
+               return -EINVAL;
 
-       buf = dma->buflist[iload.idx];
+       buf = dma->buflist[iload->idx];
        buf_priv = buf->dev_private;
 
-       if (mga_verify_iload(dev_priv, iload.dstorg, iload.length)) {
+       if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) {
                mga_freelist_put(dev, buf);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        WRAP_TEST_WITH_RETURN(dev_priv);
 
-       mga_dma_dispatch_iload(dev, buf, iload.dstorg, iload.length);
+       mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length);
 
        /* Make sure we restore the 3D state next time.
         */
@@ -1037,28 +1018,24 @@ static int mga_dma_iload(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int mga_dma_blit(DRM_IOCTL_ARGS)
+static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_blit_t blit;
+       drm_mga_blit_t *blit = data;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data,
-                                sizeof(blit));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
-       if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg))
-               return DRM_ERR(EINVAL);
+       if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg))
+               return -EINVAL;
 
        WRAP_TEST_WITH_RETURN(dev_priv);
 
-       mga_dma_dispatch_blit(dev, &blit);
+       mga_dma_dispatch_blit(dev, blit);
 
        /* Make sure we restore the 3D state next time.
         */
@@ -1067,24 +1044,20 @@ static int mga_dma_blit(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int mga_getparam(DRM_IOCTL_ARGS)
+static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_getparam_t param;
+       drm_mga_getparam_t *param = data;
        int value;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(param, (drm_mga_getparam_t __user *) data,
-                                sizeof(param));
-
        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
 
-       switch (param.param) {
+       switch (param->param) {
        case MGA_PARAM_IRQ_NR:
                value = dev->irq;
                break;
@@ -1092,36 +1065,35 @@ static int mga_getparam(DRM_IOCTL_ARGS)
                value = dev_priv->chipset;
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
 }
 
-static int mga_set_fence(DRM_IOCTL_ARGS)
+static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
-       u32 temp;
+       u32 *fence = data;
        DMA_LOCALS;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
 
-       /* I would normal do this assignment in the declaration of temp,
+       /* I would normal do this assignment in the declaration of fence,
         * but dev_priv may be NULL.
         */
 
-       temp = dev_priv->next_fence_to_post;
+       *fence = dev_priv->next_fence_to_post;
        dev_priv->next_fence_to_post++;
 
        BEGIN_DMA(1);
@@ -1131,47 +1103,40 @@ static int mga_set_fence(DRM_IOCTL_ARGS)
                  MGA_SOFTRAP, 0x00000000);
        ADVANCE_DMA();
 
-       DRM_COPY_TO_USER_IOCTL((u32 __user *)data, temp, sizeof(u32));
-
        return 0;
 }
 
-static int mga_wait_fence(DRM_IOCTL_ARGS)
+static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_mga_private_t *dev_priv = dev->dev_private;
-       u32 fence;
+       u32 *fence = data;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32));
-
        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
 
-       mga_driver_fence_wait(dev, & fence);
-
-       DRM_COPY_TO_USER_IOCTL((u32 __user *)data, fence, sizeof(u32));
+       mga_driver_fence_wait(dev, fence);
 
        return 0;
 }
 
-drm_ioctl_desc_t mga_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+struct drm_ioctl_desc mga_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_MGA_FLUSH, mga_dma_flush, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_RESET, mga_dma_reset, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_SWAP, mga_dma_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_CLEAR, mga_dma_clear, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_VERTEX, mga_dma_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_INDICES, mga_dma_indices, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_ILOAD, mga_dma_iload, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_BLIT, mga_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_GETPARAM, mga_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_SET_FENCE, mga_set_fence, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
 };
 
index 05ed805..9a44bdd 100644 (file)
@@ -146,7 +146,7 @@ int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
        if (size > dev_priv->warp->size) {
                DRM_ERROR("microcode too large! (%u > %lu)\n",
                          size, dev_priv->warp->size);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        switch (dev_priv->chipset) {
@@ -156,7 +156,7 @@ int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
        case MGA_CARD_TYPE_G200:
                return mga_warp_install_g200_microcode(dev_priv);
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 }
 
@@ -182,7 +182,7 @@ int mga_warp_init(drm_mga_private_t * dev_priv)
                MGA_WRITE(MGA_WVRTXSZ, 7);
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
@@ -191,7 +191,7 @@ int mga_warp_init(drm_mga_private_t * dev_priv)
        if (wmisc != WMISC_EXPECTED) {
                DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
                          wmisc, WMISC_EXPECTED);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c
new file mode 100644 (file)
index 0000000..ab502e6
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+
+#define SKIPS 8
+
+int
+nouveau_dma_channel_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_drm_channel *dchan = &dev_priv->channel;
+       struct nouveau_gpuobj *gpuobj = NULL;
+       struct mem_block *pushbuf;
+       int grclass, ret, i;
+
+       DRM_DEBUG("\n");
+
+       pushbuf = nouveau_mem_alloc(dev, 0, 0x8000,
+                                   NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
+                                   (struct drm_file *)-2);
+       if (!pushbuf) {
+               DRM_ERROR("Failed to allocate DMA push buffer\n");
+               return -ENOMEM;
+       }
+
+       /* Allocate channel */
+       ret = nouveau_fifo_alloc(dev, &dchan->chan, (struct drm_file *)-2,
+                                pushbuf, NvDmaFB, NvDmaTT);
+       if (ret) {
+               DRM_ERROR("Error allocating GPU channel: %d\n", ret);
+               return ret;
+       }
+       DRM_DEBUG("Using FIFO channel %d\n", dchan->chan->id);
+
+       /* Map push buffer */
+       drm_core_ioremap(dchan->chan->pushbuf_mem->map, dev);
+       if (!dchan->chan->pushbuf_mem->map->handle) {
+               DRM_ERROR("Failed to ioremap push buffer\n");
+               return -EINVAL;
+       }
+       dchan->pushbuf = (void*)dchan->chan->pushbuf_mem->map->handle;
+
+       /* Initialise DMA vars */
+       dchan->max  = (dchan->chan->pushbuf_mem->size >> 2) - 2;
+       dchan->put  = dchan->chan->pushbuf_base >> 2;
+       dchan->cur  = dchan->put;
+       dchan->free = dchan->max - dchan->cur;
+
+       /* Insert NOPS for SKIPS */
+       dchan->free -= SKIPS;
+       dchan->push_free = SKIPS;
+       for (i=0; i<SKIPS; i++)
+               OUT_RING(0);
+
+       /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier */
+       if ((ret = nouveau_notifier_alloc(dchan->chan, NvNotify0, 1,
+                                         &dchan->notify0_offset))) {
+               DRM_ERROR("Error allocating NvNotify0: %d\n", ret);
+               return ret;
+       }
+
+       /* We use NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
+       if (dev_priv->card_type < NV_50) grclass = NV_MEMORY_TO_MEMORY_FORMAT;
+       else                             grclass = NV50_MEMORY_TO_MEMORY_FORMAT;
+       if ((ret = nouveau_gpuobj_gr_new(dchan->chan, grclass, &gpuobj))) {
+               DRM_ERROR("Error creating NvM2MF: %d\n", ret);
+               return ret;
+       }
+
+       if ((ret = nouveau_gpuobj_ref_add(dev, dchan->chan, NvM2MF,
+                                         gpuobj, NULL))) {
+               DRM_ERROR("Error referencing NvM2MF: %d\n", ret);
+               return ret;
+       }
+       dchan->m2mf_dma_source = NvDmaFB;
+       dchan->m2mf_dma_destin = NvDmaFB;
+
+       BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
+       OUT_RING  (NvM2MF);
+       BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY, 1);
+       OUT_RING  (NvNotify0);
+       BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2);
+       OUT_RING  (dchan->m2mf_dma_source);
+       OUT_RING  (dchan->m2mf_dma_destin);
+       FIRE_RING();
+
+       return 0;
+}
+
+void
+nouveau_dma_channel_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_drm_channel *dchan = &dev_priv->channel;
+
+       DRM_DEBUG("\n");
+
+       if (dchan->chan) {
+               nouveau_fifo_free(dchan->chan);
+               dchan->chan = NULL;
+       }
+}
+
+#define RING_SKIPS 8
+
+#define READ_GET() ((NV_READ(NV03_FIFO_REGS_DMAGET(dchan->chan->id)) -         \
+                    dchan->chan->pushbuf_base) >> 2)
+#define WRITE_PUT(val) do {                                                    \
+       NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id),                       \
+                ((val) << 2) + dchan->chan->pushbuf_base);                    \
+} while(0)
+
+int
+nouveau_dma_wait(struct drm_device *dev, int size)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_drm_channel *dchan = &dev_priv->channel;
+       uint32_t get;
+
+       while (dchan->free < size) {
+               get = READ_GET();
+
+               if (dchan->put >= get) {
+                       dchan->free = dchan->max - dchan->cur;
+
+                       if (dchan->free < size) {
+                               dchan->push_free = 1;
+                               OUT_RING(0x20000000|dchan->chan->pushbuf_base);
+                               if (get <= RING_SKIPS) {
+                                       /*corner case - will be idle*/
+                                       if (dchan->put <= RING_SKIPS)
+                                               WRITE_PUT(RING_SKIPS + 1);
+
+                                       do {
+                                               get = READ_GET();
+                                       } while (get <= RING_SKIPS);
+                               }
+
+                               WRITE_PUT(RING_SKIPS);
+                               dchan->cur  = dchan->put = RING_SKIPS;
+                               dchan->free = get - (RING_SKIPS + 1);
+                       }
+               } else {
+                       dchan->free = get - dchan->cur - 1;
+               }
+       }
+
+       return 0;
+}
+
diff --git a/shared-core/nouveau_dma.h b/shared-core/nouveau_dma.h
new file mode 100644 (file)
index 0000000..5e51c1c
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 __NOUVEAU_DMA_H__
+#define __NOUVEAU_DMA_H__
+
+typedef enum {
+       NvSubM2MF       = 0,
+} nouveau_subchannel_id_t;
+
+typedef enum {
+       NvM2MF          = 0x80039001,
+       NvDmaFB         = 0x8003d001,
+       NvDmaTT         = 0x8003d002,
+       NvNotify0       = 0x8003d003
+} nouveau_object_handle_t;
+
+#define NV_MEMORY_TO_MEMORY_FORMAT                                    0x00000039
+#define NV_MEMORY_TO_MEMORY_FORMAT_NAME                               0x00000000
+#define NV_MEMORY_TO_MEMORY_FORMAT_SET_REF                            0x00000050
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOP                                0x00000100
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY                             0x00000104
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE                 0x00000000
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN       0x00000001
+#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY                     0x00000180
+#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE                     0x00000184
+#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN                          0x0000030c
+
+#define NV50_MEMORY_TO_MEMORY_FORMAT                                  0x00005039
+#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK200                           0x00000200
+#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK21C                           0x0000021c
+#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH                   0x00000238
+#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH                  0x0000023c
+
+#define BEGIN_RING(subc, mthd, cnt) do {                                       \
+       int push_size = (cnt) + 1;                                             \
+       if (dchan->push_free) {                                                \
+               DRM_ERROR("prior packet incomplete: %d\n", dchan->push_free);  \
+               break;                                                         \
+       }                                                                      \
+       if (dchan->free < push_size) {                                         \
+               if (nouveau_dma_wait(dev, push_size)) {                        \
+                       DRM_ERROR("FIFO timeout\n");                           \
+                       break;                                                 \
+               }                                                              \
+       }                                                                      \
+       dchan->free -= push_size;                                              \
+       dchan->push_free = push_size;                                          \
+       OUT_RING(((cnt)<<18) | ((subc)<<15) | mthd);                           \
+} while(0)
+
+#define OUT_RING(data) do {                                                    \
+       if (dchan->push_free == 0) {                                           \
+               DRM_ERROR("no space left in packet\n");                        \
+               break;                                                         \
+       }                                                                      \
+       dchan->pushbuf[dchan->cur++] = (data);                                 \
+       dchan->push_free--;                                                    \
+} while(0)
+
+#define FIRE_RING() do {                                                       \
+       if (dchan->push_free) {                                                \
+               DRM_ERROR("packet incomplete: %d\n", dchan->push_free);        \
+               break;                                                         \
+       }                                                                      \
+       if (dchan->cur != dchan->put) {                                        \
+               DRM_MEMORYBARRIER();                                           \
+               dchan->put = dchan->cur;                                       \
+               NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id),               \
+                        (dchan->put<<2));                                     \
+       }                                                                      \
+} while(0)
+
+#endif
+
index 1e7322e..988d467 100644 (file)
 #ifndef __NOUVEAU_DRM_H__
 #define __NOUVEAU_DRM_H__
 
-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 6
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10
+
+struct drm_nouveau_channel_alloc {
+       uint32_t     fb_ctxdma_handle;
+       uint32_t     tt_ctxdma_handle;
 
-typedef struct drm_nouveau_fifo_alloc {
        int          channel;
        uint32_t     put_base;
        /* FIFO control regs */
@@ -36,52 +39,61 @@ typedef struct drm_nouveau_fifo_alloc {
        /* DMA command buffer */
        drm_handle_t cmdbuf;
        int          cmdbuf_size;
-}
-drm_nouveau_fifo_alloc_t;
+       /* Notifier memory */
+       drm_handle_t notifier;
+       int          notifier_size;
+};
 
-typedef struct drm_nouveau_object_init {
+struct drm_nouveau_channel_free {
+       int channel;
+};
+
+struct drm_nouveau_grobj_alloc {
        int      channel;
        uint32_t handle;
        int      class;
-}
-drm_nouveau_object_init_t;
+};
 
 #define NOUVEAU_MEM_ACCESS_RO  1
 #define NOUVEAU_MEM_ACCESS_WO  2
 #define NOUVEAU_MEM_ACCESS_RW  3
-typedef struct drm_nouveau_dma_object_init {
+struct drm_nouveau_notifierobj_alloc {
        int      channel;
        uint32_t handle;
-       int      class;
-       int      access;
-       int      target;
+       int      count;
+
        uint32_t offset;
-       int      size;
-}
-drm_nouveau_dma_object_init_t;
+};
+
+struct drm_nouveau_gpuobj_free {
+       int      channel;
+       uint32_t handle;
+};
 
 #define NOUVEAU_MEM_FB                 0x00000001
 #define NOUVEAU_MEM_AGP                        0x00000002
 #define NOUVEAU_MEM_FB_ACCEPTABLE      0x00000004
 #define NOUVEAU_MEM_AGP_ACCEPTABLE     0x00000008
-#define NOUVEAU_MEM_PINNED             0x00000010
-#define NOUVEAU_MEM_USER_BACKED                0x00000020
-#define NOUVEAU_MEM_MAPPED             0x00000040
-#define NOUVEAU_MEM_INSTANCE           0x00000080 /* internal */
-
-typedef struct drm_nouveau_mem_alloc {
+#define NOUVEAU_MEM_PCI                        0x00000010
+#define NOUVEAU_MEM_PCI_ACCEPTABLE     0x00000020
+#define NOUVEAU_MEM_PINNED             0x00000040
+#define NOUVEAU_MEM_USER_BACKED                0x00000080
+#define NOUVEAU_MEM_MAPPED             0x00000100
+#define NOUVEAU_MEM_INSTANCE           0x00000200 /* internal */
+#define NOUVEAU_MEM_NOTIFIER            0x00000400 /* internal */
+
+struct drm_nouveau_mem_alloc {
        int flags;
        int alignment;
        uint64_t size;  // in bytes
-       uint64_t region_offset;
-}
-drm_nouveau_mem_alloc_t;
+       uint64_t offset;
+       drm_handle_t map_handle;
+};
 
-typedef struct drm_nouveau_mem_free {
-       uint64_t region_offset;
+struct drm_nouveau_mem_free {
+       uint64_t offset;
        int flags;
-}
-drm_nouveau_mem_free_t;
+};
 
 /* FIXME : maybe unify {GET,SET}PARAMs */
 #define NOUVEAU_GETPARAM_PCI_VENDOR      3
@@ -91,34 +103,29 @@ drm_nouveau_mem_free_t;
 #define NOUVEAU_GETPARAM_AGP_PHYSICAL    7
 #define NOUVEAU_GETPARAM_FB_SIZE         8
 #define NOUVEAU_GETPARAM_AGP_SIZE        9
-typedef struct drm_nouveau_getparam {
+#define NOUVEAU_GETPARAM_PCI_PHYSICAL    10
+#define NOUVEAU_GETPARAM_CHIPSET_ID      11
+struct drm_nouveau_getparam {
        uint64_t param;
        uint64_t value;
-}
-drm_nouveau_getparam_t;
+};
 
 #define NOUVEAU_SETPARAM_CMDBUF_LOCATION 1
 #define NOUVEAU_SETPARAM_CMDBUF_SIZE     2
-typedef struct drm_nouveau_setparam {
+struct drm_nouveau_setparam {
        uint64_t param;
        uint64_t value;
-}
-drm_nouveau_setparam_t;
+};
 
 enum nouveau_card_type {
        NV_UNKNOWN =0,
-       NV_01      =1,
-       NV_03      =3,
        NV_04      =4,
        NV_05      =5,
        NV_10      =10,
-       NV_11      =10,
-       NV_15      =10,
+       NV_11      =11,
        NV_17      =17,
        NV_20      =20,
-       NV_25      =20,
        NV_30      =30,
-       NV_34      =30,
        NV_40      =40,
        NV_44      =44,
        NV_50      =50,
@@ -133,20 +140,22 @@ enum nouveau_bus_type {
 
 #define NOUVEAU_MAX_SAREA_CLIPRECTS 16
 
-typedef struct drm_nouveau_sarea {
+struct drm_nouveau_sarea {
        /* the cliprects */
-       drm_clip_rect_t boxes[NOUVEAU_MAX_SAREA_CLIPRECTS];
+       struct drm_clip_rect boxes[NOUVEAU_MAX_SAREA_CLIPRECTS];
        unsigned int nbox;
-}
-drm_nouveau_sarea_t;
-
-#define DRM_NOUVEAU_FIFO_ALLOC      0x00
-#define DRM_NOUVEAU_OBJECT_INIT     0x01
-#define DRM_NOUVEAU_DMA_OBJECT_INIT 0x02
-#define DRM_NOUVEAU_MEM_ALLOC       0x03
-#define DRM_NOUVEAU_MEM_FREE        0x04
-#define DRM_NOUVEAU_GETPARAM        0x05
-#define DRM_NOUVEAU_SETPARAM        0x06
+};
+
+#define DRM_NOUVEAU_CARD_INIT          0x00
+#define DRM_NOUVEAU_GETPARAM           0x01
+#define DRM_NOUVEAU_SETPARAM           0x02
+#define DRM_NOUVEAU_CHANNEL_ALLOC      0x03
+#define DRM_NOUVEAU_CHANNEL_FREE       0x04
+#define DRM_NOUVEAU_GROBJ_ALLOC        0x05
+#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC  0x06
+#define DRM_NOUVEAU_GPUOBJ_FREE        0x07
+#define DRM_NOUVEAU_MEM_ALLOC          0x08
+#define DRM_NOUVEAU_MEM_FREE           0x09
 
 #endif /* __NOUVEAU_DRM_H__ */
 
index debee8e..e5cef07 100644 (file)
@@ -34,7 +34,7 @@
 
 #define DRIVER_MAJOR           0
 #define DRIVER_MINOR           0
-#define DRIVER_PATCHLEVEL      6
+#define DRIVER_PATCHLEVEL      10
 
 #define NOUVEAU_FAMILY   0x0000FFFF
 #define NOUVEAU_FLAGS    0xFFFF0000
@@ -47,9 +47,10 @@ struct mem_block {
        struct mem_block *prev;
        uint64_t start;
        uint64_t size;
-       DRMFILE filp;           /* 0: free, -1: heap, other: real files */
+       struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
        int flags;
        drm_local_map_t *map;
+       drm_handle_t map_handle;
 };
 
 enum nouveau_flags {
@@ -57,39 +58,97 @@ enum nouveau_flags {
        NV_NFORCE2  =0x20000000
 };
 
-struct nouveau_object
-{
-       struct nouveau_object *next;
-       struct nouveau_object *prev;
-       int channel;
+#define NVOBJ_ENGINE_SW                0
+#define NVOBJ_ENGINE_GR        1
+#define NVOBJ_ENGINE_INT       0xdeadbeef
+
+#define NVOBJ_FLAG_ALLOW_NO_REFS       (1 << 0)
+#define NVOBJ_FLAG_ZERO_ALLOC          (1 << 1)
+#define NVOBJ_FLAG_ZERO_FREE           (1 << 2)
+#define NVOBJ_FLAG_FAKE                        (1 << 3)
+struct nouveau_gpuobj {
+       struct list_head list;
+
+       int im_channel;
+       struct mem_block *im_pramin;
+       struct mem_block *im_backing;
+       int im_bound;
+
+       uint32_t flags;
+       int refcount;
+
+       uint32_t engine;
+       uint32_t class;
 
-       struct mem_block *instance;
-       uint32_t          ht_loc;
+       void (*dtor)(struct drm_device *, struct nouveau_gpuobj *);
+       void *priv;
+};
+
+struct nouveau_gpuobj_ref {
+       struct list_head list;
+
+       struct nouveau_gpuobj *gpuobj;
+       uint32_t instance;
 
-       uint32_t handle;
-       int      class;
-       int      engine;
+       int channel;
+       int handle;
 };
 
-struct nouveau_fifo
+struct nouveau_channel
 {
-       int used;
+       struct drm_device *dev;
+       int id;
+
        /* owner of this fifo */
-       DRMFILE filp;
+       struct drm_file *file_priv;
        /* mapping of the fifo itself */
        drm_local_map_t *map;
        /* mapping of the regs controling the fifo */
        drm_local_map_t *regs;
-       /* dma object for the command buffer itself */
-       struct mem_block      *cmdbuf_mem;
-       struct nouveau_object *cmdbuf_obj;
-       /* PGRAPH context, for cards that keep it in RAMIN */
-       struct mem_block *ramin_grctx;
-       /* objects belonging to this fifo */
-       struct nouveau_object *objs;
-
-       /* XXX dynamic alloc ? */
-       uint32_t pgraph_ctx [340];
+
+       /* DMA push buffer */
+       struct nouveau_gpuobj_ref *pushbuf;
+       struct mem_block          *pushbuf_mem;
+       uint32_t                   pushbuf_base;
+
+       /* Notifier memory */
+       struct mem_block *notifier_block;
+       struct mem_block *notifier_heap;
+       drm_local_map_t  *notifier_map;
+
+       /* PFIFO context */
+       struct nouveau_gpuobj_ref *ramfc;
+
+       /* PGRAPH context */
+       /* XXX may be merge 2 pointers as private data ??? */
+       struct nouveau_gpuobj_ref *ramin_grctx;
+       void *pgraph_ctx;
+
+       /* NV50 VM */
+       struct nouveau_gpuobj     *vm_pd;
+       struct nouveau_gpuobj_ref *vm_gart_pt;
+
+       /* Objects */
+       struct nouveau_gpuobj_ref *ramin; /* Private instmem */
+       struct mem_block          *ramin_heap; /* Private PRAMIN heap */
+       struct nouveau_gpuobj_ref *ramht; /* Hash table */
+       struct list_head           ramht_refs; /* Objects referenced by RAMHT */
+};
+
+struct nouveau_drm_channel {
+       struct nouveau_channel *chan;
+
+       /* DMA state */
+       int max, put, cur, free;
+       int push_free;
+       volatile uint32_t *pushbuf;
+
+       /* Notifiers */
+       uint32_t notify0_offset;
+
+       /* Buffer moves */
+       uint32_t m2mf_dma_source;
+       uint32_t m2mf_dma_destin;
 };
 
 struct nouveau_config {
@@ -99,34 +158,73 @@ struct nouveau_config {
        } cmdbuf;
 };
 
-struct nouveau_engine_func {
-       struct {
-               int     (*Init)(drm_device_t *dev);
-               void    (*Takedown)(drm_device_t *dev);
-       } Mc;
+struct nouveau_instmem_engine {
+       void    *priv;
 
-       struct {
-               int     (*Init)(drm_device_t *dev);
-               void    (*Takedown)(drm_device_t *dev);
-       } Timer;
+       int     (*init)(struct drm_device *dev);
+       void    (*takedown)(struct drm_device *dev);
 
-       struct {
-               int     (*Init)(drm_device_t *dev);
-               void    (*Takedown)(drm_device_t *dev);
-       } Fb;
+       int     (*populate)(struct drm_device *, struct nouveau_gpuobj *,
+                           uint32_t *size);
+       void    (*clear)(struct drm_device *, struct nouveau_gpuobj *);
+       int     (*bind)(struct drm_device *, struct nouveau_gpuobj *);
+       int     (*unbind)(struct drm_device *, struct nouveau_gpuobj *);
+};
 
-       struct {
-               int     (*Init)(drm_device_t *dev);
-               void    (*Takedown)(drm_device_t *dev);
-       } Graph;
+struct nouveau_mc_engine {
+       int  (*init)(struct drm_device *dev);
+       void (*takedown)(struct drm_device *dev);
+};
 
-       struct {
-               int     (*Init)(drm_device_t *dev);
-               void    (*Takedown)(drm_device_t *dev);
-       } Fifo;
+struct nouveau_timer_engine {
+       int      (*init)(struct drm_device *dev);
+       void     (*takedown)(struct drm_device *dev);
+       uint64_t (*read)(struct drm_device *dev);
 };
 
-typedef struct drm_nouveau_private {
+struct nouveau_fb_engine {
+       int  (*init)(struct drm_device *dev);
+       void (*takedown)(struct drm_device *dev);
+};
+
+struct nouveau_fifo_engine {
+       void *priv;
+
+       int  (*init)(struct drm_device *);
+       void (*takedown)(struct drm_device *);
+
+       int  (*create_context)(struct nouveau_channel *);
+       void (*destroy_context)(struct nouveau_channel *);
+       int  (*load_context)(struct nouveau_channel *);
+       int  (*save_context)(struct nouveau_channel *);
+};
+
+struct nouveau_pgraph_engine {
+       int  (*init)(struct drm_device *);
+       void (*takedown)(struct drm_device *);
+
+       int  (*create_context)(struct nouveau_channel *);
+       void (*destroy_context)(struct nouveau_channel *);
+       int  (*load_context)(struct nouveau_channel *);
+       int  (*save_context)(struct nouveau_channel *);
+};
+
+struct nouveau_engine {
+       struct nouveau_instmem_engine instmem;
+       struct nouveau_mc_engine      mc;
+       struct nouveau_timer_engine   timer;
+       struct nouveau_fb_engine      fb;
+       struct nouveau_pgraph_engine  graph;
+       struct nouveau_fifo_engine    fifo;
+};
+
+struct drm_nouveau_private {
+       enum {
+               NOUVEAU_CARD_INIT_DOWN,
+               NOUVEAU_CARD_INIT_DONE,
+               NOUVEAU_CARD_INIT_FAILED
+       } init_state;
+
        /* the card type, takes NV_* as values */
        int card_type;
        /* exact chipset, derived from NV_PMC_BOOT_0 */
@@ -138,12 +236,14 @@ typedef struct drm_nouveau_private {
        drm_local_map_t *ramin; /* NV40 onwards */
 
        int fifo_alloc_count;
-       struct nouveau_fifo fifos[NV_MAX_FIFO_NUMBER];
+       struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER];
 
-       struct nouveau_engine_func Engine;
+       struct nouveau_engine Engine;
+       struct nouveau_drm_channel channel;
 
        /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
-       uint32_t ramin_size;
+       struct nouveau_gpuobj *ramht;
+       uint32_t ramin_rsvd_vram;
        uint32_t ramht_offset;
        uint32_t ramht_size;
        uint32_t ramht_bits;
@@ -155,8 +255,24 @@ typedef struct drm_nouveau_private {
        /* base physical adresses */
        uint64_t fb_phys;
        uint64_t fb_available_size;
-       uint64_t agp_phys;
-       uint64_t agp_available_size;
+
+       struct {
+               enum {
+                       NOUVEAU_GART_NONE = 0,
+                       NOUVEAU_GART_AGP,
+                       NOUVEAU_GART_SGDMA
+               } type;
+               uint64_t aper_base;
+               uint64_t aper_size;
+
+               struct nouveau_gpuobj *sg_ctxdma;
+               struct page *sg_dummy_page;
+               dma_addr_t sg_dummy_bus;
+
+               /* nottm hack */
+               struct drm_ttm_backend *sg_be;
+               unsigned long sg_handle;
+       } gart_info;
 
        /* the mtrr covering the FB */
        int fb_mtrr;
@@ -165,129 +281,277 @@ typedef struct drm_nouveau_private {
        struct mem_block *fb_heap;
        struct mem_block *fb_nomap_heap;
        struct mem_block *ramin_heap;
+       struct mem_block *pci_heap;
 
         /* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */
         uint32_t ctx_table_size;
-        struct mem_block *ctx_table;
+       struct nouveau_gpuobj_ref *ctx_table;
 
        struct nouveau_config config;
-}
-drm_nouveau_private_t;
+
+       struct list_head gpuobj_list;
+};
+
+#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do {         \
+       struct drm_nouveau_private *nv = dev->dev_private; \
+       if (nv->init_state != NOUVEAU_CARD_INIT_DONE) {    \
+               DRM_ERROR("called without init\n");        \
+               return -EINVAL;                            \
+       }                                                  \
+} while(0)
+
+#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do {  \
+       struct drm_nouveau_private *nv = dev->dev_private;   \
+       if (!nouveau_fifo_owner(dev, (cl), (id))) {          \
+               DRM_ERROR("pid %d doesn't own channel %d\n", \
+                         DRM_CURRENTPID, (id));             \
+               return -EPERM;                               \
+       }                                                    \
+       (ch) = nv->fifos[(id)];                              \
+} while(0)
 
 /* nouveau_state.c */
-extern void nouveau_preclose(drm_device_t * dev, DRMFILE filp);
-extern int nouveau_load(struct drm_device *dev, unsigned long flags);
-extern int nouveau_firstopen(struct drm_device *dev);
-extern void nouveau_lastclose(struct drm_device *dev);
-extern int nouveau_unload(struct drm_device *dev);
-extern int nouveau_ioctl_getparam(DRM_IOCTL_ARGS);
-extern int nouveau_ioctl_setparam(DRM_IOCTL_ARGS);
-extern void nouveau_wait_for_idle(struct drm_device *dev);
-extern int nouveau_ioctl_card_init(DRM_IOCTL_ARGS);
+extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
+extern int  nouveau_load(struct drm_device *, unsigned long flags);
+extern int  nouveau_firstopen(struct drm_device *);
+extern void nouveau_lastclose(struct drm_device *);
+extern int  nouveau_unload(struct drm_device *);
+extern int  nouveau_ioctl_getparam(struct drm_device *, void *data,
+                                  struct drm_file *);
+extern int  nouveau_ioctl_setparam(struct drm_device *, void *data,
+                                  struct drm_file *);
+extern void nouveau_wait_for_idle(struct drm_device *);
+extern int  nouveau_card_init(struct drm_device *);
+extern int  nouveau_ioctl_card_init(struct drm_device *, void *data,
+                                   struct drm_file *);
 
 /* nouveau_mem.c */
-extern uint64_t          nouveau_mem_fb_amount(struct drm_device *dev);
-extern void              nouveau_mem_release(DRMFILE filp, struct mem_block *heap);
-extern int               nouveau_ioctl_mem_alloc(DRM_IOCTL_ARGS);
-extern int               nouveau_ioctl_mem_free(DRM_IOCTL_ARGS);
-extern struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size, int flags, DRMFILE filp);
-extern void              nouveau_mem_free(struct drm_device* dev, struct mem_block*);
-extern int               nouveau_mem_init(struct drm_device *dev);
-extern void              nouveau_mem_close(struct drm_device *dev);
-extern int               nouveau_instmem_init(struct drm_device *dev);
-extern struct mem_block* nouveau_instmem_alloc(struct drm_device *dev,
-                                              uint32_t size, uint32_t align);
-extern void              nouveau_instmem_free(struct drm_device *dev,
-                                             struct mem_block *block);
-extern uint32_t          nouveau_instmem_r32(drm_nouveau_private_t *dev_priv,
-                                            struct mem_block *mem, int index);
-extern void              nouveau_instmem_w32(drm_nouveau_private_t *dev_priv,
-                                            struct mem_block *mem, int index,
-                                            uint32_t val);
+extern int  nouveau_mem_init_heap(struct mem_block **, uint64_t start,
+                                uint64_t size);
+extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,
+                                                uint64_t size, int align2,
+                                                struct drm_file *);
+extern void nouveau_mem_takedown(struct mem_block **heap);
+extern void nouveau_mem_free_block(struct mem_block *);
+extern uint64_t nouveau_mem_fb_amount(struct drm_device *);
+extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
+extern int  nouveau_ioctl_mem_alloc(struct drm_device *, void *data,
+                                   struct drm_file *);
+extern int  nouveau_ioctl_mem_free(struct drm_device *, void *data,
+                                  struct drm_file *);
+extern struct mem_block* nouveau_mem_alloc(struct drm_device *,
+                                          int alignment, uint64_t size,
+                                          int flags, struct drm_file *);
+extern void nouveau_mem_free(struct drm_device *dev, struct mem_block*);
+extern int  nouveau_mem_init(struct drm_device *);
+extern void nouveau_mem_close(struct drm_device *);
+
+/* nouveau_notifier.c */
+extern int  nouveau_notifier_init_channel(struct nouveau_channel *);
+extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
+extern int  nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
+                                  int cout, uint32_t *offset);
+extern int  nouveau_ioctl_notifier_alloc(struct drm_device *, void *data,
+                                        struct drm_file *);
+extern int  nouveau_ioctl_notifier_free(struct drm_device *, void *data,
+                                       struct drm_file *);
 
 /* nouveau_fifo.c */
-extern int  nouveau_fifo_init(drm_device_t *dev);
-extern int  nouveau_fifo_number(drm_device_t *dev);
-extern int  nouveau_fifo_ctx_size(drm_device_t *dev);
-extern void nouveau_fifo_cleanup(drm_device_t *dev, DRMFILE filp);
-extern int  nouveau_fifo_owner(drm_device_t *dev, DRMFILE filp, int channel);
-extern void nouveau_fifo_free(drm_device_t *dev, int channel);
+extern int  nouveau_fifo_init(struct drm_device *);
+extern int  nouveau_fifo_number(struct drm_device *);
+extern int  nouveau_fifo_ctx_size(struct drm_device *);
+extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *);
+extern int  nouveau_fifo_owner(struct drm_device *, struct drm_file *,
+                              int channel);
+extern int  nouveau_fifo_alloc(struct drm_device *dev,
+                              struct nouveau_channel **chan,
+                              struct drm_file *file_priv,
+                              struct mem_block *pushbuf,
+                              uint32_t fb_ctxdma, uint32_t tt_ctxdma);
+extern void nouveau_fifo_free(struct nouveau_channel *);
 
 /* nouveau_object.c */
-extern void nouveau_object_cleanup(drm_device_t *dev, int channel);
-extern struct nouveau_object *
-nouveau_object_gr_create(drm_device_t *dev, int channel, int class);
-extern struct nouveau_object *
-nouveau_object_dma_create(drm_device_t *dev, int channel, int class,
-                         uint32_t offset, uint32_t size,
-                         int access, int target);
-extern void nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj);
-extern int  nouveau_ioctl_object_init(DRM_IOCTL_ARGS);
-extern int  nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS);
-extern uint32_t nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem);
+extern int  nouveau_gpuobj_early_init(struct drm_device *);
+extern int  nouveau_gpuobj_init(struct drm_device *);
+extern void nouveau_gpuobj_takedown(struct drm_device *);
+extern void nouveau_gpuobj_late_takedown(struct drm_device *);
+extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
+                                      uint32_t vram_h, uint32_t tt_h);
+extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
+extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *,
+                             int size, int align, uint32_t flags,
+                             struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *,
+                                 uint32_t handle, struct nouveau_gpuobj *,
+                                 struct nouveau_gpuobj_ref **);
+extern int nouveau_gpuobj_ref_del(struct drm_device *,
+                                 struct nouveau_gpuobj_ref **);
+extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle,
+                                  struct nouveau_gpuobj_ref **ref_ret);
+extern int nouveau_gpuobj_new_ref(struct drm_device *,
+                                 struct nouveau_channel *alloc_chan,
+                                 struct nouveau_channel *ref_chan,
+                                 uint32_t handle, int size, int align,
+                                 uint32_t flags, struct nouveau_gpuobj_ref **);
+extern int nouveau_gpuobj_new_fake(struct drm_device *,
+                                  uint32_t p_offset, uint32_t b_offset,
+                                  uint32_t size, uint32_t flags,
+                                  struct nouveau_gpuobj **,
+                                  struct nouveau_gpuobj_ref**);
+extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class,
+                                 uint64_t offset, uint64_t size, int access,
+                                 int target, struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *,
+                                      uint64_t offset, uint64_t size,
+                                      int access, struct nouveau_gpuobj **,
+                                      uint32_t *o_ret);
+extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
+                                struct nouveau_gpuobj **);
+extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
+                                    struct drm_file *);
+extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
+                                    struct drm_file *);
 
 /* nouveau_irq.c */
 extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
-extern void        nouveau_irq_preinstall(drm_device_t*);
-extern void        nouveau_irq_postinstall(drm_device_t*);
-extern void        nouveau_irq_uninstall(drm_device_t*);
+extern void        nouveau_irq_preinstall(struct drm_device *);
+extern void        nouveau_irq_postinstall(struct drm_device *);
+extern void        nouveau_irq_uninstall(struct drm_device *);
+
+/* nouveau_sgdma.c */
+extern int nouveau_sgdma_init(struct drm_device *);
+extern void nouveau_sgdma_takedown(struct drm_device *);
+extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset,
+                                 uint32_t *page);
+extern struct drm_ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
+extern int nouveau_sgdma_nottm_hack_init(struct drm_device *);
+extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *);
+
+/* nouveau_dma.c */
+extern int  nouveau_dma_channel_init(struct drm_device *);
+extern void nouveau_dma_channel_takedown(struct drm_device *);
+extern int  nouveau_dma_wait(struct drm_device *, int size);
 
 /* nv04_fb.c */
-extern int  nv04_fb_init(drm_device_t *dev);
-extern void nv04_fb_takedown(drm_device_t *dev);
+extern int  nv04_fb_init(struct drm_device *);
+extern void nv04_fb_takedown(struct drm_device *);
 
 /* nv10_fb.c */
-extern int  nv10_fb_init(drm_device_t *dev);
-extern void nv10_fb_takedown(drm_device_t *dev);
+extern int  nv10_fb_init(struct drm_device *);
+extern void nv10_fb_takedown(struct drm_device *);
 
 /* nv40_fb.c */
-extern int  nv40_fb_init(drm_device_t *dev);
-extern void nv40_fb_takedown(drm_device_t *dev);
+extern int  nv40_fb_init(struct drm_device *);
+extern void nv40_fb_takedown(struct drm_device *);
+
+/* nv04_fifo.c */
+extern int  nv04_fifo_create_context(struct nouveau_channel *);
+extern void nv04_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv04_fifo_load_context(struct nouveau_channel *);
+extern int  nv04_fifo_save_context(struct nouveau_channel *);
+
+/* nv10_fifo.c */
+extern int  nv10_fifo_create_context(struct nouveau_channel *);
+extern void nv10_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv10_fifo_load_context(struct nouveau_channel *);
+extern int  nv10_fifo_save_context(struct nouveau_channel *);
+
+/* nv40_fifo.c */
+extern int  nv40_fifo_init(struct drm_device *);
+extern int  nv40_fifo_create_context(struct nouveau_channel *);
+extern void nv40_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv40_fifo_load_context(struct nouveau_channel *);
+extern int  nv40_fifo_save_context(struct nouveau_channel *);
+
+/* nv50_fifo.c */
+extern int  nv50_fifo_init(struct drm_device *);
+extern void nv50_fifo_takedown(struct drm_device *);
+extern int  nv50_fifo_create_context(struct nouveau_channel *);
+extern void nv50_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv50_fifo_load_context(struct nouveau_channel *);
+extern int  nv50_fifo_save_context(struct nouveau_channel *);
 
 /* nv04_graph.c */
-extern void nouveau_nv04_context_switch(drm_device_t *dev);
-extern int nv04_graph_init(drm_device_t *dev);
-extern void nv04_graph_takedown(drm_device_t *dev);
-extern int nv04_graph_context_create(drm_device_t *dev, int channel);
+extern void nouveau_nv04_context_switch(struct drm_device *);
+extern int  nv04_graph_init(struct drm_device *);
+extern void nv04_graph_takedown(struct drm_device *);
+extern int  nv04_graph_create_context(struct nouveau_channel *);
+extern void nv04_graph_destroy_context(struct nouveau_channel *);
+extern int  nv04_graph_load_context(struct nouveau_channel *);
+extern int  nv04_graph_save_context(struct nouveau_channel *);
 
 /* nv10_graph.c */
-extern void nouveau_nv10_context_switch(drm_device_t *dev);
-extern int nv10_graph_init(drm_device_t *dev);
-extern void nv10_graph_takedown(drm_device_t *dev);
-extern int nv10_graph_context_create(drm_device_t *dev, int channel);
+extern void nouveau_nv10_context_switch(struct drm_device *);
+extern int  nv10_graph_init(struct drm_device *);
+extern void nv10_graph_takedown(struct drm_device *);
+extern int  nv10_graph_create_context(struct nouveau_channel *);
+extern void nv10_graph_destroy_context(struct nouveau_channel *);
+extern int  nv10_graph_load_context(struct nouveau_channel *);
+extern int  nv10_graph_save_context(struct nouveau_channel *);
 
 /* nv20_graph.c */
-extern void nouveau_nv20_context_switch(drm_device_t *dev);
-extern int nv20_graph_init(drm_device_t *dev);
-extern void nv20_graph_takedown(drm_device_t *dev);
-extern int nv20_graph_context_create(drm_device_t *dev, int channel);
-
-/* nv30_graph.c */
-extern int nv30_graph_init(drm_device_t *dev);
-extern void nv30_graph_takedown(drm_device_t *dev);
-extern int nv30_graph_context_create(drm_device_t *dev, int channel);
+extern int  nv20_graph_create_context(struct nouveau_channel *);
+extern void nv20_graph_destroy_context(struct nouveau_channel *);
+extern int  nv20_graph_load_context(struct nouveau_channel *);
+extern int  nv20_graph_save_context(struct nouveau_channel *);
+extern int  nv20_graph_init(struct drm_device *);
+extern void nv20_graph_takedown(struct drm_device *);
+extern int  nv30_graph_init(struct drm_device *);
 
 /* nv40_graph.c */
-extern int  nv40_graph_init(drm_device_t *dev);
-extern void nv40_graph_takedown(drm_device_t *dev);
-extern int  nv40_graph_context_create(drm_device_t *dev, int channel);
-extern void nv40_graph_context_save_current(drm_device_t *dev);
-extern void nv40_graph_context_restore(drm_device_t *dev, int channel);
+extern int  nv40_graph_init(struct drm_device *);
+extern void nv40_graph_takedown(struct drm_device *);
+extern int  nv40_graph_create_context(struct nouveau_channel *);
+extern void nv40_graph_destroy_context(struct nouveau_channel *);
+extern int  nv40_graph_load_context(struct nouveau_channel *);
+extern int  nv40_graph_save_context(struct nouveau_channel *);
+
+/* nv50_graph.c */
+extern int  nv50_graph_init(struct drm_device *);
+extern void nv50_graph_takedown(struct drm_device *);
+extern int  nv50_graph_create_context(struct nouveau_channel *);
+extern void nv50_graph_destroy_context(struct nouveau_channel *);
+extern int  nv50_graph_load_context(struct nouveau_channel *);
+extern int  nv50_graph_save_context(struct nouveau_channel *);
+
+/* nv04_instmem.c */
+extern int  nv04_instmem_init(struct drm_device *);
+extern void nv04_instmem_takedown(struct drm_device *);
+extern int  nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
+                                 uint32_t *size);
+extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
+
+/* nv50_instmem.c */
+extern int  nv50_instmem_init(struct drm_device *);
+extern void nv50_instmem_takedown(struct drm_device *);
+extern int  nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
+                                 uint32_t *size);
+extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
 
 /* nv04_mc.c */
-extern int  nv04_mc_init(drm_device_t *dev);
-extern void nv04_mc_takedown(drm_device_t *dev);
+extern int  nv04_mc_init(struct drm_device *);
+extern void nv04_mc_takedown(struct drm_device *);
 
 /* nv40_mc.c */
-extern int  nv40_mc_init(drm_device_t *dev);
-extern void nv40_mc_takedown(drm_device_t *dev);
+extern int  nv40_mc_init(struct drm_device *);
+extern void nv40_mc_takedown(struct drm_device *);
+
+/* nv50_mc.c */
+extern int  nv50_mc_init(struct drm_device *);
+extern void nv50_mc_takedown(struct drm_device *);
 
 /* nv04_timer.c */
-extern int  nv04_timer_init(drm_device_t *dev);
-extern void nv04_timer_takedown(drm_device_t *dev);
+extern int  nv04_timer_init(struct drm_device *);
+extern uint64_t nv04_timer_read(struct drm_device *);
+extern void nv04_timer_takedown(struct drm_device *);
 
-extern long nouveau_compat_ioctl(struct file *filp, unsigned int cmd,
-                               unsigned long arg);
+extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
+                                unsigned long arg);
 
 #if defined(__powerpc__)
 #define NV_READ(reg)        in_be32((void __iomem *)(dev_priv->mmio)->handle + (reg) )
@@ -297,8 +561,17 @@ extern long nouveau_compat_ioctl(struct file *filp, unsigned int cmd,
 #define NV_WRITE(reg,val)   DRM_WRITE32( dev_priv->mmio, (reg), (val) )
 #endif
 
-#define INSTANCE_WR(mem,ofs,val) nouveau_instmem_w32(dev_priv,(mem),(ofs),(val))
-#define INSTANCE_RD(mem,ofs)     nouveau_instmem_r32(dev_priv,(mem),(ofs))
+/* PRAMIN access */
+#if defined(__powerpc__)
+#define NV_RI32(o) in_be32((void __iomem *)(dev_priv->ramin)->handle+(o))
+#define NV_WI32(o,v) out_be32((void __iomem*)(dev_priv->ramin)->handle+(o), (v))
+#else
+#define NV_RI32(o) DRM_READ32(dev_priv->ramin, (o))
+#define NV_WI32(o,v) DRM_WRITE32(dev_priv->ramin, (o), (v))
+#endif
+
+#define INSTANCE_RD(o,i) NV_RI32((o)->im_pramin->start + ((i)<<2))
+#define INSTANCE_WR(o,i,v) NV_WI32((o)->im_pramin->start + ((i)<<2), (v))
 
 #endif /* __NOUVEAU_DRV_H__ */
 
index 8e66ca2..f82d130 100644 (file)
 
 
 /* returns the number of hw fifos */
-int nouveau_fifo_number(drm_device_t* dev)
+int nouveau_fifo_number(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
+       struct drm_nouveau_private *dev_priv=dev->dev_private;
        switch(dev_priv->card_type)
        {
-               case NV_03:
-                       return 8;
                case NV_04:
                case NV_05:
                        return 16;
+               case NV_50:
+                       return 128;
                default:
                        return 32;
        }
 }
 
 /* returns the size of fifo context */
-int nouveau_fifo_ctx_size(drm_device_t* dev)
+int nouveau_fifo_ctx_size(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
+       struct drm_nouveau_private *dev_priv=dev->dev_private;
 
        if (dev_priv->card_type >= NV_40)
                return 128;
@@ -66,9 +66,9 @@ int nouveau_fifo_ctx_size(drm_device_t* dev)
  * voir nv_driver.c : NVPreInit 
  */
 
-static int nouveau_fifo_instmem_configure(drm_device_t *dev)
+static int nouveau_fifo_instmem_configure(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        NV_WRITE(NV03_PFIFO_RAMHT,
                        (0x03 << 24) /* search 128 */ | 
@@ -82,6 +82,15 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev)
        {
                case NV_50:
                case NV_40:
+                       switch (dev_priv->chipset) {
+                       case 0x47:
+                       case 0x49:
+                       case 0x4b:
+                               NV_WRITE(0x2230, 1);
+                               break;
+                       default:
+                               break;
+                       }
                        NV_WRITE(NV40_PFIFO_RAMFC, 0x30002);
                        break;
                case NV_44:
@@ -95,9 +104,9 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev)
                                        (1 << 16) /* 64 Bytes entry*/);
                        /* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */
                        break;
+               case NV_11:
                case NV_10:
                case NV_04:
-               case NV_03:
                        NV_WRITE(NV03_PFIFO_RAMFC, dev_priv->ramfc_offset>>8);
                        break;
        }
@@ -105,9 +114,9 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev)
        return 0;
 }
 
-int nouveau_fifo_init(drm_device_t *dev)
+int nouveau_fifo_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int ret;
 
        NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
@@ -115,6 +124,10 @@ int nouveau_fifo_init(drm_device_t *dev)
        NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
                         NV_PMC_ENABLE_PFIFO);
 
+       /* Enable PFIFO error reporting */
+       NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
+       NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
+
        NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
 
        ret = nouveau_fifo_instmem_configure(dev);
@@ -181,286 +194,90 @@ int nouveau_fifo_init(drm_device_t *dev)
 }
 
 static int
-nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel)
+nouveau_fifo_pushbuf_ctxdma_init(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_config *config = &dev_priv->config;
-       struct mem_block *cb;
-       struct nouveau_object *cb_dma = NULL;
-       int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
-
-       /* Defaults for unconfigured values */
-       if (!config->cmdbuf.location)
-               config->cmdbuf.location = NOUVEAU_MEM_FB;
-       if (!config->cmdbuf.size || config->cmdbuf.size < cb_min_size)
-               config->cmdbuf.size = cb_min_size;
-
-       cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
-                       config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
-                       (DRMFILE)-2);
-       if (!cb) {
-               DRM_ERROR("Couldn't allocate DMA command buffer.\n");
-               return DRM_ERR(ENOMEM);
-       }
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct mem_block *pb = chan->pushbuf_mem;
+       struct nouveau_gpuobj *pushbuf = NULL;
+       int ret;
 
-       if (cb->flags & NOUVEAU_MEM_AGP) {
-               cb_dma = nouveau_object_dma_create(dev, channel,
-                               NV_CLASS_DMA_IN_MEMORY,
-                               cb->start - dev_priv->agp_phys,
-                               cb->size,
-                               NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP);
+       if (pb->flags & NOUVEAU_MEM_AGP) {
+               ret = nouveau_gpuobj_gart_dma_new(chan, pb->start, pb->size,
+                                                 NV_DMA_ACCESS_RO,
+                                                 &pushbuf,
+                                                 &chan->pushbuf_base);
+       } else
+       if (pb->flags & NOUVEAU_MEM_PCI) {
+               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                            pb->start, pb->size,
+                                            NV_DMA_ACCESS_RO,
+                                            NV_DMA_TARGET_PCI_NONLINEAR,
+                                            &pushbuf);
+               chan->pushbuf_base = 0;
        } else if (dev_priv->card_type != NV_04) {
-               cb_dma = nouveau_object_dma_create(dev, channel,
-                               NV_CLASS_DMA_IN_MEMORY,
-                               cb->start - drm_get_resource_start(dev, 1),
-                               cb->size,
-                               NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM);
+               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                            pb->start, pb->size,
+                                            NV_DMA_ACCESS_RO,
+                                            NV_DMA_TARGET_VIDMEM, &pushbuf);
+               chan->pushbuf_base = 0;
        } else {
                /* NV04 cmdbuf hack, from original ddx.. not sure of it's
                 * exact reason for existing :)  PCI access to cmdbuf in
                 * VRAM.
                 */
-               cb_dma = nouveau_object_dma_create(dev, channel,
-                               NV_CLASS_DMA_IN_MEMORY,
-                               cb->start, cb->size,
-                               NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI);
+               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                            pb->start +
+                                              drm_get_resource_start(dev, 1),
+                                            pb->size, NV_DMA_ACCESS_RO,
+                                            NV_DMA_TARGET_PCI, &pushbuf);
+               chan->pushbuf_base = 0;
        }
 
-       if (!cb_dma) {
-               nouveau_mem_free(dev, cb);
-               DRM_ERROR("Failed to alloc DMA object for command buffer\n");
-               return DRM_ERR(ENOMEM);
+       if ((ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf,
+                                         &chan->pushbuf))) {
+               DRM_ERROR("Error referencing push buffer ctxdma: %d\n", ret);
+               if (pushbuf != dev_priv->gart_info.sg_ctxdma)
+                       nouveau_gpuobj_del(dev, &pushbuf);
+               return ret;
        }
 
-       dev_priv->fifos[channel].cmdbuf_mem = cb;
-       dev_priv->fifos[channel].cmdbuf_obj = cb_dma;
        return 0;
 }
 
-#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV04_RAMFC_##offset, (val))
-static void nouveau_nv04_context_init(drm_device_t *dev, int channel)
-{
-        drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_object *cb_obj;
-       uint32_t fifoctx, ctx_size = 32;
-       int i;
-
-       cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
-
-       fifoctx=NV_RAMIN+dev_priv->ramfc_offset+channel*ctx_size;
-       
-        // clear the fifo context
-        for(i=0;i<ctx_size/4;i++)
-                NV_WRITE(fifoctx+4*i,0x0);
-
-       RAMFC_WR(DMA_INSTANCE   , nouveau_chip_instance_get(dev, cb_obj->instance));
-
-        RAMFC_WR(DMA_FETCH,    NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
-                                NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-                                NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4     |
-#ifdef __BIG_ENDIAN
-                                NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
-                               0x00000000);
-}
-#undef RAMFC_WR
-
-#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV10_RAMFC_##offset, (val))
-static void nouveau_nv10_context_init(drm_device_t *dev, int channel)
-{
-        drm_nouveau_private_t *dev_priv = dev->dev_private;
-        struct nouveau_object *cb_obj;
-        uint32_t fifoctx;
-        int ctx_size = nouveau_fifo_ctx_size(dev);
-        int i;
-        cb_obj  = dev_priv->fifos[channel].cmdbuf_obj;
-        fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*ctx_size;
-
-        for (i=0;i<ctx_size;i+=4)
-                NV_WRITE(fifoctx + i, 0);
-
-        /* Fill entries that are seen filled in dumps of nvidia driver just
-         * after channel's is put into DMA mode
-         */
-
-        RAMFC_WR(DMA_INSTANCE  , nouveau_chip_instance_get(dev,
-                                cb_obj->instance));
-
-        RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES | 
-                        NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-                        NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4     |
-#ifdef __BIG_ENDIAN
-                        NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
-                       0x00000000);
-}
-
-static void nouveau_nv30_context_init(drm_device_t *dev, int channel)
-{
-        drm_nouveau_private_t *dev_priv = dev->dev_private;
-        struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       struct nouveau_object *cb_obj;
-       uint32_t fifoctx, grctx_inst, cb_inst, ctx_size = 64;
-       int i;
-
-       cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
-        cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
-        grctx_inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
-        fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel * ctx_size;
-        
-        for (i = 0; i < ctx_size; i += 4)
-                NV_WRITE(fifoctx + i, 0);
-
-        RAMFC_WR(REF_CNT,       NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
-        RAMFC_WR(DMA_INSTANCE,  cb_inst);
-        RAMFC_WR(DMA_STATE,     NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
-        RAMFC_WR(DMA_FETCH,     NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | 
-                                NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-                                NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
-#ifdef __BIG_ENDIAN
-                                NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
-                                0x00000000);
-        
-        RAMFC_WR(ENGINE,                NV_READ(NV04_PFIFO_CACHE1_ENGINE));
-        RAMFC_WR(PULL1_ENGINE,          NV_READ(NV04_PFIFO_CACHE1_PULL1)); 
-        RAMFC_WR(ACQUIRE_VALUE,         NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
-        RAMFC_WR(ACQUIRE_TIMESTAMP,     NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
-        RAMFC_WR(ACQUIRE_TIMEOUT,       NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
-        RAMFC_WR(SEMAPHORE,             NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
-}
-
-#if 0
-static void nouveau_nv10_context_save(drm_device_t *dev)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       uint32_t fifoctx;
-       int channel;
-
-       channel = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1);
-       fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*64;
-
-       RAMFC_WR(DMA_PUT          , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
-       RAMFC_WR(DMA_GET          , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
-       RAMFC_WR(REF_CNT          , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
-       RAMFC_WR(DMA_INSTANCE     , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE));
-       RAMFC_WR(DMA_STATE        , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
-       RAMFC_WR(DMA_FETCH        , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
-       RAMFC_WR(ENGINE           , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
-       RAMFC_WR(PULL1_ENGINE     , NV_READ(NV04_PFIFO_CACHE1_PULL1));
-       RAMFC_WR(ACQUIRE_VALUE    , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
-       RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
-       RAMFC_WR(ACQUIRE_TIMEOUT  , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
-       RAMFC_WR(SEMAPHORE        , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
-       RAMFC_WR(DMA_SUBROUTINE   , NV_READ(NV10_PFIFO_CACHE1_DMA_SUBROUTINE));
-}
-#endif
-#undef RAMFC_WR
-
-#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV40_RAMFC_##offset, (val))
-static void nouveau_nv40_context_init(drm_device_t *dev, int channel)
+static struct mem_block *
+nouveau_fifo_user_pushbuf_alloc(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       uint32_t fifoctx, cb_inst, grctx_inst;
-       int i;
-
-       cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
-       grctx_inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
-       fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*128;
-       for (i=0;i<128;i+=4)
-               NV_WRITE(fifoctx + i, 0);
-
-       /* Fill entries that are seen filled in dumps of nvidia driver just
-        * after channel's is put into DMA mode
-        */
-       RAMFC_WR(DMA_INSTANCE  , cb_inst);
-       RAMFC_WR(DMA_FETCH     , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
-                                NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-                                NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
-#ifdef __BIG_ENDIAN
-                                NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
-                                0x30000000 /* no idea.. */);
-       RAMFC_WR(GRCTX_INSTANCE, grctx_inst);
-       RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF);
-}
-
-static void nouveau_nv40_context_save(drm_device_t *dev)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       uint32_t fifoctx;
-       int channel;
-
-       channel = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1);
-       fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*128;
-
-       RAMFC_WR(DMA_PUT          , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
-       RAMFC_WR(DMA_GET          , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
-       RAMFC_WR(REF_CNT          , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
-       RAMFC_WR(DMA_INSTANCE     , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE));
-       RAMFC_WR(DMA_DCOUNT       , NV_READ(NV10_PFIFO_CACHE1_DMA_DCOUNT));
-       RAMFC_WR(DMA_STATE        , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
-       RAMFC_WR(DMA_FETCH        , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
-       RAMFC_WR(ENGINE           , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
-       RAMFC_WR(PULL1_ENGINE     , NV_READ(NV04_PFIFO_CACHE1_PULL1));
-       RAMFC_WR(ACQUIRE_VALUE    , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
-       RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
-       RAMFC_WR(ACQUIRE_TIMEOUT  , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
-       RAMFC_WR(SEMAPHORE        , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
-       RAMFC_WR(DMA_SUBROUTINE   , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
-       RAMFC_WR(GRCTX_INSTANCE   , NV_READ(NV40_PFIFO_GRCTX_INSTANCE));
-       RAMFC_WR(DMA_TIMESLICE    , NV_READ(NV04_PFIFO_DMA_TIMESLICE) & 0x1FFFF);
-       RAMFC_WR(UNK_40           , NV_READ(NV40_PFIFO_UNK32E4));
-}
-#undef RAMFC_WR
-
-/* This function should load values from RAMFC into PFIFO, but for now
- * it just clobbers PFIFO with what nouveau_fifo_alloc used to setup
- * unconditionally.
- */
-static void
-nouveau_fifo_context_restore(drm_device_t *dev, int channel)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       uint32_t cb_inst;
-
-       cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
-
-       // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF);
-
-       if (dev_priv->card_type >= NV_40)
-               NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00010000|channel);
-       else
-               NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00000100|channel);
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_config *config = &dev_priv->config;
+       struct mem_block *pb;
+       int pb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
 
-       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0 /*RAMFC_DMA_PUT*/);
-       NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, 0 /*RAMFC_DMA_GET*/);
-       NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, cb_inst);
-       NV_WRITE(NV04_PFIFO_SIZE , 0x0000FFFF);
-       NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF);
+       /* Defaults for unconfigured values */
+       if (!config->cmdbuf.location)
+               config->cmdbuf.location = NOUVEAU_MEM_FB;
+       if (!config->cmdbuf.size || config->cmdbuf.size < pb_min_size)
+               config->cmdbuf.size = pb_min_size;
 
-       NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001);
-       NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, 0x00000000);
-       NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
-       NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, 0x00000000);
+       pb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
+                              config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
+                              (struct drm_file *)-2);
+       if (!pb)
+               DRM_ERROR("Couldn't allocate DMA push buffer.\n");
 
-       NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH,   NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
-                                       NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-                                       NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 |
-#ifdef __BIG_ENDIAN
-                                       NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
-                                       0x00000000);
+       return pb;
 }
 
 /* allocates and initializes a fifo for user space consumption */
-static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
+int
+nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
+                  struct drm_file *file_priv, struct mem_block *pushbuf,
+                  uint32_t vram_handle, uint32_t tt_handle)
 {
        int ret;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_object *cb_obj;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->Engine;
+       struct nouveau_channel *chan;
        int channel;
 
        /*
@@ -471,29 +288,47 @@ static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
         * (woo, full userspace command submission !)
         * When there are no more contexts, you lost
         */
-       for(channel=0; channel<nouveau_fifo_number(dev); channel++)
-               if (dev_priv->fifos[channel].used==0)
+       for(channel=0; channel<nouveau_fifo_number(dev); channel++) {
+               if (dev_priv->fifos[channel] == NULL)
                        break;
+       }
        /* no more fifos. you lost. */
        if (channel==nouveau_fifo_number(dev))
-               return DRM_ERR(EINVAL);
-       (*chan_ret) = channel;
+               return -EINVAL;
+
+       dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel),
+                                             DRM_MEM_DRIVER);
+       if (!dev_priv->fifos[channel])
+               return -ENOMEM;
+       dev_priv->fifo_alloc_count++;
+       chan = dev_priv->fifos[channel];
+       chan->dev = dev;
+       chan->id = channel;
+       chan->file_priv = file_priv;
+       chan->pushbuf_mem = pushbuf;
 
        DRM_INFO("Allocating FIFO number %d\n", channel);
 
-       /* that fifo is used */
-       dev_priv->fifos[channel].used = 1;
-       dev_priv->fifos[channel].filp = filp;
-       /* FIFO has no objects yet */
-       dev_priv->fifos[channel].objs = NULL;
+       /* Allocate space for per-channel fixed notifier memory */
+       ret = nouveau_notifier_init_channel(chan);
+       if (ret) {
+               nouveau_fifo_free(chan);
+               return ret;
+       }
+
+       /* Setup channel's default objects */
+       ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle);
+       if (ret) {
+               nouveau_fifo_free(chan);
+               return ret;
+       }
 
-       /* allocate a command buffer, and create a dma object for the gpu */
-       ret = nouveau_fifo_cmdbuf_alloc(dev, channel);
+       /* Create a dma object for the push buffer */
+       ret = nouveau_fifo_pushbuf_ctxdma_init(chan);
        if (ret) {
-               nouveau_fifo_free(dev, channel);
+               nouveau_fifo_free(chan);
                return ret;
        }
-       cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
 
        nouveau_wait_for_idle(dev);
 
@@ -503,200 +338,215 @@ static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
        NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
        NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
 
-       /* Construct inital RAMFC for new channel */
-       switch(dev_priv->card_type)
-       {
-               case NV_04:
-               case NV_05:
-                       nv04_graph_context_create(dev, channel);
-                       nouveau_nv04_context_init(dev, channel);
-                       break;
-               case NV_10:
-               case NV_17:
-                       nv10_graph_context_create(dev, channel);
-                       nouveau_nv10_context_init(dev, channel);
-                       break;
-               case NV_20:
-                       ret = nv20_graph_context_create(dev, channel);
-                       if (ret) {
-                               nouveau_fifo_free(dev, channel);
-                               return ret;
-                       }
-                       nouveau_nv10_context_init(dev, channel);
-                       break;
-               case NV_30:
-                       ret = nv30_graph_context_create(dev, channel);
-                       if (ret) {
-                               nouveau_fifo_free(dev, channel);
-                               return ret;
-                       }
-                       nouveau_nv30_context_init(dev, channel);
-                       break;
-               case NV_40:
-               case NV_44:
-               case NV_50:
-                       ret = nv40_graph_context_create(dev, channel);
-                       if (ret) {
-                               nouveau_fifo_free(dev, channel);
-                               return ret;
-                       }
-                       nouveau_nv40_context_init(dev, channel);
-                       break;
+       /* Create a graphics context for new channel */
+       ret = engine->graph.create_context(chan);
+       if (ret) {
+               nouveau_fifo_free(chan);
+               return ret;
        }
 
-       /* enable the fifo dma operation */
-       NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<channel));
+       /* Construct inital RAMFC for new channel */
+       ret = engine->fifo.create_context(chan);
+       if (ret) {
+               nouveau_fifo_free(chan);
+               return ret;
+       }
 
        /* setup channel's default get/put values */
-       NV_WRITE(NV03_FIFO_REGS_DMAPUT(channel), 0);
-       NV_WRITE(NV03_FIFO_REGS_DMAGET(channel), 0);
+       if (dev_priv->card_type < NV_50) {
+               NV_WRITE(NV03_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base);
+               NV_WRITE(NV03_FIFO_REGS_DMAGET(channel), chan->pushbuf_base);
+       } else {
+               NV_WRITE(NV50_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base);
+               NV_WRITE(NV50_FIFO_REGS_DMAGET(channel), chan->pushbuf_base);
+       }
 
        /* If this is the first channel, setup PFIFO ourselves.  For any
         * other case, the GPU will handle this when it switches contexts.
         */
-       if (dev_priv->fifo_alloc_count == 0) {
-               nouveau_fifo_context_restore(dev, channel);
-               if (dev_priv->card_type >= NV_30) {
-                       struct nouveau_fifo *chan;
-                       uint32_t inst;
-
-                       chan = &dev_priv->fifos[channel];
-                       inst = nouveau_chip_instance_get(dev,
-                                                        chan->ramin_grctx);
-
-                       /* see comments in nv40_graph_context_restore() */
-                       NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, inst);
-                        if (dev_priv->card_type >= NV_40) {
-                                NV_WRITE(0x40032C, inst | 0x01000000);
-                                NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst);
-                        }
+       if (dev_priv->fifo_alloc_count == 1) {
+               ret = engine->fifo.load_context(chan);
+               if (ret) {
+                       nouveau_fifo_free(chan);
+                       return ret;
+               }
+
+               ret = engine->graph.load_context(chan);
+               if (ret) {
+                       nouveau_fifo_free(chan);
+                       return ret;
                }
        }
 
-       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH,
+                NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
        NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001);
        NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001);
        NV_WRITE(NV04_PFIFO_CACHE1_PULL1, 0x00000001);
 
        /* reenable the fifo caches */
-       NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
-
-       dev_priv->fifo_alloc_count++;
+       NV_WRITE(NV03_PFIFO_CACHES, 1);
 
        DRM_INFO("%s: initialised FIFO %d\n", __func__, channel);
+       *chan_ret = chan;
        return 0;
 }
 
 /* stops a fifo */
-void nouveau_fifo_free(drm_device_t* dev, int channel)
+void nouveau_fifo_free(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       int i;
-       int ctx_size = nouveau_fifo_ctx_size(dev);
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->Engine;
 
-       chan->used = 0;
-       DRM_INFO("%s: freeing fifo %d\n", __func__, channel);
+       DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id);
 
        /* disable the fifo caches */
        NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH)&(~0x1));
+       NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
+       NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
 
-       NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<channel));
-       // FIXME XXX needs more code
-       
-       /* Clean RAMFC */
-       for (i=0;i<ctx_size;i+=4) {
-               DRM_DEBUG("RAMFC +%02x: 0x%08x\n", i, NV_READ(NV_RAMIN +
-                                       dev_priv->ramfc_offset + 
-                                       channel*ctx_size + i));
-               NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset +
-                               channel*ctx_size + i, 0);
+       /* stop the fifo, otherwise it could be running and
+        * it will crash when removing gpu objects */
+       if (dev_priv->card_type < NV_50) {
+               NV_WRITE(NV03_FIFO_REGS_DMAPUT(chan->id), chan->pushbuf_base);
+               NV_WRITE(NV03_FIFO_REGS_DMAGET(chan->id), chan->pushbuf_base);
+       } else {
+               NV_WRITE(NV50_FIFO_REGS_DMAPUT(chan->id), chan->pushbuf_base);
+               NV_WRITE(NV50_FIFO_REGS_DMAGET(chan->id), chan->pushbuf_base);
        }
+       // FIXME XXX needs more code
+
+       engine->fifo.destroy_context(chan);
 
        /* Cleanup PGRAPH state */
-       if (dev_priv->card_type >= NV_40)
-               nouveau_instmem_free(dev, chan->ramin_grctx);
-       else if (dev_priv->card_type >= NV_30) {
-       }
-       else if (dev_priv->card_type >= NV_20) {
-               /* clear ctx table */
-               INSTANCE_WR(dev_priv->ctx_table, channel, 0);
-               nouveau_instmem_free(dev, chan->ramin_grctx);
-       }
+       engine->graph.destroy_context(chan);
 
        /* reenable the fifo caches */
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH,
+                NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
+       NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000001);
+       NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000001);
        NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
 
-       /* Deallocate command buffer */
-       if (chan->cmdbuf_mem)
-               nouveau_mem_free(dev, chan->cmdbuf_mem);
+       /* Deallocate push buffer */
+       nouveau_gpuobj_ref_del(dev, &chan->pushbuf);
+       if (chan->pushbuf_mem) {
+               nouveau_mem_free(dev, chan->pushbuf_mem);
+               chan->pushbuf_mem = NULL;
+       }
 
        /* Destroy objects belonging to the channel */
-       nouveau_object_cleanup(dev, channel);
+       nouveau_gpuobj_channel_takedown(chan);
+
+       nouveau_notifier_takedown_channel(chan);
 
+       dev_priv->fifos[chan->id] = NULL;
        dev_priv->fifo_alloc_count--;
+       drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER);
 }
 
-/* cleanups all the fifos from filp */
-void nouveau_fifo_cleanup(drm_device_t* dev, DRMFILE filp)
+/* cleanups all the fifos from file_priv */
+void nouveau_fifo_cleanup(struct drm_device *dev, struct drm_file *file_priv)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
 
-       DRM_DEBUG("clearing FIFO enables from filp\n");
-       for(i=0;i<nouveau_fifo_number(dev);i++)
-               if (dev_priv->fifos[i].used && dev_priv->fifos[i].filp==filp)
-                       nouveau_fifo_free(dev,i);
+       DRM_DEBUG("clearing FIFO enables from file_priv\n");
+       for(i = 0; i < nouveau_fifo_number(dev); i++) {
+               struct nouveau_channel *chan = dev_priv->fifos[i];
+
+               if (chan && chan->file_priv == file_priv)
+                       nouveau_fifo_free(chan);
+       }
 }
 
 int
-nouveau_fifo_owner(drm_device_t *dev, DRMFILE filp, int channel)
+nouveau_fifo_owner(struct drm_device *dev, struct drm_file *file_priv,
+                  int channel)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        if (channel >= nouveau_fifo_number(dev))
                return 0;
-       if (dev_priv->fifos[channel].used == 0)
+       if (dev_priv->fifos[channel] == NULL)
                return 0;
-       return (dev_priv->fifos[channel].filp == filp);
+       return (dev_priv->fifos[channel]->file_priv == file_priv);
 }
 
 /***********************************
  * ioctls wrapping the functions
  ***********************************/
 
-static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS)
+static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       drm_nouveau_fifo_alloc_t init;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct drm_nouveau_channel_alloc *init = data;
+       struct drm_map_list *entry;
+       struct nouveau_channel *chan;
+       struct mem_block *pushbuf;
        int res;
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_fifo_alloc_t __user *) data,
-                                sizeof(init));
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+       if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
+               return -EINVAL;
 
-       res = nouveau_fifo_alloc(dev, &init.channel, filp);
+       pushbuf = nouveau_fifo_user_pushbuf_alloc(dev);
+       if (!pushbuf)
+               return -ENOMEM;
+
+       res = nouveau_fifo_alloc(dev, &chan, file_priv, pushbuf,
+                                init->fb_ctxdma_handle,
+                                init->tt_ctxdma_handle);
        if (res)
                return res;
-
-       /* this should probably disappear in the next abi break? */
-       init.put_base = 0;
+       init->channel  = chan->id;
+       init->put_base = chan->pushbuf_base;
 
        /* make the fifo available to user space */
        /* first, the fifo control regs */
-       init.ctrl      = dev_priv->mmio->offset + NV03_FIFO_REGS(init.channel);
-       init.ctrl_size = NV03_FIFO_REGS_SIZE;
-       res = drm_addmap(dev, init.ctrl, init.ctrl_size, _DRM_REGISTERS,
-                        0, &dev_priv->fifos[init.channel].regs);
+       init->ctrl = dev_priv->mmio->offset;
+       if (dev_priv->card_type < NV_50) {
+               init->ctrl      += NV03_FIFO_REGS(init->channel);
+               init->ctrl_size  = NV03_FIFO_REGS_SIZE;
+       } else {
+               init->ctrl      += NV50_FIFO_REGS(init->channel);
+               init->ctrl_size  = NV50_FIFO_REGS_SIZE;
+       }
+       res = drm_addmap(dev, init->ctrl, init->ctrl_size, _DRM_REGISTERS,
+                        0, &chan->regs);
        if (res != 0)
                return res;
 
+       entry = drm_find_matching_map(dev, chan->regs);
+       if (!entry)
+               return -EINVAL;
+       init->ctrl = entry->user_token;
+
        /* pass back FIFO map info to the caller */
-       init.cmdbuf      = dev_priv->fifos[init.channel].cmdbuf_mem->start;
-       init.cmdbuf_size = dev_priv->fifos[init.channel].cmdbuf_mem->size;
+       init->cmdbuf      = chan->pushbuf_mem->map_handle;
+       init->cmdbuf_size = chan->pushbuf_mem->size;
+
+       /* and the notifier block */
+       init->notifier      = chan->notifier_block->map_handle;
+       init->notifier_size = chan->notifier_block->size;
+
+       return 0;
+}
+
+static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv)
+{
+       struct drm_nouveau_channel_free *cfree = data;
+       struct nouveau_channel *chan;
+
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+       NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
 
-       DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_alloc_t __user *)data,
-                              init, sizeof(init));
+       nouveau_fifo_free(chan);
        return 0;
 }
 
@@ -704,14 +554,17 @@ static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS)
  * finally, the ioctl table
  ***********************************/
 
-drm_ioctl_desc_t nouveau_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_NOUVEAU_FIFO_ALLOC)] = {nouveau_ioctl_fifo_alloc, DRM_AUTH},  
-       [DRM_IOCTL_NR(DRM_NOUVEAU_OBJECT_INIT)] = {nouveau_ioctl_object_init, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_NOUVEAU_DMA_OBJECT_INIT)] = {nouveau_ioctl_dma_object_init, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_NOUVEAU_MEM_ALLOC)] = {nouveau_ioctl_mem_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_NOUVEAU_MEM_FREE)] = {nouveau_ioctl_mem_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_NOUVEAU_GETPARAM)] = {nouveau_ioctl_getparam, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_NOUVEAU_SETPARAM)] = {nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},     
+struct drm_ioctl_desc nouveau_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
 };
 
 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
index 8de6e70..ac50729 100644 (file)
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
 #include "nouveau_reg.h"
+#include "nouveau_swmthd.h"
 
-void nouveau_irq_preinstall(drm_device_t *dev)
+void
+nouveau_irq_preinstall(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       DRM_DEBUG("IRQ: preinst\n");
-
-       if (!dev_priv) {
-               DRM_ERROR("AIII, no dev_priv\n");
-               return;
-       }
-       if (!dev_priv->mmio) {
-               DRM_ERROR("AIII, no dev_priv->mmio\n");
-               return;
-       }
-
-       /* Disable/Clear PFIFO interrupts */
-       NV_WRITE(NV03_PFIFO_INTR_EN_0, 0);
-       NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
-       /* Disable/Clear PGRAPH interrupts */
-       if (dev_priv->card_type<NV_40)
-               NV_WRITE(NV03_PGRAPH_INTR_EN, 0);
-       else
-               NV_WRITE(NV40_PGRAPH_INTR_EN, 0);
-       NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
-#if 0
-       /* Disable/Clear CRTC0/1 interrupts */
-       NV_WRITE(NV_CRTC0_INTEN, 0);
-       NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
-       NV_WRITE(NV_CRTC1_INTEN, 0);
-       NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
-#endif
        /* Master disable */
        NV_WRITE(NV03_PMC_INTR_EN_0, 0);
 }
 
-void nouveau_irq_postinstall(drm_device_t *dev)
+void
+nouveau_irq_postinstall(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-
-       if (!dev_priv) {
-               DRM_ERROR("AIII, no dev_priv\n");
-               return;
-       }
-       if (!dev_priv->mmio) {
-               DRM_ERROR("AIII, no dev_priv->mmio\n");
-               return;
-       }
-
-       DRM_DEBUG("IRQ: postinst\n");
-
-       /* Enable PFIFO error reporting */
-       NV_WRITE(NV03_PFIFO_INTR_EN_0 , 
-                       NV_PFIFO_INTR_CACHE_ERROR |
-                       NV_PFIFO_INTR_RUNOUT |
-                       NV_PFIFO_INTR_RUNOUT_OVERFLOW |
-                       NV_PFIFO_INTR_DMA_PUSHER |
-                       NV_PFIFO_INTR_DMA_PT |
-                       NV_PFIFO_INTR_SEMAPHORE |
-                       NV_PFIFO_INTR_ACQUIRE_TIMEOUT
-                       );
-       NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
-
-       /* Enable PGRAPH interrupts */
-       if (dev_priv->card_type<NV_40)
-               NV_WRITE(NV03_PGRAPH_INTR_EN,
-                               NV_PGRAPH_INTR_NOTIFY |
-                               NV_PGRAPH_INTR_MISSING_HW |
-                               NV_PGRAPH_INTR_CONTEXT_SWITCH |
-                               NV_PGRAPH_INTR_BUFFER_NOTIFY |
-                               NV_PGRAPH_INTR_ERROR
-                               );
-       else
-               NV_WRITE(NV40_PGRAPH_INTR_EN,
-                               NV_PGRAPH_INTR_NOTIFY |
-                               NV_PGRAPH_INTR_MISSING_HW |
-                               NV_PGRAPH_INTR_CONTEXT_SWITCH |
-                               NV_PGRAPH_INTR_BUFFER_NOTIFY |
-                               NV_PGRAPH_INTR_ERROR
-                               );
-       NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
-
-#if 0
-       /* Enable CRTC0/1 interrupts */
-       NV_WRITE(NV_CRTC0_INTEN, NV_CRTC_INTR_VBLANK);
-       NV_WRITE(NV_CRTC1_INTEN, NV_CRTC_INTR_VBLANK);
-#endif
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        /* Master enable */
        NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
 }
 
-void nouveau_irq_uninstall(drm_device_t *dev)
+void
+nouveau_irq_uninstall(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-
-       if (!dev_priv) {
-               DRM_ERROR("AIII, no dev_priv\n");
-               return;
-       }
-       if (!dev_priv->mmio) {
-               DRM_ERROR("AIII, no dev_priv->mmio\n");
-               return;
-       }
-
-       DRM_DEBUG("IRQ: uninst\n");
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       /* Disable PFIFO interrupts */
-       NV_WRITE(NV03_PFIFO_INTR_EN_0, 0);
-       /* Disable PGRAPH interrupts */
-       if (dev_priv->card_type<NV_40)
-               NV_WRITE(NV03_PGRAPH_INTR_EN, 0);
-       else
-               NV_WRITE(NV40_PGRAPH_INTR_EN, 0);
-#if 0
-       /* Disable CRTC0/1 interrupts */
-       NV_WRITE(NV_CRTC0_INTEN, 0);
-       NV_WRITE(NV_CRTC1_INTEN, 0);
-#endif
        /* Master disable */
        NV_WRITE(NV03_PMC_INTR_EN_0, 0);
 }
 
-static void nouveau_fifo_irq_handler(drm_device_t *dev)
+static void
+nouveau_fifo_irq_handler(struct drm_device *dev)
 {
-       uint32_t status, chmode, chstat, channel;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t status;
 
-       status = NV_READ(NV03_PFIFO_INTR_0);
-       if (!status)
-               return;
-       chmode = NV_READ(NV04_PFIFO_MODE);
-       chstat = NV_READ(NV04_PFIFO_DMA);
-       channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
+       while ((status = NV_READ(NV03_PFIFO_INTR_0))) {
+               uint32_t chid, get;
+
+               NV_WRITE(NV03_PFIFO_CACHES, 0);
+
+               chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) &
+                               (nouveau_fifo_number(dev) - 1);
+               get  = NV_READ(NV03_PFIFO_CACHE1_GET);
+
+               if (status & NV_PFIFO_INTR_CACHE_ERROR) {
+                       uint32_t mthd, data;
+                       int ptr;
+                       
+                       ptr = get >> 2;
+                       if (dev_priv->card_type < NV_40) {
+                               mthd = NV_READ(NV04_PFIFO_CACHE1_METHOD(ptr));
+                               data = NV_READ(NV04_PFIFO_CACHE1_DATA(ptr));
+                       } else {
+                               mthd = NV_READ(NV40_PFIFO_CACHE1_METHOD(ptr));
+                               data = NV_READ(NV40_PFIFO_CACHE1_DATA(ptr));
+                       }
 
-       DRM_DEBUG("NV: PFIFO interrupt! Channel=%d, INTSTAT=0x%08x/MODE=0x%08x/PEND=0x%08x\n", channel, status, chmode, chstat);
+                       DRM_INFO("PFIFO_CACHE_ERROR - "
+                                "Ch %d/%d Mthd 0x%04x Data 0x%08x\n",
+                                chid, (mthd >> 13) & 7, mthd & 0x1ffc, data);
 
-       if (status & NV_PFIFO_INTR_CACHE_ERROR) {
-               uint32_t c1get, c1method, c1data;
+                       NV_WRITE(NV03_PFIFO_CACHE1_GET, get + 4);
+                       NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 1);
 
-               DRM_ERROR("NV: PFIFO error interrupt\n");
+                       status &= ~NV_PFIFO_INTR_CACHE_ERROR;
+                       NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
+               }
 
-               c1get = NV_READ(NV03_PFIFO_CACHE1_GET) >> 2;
-               if (dev_priv->card_type < NV_40) {
-                       /* Untested, so it may not work.. */
-                       c1method = NV_READ(NV04_PFIFO_CACHE1_METHOD(c1get));
-                       c1data   = NV_READ(NV04_PFIFO_CACHE1_DATA(c1get));
-               } else {
-                       c1method = NV_READ(NV40_PFIFO_CACHE1_METHOD(c1get));
-                       c1data   = NV_READ(NV40_PFIFO_CACHE1_DATA(c1get));
+               if (status & NV_PFIFO_INTR_DMA_PUSHER) {
+                       DRM_INFO("PFIFO_DMA_PUSHER - Ch %d\n", chid);
+
+                       status &= ~NV_PFIFO_INTR_DMA_PUSHER;
+                       NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER);
+
+                       NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
+                       if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT) != get)
+                               NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, get + 4);
                }
 
-               DRM_ERROR("NV: Channel %d/%d - Method 0x%04x, Data 0x%08x\n",
-                               channel, (c1method >> 13) & 7,
-                               c1method & 0x1ffc, c1data
-                        );
+               if (status) {
+                       DRM_INFO("Unhandled PFIFO_INTR - 0x%8x\n", status);
+                       NV_WRITE(NV03_PFIFO_INTR_0, status);
+               }
 
-               status &= ~NV_PFIFO_INTR_CACHE_ERROR;
-               NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
+               NV_WRITE(NV03_PFIFO_CACHES, 1);
        }
 
-       if (status & NV_PFIFO_INTR_DMA_PUSHER) {
-               DRM_INFO("NV: PFIFO DMA pusher interrupt\n");
+       NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
+}
 
-               status &= ~NV_PFIFO_INTR_DMA_PUSHER;
-               NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER);
+struct nouveau_bitfield_names {
+       uint32_t mask;
+       const char * name;
+};
 
-               NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
-               if (NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)!=NV_READ(NV04_PFIFO_CACHE1_DMA_GET))
-               {
-                       uint32_t getval=NV_READ(NV04_PFIFO_CACHE1_DMA_GET)+4;
-                       NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET,getval);
-               }
-       }
+static struct nouveau_bitfield_names nouveau_nstatus_names[] =
+{
+       { NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
+       { NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
+       { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
+       { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
+};
 
-       if (status) {
-               DRM_INFO("NV: unknown PFIFO interrupt. status=0x%08x\n", status);
+static struct nouveau_bitfield_names nouveau_nstatus_names_nv10[] =
+{
+       { NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
+       { NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
+       { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
+       { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
+};
 
-               NV_WRITE(NV03_PFIFO_INTR_0, status);
-       }
+static struct nouveau_bitfield_names nouveau_nsource_names[] =
+{
+       { NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
+       { NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
+       { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
+       { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
+       { NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
+       { NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
+       { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
+       { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
+       { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
+       { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
+       { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
+       { NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
+       { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
+       { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
+       { NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
+       { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
+       { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
+       { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
+       { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
+};
 
-       NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
+static void
+nouveau_print_bitfield_names(uint32_t value,
+                             const struct nouveau_bitfield_names *namelist,
+                             const int namelist_len)
+{
+       int i;
+       for(i=0; i<namelist_len; ++i) {
+               uint32_t mask = namelist[i].mask;
+               if(value & mask) {
+                       printk(" %s", namelist[i].name);
+                       value &= ~mask;
+               }
+       }
+       if(value)
+               printk(" (unknown bits 0x%08x)", value);
 }
 
-#if 0
-static void nouveau_nv04_context_switch(drm_device_t *dev)
+static int
+nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       uint32_t channel,i;
-       uint32_t max=0;
-       NV_WRITE(NV04_PGRAPH_FIFO,0x0);
-       channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
-       //DRM_INFO("raw PFIFO_CACH1_PHS1 reg is %x\n",NV_READ(NV03_PFIFO_CACHE1_PUSH1));
-       //DRM_INFO("currently on channel %d\n",channel);
-       for (i=0;i<nouveau_fifo_number(dev);i++)
-               if ((dev_priv->fifos[i].used)&&(i!=channel)) {
-                       uint32_t put,get,pending;
-                       //put=NV_READ(dev_priv->ramfc_offset+i*32);
-                       //get=NV_READ(dev_priv->ramfc_offset+4+i*32);
-                       put=NV_READ(NV03_FIFO_REGS_DMAPUT(i));
-                       get=NV_READ(NV03_FIFO_REGS_DMAGET(i));
-                       pending=NV_READ(NV04_PFIFO_DMA);
-                       //DRM_INFO("Channel %d (put/get %x/%x)\n",i,put,get);
-                       /* mark all pending channels as such */
-                       if ((put!=get)&!(pending&(1<<i)))
-                       {
-                               pending|=(1<<i);
-                               NV_WRITE(NV04_PFIFO_DMA,pending);
-                       }
-                       max++;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int channel;
+
+       if (dev_priv->card_type < NV_10) {
+               channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
+       } else if (dev_priv->card_type < NV_40) {
+               channel = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
+       } else
+       if (dev_priv->card_type < NV_50) {
+               uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 4;
+
+               /* 0x400704 *sometimes* contains a sensible channel ID, but
+                * mostly not.. for now lookup which channel owns the active
+                * PGRAPH context.  Probably a better way, but this'll do
+                * for now.
+                */
+               for (channel = 0; channel < 32; channel++) {
+                       if (dev_priv->fifos[channel] == NULL)
+                               continue;
+                       if (cur_grctx ==
+                           dev_priv->fifos[channel]->ramin_grctx->instance)
+                               break;
+               }
+               if (channel == 32) {
+                       DRM_ERROR("AIII, unable to determine active channel "
+                                 "from PGRAPH context 0x%08x\n", cur_grctx);
+                       return -EINVAL;
+               }
+       } else {
+               uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 12;
+
+               for (channel = 0; channel < 128; channel++) {
+                       if (dev_priv->fifos[channel] == NULL)
+                               continue;
+                       if (cur_grctx ==
+                           dev_priv->fifos[channel]->ramin_grctx->instance)
+                               break;
+               }
+               if (channel == 128) {
+                       DRM_ERROR("AIII, unable to determine active channel "
+                                 "from PGRAPH context 0x%08x\n", cur_grctx);
+                       return -EINVAL;
                }
-       nouveau_wait_for_idle(dev);
+       }
 
-#if 1
-       /* 2-channel commute */
-       //              NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,channel|0x100);
-       if (channel==0)
-               channel=1;
-       else
-               channel=0;
-       //              dev_priv->cur_fifo=channel;
-       NV_WRITE(NV04_PFIFO_NEXT_CHANNEL,channel|0x100);
-#endif
-       //NV_WRITE(NV03_PFIFO_CACHE1_PUSH1,max|0x100);
-       //NV_WRITE(0x2050,max|0x100);
-
-       NV_WRITE(NV04_PGRAPH_FIFO,0x1);
-       
+       if (channel > nouveau_fifo_number(dev) ||
+           dev_priv->fifos[channel] == NULL) {
+               DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel);
+               return -EINVAL;
+       }
+
+       *channel_ret = channel;
+       return 0;
 }
-#endif
 
 static void
-nouveau_graph_dump_trap_info(drm_device_t *dev)
+nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t address;
-       uint32_t channel;
-       uint32_t method, subc, data;
+       uint32_t channel, class;
+       uint32_t method, subc, data, data2;
+       uint32_t nsource, nstatus;
+
+       if (nouveau_graph_trapped_channel(dev, &channel))
+               channel = -1;
 
-       address = NV_READ(0x400704);
-       data    = NV_READ(0x400708);
-       channel = (address >> 20) & 0x1F;
-       subc    = (address >> 16) & 0x7;
+       data    = NV_READ(NV04_PGRAPH_TRAPPED_DATA);
+       address = NV_READ(NV04_PGRAPH_TRAPPED_ADDR);
        method  = address & 0x1FFC;
+       if (dev_priv->card_type < NV_10) {
+               subc = (address >> 13) & 0x7;
+               data2= 0;
+       } else {
+               subc = (address >> 16) & 0x7;
+               data2= NV_READ(NV10_PGRAPH_TRAPPED_DATA_HIGH);
+       }
+       nsource = NV_READ(NV03_PGRAPH_NSOURCE);
+       nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
+       if (dev_priv->card_type < NV_10) {
+               class = NV_READ(0x400180 + subc*4) & 0xFF;
+       } else if (dev_priv->card_type < NV_40) {
+               class = NV_READ(0x400160 + subc*4) & 0xFFF;
+       } else if (dev_priv->card_type < NV_50) {
+               class = NV_READ(0x400160 + subc*4) & 0xFFFF;
+       } else {
+               class = NV_READ(0x400814);
+       }
 
-       DRM_ERROR("NV: nSource: 0x%08x, nStatus: 0x%08x\n",
-                       NV_READ(0x400108), NV_READ(0x400104));
-       DRM_ERROR("NV: Channel %d/%d (class 0x%04x) -"
-                       "Method 0x%04x, Data 0x%08x\n",
-                       channel, subc,
-                       NV_READ(0x400160+subc*4) & 0xFFFF,
-                       method, data
-                );
+       DRM_INFO("%s - nSource:", id);
+       nouveau_print_bitfield_names(nsource, nouveau_nsource_names,
+                                    ARRAY_SIZE(nouveau_nsource_names));
+       printk(", nStatus:");
+       if (dev_priv->card_type < NV_10)
+               nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names,
+                                    ARRAY_SIZE(nouveau_nstatus_names));
+       else
+               nouveau_print_bitfield_names(nstatus, nouveau_nstatus_names_nv10,
+                                    ARRAY_SIZE(nouveau_nstatus_names_nv10));
+       printk("\n");
+
+       DRM_INFO("%s - Ch %d/%d Class 0x%04x Mthd 0x%04x Data 0x%08x:0x%08x\n",
+                id, channel, subc, class, method, data2, data);
 }
 
-static void nouveau_pgraph_irq_handler(drm_device_t *dev)
+static inline void
+nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
 {
-       uint32_t status;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-
-       status = NV_READ(NV03_PGRAPH_INTR);
-       if (!status)
-               return;
-
-       if (status & NV_PGRAPH_INTR_NOTIFY) {
-               uint32_t nsource, nstatus, instance, notify;
-               DRM_DEBUG("NV: PGRAPH notify interrupt\n");
-
-               nstatus = NV_READ(0x00400104);
-               nsource = NV_READ(0x00400108);
-               DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
-
-               /* if this wasn't NOTIFICATION_PENDING, dump extra trap info */
-               if (nsource & ~(1<<0)) {
-                       nouveau_graph_dump_trap_info(dev);
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int handled = 0;
+
+       DRM_DEBUG("PGRAPH notify interrupt\n");
+       if (dev_priv->card_type == NV_04 &&
+           (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
+               uint32_t class, mthd;
+
+               /* NV4 (nvidia TNT 1) reports software methods with
+                * PGRAPH NOTIFY ILLEGAL_MTHD
+                */
+               mthd = NV_READ(NV04_PGRAPH_TRAPPED_ADDR) & 0x1FFC;
+               class = NV_READ(NV04_PGRAPH_CTX_SWITCH1) & 0xFFF;
+               DRM_DEBUG("Got NV04 software method method %x for class %#x\n",
+                         mthd, class);
+
+               if (nouveau_sw_method_execute(dev, class, mthd)) {
+                       DRM_ERROR("Unable to execute NV04 software method %x "
+                                 "for object class %x. Please report.\n",
+                                 mthd, class);
                } else {
-                       instance = NV_READ(0x00400158);
-                       notify   = NV_READ(0x00400150) >> 16;
-                       DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n",
-                                       nsource, nstatus);
+                       handled = 1;
                }
-
-               status &= ~NV_PGRAPH_INTR_NOTIFY;
-               NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
        }
 
-       if (status & NV_PGRAPH_INTR_BUFFER_NOTIFY) {
-               uint32_t nsource, nstatus, instance, notify;
-               DRM_DEBUG("NV: PGRAPH buffer notify interrupt\n");
-
-               nstatus = NV_READ(0x00400104);
-               nsource = NV_READ(0x00400108);
-               DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
+       if (!handled)
+               nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY");
+}
 
-               instance = NV_READ(0x00400158);
-               notify   = NV_READ(0x00400150) >> 16;
-               DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", instance, notify);
+static inline void
+nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
+{
+       nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR");
+}
 
-               status &= ~NV_PGRAPH_INTR_BUFFER_NOTIFY;
-               NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_BUFFER_NOTIFY);
+static inline void
+nouveau_pgraph_intr_context_switch(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t chid;
+       
+       chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1);
+       DRM_DEBUG("PGRAPH context switch interrupt channel %x\n", chid);
+
+       switch(dev_priv->card_type) {
+       case NV_04:
+       case NV_05:
+               nouveau_nv04_context_switch(dev);
+               break;
+       case NV_10:
+       case NV_11:
+       case NV_17:
+               nouveau_nv10_context_switch(dev);
+               break;
+       default:
+               DRM_ERROR("Context switch not implemented\n");
+               break;
        }
+}
 
-       if (status & NV_PGRAPH_INTR_MISSING_HW) {
-               DRM_ERROR("NV: PGRAPH missing hw interrupt\n");
-
-               status &= ~NV_PGRAPH_INTR_MISSING_HW;
-               NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_MISSING_HW);
-       }
+static void
+nouveau_pgraph_irq_handler(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t status;
 
-       if (status & NV_PGRAPH_INTR_ERROR) {
-               uint32_t nsource, nstatus, instance;
+       while ((status = NV_READ(NV03_PGRAPH_INTR))) {
+               uint32_t nsource = NV_READ(NV03_PGRAPH_NSOURCE);
 
-               DRM_ERROR("NV: PGRAPH error interrupt\n");
+               if (status & NV_PGRAPH_INTR_NOTIFY) {
+                       nouveau_pgraph_intr_notify(dev, nsource);
 
-               nstatus = NV_READ(0x00400104);
-               nsource = NV_READ(0x00400108);
-               DRM_ERROR("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
+                       status &= ~NV_PGRAPH_INTR_NOTIFY;
+                       NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
+               }
 
-               instance = NV_READ(0x00400158);
-               DRM_ERROR("instance:0x%08x\n", instance);
+               if (status & NV_PGRAPH_INTR_ERROR) {
+                       nouveau_pgraph_intr_error(dev, nsource);
 
-               nouveau_graph_dump_trap_info(dev);
+                       status &= ~NV_PGRAPH_INTR_ERROR;
+                       NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
+               }
 
-               status &= ~NV_PGRAPH_INTR_ERROR;
-               NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
-       }
+               if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
+                       nouveau_pgraph_intr_context_switch(dev);
 
-       if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
-               uint32_t channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
-               DRM_INFO("NV: PGRAPH context switch interrupt channel %x\n",channel);
-               switch(dev_priv->card_type)
-               {
-                       case NV_04:
-                       case NV_05:
-                               nouveau_nv04_context_switch(dev);
-                               break;
-                       case NV_10:
-                       case NV_17:
-                               nouveau_nv10_context_switch(dev);
-                               break;
-                       case NV_20:
-                       case NV_30:
-                               nouveau_nv20_context_switch(dev);
-                               break;
-                       default:
-                               DRM_INFO("NV: Context switch not implemented\n");
-                               break;
+                       status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
+                       NV_WRITE(NV03_PGRAPH_INTR,
+                                NV_PGRAPH_INTR_CONTEXT_SWITCH);
                }
 
-               status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
-               NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
-       }
+               if (status) {
+                       DRM_INFO("Unhandled PGRAPH_INTR - 0x%8x\n", status);
+                       NV_WRITE(NV03_PGRAPH_INTR, status);
+               }
 
-       if (status) {
-               DRM_INFO("NV: Unknown PGRAPH interrupt! STAT=0x%08x\n", status);
-               NV_WRITE(NV03_PGRAPH_INTR, status);
+               if ((NV_READ(NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
+                       NV_WRITE(NV04_PGRAPH_FIFO, 1);
        }
 
        NV_WRITE(NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
 }
 
-static void nouveau_crtc_irq_handler(drm_device_t *dev, int crtc)
+static void
+nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
        if (crtc&1) {
                NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
        }
@@ -408,26 +414,27 @@ static void nouveau_crtc_irq_handler(drm_device_t *dev, int crtc)
        }
 }
 
-irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t
+nouveau_irq_handler(DRM_IRQ_ARGS)
 {
-       drm_device_t          *dev = (drm_device_t*)arg;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_device *dev = (struct drm_device*)arg;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t status;
 
        status = NV_READ(NV03_PMC_INTR_0);
        if (!status)
                return IRQ_NONE;
 
-       DRM_DEBUG("PMC INTSTAT: 0x%08x\n", status);
-
        if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
                nouveau_fifo_irq_handler(dev);
                status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
        }
+
        if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
                nouveau_pgraph_irq_handler(dev);
                status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
        }
+
        if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
                nouveau_crtc_irq_handler(dev, (status>>24)&3);
                status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
index a5343b9..448b69d 100644 (file)
@@ -36,7 +36,7 @@
 #include "nouveau_drv.h"
 
 static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64_t size,
-               DRMFILE filp)
+               struct drm_file *file_priv)
 {
        /* Maybe cut off the start of an existing block */
        if (start > p->start) {
@@ -46,7 +46,7 @@ static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64
                        goto out;
                newblock->start = start;
                newblock->size = p->size - (start - p->start);
-               newblock->filp = NULL;
+               newblock->file_priv = NULL;
                newblock->next = p->next;
                newblock->prev = p;
                p->next->prev = newblock;
@@ -63,7 +63,7 @@ static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64
                        goto out;
                newblock->start = start + size;
                newblock->size = p->size - size;
-               newblock->filp = NULL;
+               newblock->file_priv = NULL;
                newblock->next = p->next;
                newblock->prev = p;
                p->next->prev = newblock;
@@ -73,12 +73,14 @@ static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64
 
 out:
        /* Our block is in the middle */
-       p->filp = filp;
+       p->file_priv = file_priv;
        return p;
 }
 
-static struct mem_block *alloc_block(struct mem_block *heap, uint64_t size,
-               int align2, DRMFILE filp)
+struct mem_block *nouveau_mem_alloc_block(struct mem_block *heap,
+                                         uint64_t size,
+                                         int align2,
+                                         struct drm_file *file_priv)
 {
        struct mem_block *p;
        uint64_t mask = (1 << align2) - 1;
@@ -88,8 +90,8 @@ static struct mem_block *alloc_block(struct mem_block *heap, uint64_t size,
 
        list_for_each(p, heap) {
                uint64_t start = (p->start + mask) & ~mask;
-               if (p->filp == 0 && start + size <= p->start + p->size)
-                       return split_block(p, start, size, filp);
+               if (p->file_priv == 0 && start + size <= p->start + p->size)
+                       return split_block(p, start, size, file_priv);
        }
 
        return NULL;
@@ -106,14 +108,14 @@ static struct mem_block *find_block(struct mem_block *heap, uint64_t start)
        return NULL;
 }
 
-static void free_block(struct mem_block *p)
+void nouveau_mem_free_block(struct mem_block *p)
 {
-       p->filp = NULL;
+       p->file_priv = NULL;
 
-       /* Assumes a single contiguous range.  Needs a special filp in
+       /* Assumes a single contiguous range.  Needs a special file_priv in
         * 'heap' to stop it being subsumed.
         */
-       if (p->next->filp == 0) {
+       if (p->next->file_priv == 0) {
                struct mem_block *q = p->next;
                p->size += q->size;
                p->next = q->next;
@@ -121,7 +123,7 @@ static void free_block(struct mem_block *p)
                drm_free(q, sizeof(*q), DRM_MEM_BUFS);
        }
 
-       if (p->prev->filp == 0) {
+       if (p->prev->file_priv == 0) {
                struct mem_block *q = p->prev;
                q->size += p->size;
                q->next = p->next;
@@ -132,34 +134,35 @@ static void free_block(struct mem_block *p)
 
 /* Initialize.  How to check for an uninitialized heap?
  */
-static int init_heap(struct mem_block **heap, uint64_t start, uint64_t size)
+int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start,
+                         uint64_t size)
 {
        struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
 
        if (!blocks)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
        if (!*heap) {
                drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        blocks->start = start;
        blocks->size = size;
-       blocks->filp = NULL;
+       blocks->file_priv = NULL;
        blocks->next = blocks->prev = *heap;
 
        memset(*heap, 0, sizeof(**heap));
-       (*heap)->filp = (DRMFILE) - 1;
+       (*heap)->file_priv = (struct drm_file *) - 1;
        (*heap)->next = (*heap)->prev = blocks;
        return 0;
 }
 
 /* 
- * Free all blocks associated with the releasing filp
+ * Free all blocks associated with the releasing file_priv
  */
-void nouveau_mem_release(DRMFILE filp, struct mem_block *heap)
+void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
 {
        struct mem_block *p;
 
@@ -167,15 +170,16 @@ void nouveau_mem_release(DRMFILE filp, struct mem_block *heap)
                return;
 
        list_for_each(p, heap) {
-               if (p->filp == filp)
-                       p->filp = NULL;
+               if (p->file_priv == file_priv)
+                       p->file_priv = NULL;
        }
 
-       /* Assumes a single contiguous range.  Needs a special filp in
+       /* Assumes a single contiguous range.  Needs a special file_priv in
         * 'heap' to stop it being subsumed.
         */
        list_for_each(p, heap) {
-               while ((p->filp == 0) && (p->next->filp == 0) && (p->next!=heap)) {
+               while ((p->file_priv == 0) && (p->next->file_priv == 0) &&
+                      (p->next!=heap)) {
                        struct mem_block *q = p->next;
                        p->size += q->size;
                        p->next = q->next;
@@ -188,7 +192,7 @@ void nouveau_mem_release(DRMFILE filp, struct mem_block *heap)
 /* 
  * Cleanup everything
  */
-static void nouveau_mem_takedown(struct mem_block **heap)
+void nouveau_mem_takedown(struct mem_block **heap)
 {
        struct mem_block *p;
 
@@ -207,29 +211,52 @@ static void nouveau_mem_takedown(struct mem_block **heap)
 
 void nouveau_mem_close(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
        nouveau_mem_takedown(&dev_priv->agp_heap);
        nouveau_mem_takedown(&dev_priv->fb_heap);
+       if (dev_priv->pci_heap)
+               nouveau_mem_takedown(&dev_priv->pci_heap);
+}
+
+/*XXX won't work on BSD because of pci_read_config_dword */
+static uint32_t
+nouveau_mem_fb_amount_igp(struct drm_device *dev)
+{
+#if defined(__linux__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19))
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct pci_dev *bridge;
+       uint32_t mem;
+
+       bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0,1));
+       if (!bridge) {
+               DRM_ERROR("no bridge device\n");
+               return 0;
+       }
+
+       if (dev_priv->flags&NV_NFORCE) {
+               pci_read_config_dword(bridge, 0x7C, &mem);
+               return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;
+       } else
+       if(dev_priv->flags&NV_NFORCE2) {
+               pci_read_config_dword(bridge, 0x84, &mem);
+               return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;
+       }
+
+       DRM_ERROR("impossible!\n");
+#else
+       DRM_ERROR("Linux kernel >= 2.6.19 required to check for igp memory amount\n");
+#endif
+
+       return 0;
 }
 
 /* returns the amount of FB ram in bytes */
 uint64_t nouveau_mem_fb_amount(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
+       struct drm_nouveau_private *dev_priv=dev->dev_private;
        switch(dev_priv->card_type)
        {
-               case NV_03:
-                       switch(NV_READ(NV03_BOOT_0)&NV03_BOOT_0_RAM_AMOUNT)
-                       {
-                               case NV03_BOOT_0_RAM_AMOUNT_8MB:
-                               case NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM:
-                                       return 8*1024*1024;
-                               case NV03_BOOT_0_RAM_AMOUNT_4MB:
-                                       return 4*1024*1024;
-                               case NV03_BOOT_0_RAM_AMOUNT_2MB:
-                                       return 2*1024*1024;
-                       }
-                       break;
                case NV_04:
                case NV_05:
                        if (NV_READ(NV03_BOOT_0) & 0x00000100) {
@@ -248,6 +275,7 @@ uint64_t nouveau_mem_fb_amount(struct drm_device *dev)
                        }
                        break;
                case NV_10:
+               case NV_11:
                case NV_17:
                case NV_20:
                case NV_30:
@@ -255,18 +283,14 @@ uint64_t nouveau_mem_fb_amount(struct drm_device *dev)
                case NV_44:
                case NV_50:
                default:
-                       // XXX won't work on BSD because of pci_read_config_dword
-                       if (dev_priv->flags&NV_NFORCE) {
-                               uint32_t mem;
-                               pci_read_config_dword(dev->pdev, 0x7C, &mem);
-                               return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;
-                       } else if(dev_priv->flags&NV_NFORCE2) {
-                               uint32_t mem;
-                               pci_read_config_dword(dev->pdev, 0x84, &mem);
-                               return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;
+                       if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
+                               return nouveau_mem_fb_amount_igp(dev);
                        } else {
                                uint64_t mem;
-                               mem=(NV_READ(NV04_FIFO_DATA)&NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >> NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT;
+
+                               mem = (NV_READ(NV04_FIFO_DATA) & 
+                                      NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >>
+                                     NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT;
                                return mem*1024*1024;
                        }
                        break;
@@ -276,68 +300,67 @@ uint64_t nouveau_mem_fb_amount(struct drm_device *dev)
        return 0;
 }
 
-
-
-int nouveau_mem_init(struct drm_device *dev)
+static int
+nouveau_mem_init_agp(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       uint32_t fb_size;
-       dev_priv->agp_phys=0;
-       dev_priv->fb_phys=0;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct drm_agp_info info;
+       struct drm_agp_mode mode;
+       struct drm_agp_buffer agp_req;
+       struct drm_agp_binding bind_req;
+       int ret;
+
+       ret = drm_agp_acquire(dev);
+       if (ret) {
+               DRM_ERROR("Unable to acquire AGP: %d\n", ret);
+               return ret;
+       }
 
-       /* init AGP */
-       dev_priv->agp_heap=NULL;
-       if (drm_device_is_agp(dev))
-       {
-               int err;
-               drm_agp_info_t info;
-               drm_agp_mode_t mode;
-               drm_agp_buffer_t agp_req;
-               drm_agp_binding_t bind_req;
-
-               err = drm_agp_acquire(dev);
-               if (err) {
-                       DRM_ERROR("Unable to acquire AGP: %d\n", err);
-                       goto no_agp;
-               }
+       ret = drm_agp_info(dev, &info);
+       if (ret) {
+               DRM_ERROR("Unable to get AGP info: %d\n", ret);
+               return ret;
+       }
 
-               err = drm_agp_info(dev, &info);
-               if (err) {
-                       DRM_ERROR("Unable to get AGP info: %d\n", err);
-                       goto no_agp;
-               }
+       /* see agp.h for the AGPSTAT_* modes available */
+       mode.mode = info.mode;
+       ret = drm_agp_enable(dev, mode);
+       if (ret) {
+               DRM_ERROR("Unable to enable AGP: %d\n", ret);
+               return ret;
+       }
 
-               /* see agp.h for the AGPSTAT_* modes available */
-               mode.mode = info.mode;
-               err = drm_agp_enable(dev, mode);
-               if (err) {
-                       DRM_ERROR("Unable to enable AGP: %d\n", err);
-                       goto no_agp;
-               }
+       agp_req.size = info.aperture_size;
+       agp_req.type = 0;
+       ret = drm_agp_alloc(dev, &agp_req);
+       if (ret) {
+               DRM_ERROR("Unable to alloc AGP: %d\n", ret);
+               return ret;
+       }
 
-               agp_req.size = info.aperture_size;
-               agp_req.type = 0;
-               err = drm_agp_alloc(dev, &agp_req);
-               if (err) {
-                       DRM_ERROR("Unable to alloc AGP: %d\n", err);
-                       goto no_agp;
-               }
+       bind_req.handle = agp_req.handle;
+       bind_req.offset = 0;
+       ret = drm_agp_bind(dev, &bind_req);
+       if (ret) {
+               DRM_ERROR("Unable to bind AGP: %d\n", ret);
+               return ret;
+       }
 
-               bind_req.handle = agp_req.handle;
-               bind_req.offset = 0;
-               err = drm_agp_bind(dev, &bind_req);
-               if (err) {
-                       DRM_ERROR("Unable to bind AGP: %d\n", err);
-                       goto no_agp;
-               }
+       dev_priv->gart_info.type        = NOUVEAU_GART_AGP;
+       dev_priv->gart_info.aper_base   = info.aperture_base;
+       dev_priv->gart_info.aper_size   = info.aperture_size;
+       return 0;
+}
 
-               if (init_heap(&dev_priv->agp_heap, info.aperture_base, info.aperture_size))
-                       goto no_agp;
+int nouveau_mem_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t fb_size;
+       int ret = 0;
 
-               dev_priv->agp_phys              = info.aperture_base;
-               dev_priv->agp_available_size    = info.aperture_size;
-       }
-no_agp:
+       dev_priv->agp_heap = dev_priv->pci_heap = dev_priv->fb_heap = NULL;
+       dev_priv->fb_phys = 0;
+       dev_priv->gart_info.type = NOUVEAU_GART_NONE;
 
        /* setup a mtrr over the FB */
        dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
@@ -350,31 +373,83 @@ no_agp:
        /* On at least NV40, RAMIN is actually at the end of vram.
         * We don't want to allocate this... */
        if (dev_priv->card_type >= NV_40)
-               fb_size -= dev_priv->ramin_size;
+               fb_size -= dev_priv->ramin_rsvd_vram;
        dev_priv->fb_available_size = fb_size;
        DRM_DEBUG("Available VRAM: %dKiB\n", fb_size>>10);
 
        if (fb_size>256*1024*1024) {
                /* On cards with > 256Mb, you can't map everything. 
                 * So we create a second FB heap for that type of memory */
-               if (init_heap(&dev_priv->fb_heap, drm_get_resource_start(dev,1), 256*1024*1024))
-                       return DRM_ERR(ENOMEM);
-               if (init_heap(&dev_priv->fb_nomap_heap, drm_get_resource_start(dev,1)+256*1024*1024, fb_size-256*1024*1024))
-                       return DRM_ERR(ENOMEM);
+               if (nouveau_mem_init_heap(&dev_priv->fb_heap,
+                                         0, 256*1024*1024))
+                       return -ENOMEM;
+               if (nouveau_mem_init_heap(&dev_priv->fb_nomap_heap,
+                                         256*1024*1024, fb_size-256*1024*1024))
+                       return -ENOMEM;
        } else {
-               if (init_heap(&dev_priv->fb_heap, drm_get_resource_start(dev,1), fb_size))
-                       return DRM_ERR(ENOMEM);
+               if (nouveau_mem_init_heap(&dev_priv->fb_heap, 0, fb_size))
+                       return -ENOMEM;
                dev_priv->fb_nomap_heap=NULL;
        }
 
+       /* Init AGP / NV50 PCIEGART */
+       if (drm_device_is_agp(dev) && dev->agp) {
+               if ((ret = nouveau_mem_init_agp(dev)))
+                       DRM_ERROR("Error initialising AGP: %d\n", ret);
+       }
+
+       /*Note: this is *not* just NV50 code, but only used on NV50 for now */
+       if (dev_priv->gart_info.type == NOUVEAU_GART_NONE &&
+           dev_priv->card_type >= NV_50) {
+               ret = nouveau_sgdma_init(dev);
+               if (!ret) {
+                       ret = nouveau_sgdma_nottm_hack_init(dev);
+                       if (ret)
+                               nouveau_sgdma_takedown(dev); 
+               }
+
+               if (ret)
+                       DRM_ERROR("Error initialising SG DMA: %d\n", ret);
+       }
+
+       if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) {
+               if (nouveau_mem_init_heap(&dev_priv->agp_heap,
+                                         0, dev_priv->gart_info.aper_size)) {
+                       if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) {
+                               nouveau_sgdma_nottm_hack_takedown(dev);
+                               nouveau_sgdma_takedown(dev); 
+                       }
+               }
+       }
+
+       /* NV04-NV40 PCIEGART */
+       if (!dev_priv->agp_heap && dev_priv->card_type < NV_50) {
+               struct drm_scatter_gather sgreq;
+
+               DRM_DEBUG("Allocating sg memory for PCI DMA\n");
+               sgreq.size = 16 << 20; //16MB of PCI scatter-gather zone
+
+               if (drm_sg_alloc(dev, &sgreq)) {
+                       DRM_ERROR("Unable to allocate %ldMB of scatter-gather"
+                                 " pages for PCI DMA!",sgreq.size>>20);
+               } else {
+                       if (nouveau_mem_init_heap(&dev_priv->pci_heap, 0,
+                                                 dev->sg->pages * PAGE_SIZE)) {
+                               DRM_ERROR("Unable to initialize pci_heap!");    
+                       }
+               }
+       }
+
        return 0;
 }
 
-struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size, int flags, DRMFILE filp)
+struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment,
+                                   uint64_t size, int flags,
+                                   struct drm_file *file_priv)
 {
        struct mem_block *block;
        int type;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        /* 
         * Make things easier on ourselves: all allocations are page-aligned. 
@@ -395,25 +470,42 @@ struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, uint6
        if (size & (~PAGE_MASK))
                size = ((size/PAGE_SIZE) + 1) * PAGE_SIZE;
 
-       if (flags&NOUVEAU_MEM_AGP) {
-               type=NOUVEAU_MEM_AGP;
-               block = alloc_block(dev_priv->agp_heap, size, alignment, filp);
-               if (block) goto alloc_ok;
-       }
-       if (flags&(NOUVEAU_MEM_FB|NOUVEAU_MEM_FB_ACCEPTABLE)) {
-               type=NOUVEAU_MEM_FB;
-               if (!(flags&NOUVEAU_MEM_MAPPED)) {
-                       block = alloc_block(dev_priv->fb_nomap_heap, size, alignment, filp);
-                       if (block) goto alloc_ok;
-               }
-               block = alloc_block(dev_priv->fb_heap, size, alignment, filp);
-               if (block) goto alloc_ok;       
-       }
-       if (flags&NOUVEAU_MEM_AGP_ACCEPTABLE) {
-               type=NOUVEAU_MEM_AGP;
-               block = alloc_block(dev_priv->agp_heap, size, alignment, filp);
-               if (block) goto alloc_ok;
-       }
+
+#define NOUVEAU_MEM_ALLOC_AGP {\
+               type=NOUVEAU_MEM_AGP;\
+                block = nouveau_mem_alloc_block(dev_priv->agp_heap, size,\
+                                                alignment, file_priv); \
+                if (block) goto alloc_ok;\
+               }
+
+#define NOUVEAU_MEM_ALLOC_PCI {\
+                type = NOUVEAU_MEM_PCI;\
+                block = nouveau_mem_alloc_block(dev_priv->pci_heap, size, \
+                                               alignment, file_priv); \
+                if ( block ) goto alloc_ok;\
+               }
+
+#define NOUVEAU_MEM_ALLOC_FB {\
+                type=NOUVEAU_MEM_FB;\
+                if (!(flags&NOUVEAU_MEM_MAPPED)) {\
+                        block = nouveau_mem_alloc_block(dev_priv->fb_nomap_heap,\
+                                                        size, alignment, \
+                                                       file_priv); \
+                        if (block) goto alloc_ok;\
+                }\
+                block = nouveau_mem_alloc_block(dev_priv->fb_heap, size,\
+                                                alignment, file_priv);\
+                if (block) goto alloc_ok;\
+               }
+
+
+       if (flags&NOUVEAU_MEM_FB) NOUVEAU_MEM_ALLOC_FB
+       if (flags&NOUVEAU_MEM_AGP) NOUVEAU_MEM_ALLOC_AGP
+       if (flags&NOUVEAU_MEM_PCI) NOUVEAU_MEM_ALLOC_PCI
+       if (flags&NOUVEAU_MEM_FB_ACCEPTABLE) NOUVEAU_MEM_ALLOC_FB
+       if (flags&NOUVEAU_MEM_AGP_ACCEPTABLE) NOUVEAU_MEM_ALLOC_AGP
+       if (flags&NOUVEAU_MEM_PCI_ACCEPTABLE) NOUVEAU_MEM_ALLOC_PCI
+
 
        return NULL;
 
@@ -422,252 +514,92 @@ alloc_ok:
 
        if (flags&NOUVEAU_MEM_MAPPED)
        {
-               int ret;
+               struct drm_map_list *entry;
+               int ret = 0;
                block->flags|=NOUVEAU_MEM_MAPPED;
 
-               if (type == NOUVEAU_MEM_AGP)
-                       ret = drm_addmap(dev, block->start - dev->agp->base, block->size, 
-                                       _DRM_AGP, 0, &block->map);
-               else
+               if (type == NOUVEAU_MEM_AGP) {
+                       if (dev_priv->gart_info.type != NOUVEAU_GART_SGDMA)
+                       ret = drm_addmap(dev, block->start, block->size,
+                                        _DRM_AGP, 0, &block->map);
+                       else
                        ret = drm_addmap(dev, block->start, block->size,
-                                       _DRM_FRAME_BUFFER, 0, &block->map);
+                                        _DRM_SCATTER_GATHER, 0, &block->map);
+               }
+               else if (type == NOUVEAU_MEM_FB)
+                       ret = drm_addmap(dev, block->start + dev_priv->fb_phys,
+                                        block->size, _DRM_FRAME_BUFFER,
+                                        0, &block->map);
+               else if (type == NOUVEAU_MEM_PCI)
+                       ret = drm_addmap(dev, block->start, block->size,
+                                        _DRM_SCATTER_GATHER, 0, &block->map);
+
                if (ret) { 
-                       free_block(block);
+                       nouveau_mem_free_block(block);
+                       return NULL;
+               }
+
+               entry = drm_find_matching_map(dev, block->map);
+               if (!entry) {
+                       nouveau_mem_free_block(block);
                        return NULL;
                }
+               block->map_handle = entry->user_token;
        }
 
-       DRM_INFO("allocated 0x%llx\n", block->start);
+       DRM_DEBUG("allocated 0x%llx type=0x%08x\n", block->start, block->flags);
        return block;
 }
 
 void nouveau_mem_free(struct drm_device* dev, struct mem_block* block)
 {
-       DRM_INFO("freeing 0x%llx\n", block->start);
+       DRM_DEBUG("freeing 0x%llx type=0x%08x\n", block->start, block->flags);
        if (block->flags&NOUVEAU_MEM_MAPPED)
                drm_rmmap(dev, block->map);
-       free_block(block);
-}
-
-static void
-nouveau_instmem_determine_amount(struct drm_device *dev)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int i;
-
-       /* Figure out how much instance memory we need */
-       switch (dev_priv->card_type) {
-       case NV_40:
-               /* We'll want more instance memory than this on some NV4x cards.
-                * There's a 16MB aperture to play with that maps onto the end
-                * of vram.  For now, only reserve a small piece until we know
-                * more about what each chipset requires.
-                */
-               dev_priv->ramin_size = (1*1024* 1024);
-               break;
-       default:
-               /*XXX: what *are* the limits on <NV40 cards?, and does RAMIN
-                *     exist in vram on those cards as well?
-                */
-               dev_priv->ramin_size = (512*1024);
-               break;
-       }
-       DRM_DEBUG("RAMIN size: %dKiB\n", dev_priv->ramin_size>>10);
-
-       /* Clear all of it, except the BIOS image that's in the first 64KiB */
-       if (dev_priv->ramin) {
-               for (i=(64*1024); i<dev_priv->ramin_size; i+=4)
-                       DRM_WRITE32(dev_priv->ramin, i, 0x00000000);
-       } else {
-               for (i=(64*1024); i<dev_priv->ramin_size; i+=4)
-                       DRM_WRITE32(dev_priv->mmio, NV_RAMIN + i, 0x00000000);
-       }
-}
-
-static void
-nouveau_instmem_configure_fixed_tables(struct drm_device *dev)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-
-       /* FIFO hash table (RAMHT)
-        *   use 4k hash table at RAMIN+0x10000
-        *   TODO: extend the hash table
-        */
-       dev_priv->ramht_offset = 0x10000;
-       dev_priv->ramht_bits   = 9;
-       dev_priv->ramht_size   = (1 << dev_priv->ramht_bits);
-       DRM_DEBUG("RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset,
-                                                 dev_priv->ramht_size);
-
-       /* FIFO runout table (RAMRO) - 512k at 0x11200 */
-       dev_priv->ramro_offset = 0x11200;
-       dev_priv->ramro_size   = 512;
-       DRM_DEBUG("RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset,
-                                                 dev_priv->ramro_size);
-
-       /* FIFO context table (RAMFC)
-        *   NV40  : Not sure exactly how to position RAMFC on some cards,
-        *           0x30002 seems to position it at RAMIN+0x20000 on these
-        *           cards.  RAMFC is 4kb (32 fifos, 128byte entries).
-        *   Others: Position RAMFC at RAMIN+0x11400
-        */
-       switch(dev_priv->card_type)
-       {
-               case NV_50:
-               case NV_40:
-               case NV_44:
-                       dev_priv->ramfc_offset = 0x20000;
-                       dev_priv->ramfc_size   = nouveau_fifo_number(dev) *
-                               nouveau_fifo_ctx_size(dev);
-                       break;
-               case NV_30:
-               case NV_20:
-               case NV_17:
-               case NV_10:
-               case NV_04:
-               case NV_03:
-               default:
-                       dev_priv->ramfc_offset = 0x11400;
-                       dev_priv->ramfc_size   = nouveau_fifo_number(dev) *
-                               nouveau_fifo_ctx_size(dev);
-                       break;
-       }
-       DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset,
-                                                 dev_priv->ramfc_size);
-}
-
-int nouveau_instmem_init(struct drm_device *dev)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       uint32_t offset;
-       int ret = 0;
-
-       nouveau_instmem_determine_amount(dev);
-       nouveau_instmem_configure_fixed_tables(dev);
-
-       /* Create a heap to manage RAMIN allocations, we don't allocate
-        * the space that was reserved for RAMHT/FC/RO.
-        */
-       offset = dev_priv->ramfc_offset + dev_priv->ramfc_size;
-       ret = init_heap(&dev_priv->ramin_heap,
-                        offset, dev_priv->ramin_size - offset);
-       if (ret) {
-               dev_priv->ramin_heap = NULL;
-               DRM_ERROR("Failed to init RAMIN heap\n");
-       }
-
-       return ret;
-}
-
-struct mem_block *nouveau_instmem_alloc(struct drm_device *dev,
-                                       uint32_t size, uint32_t align)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct mem_block *block;
-
-       if (!dev_priv->ramin_heap) {
-               DRM_ERROR("instmem alloc called without init\n");
-               return NULL;
-       }
-
-       block = alloc_block(dev_priv->ramin_heap, size, align, (DRMFILE)-2);
-       if (block) {
-               block->flags = NOUVEAU_MEM_INSTANCE;
-               DRM_DEBUG("instance(size=%d, align=%d) alloc'd at 0x%08x\n",
-                               size, (1<<align), (uint32_t)block->start);
-       }
-
-       return block;
-}
-
-void nouveau_instmem_free(struct drm_device *dev, struct mem_block *block)
-{
-       if (dev && block) {
-               free_block(block);
-       }
-}
-
-uint32_t nouveau_instmem_r32(drm_nouveau_private_t *dev_priv,
-                            struct mem_block *mem, int index)
-{
-       uint32_t ofs = (uint32_t)mem->start + (index<<2);
-
-       if (dev_priv->ramin) {
-#if defined(__powerpc__)
-               return in_be32((void __iomem *)(dev_priv->ramin)->handle + ofs);
-#else
-               return DRM_READ32(dev_priv->ramin, ofs);
-#endif
-       } else {
-               return NV_READ(NV_RAMIN+ofs);
-       }
-}
-
-void nouveau_instmem_w32(drm_nouveau_private_t *dev_priv,
-                        struct mem_block *mem, int index, uint32_t val)
-{
-       uint32_t ofs = (uint32_t)mem->start + (index<<2);
-
-       if (dev_priv->ramin) {
-#if defined(__powerpc__)
-               out_be32((void __iomem *)(dev_priv->ramin)->handle + ofs, val);
-#else
-               DRM_WRITE32(dev_priv->ramin, ofs, val);
-#endif
-       } else {
-               NV_WRITE(NV_RAMIN+ofs, val);
-       }
+       nouveau_mem_free_block(block);
 }
 
 /*
  * Ioctls
  */
 
-int nouveau_ioctl_mem_alloc(DRM_IOCTL_ARGS)
+int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       drm_nouveau_mem_alloc_t alloc;
+       struct drm_nouveau_mem_alloc *alloc = data;
        struct mem_block *block;
 
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
-       }
-
-       DRM_COPY_FROM_USER_IOCTL(alloc, (drm_nouveau_mem_alloc_t __user *) data,
-                                sizeof(alloc));
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 
-       block=nouveau_mem_alloc(dev, alloc.alignment, alloc.size, alloc.flags, filp);
+       block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size,
+                               alloc->flags, file_priv);
        if (!block)
-               return DRM_ERR(ENOMEM);
-       alloc.region_offset=block->start;
-       alloc.flags=block->flags;
-
-       DRM_COPY_TO_USER_IOCTL((drm_nouveau_mem_alloc_t __user *) data, alloc, sizeof(alloc));
+               return -ENOMEM;
+       alloc->map_handle=block->map_handle;
+       alloc->offset=block->start;
+       alloc->flags=block->flags;
 
        return 0;
 }
 
-int nouveau_ioctl_mem_free(DRM_IOCTL_ARGS)
+int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       drm_nouveau_mem_free_t memfree;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct drm_nouveau_mem_free *memfree = data;
        struct mem_block *block;
 
-       DRM_COPY_FROM_USER_IOCTL(memfree, (drm_nouveau_mem_free_t __user *) data,
-                                sizeof(memfree));
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 
        block=NULL;
-       if (memfree.flags&NOUVEAU_MEM_FB)
-               block = find_block(dev_priv->fb_heap, memfree.region_offset);
-       else if (memfree.flags&NOUVEAU_MEM_AGP)
-               block = find_block(dev_priv->agp_heap, memfree.region_offset);
+       if (memfree->flags & NOUVEAU_MEM_FB)
+               block = find_block(dev_priv->fb_heap, memfree->offset);
+       else if (memfree->flags & NOUVEAU_MEM_AGP)
+               block = find_block(dev_priv->agp_heap, memfree->offset);
+       else if (memfree->flags & NOUVEAU_MEM_PCI)
+               block = find_block(dev_priv->pci_heap, memfree->offset);
        if (!block)
-               return DRM_ERR(EFAULT);
-       if (block->filp != filp)
-               return DRM_ERR(EPERM);
+               return -EFAULT;
+       if (block->file_priv != file_priv)
+               return -EPERM;
 
        nouveau_mem_free(dev, block);
        return 0;
diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c
new file mode 100644 (file)
index 0000000..31e2b24
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+int
+nouveau_notifier_init_channel(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       int flags, ret;
+
+       flags = (NOUVEAU_MEM_PCI | NOUVEAU_MEM_MAPPED |
+                NOUVEAU_MEM_FB_ACCEPTABLE);
+
+       chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,
+                                                (struct drm_file *)-2);
+       if (!chan->notifier_block)
+               return -ENOMEM;
+       DRM_DEBUG("Allocated notifier block in 0x%08x\n",
+                 chan->notifier_block->flags);
+
+       ret = nouveau_mem_init_heap(&chan->notifier_heap,
+                                   0, chan->notifier_block->size);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+void
+nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+
+       if (chan->notifier_block) {
+               nouveau_mem_free(dev, chan->notifier_block);
+               chan->notifier_block = NULL;
+       }
+
+       nouveau_mem_takedown(&chan->notifier_heap);
+}
+
+static void
+nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
+                            struct nouveau_gpuobj *gpuobj)
+{
+       DRM_DEBUG("\n");
+
+       if (gpuobj->priv)
+               nouveau_mem_free_block(gpuobj->priv);
+}
+
+int
+nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
+                      int count, uint32_t *b_offset)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *nobj = NULL;
+       struct mem_block *mem;
+       uint32_t offset;
+       int target, ret;
+
+       if (!chan->notifier_heap) {
+               DRM_ERROR("Channel %d doesn't have a notifier heap!\n",
+                         chan->id);
+               return -EINVAL;
+       }
+
+       mem = nouveau_mem_alloc_block(chan->notifier_heap, count*32, 0,
+                                     (struct drm_file *)-2);
+       if (!mem) {
+               DRM_ERROR("Channel %d notifier block full\n", chan->id);
+               return -ENOMEM;
+       }
+       mem->flags = NOUVEAU_MEM_NOTIFIER;
+
+       offset = chan->notifier_block->start;
+       if (chan->notifier_block->flags & NOUVEAU_MEM_FB) {
+               target = NV_DMA_TARGET_VIDMEM;
+       } else
+       if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) {
+               if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA &&
+                   dev_priv->card_type < NV_50) {
+                       ret = nouveau_sgdma_get_page(dev, offset, &offset);
+                       if (ret)
+                               return ret;
+                       target = NV_DMA_TARGET_PCI;
+               } else {
+                       target = NV_DMA_TARGET_AGP;
+               }
+       } else 
+       if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) {
+               target = NV_DMA_TARGET_PCI_NONLINEAR;
+       } else {
+               DRM_ERROR("Bad DMA target, flags 0x%08x!\n",
+                         chan->notifier_block->flags);
+               return -EINVAL;
+       }
+       offset += mem->start;
+
+       if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                         offset, mem->size,
+                                         NV_DMA_ACCESS_RW, target, &nobj))) {
+               nouveau_mem_free_block(mem);
+               DRM_ERROR("Error creating notifier ctxdma: %d\n", ret);
+               return ret;
+       }
+       nobj->dtor   = nouveau_notifier_gpuobj_dtor;
+       nobj->priv   = mem;
+
+       if ((ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL))) {
+               nouveau_gpuobj_del(dev, &nobj);
+               nouveau_mem_free_block(mem);
+               DRM_ERROR("Error referencing notifier ctxdma: %d\n", ret);
+               return ret;
+       }
+
+       *b_offset = mem->start;
+       return 0;
+}
+
+int
+nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv)
+{
+       struct drm_nouveau_notifierobj_alloc *na = data;
+       struct nouveau_channel *chan;
+       int ret;
+
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+       NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
+
+       ret = nouveau_notifier_alloc(chan, na->handle, na->count, &na->offset);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
index e36568c..fbce770 100644 (file)
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
-/* TODO
- *  - Check object class, deny unsafe objects (add card-specific versioning?)
- *  - Get rid of DMA object creation, this should be wrapped by MM routines.
- */
-
-/* Translate a RAMIN offset into a value the card understands, will be useful
- * in the future when we can access more instance ram which isn't mapped into
- * the PRAMIN aperture
- */
-uint32_t
-nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem)
-{
-       uint32_t inst = (uint32_t)mem->start >> 4;
-       DRM_DEBUG("****** on-chip instance for 0x%016llx = 0x%08x\n",
-                       mem->start, inst);
-       return inst;
-}
-
-static void
-nouveau_object_link(drm_device_t *dev, struct nouveau_object *obj)
-{
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel];
-
-       if (!chan->objs) {
-               chan->objs = obj;
-               return;
-       }
-
-       obj->prev = NULL;
-       obj->next = chan->objs;
-
-       chan->objs->prev = obj;
-       chan->objs = obj;
-}
-
-static void
-nouveau_object_unlink(drm_device_t *dev, struct nouveau_object *obj)
-{
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel];
-
-       if (obj->prev == NULL) {        
-               if (obj->next)
-                       obj->next->prev = NULL;
-               chan->objs = obj->next;
-       } else if (obj->next == NULL) {
-               if (obj->prev)
-                       obj->prev->next = NULL;
-       } else {
-               obj->prev->next = obj->next;
-               obj->next->prev = obj->prev;
-       }
-}
-
-static struct nouveau_object *
-nouveau_object_handle_find(drm_device_t *dev, int channel, uint32_t handle)
-{
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       struct nouveau_object *obj = chan->objs;
-
-       DRM_DEBUG("Looking for handle 0x%08x\n", handle);
-       while (obj) {
-               if (obj->handle == handle)
-                       return obj;
-               obj = obj->next;
-       }
-
-       DRM_DEBUG("...couldn't find handle\n");
-       return NULL;
-}
-
 /* NVidia uses context objects to drive drawing operations.
 
    Context objects can be selected into 8 subchannels in the FIFO,
@@ -139,130 +66,550 @@ nouveau_object_handle_find(drm_device_t *dev, int channel, uint32_t handle)
    is given as:
 */
 static uint32_t
-nouveau_ht_handle_hash(drm_device_t *dev, int channel, uint32_t handle)
+nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
+       struct drm_nouveau_private *dev_priv=dev->dev_private;
        uint32_t hash = 0;
        int i;
 
+       DRM_DEBUG("ch%d handle=0x%08x\n", channel, handle);
+
        for (i=32;i>0;i-=dev_priv->ramht_bits) {
                hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1));
                handle >>= dev_priv->ramht_bits;
        }
-       hash ^= channel << (dev_priv->ramht_bits - 4);
-       return hash << 3;
+       if (dev_priv->card_type < NV_50)
+               hash ^= channel << (dev_priv->ramht_bits - 4);
+       hash <<= 3;
+
+       DRM_DEBUG("hash=0x%08x\n", hash);
+       return hash;
 }
 
 static int
-nouveau_ht_object_insert(drm_device_t* dev, int channel, uint32_t handle,
-                        struct nouveau_object *obj)
+nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht,
+                         uint32_t offset)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       int ht_base = NV_RAMIN + dev_priv->ramht_offset;
-       int ht_end  = ht_base + dev_priv->ramht_size;
-       int o_ofs, ofs;
-
-       obj->handle = handle;
-       o_ofs = ofs = nouveau_ht_handle_hash(dev, channel, obj->handle);
-
-       while (NV_READ(ht_base + ofs) || NV_READ(ht_base + ofs + 4)) {
-               ofs += 8;
-               if (ofs == dev_priv->ramht_size) ofs = 0;
-               if (ofs == o_ofs) {
-                       DRM_ERROR("no free hash table entries\n");
-                       return 1;
+       struct drm_nouveau_private *dev_priv=dev->dev_private;
+       uint32_t ctx = INSTANCE_RD(ramht, (offset + 4)/4);
+
+       if (dev_priv->card_type < NV_40)
+               return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0);
+       return (ctx != 0);
+}
+
+static int
+nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
+{
+       struct drm_nouveau_private *dev_priv=dev->dev_private;
+       struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
+       struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
+       struct nouveau_gpuobj *gpuobj = ref->gpuobj;
+       uint32_t ctx, co, ho;
+
+       if (!ramht) {
+               DRM_ERROR("No hash table!\n");
+               return -EINVAL;
+       }
+
+       if (dev_priv->card_type < NV_40) {
+               ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) |
+                     (ref->channel   << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+                     (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT);
+       } else
+       if (dev_priv->card_type < NV_50) {
+               ctx = (ref->instance >> 4) |
+                     (ref->channel   << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+                     (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
+       } else {
+               ctx = (ref->instance  >> 4) |
+                     (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
+       }
+
+       co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle);
+       do {
+               if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
+                       DRM_DEBUG("insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
+                                 ref->channel, co, ref->handle, ctx);
+                       INSTANCE_WR(ramht, (co + 0)/4, ref->handle);
+                       INSTANCE_WR(ramht, (co + 4)/4, ctx);
+
+                       list_add_tail(&ref->list, &chan->ramht_refs);
+                       return 0;
+               }
+               DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n",
+                         ref->channel, co, INSTANCE_RD(ramht, co/4));
+
+               co += 8;
+               if (co >= dev_priv->ramht_size) {
+                       DRM_INFO("no space left after collision\n");
+                       co = 0;
+                       /* exit as it seems to cause crash with nouveau_demo and
+                        * 0xdead0001 object */
+                       break;
+               }
+       } while (co != ho);
+
+       DRM_ERROR("RAMHT space exhausted. ch=%d\n", ref->channel);
+       return -ENOMEM;
+}
+
+static void
+nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
+       struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
+       uint32_t co, ho;
+
+       if (!ramht) {
+               DRM_ERROR("No hash table!\n");
+               return;
+       }
+
+       co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle);
+       do {
+               if (nouveau_ramht_entry_valid(dev, ramht, co) &&
+                   (ref->handle == INSTANCE_RD(ramht, (co/4)))) {
+                       DRM_DEBUG("remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
+                                 ref->channel, co, ref->handle,
+                                 INSTANCE_RD(ramht, (co + 4)));
+                       INSTANCE_WR(ramht, (co + 0)/4, 0x00000000);
+                       INSTANCE_WR(ramht, (co + 4)/4, 0x00000000);
+
+                       list_del(&ref->list);
+                       return;
                }
+
+               co += 8;
+               if (co >= dev_priv->ramht_size)
+                       co = 0;
+       } while (co != ho);
+
+       DRM_ERROR("RAMHT entry not found. ch=%d, handle=0x%08x\n",
+                 ref->channel, ref->handle);
+}
+
+int
+nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
+                  int size, int align, uint32_t flags,
+                  struct nouveau_gpuobj **gpuobj_ret)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->Engine;
+       struct nouveau_gpuobj *gpuobj;
+       struct mem_block *pramin = NULL;
+       int ret;
+
+       DRM_DEBUG("ch%d size=%d align=%d flags=0x%08x\n",
+                 chan ? chan->id : -1, size, align, flags);
+
+       if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL)
+               return -EINVAL;
+
+       gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER);
+       if (!gpuobj)
+               return -ENOMEM;
+       DRM_DEBUG("gpuobj %p\n", gpuobj);
+       gpuobj->flags = flags;
+       gpuobj->im_channel = chan ? chan->id : -1;
+
+       list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
+
+       /* Choose between global instmem heap, and per-channel private
+        * instmem heap.  On <NV50 allow requests for private instmem
+        * to be satisfied from global heap if no per-channel area
+        * available.
+        */
+       if (chan) {
+               if (chan->ramin_heap) {
+                       DRM_DEBUG("private heap\n");
+                       pramin = chan->ramin_heap;
+               } else
+               if (dev_priv->card_type < NV_50) {
+                       DRM_DEBUG("global heap fallback\n");
+                       pramin = dev_priv->ramin_heap;
+               }
+       } else {
+               DRM_DEBUG("global heap\n");
+               pramin = dev_priv->ramin_heap;
        }
-       ofs += ht_base;
 
-       DRM_DEBUG("Channel %d - Handle 0x%08x at 0x%08x\n",
-               channel, obj->handle, ofs);
+       if (!pramin) {
+               DRM_ERROR("No PRAMIN heap!\n");
+               return -EINVAL;
+       }
+
+       if (!chan && (ret = engine->instmem.populate(dev, gpuobj, &size))) {
+               nouveau_gpuobj_del(dev, &gpuobj);
+               return ret;
+       }
+
+       /* Allocate a chunk of the PRAMIN aperture */
+       gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,
+                                                   drm_order(align),
+                                                   (struct drm_file *)-2);
+       if (!gpuobj->im_pramin) {
+               nouveau_gpuobj_del(dev, &gpuobj);
+               return -ENOMEM;
+       }
+       gpuobj->im_pramin->flags = NOUVEAU_MEM_INSTANCE;
+
+       if (!chan && (ret = engine->instmem.bind(dev, gpuobj))) {
+               nouveau_gpuobj_del(dev, &gpuobj);
+               return ret;
+       }
+
+       if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
+               int i;
+
+               for (i = 0; i < gpuobj->im_pramin->size; i += 4)
+                       INSTANCE_WR(gpuobj, i/4, 0);
+       }
+
+       *gpuobj_ret = gpuobj;
+       return 0;
+}
+
+int
+nouveau_gpuobj_early_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       INIT_LIST_HEAD(&dev_priv->gpuobj_list);
 
-       NV_WRITE(NV_RAMHT_HANDLE_OFFSET + ofs, obj->handle);
-       if (dev_priv->card_type >= NV_40)
-               NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
-                       (channel     << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
-                       (obj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT) |
-                       nouveau_chip_instance_get(dev, obj->instance)
-                       );          
-       else
-               NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
-                       NV_RAMHT_CONTEXT_VALID |
-                       (channel     << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
-                       (obj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT) |
-                       nouveau_chip_instance_get(dev, obj->instance)
-                       );
-
-       obj->ht_loc = ofs;
        return 0;
 }
 
-static void nouveau_hash_table_remove(drm_device_t* dev,
-                                     struct nouveau_object *obj)
+int
+nouveau_gpuobj_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       DRM_DEBUG("\n");
+
+       if (dev_priv->card_type < NV_50) {
+               if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset,
+                                                  ~0, dev_priv->ramht_size,
+                                                  NVOBJ_FLAG_ZERO_ALLOC |
+                                                  NVOBJ_FLAG_ALLOW_NO_REFS,
+                                                  &dev_priv->ramht, NULL)))
+                       return ret;
+       }
+
+       return 0;
+}
+
+void
+nouveau_gpuobj_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       nouveau_gpuobj_del(dev, &dev_priv->ramht);
+}
+
+void
+nouveau_gpuobj_late_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *gpuobj = NULL;
+       struct list_head *entry, *tmp;
+
+       DRM_DEBUG("\n");
+
+       list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
+               gpuobj = list_entry(entry, struct nouveau_gpuobj, list);
+
+               DRM_ERROR("gpuobj %p still exists at takedown, refs=%d\n",
+                         gpuobj, gpuobj->refcount);
+               gpuobj->refcount = 0;
+               nouveau_gpuobj_del(dev, &gpuobj);
+       }
+}
+
+int
+nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->Engine;
+       struct nouveau_gpuobj *gpuobj;
+
+       DRM_DEBUG("gpuobj %p\n", pgpuobj ? *pgpuobj : NULL);
 
-       DRM_DEBUG("Remove handle 0x%08x at 0x%08x from HT\n",
-                       obj->handle, obj->ht_loc);
-       if (obj->ht_loc) {
-               DRM_DEBUG("... HT entry was: 0x%08x/0x%08x\n",
-                               NV_READ(obj->ht_loc), NV_READ(obj->ht_loc+4));
-               NV_WRITE(obj->ht_loc  , 0x00000000);
-               NV_WRITE(obj->ht_loc+4, 0x00000000);
+       if (!dev_priv || !pgpuobj || !(*pgpuobj))
+               return -EINVAL;
+       gpuobj = *pgpuobj;
+
+       if (gpuobj->refcount != 0) {
+               DRM_ERROR("gpuobj refcount is %d\n", gpuobj->refcount);
+               return -EINVAL;
        }
+
+       if (gpuobj->dtor)
+               gpuobj->dtor(dev, gpuobj);
+
+       if (gpuobj->im_backing) {
+               if (gpuobj->flags & NVOBJ_FLAG_FAKE)
+                       drm_free(gpuobj->im_backing,
+                                sizeof(*gpuobj->im_backing), DRM_MEM_DRIVER);
+               else
+                       engine->instmem.clear(dev, gpuobj);
+       }
+
+       if (gpuobj->im_pramin) {
+               if (gpuobj->flags & NVOBJ_FLAG_FAKE)
+                       drm_free(gpuobj->im_pramin, sizeof(*gpuobj->im_pramin),
+                                DRM_MEM_DRIVER);
+               else
+                       nouveau_mem_free_block(gpuobj->im_pramin);
+       }
+
+       list_del(&gpuobj->list);
+
+       *pgpuobj = NULL;
+       drm_free(gpuobj, sizeof(*gpuobj), DRM_MEM_DRIVER);
+       return 0;
 }
 
-static struct nouveau_object *
-nouveau_object_instance_alloc(drm_device_t* dev, int channel)
+static int
+nouveau_gpuobj_instance_get(struct drm_device *dev,
+                           struct nouveau_channel *chan,
+                           struct nouveau_gpuobj *gpuobj, uint32_t *inst)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       struct nouveau_object       *obj;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *cpramin;
+
+       /* <NV50 use PRAMIN address everywhere */
+       if (dev_priv->card_type < NV_50) {
+               *inst = gpuobj->im_pramin->start;
+               return 0;
+       }
 
-       /* Create object struct */
-       obj = drm_calloc(1, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
-       if (!obj) {
-               DRM_ERROR("couldn't alloc memory for object\n");
-               return NULL;
+       if (chan && gpuobj->im_channel != chan->id) {
+               DRM_ERROR("Channel mismatch: obj %d, ref %d\n",
+                         gpuobj->im_channel, chan->id);
+               return -EINVAL;
        }
 
-       /* Allocate instance memory */
-       obj->instance  = nouveau_instmem_alloc(dev,
-                       (dev_priv->card_type >= NV_40 ? 32 : 16), 4);
-       if (!obj->instance) {
-               DRM_ERROR("couldn't alloc RAMIN for object\n");
-               drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
-               return NULL;
+       /* NV50 channel-local instance */
+       if (chan > 0) {
+               cpramin = chan->ramin->gpuobj;
+               *inst = gpuobj->im_pramin->start - cpramin->im_pramin->start;
+               return 0;
        }
 
-       /* Bind object to channel */
-       obj->channel = channel;
-       obj->handle  = ~0;
-       nouveau_object_link(dev, obj);
+       /* NV50 global (VRAM) instance */
+       if (gpuobj->im_channel < 0) {
+               /* ...from global heap */
+               if (!gpuobj->im_backing) {
+                       DRM_ERROR("AII, no VRAM backing gpuobj\n");
+                       return -EINVAL;
+               }
+               *inst = gpuobj->im_backing->start;
+               return 0;
+       } else {
+               /* ...from local heap */
+               cpramin = dev_priv->fifos[gpuobj->im_channel]->ramin->gpuobj;
+               *inst = cpramin->im_backing->start +
+                       (gpuobj->im_pramin->start - cpramin->im_pramin->start);
+               return 0;
+       }
 
-       return obj;
+       return -EINVAL;
 }
 
-static void
-nouveau_object_instance_free(drm_device_t *dev, struct nouveau_object *obj)
+int
+nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan,
+                      uint32_t handle, struct nouveau_gpuobj *gpuobj,
+                      struct nouveau_gpuobj_ref **ref_ret)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj_ref *ref;
+       uint32_t instance;
+       int ret;
+
+       DRM_DEBUG("ch%d h=0x%08x gpuobj=%p\n",
+                 chan ? chan->id : -1, handle, gpuobj);
+
+       if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL))
+               return -EINVAL;
+
+       if (!chan && !ref_ret)
+               return -EINVAL;
+
+       ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance);
+       if (ret)
+               return ret;
+
+       ref = drm_calloc(1, sizeof(*ref), DRM_MEM_DRIVER);
+       if (!ref)
+               return -ENOMEM;
+       ref->gpuobj   = gpuobj;
+       ref->channel  = chan ? chan->id : -1;
+       ref->instance = instance;
+
+       if (!ref_ret) {
+               ref->handle = handle;
+
+               ret = nouveau_ramht_insert(dev, ref);
+               if (ret) {
+                       drm_free(ref, sizeof(*ref), DRM_MEM_DRIVER);
+                       return ret;
+               }
+       } else {
+               ref->handle = ~0;
+               *ref_ret = ref;
+       }
+
+       ref->gpuobj->refcount++;
+       return 0;
+}
+
+int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **pref)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
+       struct nouveau_gpuobj_ref *ref;
+
+       DRM_DEBUG("ref %p\n", pref ? *pref : NULL);
+
+       if (!dev || !pref || *pref == NULL)
+               return -EINVAL;
+       ref = *pref;
+
+       if (ref->handle != ~0)
+               nouveau_ramht_remove(dev, ref);
+
+       if (ref->gpuobj) {
+               ref->gpuobj->refcount--;
+
+               if (ref->gpuobj->refcount == 0) {
+                       if (!(ref->gpuobj->flags & NVOBJ_FLAG_ALLOW_NO_REFS))
+                               nouveau_gpuobj_del(dev, &ref->gpuobj);
+               }
+       }
+
+       *pref = NULL;
+       drm_free(ref, sizeof(ref), DRM_MEM_DRIVER);
+       return 0;
+}
+
+int
+nouveau_gpuobj_new_ref(struct drm_device *dev,
+                      struct nouveau_channel *oc, struct nouveau_channel *rc,
+                      uint32_t handle, int size, int align, uint32_t flags,
+                      struct nouveau_gpuobj_ref **ref)
+{
+       struct nouveau_gpuobj *gpuobj = NULL;
+       int ret;
+
+       if ((ret = nouveau_gpuobj_new(dev, oc, size, align, flags, &gpuobj)))
+               return ret;
+
+       if ((ret = nouveau_gpuobj_ref_add(dev, rc, handle, gpuobj, ref))) {
+               nouveau_gpuobj_del(dev, &gpuobj);
+               return ret;
+       }
+
+       return 0;
+}
+
+int
+nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle,
+                       struct nouveau_gpuobj_ref **ref_ret)
+{
+       struct nouveau_gpuobj_ref *ref;
+       struct list_head *entry, *tmp;
+
+       list_for_each_safe(entry, tmp, &chan->ramht_refs) {             
+               ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
+
+               if (ref->handle == handle) {
+                       if (ref_ret)
+                               *ref_ret = ref;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+int
+nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
+                       uint32_t b_offset, uint32_t size,
+                       uint32_t flags, struct nouveau_gpuobj **pgpuobj,
+                       struct nouveau_gpuobj_ref **pref)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *gpuobj = NULL;
        int i;
 
-       /* Unbind object from channel */
-       nouveau_object_unlink(dev, obj);
+       DRM_DEBUG("p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n",
+                 p_offset, b_offset, size, flags);
+
+       gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER);
+       if (!gpuobj)
+               return -ENOMEM;
+       DRM_DEBUG("gpuobj %p\n", gpuobj);
+       gpuobj->im_channel = -1;
+       gpuobj->flags      = flags | NVOBJ_FLAG_FAKE;
+
+       list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
 
-       /* Clean RAMIN entry */
-       DRM_DEBUG("Instance entry for 0x%08x"
-               "(engine %d, class 0x%x) before destroy:\n",
-               obj->handle, obj->engine, obj->class);
-       for (i=0; i<(obj->instance->size/4); i++) {
-               DRM_DEBUG("  +0x%02x: 0x%08x\n", (i*4),
-                       INSTANCE_RD(obj->instance, i));
-               INSTANCE_WR(obj->instance, i, 0x00000000);
+       if (p_offset != ~0) {
+               gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block),
+                                              DRM_MEM_DRIVER);
+               if (!gpuobj->im_pramin) {
+                       nouveau_gpuobj_del(dev, &gpuobj);
+                       return -ENOMEM;
+               }
+               gpuobj->im_pramin->start = p_offset;
+               gpuobj->im_pramin->size  = size;
+       }
+
+       if (b_offset != ~0) {
+               gpuobj->im_backing = drm_calloc(1, sizeof(struct mem_block),
+                                              DRM_MEM_DRIVER);
+               if (!gpuobj->im_backing) {
+                       nouveau_gpuobj_del(dev, &gpuobj);
+                       return -ENOMEM;
+               }
+               gpuobj->im_backing->start = b_offset;
+               gpuobj->im_backing->size  = size;
        }
 
-       /* Free RAMIN */
-       nouveau_instmem_free(dev, obj->instance);
+       if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
+               for (i = 0; i < gpuobj->im_pramin->size; i += 4)
+                       INSTANCE_WR(gpuobj, i/4, 0);
+       }
+
+       if (pref) {
+               if ((i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref))) {
+                       nouveau_gpuobj_del(dev, &gpuobj);
+                       return i;
+               }
+       }
+
+       if (pgpuobj)
+               *pgpuobj = gpuobj;
+       return 0;
+}
+
+
+static int
+nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       /*XXX: dodgy hack for now */
+       if (dev_priv->card_type >= NV_50)
+               return 24;
+       if (dev_priv->card_type >= NV_40)
+               return 32;
+       return 16;
 }
 
 /*
@@ -278,76 +625,191 @@ nouveau_object_instance_free(drm_device_t *dev, struct nouveau_object *obj)
    17:16 target: 0 NV memory, 1 NV memory tiled, 2 PCI, 3 AGP
    31:20 dma adjust (bits 0-11 of the address)
    entry[1]
-   dma limit
-   entry[2]
+   dma limit (size of transfer)
+   entry[X]
    1     0 readonly, 1 readwrite
-   31:12 dma frame address (bits 12-31 of the address)
+   31:12 dma frame address of the page (bits 12-31 of the address)
+   entry[N]
+   page table terminator, same value as the first pte, as does nvidia
+   rivatv uses 0xffffffff
 
-   Non linear page tables seem to need a list of frame addresses afterwards,
-   the rivatv project has some info on this.   
+   Non linear page tables need a list of frame addresses afterwards,
+   the rivatv project has some info on this.
 
    The method below creates a DMA object in instance RAM and returns a handle
    to it that can be used to set up context objects.
 */
-
-struct nouveau_object *
-nouveau_object_dma_create(drm_device_t* dev, int channel, int class,
-                         uint32_t offset, uint32_t size,
-                         int access, int target)
+int
+nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
+                      uint64_t offset, uint64_t size, int access,
+                      int target, struct nouveau_gpuobj **gpuobj)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       struct   nouveau_object *obj;
-       uint32_t frame, adjust;
-       uint32_t pte_flags = 0;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+       uint32_t is_scatter_gather = 0;
+       
+       /* Total number of pages covered by the request.
+        */
+       const unsigned int page_count = (size + PAGE_SIZE - 1) / PAGE_SIZE;
 
-       DRM_DEBUG("offset:0x%08x, size:0x%08x, target:%d, access:%d\n",
-                       offset, size, target, access);
+
+       DRM_DEBUG("ch%d class=0x%04x offset=0x%llx size=0x%llx\n",
+                 chan->id, class, offset, size);
+       DRM_DEBUG("access=%d target=%d\n", access, target);
 
        switch (target) {
-       case NV_DMA_TARGET_AGP:
-               offset += dev_priv->agp_phys;
-               break;
-       default:
-               break;
+        case NV_DMA_TARGET_AGP:
+                 offset += dev_priv->gart_info.aper_base;
+                 break;
+        case NV_DMA_TARGET_PCI_NONLINEAR:
+                /*assume the "offset" is a virtual memory address*/
+                is_scatter_gather = 1;
+                /*put back the right value*/
+                target = NV_DMA_TARGET_PCI;
+                break;
+        default:
+                break;
+        }
+       
+       ret = nouveau_gpuobj_new(dev, chan,
+                                is_scatter_gather ? ((page_count << 2) + 12) : nouveau_gpuobj_class_instmem_size(dev, class),
+                                16,
+                                NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
+                                gpuobj);
+       if (ret) {
+               DRM_ERROR("Error creating gpuobj: %d\n", ret);
+               return ret;
        }
 
-       switch (access) {
-       case NV_DMA_ACCESS_RO:
-               break;
-       case NV_DMA_ACCESS_WO:
-       case NV_DMA_ACCESS_RW:
-               pte_flags  |= (1 << 1);
-               break;
-       default:
-               DRM_ERROR("invalid access mode=%d\n", access);
-               return NULL;
-       }
+       if (dev_priv->card_type < NV_50) {
+               uint32_t frame, adjust, pte_flags = 0;
+               adjust = offset &  0x00000fff;
+               if (access != NV_DMA_ACCESS_RO)
+                               pte_flags |= (1<<1);
+               
+               if ( ! is_scatter_gather ) 
+                       {
+                       frame  = offset & ~0x00000fff;
+                       
+                       INSTANCE_WR(*gpuobj, 0, ((1<<12) | (1<<13) |
+                                       (adjust << 20) |
+                                        (access << 14) |
+                                        (target << 16) |
+                                         class));
+                       INSTANCE_WR(*gpuobj, 1, size - 1);
+                       INSTANCE_WR(*gpuobj, 2, frame | pte_flags);
+                       INSTANCE_WR(*gpuobj, 3, frame | pte_flags);
+                       }
+               else 
+                       {
+                       /* Intial page entry in the scatter-gather area that
+                        * corresponds to the base offset
+                        */
+                       unsigned int idx = offset / PAGE_SIZE;
+
+                       uint32_t instance_offset;
+                       unsigned int i;
+
+                       if ((idx + page_count) > dev->sg->pages) {
+                               DRM_ERROR("Requested page range exceedes "
+                                         "allocated scatter-gather range!");
+                               return -E2BIG;
+                       }
+
+                       DRM_DEBUG("Creating PCI DMA object using virtual zone starting at %#llx, size %d\n", offset, (uint32_t)size);
+                       INSTANCE_WR(*gpuobj, 0, ((1<<12) | (0<<13) |
+                                (adjust << 20) |
+                                (access << 14) |
+                                (target << 16) |
+                                class));
+                       INSTANCE_WR(*gpuobj, 1, (uint32_t) size-1);
+
+
+                       /*write starting at the third dword*/
+                       instance_offset = 2;
+                       /*for each PAGE, get its bus address, fill in the page table entry, and advance*/
+                       for (i = 0; i < page_count; i++) {
+                               if (dev->sg->busaddr[idx] == 0) {
+                                       dev->sg->busaddr[idx] =
+                                               pci_map_page(dev->pdev,
+                                                            dev->sg->pagelist[idx],
+                                                            0,
+                                                            PAGE_SIZE,
+                                                            DMA_BIDIRECTIONAL);
+
+                                       if (dma_mapping_error(dev->sg->busaddr[idx])) {
+                                               return -ENOMEM;
+                                       }
+                               }
+
+                               frame = (uint32_t) dev->sg->busaddr[idx];
+                               INSTANCE_WR(*gpuobj, instance_offset, 
+                                           frame | pte_flags);
+                               idx++;
+                               instance_offset ++;
+                       }
+                       }
+       } else {
+               uint32_t flags0, flags5;
 
-       frame  = offset & ~0x00000FFF;
-       adjust = offset &  0x00000FFF;
+               if (target == NV_DMA_TARGET_VIDMEM) {
+                       flags0 = 0x00190000;
+                       flags5 = 0x00010000;
+               } else {
+                       flags0 = 0x7fc00000;
+                       flags5 = 0x00080000;
+               }
 
-       obj = nouveau_object_instance_alloc(dev, channel);
-       if (!obj) {
-               DRM_ERROR("couldn't allocate DMA object\n");
-               return obj;
+               INSTANCE_WR(*gpuobj, 0, flags0 | class);
+               INSTANCE_WR(*gpuobj, 1, offset + size - 1);
+               INSTANCE_WR(*gpuobj, 2, offset);
+               INSTANCE_WR(*gpuobj, 5, flags5);
        }
 
-       obj->engine = 0;
-       obj->class  = class;
+       (*gpuobj)->engine = NVOBJ_ENGINE_SW;
+       (*gpuobj)->class  = class;
+       return 0;
+}
 
-       INSTANCE_WR(obj->instance, 0, ((1<<12) | (1<<13) |
-                               (adjust << 20) |
-                               (access << 14) |
-                               (target << 16) |
-                               class));
-       INSTANCE_WR(obj->instance, 1, size-1);
-       INSTANCE_WR(obj->instance, 2, frame | pte_flags);
-       INSTANCE_WR(obj->instance, 3, frame | pte_flags);
+int
+nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan,
+                           uint64_t offset, uint64_t size, int access,
+                           struct nouveau_gpuobj **gpuobj,
+                           uint32_t *o_ret)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       if (dev_priv->gart_info.type == NOUVEAU_GART_AGP ||
+           (dev_priv->card_type >= NV_50 &&
+            dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) {
+               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                            offset, size, access,
+                                            NV_DMA_TARGET_AGP, gpuobj);
+               if (o_ret)
+                       *o_ret = 0;
+       } else
+       if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) {
+               *gpuobj = dev_priv->gart_info.sg_ctxdma;
+               if (offset & ~0xffffffffULL) {
+                       DRM_ERROR("obj offset exceeds 32-bits\n");
+                       return -EINVAL;
+               }
+               if (o_ret)
+                       *o_ret = (uint32_t)offset;
+               ret = (*gpuobj != NULL) ? 0 : -EINVAL;
+       } else {
+               DRM_ERROR("Invalid GART type %d\n", dev_priv->gart_info.type);
+               return -EINVAL;
+       }
 
-       return obj;
+       return ret;
 }
 
-
 /* Context objects in the instance RAM have the following structure.
  * On NV40 they are 32 byte long, on NV30 and smaller 16 bytes.
 
@@ -399,205 +861,287 @@ nouveau_object_dma_create(drm_device_t* dev, int channel, int class,
    entry[5]:
    set to 0?
 */
-struct nouveau_object *
-nouveau_object_gr_create(drm_device_t* dev, int channel, int class)
+int
+nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
+                     struct nouveau_gpuobj **gpuobj)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       struct   nouveau_object *obj;
-
-       DRM_DEBUG("class=%x\n", class);
-
-       obj = nouveau_object_instance_alloc(dev, channel);
-       if (!obj) {
-               DRM_ERROR("couldn't allocate context object\n");
-               return obj;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       DRM_DEBUG("ch%d class=0x%04x\n", chan->id, class);
+
+       ret = nouveau_gpuobj_new(dev, chan,
+                                nouveau_gpuobj_class_instmem_size(dev, class),
+                                16,
+                                NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
+                                gpuobj);
+       if (ret) {
+               DRM_ERROR("Error creating gpuobj: %d\n", ret);
+               return ret;
        }
 
-       obj->engine = 1;
-       obj->class  = class;
-
+       if (dev_priv->card_type >= NV_50) {
+               INSTANCE_WR(*gpuobj, 0, class);
+               INSTANCE_WR(*gpuobj, 5, 0x00010000);
+       } else {
        switch (class) {
        case NV_CLASS_NULL:
-               INSTANCE_WR(obj->instance, 0, 0x00001030);
-               INSTANCE_WR(obj->instance, 1, 0xFFFFFFFF);
-               INSTANCE_WR(obj->instance, 2, 0x00000000);
-               INSTANCE_WR(obj->instance, 2, 0x00000000);
+               INSTANCE_WR(*gpuobj, 0, 0x00001030);
+               INSTANCE_WR(*gpuobj, 1, 0xFFFFFFFF);
                break;
        default:
                if (dev_priv->card_type >= NV_40) {
-                       INSTANCE_WR(obj->instance, 0,  obj->class);
-                       INSTANCE_WR(obj->instance, 1, 0x00000000);
+                       INSTANCE_WR(*gpuobj, 0, class);
 #ifdef __BIG_ENDIAN
-                       INSTANCE_WR(obj->instance, 2, 0x01000000);
-#else
-                       INSTANCE_WR(obj->instance, 2, 0x00000000);
+                       INSTANCE_WR(*gpuobj, 2, 0x01000000);
 #endif
-                       INSTANCE_WR(obj->instance, 3, 0x00000000);
-                       INSTANCE_WR(obj->instance, 4, 0x00000000);
-                       INSTANCE_WR(obj->instance, 5, 0x00000000);
-                       INSTANCE_WR(obj->instance, 6, 0x00000000);
-                       INSTANCE_WR(obj->instance, 7, 0x00000000);
                } else {
 #ifdef __BIG_ENDIAN
-                       INSTANCE_WR(obj->instance, 0, obj->class | 0x00080000);
+                       INSTANCE_WR(*gpuobj, 0, class | 0x00080000);
 #else
-                       INSTANCE_WR(obj->instance, 0, obj->class);
+                       INSTANCE_WR(*gpuobj, 0, class);
 #endif
-                       INSTANCE_WR(obj->instance, 1, 0x00000000);
-                       INSTANCE_WR(obj->instance, 2, 0x00000000);
-                       INSTANCE_WR(obj->instance, 3, 0x00000000);
                }
        }
+       }
 
-       return obj;
-}
-
-void
-nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj)
-{
-       nouveau_object_instance_free(dev, obj);
-       if (obj->handle != ~0)
-               nouveau_hash_table_remove(dev, obj);
-       drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
+       (*gpuobj)->engine = NVOBJ_ENGINE_GR;
+       (*gpuobj)->class  = class;
+       return 0;
 }
 
-void nouveau_object_cleanup(drm_device_t *dev, int channel)
+static int
+nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *pramin = NULL;
+       int size, base, ret;
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+       /* Base amount for object storage (4KiB enough?) */
+       size = 0x1000;
+       base = 0;
+
+       /* PGRAPH context */
+
+       if (dev_priv->card_type == NV_50) {
+               /* Various fixed table thingos */
+               size += 0x1400; /* mostly unknown stuff */
+               size += 0x4000; /* vm pd */
+               base  = 0x6000;
+               /* RAMHT, not sure about setting size yet, 32KiB to be safe */
+               size += 0x8000;
+               /* RAMFC */
+               size += 0x1000;
+               /* PGRAPH context */
+               size += 0x60000;
+       }
 
-       while (dev_priv->fifos[channel].objs) {
-               nouveau_object_free(dev, dev_priv->fifos[channel].objs);
+       DRM_DEBUG("ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n",
+                 chan->id, size, base);
+       ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,
+                                    &chan->ramin);
+       if (ret) {
+               DRM_ERROR("Error allocating channel PRAMIN: %d\n", ret);
+               return ret;
+       }
+       pramin = chan->ramin->gpuobj;
+
+       ret = nouveau_mem_init_heap(&chan->ramin_heap,
+                                   pramin->im_pramin->start + base, size);
+       if (ret) {
+               DRM_ERROR("Error creating PRAMIN heap: %d\n", ret);
+               nouveau_gpuobj_ref_del(dev, &chan->ramin);
+               return ret;
        }
+
+       return 0;
 }
 
-int nouveau_ioctl_object_init(DRM_IOCTL_ARGS)
+int
+nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
+                           uint32_t vram_h, uint32_t tt_h)
 {
-       DRM_DEVICE;
-       drm_nouveau_object_init_t init;
-       struct nouveau_object *obj;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *vram = NULL, *tt = NULL;
+       int ret, i;
+
+       INIT_LIST_HEAD(&chan->ramht_refs);
+
+       DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
+
+       /* Reserve a block of PRAMIN for the channel
+        *XXX: maybe on <NV50 too at some point
+        */
+       if (0 || dev_priv->card_type == NV_50) {
+               ret = nouveau_gpuobj_channel_init_pramin(chan);
+               if (ret)
+                       return ret;
+       }
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_object_init_t __user *)
-               data, sizeof(init));
+       /* NV50 VM, point offset 0-512MiB at shared PCIEGART table  */
+       if (dev_priv->card_type >= NV_50) {
+               uint32_t vm_offset;
+               
+               vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
+               vm_offset += chan->ramin->gpuobj->im_pramin->start;
+               if ((ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
+                                                  0, &chan->vm_pd, NULL)))
+                       return ret;
+               for (i=0; i<0x4000; i+=8) {
+                       INSTANCE_WR(chan->vm_pd, (i+0)/4, 0x00000000);
+                       INSTANCE_WR(chan->vm_pd, (i+4)/4, 0xdeadcafe);
+               }
 
-       if (!nouveau_fifo_owner(dev, filp, init.channel)) {
-               DRM_ERROR("pid %d doesn't own channel %d\n",
-                               DRM_CURRENTPID, init.channel);
-               return DRM_ERR(EINVAL);
+               if ((ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
+                                                 dev_priv->gart_info.sg_ctxdma,
+                                                 &chan->vm_gart_pt)))
+                       return ret;
+               INSTANCE_WR(chan->vm_pd, (0+0)/4,
+                           chan->vm_gart_pt->instance | 0x03);
+               INSTANCE_WR(chan->vm_pd, (0+4)/4, 0x00000000);
        }
 
-       //FIXME: check args, only allow trusted objects to be created
+       /* RAMHT */
+       if (dev_priv->card_type < NV_50) {
+               ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht,
+                                            &chan->ramht);
+               if (ret)
+                       return ret;
+       } else {
+               ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0,
+                                            0x8000, 16,
+                                            NVOBJ_FLAG_ZERO_ALLOC,
+                                            &chan->ramht);
+               if (ret)
+                       return ret;
+       }
+
+       /* VRAM ctxdma */
+       if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                         0, dev_priv->fb_available_size,
+                                         NV_DMA_ACCESS_RW,
+                                         NV_DMA_TARGET_VIDMEM, &vram))) {
+               DRM_ERROR("Error creating VRAM ctxdma: %d\n", ret);
+               return ret;
+       }
 
-       if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
-               DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
-                       init.channel, init.handle);
-               return DRM_ERR(EINVAL);
+       if ((ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL))) {
+               DRM_ERROR("Error referencing VRAM ctxdma: %d\n", ret);
+               return ret;
        }
 
-       obj = nouveau_object_gr_create(dev, init.channel, init.class);
-       if (!obj)
-               return DRM_ERR(ENOMEM);
+       /* TT memory ctxdma */
+       if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) {
+               ret = nouveau_gpuobj_gart_dma_new(chan, 0,
+                                                 dev_priv->gart_info.aper_size,
+                                                 NV_DMA_ACCESS_RW, &tt, NULL);
+       } else
+       if (dev_priv->pci_heap) {
+               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                            0, dev->sg->pages * PAGE_SIZE,
+                                            NV_DMA_ACCESS_RW,
+                                            NV_DMA_TARGET_PCI_NONLINEAR, &tt);
+       } else {
+               DRM_ERROR("Invalid GART type %d\n", dev_priv->gart_info.type);
+               ret = -EINVAL;
+       }
+
+       if (ret) {
+               DRM_ERROR("Error creating TT ctxdma: %d\n", ret);
+               return ret;
+       }
 
-       if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) {
-               nouveau_object_free(dev, obj);
-               return DRM_ERR(ENOMEM);
+       ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL);
+       if (ret) {
+               DRM_ERROR("Error referencing TT ctxdma: %d\n", ret);
+               return ret;
        }
 
        return 0;
 }
 
-static int
-nouveau_dma_object_check_access(drm_device_t *dev,
-                               drm_nouveau_dma_object_init_t *init)
+void
+nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       uint64_t limit;
-
-       /* Check for known DMA object classes */
-       switch (init->class) {
-       case NV_CLASS_DMA_IN_MEMORY:
-       case NV_CLASS_DMA_FROM_MEMORY:
-       case NV_CLASS_DMA_TO_MEMORY:
-               break;
-       default:
-               DRM_ERROR("invalid class = 0x%x\n", init->class);
-               return DRM_ERR(EPERM);
-       }
+       struct drm_device *dev = chan->dev;
+       struct list_head *entry, *tmp;
+       struct nouveau_gpuobj_ref *ref;
 
-       /* Check access mode, and translate to NV_DMA_ACCESS_* */
-       switch (init->access) {
-       case NOUVEAU_MEM_ACCESS_RO:
-               init->access = NV_DMA_ACCESS_RO;
-               break;
-       case NOUVEAU_MEM_ACCESS_WO:
-               init->access = NV_DMA_ACCESS_WO;
-               break;
-       case NOUVEAU_MEM_ACCESS_RW:
-               init->access = NV_DMA_ACCESS_RW;
-               break;
-       default:
-               DRM_ERROR("invalid access mode = %d\n", init->access);
-               return DRM_ERR(EPERM);
-       }
+       DRM_DEBUG("ch%d\n", chan->id);
 
-       /* Check that request is within the allowed limits of "target" */
-       switch (init->target) {
-       case NOUVEAU_MEM_FB:
-               limit = dev_priv->fb_available_size;
-               init->target = NV_DMA_TARGET_VIDMEM;
-               break;
-       case NOUVEAU_MEM_AGP:
-               limit = dev_priv->agp_available_size;
-               init->target = NV_DMA_TARGET_AGP;
-               break;
-       default:
-               DRM_ERROR("invalid target = 0x%x\n", init->target);
-               return DRM_ERR(EPERM);
-       }
+       list_for_each_safe(entry, tmp, &chan->ramht_refs) {             
+               ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
 
-       if ((init->offset > limit) || (init->offset + init->size) > limit) {
-               DRM_ERROR("access out of allowed range (%d,0x%08x,0x%08x)\n",
-                               init->target, init->offset, init->size);
-               return DRM_ERR(EPERM);
+               nouveau_gpuobj_ref_del(dev, &ref);
        }
 
-       return 0;
+       nouveau_gpuobj_ref_del(dev, &chan->ramht);
+
+       nouveau_gpuobj_del(dev, &chan->vm_pd);
+       nouveau_gpuobj_ref_del(dev, &chan->vm_gart_pt);
+
+       if (chan->ramin_heap)
+               nouveau_mem_takedown(&chan->ramin_heap);
+       if (chan->ramin)
+               nouveau_gpuobj_ref_del(dev, &chan->ramin);
+
 }
 
-int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS)
+int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_nouveau_dma_object_init_t init;
-       struct nouveau_object *obj;
+       struct nouveau_channel *chan;
+       struct drm_nouveau_grobj_alloc *init = data;
+       struct nouveau_gpuobj *gr = NULL;
+       int ret;
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_dma_object_init_t __user *)
-               data, sizeof(init));
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+       NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
 
-       if (!nouveau_fifo_owner(dev, filp, init.channel)) {
-               DRM_ERROR("pid %d doesn't own channel %d\n",
-                               DRM_CURRENTPID, init.channel);
-               return DRM_ERR(EINVAL);
+       //FIXME: check args, only allow trusted objects to be created
+       
+       if (init->handle == ~0)
+               return -EINVAL;
+
+       if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0)
+               return -EEXIST;
+
+       ret = nouveau_gpuobj_gr_new(chan, init->class, &gr);
+       if (ret) {
+               DRM_ERROR("Error creating gr object: %d (%d/0x%08x)\n",
+                         ret, init->channel, init->handle);
+               return ret;
        }
 
-       if (nouveau_dma_object_check_access(dev, &init))
-               return DRM_ERR(EPERM);
-
-       if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
-               DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
-                       init.channel, init.handle);
-               return DRM_ERR(EINVAL);
+       if ((ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL))) {
+               DRM_ERROR("Error referencing gr object: %d (%d/0x%08x\n)",
+                         ret, init->channel, init->handle);
+               nouveau_gpuobj_del(dev, &gr);
+               return ret;
        }
 
-       obj = nouveau_object_dma_create(dev, init.channel, init.class,
-                                            init.offset, init.size,
-                                            init.access, init.target);
-       if (!obj)
-               return DRM_ERR(ENOMEM);
+       return 0;
+}
 
-       obj->handle = init.handle;
-       if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) {
-               nouveau_object_free(dev, obj);
-               return DRM_ERR(ENOMEM);
-       }
+int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct drm_nouveau_gpuobj_free *objfree = data;
+       struct nouveau_gpuobj_ref *ref;
+       struct nouveau_channel *chan;
+       int ret;
+
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+       NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
+
+       if ((ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref)))
+               return ret;
+       nouveau_gpuobj_ref_del(dev, &ref);
 
        return 0;
 }
index ea4a2f6..4dc3b7f 100644 (file)
@@ -15,9 +15,6 @@
 #    define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK              0xfff00000
 #    define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT             20
 
-#define NV03_PGRAPH_STATUS                                 0x004006b0
-#define NV04_PGRAPH_STATUS                                 0x00400700
-
 #define NV_RAMIN                                           0x00700000
 
 #define NV_RAMHT_HANDLE_OFFSET                             0
@@ -39,6 +36,8 @@
 #define NV_DMA_TARGET_VIDMEM 0
 #define NV_DMA_TARGET_PCI    2
 #define NV_DMA_TARGET_AGP    3
+/*The following is not a real value used by nvidia cards, it's changed by nouveau_object_dma_create*/
+#define NV_DMA_TARGET_PCI_NONLINEAR   8
 
 /* Some object classes we care about in the drm */
 #define NV_CLASS_DMA_FROM_MEMORY                           0x00000002
 #define NV_CLASS_DMA_IN_MEMORY                             0x0000003D
 
 #define NV03_FIFO_SIZE                                     0x8000UL
-#define NV_MAX_FIFO_NUMBER                                 32
+#define NV_MAX_FIFO_NUMBER                                 128
 #define NV03_FIFO_REGS_SIZE                                0x10000
 #define NV03_FIFO_REGS(i)                                  (0x00800000+i*NV03_FIFO_REGS_SIZE)
 #    define NV03_FIFO_REGS_DMAPUT(i)                       (NV03_FIFO_REGS(i)+0x40)
 #    define NV03_FIFO_REGS_DMAGET(i)                       (NV03_FIFO_REGS(i)+0x44)
+#define NV50_FIFO_REGS_SIZE                                0x2000
+#define NV50_FIFO_REGS(i)                                  (0x00c00000+i*NV50_FIFO_REGS_SIZE)
+#    define NV50_FIFO_REGS_DMAPUT(i)                       (NV50_FIFO_REGS(i)+0x40)
+#    define NV50_FIFO_REGS_DMAGET(i)                       (NV50_FIFO_REGS(i)+0x44)
 
 #define NV03_PMC_BOOT_0                                    0x00000000
+#define NV03_PMC_BOOT_1                                    0x00000004
 #define NV03_PMC_INTR_0                                    0x00000100
 #    define NV_PMC_INTR_0_PFIFO_PENDING                       (1<< 8)
 #    define NV_PMC_INTR_0_PGRAPH_PENDING                      (1<<12)
 #define NV40_PMC_1708                                      0x00001708
 #define NV40_PMC_170C                                      0x0000170C
 
+/* probably PMC ? */
+#define NV50_PUNK_BAR0_PRAMIN                              0x00001700
+#define NV50_PUNK_BAR_CFG_BASE                             0x00001704
+#define NV50_PUNK_BAR_CFG_BASE_VALID                          (1<<30)
+#define NV50_PUNK_BAR1_CTXDMA                              0x00001708
+#define NV50_PUNK_BAR1_CTXDMA_VALID                           (1<<31)
+#define NV50_PUNK_BAR3_CTXDMA                              0x0000170C
+#define NV50_PUNK_BAR3_CTXDMA_VALID                           (1<<31)
+#define NV50_PUNK_UNK1710                                  0x00001710
+
 #define NV04_PTIMER_INTR_0                                 0x00009100
 #define NV04_PTIMER_INTR_EN_0                              0x00009140
 #define NV04_PTIMER_NUMERATOR                              0x00009200
 #define NV04_PGRAPH_DEBUG_3                                0x0040008c
 #define NV10_PGRAPH_DEBUG_4                                0x00400090
 #define NV03_PGRAPH_INTR                                   0x00400100
+#define NV03_PGRAPH_NSTATUS                                0x00400104
+#    define NV04_PGRAPH_NSTATUS_STATE_IN_USE                  (1<<11)
+#    define NV04_PGRAPH_NSTATUS_INVALID_STATE                 (1<<12)
+#    define NV04_PGRAPH_NSTATUS_BAD_ARGUMENT                  (1<<13)
+#    define NV04_PGRAPH_NSTATUS_PROTECTION_FAULT              (1<<14)
+#    define NV10_PGRAPH_NSTATUS_STATE_IN_USE                  (1<<23)
+#    define NV10_PGRAPH_NSTATUS_INVALID_STATE                 (1<<24)
+#    define NV10_PGRAPH_NSTATUS_BAD_ARGUMENT                  (1<<25)
+#    define NV10_PGRAPH_NSTATUS_PROTECTION_FAULT              (1<<26)
+#define NV03_PGRAPH_NSOURCE                                0x00400108
+#    define NV03_PGRAPH_NSOURCE_NOTIFICATION                  (1<< 0)
+#    define NV03_PGRAPH_NSOURCE_DATA_ERROR                    (1<< 1)
+#    define NV03_PGRAPH_NSOURCE_PROTECTION_ERROR              (1<< 2)
+#    define NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION               (1<< 3)
+#    define NV03_PGRAPH_NSOURCE_LIMIT_COLOR                   (1<< 4)
+#    define NV03_PGRAPH_NSOURCE_LIMIT_ZETA                    (1<< 5)
+#    define NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD                  (1<< 6)
+#    define NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION              (1<< 7)
+#    define NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION              (1<< 8)
+#    define NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION              (1<< 9)
+#    define NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION               (1<<10)
+#    define NV03_PGRAPH_NSOURCE_STATE_INVALID                 (1<<11)
+#    define NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY                 (1<<12)
+#    define NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE                 (1<<13)
+#    define NV03_PGRAPH_NSOURCE_METHOD_CNT                    (1<<14)
+#    define NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION              (1<<15)
+#    define NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION            (1<<16)
+#    define NV03_PGRAPH_NSOURCE_DMA_WIDTH_A                   (1<<17)
+#    define NV03_PGRAPH_NSOURCE_DMA_WIDTH_B                   (1<<18)
 #define NV03_PGRAPH_INTR_EN                                0x00400140
 #define NV40_PGRAPH_INTR_EN                                0x0040013C
 #    define NV_PGRAPH_INTR_NOTIFY                             (1<< 0)
 #define NV10_PGRAPH_CTX_CACHE4                             0x004001C0
 #define NV04_PGRAPH_CTX_CACHE4                             0x004001E0
 #define NV10_PGRAPH_CTX_CACHE5                             0x004001E0
+#define NV40_PGRAPH_CTXCTL_0304                            0x00400304
+#define NV40_PGRAPH_CTXCTL_0304_XFER_CTX                   0x00000001
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT                      0x00400308
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_MASK              0xff000000
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT                     24
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK              0x00ffffff
+#define NV40_PGRAPH_CTXCTL_0310                            0x00400310
+#define NV40_PGRAPH_CTXCTL_0310_XFER_SAVE                  0x00000020
+#define NV40_PGRAPH_CTXCTL_0310_XFER_LOAD                  0x00000040
+#define NV40_PGRAPH_CTXCTL_030C                            0x0040030c
+#define NV40_PGRAPH_CTXCTL_UCODE_INDEX                     0x00400324
+#define NV40_PGRAPH_CTXCTL_UCODE_DATA                      0x00400328
+#define NV40_PGRAPH_CTXCTL_CUR                             0x0040032c
+#define NV40_PGRAPH_CTXCTL_CUR_LOADED                      0x01000000
+#define NV40_PGRAPH_CTXCTL_CUR_INST_MASK                   0x000FFFFF
 #define NV03_PGRAPH_ABS_X_RAM                              0x00400400
 #define NV03_PGRAPH_ABS_Y_RAM                              0x00400480
 #define NV03_PGRAPH_X_MISC                                 0x00400500
 #define NV04_PGRAPH_BLIMIT5                                0x00400698
 #define NV04_PGRAPH_BSWIZZLE2                              0x0040069C
 #define NV04_PGRAPH_BSWIZZLE5                              0x004006A0
+#define NV03_PGRAPH_STATUS                                 0x004006B0
+#define NV04_PGRAPH_STATUS                                 0x00400700
+#define NV04_PGRAPH_TRAPPED_ADDR                           0x00400704
+#define NV04_PGRAPH_TRAPPED_DATA                           0x00400708
 #define NV04_PGRAPH_SURFACE                                0x0040070C
+#define NV10_PGRAPH_TRAPPED_DATA_HIGH                      0x0040070C
 #define NV04_PGRAPH_STATE                                  0x00400710
 #define NV10_PGRAPH_SURFACE                                0x00400710
 #define NV04_PGRAPH_NOTIFY                                 0x00400714
 #define NV10_PGRAPH_DMA_PITCH                              0x00400770
 #define NV10_PGRAPH_DVD_COLORFMT                           0x00400774
 #define NV10_PGRAPH_SCALED_FORMAT                          0x00400778
-#define NV10_PGRAPH_CHANNEL_CTX_TABLE                      0x00400780
-#define NV10_PGRAPH_CHANNEL_CTX_SIZE                       0x00400784
-#define NV10_PGRAPH_CHANNEL_CTX_POINTER                    0x00400788
+#define NV20_PGRAPH_CHANNEL_CTX_TABLE                      0x00400780
+#define NV20_PGRAPH_CHANNEL_CTX_POINTER                    0x00400784
+#define NV20_PGRAPH_CHANNEL_CTX_XFER                       0x00400788
+#define NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD                  0x00000001
+#define NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE                  0x00000002
 #define NV04_PGRAPH_PATT_COLOR0                            0x00400800
 #define NV04_PGRAPH_PATT_COLOR1                            0x00400804
 #define NV04_PGRAPH_PATTERN                                0x00400808
 #define NV47_PGRAPH_TSTATUS0(i)                            0x00400D0C
 #define NV04_PGRAPH_V_RAM                                  0x00400D40
 #define NV04_PGRAPH_W_RAM                                  0x00400D80
+#define NV10_PGRAPH_COMBINER0_IN_ALPHA                     0x00400E40
+#define NV10_PGRAPH_COMBINER1_IN_ALPHA                     0x00400E44
+#define NV10_PGRAPH_COMBINER0_IN_RGB                       0x00400E48
+#define NV10_PGRAPH_COMBINER1_IN_RGB                       0x00400E4C
+#define NV10_PGRAPH_COMBINER_COLOR0                        0x00400E50
+#define NV10_PGRAPH_COMBINER_COLOR1                        0x00400E54
+#define NV10_PGRAPH_COMBINER0_OUT_ALPHA                    0x00400E58
+#define NV10_PGRAPH_COMBINER1_OUT_ALPHA                    0x00400E5C
+#define NV10_PGRAPH_COMBINER0_OUT_RGB                      0x00400E60
+#define NV10_PGRAPH_COMBINER1_OUT_RGB                      0x00400E64
+#define NV10_PGRAPH_COMBINER_FINAL0                        0x00400E68
+#define NV10_PGRAPH_COMBINER_FINAL1                        0x00400E6C
 #define NV10_PGRAPH_WINDOWCLIP_HORIZONTAL                  0x00400F00
 #define NV10_PGRAPH_WINDOWCLIP_VERTICAL                    0x00400F20
 #define NV10_PGRAPH_XFMODE0                                0x00400F40
 #define NV04_PFIFO_MODE                                    0x00002504
 #define NV04_PFIFO_DMA                                     0x00002508
 #define NV04_PFIFO_SIZE                                    0x0000250c
+#define NV50_PFIFO_CTX_TABLE(c)                        (0x2600+(c)*4)
+#define NV50_PFIFO_CTX_TABLE__SIZE                                128
+#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED                  (1<<31)
+#define NV50_PFIFO_CTX_TABLE_UNK30_BAD                        (1<<30)
+#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80             0x0FFFFFFF
+#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84             0x00FFFFFF
 #define NV03_PFIFO_CACHE0_PUSH0                            0x00003000
 #define NV03_PFIFO_CACHE0_PULL0                            0x00003040
 #define NV04_PFIFO_CACHE0_PULL0                            0x00003050
 #define NV10_PFIFO_CACHE1_SEMAPHORE                        0x0000326C
 #define NV03_PFIFO_CACHE1_GET                              0x00003270
 #define NV04_PFIFO_CACHE1_ENGINE                           0x00003280
-#define NV10_PFIFO_CACHE1_DMA_DCOUNT                       0x000032A0
+#define NV04_PFIFO_CACHE1_DMA_DCOUNT                       0x000032A0
 #define NV40_PFIFO_GRCTX_INSTANCE                          0x000032E0
 #define NV40_PFIFO_UNK32E4                                 0x000032E4
 #define NV04_PFIFO_CACHE1_METHOD(i)                (0x00003800+(i*8))
 #define NV04_RAMFC_DMA_PUT                                       0x00
 #define NV04_RAMFC_DMA_GET                                       0x04
 #define NV04_RAMFC_DMA_INSTANCE                                  0x08
+#define NV04_RAMFC_DMA_STATE                                     0x0C
 #define NV04_RAMFC_DMA_FETCH                                     0x10
+#define NV04_RAMFC_ENGINE                                        0x14
+#define NV04_RAMFC_PULL1_ENGINE                                  0x18
 
 #define NV10_RAMFC_DMA_PUT                                       0x00
 #define NV10_RAMFC_DMA_GET                                       0x04
 #define NV40_RAMFC_UNK_40                                        0x40
 #define NV40_RAMFC_UNK_44                                        0x44
 #define NV40_RAMFC_UNK_48                                        0x48
-#define NV40_RAMFC_2088                                          0x4C
-#define NV40_RAMFC_3300                                          0x50
+#define NV40_RAMFC_UNK_4C                                        0x4C
+#define NV40_RAMFC_UNK_50                                        0x50
 
index e7930b9..add2d59 100644 (file)
@@ -28,9 +28,9 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 
-static int nouveau_init_card_mappings(drm_device_t *dev)
+static int nouveau_init_card_mappings(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int ret;
 
        /* resource 0 is mmio regs */
@@ -51,6 +51,7 @@ static int nouveau_init_card_mappings(drm_device_t *dev)
        DRM_DEBUG("regs mapped ok at 0x%lx\n", dev_priv->mmio->offset);
 
        /* map larger RAMIN aperture on NV40 cards */
+       dev_priv->ramin = NULL;
        if (dev_priv->card_type >= NV_40) {
                int ramin_resource = 2;
                if (drm_get_resource_len(dev, ramin_resource) == 0)
@@ -66,80 +67,198 @@ static int nouveau_init_card_mappings(drm_device_t *dev)
                                  "limited instance memory available\n");
                        dev_priv->ramin = NULL;
                }
-       } else
-               dev_priv->ramin = NULL;
+       }
+
+       /* On older cards (or if the above failed), create a map covering
+        * the BAR0 PRAMIN aperture */
+       if (!dev_priv->ramin) {
+               ret = drm_addmap(dev,
+                                drm_get_resource_start(dev, 0) + NV_RAMIN,
+                                (1*1024*1024),
+                                _DRM_REGISTERS, _DRM_READ_ONLY,
+                                &dev_priv->ramin);
+               if (ret) {
+                       DRM_ERROR("Failed to map BAR0 PRAMIN: %d\n", ret);
+                       return ret;
+               }
+       }
 
        return 0;
 }
 
-static void nouveau_stub_takedown(drm_device_t *dev) {}
-static int nouveau_init_engine_ptrs(drm_device_t *dev)
+static int nouveau_stub_init(struct drm_device *dev) { return 0; }
+static void nouveau_stub_takedown(struct drm_device *dev) {}
+static uint64_t nouveau_stub_timer_read(struct drm_device *dev) { return 0; }
+
+static int nouveau_init_engine_ptrs(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_engine_func *engine = &dev_priv->Engine;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->Engine;
 
        switch (dev_priv->chipset & 0xf0) {
        case 0x00:
-               engine->Mc.Init         = nv04_mc_init;
-               engine->Mc.Takedown     = nv04_mc_takedown;
-               engine->Timer.Init      = nv04_timer_init;
-               engine->Timer.Takedown  = nv04_timer_takedown;
-               engine->Fb.Init         = nv04_fb_init;
-               engine->Fb.Takedown     = nv04_fb_takedown;
-               engine->Graph.Init      = nv04_graph_init;
-               engine->Graph.Takedown  = nv04_graph_takedown;
-               engine->Fifo.Init       = nouveau_fifo_init;
-               engine->Fifo.Takedown   = nouveau_stub_takedown;
+               engine->instmem.init    = nv04_instmem_init;
+               engine->instmem.takedown= nv04_instmem_takedown;
+               engine->instmem.populate        = nv04_instmem_populate;
+               engine->instmem.clear           = nv04_instmem_clear;
+               engine->instmem.bind            = nv04_instmem_bind;
+               engine->instmem.unbind          = nv04_instmem_unbind;
+               engine->mc.init         = nv04_mc_init;
+               engine->mc.takedown     = nv04_mc_takedown;
+               engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
+               engine->timer.takedown  = nv04_timer_takedown;
+               engine->fb.init         = nv04_fb_init;
+               engine->fb.takedown     = nv04_fb_takedown;
+               engine->graph.init      = nv04_graph_init;
+               engine->graph.takedown  = nv04_graph_takedown;
+               engine->graph.create_context    = nv04_graph_create_context;
+               engine->graph.destroy_context   = nv04_graph_destroy_context;
+               engine->graph.load_context      = nv04_graph_load_context;
+               engine->graph.save_context      = nv04_graph_save_context;
+               engine->fifo.init       = nouveau_fifo_init;
+               engine->fifo.takedown   = nouveau_stub_takedown;
+               engine->fifo.create_context     = nv04_fifo_create_context;
+               engine->fifo.destroy_context    = nv04_fifo_destroy_context;
+               engine->fifo.load_context       = nv04_fifo_load_context;
+               engine->fifo.save_context       = nv04_fifo_save_context;
                break;
        case 0x10:
-               engine->Mc.Init         = nv04_mc_init;
-               engine->Mc.Takedown     = nv04_mc_takedown;
-               engine->Timer.Init      = nv04_timer_init;
-               engine->Timer.Takedown  = nv04_timer_takedown;
-               engine->Fb.Init         = nv10_fb_init;
-               engine->Fb.Takedown     = nv10_fb_takedown;
-               engine->Graph.Init      = nv10_graph_init;
-               engine->Graph.Takedown  = nv10_graph_takedown;
-               engine->Fifo.Init       = nouveau_fifo_init;
-               engine->Fifo.Takedown   = nouveau_stub_takedown;
+               engine->instmem.init    = nv04_instmem_init;
+               engine->instmem.takedown= nv04_instmem_takedown;
+               engine->instmem.populate        = nv04_instmem_populate;
+               engine->instmem.clear           = nv04_instmem_clear;
+               engine->instmem.bind            = nv04_instmem_bind;
+               engine->instmem.unbind          = nv04_instmem_unbind;
+               engine->mc.init         = nv04_mc_init;
+               engine->mc.takedown     = nv04_mc_takedown;
+               engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
+               engine->timer.takedown  = nv04_timer_takedown;
+               engine->fb.init         = nv10_fb_init;
+               engine->fb.takedown     = nv10_fb_takedown;
+               engine->graph.init      = nv10_graph_init;
+               engine->graph.takedown  = nv10_graph_takedown;
+               engine->graph.create_context    = nv10_graph_create_context;
+               engine->graph.destroy_context   = nv10_graph_destroy_context;
+               engine->graph.load_context      = nv10_graph_load_context;
+               engine->graph.save_context      = nv10_graph_save_context;
+               engine->fifo.init       = nouveau_fifo_init;
+               engine->fifo.takedown   = nouveau_stub_takedown;
+               engine->fifo.create_context     = nv10_fifo_create_context;
+               engine->fifo.destroy_context    = nv10_fifo_destroy_context;
+               engine->fifo.load_context       = nv10_fifo_load_context;
+               engine->fifo.save_context       = nv10_fifo_save_context;
                break;
        case 0x20:
-               engine->Mc.Init         = nv04_mc_init;
-               engine->Mc.Takedown     = nv04_mc_takedown;
-               engine->Timer.Init      = nv04_timer_init;
-               engine->Timer.Takedown  = nv04_timer_takedown;
-               engine->Fb.Init         = nv10_fb_init;
-               engine->Fb.Takedown     = nv10_fb_takedown;
-               engine->Graph.Init      = nv20_graph_init;
-               engine->Graph.Takedown  = nv20_graph_takedown;
-               engine->Fifo.Init       = nouveau_fifo_init;
-               engine->Fifo.Takedown   = nouveau_stub_takedown;
+               engine->instmem.init    = nv04_instmem_init;
+               engine->instmem.takedown= nv04_instmem_takedown;
+               engine->instmem.populate        = nv04_instmem_populate;
+               engine->instmem.clear           = nv04_instmem_clear;
+               engine->instmem.bind            = nv04_instmem_bind;
+               engine->instmem.unbind          = nv04_instmem_unbind;
+               engine->mc.init         = nv04_mc_init;
+               engine->mc.takedown     = nv04_mc_takedown;
+               engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
+               engine->timer.takedown  = nv04_timer_takedown;
+               engine->fb.init         = nv10_fb_init;
+               engine->fb.takedown     = nv10_fb_takedown;
+               engine->graph.init      = nv20_graph_init;
+               engine->graph.takedown  = nv20_graph_takedown;
+               engine->graph.create_context    = nv20_graph_create_context;
+               engine->graph.destroy_context   = nv20_graph_destroy_context;
+               engine->graph.load_context      = nv20_graph_load_context;
+               engine->graph.save_context      = nv20_graph_save_context;
+               engine->fifo.init       = nouveau_fifo_init;
+               engine->fifo.takedown   = nouveau_stub_takedown;
+               engine->fifo.create_context     = nv10_fifo_create_context;
+               engine->fifo.destroy_context    = nv10_fifo_destroy_context;
+               engine->fifo.load_context       = nv10_fifo_load_context;
+               engine->fifo.save_context       = nv10_fifo_save_context;
                break;
        case 0x30:
-               engine->Mc.Init         = nv04_mc_init;
-               engine->Mc.Takedown     = nv04_mc_takedown;
-               engine->Timer.Init      = nv04_timer_init;
-               engine->Timer.Takedown  = nv04_timer_takedown;
-               engine->Fb.Init         = nv10_fb_init;
-               engine->Fb.Takedown     = nv10_fb_takedown;
-               engine->Graph.Init      = nv30_graph_init;
-               engine->Graph.Takedown  = nv30_graph_takedown;
-               engine->Fifo.Init       = nouveau_fifo_init;
-               engine->Fifo.Takedown   = nouveau_stub_takedown;
+               engine->instmem.init    = nv04_instmem_init;
+               engine->instmem.takedown= nv04_instmem_takedown;
+               engine->instmem.populate        = nv04_instmem_populate;
+               engine->instmem.clear           = nv04_instmem_clear;
+               engine->instmem.bind            = nv04_instmem_bind;
+               engine->instmem.unbind          = nv04_instmem_unbind;
+               engine->mc.init         = nv04_mc_init;
+               engine->mc.takedown     = nv04_mc_takedown;
+               engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
+               engine->timer.takedown  = nv04_timer_takedown;
+               engine->fb.init         = nv10_fb_init;
+               engine->fb.takedown     = nv10_fb_takedown;
+               engine->graph.init      = nv30_graph_init;
+               engine->graph.takedown  = nv20_graph_takedown;
+               engine->graph.create_context    = nv20_graph_create_context;
+               engine->graph.destroy_context   = nv20_graph_destroy_context;
+               engine->graph.load_context      = nv20_graph_load_context;
+               engine->graph.save_context      = nv20_graph_save_context;
+               engine->fifo.init       = nouveau_fifo_init;
+               engine->fifo.takedown   = nouveau_stub_takedown;
+               engine->fifo.create_context     = nv10_fifo_create_context;
+               engine->fifo.destroy_context    = nv10_fifo_destroy_context;
+               engine->fifo.load_context       = nv10_fifo_load_context;
+               engine->fifo.save_context       = nv10_fifo_save_context;
                break;
        case 0x40:
-               engine->Mc.Init         = nv40_mc_init;
-               engine->Mc.Takedown     = nv40_mc_takedown;
-               engine->Timer.Init      = nv04_timer_init;
-               engine->Timer.Takedown  = nv04_timer_takedown;
-               engine->Fb.Init         = nv40_fb_init;
-               engine->Fb.Takedown     = nv40_fb_takedown;
-               engine->Graph.Init      = nv40_graph_init;
-               engine->Graph.Takedown  = nv40_graph_takedown;
-               engine->Fifo.Init       = nouveau_fifo_init;
-               engine->Fifo.Takedown   = nouveau_stub_takedown;
+               engine->instmem.init    = nv04_instmem_init;
+               engine->instmem.takedown= nv04_instmem_takedown;
+               engine->instmem.populate        = nv04_instmem_populate;
+               engine->instmem.clear           = nv04_instmem_clear;
+               engine->instmem.bind            = nv04_instmem_bind;
+               engine->instmem.unbind          = nv04_instmem_unbind;
+               engine->mc.init         = nv40_mc_init;
+               engine->mc.takedown     = nv40_mc_takedown;
+               engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
+               engine->timer.takedown  = nv04_timer_takedown;
+               engine->fb.init         = nv40_fb_init;
+               engine->fb.takedown     = nv40_fb_takedown;
+               engine->graph.init      = nv40_graph_init;
+               engine->graph.takedown  = nv40_graph_takedown;
+               engine->graph.create_context    = nv40_graph_create_context;
+               engine->graph.destroy_context   = nv40_graph_destroy_context;
+               engine->graph.load_context      = nv40_graph_load_context;
+               engine->graph.save_context      = nv40_graph_save_context;
+               engine->fifo.init       = nv40_fifo_init;
+               engine->fifo.takedown   = nouveau_stub_takedown;
+               engine->fifo.create_context     = nv40_fifo_create_context;
+               engine->fifo.destroy_context    = nv40_fifo_destroy_context;
+               engine->fifo.load_context       = nv40_fifo_load_context;
+               engine->fifo.save_context       = nv40_fifo_save_context;
                break;
        case 0x50:
+       case 0x80: /* gotta love NVIDIA's consistency.. */
+               engine->instmem.init    = nv50_instmem_init;
+               engine->instmem.takedown= nv50_instmem_takedown;
+               engine->instmem.populate        = nv50_instmem_populate;
+               engine->instmem.clear           = nv50_instmem_clear;
+               engine->instmem.bind            = nv50_instmem_bind;
+               engine->instmem.unbind          = nv50_instmem_unbind;
+               engine->mc.init         = nv50_mc_init;
+               engine->mc.takedown     = nv50_mc_takedown;
+               engine->timer.init      = nouveau_stub_init;
+               engine->timer.read      = nouveau_stub_timer_read;
+               engine->timer.takedown  = nouveau_stub_takedown;
+               engine->fb.init         = nouveau_stub_init;
+               engine->fb.takedown     = nouveau_stub_takedown;
+               engine->graph.init      = nv50_graph_init;
+               engine->graph.takedown  = nv50_graph_takedown;
+               engine->graph.create_context    = nv50_graph_create_context;
+               engine->graph.destroy_context   = nv50_graph_destroy_context;
+               engine->graph.load_context      = nv50_graph_load_context;
+               engine->graph.save_context      = nv50_graph_save_context;
+               engine->fifo.init       = nv50_fifo_init;
+               engine->fifo.takedown   = nv50_fifo_takedown;
+               engine->fifo.create_context     = nv50_fifo_create_context;
+               engine->fifo.destroy_context    = nv50_fifo_destroy_context;
+               engine->fifo.load_context       = nv50_fifo_load_context;
+               engine->fifo.save_context       = nv50_fifo_save_context;
+               break;
        default:
                DRM_ERROR("NV%02x unsupported\n", dev_priv->chipset);
                return 1;
@@ -148,16 +267,28 @@ static int nouveau_init_engine_ptrs(drm_device_t *dev)
        return 0;
 }
 
-static int nouveau_card_init(drm_device_t *dev)
+int
+nouveau_card_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_engine_func *engine;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine;
        int ret;
 
+       DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
+
+       if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
+               return 0;
+
        /* Map any PCI resources we need on the card */
        ret = nouveau_init_card_mappings(dev);
        if (ret) return ret;
 
+       /* Put the card in BE mode if it's not */
+       if (NV_READ(NV03_PMC_BOOT_1))
+               NV_WRITE(NV03_PMC_BOOT_1,0x00000001);
+
+       DRM_MEMORYBARRIER();
+
        /* Determine exact chipset we're running on */
        if (dev_priv->card_type < NV_10)
                dev_priv->chipset = dev_priv->card_type;
@@ -169,105 +300,204 @@ static int nouveau_card_init(drm_device_t *dev)
        ret = nouveau_init_engine_ptrs(dev);
        if (ret) return ret;
        engine = &dev_priv->Engine;
+       dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
+
+       ret = nouveau_gpuobj_early_init(dev);
+       if (ret) return ret;
 
        /* Initialise instance memory, must happen before mem_init so we
         * know exactly how much VRAM we're able to use for "normal"
         * purposes.
         */
-       ret = nouveau_instmem_init(dev);
+       ret = engine->instmem.init(dev);
        if (ret) return ret;
 
        /* Setup the memory manager */
        ret = nouveau_mem_init(dev);
        if (ret) return ret;
 
+       ret = nouveau_gpuobj_init(dev);
+       if (ret) return ret;
+
        /* Parse BIOS tables / Run init tables? */
 
        /* PMC */
-       ret = engine->Mc.Init(dev);
+       ret = engine->mc.init(dev);
        if (ret) return ret;
 
        /* PTIMER */
-       ret = engine->Timer.Init(dev);
+       ret = engine->timer.init(dev);
        if (ret) return ret;
 
        /* PFB */
-       ret = engine->Fb.Init(dev);
+       ret = engine->fb.init(dev);
        if (ret) return ret;
 
        /* PGRAPH */
-       ret = engine->Graph.Init(dev);
+       ret = engine->graph.init(dev);
        if (ret) return ret;
 
        /* PFIFO */
-       ret = engine->Fifo.Init(dev);
+       ret = engine->fifo.init(dev);
+       if (ret) return ret;
+
+       /* this call irq_preinstall, register irq handler and
+        * call irq_postinstall
+        */
+       ret = drm_irq_install(dev);
        if (ret) return ret;
 
        /* what about PVIDEO/PCRTC/PRAMDAC etc? */
 
+       ret = nouveau_dma_channel_init(dev);
+       if (ret) return ret;
+
+       dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
        return 0;
 }
 
-/* here a client dies, release the stuff that was allocated for its filp */
-void nouveau_preclose(drm_device_t * dev, DRMFILE filp)
+static void nouveau_card_takedown(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->Engine;
+
+       DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
+
+       if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
+               nouveau_dma_channel_takedown(dev);
+
+               engine->fifo.takedown(dev);
+               engine->graph.takedown(dev);
+               engine->fb.takedown(dev);
+               engine->timer.takedown(dev);
+               engine->mc.takedown(dev);
 
-       nouveau_mem_release(filp,dev_priv->fb_heap);
-       nouveau_mem_release(filp,dev_priv->agp_heap);
-       nouveau_fifo_cleanup(dev, filp);
+               nouveau_sgdma_nottm_hack_takedown(dev);
+               nouveau_sgdma_takedown(dev);
+
+               nouveau_gpuobj_takedown(dev);
+
+               nouveau_mem_close(dev);
+               engine->instmem.takedown(dev);
+
+               drm_irq_uninstall(dev);
+
+               nouveau_gpuobj_late_takedown(dev);
+
+               dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
+       }
 }
 
-/* first module load, setup the mmio/fb mapping */
-int nouveau_firstopen(struct drm_device *dev)
+/* here a client dies, release the stuff that was allocated for its
+ * file_priv */
+void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
 {
-       int ret;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-       ret = nouveau_card_init(dev);
-       if (ret) {
-               DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
-               return ret;
-       }
+       nouveau_fifo_cleanup(dev, file_priv);
+       nouveau_mem_release(file_priv,dev_priv->fb_heap);
+       nouveau_mem_release(file_priv,dev_priv->agp_heap);
+       nouveau_mem_release(file_priv,dev_priv->pci_heap);
+}
 
+/* first module load, setup the mmio/fb mapping */
+int nouveau_firstopen(struct drm_device *dev)
+{
        return 0;
 }
 
 int nouveau_load(struct drm_device *dev, unsigned long flags)
 {
-       drm_nouveau_private_t *dev_priv;
-       int ret;
+       struct drm_nouveau_private *dev_priv;
+       void __iomem *regs;
+       uint32_t reg0,reg1;
+       uint8_t architecture = 0;
 
-       if (flags==NV_UNKNOWN)
-               return DRM_ERR(EINVAL);
+       dev_priv = drm_calloc(1, sizeof(*dev_priv), DRM_MEM_DRIVER);
+       if (!dev_priv)
+               return -ENOMEM;
 
-       dev_priv = drm_alloc(sizeof(drm_nouveau_private_t), DRM_MEM_DRIVER);
-       if (!dev_priv)                   
-               return DRM_ERR(ENOMEM);
+       dev_priv->flags = flags & NOUVEAU_FLAGS;
+       dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
 
-       memset(dev_priv, 0, sizeof(drm_nouveau_private_t));
-       dev_priv->card_type=flags&NOUVEAU_FAMILY;
-       dev_priv->flags=flags&NOUVEAU_FLAGS;
+       DRM_DEBUG("vendor: 0x%X device: 0x%X class: 0x%X\n", dev->pci_vendor, dev->pci_device, dev->pdev->class);
 
-       dev->dev_private = (void *)dev_priv;
+       /* Time to determine the card architecture */
+       regs = ioremap_nocache(pci_resource_start(dev->pdev, 0), 0x8); 
+       if (!regs) {
+               DRM_ERROR("Could not ioremap to determine register\n");
+               return -ENOMEM;
+       }
 
-#if 0
-       ret = nouveau_card_init(dev);
-       if (ret) {
-               DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
-               return ret;
+       reg0 = readl(regs+NV03_PMC_BOOT_0);
+       reg1 = readl(regs+NV03_PMC_BOOT_1);
+       if (reg1)
+               reg0=___swab32(reg0);
+
+       /* We're dealing with >=NV10 */
+       if ((reg0 & 0x0f000000) > 0 ) {
+               /* Bit 27-20 contain the architecture in hex */
+               architecture = (reg0 & 0xff00000) >> 20;
+       /* NV04 or NV05 */
+       } else if ((reg0 & 0xff00fff0) == 0x20004000) {
+               architecture = 0x04;
+       }
+
+       iounmap(regs);
+
+       if (architecture >= 0x50) {
+               dev_priv->card_type = NV_50;
+       } else if (architecture >= 0x44) {
+               dev_priv->card_type = NV_44;
+       } else if (architecture >= 0x40) {
+               dev_priv->card_type = NV_40;
+       } else if (architecture >= 0x30) {
+               dev_priv->card_type = NV_30;
+       } else if (architecture >= 0x20) {
+               dev_priv->card_type = NV_20;
+       } else if (architecture >= 0x17) {
+               dev_priv->card_type = NV_17;
+       } else if (architecture >= 0x11) {
+               dev_priv->card_type = NV_11;
+       } else if (architecture >= 0x10) {
+               dev_priv->card_type = NV_10;
+       } else if (architecture >= 0x04) {
+               dev_priv->card_type = NV_04;
+       } else {
+               dev_priv->card_type = NV_UNKNOWN;
        }
-#endif
+
+       DRM_INFO("Detected an NV%d generation card (0x%08x)\n", dev_priv->card_type,reg0);
+
+       if (dev_priv->card_type == NV_UNKNOWN) {
+               return -EINVAL;
+       }
+
+       /* Special flags */
+       if (dev->pci_device == 0x01a0) {
+               dev_priv->flags |= NV_NFORCE;
+       } else if (dev->pci_device == 0x01f0) {
+               dev_priv->flags |= NV_NFORCE2;
+       }
+
+       dev->dev_private = (void *)dev_priv;
 
        return 0;
 }
 
 void nouveau_lastclose(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       if(dev_priv->fb_mtrr>0)
-       {
-               drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),nouveau_mem_fb_amount(dev), DRM_MTRR_WC);
-               dev_priv->fb_mtrr=0;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       /* In the case of an error dev_priv may not be be allocated yet */
+       if (dev_priv && dev_priv->card_type) {
+               nouveau_card_takedown(dev);
+
+               if(dev_priv->fb_mtrr>0)
+               {
+                       drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),nouveau_mem_fb_amount(dev), DRM_MTRR_WC);
+                       dev_priv->fb_mtrr=0;
+               }
        }
 }
 
@@ -278,80 +508,95 @@ int nouveau_unload(struct drm_device *dev)
        return 0;
 }
 
-int nouveau_ioctl_getparam(DRM_IOCTL_ARGS)
+int
+nouveau_ioctl_card_init(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       return nouveau_card_init(dev);
+}
+
+int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       drm_nouveau_getparam_t getparam;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct drm_nouveau_getparam *getparam = data;
 
-       DRM_COPY_FROM_USER_IOCTL(getparam, (drm_nouveau_getparam_t __user *)data,
-                       sizeof(getparam));
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 
-       switch (getparam.param) {
+       switch (getparam->param) {
+       case NOUVEAU_GETPARAM_CHIPSET_ID:
+               getparam->value = dev_priv->chipset;
+               break;
        case NOUVEAU_GETPARAM_PCI_VENDOR:
-               getparam.value=dev->pci_vendor;
+               getparam->value=dev->pci_vendor;
                break;
        case NOUVEAU_GETPARAM_PCI_DEVICE:
-               getparam.value=dev->pci_device;
+               getparam->value=dev->pci_device;
                break;
        case NOUVEAU_GETPARAM_BUS_TYPE:
                if (drm_device_is_agp(dev))
-                       getparam.value=NV_AGP;
+                       getparam->value=NV_AGP;
                else if (drm_device_is_pcie(dev))
-                       getparam.value=NV_PCIE;
+                       getparam->value=NV_PCIE;
                else
-                       getparam.value=NV_PCI;
+                       getparam->value=NV_PCI;
                break;
        case NOUVEAU_GETPARAM_FB_PHYSICAL:
-               getparam.value=dev_priv->fb_phys;
+               getparam->value=dev_priv->fb_phys;
                break;
        case NOUVEAU_GETPARAM_AGP_PHYSICAL:
-               getparam.value=dev_priv->agp_phys;
+               getparam->value=dev_priv->gart_info.aper_base;
+               break;
+       case NOUVEAU_GETPARAM_PCI_PHYSICAL:
+               if ( dev -> sg )
+                       getparam->value=(uint64_t) dev->sg->virtual;
+               else 
+                    {
+                    DRM_ERROR("Requested PCIGART address, while no PCIGART was created\n");
+                    return -EINVAL;
+                    }
                break;
        case NOUVEAU_GETPARAM_FB_SIZE:
-               getparam.value=dev_priv->fb_available_size;
+               getparam->value=dev_priv->fb_available_size;
                break;
        case NOUVEAU_GETPARAM_AGP_SIZE:
-               getparam.value=dev_priv->agp_available_size;
+               getparam->value=dev_priv->gart_info.aper_size;
                break;
        default:
-               DRM_ERROR("unknown parameter %lld\n", getparam.param);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("unknown parameter %lld\n", getparam->param);
+               return -EINVAL;
        }
 
-       DRM_COPY_TO_USER_IOCTL((drm_nouveau_getparam_t __user *)data, getparam,
-                       sizeof(getparam));
        return 0;
 }
 
-int nouveau_ioctl_setparam(DRM_IOCTL_ARGS)
+int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       drm_nouveau_setparam_t setparam;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct drm_nouveau_setparam *setparam = data;
 
-       DRM_COPY_FROM_USER_IOCTL(setparam, (drm_nouveau_setparam_t __user *)data,
-                       sizeof(setparam));
+       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 
-       switch (setparam.param) {
+       switch (setparam->param) {
        case NOUVEAU_SETPARAM_CMDBUF_LOCATION:
-               switch (setparam.value) {
+               switch (setparam->value) {
                case NOUVEAU_MEM_AGP:
                case NOUVEAU_MEM_FB:
+               case NOUVEAU_MEM_PCI:
+               case NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE:
                        break;
                default:
                        DRM_ERROR("invalid CMDBUF_LOCATION value=%lld\n",
-                                       setparam.value);
-                       return DRM_ERR(EINVAL);
+                                       setparam->value);
+                       return -EINVAL;
                }
-               dev_priv->config.cmdbuf.location = setparam.value;
+               dev_priv->config.cmdbuf.location = setparam->value;
                break;
        case NOUVEAU_SETPARAM_CMDBUF_SIZE:
-               dev_priv->config.cmdbuf.size = setparam.value;
+               dev_priv->config.cmdbuf.size = setparam->value;
                break;
        default:
-               DRM_ERROR("unknown parameter %lld\n", setparam.param);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("unknown parameter %lld\n", setparam->param);
+               return -EINVAL;
        }
 
        return 0;
@@ -360,15 +605,30 @@ int nouveau_ioctl_setparam(DRM_IOCTL_ARGS)
 /* waits for idle */
 void nouveau_wait_for_idle(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv=dev->dev_private;
-       switch(dev_priv->card_type)
-       {
-               case NV_03:
-                       while(NV_READ(NV03_PGRAPH_STATUS));
-                       break;
-               default:
-                       while(NV_READ(NV04_PGRAPH_STATUS));
-                       break;
+       struct drm_nouveau_private *dev_priv=dev->dev_private;
+       switch(dev_priv->card_type) {
+       case NV_50:
+               break;
+       default: {
+               /* This stuff is more or less a copy of what is seen
+                * in nv28 kmmio dump.
+                */
+               uint64_t started = dev_priv->Engine.timer.read(dev);
+               uint64_t stopped = started;
+               uint32_t status;
+               do {
+                       uint32_t pmc_e = NV_READ(NV03_PMC_ENABLE);
+                       (void)pmc_e;
+                       status = NV_READ(NV04_PGRAPH_STATUS);
+                       if (!status)
+                               break;
+                       stopped = dev_priv->Engine.timer.read(dev);
+               /* It'll never wrap anyway... */
+               } while (stopped - started < 1000000000ULL);
+               if (status)
+                       DRM_ERROR("timed out with status 0x%08x\n",
+                                 status);
+       }
        }
 }
 
diff --git a/shared-core/nouveau_swmthd.c b/shared-core/nouveau_swmthd.c
new file mode 100644 (file)
index 0000000..66ef623
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2007 Arthur Huillet.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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:
+ *   Arthur Huillet <arthur.huillet AT free DOT fr>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_reg.h"
+
+/*TODO: add a "card_type" attribute*/
+typedef struct{
+       uint32_t oclass; /* object class for this software method */
+       uint32_t mthd; /* method number */
+       void (*method_code)(struct drm_device *dev, uint32_t oclass, uint32_t mthd); /* pointer to the function that does the work */
+ } nouveau_software_method_t;
+
+
+ /* This function handles the NV04 setcontext software methods.
+One function for all because they are very similar.*/
+static void nouveau_NV04_setcontext_sw_method(struct drm_device *dev, uint32_t oclass, uint32_t mthd) {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t inst_loc = NV_READ(NV04_PGRAPH_CTX_SWITCH4) & 0xFFFF;
+       uint32_t value_to_set = 0, bit_to_set = 0;
+
+       switch ( oclass ) {
+               case 0x4a:
+                       switch ( mthd ) {
+                               case 0x188 :
+                               case 0x18c :
+                                       bit_to_set = 0;
+                                       break;
+                               case 0x198 :
+                                       bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
+                                       break;
+                               case 0x2fc :
+                                       bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
+                                       break;
+                               default : ;
+                               };
+                       break;
+               case 0x5c:
+                       switch ( mthd ) {
+                               case 0x184:
+                                       bit_to_set = 1 << 13; /*USER_CLIP_ENABLE*/
+                                       break;
+                               case 0x188:
+                               case 0x18c:
+                                       bit_to_set = 0;
+                                       break;
+                               case 0x198:
+                                       bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
+                                       break;
+                               case 0x2fc :
+                                       bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
+                                       break;
+                       };
+                       break;
+               case 0x5f:
+                       switch ( mthd ) {
+                               case 0x184 :
+                                       bit_to_set = 1 << 12; /*CHROMA_KEY_ENABLE*/
+                                       break;
+                               case 0x188 :
+                                       bit_to_set = 1 << 13; /*USER_CLIP_ENABLE*/
+                                       break;
+                               case 0x18c :
+                               case 0x190 :
+                                       bit_to_set = 0;
+                                       break;
+                               case 0x19c :
+                                       bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
+                                       break;
+                               case 0x2fc :
+                                       bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
+                                       break;
+                       };
+                       break;
+               case 0x61:
+                       switch ( mthd ) {
+                               case 0x188 :
+                                       bit_to_set = 1 << 13; /*USER_CLIP_ENABLE*/
+                                       break;
+                               case 0x18c :
+                               case 0x190 :
+                                       bit_to_set = 0;
+                                       break;
+                               case 0x19c :
+                                       bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
+                                       break;
+                               case 0x2fc :
+                                       bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; /*PATCH_CONFIG = NV04_PGRAPH_TRAPPED_DATA*/
+                                       break;
+                       };
+                       break;
+               case 0x77:
+                       switch ( mthd ) {
+                               case 0x198 :
+                                       bit_to_set = 1 << 24; /*PATCH_STATUS_VALID*/
+                                       break;
+                               case 0x304 :
+                                       bit_to_set = NV_READ(NV04_PGRAPH_TRAPPED_DATA) << 15; //PATCH_CONFIG
+                                       break;
+                       };
+                       break;
+               default :;
+               };
+
+       value_to_set = (NV_READ(0x00700000 | inst_loc << 4))| bit_to_set;
+
+       /*RAMIN*/
+       nouveau_wait_for_idle(dev);
+       NV_WRITE(0x00700000 | inst_loc << 4, value_to_set);
+
+       /*DRM_DEBUG("CTX_SWITCH1 value is %#x\n", NV_READ(NV04_PGRAPH_CTX_SWITCH1));*/
+       NV_WRITE(NV04_PGRAPH_CTX_SWITCH1, value_to_set);
+
+       /*DRM_DEBUG("CTX_CACHE1 + xxx value is %#x\n", NV_READ(NV04_PGRAPH_CTX_CACHE1 + (((NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7) << 2)));*/
+       NV_WRITE(NV04_PGRAPH_CTX_CACHE1 + (((NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7) << 2), value_to_set);
+}
+
+ nouveau_software_method_t nouveau_sw_methods[] = {
+       /*NV04 context software methods*/
+       { 0x4a, 0x188, nouveau_NV04_setcontext_sw_method },
+       { 0x4a, 0x18c, nouveau_NV04_setcontext_sw_method },
+       { 0x4a, 0x198, nouveau_NV04_setcontext_sw_method },
+       { 0x4a, 0x2fc, nouveau_NV04_setcontext_sw_method },
+       { 0x5c, 0x184, nouveau_NV04_setcontext_sw_method },
+       { 0x5c, 0x188, nouveau_NV04_setcontext_sw_method },
+       { 0x5c, 0x18c, nouveau_NV04_setcontext_sw_method },
+       { 0x5c, 0x198, nouveau_NV04_setcontext_sw_method },
+       { 0x5c, 0x2fc, nouveau_NV04_setcontext_sw_method },
+       { 0x5f, 0x184, nouveau_NV04_setcontext_sw_method },
+       { 0x5f, 0x188, nouveau_NV04_setcontext_sw_method },
+       { 0x5f, 0x18c, nouveau_NV04_setcontext_sw_method },
+       { 0x5f, 0x190, nouveau_NV04_setcontext_sw_method },
+       { 0x5f, 0x19c, nouveau_NV04_setcontext_sw_method },
+       { 0x5f, 0x2fc, nouveau_NV04_setcontext_sw_method },
+       { 0x61, 0x188, nouveau_NV04_setcontext_sw_method },
+       { 0x61, 0x18c, nouveau_NV04_setcontext_sw_method },
+       { 0x61, 0x190, nouveau_NV04_setcontext_sw_method },
+       { 0x61, 0x19c, nouveau_NV04_setcontext_sw_method },
+       { 0x61, 0x2fc, nouveau_NV04_setcontext_sw_method },
+       { 0x77, 0x198, nouveau_NV04_setcontext_sw_method },
+       { 0x77, 0x304, nouveau_NV04_setcontext_sw_method },
+       /*terminator*/
+       { 0x0, 0x0, NULL, },
+ };
+
+ int nouveau_sw_method_execute(struct drm_device *dev, uint32_t oclass, uint32_t method) {
+       int i = 0;
+       while ( nouveau_sw_methods[ i ] . method_code != NULL )
+               {
+               if ( nouveau_sw_methods[ i ] . oclass == oclass && nouveau_sw_methods[ i ] . mthd == method )
+                       {
+                       nouveau_sw_methods[ i ] . method_code(dev, oclass, method);
+                       return 0;
+                       }
+               i ++;
+               }
+
+        return 1;
+ }
+
+
diff --git a/shared-core/nouveau_swmthd.h b/shared-core/nouveau_swmthd.h
new file mode 100644 (file)
index 0000000..df8c740
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007 Arthur Huillet.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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:
+ *   Arthur Huillet <arthur.huillet AT free DOT fr>
+ */
+
+int nouveau_sw_method_execute(struct drm_device *dev, uint32_t oclass, uint32_t method); /* execute the given software method, returns 0 on success */
+
index 06b1c99..534fb50 100644 (file)
@@ -4,9 +4,9 @@
 #include "nouveau_drm.h"
 
 int
-nv04_fb_init(drm_device_t *dev)
+nv04_fb_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        /* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows
         * nvidia reading PFB_CFG_0, then writing back its original value.
@@ -18,7 +18,7 @@ nv04_fb_init(drm_device_t *dev)
 }
 
 void
-nv04_fb_takedown(drm_device_t *dev)
+nv04_fb_takedown(struct drm_device *dev)
 {
 }
 
diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c
new file mode 100644 (file)
index 0000000..d750ced
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+#define RAMFC_WR(offset,val) INSTANCE_WR(chan->ramfc->gpuobj, \
+                                        NV04_RAMFC_##offset/4, (val))
+#define RAMFC_RD(offset)     INSTANCE_RD(chan->ramfc->gpuobj, \
+                                        NV04_RAMFC_##offset/4)
+#define NV04_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV04_RAMFC__SIZE))
+#define NV04_RAMFC__SIZE 32
+
+int
+nv04_fifo_create_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0,
+                                               NV04_RAMFC__SIZE,
+                                               NVOBJ_FLAG_ZERO_ALLOC |
+                                               NVOBJ_FLAG_ZERO_FREE,
+                                               NULL, &chan->ramfc)))
+               return ret;
+
+       /* Setup initial state */
+       RAMFC_WR(DMA_PUT, chan->pushbuf_base);
+       RAMFC_WR(DMA_GET, chan->pushbuf_base);
+       RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4);
+       RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+                            NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+                            NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+                            NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+                            0));
+
+       /* enable the fifo dma operation */
+       NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE) | (1<<chan->id));
+       return 0;
+}
+
+void
+nv04_fifo_destroy_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       
+       NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<chan->id));
+
+       nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+}
+
+int
+nv04_fifo_load_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | chan->id);
+
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, RAMFC_RD(DMA_GET));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, RAMFC_RD(DMA_PUT));
+       
+       tmp = RAMFC_RD(DMA_INSTANCE);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16);
+       
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, RAMFC_RD(DMA_STATE));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, RAMFC_RD(DMA_FETCH));
+       NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, RAMFC_RD(ENGINE));
+       NV_WRITE(NV04_PFIFO_CACHE1_PULL1, RAMFC_RD(PULL1_ENGINE));
+
+       /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
+       tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+       return 0;
+}
+
+int
+nv04_fifo_save_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       RAMFC_WR(DMA_PUT, NV04_PFIFO_CACHE1_DMA_PUT);
+       RAMFC_WR(DMA_GET, NV04_PFIFO_CACHE1_DMA_GET);
+
+       tmp  = NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
+       tmp |= NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE);
+       RAMFC_WR(DMA_INSTANCE, tmp);
+
+       RAMFC_WR(DMA_STATE, NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
+       RAMFC_WR(DMA_FETCH, NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
+       RAMFC_WR(ENGINE, NV_READ(NV04_PFIFO_CACHE1_ENGINE));
+       RAMFC_WR(PULL1_ENGINE, NV_READ(NV04_PFIFO_CACHE1_PULL1));
+       
+       return 0;
+}
+
index 0cd4d3b..cffa3e4 100644 (file)
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
 
-struct reg_interval
-{
-       uint32_t reg;
-       int number;
-} nv04_graph_ctx_regs [] = {
-       {NV04_PGRAPH_CTX_SWITCH1,1},
-       {NV04_PGRAPH_CTX_SWITCH2,1},
-       {NV04_PGRAPH_CTX_SWITCH3,1},
-       {NV04_PGRAPH_CTX_SWITCH4,1},
-       {NV04_PGRAPH_CTX_CACHE1,1},
-       {NV04_PGRAPH_CTX_CACHE2,1},
-       {NV04_PGRAPH_CTX_CACHE3,1},
-       {NV04_PGRAPH_CTX_CACHE4,1},
-       {0x00400184,1},
-       {0x004001a4,1},
-       {0x004001c4,1},
-       {0x004001e4,1},
-       {0x00400188,1},
-       {0x004001a8,1},
-       {0x004001c8,1},
-       {0x004001e8,1},
-       {0x0040018c,1},
-       {0x004001ac,1},
-       {0x004001cc,1},
-       {0x004001ec,1},
-       {0x00400190,1},
-       {0x004001b0,1},
-       {0x004001d0,1},
-       {0x004001f0,1},
-       {0x00400194,1},
-       {0x004001b4,1},
-       {0x004001d4,1},
-       {0x004001f4,1},
-       {0x00400198,1},
-       {0x004001b8,1},
-       {0x004001d8,1},
-       {0x004001f8,1},
-       {0x0040019c,1},
-       {0x004001bc,1},
-       {0x004001dc,1},
-       {0x004001fc,1},
-       {0x00400174,1},
-       {NV04_PGRAPH_DMA_START_0,1},
-       {NV04_PGRAPH_DMA_START_1,1},
-       {NV04_PGRAPH_DMA_LENGTH,1},
-       {NV04_PGRAPH_DMA_MISC,1},
-       {NV04_PGRAPH_DMA_PITCH,1},
-       {NV04_PGRAPH_BOFFSET0,1},
-       {NV04_PGRAPH_BBASE0,1},
-       {NV04_PGRAPH_BLIMIT0,1},
-       {NV04_PGRAPH_BOFFSET1,1},
-       {NV04_PGRAPH_BBASE1,1},
-       {NV04_PGRAPH_BLIMIT1,1},
-       {NV04_PGRAPH_BOFFSET2,1},
-       {NV04_PGRAPH_BBASE2,1},
-       {NV04_PGRAPH_BLIMIT2,1},
-       {NV04_PGRAPH_BOFFSET3,1},
-       {NV04_PGRAPH_BBASE3,1},
-       {NV04_PGRAPH_BLIMIT3,1},
-       {NV04_PGRAPH_BOFFSET4,1},
-       {NV04_PGRAPH_BBASE4,1},
-       {NV04_PGRAPH_BLIMIT4,1},
-       {NV04_PGRAPH_BOFFSET5,1},
-       {NV04_PGRAPH_BBASE5,1},
-       {NV04_PGRAPH_BLIMIT5,1},
-       {NV04_PGRAPH_BPITCH0,1},
-       {NV04_PGRAPH_BPITCH1,1},
-       {NV04_PGRAPH_BPITCH2,1},
-       {NV04_PGRAPH_BPITCH3,1},
-       {NV04_PGRAPH_BPITCH4,1},
-       {NV04_PGRAPH_SURFACE,1},
-       {NV04_PGRAPH_STATE,1},
-       {NV04_PGRAPH_BSWIZZLE2,1},
-       {NV04_PGRAPH_BSWIZZLE5,1},
-       {NV04_PGRAPH_BPIXEL,1},
-       {NV04_PGRAPH_NOTIFY,1},
-       {NV04_PGRAPH_PATT_COLOR0,1},
-       {NV04_PGRAPH_PATT_COLOR1,1},
-       {NV04_PGRAPH_PATT_COLORRAM,64},
-       {NV04_PGRAPH_PATTERN,1},
-       {0x0040080c,1},
-       {NV04_PGRAPH_PATTERN_SHAPE,1},
-       {0x00400600,1},
-       {NV04_PGRAPH_ROP3,1},
-       {NV04_PGRAPH_CHROMA,1},
-       {NV04_PGRAPH_BETA_AND,1},
-       {NV04_PGRAPH_BETA_PREMULT,1},
-       {NV04_PGRAPH_CONTROL0,1},
-       {NV04_PGRAPH_CONTROL1,1},
-       {NV04_PGRAPH_CONTROL2,1},
-       {NV04_PGRAPH_BLEND,1},
-       {NV04_PGRAPH_STORED_FMT,1},
-       {NV04_PGRAPH_SOURCE_COLOR,1},
-       {0x00400560,1},
-       {0x00400568,1},
-       {0x00400564,1},
-       {0x0040056c,1},
-       {0x00400400,1},
-       {0x00400480,1},
-       {0x00400404,1},
-       {0x00400484,1},
-       {0x00400408,1},
-       {0x00400488,1},
-       {0x0040040c,1},
-       {0x0040048c,1},
-       {0x00400410,1},
-       {0x00400490,1},
-       {0x00400414,1},
-       {0x00400494,1},
-       {0x00400418,1},
-       {0x00400498,1},
-       {0x0040041c,1},
-       {0x0040049c,1},
-       {0x00400420,1},
-       {0x004004a0,1},
-       {0x00400424,1},
-       {0x004004a4,1},
-       {0x00400428,1},
-       {0x004004a8,1},
-       {0x0040042c,1},
-       {0x004004ac,1},
-       {0x00400430,1},
-       {0x004004b0,1},
-       {0x00400434,1},
-       {0x004004b4,1},
-       {0x00400438,1},
-       {0x004004b8,1},
-       {0x0040043c,1},
-       {0x004004bc,1},
-       {0x00400440,1},
-       {0x004004c0,1},
-       {0x00400444,1},
-       {0x004004c4,1},
-       {0x00400448,1},
-       {0x004004c8,1},
-       {0x0040044c,1},
-       {0x004004cc,1},
-       {0x00400450,1},
-       {0x004004d0,1},
-       {0x00400454,1},
-       {0x004004d4,1},
-       {0x00400458,1},
-       {0x004004d8,1},
-       {0x0040045c,1},
-       {0x004004dc,1},
-       {0x00400460,1},
-       {0x004004e0,1},
-       {0x00400464,1},
-       {0x004004e4,1},
-       {0x00400468,1},
-       {0x004004e8,1},
-       {0x0040046c,1},
-       {0x004004ec,1},
-       {0x00400470,1},
-       {0x004004f0,1},
-       {0x00400474,1},
-       {0x004004f4,1},
-       {0x00400478,1},
-       {0x004004f8,1},
-       {0x0040047c,1},
-       {0x004004fc,1},
-       {0x0040053c,1},
-       {0x00400544,1},
-       {0x00400540,1},
-       {0x00400548,1},
-       {0x00400560,1},
-       {0x00400568,1},
-       {0x00400564,1},
-       {0x0040056c,1},
-       {0x00400534,1},
-       {0x00400538,1},
-       {0x00400514,1},
-       {0x00400518,1},
-       {0x0040051c,1},
-       {0x00400520,1},
-       {0x00400524,1},
-       {0x00400528,1},
-       {0x0040052c,1},
-       {0x00400530,1},
-       {0x00400d00,1},
-       {0x00400d40,1},
-       {0x00400d80,1},
-       {0x00400d04,1},
-       {0x00400d44,1},
-       {0x00400d84,1},
-       {0x00400d08,1},
-       {0x00400d48,1},
-       {0x00400d88,1},
-       {0x00400d0c,1},
-       {0x00400d4c,1},
-       {0x00400d8c,1},
-       {0x00400d10,1},
-       {0x00400d50,1},
-       {0x00400d90,1},
-       {0x00400d14,1},
-       {0x00400d54,1},
-       {0x00400d94,1},
-       {0x00400d18,1},
-       {0x00400d58,1},
-       {0x00400d98,1},
-       {0x00400d1c,1},
-       {0x00400d5c,1},
-       {0x00400d9c,1},
-       {0x00400d20,1},
-       {0x00400d60,1},
-       {0x00400da0,1},
-       {0x00400d24,1},
-       {0x00400d64,1},
-       {0x00400da4,1},
-       {0x00400d28,1},
-       {0x00400d68,1},
-       {0x00400da8,1},
-       {0x00400d2c,1},
-       {0x00400d6c,1},
-       {0x00400dac,1},
-       {0x00400d30,1},
-       {0x00400d70,1},
-       {0x00400db0,1},
-       {0x00400d34,1},
-       {0x00400d74,1},
-       {0x00400db4,1},
-       {0x00400d38,1},
-       {0x00400d78,1},
-       {0x00400db8,1},
-       {0x00400d3c,1},
-       {0x00400d7c,1},
-       {0x00400dbc,1},
-       {0x00400590,1},
-       {0x00400594,1},
-       {0x00400598,1},
-       {0x0040059c,1},
-       {0x004005a8,1},
-       {0x004005ac,1},
-       {0x004005b0,1},
-       {0x004005b4,1},
-       {0x004005c0,1},
-       {0x004005c4,1},
-       {0x004005c8,1},
-       {0x004005cc,1},
-       {0x004005d0,1},
-       {0x004005d4,1},
-       {0x004005d8,1},
-       {0x004005dc,1},
-       {0x004005e0,1},
-       {NV04_PGRAPH_PASSTHRU_0,1},
-       {NV04_PGRAPH_PASSTHRU_1,1},
-       {NV04_PGRAPH_PASSTHRU_2,1},
-       {NV04_PGRAPH_DVD_COLORFMT,1},
-       {NV04_PGRAPH_SCALED_FORMAT,1},
-       {NV04_PGRAPH_MISC24_0,1},
-       {NV04_PGRAPH_MISC24_1,1},
-       {NV04_PGRAPH_MISC24_2,1},
-       {0x00400500,1},
-       {0x00400504,1},
-       {NV04_PGRAPH_VALID1,1},
-       {NV04_PGRAPH_VALID2,1}
+static uint32_t nv04_graph_ctx_regs [] = {
+       NV04_PGRAPH_CTX_SWITCH1,
+       NV04_PGRAPH_CTX_SWITCH2,
+       NV04_PGRAPH_CTX_SWITCH3,
+       NV04_PGRAPH_CTX_SWITCH4,
+       NV04_PGRAPH_CTX_CACHE1,
+       NV04_PGRAPH_CTX_CACHE2,
+       NV04_PGRAPH_CTX_CACHE3,
+       NV04_PGRAPH_CTX_CACHE4,
+       0x00400184,
+       0x004001a4,
+       0x004001c4,
+       0x004001e4,
+       0x00400188,
+       0x004001a8,
+       0x004001c8,
+       0x004001e8,
+       0x0040018c,
+       0x004001ac,
+       0x004001cc,
+       0x004001ec,
+       0x00400190,
+       0x004001b0,
+       0x004001d0,
+       0x004001f0,
+       0x00400194,
+       0x004001b4,
+       0x004001d4,
+       0x004001f4,
+       0x00400198,
+       0x004001b8,
+       0x004001d8,
+       0x004001f8,
+       0x0040019c,
+       0x004001bc,
+       0x004001dc,
+       0x004001fc,
+       0x00400174,
+       NV04_PGRAPH_DMA_START_0,
+       NV04_PGRAPH_DMA_START_1,
+       NV04_PGRAPH_DMA_LENGTH,
+       NV04_PGRAPH_DMA_MISC,
+       NV04_PGRAPH_DMA_PITCH,
+       NV04_PGRAPH_BOFFSET0,
+       NV04_PGRAPH_BBASE0,
+       NV04_PGRAPH_BLIMIT0,
+       NV04_PGRAPH_BOFFSET1,
+       NV04_PGRAPH_BBASE1,
+       NV04_PGRAPH_BLIMIT1,
+       NV04_PGRAPH_BOFFSET2,
+       NV04_PGRAPH_BBASE2,
+       NV04_PGRAPH_BLIMIT2,
+       NV04_PGRAPH_BOFFSET3,
+       NV04_PGRAPH_BBASE3,
+       NV04_PGRAPH_BLIMIT3,
+       NV04_PGRAPH_BOFFSET4,
+       NV04_PGRAPH_BBASE4,
+       NV04_PGRAPH_BLIMIT4,
+       NV04_PGRAPH_BOFFSET5,
+       NV04_PGRAPH_BBASE5,
+       NV04_PGRAPH_BLIMIT5,
+       NV04_PGRAPH_BPITCH0,
+       NV04_PGRAPH_BPITCH1,
+       NV04_PGRAPH_BPITCH2,
+       NV04_PGRAPH_BPITCH3,
+       NV04_PGRAPH_BPITCH4,
+       NV04_PGRAPH_SURFACE,
+       NV04_PGRAPH_STATE,
+       NV04_PGRAPH_BSWIZZLE2,
+       NV04_PGRAPH_BSWIZZLE5,
+       NV04_PGRAPH_BPIXEL,
+       NV04_PGRAPH_NOTIFY,
+       NV04_PGRAPH_PATT_COLOR0,
+       NV04_PGRAPH_PATT_COLOR1,
+       NV04_PGRAPH_PATT_COLORRAM+0x00,
+       NV04_PGRAPH_PATT_COLORRAM+0x01,
+       NV04_PGRAPH_PATT_COLORRAM+0x02,
+       NV04_PGRAPH_PATT_COLORRAM+0x03,
+       NV04_PGRAPH_PATT_COLORRAM+0x04,
+       NV04_PGRAPH_PATT_COLORRAM+0x05,
+       NV04_PGRAPH_PATT_COLORRAM+0x06,
+       NV04_PGRAPH_PATT_COLORRAM+0x07,
+       NV04_PGRAPH_PATT_COLORRAM+0x08,
+       NV04_PGRAPH_PATT_COLORRAM+0x09,
+       NV04_PGRAPH_PATT_COLORRAM+0x0A,
+       NV04_PGRAPH_PATT_COLORRAM+0x0B,
+       NV04_PGRAPH_PATT_COLORRAM+0x0C,
+       NV04_PGRAPH_PATT_COLORRAM+0x0D,
+       NV04_PGRAPH_PATT_COLORRAM+0x0E,
+       NV04_PGRAPH_PATT_COLORRAM+0x0F,
+       NV04_PGRAPH_PATT_COLORRAM+0x10,
+       NV04_PGRAPH_PATT_COLORRAM+0x11,
+       NV04_PGRAPH_PATT_COLORRAM+0x12,
+       NV04_PGRAPH_PATT_COLORRAM+0x13,
+       NV04_PGRAPH_PATT_COLORRAM+0x14,
+       NV04_PGRAPH_PATT_COLORRAM+0x15,
+       NV04_PGRAPH_PATT_COLORRAM+0x16,
+       NV04_PGRAPH_PATT_COLORRAM+0x17,
+       NV04_PGRAPH_PATT_COLORRAM+0x18,
+       NV04_PGRAPH_PATT_COLORRAM+0x19,
+       NV04_PGRAPH_PATT_COLORRAM+0x1A,
+       NV04_PGRAPH_PATT_COLORRAM+0x1B,
+       NV04_PGRAPH_PATT_COLORRAM+0x1C,
+       NV04_PGRAPH_PATT_COLORRAM+0x1D,
+       NV04_PGRAPH_PATT_COLORRAM+0x1E,
+       NV04_PGRAPH_PATT_COLORRAM+0x1F,
+       NV04_PGRAPH_PATT_COLORRAM+0x20,
+       NV04_PGRAPH_PATT_COLORRAM+0x21,
+       NV04_PGRAPH_PATT_COLORRAM+0x22,
+       NV04_PGRAPH_PATT_COLORRAM+0x23,
+       NV04_PGRAPH_PATT_COLORRAM+0x24,
+       NV04_PGRAPH_PATT_COLORRAM+0x25,
+       NV04_PGRAPH_PATT_COLORRAM+0x26,
+       NV04_PGRAPH_PATT_COLORRAM+0x27,
+       NV04_PGRAPH_PATT_COLORRAM+0x28,
+       NV04_PGRAPH_PATT_COLORRAM+0x29,
+       NV04_PGRAPH_PATT_COLORRAM+0x2A,
+       NV04_PGRAPH_PATT_COLORRAM+0x2B,
+       NV04_PGRAPH_PATT_COLORRAM+0x2C,
+       NV04_PGRAPH_PATT_COLORRAM+0x2D,
+       NV04_PGRAPH_PATT_COLORRAM+0x2E,
+       NV04_PGRAPH_PATT_COLORRAM+0x2F,
+       NV04_PGRAPH_PATT_COLORRAM+0x30,
+       NV04_PGRAPH_PATT_COLORRAM+0x31,
+       NV04_PGRAPH_PATT_COLORRAM+0x32,
+       NV04_PGRAPH_PATT_COLORRAM+0x33,
+       NV04_PGRAPH_PATT_COLORRAM+0x34,
+       NV04_PGRAPH_PATT_COLORRAM+0x35,
+       NV04_PGRAPH_PATT_COLORRAM+0x36,
+       NV04_PGRAPH_PATT_COLORRAM+0x37,
+       NV04_PGRAPH_PATT_COLORRAM+0x38,
+       NV04_PGRAPH_PATT_COLORRAM+0x39,
+       NV04_PGRAPH_PATT_COLORRAM+0x3A,
+       NV04_PGRAPH_PATT_COLORRAM+0x3B,
+       NV04_PGRAPH_PATT_COLORRAM+0x3C,
+       NV04_PGRAPH_PATT_COLORRAM+0x3D,
+       NV04_PGRAPH_PATT_COLORRAM+0x3E,
+       NV04_PGRAPH_PATT_COLORRAM+0x3F,
+       NV04_PGRAPH_PATTERN,
+       0x0040080c,
+       NV04_PGRAPH_PATTERN_SHAPE,
+       0x00400600,
+       NV04_PGRAPH_ROP3,
+       NV04_PGRAPH_CHROMA,
+       NV04_PGRAPH_BETA_AND,
+       NV04_PGRAPH_BETA_PREMULT,
+       NV04_PGRAPH_CONTROL0,
+       NV04_PGRAPH_CONTROL1,
+       NV04_PGRAPH_CONTROL2,
+       NV04_PGRAPH_BLEND,
+       NV04_PGRAPH_STORED_FMT,
+       NV04_PGRAPH_SOURCE_COLOR,
+       0x00400560,
+       0x00400568,
+       0x00400564,
+       0x0040056c,
+       0x00400400,
+       0x00400480,
+       0x00400404,
+       0x00400484,
+       0x00400408,
+       0x00400488,
+       0x0040040c,
+       0x0040048c,
+       0x00400410,
+       0x00400490,
+       0x00400414,
+       0x00400494,
+       0x00400418,
+       0x00400498,
+       0x0040041c,
+       0x0040049c,
+       0x00400420,
+       0x004004a0,
+       0x00400424,
+       0x004004a4,
+       0x00400428,
+       0x004004a8,
+       0x0040042c,
+       0x004004ac,
+       0x00400430,
+       0x004004b0,
+       0x00400434,
+       0x004004b4,
+       0x00400438,
+       0x004004b8,
+       0x0040043c,
+       0x004004bc,
+       0x00400440,
+       0x004004c0,
+       0x00400444,
+       0x004004c4,
+       0x00400448,
+       0x004004c8,
+       0x0040044c,
+       0x004004cc,
+       0x00400450,
+       0x004004d0,
+       0x00400454,
+       0x004004d4,
+       0x00400458,
+       0x004004d8,
+       0x0040045c,
+       0x004004dc,
+       0x00400460,
+       0x004004e0,
+       0x00400464,
+       0x004004e4,
+       0x00400468,
+       0x004004e8,
+       0x0040046c,
+       0x004004ec,
+       0x00400470,
+       0x004004f0,
+       0x00400474,
+       0x004004f4,
+       0x00400478,
+       0x004004f8,
+       0x0040047c,
+       0x004004fc,
+       0x0040053c,
+       0x00400544,
+       0x00400540,
+       0x00400548,
+       0x00400560,
+       0x00400568,
+       0x00400564,
+       0x0040056c,
+       0x00400534,
+       0x00400538,
+       0x00400514,
+       0x00400518,
+       0x0040051c,
+       0x00400520,
+       0x00400524,
+       0x00400528,
+       0x0040052c,
+       0x00400530,
+       0x00400d00,
+       0x00400d40,
+       0x00400d80,
+       0x00400d04,
+       0x00400d44,
+       0x00400d84,
+       0x00400d08,
+       0x00400d48,
+       0x00400d88,
+       0x00400d0c,
+       0x00400d4c,
+       0x00400d8c,
+       0x00400d10,
+       0x00400d50,
+       0x00400d90,
+       0x00400d14,
+       0x00400d54,
+       0x00400d94,
+       0x00400d18,
+       0x00400d58,
+       0x00400d98,
+       0x00400d1c,
+       0x00400d5c,
+       0x00400d9c,
+       0x00400d20,
+       0x00400d60,
+       0x00400da0,
+       0x00400d24,
+       0x00400d64,
+       0x00400da4,
+       0x00400d28,
+       0x00400d68,
+       0x00400da8,
+       0x00400d2c,
+       0x00400d6c,
+       0x00400dac,
+       0x00400d30,
+       0x00400d70,
+       0x00400db0,
+       0x00400d34,
+       0x00400d74,
+       0x00400db4,
+       0x00400d38,
+       0x00400d78,
+       0x00400db8,
+       0x00400d3c,
+       0x00400d7c,
+       0x00400dbc,
+       0x00400590,
+       0x00400594,
+       0x00400598,
+       0x0040059c,
+       0x004005a8,
+       0x004005ac,
+       0x004005b0,
+       0x004005b4,
+       0x004005c0,
+       0x004005c4,
+       0x004005c8,
+       0x004005cc,
+       0x004005d0,
+       0x004005d4,
+       0x004005d8,
+       0x004005dc,
+       0x004005e0,
+       NV04_PGRAPH_PASSTHRU_0,
+       NV04_PGRAPH_PASSTHRU_1,
+       NV04_PGRAPH_PASSTHRU_2,
+       NV04_PGRAPH_DVD_COLORFMT,
+       NV04_PGRAPH_SCALED_FORMAT,
+       NV04_PGRAPH_MISC24_0,
+       NV04_PGRAPH_MISC24_1,
+       NV04_PGRAPH_MISC24_2,
+       0x00400500,
+       0x00400504,
+       NV04_PGRAPH_VALID1,
+       NV04_PGRAPH_VALID2
+
 
+};
 
+struct graph_state {
+       int nv04[sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0])];
 };
 
-void nouveau_nv04_context_switch(drm_device_t *dev)
+void nouveau_nv04_context_switch(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int channel, channel_old, i, j, index;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_channel *next, *last;
+       int chid;
+
+       if (!dev) {
+               DRM_DEBUG("Invalid drm_device\n");
+               return;
+       }
+       dev_priv = dev->dev_private;
+       if (!dev_priv) {
+               DRM_DEBUG("Invalid drm_nouveau_private\n");
+               return;
+       }
+       if (!dev_priv->fifos) {
+               DRM_DEBUG("Invalid drm_nouveau_private->fifos\n");
+               return;
+       }
 
-       channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
-       channel_old = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+       chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
+       next = dev_priv->fifos[chid];
 
-       DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel);
+       if (!next) {
+               DRM_DEBUG("Invalid next channel\n");
+               return;
+       }
 
-       NV_WRITE(NV03_PFIFO_CACHES, 0x0);
+       chid = (NV_READ(NV04_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+       last = dev_priv->fifos[chid];
+
+       if (!last) {
+               DRM_DEBUG("WARNING: Invalid last channel, switch to %x\n",
+                         next->id);
+       } else {
+               DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",
+                        last->id, next->id);
+       }
+
+/*     NV_WRITE(NV03_PFIFO_CACHES, 0x0);
        NV_WRITE(NV04_PFIFO_CACHE0_PULL0, 0x0);
-       NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x0);
+       NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x0);*/
        NV_WRITE(NV04_PGRAPH_FIFO,0x0);
 
-       nouveau_wait_for_idle(dev);
+       if (last)
+               nv04_graph_save_context(last);
 
-       // save PGRAPH context
-       index=0;
-       for (i = 0; i<sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++)
-               for (j = 0; j<nv04_graph_ctx_regs[i].number; j++)
-               {
-                       dev_priv->fifos[channel_old].pgraph_ctx[index] = NV_READ(nv04_graph_ctx_regs[i].reg+j*4);
-                       index++;
-               }
+       nouveau_wait_for_idle(dev);
 
        NV_WRITE(NV04_PGRAPH_CTX_CONTROL, 0x10000000);
        NV_WRITE(NV04_PGRAPH_CTX_USER, (NV_READ(NV04_PGRAPH_CTX_USER) & 0xffffff) | (0x0f << 24));
 
-       // restore PGRAPH context
-       index=0;
-       for (i = 0; i<sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++)
-               for (j = 0; j<nv04_graph_ctx_regs[i].number; j++)
-               {
-                       NV_WRITE(nv04_graph_ctx_regs[i].reg+j*4, dev_priv->fifos[channel].pgraph_ctx[index]);
-                       index++;
-               }
+       nouveau_wait_for_idle(dev);
+
+       nv04_graph_load_context(next);
 
        NV_WRITE(NV04_PGRAPH_CTX_CONTROL, 0x10010100);
-       NV_WRITE(NV04_PGRAPH_CTX_USER, channel << 24);
+       NV_WRITE(NV04_PGRAPH_CTX_USER, next->id << 24);
        NV_WRITE(NV04_PGRAPH_FFINTFC_ST2, NV_READ(NV04_PGRAPH_FFINTFC_ST2)&0x000FFFFF);
 
-       NV_WRITE(NV04_PGRAPH_FIFO,0x0);
+/*     NV_WRITE(NV04_PGRAPH_FIFO,0x0);
        NV_WRITE(NV04_PFIFO_CACHE0_PULL0, 0x0);
        NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x1);
-       NV_WRITE(NV03_PFIFO_CACHES, 0x1);
+       NV_WRITE(NV03_PFIFO_CACHES, 0x1);*/
        NV_WRITE(NV04_PGRAPH_FIFO,0x1);
 }
 
-int nv04_graph_context_create(drm_device_t *dev, int channel) {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("nv04_graph_context_create %d\n", channel);
+int nv04_graph_create_context(struct nouveau_channel *chan) {
+       struct graph_state* pgraph_ctx;
+       DRM_DEBUG("nv04_graph_context_create %d\n", chan->id);
+
+       chan->pgraph_ctx = pgraph_ctx = drm_calloc(1, sizeof(*pgraph_ctx),
+                                             DRM_MEM_DRIVER);
 
-       memset(dev_priv->fifos[channel].pgraph_ctx, 0, sizeof(dev_priv->fifos[channel].pgraph_ctx));
+       if (pgraph_ctx == NULL)
+               return -ENOMEM;
 
        //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24;
-       dev_priv->fifos[channel].pgraph_ctx[0] = 0x0001ffff;
+       pgraph_ctx->nv04[0] = 0x0001ffff;
        /* is it really needed ??? */
        //dev_priv->fifos[channel].pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4);
        //dev_priv->fifos[channel].pgraph_ctx[2] = NV_READ(0x004006b0);
@@ -351,34 +436,68 @@ int nv04_graph_context_create(drm_device_t *dev, int channel) {
        return 0;
 }
 
+void nv04_graph_destroy_context(struct nouveau_channel *chan)
+{
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+
+       drm_free(pgraph_ctx, sizeof(*pgraph_ctx), DRM_MEM_DRIVER);
+       chan->pgraph_ctx = NULL;
+}
+
+int nv04_graph_load_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       int i;
+
+       for (i = 0; i < sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++)
+               NV_WRITE(nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]);
+
+       return 0;
+}
+
+int nv04_graph_save_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       int i;
 
-int nv04_graph_init(drm_device_t *dev) {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int i,sum=0;
+       for (i = 0; i < sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++)
+               pgraph_ctx->nv04[i] = NV_READ(nv04_graph_ctx_regs[i]);
+
+       return 0;
+}
+
+int nv04_graph_init(struct drm_device *dev) {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
                        ~NV_PMC_ENABLE_PGRAPH);
        NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
                         NV_PMC_ENABLE_PGRAPH);
 
-       // check the context is big enough
-       for ( i = 0 ; i<sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++)
-               sum+=nv04_graph_ctx_regs[i].number;
-       if ( sum*4>sizeof(dev_priv->fifos[0].pgraph_ctx) )
-               DRM_ERROR("pgraph_ctx too small\n");
-
-       NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
-       NV_WRITE(NV03_PGRAPH_INTR   , 0xFFFFFFFF);
-
-       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x000001FF);
-       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x1230C000);
-       NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x72111101);
-       NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x11D5F071);
-       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x0004FF31);
-       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x4004FF31 |
-                                   (0x00D00000) |
-                                   (1<<29) |
-                                   (1<<31));
+       /* Enable PGRAPH interrupts */
+       NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
+       NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
+
+       NV_WRITE(NV04_PGRAPH_VALID1, 0);
+       NV_WRITE(NV04_PGRAPH_VALID2, 0);
+       /*NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x000001FF);
+       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/
+       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x1231c000);
+       /*1231C000 blob, 001 haiku*/
+       //*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/
+       NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x72111100);
+       /*0x72111100 blob , 01 haiku*/
+       /*NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/
+       NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x11d5f071);
+       /*haiku same*/
+
+       /*NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/
+       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x10d4ff31);
+       /*haiku and blob 10d4*/
 
        NV_WRITE(NV04_PGRAPH_STATE        , 0xFFFFFFFF);
        NV_WRITE(NV04_PGRAPH_CTX_CONTROL  , 0x10010100);
@@ -391,7 +510,6 @@ int nv04_graph_init(drm_device_t *dev) {
        return 0;
 }
 
-void nv04_graph_takedown(drm_device_t *dev)
+void nv04_graph_takedown(struct drm_device *dev)
 {
 }
-
diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c
new file mode 100644 (file)
index 0000000..5a44645
--- /dev/null
@@ -0,0 +1,159 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+static void
+nv04_instmem_determine_amount(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
+
+       /* Figure out how much instance memory we need */
+       if (dev_priv->card_type >= NV_40) {
+               /* We'll want more instance memory than this on some NV4x cards.
+                * There's a 16MB aperture to play with that maps onto the end
+                * of vram.  For now, only reserve a small piece until we know
+                * more about what each chipset requires.
+                */
+               dev_priv->ramin_rsvd_vram = (1*1024* 1024);
+       } else {
+               /*XXX: what *are* the limits on <NV40 cards?, and does RAMIN
+                *     exist in vram on those cards as well?
+                */
+               dev_priv->ramin_rsvd_vram = (512*1024);
+       }
+       DRM_DEBUG("RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram>>10);
+
+       /* Clear all of it, except the BIOS image that's in the first 64KiB */
+       for (i=(64*1024); i<dev_priv->ramin_rsvd_vram; i+=4)
+               NV_WI32(i, 0x00000000);
+}
+
+static void
+nv04_instmem_configure_fixed_tables(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       /* FIFO hash table (RAMHT)
+        *   use 4k hash table at RAMIN+0x10000
+        *   TODO: extend the hash table
+        */
+       dev_priv->ramht_offset = 0x10000;
+       dev_priv->ramht_bits   = 9;
+       dev_priv->ramht_size   = (1 << dev_priv->ramht_bits);
+       DRM_DEBUG("RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset,
+                                                 dev_priv->ramht_size);
+
+       /* FIFO runout table (RAMRO) - 512k at 0x11200 */
+       dev_priv->ramro_offset = 0x11200;
+       dev_priv->ramro_size   = 512;
+       DRM_DEBUG("RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset,
+                                                 dev_priv->ramro_size);
+
+       /* FIFO context table (RAMFC)
+        *   NV40  : Not sure exactly how to position RAMFC on some cards,
+        *           0x30002 seems to position it at RAMIN+0x20000 on these
+        *           cards.  RAMFC is 4kb (32 fifos, 128byte entries).
+        *   Others: Position RAMFC at RAMIN+0x11400
+        */
+       switch(dev_priv->card_type)
+       {
+               case NV_40:
+               case NV_44:
+                       dev_priv->ramfc_offset = 0x20000;
+                       dev_priv->ramfc_size   = nouveau_fifo_number(dev) *
+                               nouveau_fifo_ctx_size(dev);
+                       break;
+               case NV_30:
+               case NV_20:
+               case NV_17:
+               case NV_11:
+               case NV_10:
+               case NV_04:
+               default:
+                       dev_priv->ramfc_offset = 0x11400;
+                       dev_priv->ramfc_size   = nouveau_fifo_number(dev) *
+                               nouveau_fifo_ctx_size(dev);
+                       break;
+       }
+       DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset,
+                                                 dev_priv->ramfc_size);
+}
+
+int nv04_instmem_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t offset;
+       int ret = 0;
+
+       nv04_instmem_determine_amount(dev);
+       nv04_instmem_configure_fixed_tables(dev);
+
+       /* Create a heap to manage RAMIN allocations, we don't allocate
+        * the space that was reserved for RAMHT/FC/RO.
+        */
+       offset = dev_priv->ramfc_offset + dev_priv->ramfc_size;
+
+       /* On my NV4E, there's *something* clobbering the 16KiB just after
+        * where we setup these fixed tables.  No idea what it is just yet,
+        * so reserve this space on all NV4X cards for now.
+        */
+       if (dev_priv->card_type >= NV_40)
+               offset += 16*1024;
+
+       ret = nouveau_mem_init_heap(&dev_priv->ramin_heap,
+                                   offset, dev_priv->ramin_rsvd_vram - offset);
+       if (ret) {
+               dev_priv->ramin_heap = NULL;
+               DRM_ERROR("Failed to init RAMIN heap\n");
+       }
+
+       return ret;
+}
+
+void
+nv04_instmem_takedown(struct drm_device *dev)
+{
+}
+
+int
+nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz)
+{
+       if (gpuobj->im_backing)
+               return -EINVAL;
+
+       return 0;
+}
+
+void
+nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (gpuobj && gpuobj->im_backing) {
+               if (gpuobj->im_bound)
+                       dev_priv->Engine.instmem.unbind(dev, gpuobj);
+               gpuobj->im_backing = NULL;
+       }       
+}
+
+int
+nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+       if (!gpuobj->im_pramin || gpuobj->im_bound)
+               return -EINVAL;
+
+       gpuobj->im_bound = 1;
+       return 0;
+}
+
+int
+nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+       if (gpuobj->im_bound == 0)
+               return -EINVAL;
+
+       gpuobj->im_bound = 0;
+       return 0;
+}
+
index 0e23efb..eee0c50 100644 (file)
@@ -4,22 +4,20 @@
 #include "nouveau_drm.h"
 
 int
-nv04_mc_init(drm_device_t *dev)
+nv04_mc_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        /* Power up everything, resetting each individual unit will
         * be done later if needed.
         */
        NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
 
-       NV_WRITE(NV03_PMC_INTR_EN_0, 0);
-
        return 0;
 }
 
 void
-nv04_mc_takedown(drm_device_t *dev)
+nv04_mc_takedown(struct drm_device *dev)
 {
 }
 
index a4b4e82..08a27f4 100644 (file)
@@ -4,9 +4,9 @@
 #include "nouveau_drm.h"
 
 int
-nv04_timer_init(drm_device_t *dev)
+nv04_timer_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
 
        NV_WRITE(NV04_PTIMER_INTR_EN_0, 0x00000000);
        NV_WRITE(NV04_PTIMER_INTR_0, 0xFFFFFFFF);
@@ -17,8 +17,29 @@ nv04_timer_init(drm_device_t *dev)
        return 0;
 }
 
+uint64_t
+nv04_timer_read(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t low;
+       /* From kmmio dumps on nv28 this looks like how the blob does this.
+        * It reads the high dword twice, before and after.
+        * The only explanation seems to be that the 64-bit timer counter
+        * advances between high and low dword reads and may corrupt the
+        * result. Not confirmed.
+        */
+       uint32_t high2 = NV_READ(NV04_PTIMER_TIME_1);
+       uint32_t high1;
+       do {
+               high1 = high2;
+               low = NV_READ(NV04_PTIMER_TIME_0);
+               high2 = NV_READ(NV04_PTIMER_TIME_1);
+       } while(high1 != high2);
+       return (((uint64_t)high2) << 32) | (uint64_t)low;
+}
+
 void
-nv04_timer_takedown(drm_device_t *dev)
+nv04_timer_takedown(struct drm_device *dev)
 {
 }
 
index e8336a2..7fff5b3 100644 (file)
@@ -4,9 +4,9 @@
 #include "nouveau_drm.h"
 
 int
-nv10_fb_init(drm_device_t *dev)
+nv10_fb_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t fb_bar_size;
        int i;
 
@@ -20,7 +20,7 @@ nv10_fb_init(drm_device_t *dev)
 }
 
 void
-nv10_fb_takedown(drm_device_t *dev)
+nv10_fb_takedown(struct drm_device *dev)
 {
 }
 
diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c
new file mode 100644 (file)
index 0000000..c86725d
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+
+#define RAMFC_WR(offset,val) INSTANCE_WR(chan->ramfc->gpuobj, \
+                                        NV10_RAMFC_##offset/4, (val))
+#define RAMFC_RD(offset)     INSTANCE_RD(chan->ramfc->gpuobj, \
+                                        NV10_RAMFC_##offset/4)
+#define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE))
+#define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32)
+
+int
+nv10_fifo_create_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0,
+                                               NV10_RAMFC__SIZE,
+                                               NVOBJ_FLAG_ZERO_ALLOC |
+                                               NVOBJ_FLAG_ZERO_FREE,
+                                               NULL, &chan->ramfc)))
+               return ret;
+
+       /* Fill entries that are seen filled in dumps of nvidia driver just
+        * after channel's is put into DMA mode
+        */
+       RAMFC_WR(DMA_PUT       , chan->pushbuf_base);
+       RAMFC_WR(DMA_GET       , chan->pushbuf_base);
+       RAMFC_WR(DMA_INSTANCE  , chan->pushbuf->instance >> 4);
+       RAMFC_WR(DMA_FETCH     , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+                                NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+                                NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+                                NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+                                0);
+
+       /* enable the fifo dma operation */
+       NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<chan->id));
+       return 0;
+}
+
+void
+nv10_fifo_destroy_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<chan->id));
+
+       nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+}
+
+int
+nv10_fifo_load_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       NV_WRITE(NV03_PFIFO_CACHE1_PUSH1            , 0x00000100 | chan->id);
+
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET          , RAMFC_RD(DMA_GET));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT          , RAMFC_RD(DMA_PUT));
+       NV_WRITE(NV10_PFIFO_CACHE1_REF_CNT          , RAMFC_RD(REF_CNT));
+
+       tmp = RAMFC_RD(DMA_INSTANCE);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE     , tmp & 0xFFFF);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT       , tmp >> 16);
+
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE        , RAMFC_RD(DMA_STATE));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH        , RAMFC_RD(DMA_FETCH));
+       NV_WRITE(NV04_PFIFO_CACHE1_ENGINE           , RAMFC_RD(ENGINE));
+       NV_WRITE(NV04_PFIFO_CACHE1_PULL1            , RAMFC_RD(PULL1_ENGINE));
+
+       if (dev_priv->chipset >= 0x17) {
+               NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_VALUE,
+                        RAMFC_RD(ACQUIRE_VALUE));
+               NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP,
+                        RAMFC_RD(ACQUIRE_TIMESTAMP));
+               NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT,
+                        RAMFC_RD(ACQUIRE_TIMEOUT));
+               NV_WRITE(NV10_PFIFO_CACHE1_SEMAPHORE,
+                        RAMFC_RD(SEMAPHORE));
+               NV_WRITE(NV10_PFIFO_CACHE1_DMA_SUBROUTINE,
+                        RAMFC_RD(DMA_SUBROUTINE));
+       }
+
+       /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
+       tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+       return 0;
+}
+
+int
+nv10_fifo_save_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       RAMFC_WR(DMA_PUT          , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
+       RAMFC_WR(DMA_GET          , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+       RAMFC_WR(REF_CNT          , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
+
+       tmp  = NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE) & 0xFFFF;
+       tmp |= (NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16);
+       RAMFC_WR(DMA_INSTANCE     , tmp);
+
+       RAMFC_WR(DMA_STATE        , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
+       RAMFC_WR(DMA_FETCH        , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
+       RAMFC_WR(ENGINE           , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
+       RAMFC_WR(PULL1_ENGINE     , NV_READ(NV04_PFIFO_CACHE1_PULL1));
+
+       if (dev_priv->chipset >= 0x17) {
+               RAMFC_WR(ACQUIRE_VALUE,
+                        NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
+               RAMFC_WR(ACQUIRE_TIMESTAMP,
+                        NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
+               RAMFC_WR(ACQUIRE_TIMEOUT,
+                        NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
+               RAMFC_WR(SEMAPHORE,
+                        NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
+               RAMFC_WR(DMA_SUBROUTINE,
+                        NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+       }
+
+       return 0;
+}
+
index fb18970..c6319b8 100644 (file)
 #include "nouveau_drm.h"
 #include "nouveau_drv.h"
 
+#define NV10_FIFO_NUMBER 32
+
+struct pipe_state {
+       uint32_t pipe_0x0000[0x040/4];
+       uint32_t pipe_0x0040[0x010/4];
+       uint32_t pipe_0x0200[0x0c0/4];
+       uint32_t pipe_0x4400[0x080/4];
+       uint32_t pipe_0x6400[0x3b0/4];
+       uint32_t pipe_0x6800[0x2f0/4];
+       uint32_t pipe_0x6c00[0x030/4];
+       uint32_t pipe_0x7000[0x130/4];
+       uint32_t pipe_0x7400[0x0c0/4];
+       uint32_t pipe_0x7800[0x0c0/4];
+};
 
-static void nv10_praph_pipe(drm_device_t *dev) {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int i;
-
-       nouveau_wait_for_idle(dev);
-       /* XXX check haiku comments */
-       NV_WRITE(NV10_PGRAPH_XFMODE0, 0x10000000);
-       NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
-       for (i = 0; i < 4; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       for (i = 0; i < 4; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
-       
-       for (i = 0; i < 3; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
-       for (i = 0; i < 3; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000008);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000200);
-       for (i = 0; i < 48; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       nouveau_wait_for_idle(dev);
-
-       NV_WRITE(NV10_PGRAPH_XFMODE0, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006400);
-       for (i = 0; i < 211; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x40000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006800);
-       for (i = 0; i < 162; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
-       for (i = 0; i < 25; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006c00);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0xbf800000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x7149f2ca);
-       for (i = 0; i < 35; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007400);
-       for (i = 0; i < 48; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00007800);
-       for (i = 0; i < 48; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00004400);
-       for (i = 0; i < 32; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000000);
-       for (i = 0; i < 16; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
-       for (i = 0; i < 4; i++)
-               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
-
-       nouveau_wait_for_idle(dev);
-}
-
-/* TODO replace address with name
-   use loops */
 static int nv10_graph_ctx_regs [] = {
-NV03_PGRAPH_XY_LOGIC_MISC0,
-
 NV10_PGRAPH_CTX_SWITCH1,
 NV10_PGRAPH_CTX_SWITCH2,
 NV10_PGRAPH_CTX_SWITCH3,
@@ -455,6 +312,7 @@ NV03_PGRAPH_ABS_UCLIPA_YMIN,
 NV03_PGRAPH_ABS_UCLIPA_YMAX,
 NV03_PGRAPH_ABS_ICLIP_XMAX,
 NV03_PGRAPH_ABS_ICLIP_YMAX,
+NV03_PGRAPH_XY_LOGIC_MISC0,
 NV03_PGRAPH_XY_LOGIC_MISC1,
 NV03_PGRAPH_XY_LOGIC_MISC2,
 NV03_PGRAPH_XY_LOGIC_MISC3,
@@ -462,18 +320,18 @@ NV03_PGRAPH_CLIPX_0,
 NV03_PGRAPH_CLIPX_1,
 NV03_PGRAPH_CLIPY_0,
 NV03_PGRAPH_CLIPY_1,
-0x00400e40,
-0x00400e44,
-0x00400e48,
-0x00400e4c,
-0x00400e50,
-0x00400e54,
-0x00400e58,
-0x00400e5c,
-0x00400e60,
-0x00400e64,
-0x00400e68,
-0x00400e6c,
+NV10_PGRAPH_COMBINER0_IN_ALPHA,
+NV10_PGRAPH_COMBINER1_IN_ALPHA,
+NV10_PGRAPH_COMBINER0_IN_RGB,
+NV10_PGRAPH_COMBINER1_IN_RGB,
+NV10_PGRAPH_COMBINER_COLOR0,
+NV10_PGRAPH_COMBINER_COLOR1,
+NV10_PGRAPH_COMBINER0_OUT_ALPHA,
+NV10_PGRAPH_COMBINER1_OUT_ALPHA,
+NV10_PGRAPH_COMBINER0_OUT_RGB,
+NV10_PGRAPH_COMBINER1_OUT_RGB,
+NV10_PGRAPH_COMBINER_FINAL0,
+NV10_PGRAPH_COMBINER_FINAL1,
 0x00400e00,
 0x00400e04,
 0x00400e08,
@@ -527,99 +385,396 @@ NV10_PGRAPH_DEBUG_4,
 0x00400a04,
 };
 
-static int nv10_graph_ctx_regs_find_offset(drm_device_t *dev, int reg)
+struct graph_state {
+       int nv10[sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0])];
+       int nv17[sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0])];
+       struct pipe_state pipe_state;
+};
+
+static void nv10_graph_save_pipe(struct nouveau_channel *chan) {
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
+       int i;
+#define PIPE_SAVE(addr) \
+       do { \
+               NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, addr); \
+               for (i=0; i < sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]); i++) \
+                       fifo_pipe_state->pipe_##addr[i] = NV_READ(NV10_PGRAPH_PIPE_DATA); \
+       } while (0)
+
+       PIPE_SAVE(0x4400);
+       PIPE_SAVE(0x0200);
+       PIPE_SAVE(0x6400);
+       PIPE_SAVE(0x6800);
+       PIPE_SAVE(0x6c00);
+       PIPE_SAVE(0x7000);
+       PIPE_SAVE(0x7400);
+       PIPE_SAVE(0x7800);
+       PIPE_SAVE(0x0040);
+       PIPE_SAVE(0x0000);
+
+#undef PIPE_SAVE
+}
+
+static void nv10_graph_load_pipe(struct nouveau_channel *chan) {
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
+       int i;
+       uint32_t xfmode0, xfmode1;
+#define PIPE_RESTORE(addr) \
+       do { \
+               NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, addr); \
+               for (i=0; i < sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]); i++) \
+                       NV_WRITE(NV10_PGRAPH_PIPE_DATA, fifo_pipe_state->pipe_##addr[i]); \
+       } while (0)
+
+
+       nouveau_wait_for_idle(dev);
+       /* XXX check haiku comments */
+       xfmode0 = NV_READ(NV10_PGRAPH_XFMODE0);
+       xfmode1 = NV_READ(NV10_PGRAPH_XFMODE1);
+       NV_WRITE(NV10_PGRAPH_XFMODE0, 0x10000000);
+       NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000);
+       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
+       for (i = 0; i < 4; i++)
+               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+       for (i = 0; i < 4; i++)
+               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
+       for (i = 0; i < 3; i++)
+               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+
+       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
+       for (i = 0; i < 3; i++)
+               NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+       NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
+       NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000008);
+
+
+       PIPE_RESTORE(0x0200);
+       nouveau_wait_for_idle(dev);
+
+       /* restore XFMODE */
+       NV_WRITE(NV10_PGRAPH_XFMODE0, xfmode0);
+       NV_WRITE(NV10_PGRAPH_XFMODE1, xfmode1);
+       PIPE_RESTORE(0x6400);
+       PIPE_RESTORE(0x6800);
+       PIPE_RESTORE(0x6c00);
+       PIPE_RESTORE(0x7000);
+       PIPE_RESTORE(0x7400);
+       PIPE_RESTORE(0x7800);
+       PIPE_RESTORE(0x4400);
+       PIPE_RESTORE(0x0000);
+       PIPE_RESTORE(0x0040);
+       nouveau_wait_for_idle(dev);
+
+#undef PIPE_RESTORE
+}
+
+static void nv10_graph_create_pipe(struct nouveau_channel *chan) {
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
+       uint32_t *fifo_pipe_state_addr;
+       int i;
+#define PIPE_INIT(addr) \
+       do { \
+               fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \
+       } while (0)
+#define PIPE_INIT_END(addr) \
+       do { \
+               if (fifo_pipe_state_addr != \
+                               sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]) + fifo_pipe_state->pipe_##addr) \
+                       DRM_ERROR("incomplete pipe init for 0x%x :  %p/%p\n", addr, fifo_pipe_state_addr, \
+                                       sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]) + fifo_pipe_state->pipe_##addr); \
+       } while (0)
+#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value
+
+       PIPE_INIT(0x0200);
+       for (i = 0; i < 48; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x0200);
+
+       PIPE_INIT(0x6400);
+       for (i = 0; i < 211; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       NV_WRITE_PIPE_INIT(0x40000000);
+       NV_WRITE_PIPE_INIT(0x40000000);
+       NV_WRITE_PIPE_INIT(0x40000000);
+       NV_WRITE_PIPE_INIT(0x40000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x3f000000);
+       NV_WRITE_PIPE_INIT(0x3f000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       PIPE_INIT_END(0x6400);
+
+       PIPE_INIT(0x6800);
+       for (i = 0; i < 162; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x3f800000);
+       for (i = 0; i < 25; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x6800);
+
+       PIPE_INIT(0x6c00);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0xbf800000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x6c00);
+
+       PIPE_INIT(0x7000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x00000000);
+       NV_WRITE_PIPE_INIT(0x7149f2ca);
+       for (i = 0; i < 35; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x7000);
+
+       PIPE_INIT(0x7400);
+       for (i = 0; i < 48; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x7400);
+
+       PIPE_INIT(0x7800);
+       for (i = 0; i < 48; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x7800);
+
+       PIPE_INIT(0x4400);
+       for (i = 0; i < 32; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x4400);
+
+       PIPE_INIT(0x0000);
+       for (i = 0; i < 16; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x0000);
+
+       PIPE_INIT(0x0040);
+       for (i = 0; i < 4; i++)
+               NV_WRITE_PIPE_INIT(0x00000000);
+       PIPE_INIT_END(0x0040);
+
+#undef PIPE_INIT
+#undef PIPE_INIT_END
+#undef NV_WRITE_PIPE_INIT
+}
+
+static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int i, j;
+       int i;
        for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) {
                if (nv10_graph_ctx_regs[i] == reg)
                        return i;
        }
-       if (dev_priv->chipset>=0x17) {
-               for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) {
-                       if (nv17_graph_ctx_regs[j] == reg)
-                               return i;
-               }
+       DRM_ERROR("unknow offset nv10_ctx_regs %d\n", reg);
+       return -1;
+}
+
+static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
+{
+       int i;
+       for (i = 0; i < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++) {
+               if (nv17_graph_ctx_regs[i] == reg)
+                       return i;
        }
+       DRM_ERROR("unknow offset nv17_ctx_regs %d\n", reg);
        return -1;
 }
 
-static void restore_ctx_regs(drm_device_t *dev, int channel)
+int nv10_graph_load_context(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_fifo *fifo = &dev_priv->fifos[channel];
-       int i, j;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       int i;
+
        for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
-               NV_WRITE(nv10_graph_ctx_regs[i], fifo->pgraph_ctx[i]);
+               NV_WRITE(nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]);
        if (dev_priv->chipset>=0x17) {
-               for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++)
-                       NV_WRITE(nv17_graph_ctx_regs[j], fifo->pgraph_ctx[i]);
+               for (i = 0; i < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++)
+                       NV_WRITE(nv17_graph_ctx_regs[i], pgraph_ctx->nv17[i]);
        }
-       nouveau_wait_for_idle(dev);
+
+       nv10_graph_load_pipe(chan);
+
+       return 0;
 }
 
-void nouveau_nv10_context_switch(drm_device_t *dev)
+int nv10_graph_save_context(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int channel, channel_old, i, j;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       int i;
 
-       channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
-       channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+       for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
+               pgraph_ctx->nv10[i] = NV_READ(nv10_graph_ctx_regs[i]);
+       if (dev_priv->chipset>=0x17) {
+               for (i = 0; i < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++)
+                       pgraph_ctx->nv17[i] = NV_READ(nv17_graph_ctx_regs[i]);
+       }
 
-       DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel);
+       nv10_graph_save_pipe(chan);
 
-       NV_WRITE(NV04_PGRAPH_FIFO,0x0);
-#if 0
-       NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000000);
-       NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000);
-       NV_WRITE(NV_PFIFO_CACHES, 0x00000000);
-#endif
+       return 0;
+}
 
-       // save PGRAPH context
-       for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
-               dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]);
-       if (dev_priv->chipset>=0x17) {
-               for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++)
-                       dev_priv->fifos[channel_old].pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]);
+void nouveau_nv10_context_switch(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv;
+       struct nouveau_channel *next, *last;
+       int chid;
+
+       if (!dev) {
+               DRM_DEBUG("Invalid drm_device\n");
+               return;
+       }
+       dev_priv = dev->dev_private;
+       if (!dev_priv) {
+               DRM_DEBUG("Invalid drm_nouveau_private\n");
+               return;
+       }
+       if (!dev_priv->fifos) {
+               DRM_DEBUG("Invalid drm_nouveau_private->fifos\n");
+               return;
+       }
+
+       chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20)&(nouveau_fifo_number(dev)-1);
+       next = dev_priv->fifos[chid];
+
+       if (!next) {
+               DRM_ERROR("Invalid next channel\n");
+               return;
+       }
+
+       chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+       last = dev_priv->fifos[chid];
+
+       if (!last) {
+               DRM_INFO("WARNING: Invalid last channel, switch to %x\n",
+                         next->id);
+       } else {
+               DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",
+                        last->id, next->id);
        }
-       
+
+       NV_WRITE(NV04_PGRAPH_FIFO,0x0);
+       if (last) {
+               nouveau_wait_for_idle(dev);
+               nv10_graph_save_context(last);
+       }       
+
        nouveau_wait_for_idle(dev);
 
        NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000);
-       NV_WRITE(NV10_PGRAPH_CTX_USER, (NV_READ(NV10_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24));
 
        nouveau_wait_for_idle(dev);
-       // restore PGRAPH context
-#if 1
-       restore_ctx_regs(dev, channel);
-#endif
-       
+
+       nv10_graph_load_context(next);
+
        NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
-       NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24);
        NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF);
-
-#if 0
-       NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001);
-       NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001);
-       NV_WRITE(NV_PFIFO_CACHES, 0x00000001);
-#endif
        NV_WRITE(NV04_PGRAPH_FIFO,0x1);
 }
 
 #define NV_WRITE_CTX(reg, val) do { \
        int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
        if (offset > 0) \
-               fifo->pgraph_ctx[offset] = val; \
+               pgraph_ctx->nv10[offset] = val; \
        } while (0)
-int nv10_graph_context_create(drm_device_t *dev, int channel) {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       struct nouveau_fifo *fifo = &dev_priv->fifos[channel];
-       uint32_t tmp, vramsz;
 
-       DRM_DEBUG("nv10_graph_context_create %d\n", channel);
+#define NV17_WRITE_CTX(reg, val) do { \
+       int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \
+       if (offset > 0) \
+               pgraph_ctx->nv17[offset] = val; \
+       } while (0)
+
+int nv10_graph_create_context(struct nouveau_channel *chan) {
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx;
 
-       memset(fifo->pgraph_ctx, 0, sizeof(fifo->pgraph_ctx));
+       DRM_DEBUG("nv10_graph_context_create %d\n", chan->id);
 
+       chan->pgraph_ctx = pgraph_ctx = drm_calloc(1, sizeof(*pgraph_ctx),
+                                             DRM_MEM_DRIVER);
+
+       if (pgraph_ctx == NULL)
+               return -ENOMEM;
+
+       /* mmio trace suggest that should be done in ddx with methods/objects */
+#if 0
+       uint32_t tmp, vramsz;
        /* per channel init from ddx */
        tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
        /*XXX the original ddx code, does this in 2 steps :
@@ -644,28 +799,67 @@ int nv10_graph_context_create(drm_device_t *dev, int channel) {
        NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMIN, 0);
        NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff);
        NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff);
+#endif
 
+       NV_WRITE_CTX(0x00400e88, 0x08000000);
+       NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
        NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
-       /* is it really needed ??? */
+       NV_WRITE_CTX(0x00400e10, 0x00001000);
+       NV_WRITE_CTX(0x00400e14, 0x00001000);
+       NV_WRITE_CTX(0x00400e30, 0x00080008);
+       NV_WRITE_CTX(0x00400e34, 0x00080008);
        if (dev_priv->chipset>=0x17) {
-               NV_WRITE_CTX(NV10_PGRAPH_DEBUG_4, NV_READ(NV10_PGRAPH_DEBUG_4));
-               NV_WRITE_CTX(0x004006b0, NV_READ(0x004006b0));
+               /* is it really needed ??? */
+               NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4, NV_READ(NV10_PGRAPH_DEBUG_4));
+               NV17_WRITE_CTX(0x004006b0, NV_READ(0x004006b0));
+               NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
+               NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
+               NV17_WRITE_CTX(0x00400ec0, 0x00000080);
+               NV17_WRITE_CTX(0x00400ed0, 0x00000080);
        }
+       NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24);
 
-       /* for the first channel init the regs */
-       if (dev_priv->fifo_alloc_count == 0)
-               restore_ctx_regs(dev, channel);
-
-
-       //XXX should be saved/restored for each fifo
-       //we supposed here we have X fifo and only one 3D fifo.
-       nv10_praph_pipe(dev);
+       nv10_graph_create_pipe(chan);
        return 0;
 }
 
+void nv10_graph_destroy_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct graph_state* pgraph_ctx = chan->pgraph_ctx;
+       int chid;
+
+       drm_free(pgraph_ctx, sizeof(*pgraph_ctx), DRM_MEM_DRIVER);
+       chan->pgraph_ctx = NULL;
 
-int nv10_graph_init(drm_device_t *dev) {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+
+       /* This code seems to corrupt the 3D pipe, but blob seems to do similar things ????
+        */
+#if 0
+       /* does this avoid a potential context switch while we are written graph
+        * reg, or we should mask graph interrupt ???
+        */
+       NV_WRITE(NV04_PGRAPH_FIFO,0x0);
+       if (chid == chan->id) {
+               DRM_INFO("cleanning a channel with graph in current context\n");
+               nouveau_wait_for_idle(dev);
+               DRM_INFO("reseting current graph context\n");
+               /* can't be call here because of dynamic mem alloc */
+               //nv10_graph_create_context(chan);
+               nv10_graph_load_context(chan);
+       }
+       NV_WRITE(NV04_PGRAPH_FIFO, 0x1);
+#else
+       if (chid == chan->id) {
+               DRM_INFO("cleanning a channel with graph in current context\n");
+       }
+#endif
+}
+
+int nv10_graph_init(struct drm_device *dev) {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
 
        NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
@@ -673,16 +867,23 @@ int nv10_graph_init(drm_device_t *dev) {
        NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
                         NV_PMC_ENABLE_PGRAPH);
 
-       NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
        NV_WRITE(NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+       NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
        NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
        NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
        NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x00118700);
-       NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x24E00810);
-       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x55DE0030 |
+       //NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x24E00810); /* 0x25f92ad9 */
+       NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
+       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x55DE0830 |
                                      (1<<29) |
                                      (1<<31));
+       if (dev_priv->chipset>=0x17) {
+               NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x1f000000);
+               NV_WRITE(0x004006b0, 0x40000020);
+       }
+       else
+               NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00000000);
 
        /* copy tile info from PFB */
        for (i=0; i<NV10_PFB_TILE__SIZE; i++) {
@@ -692,6 +893,10 @@ int nv10_graph_init(drm_device_t *dev) {
                NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i)));
        }
 
+       NV_WRITE(NV10_PGRAPH_CTX_SWITCH1, 0x00000000);
+       NV_WRITE(NV10_PGRAPH_CTX_SWITCH2, 0x00000000);
+       NV_WRITE(NV10_PGRAPH_CTX_SWITCH3, 0x00000000);
+       NV_WRITE(NV10_PGRAPH_CTX_SWITCH4, 0x00000000);
        NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
        NV_WRITE(NV10_PGRAPH_STATE      , 0xFFFFFFFF);
        NV_WRITE(NV04_PGRAPH_FIFO       , 0x00000001);
@@ -699,7 +904,7 @@ int nv10_graph_init(drm_device_t *dev) {
        return 0;
 }
 
-void nv10_graph_takedown(drm_device_t *dev)
+void nv10_graph_takedown(struct drm_device *dev)
 {
 }
 
index 7190fc8..ae0e085 100644 (file)
-/* 
- * Copyright 2007 Matthieu CASTET <castet.matthieu@free.fr>
- * All Rights Reserved.
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+/*
+ * NV20
+ * -----
+ * There are 3 families :
+ * NV20 is 0x10de:0x020*
+ * NV25/28 is 0x10de:0x025* / 0x10de:0x028*
+ * NV2A is 0x10de:0x02A0
  *
- * 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:
+ * NV30
+ * -----
+ * There are 3 families :
+ * NV30/31 is 0x10de:0x030* / 0x10de:0x031*
+ * NV34 is 0x10de:0x032*
+ * NV35/36 is 0x10de:0x033* / 0x10de:0x034*
  *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
+ * Not seen in the wild, no dumps (probably NV35) :
+ * NV37 is 0x10de:0x00fc, 0x10de:0x00fd
+ * NV38 is 0x10de:0x0333, 0x10de:0x00fe
  *
- * 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 "drmP.h"
-#include "drm.h"
-#include "nouveau_drv.h"
-#include "nouveau_drm.h"
+#define NV20_GRCTX_SIZE (3580*4)
+#define NV25_GRCTX_SIZE (3529*4)
+#define NV2A_GRCTX_SIZE (3500*4)
 
-#define NV20_GRCTX_SIZE (3529*4)
+#define NV30_31_GRCTX_SIZE (22392)
+#define NV34_GRCTX_SIZE    (18140)
+#define NV35_36_GRCTX_SIZE (22396)
 
-int nv20_graph_context_create(drm_device_t *dev, int channel) {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       unsigned int ctx_size = NV20_GRCTX_SIZE;
+static void nv20_graph_context_init(struct drm_device *dev,
+                                    struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
+/*
+write32 #1 block at +0x00740adc NV_PRAMIN+0x40adc of 3369 (0xd29) elements:
++0x00740adc: ffff0000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740afc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b1c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b3c: 00000000 0fff0000 0fff0000 00000000 00000000 00000000 00000000 00000000
++0x00740b5c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b7c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b9c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740bbc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740bdc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740bfc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
 
-       /* Alloc and clear RAMIN to store the context */
-       chan->ramin_grctx = nouveau_instmem_alloc(dev, ctx_size, 4);
-       if (!chan->ramin_grctx)
-               return DRM_ERR(ENOMEM);
-       for (i=0; i<ctx_size; i+=4)
-               INSTANCE_WR(chan->ramin_grctx, i/4, 0x00000000);
++0x00740c1c: 00000101 00000000 00000000 00000000 00000000 00000111 00000000 00000000
++0x00740c3c: 00000000 00000000 00000000 44400000 00000000 00000000 00000000 00000000
++0x00740c5c: 00000000 00000000 00000000 00000000 00000000 00000000 00030303 00030303
++0x00740c7c: 00030303 00030303 00000000 00000000 00000000 00000000 00080000 00080000
++0x00740c9c: 00080000 00080000 00000000 00000000 01012000 01012000 01012000 01012000
++0x00740cbc: 000105b8 000105b8 000105b8 000105b8 00080008 00080008 00080008 00080008
++0x00740cdc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740cfc: 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000
++0x00740d1c: 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000
++0x00740d3c: 00000000 00000000 4b7fffff 00000000 00000000 00000000 00000000 00000000
 
-       /* Initialise default context values */
-       INSTANCE_WR(chan->ramin_grctx, 10, channel << 24); /* CTX_USER */
++0x00740d5c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740d7c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740d9c: 00000001 00000000 00004000 00000000 00000000 00000001 00000000 00040000
++0x00740dbc: 00010000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740ddc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+...
+*/
+       INSTANCE_WR(ctx, (0x33c/4)+0, 0xffff0000);
+       INSTANCE_WR(ctx, (0x33c/4)+25, 0x0fff0000);
+       INSTANCE_WR(ctx, (0x33c/4)+26, 0x0fff0000);
+       INSTANCE_WR(ctx, (0x33c/4)+80, 0x00000101);
+       INSTANCE_WR(ctx, (0x33c/4)+85, 0x00000111);
+       INSTANCE_WR(ctx, (0x33c/4)+91, 0x44400000);
+       for (i = 0; i < 4; ++i)
+               INSTANCE_WR(ctx, (0x33c/4)+102+i, 0x00030303);
+       for (i = 0; i < 4; ++i)
+               INSTANCE_WR(ctx, (0x33c/4)+110+i, 0x00080000);
+       for (i = 0; i < 4; ++i)
+               INSTANCE_WR(ctx, (0x33c/4)+116+i, 0x01012000);
+       for (i = 0; i < 4; ++i)
+               INSTANCE_WR(ctx, (0x33c/4)+120+i, 0x000105b8);
+       for (i = 0; i < 4; ++i)
+               INSTANCE_WR(ctx, (0x33c/4)+124+i, 0x00080008);
+       for (i = 0; i < 16; ++i)
+               INSTANCE_WR(ctx, (0x33c/4)+136+i, 0x07ff0000);
+       INSTANCE_WR(ctx, (0x33c/4)+154, 0x4b7fffff);
+       INSTANCE_WR(ctx, (0x33c/4)+176, 0x00000001);
+       INSTANCE_WR(ctx, (0x33c/4)+178, 0x00004000);
+       INSTANCE_WR(ctx, (0x33c/4)+181, 0x00000001);
+       INSTANCE_WR(ctx, (0x33c/4)+183, 0x00040000);
+       INSTANCE_WR(ctx, (0x33c/4)+184, 0x00010000);
 
-       INSTANCE_WR(dev_priv->ctx_table, channel, nouveau_chip_instance_get(dev, chan->ramin_grctx));
+/*
+...
++0x0074239c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x007423bc: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x007423dc: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x007423fc: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
+...
++0x00742bdc: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742bfc: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742c1c: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742c3c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+...
+*/
+       for (i = 0; i < 0x880; i += 0x10) {
+               INSTANCE_WR(ctx, ((0x1c1c + i)/4)+0, 0x10700ff9);
+               INSTANCE_WR(ctx, ((0x1c1c + i)/4)+1, 0x0436086c);
+               INSTANCE_WR(ctx, ((0x1c1c + i)/4)+2, 0x000c001b);
+       }
 
-       return 0;
+/*
+write32 #1 block at +0x00742fbc NV_PRAMIN+0x42fbc of 4 (0x4) elements:
++0x00742fbc: 3f800000 00000000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x281c/4), 0x3f800000);
+
+/*
+write32 #1 block at +0x00742ffc NV_PRAMIN+0x42ffc of 12 (0xc) elements:
++0x00742ffc: 40000000 3f800000 3f000000 00000000 40000000 3f800000 00000000 bf800000
++0x0074301c: 00000000 bf800000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x285c/4)+0, 0x40000000);
+       INSTANCE_WR(ctx, (0x285c/4)+1, 0x3f800000);
+       INSTANCE_WR(ctx, (0x285c/4)+2, 0x3f000000);
+       INSTANCE_WR(ctx, (0x285c/4)+4, 0x40000000);
+       INSTANCE_WR(ctx, (0x285c/4)+5, 0x3f800000);
+       INSTANCE_WR(ctx, (0x285c/4)+7, 0xbf800000);
+       INSTANCE_WR(ctx, (0x285c/4)+9, 0xbf800000);
+
+/*
+write32 #1 block at +0x00742fcc NV_PRAMIN+0x42fcc of 4 (0x4) elements:
++0x00742fcc: 00000000 3f800000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x282c/4)+1, 0x3f800000);
+
+/*
+write32 #1 block at +0x0074302c NV_PRAMIN+0x4302c of 4 (0x4) elements:
++0x0074302c: 00000000 00000000 00000000 00000000
+write32 #1 block at +0x00743c9c NV_PRAMIN+0x43c9c of 4 (0x4) elements:
++0x00743c9c: 00000000 00000000 00000000 00000000
+write32 #1 block at +0x00743c3c NV_PRAMIN+0x43c3c of 8 (0x8) elements:
++0x00743c3c: 00000000 00000000 000fe000 00000000 00000000 00000000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x349c/4)+2, 0x000fe000);
+
+/*
+write32 #1 block at +0x00743c6c NV_PRAMIN+0x43c6c of 4 (0x4) elements:
++0x00743c6c: 00000000 00000000 00000000 00000000
+write32 #1 block at +0x00743ccc NV_PRAMIN+0x43ccc of 4 (0x4) elements:
++0x00743ccc: 00000000 000003f8 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x352c/4)+1, 0x000003f8);
+
+/* write32 #1 NV_PRAMIN+0x43ce0 <- 0x002fe000 */
+       INSTANCE_WR(ctx, 0x3540/4, 0x002fe000);
+
+/*
+write32 #1 block at +0x00743cfc NV_PRAMIN+0x43cfc of 8 (0x8) elements:
++0x00743cfc: 001c527c 001c527c 001c527c 001c527c 001c527c 001c527c 001c527c 001c527c
+*/
+       for (i = 0; i < 8; ++i)
+               INSTANCE_WR(ctx, (0x355c/4)+i, 0x001c527c);
 }
 
-static void nv20_graph_rdi(drm_device_t *dev) {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
+static void nv2a_graph_context_init(struct drm_device *dev,
+                                    struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
 
-       NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x2c80000);
-       for (i = 0; i < 32; i++)
-               NV_WRITE(NV10_PGRAPH_RDI_DATA, 0);
+       INSTANCE_WR(ctx, 0x33c/4, 0xffff0000);
+       for(i = 0x3a0; i< 0x3a8; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x47c/4, 0x00000101);
+       INSTANCE_WR(ctx, 0x490/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x4a8/4, 0x44400000);
+       for(i = 0x4d4; i< 0x4e4; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00030303);
+       for(i = 0x4f4; i< 0x504; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00080000);
+       for(i = 0x50c; i< 0x51c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for(i = 0x51c; i< 0x52c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x000105b8);
+       for(i = 0x52c; i< 0x53c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       for(i = 0x55c; i< 0x59c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x5a4/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x5fc/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x604/4, 0x00004000);
+       INSTANCE_WR(ctx, 0x610/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x618/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x61c/4, 0x00010000);
 
-       nouveau_wait_for_idle(dev);
+       for (i=0x1a9c; i <= 0x22fc/4; i += 32) {
+               INSTANCE_WR(ctx, i/4    , 0x10700ff9);
+               INSTANCE_WR(ctx, i/4 + 1, 0x0436086c);
+               INSTANCE_WR(ctx, i/4 + 2, 0x000c001b);
+       }
+
+       INSTANCE_WR(ctx, 0x269c/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x26b0/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x26dc/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x26e0/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x26e4/4, 0x3f000000);
+       INSTANCE_WR(ctx, 0x26ec/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x26f0/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x26f8/4, 0xbf800000);
+       INSTANCE_WR(ctx, 0x2700/4, 0xbf800000);
+       INSTANCE_WR(ctx, 0x3024/4, 0x000fe000);
+       INSTANCE_WR(ctx, 0x30a0/4, 0x000003f8);
+       INSTANCE_WR(ctx, 0x33fc/4, 0x002fe000);
+       for(i = 0x341c; i< 0x343c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x001c527c);
 }
 
-/* Save current context (from PGRAPH) into the channel's context
- */
-static void nv20_graph_context_save_current(drm_device_t *dev, int channel) {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       uint32_t instance;
-
-       instance = INSTANCE_RD(dev_priv->ctx_table, channel);
-       if (!instance) {
-               return;
+static void nv25_graph_context_init(struct drm_device *dev,
+                                    struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
+/*
+write32 #1 block at +0x00740a7c NV_PRAMIN.GRCTX0+0x35c of 173 (0xad) elements:
++0x00740a7c: ffff0000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740a9c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740abc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740adc: 00000000 0fff0000 0fff0000 00000000 00000000 00000000 00000000 00000000
++0x00740afc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b1c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b3c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b5c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+
++0x00740b7c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740b9c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740bbc: 00000101 00000000 00000000 00000000 00000000 00000111 00000000 00000000
++0x00740bdc: 00000000 00000000 00000000 00000080 ffff0000 00000001 00000000 00000000
++0x00740bfc: 00000000 00000000 44400000 00000000 00000000 00000000 00000000 00000000
++0x00740c1c: 4b800000 00000000 00000000 00000000 00000000 00030303 00030303 00030303
++0x00740c3c: 00030303 00000000 00000000 00000000 00000000 00080000 00080000 00080000
++0x00740c5c: 00080000 00000000 00000000 01012000 01012000 01012000 01012000 000105b8
+
++0x00740c7c: 000105b8 000105b8 000105b8 00080008 00080008 00080008 00080008 00000000
++0x00740c9c: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 07ff0000
++0x00740cbc: 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000
++0x00740cdc: 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 07ff0000 00000000
++0x00740cfc: 00000000 4b7fffff 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740d1c: 00000000 00000000 00000000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x35c/4)+0, 0xffff0000);
+       INSTANCE_WR(ctx, (0x35c/4)+25, 0x0fff0000);
+       INSTANCE_WR(ctx, (0x35c/4)+26, 0x0fff0000);
+       INSTANCE_WR(ctx, (0x35c/4)+80, 0x00000101);
+       INSTANCE_WR(ctx, (0x35c/4)+85, 0x00000111);
+       INSTANCE_WR(ctx, (0x35c/4)+91, 0x00000080);
+       INSTANCE_WR(ctx, (0x35c/4)+92, 0xffff0000);
+       INSTANCE_WR(ctx, (0x35c/4)+93, 0x00000001);
+       INSTANCE_WR(ctx, (0x35c/4)+98, 0x44400000);
+       INSTANCE_WR(ctx, (0x35c/4)+104, 0x4b800000);
+       INSTANCE_WR(ctx, (0x35c/4)+109, 0x00030303);
+       INSTANCE_WR(ctx, (0x35c/4)+110, 0x00030303);
+       INSTANCE_WR(ctx, (0x35c/4)+111, 0x00030303);
+       INSTANCE_WR(ctx, (0x35c/4)+112, 0x00030303);
+       INSTANCE_WR(ctx, (0x35c/4)+117, 0x00080000);
+       INSTANCE_WR(ctx, (0x35c/4)+118, 0x00080000);
+       INSTANCE_WR(ctx, (0x35c/4)+119, 0x00080000);
+       INSTANCE_WR(ctx, (0x35c/4)+120, 0x00080000);
+       INSTANCE_WR(ctx, (0x35c/4)+123, 0x01012000);
+       INSTANCE_WR(ctx, (0x35c/4)+124, 0x01012000);
+       INSTANCE_WR(ctx, (0x35c/4)+125, 0x01012000);
+       INSTANCE_WR(ctx, (0x35c/4)+126, 0x01012000);
+       INSTANCE_WR(ctx, (0x35c/4)+127, 0x000105b8);
+       INSTANCE_WR(ctx, (0x35c/4)+128, 0x000105b8);
+       INSTANCE_WR(ctx, (0x35c/4)+129, 0x000105b8);
+       INSTANCE_WR(ctx, (0x35c/4)+130, 0x000105b8);
+       INSTANCE_WR(ctx, (0x35c/4)+131, 0x00080008);
+       INSTANCE_WR(ctx, (0x35c/4)+132, 0x00080008);
+       INSTANCE_WR(ctx, (0x35c/4)+133, 0x00080008);
+       INSTANCE_WR(ctx, (0x35c/4)+134, 0x00080008);
+       for (i=0; i<16; ++i)
+               INSTANCE_WR(ctx, (0x35c/4)+143+i, 0x07ff0000);
+       INSTANCE_WR(ctx, (0x35c/4)+161, 0x4b7fffff);
+
+/*
+write32 #1 block at +0x00740d34 NV_PRAMIN.GRCTX0+0x614 of 3136 (0xc40) elements:
++0x00740d34: 00000000 00000000 00000000 00000080 30201000 70605040 b0a09080 f0e0d0c0
++0x00740d54: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00740d74: 00000000 00000000 00000000 00000000 00000001 00000000 00004000 00000000
++0x00740d94: 00000000 00000001 00000000 00040000 00010000 00000000 00000000 00000000
++0x00740db4: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+...
++0x00742214: 00000000 00000000 00000000 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742234: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742254: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742274: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
+...
++0x00742a34: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742a54: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742a74: 10700ff9 0436086c 000c001b 00000000 10700ff9 0436086c 000c001b 00000000
++0x00742a94: 10700ff9 0436086c 000c001b 00000000 00000000 00000000 00000000 00000000
++0x00742ab4: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
++0x00742ad4: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x614/4)+3, 0x00000080);
+       INSTANCE_WR(ctx, (0x614/4)+4, 0x30201000);
+       INSTANCE_WR(ctx, (0x614/4)+5, 0x70605040);
+       INSTANCE_WR(ctx, (0x614/4)+6, 0xb0a09080);
+       INSTANCE_WR(ctx, (0x614/4)+7, 0xf0e0d0c0);
+       INSTANCE_WR(ctx, (0x614/4)+20, 0x00000001);
+       INSTANCE_WR(ctx, (0x614/4)+22, 0x00004000);
+       INSTANCE_WR(ctx, (0x614/4)+25, 0x00000001);
+       INSTANCE_WR(ctx, (0x614/4)+27, 0x00040000);
+       INSTANCE_WR(ctx, (0x614/4)+28, 0x00010000);
+       for (i=0; i < 0x880/4; i+=4) {
+               INSTANCE_WR(ctx, (0x1b04/4)+i+0, 0x10700ff9);
+               INSTANCE_WR(ctx, (0x1b04/4)+i+1, 0x0436086c);
+               INSTANCE_WR(ctx, (0x1b04/4)+i+2, 0x000c001b);
        }
-       if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx))
-               DRM_ERROR("nv20_graph_context_save_current : bad instance\n");
 
-       NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance);
-       NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 2 /* save ctx */);
+/*
+write32 #1 block at +0x00742e24 NV_PRAMIN.GRCTX0+0x2704 of 4 (0x4) elements:
++0x00742e24: 3f800000 00000000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x2704/4), 0x3f800000);
+
+/*
+write32 #1 block at +0x00742e64 NV_PRAMIN.GRCTX0+0x2744 of 12 (0xc) elements:
++0x00742e64: 40000000 3f800000 3f000000 00000000 40000000 3f800000 00000000 bf800000
++0x00742e84: 00000000 bf800000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x2744/4)+0, 0x40000000);
+       INSTANCE_WR(ctx, (0x2744/4)+1, 0x3f800000);
+       INSTANCE_WR(ctx, (0x2744/4)+2, 0x3f000000);
+       INSTANCE_WR(ctx, (0x2744/4)+4, 0x40000000);
+       INSTANCE_WR(ctx, (0x2744/4)+5, 0x3f800000);
+       INSTANCE_WR(ctx, (0x2744/4)+7, 0xbf800000);
+       INSTANCE_WR(ctx, (0x2744/4)+9, 0xbf800000);
+
+/*
+write32 #1 block at +0x00742e34 NV_PRAMIN.GRCTX0+0x2714 of 4 (0x4) elements:
++0x00742e34: 00000000 3f800000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x2714/4)+1, 0x3f800000);
+
+/*
+write32 #1 block at +0x00742e94 NV_PRAMIN.GRCTX0+0x2774 of 4 (0x4) elements:
++0x00742e94: 00000000 00000000 00000000 00000000
+write32 #1 block at +0x00743804 NV_PRAMIN.GRCTX0+0x30e4 of 4 (0x4) elements:
++0x00743804: 00000000 00000000 00000000 00000000
+write32 #1 block at +0x007437a4 NV_PRAMIN.GRCTX0+0x3084 of 8 (0x8) elements:
++0x007437a4: 00000000 00000000 000fe000 00000000 00000000 00000000 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x3084/4)+2, 0x000fe000);
+
+/*
+write32 #1 block at +0x007437d4 NV_PRAMIN.GRCTX0+0x30b4 of 4 (0x4) elements:
++0x007437d4: 00000000 00000000 00000000 00000000
+write32 #1 block at +0x00743824 NV_PRAMIN.GRCTX0+0x3104 of 4 (0x4) elements:
++0x00743824: 00000000 000003f8 00000000 00000000
+*/
+       INSTANCE_WR(ctx, (0x3104/4)+1, 0x000003f8);
+
+/* write32 #1 NV_PRAMIN.GRCTX0+0x3468 <- 0x002fe000 */
+       INSTANCE_WR(ctx, 0x3468/4, 0x002fe000);
+
+/*
+write32 #1 block at +0x00743ba4 NV_PRAMIN.GRCTX0+0x3484 of 8 (0x8) elements:
++0x00743ba4: 001c527c 001c527c 001c527c 001c527c 001c527c 001c527c 001c527c 001c527c
+*/
+       for (i=0; i<8; ++i)
+               INSTANCE_WR(ctx, (0x3484/4)+i, 0x001c527c);
 }
 
+static void nv30_31_graph_context_init(struct drm_device *dev,
+                                       struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
 
-/* Restore the context for a specific channel into PGRAPH
- */
-static void nv20_graph_context_restore(drm_device_t *dev, int channel) {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       uint32_t instance;
-
-       instance = INSTANCE_RD(dev_priv->ctx_table, channel);
-       if (!instance) {
-               return;
+       INSTANCE_WR(ctx, 0x410/4, 0x00000101);
+       INSTANCE_WR(ctx, 0x424/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x428/4, 0x00000060);
+       INSTANCE_WR(ctx, 0x444/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x448/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x44c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x460/4, 0x44400000);
+       INSTANCE_WR(ctx, 0x48c/4, 0xffff0000);
+       for(i = 0x4e0; i< 0x4e8; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x4ec/4, 0x00011100);
+       for(i = 0x508; i< 0x548; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x550/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x58c/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x590/4, 0x30201000);
+       INSTANCE_WR(ctx, 0x594/4, 0x70605040);
+       INSTANCE_WR(ctx, 0x598/4, 0xb8a89888);
+       INSTANCE_WR(ctx, 0x59c/4, 0xf8e8d8c8);
+       INSTANCE_WR(ctx, 0x5b0/4, 0xb0000000);
+       for(i = 0x600; i< 0x640; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00010588);
+       for(i = 0x640; i< 0x680; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00030303);
+       for(i = 0x6c0; i< 0x700; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0008aae4);
+       for(i = 0x700; i< 0x740; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for(i = 0x740; i< 0x780; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       INSTANCE_WR(ctx, 0x85c/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x860/4, 0x00010000);
+       for(i = 0x864; i< 0x874; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00040004);
+       INSTANCE_WR(ctx, 0x1f18/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f1c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f20/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f28/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f2c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f30/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f38/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f3c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f40/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f48/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f4c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f50/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f58/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f5c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f60/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f68/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f6c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f70/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f78/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f7c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f80/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f88/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f8c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f90/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f98/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f9c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fa0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fa8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fb0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fb8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fbc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fc0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fc8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fcc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fd0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fd8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fdc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fe0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fe8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ff0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1ff8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ffc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2000/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2008/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x200c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2010/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2018/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x201c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2020/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2028/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x202c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2030/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2038/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x203c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2040/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2048/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x204c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2050/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2058/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x205c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2060/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2068/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x206c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2070/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2078/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x207c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2080/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2088/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x208c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2090/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2098/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x209c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2100/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2108/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x210c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2110/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2118/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x211c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2120/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2128/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x212c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2130/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2138/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x213c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2140/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2148/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x214c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2150/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2158/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x215c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2160/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2168/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x216c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2170/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2178/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x217c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2180/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2188/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x218c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2190/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2198/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x219c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2200/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2208/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x220c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2210/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2218/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x221c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2220/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2228/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x222c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2230/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2238/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x223c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2240/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2248/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x224c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2250/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2258/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x225c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2260/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2268/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x226c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2270/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2278/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x227c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2280/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2288/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x228c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2290/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2298/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x229c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2300/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2308/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x230c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2310/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2318/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x231c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2320/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2328/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x232c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2330/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2338/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x233c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2340/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2348/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x234c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2350/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2358/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x235c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2360/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2368/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x236c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2370/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2378/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x237c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2380/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2388/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x238c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2390/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2398/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x239c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2400/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2408/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x240c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2410/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2418/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x241c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2420/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2428/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x242c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2430/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2438/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x243c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2440/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2448/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x244c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2450/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2458/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x245c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2460/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2468/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x246c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2470/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2478/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x247c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2480/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2488/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x248c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2490/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2498/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x249c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2500/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2508/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x250c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2510/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2518/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x251c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2520/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2528/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x252c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2530/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2538/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x253c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2540/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2548/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x254c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2550/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2558/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x255c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2560/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2568/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x256c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2570/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2578/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x257c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2580/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2588/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x258c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2590/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2598/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x259c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2600/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2608/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x260c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2610/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2618/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x261c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2620/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2628/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x262c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2630/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2638/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x263c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2640/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2648/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x264c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2650/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2658/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x265c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2660/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2668/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x266c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2670/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2678/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x267c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2680/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2688/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x268c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2690/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2698/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x269c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2700/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2708/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x270c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2710/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2718/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x271c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2720/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2728/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x272c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2730/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2738/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x273c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2740/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2748/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x274c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2750/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2758/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x275c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2760/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2768/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x276c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2770/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2778/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x277c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2780/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2788/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x278c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2790/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2798/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x279c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2800/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2808/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x280c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2810/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2818/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x281c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2820/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2828/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x282c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2830/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2838/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x283c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2840/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2848/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x284c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2850/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2858/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x285c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2860/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2868/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x286c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2870/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2878/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x287c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2880/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2888/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x288c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2890/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2898/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x289c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2900/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2908/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x290c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2910/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2918/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x291c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2920/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2928/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x292c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2930/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2938/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x293c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2940/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2948/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x294c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2950/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2958/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x295c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2960/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2968/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x296c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2970/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2978/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x297c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2980/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2988/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x298c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2990/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2998/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x299c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29a0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29a8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29ac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29b0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29b8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29bc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29c0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29c8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29cc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29d0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29d8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29dc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29e0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29e8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29ec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29f0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29f8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29fc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a00/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a08/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a0c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a10/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a18/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a1c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a20/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a28/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a2c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a30/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a38/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a3c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a40/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a48/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a4c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a50/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a58/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a5c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a60/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a68/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a6c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a70/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a78/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a7c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a80/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a88/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a8c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a90/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a98/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a9c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2aa0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2aa8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2aac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ab0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ab8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2abc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ac0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ac8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2acc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ad0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ad8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2adc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ae0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ae8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2aec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2af0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2af8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2afc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b00/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b08/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b0c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b10/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b18/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b1c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b20/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b28/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b2c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b30/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b38/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b3c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b40/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b48/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b4c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b50/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b58/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b5c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b60/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b68/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b6c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b70/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b78/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b7c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b80/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b88/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b8c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b90/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b98/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b9c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ba0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ba8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bb0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bb8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bbc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bc0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bc8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bcc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bd0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bd8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bdc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2be0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2be8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bf0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bf8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bfc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c00/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c08/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c0c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c10/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c18/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c1c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c20/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c28/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c2c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c30/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c38/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c3c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c40/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c48/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c4c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c50/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c58/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c5c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c60/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c68/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c6c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c70/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c78/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c7c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c80/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c88/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c8c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c90/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c98/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c9c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ca0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ca8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cb0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cb8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cbc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cc0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cc8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ccc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cd0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cd8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cdc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ce0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ce8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cf0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cf8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cfc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d00/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d08/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d0c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d10/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d18/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d1c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d20/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d28/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d2c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d30/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d38/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d3c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d40/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d48/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d4c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d50/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d58/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d5c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d60/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d68/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d6c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d70/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d78/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d7c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d80/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d88/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d8c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d90/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d98/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d9c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2da0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2da8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2dac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2db0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2db8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2dbc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2dc0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2dc8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2dcc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2dd0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2dd8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ddc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2de0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2de8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2dec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2df0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2df8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2dfc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e00/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e08/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e0c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e10/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e18/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e1c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e20/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e28/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e2c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e30/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e38/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e3c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e40/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e48/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e4c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e50/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e58/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e5c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e60/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e68/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e6c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e70/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e78/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e7c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e80/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e88/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e8c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e90/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e98/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e9c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ea0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ea8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2eac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2eb0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2eb8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ebc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ec0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ec8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ecc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ed0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ed8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2edc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ee0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ee8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2eec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ef0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ef8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2efc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f00/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f08/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f0c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f10/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f18/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f1c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f20/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f28/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f2c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f30/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f38/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f3c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f40/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f48/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f4c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f50/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f58/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f5c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f60/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f68/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f6c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f70/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f78/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f7c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f80/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f88/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f8c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f90/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f98/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f9c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fa0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fa8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fac/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fb0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fb8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fbc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fc0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fc8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fcc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fd0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fd8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fdc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fe0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fe8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fec/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ff0/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ff8/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ffc/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3000/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3008/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x300c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3010/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3018/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x301c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3020/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3028/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x302c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3030/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3038/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x303c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3040/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3048/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x304c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3050/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3058/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x305c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3060/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3068/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x306c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3070/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3078/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x307c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3080/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x3088/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x308c/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3090/4, 0x000c001b);
+       for(i = 0x30b8; i< 0x30c8; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x344c/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x3808/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x381c/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x3848/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x384c/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x3850/4, 0x3f000000);
+       INSTANCE_WR(ctx, 0x3858/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x385c/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x3864/4, 0xbf800000);
+       INSTANCE_WR(ctx, 0x386c/4, 0xbf800000);
+}
+
+static void nv34_graph_context_init(struct drm_device *dev,
+                                    struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
+
+       INSTANCE_WR(ctx, 0x40c/4, 0x01000101);
+       INSTANCE_WR(ctx, 0x420/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x424/4, 0x00000060);
+       INSTANCE_WR(ctx, 0x440/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x444/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x448/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x45c/4, 0x44400000);
+       INSTANCE_WR(ctx, 0x480/4, 0xffff0000);
+       for(i = 0x4d4; i< 0x4dc; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x4e0/4, 0x00011100);
+       for(i = 0x4fc; i< 0x53c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x544/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x57c/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x580/4, 0x30201000);
+       INSTANCE_WR(ctx, 0x584/4, 0x70605040);
+       INSTANCE_WR(ctx, 0x588/4, 0xb8a89888);
+       INSTANCE_WR(ctx, 0x58c/4, 0xf8e8d8c8);
+       INSTANCE_WR(ctx, 0x5a0/4, 0xb0000000);
+       for(i = 0x5f0; i< 0x630; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00010588);
+       for(i = 0x630; i< 0x670; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00030303);
+       for(i = 0x6b0; i< 0x6f0; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0008aae4);
+       for(i = 0x6f0; i< 0x730; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for(i = 0x730; i< 0x770; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       INSTANCE_WR(ctx, 0x850/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x854/4, 0x00010000);
+       for(i = 0x858; i< 0x868; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00040004);
+       INSTANCE_WR(ctx, 0x15ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x15b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x15b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x15bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x15c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x15c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x15cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x15d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x15d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x15dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x15e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x15e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x15ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x15f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x15f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x15fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1600/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1604/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x160c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1610/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1614/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x161c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1620/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1624/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x162c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1630/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1634/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x163c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1640/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1644/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x164c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1650/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1654/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x165c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1660/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1664/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x166c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1670/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1674/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x167c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1680/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1684/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x168c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1690/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1694/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x169c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x16a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x16a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x16ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x16b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x16b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x16bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x16c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x16c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x16cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x16d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x16d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x16dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x16e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x16e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x16ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x16f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x16f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x16fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1700/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1704/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x170c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1710/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1714/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x171c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1720/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1724/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x172c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1730/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1734/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x173c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1740/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1744/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x174c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1750/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1754/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x175c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1760/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1764/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x176c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1770/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1774/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x177c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1780/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1784/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x178c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1790/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1794/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x179c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x17a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x17a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x17ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x17b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x17b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x17bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x17c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x17c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x17cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x17d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x17d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x17dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x17e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x17e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x17ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x17f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x17f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x17fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1800/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1804/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x180c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1810/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1814/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x181c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1820/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1824/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x182c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1830/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1834/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x183c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1840/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1844/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x184c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1850/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1854/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x185c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1860/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1864/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x186c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1870/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1874/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x187c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1880/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1884/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x188c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1890/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1894/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x189c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x18a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x18a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x18ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x18b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x18b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x18bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x18c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x18c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x18cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x18d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x18d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x18dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x18e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x18e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x18ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x18f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x18f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x18fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1900/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1904/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x190c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1910/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1914/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x191c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1920/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1924/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x192c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1930/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1934/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x193c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1940/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1944/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x194c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1950/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1954/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x195c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1960/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1964/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x196c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1970/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1974/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x197c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1980/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1984/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x198c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1990/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1994/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x199c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x19a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x19a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x19ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x19b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x19b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x19bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x19c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x19c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x19cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x19d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x19d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x19dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x19e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x19e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x19ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x19f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x19f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x19fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1a90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1a94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1a9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1aa0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1aa4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1aac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ab0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ab4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1abc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ac0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ac4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1acc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ad0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ad4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1adc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ae0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ae4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1aec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1af0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1af4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1afc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1b90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1b94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1b9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ba0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ba4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1bac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1bb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1bb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1bbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1bc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1bc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1bcc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1bd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1bd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1bdc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1be0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1be4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1bec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1bf0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1bf4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1bfc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1c90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1c94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1c9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ca0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ca4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1cac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1cb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1cb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1cbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1cc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1cc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1ccc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1cd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1cd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1cdc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ce0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ce4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1cec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1cf0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1cf4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1cfc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1d90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1d94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1d9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1da0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1da4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1dac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1db0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1db4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1dbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1dc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1dc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1dcc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1dd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1dd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1ddc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1de0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1de4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1dec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1df0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1df4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1dfc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1e90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1e94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1e9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ea0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ea4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1eac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1eb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1eb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1ebc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ec0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ec4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1ecc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ed0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ed4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1edc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ee0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ee4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1eec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ef0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ef4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1efc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fa0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fa4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fcc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fdc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fe0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fe4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ff0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ff4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1ffc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2000/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2004/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x200c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2010/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2014/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x201c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2020/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2024/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x202c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2030/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2034/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x203c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2040/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2044/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x204c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2050/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2054/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x205c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2060/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2064/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x206c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2070/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2074/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x207c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2080/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2084/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x208c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2090/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2094/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x209c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2100/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2104/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x210c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2110/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2114/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x211c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2120/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2124/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x212c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2130/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2134/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x213c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2140/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2144/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x214c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2150/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2154/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x215c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2160/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2164/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x216c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2170/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2174/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x217c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2180/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2184/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x218c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2190/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2194/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x219c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2200/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2204/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x220c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2210/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2214/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x221c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2220/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2224/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x222c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2230/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2234/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x223c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2240/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2244/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x224c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2250/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2254/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x225c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2260/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2264/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x226c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2270/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2274/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x227c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2280/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2284/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x228c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2290/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2294/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x229c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2300/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2304/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x230c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2310/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2314/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x231c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2320/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2324/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x232c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2330/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2334/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x233c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2340/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2344/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x234c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2350/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2354/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x235c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2360/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2364/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x236c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2370/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2374/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x237c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2380/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2384/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x238c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2390/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2394/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x239c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2400/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2404/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x240c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2410/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2414/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x241c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2420/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2424/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x242c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2430/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2434/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x243c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2440/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2444/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x244c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2450/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2454/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x245c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2460/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2464/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x246c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2470/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2474/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x247c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2480/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2484/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x248c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2490/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2494/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x249c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2500/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2504/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x250c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2510/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2514/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x251c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2520/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2524/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x252c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2530/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2534/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x253c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2540/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2544/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x254c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2550/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2554/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x255c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2560/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2564/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x256c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2570/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2574/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x257c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2580/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2584/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x258c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2590/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2594/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x259c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2600/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2604/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x260c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2610/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2614/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x261c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2620/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2624/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x262c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2630/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2634/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x263c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2640/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2644/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x264c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2650/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2654/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x265c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2660/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2664/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x266c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2670/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2674/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x267c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2680/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2684/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x268c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2690/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2694/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x269c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2700/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2704/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x270c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2710/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2714/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x271c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2720/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2724/4, 0x000c001b);
+       for(i = 0x274c; i< 0x275c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x2ae0/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x2e9c/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x2eb0/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x2edc/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x2ee0/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x2ee4/4, 0x3f000000);
+       INSTANCE_WR(ctx, 0x2eec/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x2ef0/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x2ef8/4, 0xbf800000);
+       INSTANCE_WR(ctx, 0x2f00/4, 0xbf800000);
+}
+
+static void nv35_36_graph_context_init(struct drm_device *dev,
+                                       struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
+
+       INSTANCE_WR(ctx, 0x40c/4, 0x00000101);
+       INSTANCE_WR(ctx, 0x420/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x424/4, 0x00000060);
+       INSTANCE_WR(ctx, 0x440/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x444/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x448/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x45c/4, 0x44400000);
+       INSTANCE_WR(ctx, 0x488/4, 0xffff0000);
+       for(i = 0x4dc; i< 0x4e4; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x4e8/4, 0x00011100);
+       for(i = 0x504; i< 0x544; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x54c/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x588/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x58c/4, 0x30201000);
+       INSTANCE_WR(ctx, 0x590/4, 0x70605040);
+       INSTANCE_WR(ctx, 0x594/4, 0xb8a89888);
+       INSTANCE_WR(ctx, 0x598/4, 0xf8e8d8c8);
+       INSTANCE_WR(ctx, 0x5ac/4, 0xb0000000);
+       for(i = 0x604; i< 0x644; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00010588);
+       for(i = 0x644; i< 0x684; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00030303);
+       for(i = 0x6c4; i< 0x704; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0008aae4);
+       for(i = 0x704; i< 0x744; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for(i = 0x744; i< 0x784; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       INSTANCE_WR(ctx, 0x860/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x864/4, 0x00010000);
+       for(i = 0x868; i< 0x878; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00040004);
+       INSTANCE_WR(ctx, 0x1f1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1f90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1f94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1f9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fa0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fa4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fcc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fdc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1fe0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1fe4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1fec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x1ff0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x1ff4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x1ffc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2000/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2004/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x200c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2010/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2014/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x201c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2020/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2024/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x202c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2030/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2034/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x203c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2040/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2044/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x204c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2050/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2054/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x205c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2060/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2064/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x206c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2070/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2074/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x207c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2080/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2084/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x208c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2090/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2094/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x209c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x20f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x20f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x20fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2100/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2104/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x210c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2110/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2114/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x211c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2120/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2124/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x212c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2130/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2134/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x213c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2140/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2144/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x214c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2150/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2154/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x215c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2160/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2164/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x216c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2170/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2174/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x217c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2180/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2184/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x218c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2190/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2194/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x219c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x21f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x21f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x21fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2200/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2204/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x220c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2210/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2214/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x221c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2220/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2224/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x222c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2230/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2234/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x223c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2240/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2244/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x224c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2250/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2254/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x225c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2260/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2264/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x226c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2270/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2274/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x227c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2280/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2284/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x228c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2290/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2294/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x229c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x22f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x22f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x22fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2300/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2304/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x230c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2310/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2314/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x231c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2320/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2324/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x232c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2330/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2334/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x233c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2340/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2344/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x234c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2350/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2354/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x235c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2360/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2364/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x236c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2370/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2374/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x237c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2380/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2384/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x238c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2390/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2394/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x239c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x23f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x23f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x23fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2400/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2404/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x240c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2410/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2414/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x241c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2420/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2424/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x242c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2430/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2434/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x243c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2440/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2444/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x244c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2450/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2454/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x245c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2460/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2464/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x246c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2470/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2474/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x247c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2480/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2484/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x248c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2490/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2494/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x249c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x24f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x24f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x24fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2500/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2504/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x250c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2510/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2514/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x251c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2520/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2524/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x252c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2530/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2534/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x253c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2540/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2544/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x254c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2550/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2554/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x255c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2560/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2564/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x256c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2570/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2574/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x257c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2580/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2584/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x258c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2590/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2594/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x259c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x25f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x25f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x25fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2600/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2604/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x260c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2610/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2614/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x261c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2620/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2624/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x262c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2630/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2634/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x263c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2640/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2644/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x264c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2650/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2654/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x265c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2660/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2664/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x266c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2670/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2674/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x267c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2680/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2684/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x268c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2690/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2694/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x269c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x26f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x26f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x26fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2700/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2704/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x270c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2710/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2714/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x271c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2720/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2724/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x272c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2730/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2734/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x273c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2740/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2744/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x274c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2750/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2754/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x275c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2760/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2764/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x276c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2770/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2774/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x277c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2780/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2784/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x278c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2790/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2794/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x279c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x27f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x27f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x27fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2800/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2804/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x280c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2810/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2814/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x281c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2820/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2824/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x282c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2830/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2834/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x283c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2840/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2844/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x284c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2850/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2854/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x285c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2860/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2864/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x286c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2870/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2874/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x287c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2880/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2884/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x288c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2890/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2894/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x289c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x28f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x28f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x28fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2900/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2904/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x290c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2910/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2914/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x291c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2920/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2924/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x292c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2930/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2934/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x293c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2940/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2944/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x294c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2950/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2954/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x295c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2960/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2964/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x296c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2970/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2974/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x297c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2980/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2984/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x298c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2990/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2994/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x299c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29a0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29a4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29ac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29b0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29b4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29bc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29c0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29c4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29cc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29d0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29d4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29dc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29e0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29e4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29ec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x29f0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x29f4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x29fc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2a90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2a94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2a9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2aa0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2aa4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2aac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ab0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ab4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2abc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ac0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ac4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2acc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ad0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ad4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2adc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ae0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ae4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2aec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2af0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2af4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2afc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2b90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2b94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2b9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ba0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ba4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bcc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bdc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2be0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2be4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2bf0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2bf4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2bfc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2c90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2c94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2c9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ca0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ca4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ccc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cdc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ce0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ce4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2cf0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2cf4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2cfc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2d90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2d94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2d9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2da0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2da4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2dac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2db0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2db4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2dbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2dc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2dc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2dcc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2dd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2dd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ddc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2de0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2de4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2dec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2df0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2df4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2dfc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2e90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2e94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2e9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ea0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ea4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2eac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2eb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2eb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ebc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ec0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ec4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ecc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ed0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ed4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2edc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ee0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ee4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2eec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ef0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ef4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2efc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f00/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f04/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f0c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f10/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f14/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f1c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f20/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f24/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f2c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f30/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f34/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f3c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f40/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f44/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f4c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f50/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f54/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f5c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f60/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f64/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f6c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f70/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f74/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f7c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f80/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f84/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f8c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2f90/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2f94/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2f9c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fa0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fa4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fac/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fb0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fb4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fbc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fc0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fc4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fcc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fd0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fd4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fdc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2fe0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2fe4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2fec/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x2ff0/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x2ff4/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x2ffc/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3000/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3004/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x300c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3010/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3014/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x301c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3020/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3024/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x302c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3030/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3034/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x303c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3040/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3044/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x304c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3050/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3054/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x305c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3060/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3064/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x306c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3070/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3074/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x307c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3080/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3084/4, 0x000c001b);
+       INSTANCE_WR(ctx, 0x308c/4, 0x10700ff9);
+       INSTANCE_WR(ctx, 0x3090/4, 0x0436086c);
+       INSTANCE_WR(ctx, 0x3094/4, 0x000c001b);
+       for(i = 0x30bc; i< 0x30cc; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x3450/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x380c/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x3820/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x384c/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x3850/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x3854/4, 0x3f000000);
+       INSTANCE_WR(ctx, 0x385c/4, 0x40000000);
+       INSTANCE_WR(ctx, 0x3860/4, 0x3f800000);
+       INSTANCE_WR(ctx, 0x3868/4, 0xbf800000);
+       INSTANCE_WR(ctx, 0x3870/4, 0xbf800000);
+}
+
+int nv20_graph_create_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *);
+       unsigned int ctx_size;
+       unsigned int idoffs = 0x28/4;
+       int ret;
+
+       switch (dev_priv->chipset) {
+       case 0x20:
+               ctx_size = NV20_GRCTX_SIZE;
+               ctx_init = nv20_graph_context_init;
+               idoffs = 0;
+               break;
+       case 0x25:
+       case 0x28:
+               ctx_size = NV25_GRCTX_SIZE;
+               ctx_init = nv25_graph_context_init;
+               break;
+       case 0x2a:
+               ctx_size = NV2A_GRCTX_SIZE;
+               ctx_init = nv2a_graph_context_init;
+               idoffs = 0;
+               break;
+       case 0x30:
+       case 0x31:
+               ctx_size = NV30_31_GRCTX_SIZE;
+               ctx_init = nv30_31_graph_context_init;
+               break;
+       case 0x34:
+               ctx_size = NV34_GRCTX_SIZE;
+               ctx_init = nv34_graph_context_init;
+               break;
+       case 0x35:
+       case 0x36:
+               ctx_size = NV35_36_GRCTX_SIZE;
+               ctx_init = nv35_36_graph_context_init;
+               break;
+       default:
+               ctx_size = 0;
+               ctx_init = nv35_36_graph_context_init;
+               DRM_ERROR("Please contact the devs if you want your NV%x"
+                         " card to work\n", dev_priv->chipset);
+               return -ENOSYS;
+               break;
        }
-       if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx))
-               DRM_ERROR("nv20_graph_context_restore_current : bad instance\n");
 
-       NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24);
-       NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance);
-       NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */);
+       if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16,
+                                         NVOBJ_FLAG_ZERO_ALLOC,
+                                         &chan->ramin_grctx)))
+               return ret;
+
+       /* Initialise default context values */
+       ctx_init(dev, chan->ramin_grctx->gpuobj);
+
+       /* nv20: INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, chan->id<<24); */
+       INSTANCE_WR(chan->ramin_grctx->gpuobj, idoffs, (chan->id<<24)|0x1);
+                                                            /* CTX_USER */
+
+       INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id,
+                       chan->ramin_grctx->instance >> 4);
+
+       return 0;
 }
 
-void nouveau_nv20_context_switch(drm_device_t *dev)
+void nv20_graph_destroy_context(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int channel, channel_old;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (chan->ramin_grctx)
+               nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
+
+       INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0);
+}
 
-       channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
-       channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
+int nv20_graph_load_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t inst;
 
-       DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel);
+       if (!chan->ramin_grctx)
+               return -EINVAL;
+       inst = chan->ramin_grctx->instance >> 4;
 
-       NV_WRITE(NV04_PGRAPH_FIFO,0x0);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER,
+                NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD);
 
-       nv20_graph_context_save_current(dev, channel_old);
-       
        nouveau_wait_for_idle(dev);
+       return 0;
+}
 
-       NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000);
+int nv20_graph_save_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t inst;
+
+       if (!chan->ramin_grctx)
+               return -EINVAL;
+       inst = chan->ramin_grctx->instance >> 4;
 
-       nv20_graph_context_restore(dev, channel);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER,
+                NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE);
 
        nouveau_wait_for_idle(dev);
-       
-       if ((NV_READ(NV10_PGRAPH_CTX_USER) >> 24) != channel)
-               DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", channel, NV_READ(NV10_PGRAPH_CTX_USER) >> 24);
+       return 0;
+}
 
-       NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
-       NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF);
+static void nv20_graph_rdi(struct drm_device *dev) {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
 
-       NV_WRITE(NV04_PGRAPH_FIFO,0x1);
+       NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x2c80000);
+       for (i = 0; i < 32; i++)
+               NV_WRITE(NV10_PGRAPH_RDI_DATA, 0);
+
+       nouveau_wait_for_idle(dev);
 }
 
-int nv20_graph_init(drm_device_t *dev) {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       int i;
+int nv20_graph_init(struct drm_device *dev) {
+       struct drm_nouveau_private *dev_priv =
+               (struct drm_nouveau_private *)dev->dev_private;
        uint32_t tmp, vramsz;
+       int ret, i;
 
        NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
                        ~NV_PMC_ENABLE_PGRAPH);
@@ -145,25 +3194,24 @@ int nv20_graph_init(drm_device_t *dev) {
 
        /* Create Context Pointer Table */
        dev_priv->ctx_table_size = 32 * 4;
-       dev_priv->ctx_table = nouveau_instmem_alloc(dev, dev_priv->ctx_table_size, 4);
-       if (!dev_priv->ctx_table)
-               return DRM_ERR(ENOMEM);
+       if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
+                                         dev_priv->ctx_table_size, 16,
+                                         NVOBJ_FLAG_ZERO_ALLOC,
+                                         &dev_priv->ctx_table)))
+               return ret;
 
-       for (i=0; i< dev_priv->ctx_table_size; i+=4)
-               INSTANCE_WR(dev_priv->ctx_table, i/4, 0x00000000);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_TABLE,
+                dev_priv->ctx_table->instance >> 4);
 
-       NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_TABLE, nouveau_chip_instance_get(dev, dev_priv->ctx_table));
-
-       //XXX need to be done and save/restore for each fifo ???
        nv20_graph_rdi(dev);
 
-       NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
        NV_WRITE(NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+       NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
        NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
        NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
        NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x00118700);
-       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xF20E0431);
+       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xF20E0435); /* 0x4 = auto ctx switch */
        NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00000000);
        NV_WRITE(0x40009C           , 0x00000040);
 
@@ -228,7 +3276,98 @@ int nv20_graph_init(drm_device_t *dev) {
        return 0;
 }
 
-void nv20_graph_takedown(drm_device_t *dev)
+void nv20_graph_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       nouveau_gpuobj_ref_del(dev, &dev_priv->ctx_table);
+}
+
+int nv30_graph_init(struct drm_device *dev)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t vramsz, tmp;
+       int ret, i;
+
+       NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
+                       ~NV_PMC_ENABLE_PGRAPH);
+       NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
+                        NV_PMC_ENABLE_PGRAPH);
+
+       /* Create Context Pointer Table */
+       dev_priv->ctx_table_size = 32 * 4;
+       if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
+                                         dev_priv->ctx_table_size, 16,
+                                         NVOBJ_FLAG_ZERO_ALLOC,
+                                         &dev_priv->ctx_table)))
+               return ret;
+
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_TABLE,
+                       dev_priv->ctx_table->instance >> 4);
+
+       NV_WRITE(NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+       NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
+
+       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
+       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
+       NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x401287c0);
+       NV_WRITE(0x400890, 0x01b463ff);
+       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xf3de0475);
+       NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00008000);
+       NV_WRITE(NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6);
+       NV_WRITE(0x400B80, 0x1003d888);
+       NV_WRITE(0x400098, 0x00000000);
+       NV_WRITE(0x40009C, 0x0005ad00);
+       NV_WRITE(0x400B88, 0x62ff00ff); // suspiciously like PGRAPH_DEBUG_2
+       NV_WRITE(0x4000a0, 0x00000000);
+       NV_WRITE(0x4000a4, 0x00000008);
+       NV_WRITE(0x4008a8, 0xb784a400);
+       NV_WRITE(0x400ba0, 0x002f8685);
+       NV_WRITE(0x400ba4, 0x00231f3f);
+       NV_WRITE(0x4008a4, 0x40000020);
+       NV_WRITE(0x400B84, 0x0c000000);
+       NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x62ff0f7f);
+       NV_WRITE(0x4000c0, 0x00000016);
+
+       /* copy tile info from PFB */
+       for (i=0; i<NV10_PFB_TILE__SIZE; i++) {
+               NV_WRITE(NV10_PGRAPH_TILE(i), NV_READ(NV10_PFB_TILE(i)));
+               NV_WRITE(NV10_PGRAPH_TLIMIT(i), NV_READ(NV10_PFB_TLIMIT(i)));
+               NV_WRITE(NV10_PGRAPH_TSIZE(i), NV_READ(NV10_PFB_TSIZE(i)));
+               NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i)));
+       }
+
+       NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
+       NV_WRITE(NV10_PGRAPH_STATE      , 0xFFFFFFFF);
+       NV_WRITE(NV04_PGRAPH_FIFO       , 0x00000001);
+
+       /* begin RAM config */
+       vramsz = drm_get_resource_len(dev, 0) - 1;
+       NV_WRITE(0x4009A4, NV_READ(NV04_PFB_CFG0));
+       NV_WRITE(0x4009A8, NV_READ(NV04_PFB_CFG1));
+       NV_WRITE(0x400750, 0x00EA0000);
+       NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG0));
+       NV_WRITE(0x400750, 0x00EA0004);
+       NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG1));
+       NV_WRITE(0x400820, 0);
+       NV_WRITE(0x400824, 0);
+       NV_WRITE(0x400864, vramsz-1);
+       NV_WRITE(0x400868, vramsz-1);
+
+       NV_WRITE(0x400B20, 0x00000000);
+       NV_WRITE(0x400B04, 0xFFFFFFFF);
+
+       /* per-context state, doesn't belong here */
+       tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
+       NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
+       tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100;
+       NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
+
+       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_XMIN, 0);
+       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMIN, 0);
+       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff);
+       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff);
+
+       return 0;
 }
 
diff --git a/shared-core/nv30_graph.c b/shared-core/nv30_graph.c
deleted file mode 100644 (file)
index f4faadd..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Based on nv40_graph.c
- *  Someday this will all go away...
- */
-#include "drmP.h"
-#include "drm.h"
-#include "nouveau_drv.h"
-#include "nouveau_drm.h"
-
-/*
- *  This is obviously not the correct size. 
- */
-#define NV30_GRCTX_SIZE (23840)
-
-/*TODO: deciper what each offset in the context represents. The below
- *      contexts are taken from dumps just after the 3D object is
- *      created.
- */
-static void nv30_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
-{
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
-       int i;
-        
-        INSTANCE_WR(ctx, 0x28/4,  0x10000000);
-        INSTANCE_WR(ctx, 0x40c/4, 0x00000101);
-        INSTANCE_WR(ctx, 0x420/4, 0x00000111);
-        INSTANCE_WR(ctx, 0x424/4, 0x00000060);
-        INSTANCE_WR(ctx, 0x440/4, 0x00000080);
-        INSTANCE_WR(ctx, 0x444/4, 0xffff0000);
-        INSTANCE_WR(ctx, 0x448/4, 0x00000001);
-        INSTANCE_WR(ctx, 0x45c/4, 0x44400000);
-        INSTANCE_WR(ctx, 0x448/4, 0xffff0000);
-        INSTANCE_WR(ctx, 0x4dc/4, 0xfff00000);
-        INSTANCE_WR(ctx, 0x4e0/4, 0xfff00000);
-        INSTANCE_WR(ctx, 0x4e8/4, 0x00011100);
-
-        for (i = 0x504; i <= 0x540; i += 4)
-                INSTANCE_WR(ctx, i/4, 0x7ff00000);
-
-        INSTANCE_WR(ctx, 0x54c/4, 0x4b7fffff);
-        INSTANCE_WR(ctx, 0x588/4, 0x00000080);
-        INSTANCE_WR(ctx, 0x58c/4, 0x30201000);
-        INSTANCE_WR(ctx, 0x590/4, 0x70605040);
-        INSTANCE_WR(ctx, 0x594/4, 0xb8a89888);
-        INSTANCE_WR(ctx, 0x598/4, 0xf8e8d8c8);
-        INSTANCE_WR(ctx, 0x5ac/4, 0xb0000000);
-
-        for (i = 0x604; i <= 0x640; i += 4)
-                INSTANCE_WR(ctx, i/4, 0x00010588);
-
-        for (i = 0x644; i <= 0x680; i += 4)
-                INSTANCE_WR(ctx, i/4, 0x00030303);
-
-        for (i = 0x6c4; i <= 0x700; i += 4)
-                INSTANCE_WR(ctx, i/4, 0x0008aae4);
-
-        for (i = 0x704; i <= 0x740; i += 4)
-                INSTANCE_WR(ctx, i/4, 0x1012000);
-
-        for (i = 0x744; i <= 0x780; i += 4)
-                INSTANCE_WR(ctx, i/4, 0x0080008);
-
-        INSTANCE_WR(ctx, 0x860/4, 0x00040000);
-        INSTANCE_WR(ctx, 0x864/4, 0x00010000);
-        INSTANCE_WR(ctx, 0x868/4, 0x00040000);
-        INSTANCE_WR(ctx, 0x86c/4, 0x00040000);
-        INSTANCE_WR(ctx, 0x870/4, 0x00040000);
-        INSTANCE_WR(ctx, 0x874/4, 0x00040000);
-
-        for (i = 0x00; i <= 0x1170; i += 0x10)
-        {
-                INSTANCE_WR(ctx, (0x1f24 + i)/4, 0x000c001b);
-                INSTANCE_WR(ctx, (0x1f20 + i)/4, 0x0436086c);
-                INSTANCE_WR(ctx, (0x1f1c + i)/4, 0x10700ff9);
-        }
-
-        INSTANCE_WR(ctx, 0x30bc/4, 0x0000ffff);
-        INSTANCE_WR(ctx, 0x30c0/4, 0x0000ffff);
-        INSTANCE_WR(ctx, 0x30c4/4, 0x0000ffff);
-        INSTANCE_WR(ctx, 0x30c8/4, 0x0000ffff);
-
-        INSTANCE_WR(ctx, 0x380c/4, 0x3f800000);
-        INSTANCE_WR(ctx, 0x3450/4, 0x3f800000);
-        INSTANCE_WR(ctx, 0x3820/4, 0x3f800000);
-        INSTANCE_WR(ctx, 0x3854/4, 0x3f800000);
-        INSTANCE_WR(ctx, 0x3850/4, 0x3f000000);
-        INSTANCE_WR(ctx, 0x384c/4, 0x40000000);
-        INSTANCE_WR(ctx, 0x3868/4, 0xbf800000);
-        INSTANCE_WR(ctx, 0x3860/4, 0x3f800000);
-        INSTANCE_WR(ctx, 0x386c/4, 0x40000000);
-        INSTANCE_WR(ctx, 0x3870/4, 0xbf800000);
-
-        for (i = 0x4e0; i <= 0x4e1c; i += 4)
-                INSTANCE_WR(ctx, i/4, 0x001c527d);
-        INSTANCE_WR(ctx, 0x4e40, 0x001c527c);
-
-        INSTANCE_WR(ctx, 0x5680/4, 0x000a0000);
-        INSTANCE_WR(ctx, 0x87c/4, 0x10000000);
-        INSTANCE_WR(ctx, 0x28/4, 0x10000011);
-}
-
-
-int nv30_graph_context_create(drm_device_t *dev, int channel)
-{
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       void (*ctx_init)(drm_device_t *, struct mem_block *);
-       unsigned int ctx_size;
-       int i;
-
-       switch (dev_priv->chipset) {
-       default:
-               ctx_size = NV30_GRCTX_SIZE;
-               ctx_init = nv30_graph_context_init;
-               break;
-       }
-
-       /* Alloc and clear RAMIN to store the context */
-       chan->ramin_grctx = nouveau_instmem_alloc(dev, ctx_size, 4);
-       if (!chan->ramin_grctx)
-               return DRM_ERR(ENOMEM);
-       for (i=0; i<ctx_size; i+=4)
-               INSTANCE_WR(chan->ramin_grctx, i/4, 0x00000000);
-
-       /* Initialise default context values */
-       ctx_init(dev, chan->ramin_grctx);
-        
-        INSTANCE_WR(chan->ramin_grctx, 10, channel << 24); /* CTX_USER */
-        INSTANCE_WR(dev_priv->ctx_table, channel, nouveau_chip_instance_get(dev, chan->ramin_grctx));
-
-       return 0;
-}
-
-int nv30_graph_init(drm_device_t *dev)
-{
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       uint32_t vramsz, tmp;
-       int i;
-
-       NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
-                       ~NV_PMC_ENABLE_PGRAPH);
-       NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
-                        NV_PMC_ENABLE_PGRAPH);
-
-        /* Create Context Pointer Table */
-        dev_priv->ctx_table_size = 32 * 4;
-        dev_priv->ctx_table = nouveau_instmem_alloc(dev, dev_priv->ctx_table_size, 4);
-        if (!dev_priv->ctx_table)
-                return DRM_ERR(ENOMEM);
-
-        for (i=0; i< dev_priv->ctx_table_size; i+=4)
-                INSTANCE_WR(dev_priv->ctx_table, i/4, 0x00000000);
-
-        NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_TABLE, nouveau_chip_instance_get(dev, dev_priv->ctx_table));
-
-       NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
-       NV_WRITE(NV03_PGRAPH_INTR   , 0xFFFFFFFF);
-
-       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
-       NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
-       NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x401287c0);
-       NV_WRITE(0x400890, 0x00140000);
-       NV_WRITE(NV04_PGRAPH_DEBUG_3, 0xf0de0475);
-       NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x10008000);
-       NV_WRITE(NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04b1f36);
-       NV_WRITE(0x400B80, 0x1003d888);
-       NV_WRITE(0x400B84, 0x0c000000);
-       NV_WRITE(0x400B88, 0x62ff0f7f);
-       NV_WRITE(0x400098, 0x000000c0);
-       NV_WRITE(0x40009C, 0x0005dc00);
-       NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x62ff0f7f);
-       NV_WRITE(0x4000a0, 0x00000000);
-       NV_WRITE(0x4000a4, 0x00000008);
-
-       /* copy tile info from PFB */
-       for (i=0; i<NV10_PFB_TILE__SIZE; i++) {
-               NV_WRITE(NV10_PGRAPH_TILE(i), NV_READ(NV10_PFB_TILE(i)));
-               NV_WRITE(NV10_PGRAPH_TLIMIT(i), NV_READ(NV10_PFB_TLIMIT(i)));
-               NV_WRITE(NV10_PGRAPH_TSIZE(i), NV_READ(NV10_PFB_TSIZE(i)));
-               NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i)));
-       }
-
-       NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
-       NV_WRITE(NV10_PGRAPH_STATE      , 0xFFFFFFFF);
-       NV_WRITE(NV04_PGRAPH_FIFO       , 0x00000001);
-
-       /* begin RAM config */
-       vramsz = drm_get_resource_len(dev, 0) - 1;
-       NV_WRITE(0x4009A4, NV_READ(NV04_PFB_CFG0));
-       NV_WRITE(0x4009A8, NV_READ(NV04_PFB_CFG1));
-       NV_WRITE(0x400750, 0x00EA0000);
-       NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG0));
-       NV_WRITE(0x400750, 0x00EA0004);
-       NV_WRITE(0x400754, NV_READ(NV04_PFB_CFG1));
-       NV_WRITE(0x400820, 0);
-       NV_WRITE(0x400824, 0);
-       NV_WRITE(0x400864, vramsz-1);
-       NV_WRITE(0x400868, vramsz-1);
-
-       NV_WRITE(0x400B20, 0x00000000);
-       NV_WRITE(0x400B04, 0xFFFFFFFF);
-
-       /* per-context state, doesn't belong here */
-       tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
-       NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
-       tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100;
-       NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
-
-       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_XMIN, 0);
-       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMIN, 0);
-       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff);
-       NV_WRITE(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff);
-
-       return 0;
-}
-
-void nv30_graph_takedown(drm_device_t *dev)
-{
-}
-
index 83a7580..2cbb40e 100644 (file)
@@ -4,9 +4,9 @@
 #include "nouveau_drm.h"
 
 int
-nv40_fb_init(drm_device_t *dev)
+nv40_fb_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t fb_bar_size, tmp;
        int num_tiles;
        int i;
@@ -50,7 +50,7 @@ nv40_fb_init(drm_device_t *dev)
 }
 
 void
-nv40_fb_takedown(drm_device_t *dev)
+nv40_fb_takedown(struct drm_device *dev)
 {
 }
 
diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c
new file mode 100644 (file)
index 0000000..ce3f8fd
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+
+#define RAMFC_WR(offset,val) INSTANCE_WR(chan->ramfc->gpuobj, \
+                                        NV40_RAMFC_##offset/4, (val))
+#define RAMFC_RD(offset)     INSTANCE_RD(chan->ramfc->gpuobj, \
+                                        NV40_RAMFC_##offset/4)
+#define NV40_RAMFC(c) (dev_priv->ramfc_offset + ((c)*NV40_RAMFC__SIZE))
+#define NV40_RAMFC__SIZE 128
+
+int
+nv40_fifo_create_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0,
+                                               NV40_RAMFC__SIZE,
+                                               NVOBJ_FLAG_ZERO_ALLOC |
+                                               NVOBJ_FLAG_ZERO_FREE,
+                                               NULL, &chan->ramfc)))
+               return ret;
+
+       /* Fill entries that are seen filled in dumps of nvidia driver just
+        * after channel's is put into DMA mode
+        */
+       RAMFC_WR(DMA_PUT       , chan->pushbuf_base);
+       RAMFC_WR(DMA_GET       , chan->pushbuf_base);
+       RAMFC_WR(DMA_INSTANCE  , chan->pushbuf->instance >> 4);
+       RAMFC_WR(DMA_FETCH     , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+                                NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+                                NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+                                NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+                                0x30000000 /* no idea.. */);
+       RAMFC_WR(DMA_SUBROUTINE, 0);
+       RAMFC_WR(GRCTX_INSTANCE, chan->ramin_grctx->instance >> 4);
+       RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF);
+
+       /* enable the fifo dma operation */
+       NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<chan->id));
+       return 0;
+}
+
+void
+nv40_fifo_destroy_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<chan->id));
+
+       if (chan->ramfc)
+               nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+}
+
+int
+nv40_fifo_load_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t tmp, tmp2;
+
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET          , RAMFC_RD(DMA_GET));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT          , RAMFC_RD(DMA_PUT));
+       NV_WRITE(NV10_PFIFO_CACHE1_REF_CNT          , RAMFC_RD(REF_CNT));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE     , RAMFC_RD(DMA_INSTANCE));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT       , RAMFC_RD(DMA_DCOUNT));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE        , RAMFC_RD(DMA_STATE));
+
+       /* No idea what 0x2058 is.. */
+       tmp   = RAMFC_RD(DMA_FETCH);
+       tmp2  = NV_READ(0x2058) & 0xFFF;
+       tmp2 |= (tmp & 0x30000000);
+       NV_WRITE(0x2058, tmp2);
+       tmp  &= ~0x30000000;
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH        , tmp);
+
+       NV_WRITE(NV04_PFIFO_CACHE1_ENGINE           , RAMFC_RD(ENGINE));
+       NV_WRITE(NV04_PFIFO_CACHE1_PULL1            , RAMFC_RD(PULL1_ENGINE));
+       NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_VALUE    , RAMFC_RD(ACQUIRE_VALUE));
+       NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, RAMFC_RD(ACQUIRE_TIMESTAMP));
+       NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT  , RAMFC_RD(ACQUIRE_TIMEOUT));
+       NV_WRITE(NV10_PFIFO_CACHE1_SEMAPHORE        , RAMFC_RD(SEMAPHORE));
+       NV_WRITE(NV10_PFIFO_CACHE1_DMA_SUBROUTINE   , RAMFC_RD(DMA_SUBROUTINE));
+       NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE          , RAMFC_RD(GRCTX_INSTANCE));
+       NV_WRITE(0x32e4, RAMFC_RD(UNK_40));
+       /* NVIDIA does this next line twice... */
+       NV_WRITE(0x32e8, RAMFC_RD(UNK_44));
+       NV_WRITE(0x2088, RAMFC_RD(UNK_4C));
+       NV_WRITE(0x3300, RAMFC_RD(UNK_50));
+
+       /* not sure what part is PUT, and which is GET.. never seen a non-zero
+        * value appear in a mmio-trace yet..
+        */
+#if 0
+       tmp = NV_READ(UNK_84);
+       NV_WRITE(NV_PFIFO_CACHE1_GET, tmp ???);
+       NV_WRITE(NV_PFIFO_CACHE1_PUT, tmp ???);
+#endif
+
+       /* Don't clobber the TIMEOUT_ENABLED flag when restoring from RAMFC */
+       tmp  = NV_READ(NV04_PFIFO_DMA_TIMESLICE) & ~0x1FFFF;
+       tmp |= RAMFC_RD(DMA_TIMESLICE) & 0x1FFFF;
+       NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, tmp);
+
+       /* Set channel active, and in DMA mode */
+       NV_WRITE(NV03_PFIFO_CACHE1_PUSH1  , 0x00010000 | chan->id);
+       /* Reset DMA_CTL_AT_INFO to INVALID */
+       tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+       return 0;
+}
+
+int
+nv40_fifo_save_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       RAMFC_WR(DMA_PUT          , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
+       RAMFC_WR(DMA_GET          , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+       RAMFC_WR(REF_CNT          , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
+       RAMFC_WR(DMA_INSTANCE     , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE));
+       RAMFC_WR(DMA_DCOUNT       , NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT));
+       RAMFC_WR(DMA_STATE        , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
+
+       tmp  = NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH);
+       tmp |= NV_READ(0x2058) & 0x30000000;
+       RAMFC_WR(DMA_FETCH        , tmp);
+
+       RAMFC_WR(ENGINE           , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
+       RAMFC_WR(PULL1_ENGINE     , NV_READ(NV04_PFIFO_CACHE1_PULL1));
+       RAMFC_WR(ACQUIRE_VALUE    , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
+       tmp = NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP);
+       RAMFC_WR(ACQUIRE_TIMESTAMP, tmp);
+       RAMFC_WR(ACQUIRE_TIMEOUT  , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
+       RAMFC_WR(SEMAPHORE        , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
+
+       /* NVIDIA read 0x3228 first, then write DMA_GET here.. maybe something
+        * more involved depending on the value of 0x3228?
+        */
+       RAMFC_WR(DMA_SUBROUTINE   , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+
+       RAMFC_WR(GRCTX_INSTANCE   , NV_READ(NV40_PFIFO_GRCTX_INSTANCE));
+
+       /* No idea what the below is for exactly, ripped from a mmio-trace */
+       RAMFC_WR(UNK_40           , NV_READ(NV40_PFIFO_UNK32E4));
+
+       /* NVIDIA do this next line twice.. bug? */
+       RAMFC_WR(UNK_44           , NV_READ(0x32e8));
+       RAMFC_WR(UNK_4C           , NV_READ(0x2088));
+       RAMFC_WR(UNK_50           , NV_READ(0x3300));
+
+#if 0 /* no real idea which is PUT/GET in UNK_48.. */
+       tmp  = NV_READ(NV04_PFIFO_CACHE1_GET);
+       tmp |= (NV_READ(NV04_PFIFO_CACHE1_PUT) << 16);
+       RAMFC_WR(UNK_48           , tmp);
+#endif
+
+       return 0;
+}
+
+int
+nv40_fifo_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int ret;
+
+       if ((ret = nouveau_fifo_init(dev)))
+               return ret;
+
+       NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, 0x2101ffff);
+       return 0;
+}
+
index 792734e..7ce4273 100644 (file)
@@ -1,7 +1,32 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
 #include "drm.h"
 #include "nouveau_drv.h"
-#include "nouveau_drm.h"
 
 /* The sizes are taken from the difference between the start of two
  * grctx addresses while running the nvidia driver.  Probably slightly
@@ -9,9 +34,13 @@
  * between the contexts
  */
 #define NV40_GRCTX_SIZE (175*1024)
+#define NV41_GRCTX_SIZE (92*1024)
 #define NV43_GRCTX_SIZE (70*1024)
 #define NV46_GRCTX_SIZE (70*1024) /* probably ~64KiB */
+#define NV47_GRCTX_SIZE (125*1024)
+#define NV49_GRCTX_SIZE (164640)
 #define NV4A_GRCTX_SIZE (64*1024)
+#define NV4B_GRCTX_SIZE (164640)
 #define NV4C_GRCTX_SIZE (25*1024)
 #define NV4E_GRCTX_SIZE (25*1024)
 
  *      contexts are taken from dumps just after the 3D object is
  *      created.
  */
-static void nv40_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv40_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
 
        /* Always has the "instance address" of itself at offset 0 */
-       INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
        /* unknown */
        INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff);
@@ -160,12 +190,122 @@ static void nv40_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
 }
 
 static void
-nv43_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+nv41_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
+
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
+       INSTANCE_WR(ctx, 0x00000024/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00000028/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00000030/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x0000011c/4, 0x20010001);
+       INSTANCE_WR(ctx, 0x00000120/4, 0x0f73ef00);
+       INSTANCE_WR(ctx, 0x00000128/4, 0x02008821);
+       for (i = 0x00000178; i <= 0x00000180; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00000188/4, 0x00000040);
+       for (i = 0x00000194; i <= 0x000001b0; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x000001d0/4, 0x0b0b0b0c);
+       INSTANCE_WR(ctx, 0x00000340/4, 0x00040000);
+       for (i = 0x00000350; i <= 0x0000035c; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x00000388/4, 0x00000008);
+       INSTANCE_WR(ctx, 0x0000039c/4, 0x00001010);
+       INSTANCE_WR(ctx, 0x000003cc/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x000003d0/4, 0x00080060);
+       INSTANCE_WR(ctx, 0x000003ec/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x000003f0/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x000003f4/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00000408/4, 0x46400000);
+       INSTANCE_WR(ctx, 0x00000418/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x00000424/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x00000428/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x00000430/4, 0x00011100);
+       for (i = 0x0000044c; i <= 0x00000488; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x00000494/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x000004bc/4, 0x30201000);
+       INSTANCE_WR(ctx, 0x000004c0/4, 0x70605040);
+       INSTANCE_WR(ctx, 0x000004c4/4, 0xb8a89888);
+       INSTANCE_WR(ctx, 0x000004c8/4, 0xf8e8d8c8);
+       INSTANCE_WR(ctx, 0x000004dc/4, 0x40100000);
+       INSTANCE_WR(ctx, 0x000004f8/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x0000052c/4, 0x435185d6);
+       INSTANCE_WR(ctx, 0x00000530/4, 0x2155b699);
+       INSTANCE_WR(ctx, 0x00000534/4, 0xfedcba98);
+       INSTANCE_WR(ctx, 0x00000538/4, 0x00000098);
+       INSTANCE_WR(ctx, 0x00000548/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x0000054c/4, 0x00ff7000);
+       INSTANCE_WR(ctx, 0x00000550/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00000560/4, 0x00ff0000);
+       INSTANCE_WR(ctx, 0x00000598/4, 0x00ffff00);
+       for (i = 0x000005dc; i <= 0x00000618; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00018488);
+       for (i = 0x0000061c; i <= 0x00000658; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00028202);
+       for (i = 0x0000069c; i <= 0x000006d8; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0000aae4);
+       for (i = 0x000006dc; i <= 0x00000718; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for (i = 0x0000071c; i <= 0x00000758; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       for (i = 0x0000079c; i <= 0x000007d8; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00100008);
+       for (i = 0x0000082c; i <= 0x00000838; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x0001bc80);
+       for (i = 0x0000083c; i <= 0x00000848; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00000202);
+       for (i = 0x0000085c; i <= 0x00000868; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00000008);
+       for (i = 0x0000087c; i <= 0x00000888; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       INSTANCE_WR(ctx, 0x0000089c/4, 0x00000002);
+       INSTANCE_WR(ctx, 0x000008d0/4, 0x00000021);
+       INSTANCE_WR(ctx, 0x000008d4/4, 0x030c30c3);
+       INSTANCE_WR(ctx, 0x000008e0/4, 0x3e020200);
+       INSTANCE_WR(ctx, 0x000008e4/4, 0x00ffffff);
+       INSTANCE_WR(ctx, 0x000008e8/4, 0x20103f00);
+       INSTANCE_WR(ctx, 0x000008f4/4, 0x00020000);
+       INSTANCE_WR(ctx, 0x0000092c/4, 0x00008100);
+       INSTANCE_WR(ctx, 0x000009b8/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x000009fc/4, 0x00001001);
+       INSTANCE_WR(ctx, 0x00000a04/4, 0x00000003);
+       INSTANCE_WR(ctx, 0x00000a08/4, 0x00888001);
+       INSTANCE_WR(ctx, 0x00000aac/4, 0x00000005);
+       INSTANCE_WR(ctx, 0x00000ab8/4, 0x0000ffff);
+       for (i = 0x00000ad4; i <= 0x00000ae4; i += 4)
+               INSTANCE_WR(ctx, i/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00000ae8/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00000b20/4, 0x00000001);
+       for (i = 0x00002ee8; i <= 0x00002f60; i += 8)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i = 0x00005168; i <= 0x00007358; i += 24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i = 0x00007368; i <= 0x00007758; i += 16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i = 0x0000a068; i <= 0x0000c258; i += 24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i = 0x0000c268; i <= 0x0000c658; i += 16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i = 0x0000ef68; i <= 0x00011158; i += 24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i = 0x00011168; i <= 0x00011558; i += 16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i = 0x00013e68; i <= 0x00016058; i += 24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i = 0x00016068; i <= 0x00016458; i += 16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+};
+
+static void
+nv43_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
        
-       INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
        INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00030/4, 0x00000001);
@@ -275,12 +415,13 @@ nv43_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
                INSTANCE_WR(ctx, i/4, 0x3f800000);
 };
 
-static void nv46_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv46_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
 
-       INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
        INSTANCE_WR(ctx, 0x00040/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00044/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x0004c/4, 0x00000001);
@@ -425,12 +566,366 @@ static void nv46_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
                INSTANCE_WR(ctx, i/4, 0x3f800000);
 }
 
-static void nv4a_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+/* This may only work on 7800 AGP cards, will include a warning */
+static void
+nv47_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
 
-       INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+       INSTANCE_WR(ctx, 0x00000000/4, ctx->im_pramin->start);
+       INSTANCE_WR(ctx, 0x00000024/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00000028/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00000030/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x0000011c/4, 0x20010001);
+       INSTANCE_WR(ctx, 0x00000120/4, 0x0f73ef00);
+       INSTANCE_WR(ctx, 0x00000128/4, 0x02008821);
+       INSTANCE_WR(ctx, 0x00000178/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x0000017c/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00000180/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00000188/4, 0x00000040);
+       for (i=0x00000194; i<=0x000001b0; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x000001d0/4, 0x0b0b0b0c);
+       INSTANCE_WR(ctx, 0x00000340/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x00000350/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x00000354/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x00000358/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x0000035c/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x00000388/4, 0x00000008);
+       INSTANCE_WR(ctx, 0x0000039c/4, 0x00001010);
+       for (i=0x000003c0; i<=0x000003fc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00000454/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00000458/4, 0x00080060);
+       INSTANCE_WR(ctx, 0x00000474/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x00000478/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x0000047c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00000490/4, 0x46400000);
+       INSTANCE_WR(ctx, 0x000004a0/4, 0xffff0000);
+       for (i=0x000004a4; i<=0x000004e0; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x000004f4/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x000004f8/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x00000500/4, 0x00011100);
+       for (i=0x0000051c; i<=0x00000558; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x00000564/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x0000058c/4, 0x30201000);
+       INSTANCE_WR(ctx, 0x00000590/4, 0x70605040);
+       INSTANCE_WR(ctx, 0x00000594/4, 0xb8a89888);
+       INSTANCE_WR(ctx, 0x00000598/4, 0xf8e8d8c8);
+       INSTANCE_WR(ctx, 0x000005ac/4, 0x40100000);
+       INSTANCE_WR(ctx, 0x000005c8/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x000005fc/4, 0x435185d6);
+       INSTANCE_WR(ctx, 0x00000600/4, 0x2155b699);
+       INSTANCE_WR(ctx, 0x00000604/4, 0xfedcba98);
+       INSTANCE_WR(ctx, 0x00000608/4, 0x00000098);
+       INSTANCE_WR(ctx, 0x00000618/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x0000061c/4, 0x00ff7000);
+       INSTANCE_WR(ctx, 0x00000620/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00000630/4, 0x00ff0000);
+       INSTANCE_WR(ctx, 0x0000066c/4, 0x00ffff00);
+       for (i=0x000006b0; i<=0x000006ec; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00018488);
+       for (i=0x000006f0; i<=0x0000072c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00028202);
+       for (i=0x00000770; i<=0x000007ac; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x0000aae4);
+       for (i=0x000007b0; i<=0x000007ec; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for (i=0x000007f0; i<=0x0000082c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       for (i=0x00000870; i<=0x000008ac; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00100008);
+       INSTANCE_WR(ctx, 0x00000900/4, 0x0001bc80);
+       INSTANCE_WR(ctx, 0x00000904/4, 0x0001bc80);
+       INSTANCE_WR(ctx, 0x00000908/4, 0x0001bc80);
+       INSTANCE_WR(ctx, 0x0000090c/4, 0x0001bc80);
+       INSTANCE_WR(ctx, 0x00000910/4, 0x00000202);
+       INSTANCE_WR(ctx, 0x00000914/4, 0x00000202);
+       INSTANCE_WR(ctx, 0x00000918/4, 0x00000202);
+       INSTANCE_WR(ctx, 0x0000091c/4, 0x00000202);
+       for (i=0x00000930; i<=0x0000095c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00000008);
+       INSTANCE_WR(ctx, 0x00000970/4, 0x00000002);
+       INSTANCE_WR(ctx, 0x000009a4/4, 0x00000021);
+       INSTANCE_WR(ctx, 0x000009a8/4, 0x030c30c3);
+       INSTANCE_WR(ctx, 0x000009b4/4, 0x3e020200);
+       INSTANCE_WR(ctx, 0x000009b8/4, 0x00ffffff);
+       INSTANCE_WR(ctx, 0x000009bc/4, 0x40103f00);
+       INSTANCE_WR(ctx, 0x000009c8/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x00000a00/4, 0x00008100);
+       INSTANCE_WR(ctx, 0x00000a8c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00000ad0/4, 0x00001001);
+       INSTANCE_WR(ctx, 0x00000adc/4, 0x00000003);
+       INSTANCE_WR(ctx, 0x00000ae0/4, 0x00888001);
+       for (i=0x00000b10; i<=0x00000b8c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00000bb4/4, 0x00000005);
+       INSTANCE_WR(ctx, 0x00000bc0/4, 0x0000ffff);
+       for (i=0x00000bdc; i<=0x00000bf8; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00000bfc/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00000c34/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00000c38/4, 0x08e00001);
+       INSTANCE_WR(ctx, 0x00000c3c/4, 0x000e3000);
+       for (i=0x00003000; i<=0x00003078; i+=8)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i=0x00004dc0; i<=0x00006fb0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i=0x00006fc0; i<=0x000073b0; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i=0x00009800; i<=0x0000b9f0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i=0x0000ba00; i<=0x00010430; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i=0x00010440; i<=0x00010830; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i=0x00012c80; i<=0x00014e70; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i=0x00014e80; i<=0x00015270; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i=0x000176c0; i<=0x000198b0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i=0x000198c0; i<=0x00019cb0; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for (i=0x0001c100; i<=0x0001e2f0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for (i=0x0001e300; i<=0x0001e6f0; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+}
+
+static void
+nv49_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
+
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
+       INSTANCE_WR(ctx, 0x00004/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00008/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x0000c/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00010/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00014/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00018/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x0001c/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00020/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x000c4/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x000c8/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x000d0/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x001bc/4, 0x20010001);
+       INSTANCE_WR(ctx, 0x001c0/4, 0x0f73ef00);
+       INSTANCE_WR(ctx, 0x001c8/4, 0x02008821);
+       INSTANCE_WR(ctx, 0x00218/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x0021c/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00220/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00228/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00234/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00238/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x0023c/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00240/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00244/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00248/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x0024c/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00250/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00270/4, 0x0b0b0b0c);
+       INSTANCE_WR(ctx, 0x003e0/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x003f0/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x003f4/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x003f8/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x003fc/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x00428/4, 0x00000008);
+       INSTANCE_WR(ctx, 0x0043c/4, 0x00001010);
+       INSTANCE_WR(ctx, 0x00460/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00464/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00468/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0046c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00470/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00474/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00478/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0047c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00480/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00484/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00488/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0048c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00490/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00494/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00498/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0049c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x004f4/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x004f8/4, 0x00080060);
+       INSTANCE_WR(ctx, 0x00514/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x00518/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x0051c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00530/4, 0x46400000);
+       INSTANCE_WR(ctx, 0x00540/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x00544/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00548/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0054c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00550/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00554/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00558/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0055c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00560/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00564/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00568/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0056c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00570/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00574/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00578/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0057c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00580/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00594/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x00598/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x005a0/4, 0x00011100);
+       INSTANCE_WR(ctx, 0x005bc/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005c0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005c4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005c8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005cc/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005d0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005d4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005d8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005dc/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005e0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005e4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005e8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005ec/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005f0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005f4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005f8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x00604/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x0062c/4, 0x30201000);
+       INSTANCE_WR(ctx, 0x00630/4, 0x70605040);
+       INSTANCE_WR(ctx, 0x00634/4, 0xb8a89888);
+       INSTANCE_WR(ctx, 0x00638/4, 0xf8e8d8c8);
+       INSTANCE_WR(ctx, 0x0064c/4, 0x40100000);
+       INSTANCE_WR(ctx, 0x00668/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x0069c/4, 0x435185d6);
+       INSTANCE_WR(ctx, 0x006a0/4, 0x2155b699);
+       INSTANCE_WR(ctx, 0x006a4/4, 0xfedcba98);
+       INSTANCE_WR(ctx, 0x006a8/4, 0x00000098);
+       INSTANCE_WR(ctx, 0x006b8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x006bc/4, 0x00ff7000);
+       INSTANCE_WR(ctx, 0x006c0/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x006d0/4, 0x00ff0000);
+       INSTANCE_WR(ctx, 0x0070c/4, 0x00ffff00);
+       for (i=0x00750; i<=0x0078c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00018488);
+       for (i=0x00790; i<=0x007cc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00028202);
+       for (i=0x00810; i<=0x0084c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x0000aae4);
+       for (i=0x00850; i<=0x0088c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for (i=0x00890; i<=0x008cc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       for (i=0x00910; i<=0x0094c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00100008);
+       for (i=0x009a0; i<=0x009ac; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x0001bc80);
+       for (i=0x009b0; i<=0x009bc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00000202);
+       for (i=0x009d0; i<=0x009dc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00000008);
+       for (i=0x009f0; i<=0x009fc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       INSTANCE_WR(ctx, 0x00a10/4, 0x00000002);
+       INSTANCE_WR(ctx, 0x00a44/4, 0x00000421);
+       INSTANCE_WR(ctx, 0x00a48/4, 0x030c30c3);
+       INSTANCE_WR(ctx, 0x00a54/4, 0x3e020200);
+       INSTANCE_WR(ctx, 0x00a58/4, 0x00ffffff);
+       INSTANCE_WR(ctx, 0x00a5c/4, 0x20103f00);
+       INSTANCE_WR(ctx, 0x00a68/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x00aa0/4, 0x00008100);
+       INSTANCE_WR(ctx, 0x00b2c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00b70/4, 0x00001001);
+       INSTANCE_WR(ctx, 0x00b7c/4, 0x00000003);
+       INSTANCE_WR(ctx, 0x00b80/4, 0x00888001);
+       INSTANCE_WR(ctx, 0x00bb0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bb4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bb8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bbc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bc0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bc4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bc8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bcc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bd0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bd4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bd8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bdc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00be0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00be4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00be8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bec/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bf0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bf4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bf8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bfc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c00/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c04/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c08/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c0c/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c10/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c14/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c18/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c1c/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c20/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c24/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c28/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c2c/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c54/4, 0x00000005);
+       INSTANCE_WR(ctx, 0x00c60/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00c7c/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c80/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c84/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c88/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c8c/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c90/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c94/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c98/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c9c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00cd4/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00cd8/4, 0x08e00001);
+       INSTANCE_WR(ctx, 0x00cdc/4, 0x000e3000);
+       for(i=0x030a0; i<=0x03118; i+=8)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x098a0; i<=0x0ba90; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x0baa0; i<=0x0be90; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x0e2e0; i<=0x0fff0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x10008; i<=0x104d0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x104e0; i<=0x108d0; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x12d20; i<=0x14f10; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x14f20; i<=0x15310; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x17760; i<=0x19950; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x19960; i<=0x19d50; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x1c1a0; i<=0x1e390; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x1e3a0; i<=0x1e790; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x20be0; i<=0x22dd0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x22de0; i<=0x231d0; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+}
+
+static void
+nv4a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
+
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
        INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00030/4, 0x00000001);
@@ -541,13 +1036,228 @@ static void nv4a_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
                INSTANCE_WR(ctx, i/4, 0x3f800000);
 }
 
+static void
+nv4b_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i;
 
-static void nv4c_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
+       INSTANCE_WR(ctx, 0x00004/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00008/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x0000c/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00010/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00014/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00018/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x0001c/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x00020/4, 0x0000c040);
+       INSTANCE_WR(ctx, 0x000c4/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x000c8/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x000d0/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x001bc/4, 0x20010001);
+       INSTANCE_WR(ctx, 0x001c0/4, 0x0f73ef00);
+       INSTANCE_WR(ctx, 0x001c8/4, 0x02008821);
+       INSTANCE_WR(ctx, 0x00218/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x0021c/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00220/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00228/4, 0x00000040);
+       INSTANCE_WR(ctx, 0x00234/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00238/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x0023c/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00240/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00244/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00248/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x0024c/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00250/4, 0x80000000);
+       INSTANCE_WR(ctx, 0x00270/4, 0x0b0b0b0c);
+       INSTANCE_WR(ctx, 0x003e0/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x003f0/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x003f4/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x003f8/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x003fc/4, 0x55555555);
+       INSTANCE_WR(ctx, 0x00428/4, 0x00000008);
+       INSTANCE_WR(ctx, 0x0043c/4, 0x00001010);
+       INSTANCE_WR(ctx, 0x00460/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00464/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00468/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0046c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00470/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00474/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00478/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0047c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00480/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00484/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00488/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0048c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00490/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00494/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x00498/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x0049c/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x004f4/4, 0x00000111);
+       INSTANCE_WR(ctx, 0x004f8/4, 0x00080060);
+       INSTANCE_WR(ctx, 0x00514/4, 0x00000080);
+       INSTANCE_WR(ctx, 0x00518/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x0051c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00530/4, 0x46400000);
+       INSTANCE_WR(ctx, 0x00540/4, 0xffff0000);
+       INSTANCE_WR(ctx, 0x00544/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00548/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0054c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00550/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00554/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00558/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0055c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00560/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00564/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00568/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0056c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00570/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00574/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00578/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x0057c/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00580/4, 0x88888888);
+       INSTANCE_WR(ctx, 0x00594/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x00598/4, 0x0fff0000);
+       INSTANCE_WR(ctx, 0x005a0/4, 0x00011100);
+       INSTANCE_WR(ctx, 0x005bc/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005c0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005c4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005c8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005cc/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005d0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005d4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005d8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005dc/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005e0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005e4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005e8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005ec/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005f0/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005f4/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x005f8/4, 0x07ff0000);
+       INSTANCE_WR(ctx, 0x00604/4, 0x4b7fffff);
+       INSTANCE_WR(ctx, 0x0062c/4, 0x30201000);
+       INSTANCE_WR(ctx, 0x00630/4, 0x70605040);
+       INSTANCE_WR(ctx, 0x00634/4, 0xb8a89888);
+       INSTANCE_WR(ctx, 0x00638/4, 0xf8e8d8c8);
+       INSTANCE_WR(ctx, 0x0064c/4, 0x40100000);
+       INSTANCE_WR(ctx, 0x00668/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x0069c/4, 0x435185d6);
+       INSTANCE_WR(ctx, 0x006a0/4, 0x2155b699);
+       INSTANCE_WR(ctx, 0x006a4/4, 0xfedcba98);
+       INSTANCE_WR(ctx, 0x006a8/4, 0x00000098);
+       INSTANCE_WR(ctx, 0x006b8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x006bc/4, 0x00ff7000);
+       INSTANCE_WR(ctx, 0x006c0/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x006d0/4, 0x00ff0000);
+       INSTANCE_WR(ctx, 0x0070c/4, 0x00ffff00);
+       for (i=0x00750; i<=0x0078c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00018488);
+       for (i=0x00790; i<=0x007cc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00028202);
+       for (i=0x00810; i<=0x0084c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x0000aae4);
+       for (i=0x00850; i<=0x0088c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x01012000);
+       for (i=0x00890; i<=0x008cc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       for (i=0x00910; i<=0x0094c; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00100008);
+       for (i=0x009a0; i<=0x009ac; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x0001bc80);
+       for (i=0x009b0; i<=0x009bc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00000202);
+       for (i=0x009d0; i<=0x009dc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00000008);
+       for (i=0x009f0; i<=0x009fc; i+=4)
+               INSTANCE_WR(ctx, i/4, 0x00080008);
+       INSTANCE_WR(ctx, 0x00a10/4, 0x00000002);
+       INSTANCE_WR(ctx, 0x00a44/4, 0x00000421);
+       INSTANCE_WR(ctx, 0x00a48/4, 0x030c30c3);
+       INSTANCE_WR(ctx, 0x00a54/4, 0x3e020200);
+       INSTANCE_WR(ctx, 0x00a58/4, 0x00ffffff);
+       INSTANCE_WR(ctx, 0x00a5c/4, 0x20103f00);
+       INSTANCE_WR(ctx, 0x00a68/4, 0x00040000);
+       INSTANCE_WR(ctx, 0x00aa0/4, 0x00008100);
+       INSTANCE_WR(ctx, 0x00b2c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00b70/4, 0x00001001);
+       INSTANCE_WR(ctx, 0x00b7c/4, 0x00000003);
+       INSTANCE_WR(ctx, 0x00b80/4, 0x00888001);
+       INSTANCE_WR(ctx, 0x00bb0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bb4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bb8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bbc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bc0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bc4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bc8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bcc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bd0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bd4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bd8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bdc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00be0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00be4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00be8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bec/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bf0/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bf4/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bf8/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00bfc/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c00/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c04/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c08/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c0c/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c10/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c14/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c18/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c1c/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c20/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c24/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c28/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c2c/4, 0xffffffff);
+       INSTANCE_WR(ctx, 0x00c54/4, 0x00000005);
+       INSTANCE_WR(ctx, 0x00c60/4, 0x0000ffff);
+       INSTANCE_WR(ctx, 0x00c7c/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c80/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c84/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c88/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c8c/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c90/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c94/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c98/4, 0x00005555);
+       INSTANCE_WR(ctx, 0x00c9c/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00cd4/4, 0x00000001);
+       INSTANCE_WR(ctx, 0x00cd8/4, 0x08e00001);
+       INSTANCE_WR(ctx, 0x00cdc/4, 0x000e3000);
+       for(i=0x030a0; i<=0x03118; i+=8)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x098a0; i<=0x0ba90; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x0baa0; i<=0x0be90; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x0e2e0; i<=0x0fff0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x10008; i<=0x104d0; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x104e0; i<=0x108d0; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x12d20; i<=0x14f10; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x14f20; i<=0x15310; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+       for(i=0x17760; i<=0x19950; i+=24)
+               INSTANCE_WR(ctx, i/4, 0x00000001);
+       for(i=0x19960; i<=0x19d50; i+=16)
+               INSTANCE_WR(ctx, i/4, 0x3f800000);
+}
+
+static void
+nv4c_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
 
-       INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
        INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00030/4, 0x00000001);
@@ -648,12 +1358,13 @@ static void nv4c_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
                INSTANCE_WR(ctx, i/4, 0x3f800000);
 }
 
-static void nv4e_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv4e_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
 
-       INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+       INSTANCE_WR(ctx, 0x00000/4, ctx->im_pramin->start);
        INSTANCE_WR(ctx, 0x00024/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00028/4, 0x0000ffff);
        INSTANCE_WR(ctx, 0x00030/4, 0x00000001);
@@ -755,20 +1466,24 @@ static void nv4e_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
 }
 
 int
-nv40_graph_context_create(drm_device_t *dev, int channel)
+nv40_graph_create_context(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       void (*ctx_init)(drm_device_t *, struct mem_block *);
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *);
        unsigned int ctx_size;
-       int i;
+       int ret;
 
        switch (dev_priv->chipset) {
        case 0x40:
                ctx_size = NV40_GRCTX_SIZE;
                ctx_init = nv40_graph_context_init;
                break;
+       case 0x41:
+       case 0x42:
+               ctx_size = NV41_GRCTX_SIZE;
+               ctx_init = nv41_graph_context_init;
+               break;
        case 0x43:
                ctx_size = NV43_GRCTX_SIZE;
                ctx_init = nv43_graph_context_init;
@@ -777,10 +1492,24 @@ nv40_graph_context_create(drm_device_t *dev, int channel)
                ctx_size = NV46_GRCTX_SIZE;
                ctx_init = nv46_graph_context_init;
                break;
+       case 0x47:
+               DRM_INFO("NV47 warning: If your card behaves strangely, please come to the irc channel\n");
+               ctx_size = NV47_GRCTX_SIZE;
+               ctx_init = nv47_graph_context_init;
+               break;
+       case 0x49:
+               ctx_size = NV49_GRCTX_SIZE;
+               ctx_init = nv49_graph_context_init;
+               break;
+       case 0x44:
        case 0x4a:
                ctx_size = NV4A_GRCTX_SIZE;
                ctx_init = nv4a_graph_context_init;
                break;
+       case 0x4b:
+               ctx_size = NV4B_GRCTX_SIZE;
+               ctx_init = nv4b_graph_context_init;
+               break;
        case 0x4c:
                ctx_size = NV4C_GRCTX_SIZE;
                ctx_init = nv4c_graph_context_init;
@@ -795,102 +1524,113 @@ nv40_graph_context_create(drm_device_t *dev, int channel)
                break;
        }
 
-       /* Alloc and clear RAMIN to store the context */
-       chan->ramin_grctx = nouveau_instmem_alloc(dev, ctx_size, 4);
-       if (!chan->ramin_grctx)
-               return DRM_ERR(ENOMEM);
-       for (i=0; i<ctx_size; i+=4)
-               INSTANCE_WR(chan->ramin_grctx, i/4, 0x00000000);
+       if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16,
+                                         NVOBJ_FLAG_ZERO_ALLOC,
+                                         &chan->ramin_grctx)))
+               return ret;
 
        /* Initialise default context values */
-       ctx_init(dev, chan->ramin_grctx);
+       ctx_init(dev, chan->ramin_grctx->gpuobj);
 
        return 0;
 }
 
-/* Save current context (from PGRAPH) into the channel's context
- *XXX: fails sometimes, not sure why..
- */
 void
-nv40_graph_context_save_current(drm_device_t *dev)
+nv40_graph_destroy_context(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       uint32_t instance;
+       nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx);
+}
+
+static int
+nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t old_cp, tv = 1000, tmp;
        int i;
 
-       NV_WRITE(NV04_PGRAPH_FIFO, 0);
+       old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
 
-       instance = NV_READ(0x40032C) & 0xFFFFF;
-       if (!instance) {
-               NV_WRITE(NV04_PGRAPH_FIFO, 1);
-               return;
-       }
+       tmp  = NV_READ(NV40_PGRAPH_CTXCTL_0310);
+       tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
+                     NV40_PGRAPH_CTXCTL_0310_XFER_LOAD;
+       NV_WRITE(NV40_PGRAPH_CTXCTL_0310, tmp);
+       
+       tmp  = NV_READ(NV40_PGRAPH_CTXCTL_0304);
+       tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX;
+       NV_WRITE(NV40_PGRAPH_CTXCTL_0304, tmp);
 
-       NV_WRITE(0x400784, instance);
-       NV_WRITE(0x400310, NV_READ(0x400310) | 0x20);
-       NV_WRITE(0x400304, 1);
-       /* just in case, we don't want to spin in-kernel forever */
-       for (i=0; i<1000; i++) {
-               if (NV_READ(0x40030C) == 0)
+       for (i = 0; i < tv; i++) {
+               if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0)
                        break;
        }
-       if (i==1000) {
-               DRM_ERROR("failed to save current grctx to ramin\n");
-               DRM_ERROR("instance = 0x%08x\n", NV_READ(0x40032C));
-               DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C));
-               NV_WRITE(NV04_PGRAPH_FIFO, 1);
-               return;
+
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
+
+       if (i == tv) {
+               uint32_t ucstat = NV_READ(NV40_PGRAPH_CTXCTL_UCODE_STAT);
+               DRM_ERROR("Failed: Instance=0x%08x Save=%d\n", inst, save);
+               DRM_ERROR("IP: 0x%02x, Opcode: 0x%08x\n",
+                         ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT,
+                         ucstat  & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK);
+               DRM_ERROR("0x40030C = 0x%08x\n",
+                         NV_READ(NV40_PGRAPH_CTXCTL_030C));
+               return -EBUSY;
        }
 
-       NV_WRITE(NV04_PGRAPH_FIFO, 1);
+       return 0;
+}
+
+/* Save current context (from PGRAPH) into the channel's context
+ *XXX: fails sometimes, not sure why..
+ */
+int
+nv40_graph_save_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       uint32_t inst;
+
+       if (!chan->ramin_grctx)
+               return -EINVAL;
+       inst = chan->ramin_grctx->instance >> 4;
+
+       return nv40_graph_transfer_context(dev, inst, 1);
 }
 
 /* Restore the context for a specific channel into PGRAPH
  * XXX: fails sometimes.. not sure why
  */
-void
-nv40_graph_context_restore(drm_device_t *dev, int channel)
+int
+nv40_graph_load_context(struct nouveau_channel *chan)
 {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
-       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
-       uint32_t instance;
-       int i;
-
-       instance = nouveau_chip_instance_get(dev, chan->ramin_grctx);
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t inst;
+       int ret;
 
-       NV_WRITE(NV04_PGRAPH_FIFO, 0);
-       NV_WRITE(0x400784, instance);
-       NV_WRITE(0x400310, NV_READ(0x400310) | 0x40);
-       NV_WRITE(0x400304, 1);
-       /* just in case, we don't want to spin in-kernel forever */
-       for (i=0; i<1000; i++) {
-               if (NV_READ(0x40030C) == 0)
-                       break;
-       }
-       if (i==1000) {
-               DRM_ERROR("failed to restore grctx for ch%d to PGRAPH\n",
-                               channel);
-               DRM_ERROR("instance = 0x%08x\n", instance);
-               DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C));
-               NV_WRITE(NV04_PGRAPH_FIFO, 1);
-               return;
-       }
+       if (!chan->ramin_grctx)
+               return -EINVAL;
+       inst = chan->ramin_grctx->instance >> 4;
 
+       ret = nv40_graph_transfer_context(dev, inst, 0);
+       if (ret)
+               return ret;
 
        /* 0x40032C, no idea of it's exact function.  Could simply be a
         * record of the currently active PGRAPH context.  It's currently
         * unknown as to what bit 24 does.  The nv ddx has it set, so we will
         * set it here too.
         */
-       NV_WRITE(0x40032C, instance | 0x01000000);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+       NV_WRITE(NV40_PGRAPH_CTXCTL_CUR,
+                (inst & NV40_PGRAPH_CTXCTL_CUR_INST_MASK) |
+                 NV40_PGRAPH_CTXCTL_CUR_LOADED);
        /* 0x32E0 records the instance address of the active FIFO's PGRAPH
         * context.  If at any time this doesn't match 0x40032C, you will
         * recieve PGRAPH_INTR_CONTEXT_SWITCH
         */
-       NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, instance);
-       NV_WRITE(NV04_PGRAPH_FIFO, 1);
+       NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst);
+       return 0;
 }
 
 /* Some voodoo that makes context switching work without the binary driver
@@ -943,6 +1683,37 @@ static uint32_t nv40_ctx_voodoo[] = {
        ~0
 };
 
+static uint32_t nv41_ctx_voodoo[] = {
+       0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
+       0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00408f65, 0x00409306,
+       0x0040a068, 0x0040198f, 0x00200001, 0x0060000a, 0x00700080, 0x00104042,
+       0x00200001, 0x0060000a, 0x00700000, 0x001040c5, 0x00401826, 0x00401968,
+       0x0060000d, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080,
+       0x004020e6, 0x007000a0, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d,
+       0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4,
+       0x001041c9, 0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e,
+       0x001242c0, 0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143,
+       0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d10,
+       0x001046ec, 0x00500060, 0x00404087, 0x0060000d, 0x004079e6, 0x002000f1,
+       0x0060000a, 0x00148653, 0x00104668, 0x0010c66d, 0x00120682, 0x0011068b,
+       0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4, 0x001146c6,
+       0x00200020, 0x001006cc, 0x001046ed, 0x001246f0, 0x002000c0, 0x00100700,
+       0x0010c3d7, 0x001043e1, 0x00500060, 0x00200233, 0x0060000a, 0x00104800,
+       0x00108901, 0x00124920, 0x0020001f, 0x00100940, 0x00140965, 0x00148a00,
+       0x00108a14, 0x00200020, 0x00100b00, 0x00134b2c, 0x0010cd00, 0x0010cd04,
+       0x00114d08, 0x00104d80, 0x00104e00, 0x0012d600, 0x00105c00, 0x00104f06,
+       0x002002d2, 0x0060000a, 0x00300000, 0x00200680, 0x00407200, 0x00200684,
+       0x00800001, 0x00200b1a, 0x0060000a, 0x00206380, 0x0040788a, 0x00201480,
+       0x00800041, 0x00408900, 0x00600006, 0x004085e6, 0x00700080, 0x0020007a,
+       0x0060000a, 0x00104280, 0x002002d2, 0x0060000a, 0x00200004, 0x00800001,
+       0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x0040a068, 0x00700000,
+       0x00200000, 0x0060000a, 0x00106002, 0x00700080, 0x00400a68, 0x00500060,
+       0x00600007, 0x00409388, 0x0060000f, 0x00500060, 0x00200000, 0x0060000a,
+       0x00700000, 0x00106001, 0x00910880, 0x00901ffe, 0x00940400, 0x00200020,
+       0x0060000b, 0x00500069, 0x0060000c, 0x00402168, 0x0040a206, 0x0040a305,
+       0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0
+};
+
 static uint32_t nv43_ctx_voodoo[] = {
        0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
        0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409565, 0x00409a06,
@@ -976,6 +1747,39 @@ static uint32_t nv43_ctx_voodoo[] = {
        ~0
 };
 
+static uint32_t nv44_ctx_voodoo[] = {
+       0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
+       0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409a65, 0x00409f06,
+       0x0040ac68, 0x0040248f, 0x00200001, 0x0060000a, 0x00700080, 0x00104042,
+       0x001041c6, 0x00104040, 0x00200001, 0x0060000a, 0x00700000, 0x001040c5,
+       0x00402320, 0x00402321, 0x00402322, 0x00402324, 0x00402326, 0x0040232b,
+       0x001040c5, 0x00402328, 0x001040c5, 0x00402320, 0x00402468, 0x0060000d,
+       0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080, 0x00402be6,
+       0x007000a0, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d, 0x00110158,
+       0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4, 0x001041c9,
+       0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e, 0x001242c0,
+       0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143, 0x0011415f,
+       0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d10, 0x001046ec,
+       0x00500060, 0x00404b87, 0x0060000d, 0x004084e6, 0x002000f1, 0x0060000a,
+       0x00148653, 0x00104668, 0x0010c66d, 0x00120682, 0x0011068b, 0x00168691,
+       0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4, 0x001146c6, 0x001646cc,
+       0x001186e6, 0x001046ed, 0x001246f0, 0x002000c0, 0x00100700, 0x0010c3d7,
+       0x001043e1, 0x00500060, 0x00200232, 0x0060000a, 0x00104800, 0x00108901,
+       0x00104910, 0x00124920, 0x0020001f, 0x00100940, 0x00140965, 0x00148a00,
+       0x00108a14, 0x00160b00, 0x00134b2c, 0x0010cd00, 0x0010cd04, 0x0010cd08,
+       0x00104d80, 0x00104e00, 0x0012d600, 0x00105c00, 0x00104f06, 0x002002c8,
+       0x0060000a, 0x00300000, 0x00200080, 0x00407d00, 0x00200084, 0x00800001,
+       0x00200510, 0x0060000a, 0x002037e0, 0x0040838a, 0x00201320, 0x00800029,
+       0x00409400, 0x00600006, 0x004090e6, 0x00700080, 0x0020007a, 0x0060000a,
+       0x00104280, 0x002002c8, 0x0060000a, 0x00200004, 0x00800001, 0x00700000,
+       0x00200000, 0x0060000a, 0x00106002, 0x0040ac68, 0x00700000, 0x00200000,
+       0x0060000a, 0x00106002, 0x00700080, 0x00400a68, 0x00500060, 0x00600007,
+       0x00409e88, 0x0060000f, 0x00000000, 0x00500060, 0x00200000, 0x0060000a,
+       0x00700000, 0x00106001, 0x00910880, 0x00901ffe, 0x01940000, 0x00200020,
+       0x0060000b, 0x00500069, 0x0060000c, 0x00402c68, 0x0040ae06, 0x0040af05,
+       0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0
+};
+
 static uint32_t nv46_ctx_voodoo[] = {
        0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
        0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00408f65, 0x00409306,
@@ -1007,6 +1811,71 @@ static uint32_t nv46_ctx_voodoo[] = {
        0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0
 };
 
+static uint32_t nv47_ctx_voodoo[] = {
+       0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
+       0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409265, 0x00409606,
+       0x0040a368, 0x0040198f, 0x00200001, 0x0060000a, 0x00700080, 0x00104042,
+       0x00200001, 0x0060000a, 0x00700000, 0x001040c5, 0x00401826, 0x00401968,
+       0x0060000d, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080,
+       0x004020e6, 0x007000a0, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d,
+       0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4,
+       0x001041c9, 0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e,
+       0x001242c0, 0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143,
+       0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d12,
+       0x00500060, 0x00403f87, 0x0060000d, 0x00407ce6, 0x002000f0, 0x0060000a,
+       0x00200020, 0x00100620, 0x00154650, 0x00104668, 0x0017466d, 0x0011068b,
+       0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4, 0x001146c6,
+       0x00200022, 0x001006cc, 0x001246f0, 0x002000c0, 0x00100700, 0x0010c3d7,
+       0x001043e1, 0x00500060, 0x00200268, 0x0060000a, 0x00104800, 0x00108901,
+       0x00124920, 0x0020001f, 0x00100940, 0x00140965, 0x00144a00, 0x00104a19,
+       0x0010ca1c, 0x00110b00, 0x00200028, 0x00100b08, 0x00134c2e, 0x0010cd00,
+       0x0010cd04, 0x00120d08, 0x00104d80, 0x00104e00, 0x0012d600, 0x00105c00,
+       0x00104f06, 0x00105406, 0x00105709, 0x00200318, 0x0060000a, 0x00300000,
+       0x00200680, 0x00407500, 0x00200684, 0x00800001, 0x00200b60, 0x0060000a,
+       0x00209540, 0x00407b8a, 0x00201350, 0x00800041, 0x00408c00, 0x00600006,
+       0x004088e6, 0x00700080, 0x0020007a, 0x0060000a, 0x00104280, 0x00200318,
+       0x0060000a, 0x00200004, 0x00800001, 0x00700000, 0x00200000, 0x0060000a,
+       0x00106002, 0x0040a368, 0x00700000, 0x00200000, 0x0060000a, 0x00106002,
+       0x00700080, 0x00400a68, 0x00500060, 0x00600007, 0x00409688, 0x0060000f,
+       0x00500060, 0x00200000, 0x0060000a, 0x00700000, 0x00106001, 0x0091a880,
+       0x00901ffe, 0x10940000, 0x00200020, 0x0060000b, 0x00500069, 0x0060000c,
+       0x00402168, 0x0040a506, 0x0040a605, 0x00600009, 0x00700005, 0x00700006,
+       0x0060000e, ~0
+};
+
+//this is used for nv49 and nv4b
+static uint32_t nv49_4b_ctx_voodoo[] ={
+       0x00400564, 0x00400505, 0x00408165, 0x00408206, 0x00409e68, 0x00200020,
+       0x0060000a, 0x00700080, 0x00104042, 0x00200020, 0x0060000a, 0x00700000,
+       0x001040c5, 0x00400f26, 0x00401068, 0x0060000d, 0x0070008f, 0x0070000e,
+       0x00408d68, 0x004015e6, 0x007000a0, 0x00700080, 0x0040180f, 0x00700000,
+       0x00200029, 0x0060000a, 0x0011814d, 0x00110158, 0x00105401, 0x0020003a,
+       0x00100051, 0x001040c5, 0x0010c1c4, 0x001041c9, 0x0010c1dc, 0x00150210,
+       0x0012c225, 0x00108238, 0x0010823e, 0x001242c0, 0x00200040, 0x00100280,
+       0x00128100, 0x00128120, 0x00128143, 0x0011415f, 0x0010815c, 0x0010c140,
+       0x00104029, 0x00110400, 0x00104d12, 0x00500060, 0x004071e6, 0x00200118,
+       0x0060000a, 0x00200020, 0x00100620, 0x00154650, 0x00104668, 0x0017466d,
+       0x0011068b, 0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4,
+       0x001146c6, 0x00200022, 0x001006cc, 0x001246f0, 0x002000c0, 0x00100700,
+       0x0010c3d7, 0x001043e1, 0x00500060, 0x00200290, 0x0060000a, 0x00104800,
+       0x00108901, 0x00124920, 0x0020001f, 0x00100940, 0x00140965, 0x00144a00,
+       0x00104a19, 0x0010ca1c, 0x00110b00, 0x00200028, 0x00100b08, 0x00134c2e,
+       0x0010cd00, 0x0010cd04, 0x00120d08, 0x00104d80, 0x00104e00, 0x0012d600,
+       0x00105c00, 0x00104f06, 0x00105406, 0x00105709, 0x00200340, 0x0060000a,
+       0x00300000, 0x00200680, 0x00406a0f, 0x00200684, 0x00800001, 0x00200b88,
+       0x0060000a, 0x00209540, 0x0040708a, 0x00201350, 0x00800041, 0x00407c0f,
+       0x00600006, 0x00407ce6, 0x00700080, 0x002000a2, 0x0060000a, 0x00104280,
+       0x00200340, 0x0060000a, 0x00200004, 0x00800001, 0x0070008e, 0x00408d68,
+       0x0040020f, 0x00600006, 0x00409e68, 0x00600007, 0x0070000f, 0x0070000e,
+       0x00408d68, 0x0091a880, 0x00901ffe, 0x10940000, 0x00200020, 0x0060000b,
+       0x00500069, 0x0060000c, 0x00401568, 0x00700000, 0x00200001, 0x0040910e,
+       0x00200021, 0x0060000a, 0x00409b0d, 0x00104a40, 0x00104a50, 0x00104a60,
+       0x00104a70, 0x00104a80, 0x00104a90, 0x00104aa0, 0x00104ab0, 0x00407e0e,
+       0x0040130f, 0x00408568, 0x0040a006, 0x0040a105, 0x00600009, 0x00700005,
+       0x00700006, 0x0060000e, ~0
+};
+
+
 static uint32_t nv4a_ctx_voodoo[] = {
        0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001, 
        0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409965, 0x00409e06, 
@@ -1040,6 +1909,37 @@ static uint32_t nv4a_ctx_voodoo[] = {
        0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0
 };
 
+static uint32_t nv4c_ctx_voodoo[] = {
+       0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
+       0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409065, 0x00409406,
+       0x0040a168, 0x0040198f, 0x00200001, 0x0060000a, 0x00700080, 0x00104042,
+       0x00200001, 0x0060000a, 0x00700000, 0x001040c5, 0x00401826, 0x00401968,
+       0x0060000d, 0x00200000, 0x0060000a, 0x00700000, 0x00106000, 0x00700080,
+       0x004020e6, 0x007000a0, 0x00500060, 0x00200001, 0x0060000a, 0x0011814d,
+       0x00110158, 0x00105401, 0x0020003a, 0x00100051, 0x001040c5, 0x0010c1c4,
+       0x001041c9, 0x0010c1dc, 0x00150210, 0x0012c225, 0x00108238, 0x0010823e,
+       0x001242c0, 0x00200040, 0x00100280, 0x00128100, 0x00128120, 0x00128143,
+       0x0011415f, 0x0010815c, 0x0010c140, 0x00104029, 0x00110400, 0x00104d10,
+       0x0010427e, 0x001046ec, 0x00500060, 0x00404187, 0x0060000d, 0x00407ae6,
+       0x002000f2, 0x0060000a, 0x00148653, 0x00104668, 0x0010c66d, 0x00120682,
+       0x0011068b, 0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4,
+       0x001146c6, 0x00200020, 0x001006cc, 0x001046ed, 0x001246f0, 0x002000c0,
+       0x00100700, 0x0010c3d7, 0x001043e1, 0x00500060, 0x00200234, 0x0060000a,
+       0x00104800, 0x00108901, 0x00104910, 0x00124920, 0x0020001f, 0x00100940,
+       0x00140965, 0x00148a00, 0x00108a14, 0x00140b00, 0x00134b2c, 0x0010cd00,
+       0x0010cd04, 0x00104d08, 0x00104d80, 0x00104e00, 0x0012d600, 0x00105c00,
+       0x00104f06, 0x002002c0, 0x0060000a, 0x00300000, 0x00200080, 0x00407300,
+       0x00200084, 0x00800001, 0x00200508, 0x0060000a, 0x00201320, 0x0040798a,
+       0xfffffaf8, 0x00800029, 0x00408a00, 0x00600006, 0x004086e6, 0x00700080,
+       0x0020007a, 0x0060000a, 0x00104280, 0x002002c0, 0x0060000a, 0x00200004,
+       0x00800001, 0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x0040a168,
+       0x00700000, 0x00200000, 0x0060000a, 0x00106002, 0x00700080, 0x00400a68,
+       0x00500060, 0x00600007, 0x00409488, 0x0060000f, 0x00500060, 0x00200000,
+       0x0060000a, 0x00700000, 0x00106001, 0x00910880, 0x00901ffe, 0x01940000,
+       0x00200020, 0x0060000b, 0x00500069, 0x0060000c, 0x00402168, 0x0040a306,
+       0x0040a405, 0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0
+};
+
 static uint32_t nv4e_ctx_voodoo[] = {
        0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
        0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409565, 0x00409a06,
@@ -1083,10 +1983,10 @@ static uint32_t nv4e_ctx_voodoo[] = {
  * C51         0x4e
  */
 int
-nv40_graph_init(drm_device_t *dev)
+nv40_graph_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv =
-               (drm_nouveau_private_t *)dev->dev_private;
+       struct drm_nouveau_private *dev_priv =
+               (struct drm_nouveau_private *)dev->dev_private;
        uint32_t *ctx_voodoo;
        uint32_t vramsz, tmp;
        int i, j;
@@ -1098,9 +1998,16 @@ nv40_graph_init(drm_device_t *dev)
 
        switch (dev_priv->chipset) {
        case 0x40: ctx_voodoo = nv40_ctx_voodoo; break;
+       case 0x41:
+       case 0x42: ctx_voodoo = nv41_ctx_voodoo; break;
        case 0x43: ctx_voodoo = nv43_ctx_voodoo; break;
+       case 0x44: ctx_voodoo = nv44_ctx_voodoo; break;
        case 0x46: ctx_voodoo = nv46_ctx_voodoo; break;
+       case 0x47: ctx_voodoo = nv47_ctx_voodoo; break;
+       case 0x49: ctx_voodoo = nv49_4b_ctx_voodoo; break;
        case 0x4a: ctx_voodoo = nv4a_ctx_voodoo; break;
+       case 0x4b: ctx_voodoo = nv49_4b_ctx_voodoo; break;
+       case 0x4c: ctx_voodoo = nv4c_ctx_voodoo; break;
        case 0x4e: ctx_voodoo = nv4e_ctx_voodoo; break;
        default:
                DRM_ERROR("Unknown ctx_voodoo for chipset 0x%02x\n",
@@ -1114,18 +2021,18 @@ nv40_graph_init(drm_device_t *dev)
                DRM_DEBUG("Loading context-switch voodoo\n");
                i = 0;
 
-               NV_WRITE(0x400324, 0);
+               NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
                while (ctx_voodoo[i] != ~0) {
-                       NV_WRITE(0x400328, ctx_voodoo[i]);
+                       NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, ctx_voodoo[i]);
                        i++;
                }
        }       
 
        /* No context present currently */
-       NV_WRITE(0x40032C, 0x00000000);
+       NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
 
-       NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
        NV_WRITE(NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+       NV_WRITE(NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
        NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
        NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
@@ -1311,7 +2218,7 @@ nv40_graph_init(drm_device_t *dev)
        return 0;
 }
 
-void nv40_graph_takedown(drm_device_t *dev)
+void nv40_graph_takedown(struct drm_device *dev)
 {
 }
 
index 8dbd96f..c7db902 100644 (file)
@@ -4,9 +4,9 @@
 #include "nouveau_drm.h"
 
 int
-nv40_mc_init(drm_device_t *dev)
+nv40_mc_init(struct drm_device *dev)
 {
-       drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
        /* Power up everything, resetting each individual unit will
@@ -14,8 +14,6 @@ nv40_mc_init(drm_device_t *dev)
         */
        NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
 
-       NV_WRITE(NV03_PMC_INTR_EN_0, 0);
-
        switch (dev_priv->chipset) {
        case 0x44:
        case 0x46: /* G72 */
@@ -35,7 +33,7 @@ nv40_mc_init(drm_device_t *dev)
 }
 
 void
-nv40_mc_takedown(drm_device_t *dev)
+nv40_mc_takedown(struct drm_device *dev)
 {
 }
 
diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c
new file mode 100644 (file)
index 0000000..7859544
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+typedef struct {
+       struct nouveau_gpuobj_ref *thingo;
+} nv50_fifo_priv;
+
+#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
+
+static void
+nv50_fifo_init_thingo(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
+       struct nouveau_gpuobj_ref *thingo = priv->thingo;
+       int i, fi=2;
+
+       DRM_DEBUG("\n");
+
+       INSTANCE_WR(thingo->gpuobj, 0, 0x7e);
+       INSTANCE_WR(thingo->gpuobj, 1, 0x7e);
+       for (i = 1; i < 127; i++, fi) {
+               if (dev_priv->fifos[i]) {
+                       INSTANCE_WR(thingo->gpuobj, fi, i);
+                       fi++;
+               }
+       }
+
+       NV_WRITE(0x32f4, thingo->instance >> 12);
+       NV_WRITE(0x32ec, fi);
+       NV_WRITE(0x2500, 0x101);
+}
+
+static int
+nv50_fifo_channel_enable(struct drm_device *dev, int channel, int nt)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_channel *chan = dev_priv->fifos[channel];
+       uint32_t inst;
+
+       DRM_DEBUG("ch%d\n", channel);
+
+       if (!chan->ramfc)
+               return -EINVAL;
+
+       if (IS_G80) inst = chan->ramfc->instance >> 12;
+       else        inst = chan->ramfc->instance >> 8;
+       NV_WRITE(NV50_PFIFO_CTX_TABLE(channel),
+                inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
+
+       if (!nt) nv50_fifo_init_thingo(dev);
+       return 0;
+}
+
+static void
+nv50_fifo_channel_disable(struct drm_device *dev, int channel, int nt)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t inst;
+
+       DRM_DEBUG("ch%d, nt=%d\n", channel, nt);
+
+       if (IS_G80) inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80;
+       else        inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84;
+       NV_WRITE(NV50_PFIFO_CTX_TABLE(channel), inst);
+
+       if (!nt) nv50_fifo_init_thingo(dev);
+}
+
+static void
+nv50_fifo_init_reset(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t pmc_e;
+
+       DRM_DEBUG("\n");
+
+       pmc_e = NV_READ(NV03_PMC_ENABLE);
+       NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PFIFO);
+       pmc_e = NV_READ(NV03_PMC_ENABLE);
+       NV_WRITE(NV03_PMC_ENABLE, pmc_e |  NV_PMC_ENABLE_PFIFO);
+}
+
+static void
+nv50_fifo_init_intr(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
+       NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
+}
+
+static void
+nv50_fifo_init_context_table(struct drm_device *dev)
+{
+       int i;
+
+       DRM_DEBUG("\n");
+
+       for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++)
+               nv50_fifo_channel_disable(dev, i, 1);
+       nv50_fifo_init_thingo(dev);
+}
+
+static void
+nv50_fifo_init_regs__nv(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       NV_WRITE(0x250c, 0x6f3cfc34);
+}
+
+static int
+nv50_fifo_init_regs(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       NV_WRITE(0x2500, 0);
+       NV_WRITE(0x3250, 0);
+       NV_WRITE(0x3220, 0);
+       NV_WRITE(0x3204, 0);
+       NV_WRITE(0x3210, 0);
+       NV_WRITE(0x3270, 0);
+
+       /* Enable dummy channels setup by nv50_instmem.c */
+       nv50_fifo_channel_enable(dev, 0, 1);
+       nv50_fifo_channel_enable(dev, 127, 1);
+
+       return 0;
+}
+
+int
+nv50_fifo_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       nv50_fifo_priv *priv;
+       int ret;
+
+       DRM_DEBUG("\n");
+
+       priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER);
+       if (!priv)
+               return -ENOMEM;
+       dev_priv->Engine.fifo.priv = priv;
+
+       nv50_fifo_init_reset(dev);
+       nv50_fifo_init_intr(dev);
+
+       if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000,
+                                  NVOBJ_FLAG_ZERO_ALLOC,
+                                  &priv->thingo))) {
+               DRM_ERROR("error creating thingo: %d\n", ret);
+               return ret;
+       }
+
+       nv50_fifo_init_context_table(dev);
+
+       nv50_fifo_init_regs__nv(dev);
+       if ((ret = nv50_fifo_init_regs(dev)))
+               return ret;
+
+       return 0;
+}
+
+void
+nv50_fifo_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
+
+       DRM_DEBUG("\n");
+
+       if (!priv)
+               return;
+
+       nouveau_gpuobj_ref_del(dev, &priv->thingo);
+
+       dev_priv->Engine.fifo.priv = NULL;
+       drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
+}
+
+int
+nv50_fifo_create_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *ramfc = NULL;
+       int ret;
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+       if (IS_G80) {
+               uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start;
+               uint32_t vram_offset = chan->ramin->gpuobj->im_backing->start;
+               if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset,
+                                                  vram_offset, 0x100,
+                                                  NVOBJ_FLAG_ZERO_ALLOC |
+                                                  NVOBJ_FLAG_ZERO_FREE,
+                                                  &ramfc, &chan->ramfc)))
+                               return ret;
+       } else {
+               if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100,
+                                                 256,
+                                                 NVOBJ_FLAG_ZERO_ALLOC |
+                                                 NVOBJ_FLAG_ZERO_FREE,
+                                                 &chan->ramfc)))
+                       return ret;
+               ramfc = chan->ramfc->gpuobj;
+       }
+
+       INSTANCE_WR(ramfc, 0x48/4, chan->pushbuf->instance >> 4);
+       INSTANCE_WR(ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4));
+       INSTANCE_WR(ramfc, 0x3c/4, 0x000f0078); /* fetch? */
+       INSTANCE_WR(ramfc, 0x44/4, 0x2101ffff);
+       INSTANCE_WR(ramfc, 0x60/4, 0x7fffffff);
+       INSTANCE_WR(ramfc, 0x10/4, 0x00000000);
+       INSTANCE_WR(ramfc, 0x08/4, 0x00000000);
+       INSTANCE_WR(ramfc, 0x40/4, 0x00000000);
+       INSTANCE_WR(ramfc, 0x50/4, 0x2039b2e0);
+       INSTANCE_WR(ramfc, 0x54/4, 0x000f0000);
+       INSTANCE_WR(ramfc, 0x7c/4, 0x30000001);
+       INSTANCE_WR(ramfc, 0x78/4, 0x00000000);
+       INSTANCE_WR(ramfc, 0x4c/4, chan->pushbuf_mem->size - 1);
+
+       if (!IS_G80) {
+               INSTANCE_WR(chan->ramin->gpuobj, 0, chan->id);
+               INSTANCE_WR(chan->ramin->gpuobj, 1, chan->ramfc->instance);
+
+               INSTANCE_WR(ramfc, 0x88/4, 0x3d520); /* some vram addy >> 10 */
+               INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12);
+       }
+
+       if ((ret = nv50_fifo_channel_enable(dev, chan->id, 0))) {
+               DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret);
+               nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+               return ret;
+       }
+
+       return 0;
+}
+
+void
+nv50_fifo_destroy_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+       nv50_fifo_channel_disable(dev, chan->id, 0);
+
+       /* Dummy channel, also used on ch 127 */
+       if (chan->id == 0)
+               nv50_fifo_channel_disable(dev, 127, 0);
+
+       nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+}
+
+int
+nv50_fifo_load_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj;
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+       /*XXX: incomplete, only touches the regs that NV does */
+
+       NV_WRITE(0x3244, 0);
+       NV_WRITE(0x3240, 0);
+
+       NV_WRITE(0x3224, INSTANCE_RD(ramfc, 0x3c/4));
+       NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, INSTANCE_RD(ramfc, 0x48/4));
+       NV_WRITE(0x3234, INSTANCE_RD(ramfc, 0x4c/4));
+       NV_WRITE(0x3254, 1);
+       NV_WRITE(NV03_PFIFO_RAMHT, INSTANCE_RD(ramfc, 0x80/4));
+
+       if (!IS_G80) {
+               NV_WRITE(0x340c, INSTANCE_RD(ramfc, 0x88/4));
+               NV_WRITE(0x3410, INSTANCE_RD(ramfc, 0x98/4));
+       }
+
+       NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
+       return 0;
+}
+
+int
+nv50_fifo_save_context(struct nouveau_channel *chan)
+{
+       DRM_DEBUG("ch%d\n", chan->id);
+       DRM_ERROR("stub!\n");
+       return 0;
+}
+
diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c
new file mode 100644 (file)
index 0000000..e5bbf65
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
+
+static void
+nv50_graph_init_reset(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t pmc_e;
+
+       DRM_DEBUG("\n");
+
+       pmc_e = NV_READ(NV03_PMC_ENABLE);
+       NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PGRAPH);
+       pmc_e = NV_READ(NV03_PMC_ENABLE);
+       NV_WRITE(NV03_PMC_ENABLE, pmc_e |  NV_PMC_ENABLE_PGRAPH);
+}
+
+static void
+nv50_graph_init_intr(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+       NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff);
+       NV_WRITE(NV40_PGRAPH_INTR_EN, 0xffffffff);
+}
+
+static void
+nv50_graph_init_regs__nv(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       NV_WRITE(0x400804, 0xc0000000);
+       NV_WRITE(0x406800, 0xc0000000);
+       NV_WRITE(0x400c04, 0xc0000000);
+       NV_WRITE(0x401804, 0xc0000000);
+       NV_WRITE(0x405018, 0xc0000000);
+       NV_WRITE(0x402000, 0xc0000000);
+
+       NV_WRITE(0x400108, 0xffffffff);
+
+       NV_WRITE(0x400824, 0x00004000);
+       NV_WRITE(0x400500, 0x00010001);
+}
+
+static void
+nv50_graph_init_regs(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       NV_WRITE(NV04_PGRAPH_DEBUG_3, (1<<2) /* HW_CONTEXT_SWITCH_ENABLED */);
+}
+
+static uint32_t nv84_ctx_voodoo[] = {
+       0x0070008e, 0x0070009c, 0x00200020, 0x00600008, 0x0050004c, 0x00400e89,
+       0x00200000, 0x00600007, 0x00300000, 0x00c000ff, 0x00200000, 0x008000ff,
+       0x00700009, 0x0041634d, 0x00402944, 0x00402905, 0x0040290d, 0x00413e06,
+       0x00600005, 0x004015c5, 0x00600011, 0x0040270b, 0x004021c5, 0x00700000,
+       0x00700081, 0x00600004, 0x0050004a, 0x00216f40, 0x00600007, 0x00c02801,
+       0x0020002e, 0x00800001, 0x005000cb, 0x0090ffff, 0x0091ffff, 0x00200020,
+       0x00600008, 0x0050004c, 0x00600009, 0x00413e45, 0x0041594d, 0x0070009d,
+       0x00402dcf, 0x0070009f, 0x0050009f, 0x00402ac0, 0x00200200, 0x00600008,
+       0x00402a4f, 0x00402ac0, 0x004030cc, 0x00700081, 0x00200000, 0x00600006,
+       0x00700000, 0x00111bfc, 0x00700083, 0x00300000, 0x00216f40, 0x00600007,
+       0x00c00b01, 0x0020001e, 0x00800001, 0x005000cb, 0x00c000ff, 0x00700080,
+       0x00700083, 0x00200047, 0x00600006, 0x0011020a, 0x00200480, 0x00600007,
+       0x00300000, 0x00c000ff, 0x00c800ff, 0x00414907, 0x00202916, 0x008000ff,
+       0x0040508c, 0x005000cb, 0x00a0023f, 0x00200040, 0x00600006, 0x0070000f,
+       0x00170202, 0x0011020a, 0x00200032, 0x0010020d, 0x001c0242, 0x00120302,
+       0x00140402, 0x00180500, 0x00130509, 0x00150550, 0x00110605, 0x0020000f,
+       0x00100607, 0x00110700, 0x00110900, 0x00120902, 0x00110a00, 0x00160b02,
+       0x00120b28, 0x00140b2b, 0x00110c01, 0x00111400, 0x00111405, 0x00111407,
+       0x00111409, 0x0011140b, 0x002000cb, 0x00101500, 0x0040790f, 0x0040794b,
+       0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040798c,
+       0x005000cb, 0x00000000, 0x0020002b, 0x00101a05, 0x00131c00, 0x00121c04,
+       0x00141c20, 0x00111c25, 0x00131c40, 0x00121c44, 0x00141c60, 0x00111c65,
+       0x00131c80, 0x00121c84, 0x00141ca0, 0x00111ca5, 0x00131cc0, 0x00121cc4,
+       0x00141ce0, 0x00111ce5, 0x00131f00, 0x00191f40, 0x0040a1e0, 0x002001ed,
+       0x00600006, 0x00200044, 0x00102080, 0x001120c6, 0x001520c9, 0x001920d0,
+       0x00122100, 0x00122103, 0x00162200, 0x00122207, 0x00112280, 0x00112300,
+       0x00112302, 0x00122380, 0x0011238b, 0x00112394, 0x0011239c, 0x0040bee1,
+       0x00200254, 0x00600006, 0x00200044, 0x00102480, 0x0040af0f, 0x0040af4b,
+       0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040af8c,
+       0x005000cb, 0x00000000, 0x001124c6, 0x001524c9, 0x001924d0, 0x00122500,
+       0x00122503, 0x00162600, 0x00122607, 0x00112680, 0x00112700, 0x00112702,
+       0x00122780, 0x0011278b, 0x00112794, 0x0011279c, 0x0040d1e2, 0x002002bb,
+       0x00600006, 0x00200044, 0x00102880, 0x001128c6, 0x001528c9, 0x001928d0,
+       0x00122900, 0x00122903, 0x00162a00, 0x00122a07, 0x00112a80, 0x00112b00,
+       0x00112b02, 0x00122b80, 0x00112b8b, 0x00112b94, 0x00112b9c, 0x0040eee3,
+       0x00200322, 0x00600006, 0x00200044, 0x00102c80, 0x0040df0f, 0x0040df4b,
+       0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x0040df8c,
+       0x005000cb, 0x00000000, 0x00112cc6, 0x00152cc9, 0x00192cd0, 0x00122d00,
+       0x00122d03, 0x00162e00, 0x00122e07, 0x00112e80, 0x00112f00, 0x00112f02,
+       0x00122f80, 0x00112f8b, 0x00112f94, 0x00112f9c, 0x004101e4, 0x00200389,
+       0x00600006, 0x00200044, 0x00103080, 0x001130c6, 0x001530c9, 0x001930d0,
+       0x00123100, 0x00123103, 0x00163200, 0x00123207, 0x00113280, 0x00113300,
+       0x00113302, 0x00123380, 0x0011338b, 0x00113394, 0x0011339c, 0x00411ee5,
+       0x002003f0, 0x00600006, 0x00200044, 0x00103480, 0x00410f0f, 0x00410f4b,
+       0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x0070008f, 0x00410f8c,
+       0x005000cb, 0x00000000, 0x001134c6, 0x001534c9, 0x001934d0, 0x00123500,
+       0x00123503, 0x00163600, 0x00123607, 0x00113680, 0x00113700, 0x00113702,
+       0x00123780, 0x0011378b, 0x00113794, 0x0011379c, 0x00000000, 0x0041250f,
+       0x005000cb, 0x00214d40, 0x00600007, 0x0020043e, 0x008800ff, 0x005000cb,
+       0x00412887, 0x0060000a, 0x00000000, 0x00413700, 0x007000a0, 0x00700080,
+       0x00200480, 0x00600007, 0x00200004, 0x00c000ff, 0x008000ff, 0x005000cb,
+       0x00700000, 0x00200000, 0x00600006, 0x00111bfe, 0x0041594d, 0x00700000,
+       0x00200000, 0x00600006, 0x00111bfe, 0x00700080, 0x0070001d, 0x0040114d,
+       0x00700081, 0x00600004, 0x0050004a, 0x00414388, 0x0060000b, 0x00200000,
+       0x00600006, 0x00700000, 0x0041590b, 0x00111bfd, 0x0040424d, 0x00202916,
+       0x008000fd, 0x005000cb, 0x00c00002, 0x00200480, 0x00600007, 0x00200160,
+       0x00800002, 0x005000cb, 0x00c01802, 0x002027b6, 0x00800002, 0x005000cb,
+       0x00404e4d, 0x0060000b, 0x0041574d, 0x00700001, 0x005000cf, 0x00700003,
+       0x00415e06, 0x00415f05, 0x0060000d, 0x00700005, 0x0070000d, 0x00700006,
+       0x0070000b, 0x0070000e, 0x0070001c, 0x0060000c, ~0
+};
+
+static void
+nv50_graph_init_ctxctl(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t *voodoo;
+
+       DRM_DEBUG("\n");
+
+       switch (dev_priv->chipset) {
+       case 0x84:
+               voodoo = nv84_ctx_voodoo;
+               break;
+       default:
+               DRM_ERROR("no voodoo for chipset NV%02x\n", dev_priv->chipset);
+               break;
+       }
+
+       if (voodoo) {
+               NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
+               while (*voodoo != ~0) {
+                       NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, *voodoo);
+                       voodoo++;
+               }
+       }
+
+       NV_WRITE(0x400320, 4);
+       NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
+}
+
+int 
+nv50_graph_init(struct drm_device *dev)
+{
+       DRM_DEBUG("\n");
+
+       nv50_graph_init_reset(dev);
+       nv50_graph_init_intr(dev);
+       nv50_graph_init_regs__nv(dev);
+       nv50_graph_init_regs(dev);
+       nv50_graph_init_ctxctl(dev);
+
+       return 0;
+}
+
+void
+nv50_graph_takedown(struct drm_device *dev)
+{
+       DRM_DEBUG("\n");
+}
+
+int
+nv50_graph_create_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->Engine;
+       struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
+       int grctx_size = 0x60000, hdr;
+       int ret;
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+       if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0,
+                                         grctx_size, 0x1000,
+                                         NVOBJ_FLAG_ZERO_ALLOC |
+                                         NVOBJ_FLAG_ZERO_FREE,
+                                         &chan->ramin_grctx)))
+               return ret;
+
+       hdr = IS_G80 ? 0x200 : 0x20;
+       INSTANCE_WR(ramin, (hdr + 0x00)/4, 0x00190002);
+       INSTANCE_WR(ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
+                                          grctx_size - 1);
+       INSTANCE_WR(ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance);
+       INSTANCE_WR(ramin, (hdr + 0x0c)/4, 0);
+       INSTANCE_WR(ramin, (hdr + 0x10)/4, 0);
+       INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000);
+
+       if ((ret = engine->graph.load_context(chan))) {
+               DRM_ERROR("Error hacking up initial context: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+void
+nv50_graph_destroy_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       int i, hdr;
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+       hdr = IS_G80 ? 0x200 : 0x20;
+       for (i=hdr; i<hdr+24; i+=4)
+               INSTANCE_WR(chan->ramin->gpuobj, i/4, 0);
+
+       nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
+}
+
+static int
+nv50_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t old_cp, tv = 20000;
+       int i;
+
+       DRM_DEBUG("inst=0x%08x, save=%d\n", inst, save);
+
+       old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER);
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst | (1<<31));
+       NV_WRITE(0x400824, NV_READ(0x400824) |
+                (save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
+                        NV40_PGRAPH_CTXCTL_0310_XFER_LOAD));
+       NV_WRITE(NV40_PGRAPH_CTXCTL_0304, NV40_PGRAPH_CTXCTL_0304_XFER_CTX);
+
+       for (i = 0; i < tv; i++) {
+               if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0)
+                       break;
+       }
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
+
+       if (i == tv) {
+               DRM_ERROR("failed: inst=0x%08x save=%d\n", inst, save);
+               DRM_ERROR("0x40030C = 0x%08x\n",
+                         NV_READ(NV40_PGRAPH_CTXCTL_030C));
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+int
+nv50_graph_load_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31));
+       int ret; (void)ret;
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+#if 0
+       if ((ret = nv50_graph_transfer_context(dev, inst, 0)))
+               return ret;
+#endif
+
+       NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+       NV_WRITE(0x400320, 4);
+       NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, inst);
+
+       return 0;
+}
+
+int
+nv50_graph_save_context(struct nouveau_channel *chan)
+{
+       struct drm_device *dev = chan->dev;
+       uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31));
+
+       DRM_DEBUG("ch%d\n", chan->id);
+
+       return nv50_graph_transfer_context(dev, inst, 1);
+}
+
diff --git a/shared-core/nv50_instmem.c b/shared-core/nv50_instmem.c
new file mode 100644 (file)
index 0000000..1eeb54d
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+typedef struct {
+       uint32_t save1700[5]; /* 0x1700->0x1710 */
+
+       struct nouveau_gpuobj_ref *pramin_pt;
+       struct nouveau_gpuobj_ref *pramin_bar;
+} nv50_instmem_priv;
+
+#define NV50_INSTMEM_PAGE_SHIFT 12
+#define NV50_INSTMEM_PAGE_SIZE  (1 << NV50_INSTMEM_PAGE_SHIFT)
+#define NV50_INSTMEM_PT_SIZE(a)        (((a) >> 12) << 3)
+
+/*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN
+ */
+#define BAR0_WI32(g,o,v) do {                                     \
+       uint32_t offset;                                          \
+       if ((g)->im_backing) {                                    \
+               offset = (g)->im_backing->start;                  \
+       } else {                                                  \
+               offset  = chan->ramin->gpuobj->im_backing->start; \
+               offset += (g)->im_pramin->start;                  \
+       }                                                         \
+       offset += (o);                                            \
+       NV_WRITE(NV_RAMIN + (offset & 0xfffff), (v));             \
+} while(0)
+
+int
+nv50_instmem_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_channel *chan;
+       uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size;
+       nv50_instmem_priv *priv;
+       int ret, i;
+       uint32_t v;
+
+       priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER);
+       if (!priv)
+               return -ENOMEM;
+       dev_priv->Engine.instmem.priv = priv;
+
+       /* Reserve the last MiB of VRAM, we should probably try to avoid 
+        * setting up the below tables over the top of the VBIOS image at
+        * some point.
+        */
+       dev_priv->ramin_rsvd_vram = 1 << 20;
+       c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram;
+       c_size   = 128 << 10;
+       c_vmpd   = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200;
+       c_ramfc  = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20;
+       c_base   = c_vmpd + 0x4000;
+       pt_size  = NV50_INSTMEM_PT_SIZE(dev_priv->ramin->size);
+
+       DRM_DEBUG(" Rsvd VRAM base: 0x%08x\n", c_offset);
+       DRM_DEBUG("    VBIOS image: 0x%08x\n", (NV_READ(0x619f04)&~0xff)<<8);
+       DRM_DEBUG("  Aperture size: %d MiB\n",
+                 (uint32_t)dev_priv->ramin->size >> 20);
+       DRM_DEBUG("        PT size: %d KiB\n", pt_size >> 10);
+
+       NV_WRITE(NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16));
+
+       /* Create a fake channel, and use it as our "dummy" channels 0/127.
+        * The main reason for creating a channel is so we can use the gpuobj
+        * code.  However, it's probably worth noting that NVIDIA also setup
+        * their channels 0/127 with the same values they configure here.
+        * So, there may be some other reason for doing this.
+        *
+        * Have to create the entire channel manually, as the real channel
+        * creation code assumes we have PRAMIN access, and we don't until
+        * we're done here.
+        */
+       chan = drm_calloc(1, sizeof(*chan), DRM_MEM_DRIVER);
+       if (!chan)
+               return -ENOMEM;
+       chan->id = 0;
+       chan->dev = dev;
+       chan->file_priv = (struct drm_file *)-2;
+       dev_priv->fifos[0] = dev_priv->fifos[127] = chan;
+
+       /* Channel's PRAMIN object + heap */
+       if ((ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, 128<<10, 0,
+                                          NULL, &chan->ramin)))
+               return ret;
+
+       if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base))
+               return -ENOMEM;
+
+       /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */
+       if ((ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc,
+                                          0x4000, 0, NULL, &chan->ramfc)))
+               return ret;
+
+       for (i = 0; i < c_vmpd; i += 4)
+               BAR0_WI32(chan->ramin->gpuobj, i, 0);
+
+       /* VM page directory */
+       if ((ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd,
+                                          0x4000, 0, &chan->vm_pd, NULL)))
+               return ret;
+       for (i = 0; i < 0x4000; i += 8) {
+               BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000);
+               BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000);
+       }
+
+       /* PRAMIN page table, cheat and map into VM at 0x0000000000.
+        * We map the entire fake channel into the start of the PRAMIN BAR
+        */
+       if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000,
+                                         0, &priv->pramin_pt)))
+               return ret;
+
+       for (i = 0, v = c_offset; i < pt_size; i+=8, v+=0x1000) {
+               if (v < (c_offset + c_size))
+                       BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1);
+               else
+                       BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009);
+               BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); 
+       }
+
+       BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63);
+       BAR0_WI32(chan->vm_pd, 0x04, 0x00000000);
+
+       /* DMA object for PRAMIN BAR */
+       if ((ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0,
+                                         &priv->pramin_bar)))
+               return ret;
+       BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000);
+       BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin->size - 1);
+       BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000);
+       BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000);
+       BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000);
+       BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000);
+
+       /* Poke the relevant regs, and pray it works :) */
+       NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12));
+       NV_WRITE(NV50_PUNK_UNK1710, 0);
+       NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) |
+                                        NV50_PUNK_BAR_CFG_BASE_VALID);
+       NV_WRITE(NV50_PUNK_BAR1_CTXDMA, 0);
+       NV_WRITE(NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) |
+                                       NV50_PUNK_BAR3_CTXDMA_VALID);
+
+       /* Assume that praying isn't enough, check that we can re-read the
+        * entire fake channel back from the PRAMIN BAR */
+       for (i = 0; i < c_size; i+=4) {
+               if (NV_READ(NV_RAMIN + i) != NV_RI32(i)) {
+                       DRM_ERROR("Error reading back PRAMIN at 0x%08x\n", i);
+                       return -EINVAL;
+               }
+       }
+
+       /* Global PRAMIN heap */
+       if (nouveau_mem_init_heap(&dev_priv->ramin_heap,
+                                 c_size, dev_priv->ramin->size - c_size)) {
+               dev_priv->ramin_heap = NULL;
+               DRM_ERROR("Failed to init RAMIN heap\n");
+       }
+
+       /*XXX: incorrect, but needed to make hash func "work" */
+       dev_priv->ramht_offset = 0x10000;
+       dev_priv->ramht_bits   = 9;
+       dev_priv->ramht_size   = (1 << dev_priv->ramht_bits);
+       return 0;
+}
+
+void
+nv50_instmem_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv;
+       struct nouveau_channel *chan = dev_priv->fifos[0];
+       int i;
+
+       DRM_DEBUG("\n");
+
+       if (!priv)
+               return;
+
+       /* Restore state from before init */
+       for (i = 0x1700; i <= 0x1710; i+=4)
+               NV_WRITE(i, priv->save1700[(i-0x1700)/4]);
+
+       nouveau_gpuobj_ref_del(dev, &priv->pramin_bar);
+       nouveau_gpuobj_ref_del(dev, &priv->pramin_pt);
+
+       /* Destroy dummy channel */
+       if (chan) {
+               nouveau_gpuobj_del(dev, &chan->vm_pd);
+               nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+               nouveau_gpuobj_ref_del(dev, &chan->ramin);
+               nouveau_mem_takedown(&chan->ramin_heap);
+
+               dev_priv->fifos[0] = dev_priv->fifos[127] = NULL;
+               drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER);
+       }
+
+       dev_priv->Engine.instmem.priv = NULL;
+       drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
+}
+
+int
+nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz)
+{
+       if (gpuobj->im_backing)
+               return -EINVAL;
+
+       *sz = (*sz + (NV50_INSTMEM_PAGE_SIZE-1)) & ~(NV50_INSTMEM_PAGE_SIZE-1);
+       if (*sz == 0)
+               return -EINVAL;
+
+       gpuobj->im_backing = nouveau_mem_alloc(dev, NV50_INSTMEM_PAGE_SIZE,
+                                              *sz, NOUVEAU_MEM_FB,
+                                              (struct drm_file *)-2);
+       if (!gpuobj->im_backing) {
+               DRM_ERROR("Couldn't allocate vram to back PRAMIN pages\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void
+nv50_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (gpuobj && gpuobj->im_backing) {
+               if (gpuobj->im_bound)
+                       dev_priv->Engine.instmem.unbind(dev, gpuobj);
+               nouveau_mem_free(dev, gpuobj->im_backing);
+               gpuobj->im_backing = NULL;
+       }       
+}
+
+int
+nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv;
+       uint32_t pte, pte_end, vram;
+
+       if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound)
+               return -EINVAL;
+
+       DRM_DEBUG("st=0x%0llx sz=0x%0llx\n",
+                 gpuobj->im_pramin->start, gpuobj->im_pramin->size);
+
+       pte     = (gpuobj->im_pramin->start >> 12) << 3;
+       pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte;
+       vram    = gpuobj->im_backing->start;
+
+       DRM_DEBUG("pramin=0x%llx, pte=%d, pte_end=%d\n",
+                 gpuobj->im_pramin->start, pte, pte_end);
+       DRM_DEBUG("first vram page: 0x%llx\n",
+                 gpuobj->im_backing->start);
+
+       while (pte < pte_end) {
+               INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1);
+               INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000);
+
+               pte += 8;
+               vram += NV50_INSTMEM_PAGE_SIZE;
+       }
+
+       gpuobj->im_bound = 1;
+       return 0;
+}
+
+int
+nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv;
+       uint32_t pte, pte_end;
+
+       if (gpuobj->im_bound == 0)
+               return -EINVAL;
+
+       pte     = (gpuobj->im_pramin->start >> 12) << 3;
+       pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte;
+       while (pte < pte_end) {
+               INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009);
+               INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000);
+               pte += 8;
+       }
+
+       gpuobj->im_bound = 0;
+       return 0;
+}
+
diff --git a/shared-core/nv50_mc.c b/shared-core/nv50_mc.c
new file mode 100644 (file)
index 0000000..b111826
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+int
+nv50_mc_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
+
+       return 0;
+}
+
+void nv50_mc_takedown(struct drm_device *dev)
+{
+}
index a2ee18b..5bed45b 100644 (file)
@@ -81,7 +81,7 @@ static u32 r128_cce_microcode[] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-static int R128_READ_PLL(drm_device_t * dev, int addr)
+static int R128_READ_PLL(struct drm_device * dev, int addr)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
 
@@ -129,7 +129,7 @@ static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv)
 #if R128_FIFO_DEBUG
        DRM_ERROR("failed!\n");
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
@@ -146,7 +146,7 @@ static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
 #if R128_FIFO_DEBUG
        DRM_ERROR("failed!\n");
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
@@ -168,7 +168,7 @@ static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
 #if R128_FIFO_DEBUG
        DRM_ERROR("failed!\n");
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /* ================================================================
@@ -227,7 +227,7 @@ int r128_do_cce_idle(drm_r128_private_t * dev_priv)
        DRM_ERROR("failed!\n");
        r128_status(dev_priv);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /* Start the Concurrent Command Engine.
@@ -271,7 +271,7 @@ static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
 
 /* Reset the engine.  This will stop the CCE if it is running.
  */
-static int r128_do_engine_reset(drm_device_t * dev)
+static int r128_do_engine_reset(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
@@ -308,7 +308,7 @@ static int r128_do_engine_reset(drm_device_t * dev)
        return 0;
 }
 
-static void r128_cce_init_ring_buffer(drm_device_t * dev,
+static void r128_cce_init_ring_buffer(struct drm_device * dev,
                                      drm_r128_private_t * dev_priv)
 {
        u32 ring_start;
@@ -347,7 +347,7 @@ static void r128_cce_init_ring_buffer(drm_device_t * dev,
        R128_WRITE(R128_BUS_CNTL, tmp);
 }
 
-static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
+static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
 {
        drm_r128_private_t *dev_priv;
 
@@ -355,7 +355,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
 
        dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
        if (dev_priv == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        memset(dev_priv, 0, sizeof(drm_r128_private_t));
 
@@ -365,7 +365,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                DRM_ERROR("PCI GART memory not allocated!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->usec_timeout = init->usec_timeout;
@@ -374,7 +374,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                DRM_DEBUG("TIMEOUT problem!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->cce_mode = init->cce_mode;
@@ -394,7 +394,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                DRM_DEBUG("Bad cce_mode!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        switch (init->cce_mode) {
@@ -461,7 +461,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                DRM_ERROR("could not find sarea!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
@@ -469,21 +469,21 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                DRM_ERROR("could not find mmio region!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
        if (!dev_priv->cce_ring) {
                DRM_ERROR("could not find cce ring region!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
        if (!dev_priv->ring_rptr) {
                DRM_ERROR("could not find ring read pointer!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev->agp_buffer_token = init->buffers_offset;
        dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
@@ -491,7 +491,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                DRM_ERROR("could not find dma buffer region!\n");
                dev->dev_private = (void *)dev_priv;
                r128_do_cleanup_cce(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (!dev_priv->is_pci) {
@@ -501,7 +501,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                        DRM_ERROR("could not find agp texture region!\n");
                        dev->dev_private = (void *)dev_priv;
                        r128_do_cleanup_cce(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
@@ -520,7 +520,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                        DRM_ERROR("Could not ioremap agp regions!\n");
                        dev->dev_private = (void *)dev_priv;
                        r128_do_cleanup_cce(dev);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
        } else
 #endif
@@ -567,7 +567,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
                        DRM_ERROR("failed to init PCI GART!\n");
                        dev->dev_private = (void *)dev_priv;
                        r128_do_cleanup_cce(dev);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
                R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
 #if __OS_HAS_AGP
@@ -584,7 +584,7 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
        return 0;
 }
 
-int r128_do_cleanup_cce(drm_device_t * dev)
+int r128_do_cleanup_cce(struct drm_device * dev)
 {
 
        /* Make sure interrupts are disabled here because the uninstall ioctl
@@ -623,35 +623,30 @@ int r128_do_cleanup_cce(drm_device_t * dev)
        return 0;
 }
 
-int r128_cce_init(DRM_IOCTL_ARGS)
+int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_r128_init_t init;
+       drm_r128_init_t *init = data;
 
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data,
-                                sizeof(init));
-
-       switch (init.func) {
+       switch (init->func) {
        case R128_INIT_CCE:
-               return r128_do_init_cce(dev, &init);
+               return r128_do_init_cce(dev, init);
        case R128_CLEANUP_CCE:
                return r128_do_cleanup_cce(dev);
        }
 
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
-int r128_cce_start(DRM_IOCTL_ARGS)
+int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
                DRM_DEBUG("%s while CCE running\n", __FUNCTION__);
@@ -666,30 +661,26 @@ int r128_cce_start(DRM_IOCTL_ARGS)
 /* Stop the CCE.  The engine must have been idled before calling this
  * routine.
  */
-int r128_cce_stop(DRM_IOCTL_ARGS)
+int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_cce_stop_t stop;
+       drm_r128_cce_stop_t *stop = data;
        int ret;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data,
-                                sizeof(stop));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        /* Flush any pending CCE commands.  This ensures any outstanding
         * commands are exectuted by the engine before we turn it off.
         */
-       if (stop.flush) {
+       if (stop->flush) {
                r128_do_cce_flush(dev_priv);
        }
 
        /* If we fail to make the engine go idle, we return an error
         * code so that the DRM ioctl wrapper can try again.
         */
-       if (stop.idle) {
+       if (stop->idle) {
                ret = r128_do_cce_idle(dev_priv);
                if (ret)
                        return ret;
@@ -709,17 +700,16 @@ int r128_cce_stop(DRM_IOCTL_ARGS)
 
 /* Just reset the CCE ring.  Called as part of an X Server engine reset.
  */
-int r128_cce_reset(DRM_IOCTL_ARGS)
+int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_DEBUG("%s called before init done\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        r128_do_cce_reset(dev_priv);
@@ -730,13 +720,12 @@ int r128_cce_reset(DRM_IOCTL_ARGS)
        return 0;
 }
 
-int r128_cce_idle(DRM_IOCTL_ARGS)
+int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (dev_priv->cce_running) {
                r128_do_cce_flush(dev_priv);
@@ -745,19 +734,18 @@ int r128_cce_idle(DRM_IOCTL_ARGS)
        return r128_do_cce_idle(dev_priv);
 }
 
-int r128_engine_reset(DRM_IOCTL_ARGS)
+int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return r128_do_engine_reset(dev);
 }
 
-int r128_fullscreen(DRM_IOCTL_ARGS)
+int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
 /* ================================================================
@@ -767,18 +755,18 @@ int r128_fullscreen(DRM_IOCTL_ARGS)
 #define R128_BUFFER_FREE       0
 
 #if 0
-static int r128_freelist_init(drm_device_t * dev)
+static int r128_freelist_init(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        drm_r128_buf_priv_t *buf_priv;
        drm_r128_freelist_t *entry;
        int i;
 
        dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
        if (dev_priv->head == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
        dev_priv->head->age = R128_BUFFER_USED;
@@ -789,7 +777,7 @@ static int r128_freelist_init(drm_device_t * dev)
 
                entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
                if (!entry)
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
 
                entry->age = R128_BUFFER_FREE;
                entry->buf = buf;
@@ -813,12 +801,12 @@ static int r128_freelist_init(drm_device_t * dev)
 }
 #endif
 
-static drm_buf_t *r128_freelist_get(drm_device_t * dev)
+static struct drm_buf *r128_freelist_get(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_r128_private_t *dev_priv = dev->dev_private;
        drm_r128_buf_priv_t *buf_priv;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        int i, t;
 
        /* FIXME: Optimize -- use freelist code */
@@ -826,7 +814,7 @@ static drm_buf_t *r128_freelist_get(drm_device_t * dev)
        for (i = 0; i < dma->buf_count; i++) {
                buf = dma->buflist[i];
                buf_priv = buf->dev_private;
-               if (buf->filp == 0)
+               if (buf->file_priv == 0)
                        return buf;
        }
 
@@ -851,13 +839,13 @@ static drm_buf_t *r128_freelist_get(drm_device_t * dev)
        return NULL;
 }
 
-void r128_freelist_reset(drm_device_t * dev)
+void r128_freelist_reset(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int i;
 
        for (i = 0; i < dma->buf_count; i++) {
-               drm_buf_t *buf = dma->buflist[i];
+               struct drm_buf *buf = dma->buflist[i];
                drm_r128_buf_priv_t *buf_priv = buf->dev_private;
                buf_priv->age = 0;
        }
@@ -881,68 +869,64 @@ int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
 
        /* FIXME: This is being ignored... */
        DRM_ERROR("failed!\n");
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
-static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+static int r128_cce_get_buffers(struct drm_device * dev,
+                               struct drm_file *file_priv,
+                               struct drm_dma * d)
 {
        int i;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
 
        for (i = d->granted_count; i < d->request_count; i++) {
                buf = r128_freelist_get(dev);
                if (!buf)
-                       return DRM_ERR(EAGAIN);
+                       return -EAGAIN;
 
-               buf->filp = filp;
+               buf->file_priv = file_priv;
 
                if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
                                     sizeof(buf->idx)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
                                     sizeof(buf->total)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
 
                d->granted_count++;
        }
        return 0;
 }
 
-int r128_cce_buffers(DRM_IOCTL_ARGS)
+int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int ret = 0;
-       drm_dma_t __user *argp = (void __user *)data;
-       drm_dma_t d;
+       struct drm_dma *d = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        /* Please don't send us buffers.
         */
-       if (d.send_count != 0) {
+       if (d->send_count != 0) {
                DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d.send_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
        }
 
        /* We'll send you buffers.
         */
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
                DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d.request_count, dma->buf_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
        }
 
-       d.granted_count = 0;
+       d->granted_count = 0;
 
-       if (d.request_count) {
-               ret = r128_cce_get_buffers(filp, dev, &d);
+       if (d->request_count) {
+               ret = r128_cce_get_buffers(dev, file_priv, d);
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
-
        return ret;
 }
index 6e8af31..8d8878b 100644 (file)
@@ -153,7 +153,7 @@ typedef struct drm_r128_sarea {
 
        /* The current cliprects, or a subset thereof.
         */
-       drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
+       struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS];
        unsigned int nbox;
 
        /* Counters for client-side throttling of rendering clients.
@@ -161,7 +161,7 @@ typedef struct drm_r128_sarea {
        unsigned int last_frame;
        unsigned int last_dispatch;
 
-       drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
+       struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
        unsigned int tex_age[R128_NR_TEX_HEAPS];
        int ctx_owner;
        int pfAllowPageFlip;    /* number of 3d windows (0,1,2 or more) */
@@ -222,11 +222,7 @@ typedef struct drm_r128_init {
                R128_INIT_CCE = 0x01,
                R128_CLEANUP_CCE = 0x02
        } func;
-#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
-       int sarea_priv_offset;
-#else
        unsigned long sarea_priv_offset;
-#endif
        int is_pci;
        int cce_mode;
        int cce_secure;
@@ -240,21 +236,12 @@ typedef struct drm_r128_init {
        unsigned int depth_offset, depth_pitch;
        unsigned int span_offset;
 
-#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
-       unsigned int fb_offset;
-       unsigned int mmio_offset;
-       unsigned int ring_offset;
-       unsigned int ring_rptr_offset;
-       unsigned int buffers_offset;
-       unsigned int agp_textures_offset;
-#else
        unsigned long fb_offset;
        unsigned long mmio_offset;
        unsigned long ring_offset;
        unsigned long ring_rptr_offset;
        unsigned long buffers_offset;
        unsigned long agp_textures_offset;
-#endif
 } drm_r128_init_t;
 
 typedef struct drm_r128_cce_stop {
@@ -264,15 +251,10 @@ typedef struct drm_r128_cce_stop {
 
 typedef struct drm_r128_clear {
        unsigned int flags;
-#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
-       int x, y, w, h;
-#endif
        unsigned int clear_color;
        unsigned int clear_depth;
-#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
        unsigned int color_mask;
        unsigned int depth_mask;
-#endif
 } drm_r128_clear_t;
 
 typedef struct drm_r128_vertex {
index 9086835..abb9989 100644 (file)
@@ -57,7 +57,7 @@
 
 typedef struct drm_r128_freelist {
        unsigned int age;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        struct drm_r128_freelist *next;
        struct drm_r128_freelist *prev;
 } drm_r128_freelist_t;
@@ -118,7 +118,7 @@ typedef struct drm_r128_private {
        drm_local_map_t *cce_ring;
        drm_local_map_t *ring_rptr;
        drm_local_map_t *agp_textures;
-       drm_ati_pcigart_info gart_info;
+       struct ati_pcigart_info gart_info;
 } drm_r128_private_t;
 
 typedef struct drm_r128_buf_priv {
@@ -129,34 +129,35 @@ typedef struct drm_r128_buf_priv {
        drm_r128_freelist_t *list_entry;
 } drm_r128_buf_priv_t;
 
-extern drm_ioctl_desc_t r128_ioctls[];
+extern struct drm_ioctl_desc r128_ioctls[];
 extern int r128_max_ioctl;
 
                                /* r128_cce.c */
-extern int r128_cce_init(DRM_IOCTL_ARGS);
-extern int r128_cce_start(DRM_IOCTL_ARGS);
-extern int r128_cce_stop(DRM_IOCTL_ARGS);
-extern int r128_cce_reset(DRM_IOCTL_ARGS);
-extern int r128_cce_idle(DRM_IOCTL_ARGS);
-extern int r128_engine_reset(DRM_IOCTL_ARGS);
-extern int r128_fullscreen(DRM_IOCTL_ARGS);
-extern int r128_cce_buffers(DRM_IOCTL_ARGS);
+extern int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
-extern void r128_freelist_reset(drm_device_t * dev);
+extern void r128_freelist_reset(struct drm_device * dev);
 
 extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
 
 extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
-extern int r128_do_cleanup_cce(drm_device_t * dev);
+extern int r128_do_cleanup_cce(struct drm_device * dev);
 
-extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 
 extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
-extern void r128_driver_irq_preinstall(drm_device_t * dev);
-extern void r128_driver_irq_postinstall(drm_device_t * dev);
-extern void r128_driver_irq_uninstall(drm_device_t * dev);
-extern void r128_driver_lastclose(drm_device_t * dev);
-extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void r128_driver_irq_preinstall(struct drm_device * dev);
+extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern void r128_driver_irq_uninstall(struct drm_device * dev);
+extern void r128_driver_lastclose(struct drm_device * dev);
+extern void r128_driver_preclose(struct drm_device * dev,
+                                struct drm_file *file_priv);
 
 extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
@@ -428,7 +429,7 @@ do {                                                                        \
                        DRM_UDELAY(1);                          \
                }                                                       \
                DRM_ERROR( "ring space check failed!\n" );              \
-               return DRM_ERR(EBUSY);                          \
+               return -EBUSY;                          \
        }                                                               \
  __ring_space_done:                                                    \
        ;                                                               \
index 87f8ca2..c76fdca 100644 (file)
@@ -37,7 +37,7 @@
 
 irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
 {
-       drm_device_t *dev = (drm_device_t *) arg;
+       struct drm_device *dev = (struct drm_device *) arg;
        drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
        int status;
 
@@ -54,7 +54,7 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
        return IRQ_NONE;
 }
 
-int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
        unsigned int cur_vblank;
        int ret = 0;
@@ -72,7 +72,7 @@ int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
        return ret;
 }
 
-void r128_driver_irq_preinstall(drm_device_t * dev)
+void r128_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 
@@ -82,7 +82,7 @@ void r128_driver_irq_preinstall(drm_device_t * dev)
        R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
 }
 
-void r128_driver_irq_postinstall(drm_device_t * dev)
+void r128_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
 
@@ -90,7 +90,7 @@ void r128_driver_irq_postinstall(drm_device_t * dev)
        R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
 }
 
-void r128_driver_irq_uninstall(drm_device_t * dev)
+void r128_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
        if (!dev_priv)
index 17b11e7..b7f483c 100644 (file)
@@ -38,7 +38,7 @@
  */
 
 static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
-                                drm_clip_rect_t * boxes, int count)
+                                struct drm_clip_rect * boxes, int count)
 {
        u32 aux_sc_cntl = 0x00000000;
        RING_LOCALS;
@@ -352,13 +352,13 @@ static void r128_print_dirty(const char *msg, unsigned int flags)
                 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
 }
 
-static void r128_cce_dispatch_clear(drm_device_t * dev,
+static void r128_cce_dispatch_clear(struct drm_device * dev,
                                    drm_r128_clear_t * clear)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        unsigned int flags = clear->flags;
        int i;
        RING_LOCALS;
@@ -458,12 +458,12 @@ static void r128_cce_dispatch_clear(drm_device_t * dev,
        }
 }
 
-static void r128_cce_dispatch_swap(drm_device_t * dev)
+static void r128_cce_dispatch_swap(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int i;
        RING_LOCALS;
        DRM_DEBUG("%s\n", __FUNCTION__);
@@ -524,7 +524,7 @@ static void r128_cce_dispatch_swap(drm_device_t * dev)
        ADVANCE_RING();
 }
 
-static void r128_cce_dispatch_flip(drm_device_t * dev)
+static void r128_cce_dispatch_flip(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -567,7 +567,7 @@ static void r128_cce_dispatch_flip(drm_device_t * dev)
        ADVANCE_RING();
 }
 
-static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -637,8 +637,8 @@ static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
        sarea_priv->nbox = 0;
 }
 
-static void r128_cce_dispatch_indirect(drm_device_t * dev,
-                                      drm_buf_t * buf, int start, int end)
+static void r128_cce_dispatch_indirect(struct drm_device * dev,
+                                      struct drm_buf * buf, int start, int end)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        drm_r128_buf_priv_t *buf_priv = buf->dev_private;
@@ -692,8 +692,8 @@ static void r128_cce_dispatch_indirect(drm_device_t * dev,
        dev_priv->sarea_priv->last_dispatch++;
 }
 
-static void r128_cce_dispatch_indices(drm_device_t * dev,
-                                     drm_buf_t * buf,
+static void r128_cce_dispatch_indices(struct drm_device * dev,
+                                     struct drm_buf * buf,
                                      int start, int end, int count)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
@@ -776,12 +776,13 @@ static void r128_cce_dispatch_indices(drm_device_t * dev,
        sarea_priv->nbox = 0;
 }
 
-static int r128_cce_dispatch_blit(DRMFILE filp,
-                                 drm_device_t * dev, drm_r128_blit_t * blit)
+static int r128_cce_dispatch_blit(struct drm_device * dev,
+                                 struct drm_file *file_priv,
+                                 drm_r128_blit_t * blit)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_r128_buf_priv_t *buf_priv;
        u32 *data;
        int dword_shift, dwords;
@@ -809,7 +810,7 @@ static int r128_cce_dispatch_blit(DRMFILE filp,
                break;
        default:
                DRM_ERROR("invalid blit format %d\n", blit->format);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /* Flush the pixel cache, and mark the contents as Read Invalid.
@@ -829,14 +830,14 @@ static int r128_cce_dispatch_blit(DRMFILE filp,
        buf = dma->buflist[blit->idx];
        buf_priv = buf->dev_private;
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
        if (buf->pending) {
                DRM_ERROR("sending pending buffer %d\n", blit->idx);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        buf_priv->discard = 1;
@@ -887,7 +888,7 @@ static int r128_cce_dispatch_blit(DRMFILE filp,
  * have hardware stencil support.
  */
 
-static int r128_cce_dispatch_write_span(drm_device_t * dev,
+static int r128_cce_dispatch_write_span(struct drm_device * dev,
                                        drm_r128_depth_t * depth)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
@@ -900,22 +901,22 @@ static int r128_cce_dispatch_write_span(drm_device_t * dev,
 
        count = depth->n;
        if (count > 4096 || count <= 0)
-               return DRM_ERR(EMSGSIZE);
+               return -EMSGSIZE;
 
        if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
        if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        buffer_size = depth->n * sizeof(u32);
        buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
        if (buffer == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
                drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        mask_size = depth->n * sizeof(u8);
@@ -923,12 +924,12 @@ static int r128_cce_dispatch_write_span(drm_device_t * dev,
                mask = drm_alloc(mask_size, DRM_MEM_BUFS);
                if (mask == NULL) {
                        drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
                if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
                        drm_free(buffer, buffer_size, DRM_MEM_BUFS);
                        drm_free(mask, mask_size, DRM_MEM_BUFS);
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                }
 
                for (i = 0; i < count; i++, x++) {
@@ -983,7 +984,7 @@ static int r128_cce_dispatch_write_span(drm_device_t * dev,
        return 0;
 }
 
-static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
                                          drm_r128_depth_t * depth)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
@@ -996,28 +997,28 @@ static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
 
        count = depth->n;
        if (count > 4096 || count <= 0)
-               return DRM_ERR(EMSGSIZE);
+               return -EMSGSIZE;
 
        xbuf_size = count * sizeof(*x);
        ybuf_size = count * sizeof(*y);
        x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
        if (x == NULL) {
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
        y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
        if (y == NULL) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
        if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
                drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
        if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
                drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        buffer_size = depth->n * sizeof(u32);
@@ -1025,13 +1026,13 @@ static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
        if (buffer == NULL) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
                drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
        if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
                drm_free(y, ybuf_size, DRM_MEM_BUFS);
                drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        if (depth->mask) {
@@ -1041,14 +1042,14 @@ static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
                        drm_free(x, xbuf_size, DRM_MEM_BUFS);
                        drm_free(y, ybuf_size, DRM_MEM_BUFS);
                        drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
                if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
                        drm_free(x, xbuf_size, DRM_MEM_BUFS);
                        drm_free(y, ybuf_size, DRM_MEM_BUFS);
                        drm_free(buffer, buffer_size, DRM_MEM_BUFS);
                        drm_free(mask, mask_size, DRM_MEM_BUFS);
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                }
 
                for (i = 0; i < count; i++) {
@@ -1105,7 +1106,7 @@ static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
        return 0;
 }
 
-static int r128_cce_dispatch_read_span(drm_device_t * dev,
+static int r128_cce_dispatch_read_span(struct drm_device * dev,
                                       drm_r128_depth_t * depth)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1115,13 +1116,13 @@ static int r128_cce_dispatch_read_span(drm_device_t * dev,
 
        count = depth->n;
        if (count > 4096 || count <= 0)
-               return DRM_ERR(EMSGSIZE);
+               return -EMSGSIZE;
 
        if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
        if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        BEGIN_RING(7);
@@ -1148,7 +1149,7 @@ static int r128_cce_dispatch_read_span(drm_device_t * dev,
        return 0;
 }
 
-static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
+static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
                                         drm_r128_depth_t * depth)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1159,7 +1160,7 @@ static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
 
        count = depth->n;
        if (count > 4096 || count <= 0)
-               return DRM_ERR(EMSGSIZE);
+               return -EMSGSIZE;
 
        if (count > dev_priv->depth_pitch) {
                count = dev_priv->depth_pitch;
@@ -1169,22 +1170,22 @@ static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
        ybuf_size = count * sizeof(*y);
        x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
        if (x == NULL) {
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
        y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
        if (y == NULL) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
        if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
                drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
        if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
                drm_free(x, xbuf_size, DRM_MEM_BUFS);
                drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        for (i = 0; i < count; i++) {
@@ -1220,7 +1221,7 @@ static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
  * Polygon stipple
  */
 
-static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        int i;
@@ -1241,25 +1242,21 @@ static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
  * IOCTL functions
  */
 
-static int r128_cce_clear(DRM_IOCTL_ARGS)
+static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
        drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_clear_t clear;
+       drm_r128_clear_t *clear = data;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(clear, (drm_r128_clear_t __user *) data,
-                                sizeof(clear));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
        if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
 
-       r128_cce_dispatch_clear(dev, &clear);
+       r128_cce_dispatch_clear(dev, clear);
        COMMIT_RING();
 
        /* Make sure we restore the 3D state next time.
@@ -1269,7 +1266,7 @@ static int r128_cce_clear(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int r128_do_init_pageflip(drm_device_t * dev)
+static int r128_do_init_pageflip(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
@@ -1288,7 +1285,7 @@ static int r128_do_init_pageflip(drm_device_t * dev)
        return 0;
 }
 
-static int r128_do_cleanup_pageflip(drm_device_t * dev)
+static int r128_do_cleanup_pageflip(struct drm_device * dev)
 {
        drm_r128_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
@@ -1309,13 +1306,12 @@ static int r128_do_cleanup_pageflip(drm_device_t * dev)
  * They can & should be intermixed to support multiple 3d windows.
  */
 
-static int r128_cce_flip(DRM_IOCTL_ARGS)
+static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
@@ -1328,14 +1324,13 @@ static int r128_cce_flip(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int r128_cce_swap(DRM_IOCTL_ARGS)
+static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
        drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
@@ -1350,58 +1345,54 @@ static int r128_cce_swap(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int r128_cce_vertex(DRM_IOCTL_ARGS)
+static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_r128_buf_priv_t *buf_priv;
-       drm_r128_vertex_t vertex;
+       drm_r128_vertex_t *vertex = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(vertex, (drm_r128_vertex_t __user *) data,
-                                sizeof(vertex));
-
        DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
-                 DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
+                 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
 
-       if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+       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 DRM_ERR(EINVAL);
+                         vertex->idx, dma->buf_count - 1);
+               return -EINVAL;
        }
-       if (vertex.prim < 0 ||
-           vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
-               DRM_ERROR("buffer prim %d\n", vertex.prim);
-               return DRM_ERR(EINVAL);
+       if (vertex->prim < 0 ||
+           vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+               DRM_ERROR("buffer prim %d\n", vertex->prim);
+               return -EINVAL;
        }
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
        VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-       buf = dma->buflist[vertex.idx];
+       buf = dma->buflist[vertex->idx];
        buf_priv = buf->dev_private;
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
        if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", vertex.idx);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
+               return -EINVAL;
        }
 
-       buf->used = vertex.count;
-       buf_priv->prim = vertex.prim;
-       buf_priv->discard = vertex.discard;
+       buf->used = vertex->count;
+       buf_priv->prim = vertex->prim;
+       buf_priv->discard = vertex->discard;
 
        r128_cce_dispatch_vertex(dev, buf);
 
@@ -1409,134 +1400,123 @@ static int r128_cce_vertex(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int r128_cce_indices(DRM_IOCTL_ARGS)
+static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_r128_buf_priv_t *buf_priv;
-       drm_r128_indices_t elts;
+       drm_r128_indices_t *elts = data;
        int count;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(elts, (drm_r128_indices_t __user *) data,
-                                sizeof(elts));
-
        DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
-                 elts.idx, elts.start, elts.end, elts.discard);
+                 elts->idx, elts->start, elts->end, elts->discard);
 
-       if (elts.idx < 0 || elts.idx >= dma->buf_count) {
+       if (elts->idx < 0 || elts->idx >= dma->buf_count) {
                DRM_ERROR("buffer index %d (of %d max)\n",
-                         elts.idx, dma->buf_count - 1);
-               return DRM_ERR(EINVAL);
+                         elts->idx, dma->buf_count - 1);
+               return -EINVAL;
        }
-       if (elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
-               DRM_ERROR("buffer prim %d\n", elts.prim);
-               return DRM_ERR(EINVAL);
+       if (elts->prim < 0 ||
+           elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+               DRM_ERROR("buffer prim %d\n", elts->prim);
+               return -EINVAL;
        }
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
        VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-       buf = dma->buflist[elts.idx];
+       buf = dma->buflist[elts->idx];
        buf_priv = buf->dev_private;
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
        if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", elts.idx);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("sending pending buffer %d\n", elts->idx);
+               return -EINVAL;
        }
 
-       count = (elts.end - elts.start) / sizeof(u16);
-       elts.start -= R128_INDEX_PRIM_OFFSET;
+       count = (elts->end - elts->start) / sizeof(u16);
+       elts->start -= R128_INDEX_PRIM_OFFSET;
 
-       if (elts.start & 0x7) {
-               DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
-               return DRM_ERR(EINVAL);
+       if (elts->start & 0x7) {
+               DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
+               return -EINVAL;
        }
-       if (elts.start < buf->used) {
-               DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
-               return DRM_ERR(EINVAL);
+       if (elts->start < buf->used) {
+               DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
+               return -EINVAL;
        }
 
-       buf->used = elts.end;
-       buf_priv->prim = elts.prim;
-       buf_priv->discard = elts.discard;
+       buf->used = elts->end;
+       buf_priv->prim = elts->prim;
+       buf_priv->discard = elts->discard;
 
-       r128_cce_dispatch_indices(dev, buf, elts.start, elts.end, count);
+       r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);
 
        COMMIT_RING();
        return 0;
 }
 
-static int r128_cce_blit(DRM_IOCTL_ARGS)
+static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_blit_t blit;
+       drm_r128_blit_t *blit = data;
        int ret;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(blit, (drm_r128_blit_t __user *) data,
-                                sizeof(blit));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit.idx);
+       DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
 
-       if (blit.idx < 0 || blit.idx >= dma->buf_count) {
+       if (blit->idx < 0 || blit->idx >= dma->buf_count) {
                DRM_ERROR("buffer index %d (of %d max)\n",
-                         blit.idx, dma->buf_count - 1);
-               return DRM_ERR(EINVAL);
+                         blit->idx, dma->buf_count - 1);
+               return -EINVAL;
        }
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
        VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-       ret = r128_cce_dispatch_blit(filp, dev, &blit);
+       ret = r128_cce_dispatch_blit(dev, file_priv, blit);
 
        COMMIT_RING();
        return ret;
 }
 
-static int r128_cce_depth(DRM_IOCTL_ARGS)
+static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_depth_t depth;
+       drm_r128_depth_t *depth = data;
        int ret;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(depth, (drm_r128_depth_t __user *) data,
-                                sizeof(depth));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
-       ret = DRM_ERR(EINVAL);
-       switch (depth.func) {
+       ret = -EINVAL;
+       switch (depth->func) {
        case R128_WRITE_SPAN:
-               ret = r128_cce_dispatch_write_span(dev, &depth);
+               ret = r128_cce_dispatch_write_span(dev, depth);
                break;
        case R128_WRITE_PIXELS:
-               ret = r128_cce_dispatch_write_pixels(dev, &depth);
+               ret = r128_cce_dispatch_write_pixels(dev, depth);
                break;
        case R128_READ_SPAN:
-               ret = r128_cce_dispatch_read_span(dev, &depth);
+               ret = r128_cce_dispatch_read_span(dev, depth);
                break;
        case R128_READ_PIXELS:
-               ret = r128_cce_dispatch_read_pixels(dev, &depth);
+               ret = r128_cce_dispatch_read_pixels(dev, depth);
                break;
        }
 
@@ -1544,20 +1524,16 @@ static int r128_cce_depth(DRM_IOCTL_ARGS)
        return ret;
 }
 
-static int r128_cce_stipple(DRM_IOCTL_ARGS)
+static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_stipple_t stipple;
+       drm_r128_stipple_t *stipple = data;
        u32 mask[32];
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(stipple, (drm_r128_stipple_t __user *) data,
-                                sizeof(stipple));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
-               return DRM_ERR(EFAULT);
+       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+               return -EFAULT;
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
@@ -1567,61 +1543,58 @@ static int r128_cce_stipple(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int r128_cce_indirect(DRM_IOCTL_ARGS)
+static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_r128_buf_priv_t *buf_priv;
-       drm_r128_indirect_t indirect;
+       drm_r128_indirect_t *indirect = data;
 #if 0
        RING_LOCALS;
 #endif
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(indirect, (drm_r128_indirect_t __user *) data,
-                                sizeof(indirect));
-
        DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
-                 indirect.idx, indirect.start, indirect.end, indirect.discard);
+                 indirect->idx, indirect->start, indirect->end,
+                 indirect->discard);
 
-       if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
+       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 DRM_ERR(EINVAL);
+                         indirect->idx, dma->buf_count - 1);
+               return -EINVAL;
        }
 
-       buf = dma->buflist[indirect.idx];
+       buf = dma->buflist[indirect->idx];
        buf_priv = buf->dev_private;
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
        if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", indirect.idx);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("sending pending buffer %d\n", indirect->idx);
+               return -EINVAL;
        }
 
-       if (indirect.start < buf->used) {
+       if (indirect->start < buf->used) {
                DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
-                         indirect.start, buf->used);
-               return DRM_ERR(EINVAL);
+                         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;
+       buf->used = indirect->end;
+       buf_priv->discard = indirect->discard;
 
 #if 0
        /* Wait for the 3D stream to idle before the indirect buffer
@@ -1636,46 +1609,42 @@ static int r128_cce_indirect(DRM_IOCTL_ARGS)
         * X server.  This is insecure and is thus only available to
         * privileged clients.
         */
-       r128_cce_dispatch_indirect(dev, buf, indirect.start, indirect.end);
+       r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);
 
        COMMIT_RING();
        return 0;
 }
 
-static int r128_getparam(DRM_IOCTL_ARGS)
+static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_getparam_t param;
+       drm_r128_getparam_t *param = data;
        int value;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(param, (drm_r128_getparam_t __user *) data,
-                                sizeof(param));
-
        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
 
-       switch (param.param) {
+       switch (param->param) {
        case R128_PARAM_IRQ_NR:
                value = dev->irq;
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
 }
 
-void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
        if (dev->dev_private) {
                drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1685,29 +1654,29 @@ void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
        }
 }
 
-void r128_driver_lastclose(drm_device_t * dev)
+void r128_driver_lastclose(struct drm_device * dev)
 {
        r128_do_cleanup_cce(dev);
 }
 
-drm_ioctl_desc_t r128_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH},
+struct drm_ioctl_desc r128_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH),
 };
 
 int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
index d3c52d4..fe46c2d 100644 (file)
@@ -55,7 +55,7 @@ static const int r300_cliprect_cntl[4] = {
 static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
                               drm_radeon_kcmd_buffer_t *cmdbuf, int n)
 {
-       drm_clip_rect_t box;
+       struct drm_clip_rect box;
        int nr;
        int i;
        RING_LOCALS;
@@ -74,7 +74,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
                        if (DRM_COPY_FROM_USER_UNCHECKED
                            (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
                                DRM_ERROR("copy cliprect faulted\n");
-                               return DRM_ERR(EFAULT);
+                               return -EFAULT;
                        }
 
                        box.x1 =
@@ -155,7 +155,8 @@ void r300_init_reg_flags(void)
        ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
        ADD_RANGE(0x21DC, 1);
        ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
-       ADD_RANGE(0x2220, 4);
+       ADD_RANGE(R300_VAP_CLIP_X_0, 4);
+       ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
        ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
        ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
        ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
@@ -262,7 +263,7 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
                DRM_ERROR
                    ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
                     reg, sz);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        for (i = 0; i < sz; i++) {
                values[i] = ((int *)cmdbuf->buf)[i];
@@ -274,13 +275,13 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
                                DRM_ERROR
                                    ("Offset failed range check (reg=%04x sz=%d)\n",
                                     reg, sz);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        break;
                default:
                        DRM_ERROR("Register %04x failed check as flag=%02x\n",
                                  reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
@@ -316,12 +317,12 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
                return 0;
 
        if (sz * 4 > cmdbuf->bufsz)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        if (reg + sz * 4 >= 0x10000) {
                DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
                          sz);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (r300_check_range(reg, sz)) {
@@ -361,7 +362,7 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
        if (!sz)
                return 0;
        if (sz * 16 > cmdbuf->bufsz)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        BEGIN_RING(5 + sz * 4);
        /* Wait for VAP to come to senses.. */
@@ -390,7 +391,7 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
        RING_LOCALS;
 
        if (8 * 4 > cmdbuf->bufsz)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        BEGIN_RING(10);
        OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
@@ -420,7 +421,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
        if ((count + 1) > MAX_ARRAY_PACKET) {
                DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
                          count);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        memset(payload, 0, MAX_ARRAY_PACKET * 4);
        memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
@@ -436,7 +437,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
                        DRM_ERROR
                            ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
                             k, i);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                k++;
                i++;
@@ -447,7 +448,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
                        DRM_ERROR
                            ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
                             k, i);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                k++;
                i++;
@@ -457,7 +458,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
                DRM_ERROR
                    ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
                     k, i, narrays, count + 1);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /* all clear, output packet */
@@ -491,7 +492,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
                        ret = !radeon_check_offset(dev_priv, offset);
                        if (ret) {
                                DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                }
 
@@ -501,7 +502,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
                        ret = !radeon_check_offset(dev_priv, offset);
                        if (ret) {
                                DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        
                }
@@ -529,12 +530,12 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
 
        if ((cmd[1] & 0x8000ffff) != 0x80000810) {
                DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        ret = !radeon_check_offset(dev_priv, cmd[2]);
        if (ret) {
                DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        BEGIN_RING(count+2);
@@ -556,7 +557,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
        RING_LOCALS;
 
        if (4 > cmdbuf->bufsz)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        /* Fixme !! This simply emits a packet without much checking.
           We need to be smarter. */
@@ -567,7 +568,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
        /* Is it packet 3 ? */
        if ((header >> 30) != 0x3) {
                DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        count = (header >> 16) & 0x3fff;
@@ -577,7 +578,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
                DRM_ERROR
                    ("Expected packet3 of length %d but have only %d bytes left\n",
                     (count + 2) * 4, cmdbuf->bufsz);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /* Is it a packet type we know about ? */
@@ -599,7 +600,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
                break;
        default:
                DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        BEGIN_RING(count + 2);
@@ -663,7 +664,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
                        DRM_ERROR("bad packet3 type %i at %p\n",
                                  header.packet3.packet,
                                  cmdbuf->buf - sizeof(header));
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                n += R300_SIMULTANEOUS_CLIPRECTS;
@@ -705,7 +706,7 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
  * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
  * be careful about how this function is called.
  */
-static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -724,11 +725,11 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
        RING_LOCALS;
        
        if (cmdbuf->bufsz < sizeof(uint64_t) + header.scratch.n_bufs * sizeof(buf_idx) ) {
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        
        if (header.scratch.reg >= 5) {
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        
        dev_priv->scratch_ages[header.scratch.reg] ++;
@@ -743,21 +744,21 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
                buf_idx *= 2; /* 8 bytes per buf */
                
                if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                                        
                if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                                        
                if (h_pending == 0) {
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                                        
                h_pending--;
                                                
                if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                                        
                cmdbuf->buf += sizeof(buf_idx);
@@ -777,14 +778,13 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
  * commands on the DMA ring buffer.
  * Called by the ioctl handler function radeon_cp_cmdbuf.
  */
-int r300_do_cp_cmdbuf(drm_device_t *dev,
-                     DRMFILE filp,
-                     drm_file_t *filp_priv,
+int r300_do_cp_cmdbuf(struct drm_device *dev,
+                     struct drm_file *file_priv,
                      drm_radeon_kcmd_buffer_t *cmdbuf)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf = NULL;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf = NULL;
        int emit_dispatch_age = 0;
        int ret = 0;
 
@@ -877,15 +877,16 @@ int r300_do_cp_cmdbuf(drm_device_t *dev,
                        if (idx < 0 || idx >= dma->buf_count) {
                                DRM_ERROR("buffer index %d (of %d max)\n",
                                          idx, dma->buf_count - 1);
-                               ret = DRM_ERR(EINVAL);
+                               ret = -EINVAL;
                                goto cleanup;
                        }
 
                        buf = dma->buflist[idx];
-                       if (buf->filp != filp || buf->pending) {
+                       if (buf->file_priv != file_priv || buf->pending) {
                                DRM_ERROR("bad buffer %p %p %d\n",
-                                         buf->filp, filp, buf->pending);
-                               ret = DRM_ERR(EINVAL);
+                                         buf->file_priv, file_priv,
+                                         buf->pending);
+                               ret = -EINVAL;
                                goto cleanup;
                        }
 
@@ -922,7 +923,7 @@ int r300_do_cp_cmdbuf(drm_device_t *dev,
                        DRM_ERROR("bad cmd_type %i at %p\n",
                                  header.header.cmd_type,
                                  cmdbuf->buf - sizeof(header));
-                       ret = DRM_ERR(EINVAL);
+                       ret = -EINVAL;
                        goto cleanup;
                }
        }
index 0a31f0b..e59919b 100644 (file)
@@ -116,6 +116,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
 
 #define R300_VAP_OUTPUT_VTX_FMT_1           0x2094
+       /* each of the following is 3 bits wide, specifies number
+          of components */
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
 #       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
@@ -299,6 +301,18 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_221C_NORMAL                  0x00000000
 #       define R300_221C_CLEAR                   0x0001C000
 
+/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
+ * plane is per-pixel and the second plane is per-vertex.
+ *
+ * This was determined by experimentation alone but I believe it is correct.
+ *
+ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
+ */
+#define R300_VAP_CLIP_X_0                   0x2220
+#define R300_VAP_CLIP_X_1                   0x2224
+#define R300_VAP_CLIP_Y_0                   0x2228
+#define R300_VAP_CLIP_Y_1                   0x2230
+
 /* gap */
 
 /* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
@@ -322,13 +336,15 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  * The meaning of the two UNKNOWN fields is obviously not known. However,
  * experiments so far have shown that both *must* point to an instruction
  * inside the vertex program, otherwise the GPU locks up.
+ *
  * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
- * CNTL_1_UNKNOWN points to instruction where last write to position takes
- * place.
+ * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to
+ * position takes place.
+ *
  * Most likely this is used to ignore rest of the program in cases
  * where group of verts arent visible. For some reason this "section"
  * is sometimes accepted other instruction that have no relationship with
- *position calculations.
+ * position calculations.
  */
 #define R300_VAP_PVS_CNTL_1                 0x22D0
 #       define R300_PVS_CNTL_1_PROGRAM_START_SHIFT   0
@@ -967,7 +983,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  * first node is stored in NODE_2, the second node is stored in NODE_3.
  *
  * Offsets are relative to the master offset from PFS_CNTL_2.
- * LAST_NODE is set for the last node, and only for the last node.
  */
 #define R300_PFS_NODE_0                     0x4610
 #define R300_PFS_NODE_1                     0x4614
@@ -981,7 +996,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_PFS_NODE_TEX_OFFSET_MASK     (31 << 12)
 #       define R300_PFS_NODE_TEX_END_SHIFT       17
 #       define R300_PFS_NODE_TEX_END_MASK        (31 << 17)
-/*#       define R300_PFS_NODE_LAST_NODE           (1 << 22) */
 #              define R300_PFS_NODE_OUTPUT_COLOR        (1 << 22)
 #              define R300_PFS_NODE_OUTPUT_DEPTH        (1 << 23)
 
@@ -1591,6 +1605,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #    define R300_EB_UNK1_SHIFT                      24
 #    define R300_EB_UNK1                    (0x80<<24)
 #    define R300_EB_UNK2                        0x0810
+#define R300_PACKET3_3D_DRAW_VBUF_2         0x00003400
 #define R300_PACKET3_3D_DRAW_INDX_2         0x00003600
 
 /* END: Packet 3 commands */
index 2c0549e..006d04f 100644 (file)
@@ -36,7 +36,7 @@
 
 #define RADEON_FIFO_DEBUG      0
 
-static int radeon_do_cleanup_cp(drm_device_t * dev);
+static int radeon_do_cleanup_cp(struct drm_device * dev);
 
 /* CP microcode (from ATI) */
 static const u32 R200_cp_microcode[][2] = {
@@ -816,7 +816,7 @@ static const u32 R300_cp_microcode[][2] = {
        { 0000000000, 0000000000 },
 };
 
-static int RADEON_READ_PLL(drm_device_t * dev, int addr)
+static int RADEON_READ_PLL(struct drm_device * dev, int addr)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -889,7 +889,7 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
        DRM_ERROR("failed!\n");
        radeon_status(dev_priv);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
@@ -910,7 +910,7 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
        DRM_ERROR("failed!\n");
        radeon_status(dev_priv);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
@@ -936,7 +936,7 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
        DRM_ERROR("failed!\n");
        radeon_status(dev_priv);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /* ================================================================
@@ -1066,7 +1066,7 @@ static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
 
 /* Reset the engine.  This will stop the CP if it is running.
  */
-static int radeon_do_engine_reset(drm_device_t * dev)
+static int radeon_do_engine_reset(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
@@ -1122,7 +1122,7 @@ static int radeon_do_engine_reset(drm_device_t * dev)
        return 0;
 }
 
-static void radeon_cp_init_ring_buffer(drm_device_t * dev,
+static void radeon_cp_init_ring_buffer(struct drm_device * dev,
                                       drm_radeon_private_t * dev_priv)
 {
        u32 ring_start, cur_read_ptr;
@@ -1174,7 +1174,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
        } else
 #endif
        {
-               drm_sg_mem_t *entry = dev->sg;
+               struct drm_sg_mem *entry = dev->sg;
                unsigned long tmp_ofs, page_ofs;
 
                tmp_ofs = dev_priv->ring_rptr->offset -
@@ -1190,9 +1190,15 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
        /* Set ring buffer size */
 #ifdef __BIG_ENDIAN
        RADEON_WRITE(RADEON_CP_RB_CNTL,
-                    dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
+                    RADEON_BUF_SWAP_32BIT |
+                    (dev_priv->ring.fetch_size_l2ow << 18) |
+                    (dev_priv->ring.rptr_update_l2qw << 8) |
+                    dev_priv->ring.size_l2qw);
 #else
-       RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
+       RADEON_WRITE(RADEON_CP_RB_CNTL,
+                    (dev_priv->ring.fetch_size_l2ow << 18) |
+                    (dev_priv->ring.rptr_update_l2qw << 8) |
+                    dev_priv->ring.size_l2qw);
 #endif
 
        /* Start with assuming that writeback doesn't work */
@@ -1384,7 +1390,6 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
        }
 }
 
-
 void radeon_gart_flush(struct drm_device *dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1407,7 +1412,7 @@ void radeon_gart_flush(struct drm_device *dev)
 
 }
 
-static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1417,7 +1422,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
                DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP))
@@ -1435,7 +1440,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
                DRM_ERROR("PCI GART memory not allocated!\n");
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->usec_timeout = init->usec_timeout;
@@ -1443,7 +1448,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
            dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
                DRM_DEBUG("TIMEOUT problem!\n");
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /* Enable vblank on CRTC1 for older X servers
@@ -1472,7 +1477,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
            (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
                DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        switch (init->fb_bpp) {
@@ -1541,27 +1546,27 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        if (!dev_priv->sarea) {
                DRM_ERROR("could not find sarea!\n");
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
        if (!dev_priv->cp_ring) {
                DRM_ERROR("could not find cp ring region!\n");
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
        if (!dev_priv->ring_rptr) {
                DRM_ERROR("could not find ring read pointer!\n");
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev->agp_buffer_token = init->buffers_offset;
        dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
        if (!dev->agp_buffer_map) {
                DRM_ERROR("could not find dma buffer region!\n");
                radeon_do_cleanup_cp(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (init->gart_textures_offset) {
@@ -1570,7 +1575,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                if (!dev_priv->gart_textures) {
                        DRM_ERROR("could not find GART texture region!\n");
                        radeon_do_cleanup_cp(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
@@ -1588,7 +1593,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                    !dev->agp_buffer_map->handle) {
                        DRM_ERROR("could not find ioremap agp regions!\n");
                        radeon_do_cleanup_cp(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        } else
 #endif
@@ -1689,6 +1694,12 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        dev_priv->ring.size = init->ring_size;
        dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
 
+       dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
+       dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
+
+       dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
+       dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
+
        dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
 
        dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
@@ -1736,14 +1747,14 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                                DRM_ERROR
                                    ("Cannot use PCI Express without GART in FB memory\n");
                                radeon_do_cleanup_cp(dev);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                }
 
                if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
                        DRM_ERROR("failed to init PCI GART!\n");
                        radeon_do_cleanup_cp(dev);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
 
                /* Turn on PCI GART */
@@ -1761,7 +1772,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
        return 0;
 }
 
-static int radeon_do_cleanup_cp(drm_device_t * dev)
+static int radeon_do_cleanup_cp(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
@@ -1817,13 +1828,13 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
  *
  * Charl P. Botha <http://cpbotha.net>
  */
-static int radeon_do_resume_cp(drm_device_t * dev)
+static int radeon_do_resume_cp(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
        if (!dev_priv) {
                DRM_ERROR("Called with no initialization\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        DRM_DEBUG("Starting radeon_do_resume_cp()\n");
@@ -1849,38 +1860,33 @@ static int radeon_do_resume_cp(drm_device_t * dev)
        return 0;
 }
 
-int radeon_cp_init(DRM_IOCTL_ARGS)
+int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_radeon_init_t init;
+       drm_radeon_init_t *init = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_radeon_init_t __user *) data,
-                                sizeof(init));
-
-       if (init.func == RADEON_INIT_R300_CP)
+       if (init->func == RADEON_INIT_R300_CP)
                r300_init_reg_flags();
 
-       switch (init.func) {
+       switch (init->func) {
        case RADEON_INIT_CP:
        case RADEON_INIT_R200_CP:
        case RADEON_INIT_R300_CP:
-               return radeon_do_init_cp(dev, &init);
+               return radeon_do_init_cp(dev, init);
        case RADEON_CLEANUP_CP:
                return radeon_do_cleanup_cp(dev);
        }
 
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
-int radeon_cp_start(DRM_IOCTL_ARGS)
+int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (dev_priv->cp_running) {
                DRM_DEBUG("%s while CP running\n", __FUNCTION__);
@@ -1900,18 +1906,14 @@ int radeon_cp_start(DRM_IOCTL_ARGS)
 /* Stop the CP.  The engine must have been idled before calling this
  * routine.
  */
-int radeon_cp_stop(DRM_IOCTL_ARGS)
+int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_cp_stop_t stop;
+       drm_radeon_cp_stop_t *stop = data;
        int ret;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(stop, (drm_radeon_cp_stop_t __user *) data,
-                                sizeof(stop));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv->cp_running)
                return 0;
@@ -1919,14 +1921,14 @@ int radeon_cp_stop(DRM_IOCTL_ARGS)
        /* Flush any pending CP commands.  This ensures any outstanding
         * commands are exectuted by the engine before we turn it off.
         */
-       if (stop.flush) {
+       if (stop->flush) {
                radeon_do_cp_flush(dev_priv);
        }
 
        /* If we fail to make the engine go idle, we return an error
         * code so that the DRM ioctl wrapper can try again.
         */
-       if (stop.idle) {
+       if (stop->idle) {
                ret = radeon_do_cp_idle(dev_priv);
                if (ret)
                        return ret;
@@ -1944,7 +1946,7 @@ int radeon_cp_stop(DRM_IOCTL_ARGS)
        return 0;
 }
 
-void radeon_do_release(drm_device_t * dev)
+void radeon_do_release(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        int i, ret;
@@ -1994,17 +1996,16 @@ void radeon_do_release(drm_device_t * dev)
 
 /* Just reset the CP ring.  Called as part of an X Server engine reset.
  */
-int radeon_cp_reset(DRM_IOCTL_ARGS)
+int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_DEBUG("%s called before init done\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        radeon_do_cp_reset(dev_priv);
@@ -2015,32 +2016,29 @@ int radeon_cp_reset(DRM_IOCTL_ARGS)
        return 0;
 }
 
-int radeon_cp_idle(DRM_IOCTL_ARGS)
+int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return radeon_do_cp_idle(dev_priv);
 }
 
 /* Added by Charl P. Botha to call radeon_do_resume_cp().
  */
-int radeon_cp_resume(DRM_IOCTL_ARGS)
+int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
        return radeon_do_resume_cp(dev);
 }
 
-int radeon_engine_reset(DRM_IOCTL_ARGS)
+int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return radeon_do_engine_reset(dev);
 }
@@ -2051,7 +2049,7 @@ int radeon_engine_reset(DRM_IOCTL_ARGS)
 
 /* KW: Deprecated to say the least:
  */
-int radeon_fullscreen(DRM_IOCTL_ARGS)
+int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        return 0;
 }
@@ -2077,12 +2075,12 @@ int radeon_fullscreen(DRM_IOCTL_ARGS)
  * they can't get the lock.
  */
 
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_buf_priv_t *buf_priv;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        int i, t;
        int start;
 
@@ -2097,8 +2095,9 @@ drm_buf_t *radeon_freelist_get(drm_device_t * dev)
                for (i = start; i < dma->buf_count; i++) {
                        buf = dma->buflist[i];
                        buf_priv = buf->dev_private;
-                       if (buf->filp == 0 || (buf->pending &&
-                                              buf_priv->age <= done_age)) {
+                       if (buf->file_priv == NULL || (buf->pending &&
+                                                      buf_priv->age <=
+                                                      done_age)) {
                                dev_priv->stats.requested_bufs++;
                                buf->pending = 0;
                                return buf;
@@ -2117,12 +2116,12 @@ drm_buf_t *radeon_freelist_get(drm_device_t * dev)
 }
 
 #if 0
-drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_buf_priv_t *buf_priv;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        int i, t;
        int start;
        u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
@@ -2137,8 +2136,9 @@ drm_buf_t *radeon_freelist_get(drm_device_t * dev)
                for (i = start; i < dma->buf_count; i++) {
                        buf = dma->buflist[i];
                        buf_priv = buf->dev_private;
-                       if (buf->filp == 0 || (buf->pending &&
-                                              buf_priv->age <= done_age)) {
+                       if (buf->file_priv == 0 || (buf->pending &&
+                                                   buf_priv->age <=
+                                                   done_age)) {
                                dev_priv->stats.requested_bufs++;
                                buf->pending = 0;
                                return buf;
@@ -2151,15 +2151,15 @@ drm_buf_t *radeon_freelist_get(drm_device_t * dev)
 }
 #endif
 
-void radeon_freelist_reset(drm_device_t * dev)
+void radeon_freelist_reset(struct drm_device * dev)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        int i;
 
        dev_priv->last_buf = 0;
        for (i = 0; i < dma->buf_count; i++) {
-               drm_buf_t *buf = dma->buflist[i];
+               struct drm_buf *buf = dma->buflist[i];
                drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
                buf_priv->age = 0;
        }
@@ -2198,70 +2198,65 @@ int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
        radeon_status(dev_priv);
        DRM_ERROR("failed!\n");
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
-static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev,
-                                drm_dma_t * d)
+static int radeon_cp_get_buffers(struct drm_device *dev,
+                                struct drm_file *file_priv,
+                                struct drm_dma * d)
 {
        int i;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
 
        for (i = d->granted_count; i < d->request_count; i++) {
                buf = radeon_freelist_get(dev);
                if (!buf)
-                       return DRM_ERR(EBUSY);  /* NOTE: broken client */
+                       return -EBUSY;  /* NOTE: broken client */
 
-               buf->filp = filp;
+               buf->file_priv = file_priv;
 
                if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
                                     sizeof(buf->idx)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
                                     sizeof(buf->total)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
 
                d->granted_count++;
        }
        return 0;
 }
 
-int radeon_cp_buffers(DRM_IOCTL_ARGS)
+int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        int ret = 0;
-       drm_dma_t __user *argp = (void __user *)data;
-       drm_dma_t d;
+       struct drm_dma *d = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        /* Please don't send us buffers.
         */
-       if (d.send_count != 0) {
+       if (d->send_count != 0) {
                DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d.send_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
        }
 
        /* We'll send you buffers.
         */
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
                DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d.request_count, dma->buf_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
        }
 
-       d.granted_count = 0;
+       d->granted_count = 0;
 
-       if (d.request_count) {
-               ret = radeon_cp_get_buffers(filp, dev, &d);
+       if (d->request_count) {
+               ret = radeon_cp_get_buffers(dev, file_priv, d);
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
-
        return ret;
 }
 
@@ -2272,7 +2267,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
 
        dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
        if (dev_priv == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        memset(dev_priv, 0, sizeof(drm_radeon_private_t));
        dev->dev_private = (void *)dev_priv;
index 41fdbf6..913b23c 100644 (file)
@@ -417,7 +417,7 @@ typedef struct {
 
        /* The current cliprects, or a subset thereof.
         */
-       drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
+       struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS];
        unsigned int nbox;
 
        /* Counters for client-side throttling of rendering clients.
@@ -426,7 +426,7 @@ typedef struct {
        unsigned int last_dispatch;
        unsigned int last_clear;
 
-       drm_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
+       struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
                                                       1];
        unsigned int tex_age[RADEON_NR_TEX_HEAPS];
        int ctx_owner;
@@ -613,7 +613,7 @@ typedef struct drm_radeon_cmd_buffer {
        int bufsz;
        char __user *buf;
        int nbox;
-       drm_clip_rect_t __user *boxes;
+       struct drm_clip_rect __user *boxes;
 } drm_radeon_cmd_buffer_t;
 
 typedef struct drm_radeon_tex_image {
index 5a33231..f74fe93 100644 (file)
@@ -161,7 +161,7 @@ enum radeon_chip_flags {
 
 typedef struct drm_radeon_freelist {
        unsigned int age;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        struct drm_radeon_freelist *next;
        struct drm_radeon_freelist *prev;
 } drm_radeon_freelist_t;
@@ -169,8 +169,14 @@ typedef struct drm_radeon_freelist {
 typedef struct drm_radeon_ring_buffer {
        u32 *start;
        u32 *end;
-       int size;
-       int size_l2qw;
+       int size; /* Double Words */
+       int size_l2qw; /* log2 Quad Words */
+
+       int rptr_update; /* Double Words */
+       int rptr_update_l2qw; /* log2 Quad Words */
+
+       int fetch_size; /* Double Words */
+       int fetch_size_l2ow; /* log2 Oct Words */
 
        u32 tail;
        u32 tail_mask;
@@ -194,7 +200,7 @@ struct mem_block {
        struct mem_block *prev;
        int start;
        int size;
-       DRMFILE filp;           /* 0: free, -1: heap, other: real files */
+       struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
 };
 
 struct radeon_surface {
@@ -209,7 +215,7 @@ struct radeon_virt_surface {
        u32 lower;
        u32 upper;
        u32 flags;
-       DRMFILE filp;
+       struct drm_file *file_priv;
 };
 
 typedef struct drm_radeon_private {
@@ -295,7 +301,7 @@ typedef struct drm_radeon_private {
 
        unsigned long pcigart_offset;
        unsigned int pcigart_offset_set;
-       drm_ati_pcigart_info gart_info;
+       struct ati_pcigart_info gart_info;
 
        u32 scratch_ages[5];
 
@@ -312,11 +318,11 @@ typedef struct drm_radeon_kcmd_buffer {
        int bufsz;
        char *buf;
        int nbox;
-       drm_clip_rect_t __user *boxes;
+       struct drm_clip_rect __user *boxes;
 } drm_radeon_kcmd_buffer_t;
 
 extern int radeon_no_wb;
-extern drm_ioctl_desc_t radeon_ioctls[];
+extern struct drm_ioctl_desc radeon_ioctls[];
 extern int radeon_max_ioctl;
 
 /* Check whether the given hardware address is inside the framebuffer or the
@@ -335,62 +341,66 @@ static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
 }
 
                                /* radeon_cp.c */
-extern int radeon_cp_init(DRM_IOCTL_ARGS);
-extern int radeon_cp_start(DRM_IOCTL_ARGS);
-extern int radeon_cp_stop(DRM_IOCTL_ARGS);
-extern int radeon_cp_reset(DRM_IOCTL_ARGS);
-extern int radeon_cp_idle(DRM_IOCTL_ARGS);
-extern int radeon_cp_resume(DRM_IOCTL_ARGS);
-extern int radeon_engine_reset(DRM_IOCTL_ARGS);
-extern int radeon_fullscreen(DRM_IOCTL_ARGS);
-extern int radeon_cp_buffers(DRM_IOCTL_ARGS);
+extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
 extern void radeon_gart_flush(struct drm_device *dev);
 
-extern void radeon_freelist_reset(drm_device_t * dev);
-extern drm_buf_t *radeon_freelist_get(drm_device_t * dev);
+extern void radeon_freelist_reset(struct drm_device * dev);
+extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
 
 extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
 
 extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv);
 
-extern int radeon_mem_alloc(DRM_IOCTL_ARGS);
-extern int radeon_mem_free(DRM_IOCTL_ARGS);
-extern int radeon_mem_init_heap(DRM_IOCTL_ARGS);
+extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv);
 extern void radeon_mem_takedown(struct mem_block **heap);
-extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap);
+extern void radeon_mem_release(struct drm_file *file_priv,
+                              struct mem_block *heap);
 
                                /* radeon_irq.c */
-extern int radeon_irq_emit(DRM_IOCTL_ARGS);
-extern int radeon_irq_wait(DRM_IOCTL_ARGS);
-extern int radeon_emit_irq(drm_device_t * dev);
+extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_emit_irq(struct drm_device * dev);
 
-extern void radeon_do_release(drm_device_t * dev);
-extern int radeon_driver_vblank_wait(drm_device_t * dev,
+extern void radeon_do_release(struct drm_device * dev);
+extern int radeon_driver_vblank_wait(struct drm_device * dev,
                                     unsigned int *sequence);
-extern int radeon_driver_vblank_wait2(drm_device_t * dev,
+extern int radeon_driver_vblank_wait2(struct drm_device * dev,
                                      unsigned int *sequence);
 extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
-extern void radeon_driver_irq_preinstall(drm_device_t * dev);
-extern void radeon_driver_irq_postinstall(drm_device_t * dev);
-extern void radeon_driver_irq_uninstall(drm_device_t * dev);
-extern int radeon_vblank_crtc_get(drm_device_t *dev);
-extern int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value);
+extern void radeon_driver_irq_preinstall(struct drm_device * dev);
+extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern void radeon_driver_irq_uninstall(struct drm_device * dev);
+extern int radeon_vblank_crtc_get(struct drm_device *dev);
+extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
 
 extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
 extern int radeon_driver_unload(struct drm_device *dev);
 extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp);
-extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp);
-extern void radeon_driver_lastclose(drm_device_t * dev);
-extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv);
+extern void radeon_driver_preclose(struct drm_device * dev,
+                                  struct drm_file *file_priv);
+extern void radeon_driver_postclose(struct drm_device * dev,
+                                   struct drm_file *file_priv);
+extern void radeon_driver_lastclose(struct drm_device * dev);
+extern int radeon_driver_open(struct drm_device * dev,
+                             struct drm_file * file_priv);
 extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
                                         unsigned long arg);
 
 /* r300_cmdbuf.c */
 extern void r300_init_reg_flags(void);
 
-extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp,
-                            drm_file_t* filp_priv,
+extern int r300_do_cp_cmdbuf(struct drm_device *dev,
+                            struct drm_file *file_priv,
                             drm_radeon_kcmd_buffer_t* cmdbuf);
 
 
@@ -398,24 +408,24 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp,
 /* i915_fence.c */
 
 
-extern void radeon_fence_handler(drm_device_t *dev);
-extern int radeon_fence_emit_sequence(drm_device_t *dev, uint32_t class,
+extern void radeon_fence_handler(struct drm_device *dev);
+extern int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class,
                                      uint32_t flags, uint32_t *sequence, 
                                    uint32_t *native_type);
-extern void radeon_poke_flush(drm_device_t *dev, uint32_t class);
-extern int radeon_fence_has_irq(drm_device_t *dev, uint32_t class, uint32_t flags);
+extern void radeon_poke_flush(struct drm_device *dev, uint32_t class);
+extern int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags);
 #endif
 
 #ifdef RADEON_HAVE_BUFFER
 /* radeon_buffer.c */
-extern drm_ttm_backend_t *radeon_create_ttm_backend_entry(drm_device_t *dev);
+extern drm_ttm_backend_t *radeon_create_ttm_backend_entry(struct drm_device *dev);
 extern int radeon_fence_types(struct drm_buffer_object *bo, uint32_t *class, uint32_t *type);
-extern int radeon_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags);
-extern uint32_t radeon_evict_mask(drm_buffer_object_t *bo);
-extern int radeon_init_mem_type(drm_device_t * dev, uint32_t type,
-                               drm_mem_type_manager_t * man);
-extern int radeon_move(drm_buffer_object_t * bo,
-                      int evict, int no_wait, drm_bo_mem_reg_t * new_mem);
+extern int radeon_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
+extern uint32_t radeon_evict_mask(struct drm_buffer_object *bo);
+extern int radeon_init_mem_type(struct drm_device * dev, uint32_t type,
+                               struct drm_mem_type_manager * man);
+extern int radeon_move(struct drm_buffer_object * bo,
+                      int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
 #endif
 /* Flags for stats.boxes
  */
@@ -644,9 +654,51 @@ extern int radeon_move(drm_buffer_object_t * bo,
 #      define RADEON_SOFT_RESET_E2             (1 <<  5)
 #      define RADEON_SOFT_RESET_RB             (1 <<  6)
 #      define RADEON_SOFT_RESET_HDP            (1 <<  7)
+/*
+ *   6:0  Available slots in the FIFO
+ *   8    Host Interface active
+ *   9    CP request active
+ *   10   FIFO request active
+ *   11   Host Interface retry active
+ *   12   CP retry active
+ *   13   FIFO retry active
+ *   14   FIFO pipeline busy
+ *   15   Event engine busy
+ *   16   CP command stream busy
+ *   17   2D engine busy
+ *   18   2D portion of render backend busy
+ *   20   3D setup engine busy
+ *   26   GA engine busy
+ *   27   CBA 2D engine busy
+ *   31   2D engine busy or 3D engine busy or FIFO not empty or CP busy or
+ *           command stream queue not empty or Ring Buffer not empty
+ */
 #define RADEON_RBBM_STATUS             0x0e40
+/* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register.  */
+/* #define RADEON_RBBM_STATUS          0x1740 */
+/* bits 6:0 are dword slots available in the cmd fifo */
 #      define RADEON_RBBM_FIFOCNT_MASK         0x007f
-#      define RADEON_RBBM_ACTIVE               (1 << 31)
+#      define RADEON_HIRQ_ON_RBB       (1 <<  8)
+#      define RADEON_CPRQ_ON_RBB       (1 <<  9)
+#      define RADEON_CFRQ_ON_RBB       (1 << 10)
+#      define RADEON_HIRQ_IN_RTBUF     (1 << 11)
+#      define RADEON_CPRQ_IN_RTBUF     (1 << 12)
+#      define RADEON_CFRQ_IN_RTBUF     (1 << 13)
+#      define RADEON_PIPE_BUSY         (1 << 14)
+#      define RADEON_ENG_EV_BUSY       (1 << 15)
+#      define RADEON_CP_CMDSTRM_BUSY   (1 << 16)
+#      define RADEON_E2_BUSY           (1 << 17)
+#      define RADEON_RB2D_BUSY         (1 << 18)
+#      define RADEON_RB3D_BUSY         (1 << 19) /* not used on r300 */
+#      define RADEON_VAP_BUSY          (1 << 20)
+#      define RADEON_RE_BUSY           (1 << 21) /* not used on r300 */
+#      define RADEON_TAM_BUSY          (1 << 22) /* not used on r300 */
+#      define RADEON_TDM_BUSY          (1 << 23) /* not used on r300 */
+#      define RADEON_PB_BUSY           (1 << 24) /* not used on r300 */
+#      define RADEON_TIM_BUSY          (1 << 25) /* not used on r300 */
+#      define RADEON_GA_BUSY           (1 << 26)
+#      define RADEON_CBA2D_BUSY        (1 << 27)
+#      define RADEON_RBBM_ACTIVE       (1 << 31)
 #define RADEON_RE_LINE_PATTERN         0x1cd0
 #define RADEON_RE_MISC                 0x26c4
 #define RADEON_RE_TOP_LEFT             0x26c0
@@ -1249,7 +1301,7 @@ do {                                                                      \
 /* Breadcrumb - swi irq */
 #define READ_BREADCRUMB(dev_priv) RADEON_READ(RADEON_LAST_SWI_REG)
 
-static inline int radeon_update_breadcrumb(drm_device_t *dev)
+static inline int radeon_update_breadcrumb(struct drm_device *dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
index 95d8332..3162e26 100644 (file)
@@ -64,7 +64,7 @@ static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
 
 irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
 {
-       drm_device_t *dev = (drm_device_t *) arg;
+       struct drm_device *dev = (struct drm_device *) arg;
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
        u32 stat;
@@ -72,10 +72,14 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
        /* Only consider the bits we're interested in - others could be used
         * outside the DRM
         */
-       stat = radeon_acknowledge_irqs(dev_priv, dev_priv->irq_enable_reg);
+       stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+                                                 RADEON_CRTC_VBLANK_STAT |
+                                                 RADEON_CRTC2_VBLANK_STAT));
        if (!stat)
                return IRQ_NONE;
 
+       stat &= dev_priv->irq_enable_reg;
+
        /* SW interrupt */
        if (stat & RADEON_SW_INT_TEST) {
                DRM_WAKEUP(&dev_priv->irq_queue);
@@ -108,7 +112,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
        return IRQ_HANDLED;
 }
 
-int radeon_emit_irq(drm_device_t * dev)
+int radeon_emit_irq(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        unsigned int ret;
@@ -125,25 +129,26 @@ int radeon_emit_irq(drm_device_t * dev)
        return ret;
 }
 
-static int radeon_wait_irq(drm_device_t * dev, int irq_nr)
+static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
 {
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
        int ret = 0;
 
-       if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+       if (READ_BREADCRUMB(dev_priv) >= swi_nr)
                return 0;
 
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
        DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
-                   READ_BREADCRUMB(dev_priv) >= irq_nr);
+                   READ_BREADCRUMB(dev_priv) >= swi_nr);
 
        return ret;
 }
 
-int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
-                                int crtc)
+static int radeon_driver_vblank_do_wait(struct drm_device * dev,
+                                       unsigned int *sequence,
+                                       int crtc)
 {
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
@@ -153,7 +158,7 @@ int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
        atomic_t *counter;
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (crtc == DRM_RADEON_VBLANK_CRTC1) {
@@ -163,7 +168,7 @@ int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
                counter = &dev->vbl_received2;
                ack |= RADEON_CRTC2_VBLANK_STAT;
        } else
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        radeon_acknowledge_irqs(dev_priv, ack);
 
@@ -182,40 +187,36 @@ int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
        return ret;
 }
 
-int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
 {
        return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
 }
 
-int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
 {
        return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
 }
 
 /* Needs the lock as it touches the ring.
  */
-int radeon_irq_emit(DRM_IOCTL_ARGS)
+int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_irq_emit_t emit;
+       drm_radeon_irq_emit_t *emit = data;
        int result;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(emit, (drm_radeon_irq_emit_t __user *) data,
-                                sizeof(emit));
-
        result = radeon_emit_irq(dev);
 
-       if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
+       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
@@ -223,24 +224,20 @@ int radeon_irq_emit(DRM_IOCTL_ARGS)
 
 /* Doesn't need the hardware lock.
  */
-int radeon_irq_wait(DRM_IOCTL_ARGS)
+int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_irq_wait_t irqwait;
+       drm_radeon_irq_wait_t *irqwait = data;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_radeon_irq_wait_t __user *) data,
-                                sizeof(irqwait));
-
-       return radeon_wait_irq(dev, irqwait.irq_seq);
+       return radeon_wait_irq(dev, irqwait->irq_seq);
 }
 
-static void radeon_enable_interrupt(drm_device_t *dev)
+static void radeon_enable_interrupt(struct drm_device *dev)
 {
        drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
 
@@ -257,7 +254,7 @@ static void radeon_enable_interrupt(drm_device_t *dev)
 
 /* drm_dma.h hooks
 */
-void radeon_driver_irq_preinstall(drm_device_t * dev)
+void radeon_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
@@ -267,10 +264,11 @@ void radeon_driver_irq_preinstall(drm_device_t * dev)
 
        /* Clear bits if they're already high */
        radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-                                          RADEON_CRTC_VBLANK_STAT));
+                                          RADEON_CRTC_VBLANK_STAT |
+                                          RADEON_CRTC2_VBLANK_STAT));
 }
 
-void radeon_driver_irq_postinstall(drm_device_t * dev)
+void radeon_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
@@ -281,7 +279,7 @@ void radeon_driver_irq_postinstall(drm_device_t * dev)
        radeon_enable_interrupt(dev);
 }
 
-void radeon_driver_irq_uninstall(drm_device_t * dev)
+void radeon_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv =
            (drm_radeon_private_t *) dev->dev_private;
@@ -295,7 +293,7 @@ void radeon_driver_irq_uninstall(drm_device_t * dev)
 }
 
 
-int radeon_vblank_crtc_get(drm_device_t *dev)
+int radeon_vblank_crtc_get(struct drm_device *dev)
 {
        drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
        u32 flag;
@@ -312,12 +310,12 @@ int radeon_vblank_crtc_get(drm_device_t *dev)
        return value;
 }
 
-int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value)
+int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
 {
        drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
        if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
                DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        dev_priv->vblank_crtc = (unsigned int)value;
        radeon_enable_interrupt(dev);
index dbc91c9..9947e94 100644 (file)
@@ -39,7 +39,7 @@
  */
 
 static struct mem_block *split_block(struct mem_block *p, int start, int size,
-                                    DRMFILE filp)
+                                    struct drm_file *file_priv)
 {
        /* Maybe cut off the start of an existing block */
        if (start > p->start) {
@@ -49,7 +49,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
                        goto out;
                newblock->start = start;
                newblock->size = p->size - (start - p->start);
-               newblock->filp = NULL;
+               newblock->file_priv = NULL;
                newblock->next = p->next;
                newblock->prev = p;
                p->next->prev = newblock;
@@ -66,7 +66,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
                        goto out;
                newblock->start = start + size;
                newblock->size = p->size - size;
-               newblock->filp = NULL;
+               newblock->file_priv = NULL;
                newblock->next = p->next;
                newblock->prev = p;
                p->next->prev = newblock;
@@ -76,20 +76,20 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size,
 
       out:
        /* Our block is in the middle */
-       p->filp = filp;
+       p->file_priv = file_priv;
        return p;
 }
 
 static struct mem_block *alloc_block(struct mem_block *heap, int size,
-                                    int align2, DRMFILE filp)
+                                    int align2, struct drm_file *file_priv)
 {
        struct mem_block *p;
        int mask = (1 << align2) - 1;
 
        list_for_each(p, heap) {
                int start = (p->start + mask) & ~mask;
-               if (p->filp == 0 && start + size <= p->start + p->size)
-                       return split_block(p, start, size, filp);
+               if (p->file_priv == 0 && start + size <= p->start + p->size)
+                       return split_block(p, start, size, file_priv);
        }
 
        return NULL;
@@ -108,12 +108,12 @@ static struct mem_block *find_block(struct mem_block *heap, int start)
 
 static void free_block(struct mem_block *p)
 {
-       p->filp = NULL;
+       p->file_priv = NULL;
 
-       /* Assumes a single contiguous range.  Needs a special filp in
+       /* Assumes a single contiguous range.  Needs a special file_priv in
         * 'heap' to stop it being subsumed.
         */
-       if (p->next->filp == 0) {
+       if (p->next->file_priv == 0) {
                struct mem_block *q = p->next;
                p->size += q->size;
                p->next = q->next;
@@ -121,7 +121,7 @@ static void free_block(struct mem_block *p)
                drm_free(q, sizeof(*q), DRM_MEM_BUFS);
        }
 
-       if (p->prev->filp == 0) {
+       if (p->prev->file_priv == 0) {
                struct mem_block *q = p->prev;
                q->size += p->size;
                q->next = p->next;
@@ -137,28 +137,28 @@ static int init_heap(struct mem_block **heap, int start, int size)
        struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
 
        if (!blocks)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
        if (!*heap) {
                drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        blocks->start = start;
        blocks->size = size;
-       blocks->filp = NULL;
+       blocks->file_priv = NULL;
        blocks->next = blocks->prev = *heap;
 
        memset(*heap, 0, sizeof(**heap));
-       (*heap)->filp = (DRMFILE) - 1;
+       (*heap)->file_priv = (struct drm_file *) - 1;
        (*heap)->next = (*heap)->prev = blocks;
        return 0;
 }
 
 /* Free all blocks associated with the releasing file.
  */
-void radeon_mem_release(DRMFILE filp, struct mem_block *heap)
+void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap)
 {
        struct mem_block *p;
 
@@ -166,15 +166,15 @@ void radeon_mem_release(DRMFILE filp, struct mem_block *heap)
                return;
 
        list_for_each(p, heap) {
-               if (p->filp == filp)
-                       p->filp = NULL;
+               if (p->file_priv == file_priv)
+                       p->file_priv = NULL;
        }
 
-       /* Assumes a single contiguous range.  Needs a special filp in
+       /* Assumes a single contiguous range.  Needs a special file_priv in
         * 'heap' to stop it being subsumed.
         */
        list_for_each(p, heap) {
-               while (p->filp == 0 && p->next->filp == 0) {
+               while (p->file_priv == 0 && p->next->file_priv == 0) {
                        struct mem_block *q = p->next;
                        p->size += q->size;
                        p->next = q->next;
@@ -217,98 +217,86 @@ static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
        }
 }
 
-int radeon_mem_alloc(DRM_IOCTL_ARGS)
+int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_mem_alloc_t alloc;
+       drm_radeon_mem_alloc_t *alloc = data;
        struct mem_block *block, **heap;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_mem_alloc_t __user *) data,
-                                sizeof(alloc));
-
-       heap = get_heap(dev_priv, alloc.region);
+       heap = get_heap(dev_priv, alloc->region);
        if (!heap || !*heap)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
        /* Make things easier on ourselves: all allocations at least
         * 4k aligned.
         */
-       if (alloc.alignment < 12)
-               alloc.alignment = 12;
+       if (alloc->alignment < 12)
+               alloc->alignment = 12;
 
-       block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
+       block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
 
        if (!block)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
-       if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
+       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
+                            sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
 }
 
-int radeon_mem_free(DRM_IOCTL_ARGS)
+int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_mem_free_t memfree;
+       drm_radeon_mem_free_t *memfree = data;
        struct mem_block *block, **heap;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
-                                sizeof(memfree));
-
-       heap = get_heap(dev_priv, memfree.region);
+       heap = get_heap(dev_priv, memfree->region);
        if (!heap || !*heap)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
-       block = find_block(*heap, memfree.region_offset);
+       block = find_block(*heap, memfree->region_offset);
        if (!block)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
-       if (block->filp != filp)
-               return DRM_ERR(EPERM);
+       if (block->file_priv != file_priv)
+               return -EPERM;
 
        free_block(block);
        return 0;
 }
 
-int radeon_mem_init_heap(DRM_IOCTL_ARGS)
+int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_mem_init_heap_t initheap;
+       drm_radeon_mem_init_heap_t *initheap = data;
        struct mem_block **heap;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(initheap,
-                                (drm_radeon_mem_init_heap_t __user *) data,
-                                sizeof(initheap));
-
-       heap = get_heap(dev_priv, initheap.region);
+       heap = get_heap(dev_priv, initheap->region);
        if (!heap)
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
        if (*heap) {
                DRM_ERROR("heap already initialized?");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
-       return init_heap(heap, initheap.start, initheap.size);
+       return init_heap(heap, initheap->start, initheap->size);
 }
index 8ccd098..e3aadfb 100644 (file)
@@ -39,7 +39,7 @@
 
 static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
                                                    dev_priv,
-                                                   drm_file_t * filp_priv,
+                                                   struct drm_file *file_priv,
                                                    u32 * offset)
 {
        u64 off = *offset;
@@ -71,7 +71,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
         * magic offset we get from SETPARAM or calculated from fb_location
         */
        if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
-               radeon_priv = filp_priv->driver_priv;
+               radeon_priv = file_priv->driver_priv;
                off += radeon_priv->radeon_fb_delta;
        }
 
@@ -85,29 +85,29 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
                *offset = off;
                return 0;
        }
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
 static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
                                                     dev_priv,
-                                                    drm_file_t * filp_priv,
+                                                    struct drm_file *file_priv,
                                                     int id, u32 *data)
 {
        switch (id) {
 
        case RADEON_EMIT_PP_MISC:
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                    &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
                        DRM_ERROR("Invalid depth buffer offset\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
 
        case RADEON_EMIT_PP_CNTL:
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                    &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
                        DRM_ERROR("Invalid colour buffer offset\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
 
@@ -117,20 +117,20 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
        case R200_EMIT_PP_TXOFFSET_3:
        case R200_EMIT_PP_TXOFFSET_4:
        case R200_EMIT_PP_TXOFFSET_5:
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                                                  &data[0])) {
                        DRM_ERROR("Invalid R200 texture offset\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
 
        case RADEON_EMIT_PP_TXFILTER_0:
        case RADEON_EMIT_PP_TXFILTER_1:
        case RADEON_EMIT_PP_TXFILTER_2:
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                    &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
                        DRM_ERROR("Invalid R100 texture offset\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
 
@@ -143,11 +143,11 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
                        int i;
                        for (i = 0; i < 5; i++) {
                                if (radeon_check_and_fixup_offset(dev_priv,
-                                                                 filp_priv,
+                                                                 file_priv,
                                                                  &data[i])) {
                                        DRM_ERROR
                                            ("Invalid R200 cubic texture offset\n");
-                                       return DRM_ERR(EINVAL);
+                                       return -EINVAL;
                                }
                        }
                        break;
@@ -159,11 +159,11 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
                        int i;
                        for (i = 0; i < 5; i++) {
                                if (radeon_check_and_fixup_offset(dev_priv,
-                                                                 filp_priv,
+                                                                 file_priv,
                                                                  &data[i])) {
                                        DRM_ERROR
                                            ("Invalid R100 cubic texture offset\n");
-                                       return DRM_ERR(EINVAL);
+                                       return -EINVAL;
                                }
                        }
                }
@@ -256,7 +256,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 
        default:
                DRM_ERROR("Unknown state packet ID %d\n", id);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
@@ -264,7 +264,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 
 static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                                                     dev_priv,
-                                                    drm_file_t *filp_priv,
+                                                    struct drm_file *file_priv,
                                                     drm_radeon_kcmd_buffer_t *
                                                     cmdbuf,
                                                     unsigned int *cmdsz)
@@ -277,12 +277,12 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
 
        if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
                DRM_ERROR("Not a type 3 packet\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (4 * *cmdsz > cmdbuf->bufsz) {
                DRM_ERROR("Packet size larger than size of data provided\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        switch(cmd[0] & 0xff00) {
@@ -307,7 +307,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                /* safe but r200 only */
                if (dev_priv->microcode_version != UCODE_R200) {
                        DRM_ERROR("Invalid 3d packet for r100-class chip\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
 
@@ -317,7 +317,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                if (count > 18) { /* 12 arrays max */
                        DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
                                  count);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                /* carefully check packet contents */
@@ -326,22 +326,25 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                i = 2;
                while ((k < narrays) && (i < (count + 2))) {
                        i++;            /* skip attribute field */
-                       if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+                       if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                         &cmd[i])) {
                                DRM_ERROR
                                    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
                                     k, i);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        k++;
                        i++;
                        if (k == narrays)
                                break;
                        /* have one more to process, they come in pairs */
-                       if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+                       if (radeon_check_and_fixup_offset(dev_priv,
+                                                         file_priv, &cmd[i]))
+                       {
                                DRM_ERROR
                                    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
                                     k, i);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        k++;
                        i++;
@@ -351,33 +354,33 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                        DRM_ERROR
                            ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
                              k, i, narrays, count + 1);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
 
        case RADEON_3D_RNDR_GEN_INDX_PRIM:
                if (dev_priv->microcode_version != UCODE_R100) {
                        DRM_ERROR("Invalid 3d packet for r200-class chip\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) {
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
                                DRM_ERROR("Invalid rndr_gen_indx offset\n");
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                }
                break;
 
        case RADEON_CP_INDX_BUFFER:
                if (dev_priv->microcode_version != UCODE_R200) {
                        DRM_ERROR("Invalid 3d packet for r100-class chip\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                if ((cmd[1] & 0x8000ffff) != 0x80000810) {
                        DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) {
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) {
                        DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
 
@@ -389,9 +392,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                              | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
                        offset = cmd[2] << 10;
                        if (radeon_check_and_fixup_offset
-                           (dev_priv, filp_priv, &offset)) {
+                           (dev_priv, file_priv, &offset)) {
                                DRM_ERROR("Invalid first packet offset\n");
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
                }
@@ -400,9 +403,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
                    (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
                        offset = cmd[3] << 10;
                        if (radeon_check_and_fixup_offset
-                           (dev_priv, filp_priv, &offset)) {
+                           (dev_priv, file_priv, &offset)) {
                                DRM_ERROR("Invalid second packet offset\n");
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
                }
@@ -410,7 +413,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
 
        default:
                DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
@@ -421,7 +424,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
  */
 
 static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-                                            drm_clip_rect_t * box)
+                                            struct drm_clip_rect * box)
 {
        RING_LOCALS;
 
@@ -439,7 +442,7 @@ static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
 /* Emit 1.1 state
  */
 static int radeon_emit_state(drm_radeon_private_t * dev_priv,
-                            drm_file_t * filp_priv,
+                            struct drm_file *file_priv,
                             drm_radeon_context_regs_t * ctx,
                             drm_radeon_texture_regs_t * tex,
                             unsigned int dirty)
@@ -448,16 +451,16 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv,
        DRM_DEBUG("dirty=0x%08x\n", dirty);
 
        if (dirty & RADEON_UPLOAD_CONTEXT) {
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                                                  &ctx->rb3d_depthoffset)) {
                        DRM_ERROR("Invalid depth buffer offset\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                                                  &ctx->rb3d_coloroffset)) {
                        DRM_ERROR("Invalid depth buffer offset\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                BEGIN_RING(14);
@@ -543,10 +546,10 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv,
        }
 
        if (dirty & RADEON_UPLOAD_TEX0) {
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                                                  &tex[0].pp_txoffset)) {
                        DRM_ERROR("Invalid texture offset for unit 0\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                BEGIN_RING(9);
@@ -563,10 +566,10 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv,
        }
 
        if (dirty & RADEON_UPLOAD_TEX1) {
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                                                  &tex[1].pp_txoffset)) {
                        DRM_ERROR("Invalid texture offset for unit 1\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                BEGIN_RING(9);
@@ -583,10 +586,10 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv,
        }
 
        if (dirty & RADEON_UPLOAD_TEX2) {
-               if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
                                                  &tex[2].pp_txoffset)) {
                        DRM_ERROR("Invalid texture offset for unit 2\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                BEGIN_RING(9);
@@ -608,7 +611,7 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv,
 /* Emit 1.2 state
  */
 static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
-                             drm_file_t * filp_priv,
+                             struct drm_file *file_priv,
                              drm_radeon_state_t * state)
 {
        RING_LOCALS;
@@ -621,7 +624,7 @@ static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
                ADVANCE_RING();
        }
 
-       return radeon_emit_state(dev_priv, filp_priv, &state->context,
+       return radeon_emit_state(dev_priv, file_priv, &state->context,
                                 state->tex, state->dirty);
 }
 
@@ -844,7 +847,7 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
  * CP command dispatch functions
  */
 
-static void radeon_cp_dispatch_clear(drm_device_t * dev,
+static void radeon_cp_dispatch_clear(struct drm_device * dev,
                                     drm_radeon_clear_t * clear,
                                     drm_radeon_clear_rect_t * depth_boxes)
 {
@@ -852,7 +855,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
        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;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        unsigned int flags = clear->flags;
        u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
        int i;
@@ -1335,12 +1338,12 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
        ADVANCE_RING();
 }
 
-static void radeon_cp_dispatch_swap(drm_device_t * dev)
+static void radeon_cp_dispatch_swap(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
        int nbox = sarea_priv->nbox;
-       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
        int i;
        RING_LOCALS;
        DRM_DEBUG("\n");
@@ -1412,10 +1415,10 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev)
        ADVANCE_RING();
 }
 
-static void radeon_cp_dispatch_flip(drm_device_t * dev)
+static void radeon_cp_dispatch_flip(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
+       struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
        int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
            ? dev_priv->front_offset : dev_priv->back_offset;
        RING_LOCALS;
@@ -1491,8 +1494,8 @@ typedef struct {
        unsigned int vc_format;
 } drm_radeon_tcl_prim_t;
 
-static void radeon_cp_dispatch_vertex(drm_device_t * dev,
-                                     drm_buf_t * buf,
+static void radeon_cp_dispatch_vertex(struct drm_device * dev,
+                                     struct drm_buf * buf,
                                      drm_radeon_tcl_prim_t * prim)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1537,7 +1540,7 @@ static void radeon_cp_dispatch_vertex(drm_device_t * dev,
        } while (i < nbox);
 }
 
-static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -1554,8 +1557,8 @@ static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
        buf->used = 0;
 }
 
-static void radeon_cp_dispatch_indirect(drm_device_t * dev,
-                                       drm_buf_t * buf, int start, int end)
+static void radeon_cp_dispatch_indirect(struct drm_device * dev,
+                                       struct drm_buf * buf, int start, int end)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -1588,8 +1591,8 @@ static void radeon_cp_dispatch_indirect(drm_device_t * dev,
        }
 }
 
-static void radeon_cp_dispatch_indices(drm_device_t * dev,
-                                      drm_buf_t * elt_buf,
+static void radeon_cp_dispatch_indices(struct drm_device * dev,
+                                      struct drm_buf * elt_buf,
                                       drm_radeon_tcl_prim_t * prim)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1646,14 +1649,13 @@ static void radeon_cp_dispatch_indices(drm_device_t * dev,
 
 #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
 
-static int radeon_cp_dispatch_texture(DRMFILE filp,
-                                     drm_device_t * dev,
+static int radeon_cp_dispatch_texture(struct drm_device * dev,
+                                     struct drm_file *file_priv,
                                      drm_radeon_texture_t * tex,
                                      drm_radeon_tex_image_t * image)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_file_t *filp_priv;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        u32 format;
        u32 *buffer;
        const u8 __user *data;
@@ -1664,11 +1666,9 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
        u32 offset;
        RING_LOCALS;
 
-       DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
-
-       if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) {
+       if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) {
                DRM_ERROR("Invalid destination offset\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
@@ -1711,11 +1711,11 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                break;
        default:
                DRM_ERROR("invalid texture format %d\n", tex->format);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        spitch = blit_width >> 6;
        if (spitch == 0 && image->height > 1)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        texpitch = tex->pitch;
        if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
@@ -1760,8 +1760,8 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                if (!buf) {
                        DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
                        if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
-                               return DRM_ERR(EFAULT);
-                       return DRM_ERR(EAGAIN);
+                               return -EFAULT;
+                       return -EAGAIN;
                }
 
                /* Dispatch the indirect buffer.
@@ -1774,7 +1774,7 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
        do { \
                if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
                        DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
-                       return DRM_ERR(EFAULT); \
+                       return -EFAULT; \
                } \
        } while(0)
 
@@ -1841,7 +1841,7 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                }
 
 #undef RADEON_COPY_MT
-               buf->filp = filp;
+               buf->file_priv = file_priv;
                buf->used = size;
                offset = dev_priv->gart_buffers_offset + buf->offset;
                BEGIN_RING(9);
@@ -1861,6 +1861,7 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
                OUT_RING((image->width << 16) | height);
                RADEON_WAIT_UNTIL_2D_IDLE();
                ADVANCE_RING();
+               COMMIT_RING();
 
                radeon_cp_discard_buffer(dev, buf);
 
@@ -1878,10 +1879,12 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
        RADEON_FLUSH_CACHE();
        RADEON_WAIT_UNTIL_2D_IDLE();
        ADVANCE_RING();
+       COMMIT_RING();
+
        return 0;
 }
 
-static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        int i;
@@ -1929,7 +1932,8 @@ static void radeon_apply_surface_regs(int surf_index,
  * not always be available.
  */
 static int alloc_surface(drm_radeon_surface_alloc_t *new,
-                        drm_radeon_private_t *dev_priv, DRMFILE filp)
+                        drm_radeon_private_t *dev_priv,
+                        struct drm_file *file_priv)
 {
        struct radeon_virt_surface *s;
        int i;
@@ -1959,7 +1963,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new,
 
        /* find a virtual surface */
        for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
-               if (dev_priv->virt_surfaces[i].filp == 0)
+               if (dev_priv->virt_surfaces[i].file_priv == 0)
                        break;
        if (i == 2 * RADEON_MAX_SURFACES) {
                return -1;
@@ -1977,7 +1981,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new,
                        s->lower = new_lower;
                        s->upper = new_upper;
                        s->flags = new->flags;
-                       s->filp = filp;
+                       s->file_priv = file_priv;
                        dev_priv->surfaces[i].refcount++;
                        dev_priv->surfaces[i].lower = s->lower;
                        radeon_apply_surface_regs(s->surface_index, dev_priv);
@@ -1993,7 +1997,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new,
                        s->lower = new_lower;
                        s->upper = new_upper;
                        s->flags = new->flags;
-                       s->filp = filp;
+                       s->file_priv = file_priv;
                        dev_priv->surfaces[i].refcount++;
                        dev_priv->surfaces[i].upper = s->upper;
                        radeon_apply_surface_regs(s->surface_index, dev_priv);
@@ -2009,7 +2013,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new,
                        s->lower = new_lower;
                        s->upper = new_upper;
                        s->flags = new->flags;
-                       s->filp = filp;
+                       s->file_priv = file_priv;
                        dev_priv->surfaces[i].refcount = 1;
                        dev_priv->surfaces[i].lower = s->lower;
                        dev_priv->surfaces[i].upper = s->upper;
@@ -2023,7 +2027,8 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new,
        return -1;
 }
 
-static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
+static int free_surface(struct drm_file *file_priv,
+                       drm_radeon_private_t * dev_priv,
                        int lower)
 {
        struct radeon_virt_surface *s;
@@ -2031,8 +2036,9 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
        /* find the virtual surface */
        for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
                s = &(dev_priv->virt_surfaces[i]);
-               if (s->filp) {
-                       if ((lower == s->lower) && (filp == s->filp)) {
+               if (s->file_priv) {
+                       if ((lower == s->lower) && (file_priv == s->file_priv))
+                       {
                                if (dev_priv->surfaces[s->surface_index].
                                    lower == s->lower)
                                        dev_priv->surfaces[s->surface_index].
@@ -2048,7 +2054,7 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
                                    refcount == 0)
                                        dev_priv->surfaces[s->surface_index].
                                            flags = 0;
-                               s->filp = NULL;
+                               s->file_priv = NULL;
                                radeon_apply_surface_regs(s->surface_index,
                                                          dev_priv);
                                return 0;
@@ -2058,13 +2064,13 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
        return 1;
 }
 
-static void radeon_surfaces_release(DRMFILE filp,
+static void radeon_surfaces_release(struct drm_file *file_priv,
                                    drm_radeon_private_t * dev_priv)
 {
        int i;
        for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
-               if (dev_priv->virt_surfaces[i].filp == filp)
-                       free_surface(filp, dev_priv,
+               if (dev_priv->virt_surfaces[i].file_priv == file_priv)
+                       free_surface(file_priv, dev_priv,
                                     dev_priv->virt_surfaces[i].lower);
        }
 }
@@ -2072,71 +2078,58 @@ static void radeon_surfaces_release(DRMFILE filp,
 /* ================================================================
  * IOCTL functions
  */
-static int radeon_surface_alloc(DRM_IOCTL_ARGS)
+static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_surface_alloc_t alloc;
+       drm_radeon_surface_alloc_t *alloc = data;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(alloc,
-                                (drm_radeon_surface_alloc_t __user *) data,
-                                sizeof(alloc));
-
-       if (alloc_surface(&alloc, dev_priv, filp) == -1)
-               return DRM_ERR(EINVAL);
+       if (alloc_surface(alloc, dev_priv, file_priv) == -1)
+               return -EINVAL;
        else
                return 0;
 }
 
-static int radeon_surface_free(DRM_IOCTL_ARGS)
+static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_surface_free_t memfree;
+       drm_radeon_surface_free_t *memfree = data;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data,
-                                sizeof(memfree));
-
-       if (free_surface(filp, dev_priv, memfree.address))
-               return DRM_ERR(EINVAL);
+       if (free_surface(file_priv, dev_priv, memfree->address))
+               return -EINVAL;
        else
                return 0;
 }
 
-static int radeon_cp_clear(DRM_IOCTL_ARGS)
+static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_clear_t clear;
+       drm_radeon_clear_t *clear = data;
        drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data,
-                                sizeof(clear));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
        if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-       if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes,
+       if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes,
                               sarea_priv->nbox * sizeof(depth_boxes[0])))
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
-       radeon_cp_dispatch_clear(dev, &clear, depth_boxes);
+       radeon_cp_dispatch_clear(dev, clear, depth_boxes);
 
        COMMIT_RING();
        return 0;
@@ -2144,7 +2137,7 @@ static int radeon_cp_clear(DRM_IOCTL_ARGS)
 
 /* Not sure why this isn't set all the time:
  */
-static int radeon_do_init_pageflip(drm_device_t * dev)
+static int radeon_do_init_pageflip(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -2172,13 +2165,12 @@ static int radeon_do_init_pageflip(drm_device_t * dev)
 /* Swapping and flipping are different operations, need different ioctls.
  * They can & should be intermixed to support multiple 3d windows.
  */
-static int radeon_cp_flip(DRM_IOCTL_ARGS)
+static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
@@ -2191,14 +2183,13 @@ static int radeon_cp_flip(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int radeon_cp_swap(DRM_IOCTL_ARGS)
+static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
@@ -2212,71 +2203,64 @@ static int radeon_cp_swap(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int radeon_cp_vertex(DRM_IOCTL_ARGS)
+static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_file_t *filp_priv;
        drm_radeon_sarea_t *sarea_priv;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
-       drm_radeon_vertex_t vertex;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_vertex_t *vertex = data;
        drm_radeon_tcl_prim_t prim;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        sarea_priv = dev_priv->sarea_priv;
 
-       DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
-                                sizeof(vertex));
-
        DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
-                 DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
+                 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
 
-       if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+       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 DRM_ERR(EINVAL);
+                         vertex->idx, dma->buf_count - 1);
+               return -EINVAL;
        }
-       if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
-               DRM_ERROR("buffer prim %d\n", vertex.prim);
-               return DRM_ERR(EINVAL);
+       if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+               DRM_ERROR("buffer prim %d\n", vertex->prim);
+               return -EINVAL;
        }
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
        VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-       buf = dma->buflist[vertex.idx];
+       buf = dma->buflist[vertex->idx];
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
        if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", vertex.idx);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
+               return -EINVAL;
        }
 
        /* Build up a prim_t record:
         */
-       if (vertex.count) {
-               buf->used = vertex.count;       /* not used? */
+       if (vertex->count) {
+               buf->used = vertex->count;      /* not used? */
 
                if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
-                       if (radeon_emit_state(dev_priv, filp_priv,
+                       if (radeon_emit_state(dev_priv, file_priv,
                                              &sarea_priv->context_state,
                                              sarea_priv->tex_state,
                                              sarea_priv->dirty)) {
                                DRM_ERROR("radeon_emit_state failed\n");
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
 
                        sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
@@ -2286,15 +2270,15 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS)
                }
 
                prim.start = 0;
-               prim.finish = vertex.count;     /* unused */
-               prim.prim = vertex.prim;
-               prim.numverts = vertex.count;
+               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);
        }
 
-       if (vertex.discard) {
+       if (vertex->discard) {
                radeon_cp_discard_buffer(dev, buf);
        }
 
@@ -2302,80 +2286,74 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int radeon_cp_indices(DRM_IOCTL_ARGS)
+static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_file_t *filp_priv;
        drm_radeon_sarea_t *sarea_priv;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
-       drm_radeon_indices_t elts;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_indices_t *elts = data;
        drm_radeon_tcl_prim_t prim;
        int count;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        sarea_priv = dev_priv->sarea_priv;
 
-       DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
-                                sizeof(elts));
-
        DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
-                 DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard);
+                 DRM_CURRENTPID, elts->idx, elts->start, elts->end,
+                 elts->discard);
 
-       if (elts.idx < 0 || elts.idx >= dma->buf_count) {
+       if (elts->idx < 0 || elts->idx >= dma->buf_count) {
                DRM_ERROR("buffer index %d (of %d max)\n",
-                         elts.idx, dma->buf_count - 1);
-               return DRM_ERR(EINVAL);
+                         elts->idx, dma->buf_count - 1);
+               return -EINVAL;
        }
-       if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
-               DRM_ERROR("buffer prim %d\n", elts.prim);
-               return DRM_ERR(EINVAL);
+       if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+               DRM_ERROR("buffer prim %d\n", elts->prim);
+               return -EINVAL;
        }
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
        VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-       buf = dma->buflist[elts.idx];
+       buf = dma->buflist[elts->idx];
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
        if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", elts.idx);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("sending pending buffer %d\n", elts->idx);
+               return -EINVAL;
        }
 
-       count = (elts.end - elts.start) / sizeof(u16);
-       elts.start -= RADEON_INDEX_PRIM_OFFSET;
+       count = (elts->end - elts->start) / sizeof(u16);
+       elts->start -= RADEON_INDEX_PRIM_OFFSET;
 
-       if (elts.start & 0x7) {
-               DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
-               return DRM_ERR(EINVAL);
+       if (elts->start & 0x7) {
+               DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
+               return -EINVAL;
        }
-       if (elts.start < buf->used) {
-               DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
-               return DRM_ERR(EINVAL);
+       if (elts->start < buf->used) {
+               DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
+               return -EINVAL;
        }
 
-       buf->used = elts.end;
+       buf->used = elts->end;
 
        if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
-               if (radeon_emit_state(dev_priv, filp_priv,
+               if (radeon_emit_state(dev_priv, file_priv,
                                      &sarea_priv->context_state,
                                      sarea_priv->tex_state,
                                      sarea_priv->dirty)) {
                        DRM_ERROR("radeon_emit_state failed\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
 
                sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
@@ -2386,15 +2364,15 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS)
 
        /* Build up a prim_t record:
         */
-       prim.start = elts.start;
-       prim.finish = elts.end;
-       prim.prim = elts.prim;
+       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);
-       if (elts.discard) {
+       if (elts->discard) {
                radeon_cp_discard_buffer(dev, buf);
        }
 
@@ -2402,52 +2380,43 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int radeon_cp_texture(DRM_IOCTL_ARGS)
+static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_texture_t tex;
+       drm_radeon_texture_t *tex = data;
        drm_radeon_tex_image_t image;
        int ret;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data,
-                                sizeof(tex));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (tex.image == NULL) {
+       if (tex->image == NULL) {
                DRM_ERROR("null texture image!\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (DRM_COPY_FROM_USER(&image,
-                              (drm_radeon_tex_image_t __user *) tex.image,
+                              (drm_radeon_tex_image_t __user *) tex->image,
                               sizeof(image)))
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
        VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-       ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image);
+       ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
 
-       COMMIT_RING();
        return ret;
 }
 
-static int radeon_cp_stipple(DRM_IOCTL_ARGS)
+static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_stipple_t stipple;
+       drm_radeon_stipple_t *stipple = data;
        u32 mask[32];
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data,
-                                sizeof(stipple));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
-               return DRM_ERR(EFAULT);
+       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+               return -EFAULT;
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
 
@@ -2457,57 +2426,53 @@ static int radeon_cp_stipple(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int radeon_cp_indirect(DRM_IOCTL_ARGS)
+static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
-       drm_radeon_indirect_t indirect;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_indirect_t *indirect = data;
        RING_LOCALS;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(indirect,
-                                (drm_radeon_indirect_t __user *) data,
-                                sizeof(indirect));
-
        DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
-                 indirect.idx, indirect.start, indirect.end, indirect.discard);
+                 indirect->idx, indirect->start, indirect->end,
+                 indirect->discard);
 
-       if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
+       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 DRM_ERR(EINVAL);
+                         indirect->idx, dma->buf_count - 1);
+               return -EINVAL;
        }
 
-       buf = dma->buflist[indirect.idx];
+       buf = dma->buflist[indirect->idx];
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
        if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", indirect.idx);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("sending pending buffer %d\n", indirect->idx);
+               return -EINVAL;
        }
 
-       if (indirect.start < buf->used) {
+       if (indirect->start < buf->used) {
                DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
-                         indirect.start, buf->used);
-               return DRM_ERR(EINVAL);
+                         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->used = indirect->end;
 
        /* Wait for the 3D stream to idle before the indirect buffer
         * containing 2D acceleration commands is processed.
@@ -2522,8 +2487,8 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS)
         * X server.  This is insecure and is thus only available to
         * privileged clients.
         */
-       radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end);
-       if (indirect.discard) {
+       radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
+       if (indirect->discard) {
                radeon_cp_discard_buffer(dev, buf);
        }
 
@@ -2531,78 +2496,71 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
+static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_file_t *filp_priv;
        drm_radeon_sarea_t *sarea_priv;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
-       drm_radeon_vertex2_t vertex;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_vertex2_t *vertex = data;
        int i;
        unsigned char laststate;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        sarea_priv = dev_priv->sarea_priv;
 
-       DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
-                                sizeof(vertex));
-
        DRM_DEBUG("pid=%d index=%d discard=%d\n",
-                 DRM_CURRENTPID, vertex.idx, vertex.discard);
+                 DRM_CURRENTPID, vertex->idx, vertex->discard);
 
-       if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+       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 DRM_ERR(EINVAL);
+                         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];
+       buf = dma->buflist[vertex->idx];
 
-       if (buf->filp != filp) {
+       if (buf->file_priv != file_priv) {
                DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->filp);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
        }
 
        if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", vertex.idx);
-               return DRM_ERR(EINVAL);
+               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
+               return -EINVAL;
        }
 
        if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
-       for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) {
+       for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) {
                drm_radeon_prim_t prim;
                drm_radeon_tcl_prim_t tclprim;
 
-               if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim)))
-                       return DRM_ERR(EFAULT);
+               if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim)))
+                       return -EFAULT;
 
                if (prim.stateidx != laststate) {
                        drm_radeon_state_t state;
 
                        if (DRM_COPY_FROM_USER(&state,
-                                              &vertex.state[prim.stateidx],
+                                              &vertex->state[prim.stateidx],
                                               sizeof(state)))
-                               return DRM_ERR(EFAULT);
+                               return -EFAULT;
 
-                       if (radeon_emit_state2(dev_priv, filp_priv, &state)) {
+                       if (radeon_emit_state2(dev_priv, file_priv, &state)) {
                                DRM_ERROR("radeon_emit_state2 failed\n");
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
 
                        laststate = prim.stateidx;
@@ -2629,7 +2587,7 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
                        sarea_priv->nbox = 0;
        }
 
-       if (vertex.discard) {
+       if (vertex->discard) {
                radeon_cp_discard_buffer(dev, buf);
        }
 
@@ -2638,7 +2596,7 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
 }
 
 static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
-                              drm_file_t * filp_priv,
+                              struct drm_file *file_priv,
                               drm_radeon_cmd_header_t header,
                               drm_radeon_kcmd_buffer_t *cmdbuf)
 {
@@ -2648,19 +2606,19 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
        RING_LOCALS;
 
        if (id >= RADEON_MAX_STATE_PACKETS)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        sz = packet[id].len;
        reg = packet[id].start;
 
        if (sz * sizeof(int) > cmdbuf->bufsz) {
                DRM_ERROR("Packet size provided larger than data provided\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) {
+       if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) {
                DRM_ERROR("Packet verification failed\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        BEGIN_RING(sz + 1);
@@ -2748,7 +2706,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
        if (!sz)
                return 0;
        if (sz * 4 > cmdbuf->bufsz)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
        BEGIN_RING(5 + sz);
        OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
@@ -2763,8 +2721,8 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
        return 0;
 }
 
-static int radeon_emit_packet3(drm_device_t * dev,
-                              drm_file_t * filp_priv,
+static int radeon_emit_packet3(struct drm_device * dev,
+                              struct drm_file *file_priv,
                               drm_radeon_kcmd_buffer_t *cmdbuf)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2774,7 +2732,7 @@ static int radeon_emit_packet3(drm_device_t * dev,
 
        DRM_DEBUG("\n");
 
-       if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
+       if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
                                                  cmdbuf, &cmdsz))) {
                DRM_ERROR("Packet verification failed\n");
                return ret;
@@ -2789,22 +2747,22 @@ static int radeon_emit_packet3(drm_device_t * dev,
        return 0;
 }
 
-static int radeon_emit_packet3_cliprect(drm_device_t *dev,
-                                       drm_file_t *filp_priv,
+static int radeon_emit_packet3_cliprect(struct drm_device *dev,
+                                       struct drm_file *file_priv,
                                        drm_radeon_kcmd_buffer_t *cmdbuf,
                                        int orig_nbox)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_clip_rect_t box;
+       struct drm_clip_rect box;
        unsigned int cmdsz;
        int ret;
-       drm_clip_rect_t __user *boxes = cmdbuf->boxes;
+       struct drm_clip_rect __user *boxes = cmdbuf->boxes;
        int i = 0;
        RING_LOCALS;
 
        DRM_DEBUG("\n");
 
-       if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
+       if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
                                                  cmdbuf, &cmdsz))) {
                DRM_ERROR("Packet verification failed\n");
                return ret;
@@ -2816,7 +2774,7 @@ static int radeon_emit_packet3_cliprect(drm_device_t *dev,
        do {
                if (i < cmdbuf->nbox) {
                        if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
-                               return DRM_ERR(EFAULT);
+                               return -EFAULT;
                        /* FIXME The second and subsequent times round
                         * this loop, send a WAIT_UNTIL_3D_IDLE before
                         * calling emit_clip_rect(). This fixes a
@@ -2851,7 +2809,7 @@ static int radeon_emit_packet3_cliprect(drm_device_t *dev,
        return 0;
 }
 
-static int radeon_emit_wait(drm_device_t * dev, int flags)
+static int radeon_emit_wait(struct drm_device * dev, int flags)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
@@ -2874,67 +2832,59 @@ static int radeon_emit_wait(drm_device_t * dev, int flags)
                ADVANCE_RING();
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        return 0;
 }
 
-static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
+static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_file_t *filp_priv;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf = NULL;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf = NULL;
        int idx;
-       drm_radeon_kcmd_buffer_t cmdbuf;
+       drm_radeon_kcmd_buffer_t *cmdbuf = data;
        drm_radeon_cmd_header_t header;
        int orig_nbox, orig_bufsz;
        char *kbuf = NULL;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(cmdbuf,
-                                (drm_radeon_kcmd_buffer_t __user *) data,
-                                sizeof(cmdbuf));
-
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
        VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-       if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) {
-               return DRM_ERR(EINVAL);
+       if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) {
+               return -EINVAL;
        }
 
        /* Allocate an in-kernel area and copy in the cmdbuf.  Do this to avoid
         * races between checking values and using those values in other code,
         * and simply to avoid a lot of function calls to copy in data.
         */
-       orig_bufsz = cmdbuf.bufsz;
+       orig_bufsz = cmdbuf->bufsz;
        if (orig_bufsz != 0) {
-               kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
+               kbuf = drm_alloc(cmdbuf->bufsz, DRM_MEM_DRIVER);
                if (kbuf == NULL)
-                       return DRM_ERR(ENOMEM);
-               if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf,
-                                      cmdbuf.bufsz)) {
+                       return -ENOMEM;
+               if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
+                                      cmdbuf->bufsz)) {
                        drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                }
-               cmdbuf.buf = kbuf;
+               cmdbuf->buf = kbuf;
        }
 
-       orig_nbox = cmdbuf.nbox;
+       orig_nbox = cmdbuf->nbox;
 
        if (dev_priv->microcode_version == UCODE_R300) {
                int temp;
-               temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
+               temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
 
                if (orig_bufsz != 0)
                        drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
@@ -2943,17 +2893,17 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
        }
 
        /* microcode_version != r300 */
-       while (cmdbuf.bufsz >= sizeof(header)) {
+       while (cmdbuf->bufsz >= sizeof(header)) {
 
-               header.i = *(int *)cmdbuf.buf;
-               cmdbuf.buf += sizeof(header);
-               cmdbuf.bufsz -= sizeof(header);
+               header.i = *(int *)cmdbuf->buf;
+               cmdbuf->buf += sizeof(header);
+               cmdbuf->bufsz -= sizeof(header);
 
                switch (header.header.cmd_type) {
                case RADEON_CMD_PACKET:
                        DRM_DEBUG("RADEON_CMD_PACKET\n");
                        if (radeon_emit_packets
-                           (dev_priv, filp_priv, header, &cmdbuf)) {
+                           (dev_priv, file_priv, header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_packets failed\n");
                                goto err;
                        }
@@ -2961,7 +2911,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
 
                case RADEON_CMD_SCALARS:
                        DRM_DEBUG("RADEON_CMD_SCALARS\n");
-                       if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) {
+                       if (radeon_emit_scalars(dev_priv, header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_scalars failed\n");
                                goto err;
                        }
@@ -2969,7 +2919,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
 
                case RADEON_CMD_VECTORS:
                        DRM_DEBUG("RADEON_CMD_VECTORS\n");
-                       if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) {
+                       if (radeon_emit_vectors(dev_priv, header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_vectors failed\n");
                                goto err;
                        }
@@ -2985,9 +2935,10 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
                        }
 
                        buf = dma->buflist[idx];
-                       if (buf->filp != filp || buf->pending) {
+                       if (buf->file_priv != file_priv || buf->pending) {
                                DRM_ERROR("bad buffer %p %p %d\n",
-                                         buf->filp, filp, buf->pending);
+                                         buf->file_priv, file_priv,
+                                         buf->pending);
                                goto err;
                        }
 
@@ -2996,7 +2947,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
 
                case RADEON_CMD_PACKET3:
                        DRM_DEBUG("RADEON_CMD_PACKET3\n");
-                       if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) {
+                       if (radeon_emit_packet3(dev, file_priv, cmdbuf)) {
                                DRM_ERROR("radeon_emit_packet3 failed\n");
                                goto err;
                        }
@@ -3005,7 +2956,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
                case RADEON_CMD_PACKET3_CLIP:
                        DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
                        if (radeon_emit_packet3_cliprect
-                           (dev, filp_priv, &cmdbuf, orig_nbox)) {
+                           (dev, file_priv, cmdbuf, orig_nbox)) {
                                DRM_ERROR("radeon_emit_packet3_clip failed\n");
                                goto err;
                        }
@@ -3013,7 +2964,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
 
                case RADEON_CMD_SCALARS2:
                        DRM_DEBUG("RADEON_CMD_SCALARS2\n");
-                       if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) {
+                       if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_scalars2 failed\n");
                                goto err;
                        }
@@ -3028,7 +2979,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
                        break;
                case RADEON_CMD_VECLINEAR:
                        DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
-                       if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) {
+                       if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) {
                                DRM_ERROR("radeon_emit_veclinear failed\n");
                                goto err;
                        }
@@ -3037,7 +2988,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
                default:
                        DRM_ERROR("bad cmd_type %d at %p\n",
                                  header.header.cmd_type,
-                                 cmdbuf.buf - sizeof(header));
+                                 cmdbuf->buf - sizeof(header));
                        goto err;
                }
        }
@@ -3052,27 +3003,23 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
       err:
        if (orig_bufsz != 0)
                drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
-static int radeon_cp_getparam(DRM_IOCTL_ARGS)
+static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_getparam_t param;
+       drm_radeon_getparam_t *param = data;
        int value;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
-                                sizeof(param));
-
        DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
 
-       switch (param.param) {
+       switch (param->param) {
        case RADEON_PARAM_GART_BUFFER_OFFSET:
                value = dev_priv->gart_buffers_offset;
                break;
@@ -3119,7 +3066,7 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
                break;
        case RADEON_PARAM_SCRATCH_OFFSET:
                if (!dev_priv->writeback_works)
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                value = RADEON_SCRATCH_REG_OFFSET;
                break;
        
@@ -3135,48 +3082,42 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
                value = radeon_vblank_crtc_get(dev);
                break;
        default:
-               DRM_DEBUG( "Invalid parameter %d\n", param.param );
-               return DRM_ERR(EINVAL);
+               DRM_DEBUG( "Invalid parameter %d\n", param->param );
+               return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        return 0;
 }
 
-static int radeon_cp_setparam(DRM_IOCTL_ARGS)
+static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_file_t *filp_priv;
-       drm_radeon_setparam_t sp;
+       drm_radeon_setparam_t *sp = data;
        struct drm_radeon_driver_file_fields *radeon_priv;
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
-                                sizeof(sp));
-
-       switch (sp.param) {
+       switch (sp->param) {
        case RADEON_SETPARAM_FB_LOCATION:
-               radeon_priv = filp_priv->driver_priv;
-               radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+               radeon_priv = file_priv->driver_priv;
+               radeon_priv->radeon_fb_delta = dev_priv->fb_location -
+                   sp->value;
                break;
        case RADEON_SETPARAM_SWITCH_TILING:
-               if (sp.value == 0) {
+               if (sp->value == 0) {
                        DRM_DEBUG("color tiling disabled\n");
                        dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
                        dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
                        dev_priv->sarea_priv->tiling_enabled = 0;
-               } else if (sp.value == 1) {
+               } else if (sp->value == 1) {
                        DRM_DEBUG("color tiling enabled\n");
                        dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
                        dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
@@ -3184,23 +3125,23 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
                }
                break;
        case RADEON_SETPARAM_PCIGART_LOCATION:
-               dev_priv->pcigart_offset = sp.value;
+               dev_priv->pcigart_offset = sp->value;
                dev_priv->pcigart_offset_set = 1;
                break;
        case RADEON_SETPARAM_NEW_MEMMAP:
-               dev_priv->new_memmap = sp.value;
+               dev_priv->new_memmap = sp->value;
                break;
        case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
-               dev_priv->gart_info.table_size = sp.value;
+               dev_priv->gart_info.table_size = sp->value;
                if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
                        dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
                break;
        case RADEON_SETPARAM_VBLANK_CRTC:
-               return radeon_vblank_crtc_set(dev, sp.value);
+               return radeon_vblank_crtc_set(dev, sp->value);
                break;
        default:
-               DRM_DEBUG("Invalid parameter %d\n", sp.param);
-               return DRM_ERR(EINVAL);
+               DRM_DEBUG("Invalid parameter %d\n", sp->param);
+               return -EINVAL;
        }
 
        return 0;
@@ -3213,18 +3154,19 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
  *
  * DRM infrastructure takes care of reclaiming dma buffers.
  */
-void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
+void radeon_driver_preclose(struct drm_device * dev,
+                           struct drm_file *file_priv)
 {
        if (dev->dev_private) {
                drm_radeon_private_t *dev_priv = dev->dev_private;
                dev_priv->page_flipping = 0;
-               radeon_mem_release(filp, dev_priv->gart_heap);
-               radeon_mem_release(filp, dev_priv->fb_heap);
-               radeon_surfaces_release(filp, dev_priv);
+               radeon_mem_release(file_priv, dev_priv->gart_heap);
+               radeon_mem_release(file_priv, dev_priv->fb_heap);
+               radeon_surfaces_release(file_priv, dev_priv);
        }
 }
 
-void radeon_driver_lastclose(drm_device_t * dev)
+void radeon_driver_lastclose(struct drm_device * dev)
 {
        if (dev->dev_private) {
                drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3237,7 +3179,7 @@ void radeon_driver_lastclose(drm_device_t * dev)
        radeon_do_release(dev);
 }
 
-int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
+int radeon_driver_open(struct drm_device * dev, struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
        struct drm_radeon_driver_file_fields *radeon_priv;
@@ -3250,7 +3192,7 @@ int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
        if (!radeon_priv)
                return -ENOMEM;
 
-       filp_priv->driver_priv = radeon_priv;
+       file_priv->driver_priv = radeon_priv;
 
        if (dev_priv)
                radeon_priv->radeon_fb_delta = dev_priv->fb_location;
@@ -3259,42 +3201,42 @@ int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
        return 0;
 }
 
-void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
+void radeon_driver_postclose(struct drm_device * dev, struct drm_file *file_priv)
 {
        struct drm_radeon_driver_file_fields *radeon_priv =
-           filp_priv->driver_priv;
+           file_priv->driver_priv;
 
        drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
 }
 
-drm_ioctl_desc_t radeon_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH}
+struct drm_ioctl_desc radeon_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH)
 };
 
 int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
index 9a3ae1f..32ac5ac 100644 (file)
@@ -32,7 +32,7 @@
 #define SAVAGE_EVENT_USEC_TIMEOUT      5000000 /* 5s */
 #define SAVAGE_FREELIST_DEBUG          0
 
-static int savage_do_cleanup_bci(drm_device_t *dev);
+static int savage_do_cleanup_bci(struct drm_device *dev);
 
 static int
 savage_bci_wait_fifo_shadow(drm_savage_private_t *dev_priv, unsigned int n)
@@ -60,7 +60,7 @@ savage_bci_wait_fifo_shadow(drm_savage_private_t *dev_priv, unsigned int n)
        DRM_ERROR("failed!\n");
        DRM_INFO("   status=0x%08x, threshold=0x%08x\n", status, threshold);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int
@@ -81,7 +81,7 @@ savage_bci_wait_fifo_s3d(drm_savage_private_t *dev_priv, unsigned int n)
        DRM_ERROR("failed!\n");
        DRM_INFO("   status=0x%08x\n", status);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int
@@ -102,7 +102,7 @@ savage_bci_wait_fifo_s4(drm_savage_private_t *dev_priv, unsigned int n)
        DRM_ERROR("failed!\n");
        DRM_INFO("   status=0x%08x\n", status);
 #endif
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 /*
@@ -136,7 +136,7 @@ savage_bci_wait_event_shadow(drm_savage_private_t *dev_priv, uint16_t e)
        DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
 #endif
 
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 static int
@@ -158,7 +158,7 @@ savage_bci_wait_event_reg(drm_savage_private_t *dev_priv, uint16_t e)
        DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
 #endif
 
-       return DRM_ERR(EBUSY);
+       return -EBUSY;
 }
 
 uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
@@ -203,11 +203,11 @@ uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
 /*
  * Freelist management
  */
-static int savage_freelist_init(drm_device_t *dev)
+static int savage_freelist_init(struct drm_device *dev)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
        drm_savage_buf_priv_t *entry;
        int i;
        DRM_DEBUG("count=%d\n", dma->buf_count);
@@ -236,7 +236,7 @@ static int savage_freelist_init(drm_device_t *dev)
        return 0;
 }
 
-static drm_buf_t *savage_freelist_get(drm_device_t *dev)
+static struct drm_buf *savage_freelist_get(struct drm_device *dev)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
        drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
@@ -269,7 +269,7 @@ static drm_buf_t *savage_freelist_get(drm_device_t *dev)
        return NULL;
 }
 
-void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf)
+void savage_freelist_put(struct drm_device *dev, struct drm_buf *buf)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
        drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
@@ -301,7 +301,7 @@ static int savage_dma_init(drm_savage_private_t *dev_priv)
        dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
                                        dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
        if (dev_priv->dma_pages == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
                SET_AGE(&dev_priv->dma_pages[i].age, 0, 0);
@@ -535,13 +535,13 @@ static void savage_fake_dma_flush(drm_savage_private_t *dev_priv)
        dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
 }
 
-int savage_driver_load(drm_device_t *dev, unsigned long chipset)
+int savage_driver_load(struct drm_device *dev, unsigned long chipset)
 {
        drm_savage_private_t *dev_priv;
 
        dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
        if (dev_priv == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        memset(dev_priv, 0, sizeof(drm_savage_private_t));
        dev->dev_private = (void *)dev_priv;
@@ -557,7 +557,7 @@ int savage_driver_load(drm_device_t *dev, unsigned long chipset)
  * in drm_addmap. Therefore we add them manually before the maps are
  * initialized, and tear them down on last close.
  */
-int savage_driver_firstopen(drm_device_t *dev)
+int savage_driver_firstopen(struct drm_device *dev)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
        unsigned long mmio_base, fb_base, fb_size, aperture_base;
@@ -654,7 +654,7 @@ int savage_driver_firstopen(drm_device_t *dev)
 /*
  * Delete MTRRs and free device-private data.
  */
-void savage_driver_lastclose(drm_device_t *dev)
+void savage_driver_lastclose(struct drm_device *dev)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
        int i;
@@ -666,7 +666,7 @@ void savage_driver_lastclose(drm_device_t *dev)
                                     dev_priv->mtrr[i].size, DRM_MTRR_WC);
 }
 
-int savage_driver_unload(drm_device_t *dev)
+int savage_driver_unload(struct drm_device *dev)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -675,22 +675,22 @@ int savage_driver_unload(drm_device_t *dev)
        return 0;
 }
 
-static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
+static int savage_do_init_bci(struct drm_device *dev, drm_savage_init_t *init)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
 
        if (init->fb_bpp != 16 && init->fb_bpp != 32) {
                DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        if (init->depth_bpp != 16 && init->depth_bpp != 32) {
                DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        if (init->dma_type != SAVAGE_DMA_AGP &&
            init->dma_type != SAVAGE_DMA_PCI) {
                DRM_ERROR("invalid dma memory type %d!\n", init->dma_type);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->cob_size = init->cob_size;
@@ -714,14 +714,14 @@ static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
        if (!dev_priv->sarea) {
                DRM_ERROR("could not find sarea!\n");
                savage_do_cleanup_bci(dev);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        if (init->status_offset != 0) {
                dev_priv->status = drm_core_findmap(dev, init->status_offset);
                if (!dev_priv->status) {
                        DRM_ERROR("could not find shadow status region!\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        } else {
                dev_priv->status = NULL;
@@ -733,13 +733,13 @@ static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
                if (!dev->agp_buffer_map) {
                        DRM_ERROR("could not find DMA buffer region!\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                drm_core_ioremap(dev->agp_buffer_map, dev);
                if (!dev->agp_buffer_map) {
                        DRM_ERROR("failed to ioremap DMA buffer region!\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
        }
        if (init->agp_textures_offset) {
@@ -748,7 +748,7 @@ static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
                if (!dev_priv->agp_textures) {
                        DRM_ERROR("could not find agp texture region!\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        } else {
                dev_priv->agp_textures = NULL;
@@ -759,39 +759,39 @@ static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
                        DRM_ERROR("command DMA not supported on "
                                  "Savage3D/MX/IX.\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                if (dev->dma && dev->dma->buflist) {
                        DRM_ERROR("command and vertex DMA not supported "
                                  "at the same time.\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset);
                if (!dev_priv->cmd_dma) {
                        DRM_ERROR("could not find command DMA region!\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                if (dev_priv->dma_type == SAVAGE_DMA_AGP) {
                        if (dev_priv->cmd_dma->type != _DRM_AGP) {
                                DRM_ERROR("AGP command DMA region is not a "
                                          "_DRM_AGP map!\n");
                                savage_do_cleanup_bci(dev);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        drm_core_ioremap(dev_priv->cmd_dma, dev);
                        if (!dev_priv->cmd_dma->handle) {
                                DRM_ERROR("failed to ioremap command "
                                          "DMA region!\n");
                                savage_do_cleanup_bci(dev);
-                               return DRM_ERR(ENOMEM);
+                               return -ENOMEM;
                        }
                } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) {
                        DRM_ERROR("PCI command DMA region is not a "
                                  "_DRM_CONSISTENT map!\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        } else {
                dev_priv->cmd_dma = NULL;
@@ -808,7 +808,7 @@ static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
                if (!dev_priv->fake_dma.handle) {
                        DRM_ERROR("could not allocate faked DMA buffer!\n");
                        savage_do_cleanup_bci(dev);
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
                }
                dev_priv->cmd_dma = &dev_priv->fake_dma;
                dev_priv->dma_flush = savage_fake_dma_flush;
@@ -885,19 +885,19 @@ static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
        if (savage_freelist_init(dev) < 0) {
                DRM_ERROR("could not initialize freelist\n");
                savage_do_cleanup_bci(dev);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        if (savage_dma_init(dev_priv) <  0) {
                DRM_ERROR("could not initialize command DMA\n");
                savage_do_cleanup_bci(dev);
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        return 0;
 }
 
-static int savage_do_cleanup_bci(drm_device_t *dev)
+static int savage_do_cleanup_bci(struct drm_device *dev)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
 
@@ -927,59 +927,46 @@ static int savage_do_cleanup_bci(drm_device_t *dev)
        return 0;
 }
 
-static int savage_bci_init(DRM_IOCTL_ARGS)
+static int savage_bci_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_savage_init_t init;
+       drm_savage_init_t *init = data;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *)data,
-                                sizeof(init));
-
-       switch (init.func) {
+       switch (init->func) {
        case SAVAGE_INIT_BCI:
-               return savage_do_init_bci(dev, &init);
+               return savage_do_init_bci(dev, init);
        case SAVAGE_CLEANUP_BCI:
                return savage_do_cleanup_bci(dev);
        }
 
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 
-static int savage_bci_event_emit(DRM_IOCTL_ARGS)
+static int savage_bci_event_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_savage_event_emit_t event;
+       drm_savage_event_emit_t *event = data;
 
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *)data,
-                                sizeof(event));
+       event->count = savage_bci_emit_event(dev_priv, event->flags);
+       event->count |= dev_priv->event_wrap << 16;
 
-       event.count = savage_bci_emit_event(dev_priv, event.flags);
-       event.count |= dev_priv->event_wrap << 16;
-       DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *)data,
-                              event, sizeof(event));
        return 0;
 }
 
-static int savage_bci_event_wait(DRM_IOCTL_ARGS)
+static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_savage_event_wait_t event;
+       drm_savage_event_wait_t *event = data;
        unsigned int event_e, hw_e;
        unsigned int event_w, hw_w;
 
        DRM_DEBUG("\n");
 
-       DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *)data,
-                                sizeof(event));
-
        UPDATE_EVENT_COUNTER();
        if (dev_priv->status_ptr)
                hw_e = dev_priv->status_ptr[1] & 0xffff;
@@ -989,8 +976,8 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS)
        if (hw_e > dev_priv->event_counter)
                hw_w--; /* hardware hasn't passed the last wrap yet */
 
-       event_e = event.count & 0xffff;
-       event_w = event.count >> 16;
+       event_e = event->count & 0xffff;
+       event_w = event->count >> 16;
 
        /* Don't need to wait if
         * - event counter wrapped since the event was emitted or
@@ -1006,71 +993,68 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS)
  * DMA buffer management
  */
 
-static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
+static int savage_bci_get_buffers(struct drm_device *dev,
+                                 struct drm_file *file_priv,
+                                 struct drm_dma *d)
 {
-       drm_buf_t *buf;
+       struct drm_buf *buf;
        int i;
 
        for (i = d->granted_count; i < d->request_count; i++) {
                buf = savage_freelist_get(dev);
                if (!buf)
-                       return DRM_ERR(EAGAIN);
+                       return -EAGAIN;
 
-               buf->filp = filp;
+               buf->file_priv = file_priv;
 
                if (DRM_COPY_TO_USER(&d->request_indices[i],
                                     &buf->idx, sizeof(buf->idx)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
                if (DRM_COPY_TO_USER(&d->request_sizes[i],
                                     &buf->total, sizeof(buf->total)))
-                       return DRM_ERR(EFAULT);
+                       return -EFAULT;
 
                d->granted_count++;
        }
        return 0;
 }
 
-int savage_bci_buffers(DRM_IOCTL_ARGS)
+int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_device_dma_t *dma = dev->dma;
-       drm_dma_t d;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_dma *d = data;
        int ret = 0;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *)data, sizeof(d));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        /* Please don't send us buffers.
         */
-       if (d.send_count != 0) {
+       if (d->send_count != 0) {
                DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d.send_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
        }
 
        /* We'll send you buffers.
         */
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
                DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d.request_count, dma->buf_count);
-               return DRM_ERR(EINVAL);
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
        }
 
-       d.granted_count = 0;
+       d->granted_count = 0;
 
-       if (d.request_count) {
-               ret = savage_bci_get_buffers(filp, dev, &d);
+       if (d->request_count) {
+               ret = savage_bci_get_buffers(dev, file_priv, d);
        }
 
-       DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *)data, d, sizeof(d));
-
        return ret;
 }
 
-void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
+void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
 {
-       drm_device_dma_t *dma = dev->dma;
+       struct drm_device_dma *dma = dev->dma;
        drm_savage_private_t *dev_priv = dev->dev_private;
        int i;
 
@@ -1084,10 +1068,10 @@ void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
        /*i830_flush_queue(dev);*/
 
        for (i = 0; i < dma->buf_count; i++) {
-               drm_buf_t *buf = dma->buflist[i];
+               struct drm_buf *buf = dma->buflist[i];
                drm_savage_buf_priv_t *buf_priv = buf->dev_private;
 
-               if (buf->filp == filp && buf_priv &&
+               if (buf->file_priv == file_priv && buf_priv &&
                    buf_priv->next == NULL && buf_priv->prev == NULL) {
                        uint16_t event;
                        DRM_DEBUG("reclaimed from client\n");
@@ -1097,14 +1081,14 @@ void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
                }
        }
 
-       drm_core_reclaim_buffers(dev, filp);
+       drm_core_reclaim_buffers(dev, file_priv);
 }
 
-drm_ioctl_desc_t savage_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, DRM_AUTH},
+struct drm_ioctl_desc savage_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH),
 };
 
 int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
index 6526c9a..b960d55 100644 (file)
@@ -47,7 +47,7 @@
 typedef struct _drm_savage_sarea {
        /* LRU lists for texture memory in agp space and on the card.
         */
-       drm_tex_region_t texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS+1];
+       struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS+1];
        unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
 
        /* Mechanism to validate card state.
@@ -112,7 +112,7 @@ typedef struct drm_savage_cmdbuf {
        unsigned int vb_size;   /* size of client vertex buffer in bytes */
        unsigned int vb_stride; /* stride of vertices in 32bit words */
                                /* boxes in client's address space */
-       drm_clip_rect_t __user *box_addr;
+       struct drm_clip_rect __user *box_addr;
        unsigned int nbox;      /* number of clipping boxes */
 } drm_savage_cmdbuf_t;
 
index 88c571e..d86bac0 100644 (file)
@@ -58,7 +58,7 @@ typedef struct drm_savage_buf_priv {
        struct drm_savage_buf_priv *next;
        struct drm_savage_buf_priv *prev;
        drm_savage_age_t age;
-       drm_buf_t *buf;
+       struct drm_buf *buf;
 } drm_savage_buf_priv_t;
 
 typedef struct drm_savage_dma_page {
@@ -104,7 +104,7 @@ enum savage_family {
        S3_LAST
 };
 
-extern drm_ioctl_desc_t savage_ioctls[];
+extern struct drm_ioctl_desc savage_ioctls[];
 extern int savage_max_ioctl;
 
 #define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
@@ -192,33 +192,34 @@ typedef struct drm_savage_private {
        /* Err, there is a macro wait_event in include/linux/wait.h.
         * Avoid unwanted macro expansion. */
        void (*emit_clip_rect)(struct drm_savage_private *dev_priv,
-                              const drm_clip_rect_t *pbox);
+                              const struct drm_clip_rect *pbox);
        void (*dma_flush)(struct drm_savage_private *dev_priv);
 } drm_savage_private_t;
 
 /* ioctls */
-extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS);
-extern int savage_bci_buffers(DRM_IOCTL_ARGS);
+extern int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
 /* BCI functions */
 extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
                                      unsigned int flags);
-extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
+extern void savage_freelist_put(struct drm_device *dev, struct drm_buf *buf);
 extern void savage_dma_reset(drm_savage_private_t *dev_priv);
 extern void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page);
 extern uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv,
                                  unsigned int n);
-extern int savage_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int savage_driver_firstopen(drm_device_t *dev);
-extern void savage_driver_lastclose(drm_device_t *dev);
-extern int savage_driver_unload(drm_device_t *dev);
-extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
+extern int savage_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int savage_driver_firstopen(struct drm_device *dev);
+extern void savage_driver_lastclose(struct drm_device *dev);
+extern int savage_driver_unload(struct drm_device *dev);
+extern void savage_reclaim_buffers(struct drm_device *dev,
+                                  struct drm_file *file_priv);
 
 /* state functions */
 extern void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
-                                     const drm_clip_rect_t *pbox);
+                                     const struct drm_clip_rect *pbox);
 extern void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
-                                    const drm_clip_rect_t *pbox);
+                                    const struct drm_clip_rect *pbox);
 
 #define SAVAGE_FB_SIZE_S3      0x01000000      /*  16MB */
 #define SAVAGE_FB_SIZE_S4      0x02000000      /*  32MB */
index acc98f8..dd59334 100644 (file)
@@ -27,7 +27,7 @@
 #include "savage_drv.h"
 
 void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
-                              const drm_clip_rect_t *pbox)
+                              const struct drm_clip_rect *pbox)
 {
        uint32_t scstart = dev_priv->state.s3d.new_scstart;
        uint32_t scend   = dev_priv->state.s3d.new_scend;
@@ -53,7 +53,7 @@ void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
 }
 
 void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
-                             const drm_clip_rect_t *pbox)
+                             const struct drm_clip_rect *pbox)
 {
        uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
        uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
@@ -83,7 +83,7 @@ static int savage_verify_texaddr(drm_savage_private_t *dev_priv, int unit,
 {
        if ((addr & 6) != 2) { /* reserved bits */
                DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        if (!(addr & 1)) { /* local */
                addr &= ~7;
@@ -92,13 +92,13 @@ static int savage_verify_texaddr(drm_savage_private_t *dev_priv, int unit,
                        DRM_ERROR
                            ("bad texAddr%d %08x (local addr out of range)\n",
                             unit, addr);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        } else { /* AGP */
                if (!dev_priv->agp_textures) {
                        DRM_ERROR("bad texAddr%d %08x (AGP not available)\n",
                                  unit, addr);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                addr &= ~7;
                if (addr < dev_priv->agp_textures->offset ||
@@ -107,7 +107,7 @@ static int savage_verify_texaddr(drm_savage_private_t *dev_priv, int unit,
                        DRM_ERROR
                            ("bad texAddr%d %08x (AGP addr out of range)\n",
                             unit, addr);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
        return 0;
@@ -132,7 +132,7 @@ static int savage_verify_state_s3d(drm_savage_private_t *dev_priv,
            start+count-1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
                DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
                          start, start+count-1);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart,
@@ -164,7 +164,7 @@ static int savage_verify_state_s4(drm_savage_private_t *dev_priv,
            start+count-1 > SAVAGE_TEXBLENDCOLOR_S4) {
                DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
                          start, start+count-1);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0,
@@ -275,7 +275,7 @@ static int savage_dispatch_state(drm_savage_private_t *dev_priv,
 
 static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
                                    const drm_savage_cmd_header_t *cmd_header,
-                                   const drm_buf_t *dmabuf)
+                                   const struct drm_buf *dmabuf)
 {
        unsigned char reorder = 0;
        unsigned int prim = cmd_header->prim.prim;
@@ -287,7 +287,7 @@ static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
 
        if (!dmabuf) {
            DRM_ERROR("called without dma buffers!\n");
-           return DRM_ERR(EINVAL);
+           return -EINVAL;
        }
 
        if (!n)
@@ -301,7 +301,7 @@ static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
                if (n % 3 != 0) {
                        DRM_ERROR("wrong number of vertices %u in TRILIST\n",
                                  n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        case SAVAGE_PRIM_TRISTRIP:
@@ -310,18 +310,18 @@ static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
                        DRM_ERROR
                           ("wrong number of vertices %u in TRIFAN/STRIP\n",
                            n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        default:
                DRM_ERROR("invalid primitive type %u\n", prim);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
                if (skip != 0) {
                        DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        } else {
                unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
@@ -329,18 +329,18 @@ static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
                        (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
                if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
                        DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                if (reorder) {
                        DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
        if (start + n > dmabuf->total/32) {
                DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
                          start, start + n - 1, dmabuf->total/32);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        /* Vertex DMA doesn't work with command DMA at the same time,
@@ -438,7 +438,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv,
                if (n % 3 != 0) {
                        DRM_ERROR("wrong number of vertices %u in TRILIST\n",
                                  n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        case SAVAGE_PRIM_TRISTRIP:
@@ -447,24 +447,24 @@ static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv,
                        DRM_ERROR
                            ("wrong number of vertices %u in TRIFAN/STRIP\n",
                             n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        default:
                DRM_ERROR("invalid primitive type %u\n", prim);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
                if (skip > SAVAGE_SKIP_ALL_S3D) {
                        DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                vtx_size = 8; /* full vertex */
        } else {
                if (skip > SAVAGE_SKIP_ALL_S4) {
                        DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                vtx_size = 10; /* full vertex */
        }
@@ -476,13 +476,13 @@ static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv,
        if (vtx_size > vb_stride) {
                DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
                          vtx_size, vb_stride);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (start + n > vb_size / (vb_stride*4)) {
                DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
                          start, start + n - 1, vb_size / (vb_stride*4));
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        prim <<= 25;
@@ -534,7 +534,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv,
 static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
                                   const drm_savage_cmd_header_t *cmd_header,
                                   const uint16_t *idx,
-                                  const drm_buf_t *dmabuf)
+                                  const struct drm_buf *dmabuf)
 {
        unsigned char reorder = 0;
        unsigned int prim = cmd_header->idx.prim;
@@ -545,7 +545,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
 
        if (!dmabuf) {
            DRM_ERROR("called without dma buffers!\n");
-           return DRM_ERR(EINVAL);
+           return -EINVAL;
        }
 
        if (!n)
@@ -558,7 +558,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
        case SAVAGE_PRIM_TRILIST:
                if (n % 3 != 0) {
                        DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        case SAVAGE_PRIM_TRISTRIP:
@@ -566,18 +566,18 @@ static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
                if (n < 3) {
                        DRM_ERROR
                            ("wrong number of indices %u in TRIFAN/STRIP\n", n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        default:
                DRM_ERROR("invalid primitive type %u\n", prim);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
                if (skip != 0) {
                        DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        } else {
                unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
@@ -585,11 +585,11 @@ static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
                        (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
                if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
                        DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                if (reorder) {
                        DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
 
@@ -626,7 +626,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
                        if (idx[i] > dmabuf->total/32) {
                                DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
                                          i, idx[i], dmabuf->total/32);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                }
 
@@ -696,7 +696,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv,
        case SAVAGE_PRIM_TRILIST:
                if (n % 3 != 0) {
                        DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        case SAVAGE_PRIM_TRISTRIP:
@@ -704,24 +704,24 @@ static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv,
                if (n < 3) {
                        DRM_ERROR
                            ("wrong number of indices %u in TRIFAN/STRIP\n", n);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                break;
        default:
                DRM_ERROR("invalid primitive type %u\n", prim);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
                if (skip > SAVAGE_SKIP_ALL_S3D) {
                        DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                vtx_size = 8; /* full vertex */
        } else {
                if (skip > SAVAGE_SKIP_ALL_S4) {
                        DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
                vtx_size = 10; /* full vertex */
        }
@@ -733,7 +733,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv,
        if (vtx_size > vb_stride) {
                DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
                          vtx_size, vb_stride);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        prim <<= 25;
@@ -746,7 +746,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv,
                        if (idx[i] > vb_size / (vb_stride*4)) {
                                DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
                                          i, idx[i],  vb_size / (vb_stride*4));
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                }
 
@@ -790,7 +790,7 @@ static int savage_dispatch_clear(drm_savage_private_t *dev_priv,
                                 const drm_savage_cmd_header_t *cmd_header,
                                 const drm_savage_cmd_header_t *data,
                                 unsigned int nbox,
-                                const drm_clip_rect_t *boxes)
+                                const struct drm_clip_rect *boxes)
 {
        unsigned int flags = cmd_header->clear0.flags;
        unsigned int clear_cmd;
@@ -860,7 +860,7 @@ static int savage_dispatch_clear(drm_savage_private_t *dev_priv,
 }
 
 static int savage_dispatch_swap(drm_savage_private_t *dev_priv,
-                               unsigned int nbox, const drm_clip_rect_t *boxes)
+                               unsigned int nbox, const struct drm_clip_rect *boxes)
 {
        unsigned int swap_cmd;
        unsigned int i;
@@ -891,11 +891,11 @@ static int savage_dispatch_swap(drm_savage_private_t *dev_priv,
 static int savage_dispatch_draw(drm_savage_private_t *dev_priv,
                                const drm_savage_cmd_header_t *start,
                                const drm_savage_cmd_header_t *end,
-                               const drm_buf_t *dmabuf,
+                               const struct drm_buf *dmabuf,
                                const unsigned int *vtxbuf,
                                unsigned int vb_size, unsigned int vb_stride,
                                unsigned int nbox,
-                               const drm_clip_rect_t *boxes)
+                               const struct drm_clip_rect *boxes)
 {
        unsigned int i, j;
        int ret;
@@ -941,7 +941,7 @@ static int savage_dispatch_draw(drm_savage_private_t *dev_priv,
                                DRM_ERROR("IMPLEMENTATION ERROR: "
                                          "non-drawing-command %d\n",
                                          cmd_header.cmd.cmd);
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
 
                        if (ret != 0)
@@ -952,35 +952,31 @@ static int savage_dispatch_draw(drm_savage_private_t *dev_priv,
        return 0;
 }
 
-int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *dmabuf;
-       drm_savage_cmdbuf_t cmdbuf;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *dmabuf;
+       drm_savage_cmdbuf_t *cmdbuf = data;
        drm_savage_cmd_header_t *kcmd_addr = NULL;
        drm_savage_cmd_header_t *first_draw_cmd;
        unsigned int *kvb_addr = NULL;
-       drm_clip_rect_t *kbox_addr = NULL;
+       struct drm_clip_rect *kbox_addr = NULL;
        unsigned int i, j;
        int ret = 0;
 
        DRM_DEBUG("\n");
        
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *)data,
-                                sizeof(cmdbuf));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (dma && dma->buflist) {
-               if (cmdbuf.dma_idx > dma->buf_count) {
+               if (cmdbuf->dma_idx > dma->buf_count) {
                        DRM_ERROR
                            ("vertex buffer index %u out of range (0-%u)\n",
-                            cmdbuf.dma_idx, dma->buf_count-1);
-                       return DRM_ERR(EINVAL);
+                            cmdbuf->dma_idx, dma->buf_count-1);
+                       return -EINVAL;
                }
-               dmabuf = dma->buflist[cmdbuf.dma_idx];
+               dmabuf = dma->buflist[cmdbuf->dma_idx];
        } else {
                dmabuf = NULL;
        }
@@ -990,47 +986,49 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
         * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct
         * for locking on FreeBSD.
         */
-       if (cmdbuf.size) {
-               kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER);
+       if (cmdbuf->size) {
+               kcmd_addr = drm_alloc(cmdbuf->size * 8, DRM_MEM_DRIVER);
                if (kcmd_addr == NULL)
-                       return DRM_ERR(ENOMEM);
+                       return -ENOMEM;
 
-               if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr,
-                                      cmdbuf.size * 8))
+               if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr,
+                                      cmdbuf->size * 8))
                {
-                       drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
-                       return DRM_ERR(EFAULT);
+                       drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
+                       return -EFAULT;
                }
-               cmdbuf.cmd_addr = kcmd_addr;
+               cmdbuf->cmd_addr = kcmd_addr;
        }
-       if (cmdbuf.vb_size) {
-               kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER);
+       if (cmdbuf->vb_size) {
+               kvb_addr = drm_alloc(cmdbuf->vb_size, DRM_MEM_DRIVER);
                if (kvb_addr == NULL) {
-                       ret = DRM_ERR(ENOMEM);
+                       ret = -ENOMEM;
                        goto done;
                }
 
-               if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr,
-                                      cmdbuf.vb_size)) {
-                       ret = DRM_ERR(EFAULT);
+               if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr,
+                                      cmdbuf->vb_size)) {
+                       ret = -EFAULT;
                        goto done;
                }
-               cmdbuf.vb_addr = kvb_addr;
+               cmdbuf->vb_addr = kvb_addr;
        }
-       if (cmdbuf.nbox) {
-               kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),
-                                      DRM_MEM_DRIVER);
+       if (cmdbuf->nbox) {
+               kbox_addr = drm_alloc(cmdbuf->nbox *
+                                     sizeof(struct drm_clip_rect),
+                                     DRM_MEM_DRIVER);
                if (kbox_addr == NULL) {
-                       ret = DRM_ERR(ENOMEM);
+                       ret = -ENOMEM;
                        goto done;
                }
 
-               if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,
-                                      cmdbuf.nbox * sizeof(drm_clip_rect_t))) {
-                       ret = DRM_ERR(EFAULT);
+               if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr,
+                                      cmdbuf->nbox *
+                                      sizeof(struct drm_clip_rect))) {
+                       ret = -EFAULT;
                        goto done;
                }
-               cmdbuf.box_addr = kbox_addr;
+               cmdbuf->box_addr = kbox_addr;
        }
 
        /* Make sure writes to DMA buffers are finished before sending
@@ -1043,10 +1041,10 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
 
        i = 0;
        first_draw_cmd = NULL;
-       while (i < cmdbuf.size) {
+       while (i < cmdbuf->size) {
                drm_savage_cmd_header_t cmd_header;
-               cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr;
-               cmdbuf.cmd_addr++;
+               cmd_header = *(drm_savage_cmd_header_t *)cmdbuf->cmd_addr;
+               cmdbuf->cmd_addr++;
                i++;
 
                /* Group drawing commands with same state to minimize
@@ -1056,28 +1054,29 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
                case SAVAGE_CMD_DMA_IDX:
                case SAVAGE_CMD_VB_IDX:
                        j = (cmd_header.idx.count + 3) / 4;
-                       if (i + j > cmdbuf.size) {
+                       if (i + j > cmdbuf->size) {
                                DRM_ERROR("indexed drawing command extends "
                                          "beyond end of command buffer\n");
                                DMA_FLUSH();
-                               return DRM_ERR(EINVAL);
+                               return -EINVAL;
                        }
                        /* fall through */
                case SAVAGE_CMD_DMA_PRIM:
                case SAVAGE_CMD_VB_PRIM:
                        if (!first_draw_cmd)
-                               first_draw_cmd = cmdbuf.cmd_addr-1;
-                       cmdbuf.cmd_addr += j;
+                               first_draw_cmd = cmdbuf->cmd_addr-1;
+                       cmdbuf->cmd_addr += j;
                        i += j;
                        break;
                default:
                        if (first_draw_cmd) {
                                ret = savage_dispatch_draw (
                                        dev_priv, first_draw_cmd,
-                                       cmdbuf.cmd_addr-1,
-                                       dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size,
-                                       cmdbuf.vb_stride,
-                                       cmdbuf.nbox, cmdbuf.box_addr);
+                                       cmdbuf->cmd_addr-1,
+                                       dmabuf, cmdbuf->vb_addr,
+                                       cmdbuf->vb_size,
+                                       cmdbuf->vb_stride,
+                                       cmdbuf->nbox, cmdbuf->box_addr);
                                if (ret != 0)
                                        return ret;
                                first_draw_cmd = NULL;
@@ -1089,40 +1088,42 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
                switch (cmd_header.cmd.cmd) {
                case SAVAGE_CMD_STATE:
                        j = (cmd_header.state.count + 1) / 2;
-                       if (i + j > cmdbuf.size) {
+                       if (i + j > cmdbuf->size) {
                                DRM_ERROR("command SAVAGE_CMD_STATE extends "
                                          "beyond end of command buffer\n");
                                DMA_FLUSH();
-                               ret = DRM_ERR(EINVAL);
+                               ret = -EINVAL;
                                goto done;
                        }
                        ret = savage_dispatch_state(dev_priv, &cmd_header,
-                               (const uint32_t *)cmdbuf.cmd_addr);
-                       cmdbuf.cmd_addr += j;
+                               (const uint32_t *)cmdbuf->cmd_addr);
+                       cmdbuf->cmd_addr += j;
                        i += j;
                        break;
                case SAVAGE_CMD_CLEAR:
-                       if (i + 1 > cmdbuf.size) {
+                       if (i + 1 > cmdbuf->size) {
                                DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
                                          "beyond end of command buffer\n");
                                DMA_FLUSH();
-                               ret = DRM_ERR(EINVAL);
+                               ret = -EINVAL;
                                goto done;
                        }
                        ret = savage_dispatch_clear(dev_priv, &cmd_header,
-                                                   cmdbuf.cmd_addr,
-                                                   cmdbuf.nbox, cmdbuf.box_addr);
-                       cmdbuf.cmd_addr++;
+                                                   cmdbuf->cmd_addr,
+                                                   cmdbuf->nbox,
+                                                   cmdbuf->box_addr);
+                       cmdbuf->cmd_addr++;
                        i++;
                        break;
                case SAVAGE_CMD_SWAP:
-                       ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox,
-                                                  cmdbuf.box_addr);
+                       ret = savage_dispatch_swap(dev_priv, cmdbuf->nbox,
+                                                  cmdbuf->box_addr);
                        break;
                default:
-                       DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);
+                       DRM_ERROR("invalid command 0x%x\n",
+                                 cmd_header.cmd.cmd);
                        DMA_FLUSH();
-                       ret = DRM_ERR(EINVAL);
+                       ret = -EINVAL;
                        goto done;
                }
 
@@ -1134,9 +1135,9 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
 
        if (first_draw_cmd) {
                ret = savage_dispatch_draw (
-                       dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf,
-                       cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride,
-                       cmdbuf.nbox, cmdbuf.box_addr);
+                       dev_priv, first_draw_cmd, cmdbuf->cmd_addr, dmabuf,
+                       cmdbuf->vb_addr, cmdbuf->vb_size, cmdbuf->vb_stride,
+                       cmdbuf->nbox, cmdbuf->box_addr);
                if (ret != 0) {
                        DMA_FLUSH();
                        goto done;
@@ -1145,7 +1146,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
 
        DMA_FLUSH();
 
-       if (dmabuf && cmdbuf.discard) {
+       if (dmabuf && cmdbuf->discard) {
                drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private;
                uint16_t event;
                event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
@@ -1155,9 +1156,9 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
 
 done:
        /* If we didn't need to allocate them, these'll be NULL */
-       drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
-       drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);
-       drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),
+       drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
+       drm_free(kvb_addr, cmdbuf->vb_size, DRM_MEM_DRIVER);
+       drm_free(kbox_addr, cmdbuf->nbox * sizeof(struct drm_clip_rect),
                 DRM_MEM_DRIVER);
 
        return ret;
index 006d148..a4a88fe 100644 (file)
 
 #define DRIVER_AUTHOR          "SIS, Tungsten Graphics"
 #define DRIVER_NAME            "sis"
-#define DRIVER_DESC            "SIS 300/630/540"
-#define DRIVER_DATE            "20060619"
+#define DRIVER_DESC            "SIS 300/630/540 and XGI V3XE/V5/V8"
+#define DRIVER_DATE            "20070626"
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           2
-#define DRIVER_PATCHLEVEL      1
+#define DRIVER_MINOR           3
+#define DRIVER_PATCHLEVEL      0
 
 enum sis_family {
        SIS_OTHER = 0,
@@ -58,7 +58,7 @@ enum sis_family {
 typedef struct drm_sis_private {
        drm_local_map_t *mmio;
        unsigned int idle_fault;
-       drm_sman_t sman;
+       struct drm_sman sman;
        unsigned int chipset;
        int vram_initialized;
        int agp_initialized;
@@ -66,9 +66,10 @@ typedef struct drm_sis_private {
        unsigned long agp_offset;
 } drm_sis_private_t;
 
-extern int sis_idle(drm_device_t *dev);
-extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void sis_lastclose(drm_device_t *dev);
+extern int sis_idle(struct drm_device *dev);
+extern void sis_reclaim_buffers_locked(struct drm_device *dev,
+                                      struct drm_file *file_priv);
+extern void sis_lastclose(struct drm_device *dev);
 
 #else
 #include "sis_ds.h"
@@ -78,14 +79,14 @@ typedef struct drm_sis_private {
        memHeap_t *FBHeap;
 } drm_sis_private_t;
 
-extern int sis_init_context(drm_device_t * dev, int context);
-extern int sis_final_context(drm_device_t * dev, int context);
+extern int sis_init_context(struct drm_device * dev, int context);
+extern int sis_final_context(struct drm_device * dev, int context);
 
 #endif
 
 
 
-extern drm_ioctl_desc_t sis_ioctls[];
+extern struct drm_ioctl_desc sis_ioctls[];
 extern int sis_max_ioctl;
 
 #endif
index 6d074d6..e11939f 100644 (file)
@@ -81,59 +81,52 @@ static int del_alloc_set(int context, int type, unsigned int val)
 /* fb management via fb device */
 #if defined(__linux__) && defined(CONFIG_FB_SIS)
 
-static int sis_fb_init(DRM_IOCTL_ARGS)
+static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        return 0;
 }
 
-static int sis_fb_alloc(DRM_IOCTL_ARGS)
+static int sis_fb_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_sis_mem_t fb;
+       drm_sis_mem_t *fb = data;
        struct sis_memreq req;
-       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
        int retval = 0;
 
-       DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
-
-       req.size = fb.size;
+       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)) {
+               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 = DRM_ERR(EINVAL);
+                       retval = -EINVAL;
                }
        } else {
-               fb.offset = 0;
-               fb.size = 0;
-               fb.free = 0;
+               fb->offset = 0;
+               fb->size = 0;
+               fb->free = 0;
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
-
-       DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+       DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb->size, req.offset);
 
        return retval;
 }
 
-static int sis_fb_free(DRM_IOCTL_ARGS)
+static int sis_fb_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_sis_mem_t fb;
        int retval = 0;
 
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
-
-       if (!fb.free)
-               return DRM_ERR(EINVAL);
+       if (!fb->free)
+               return -EINVAL;
 
-       if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
-               retval = DRM_ERR(EINVAL);
-       sis_free(fb.free);
+       if (!del_alloc_set(fb->context, VIDEO_TYPE, fb->free))
+               retval = -EINVAL;
+       sis_free(fb->free);
 
-       DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
+       DRM_DEBUG("free fb, offset = 0x%lx\n", fb->free);
 
        return retval;
 }
@@ -150,13 +143,10 @@ static int sis_fb_free(DRM_IOCTL_ARGS)
  *    X driver/sisfb                                  HW-   Command-
  *  framebuffer memory           DRI heap           Cursor   queue
  */
-static int sis_fb_init(DRM_IOCTL_ARGS)
+static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_fb_t fb;
-
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
+       drm_sis_fb_t *fb = data;
 
        if (dev_priv == NULL) {
                dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
@@ -167,71 +157,62 @@ static int sis_fb_init(DRM_IOCTL_ARGS)
        }
 
        if (dev_priv->FBHeap != NULL)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
-       dev_priv->FBHeap = mmInit(fb.offset, fb.size);
+       dev_priv->FBHeap = mmInit(fb->offset, fb->size);
 
-       DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
+       DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size);
 
        return 0;
 }
 
-static int sis_fb_alloc(DRM_IOCTL_ARGS)
+static int sis_fb_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
-       drm_sis_mem_t fb;
+       drm_sis_mem_t *fb = data;
        PMemBlock block;
        int retval = 0;
 
        if (dev_priv == NULL || dev_priv->FBHeap == NULL)
-               return DRM_ERR(EINVAL);
-
-       DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
+               return -EINVAL;
 
-       block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
+       block = mmAllocMem(dev_priv->FBHeap, fb->size, 0, 0);
        if (block) {
                /* TODO */
-               fb.offset = block->ofs;
-               fb.free = (unsigned long)block;
-               if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
+               fb->offset = block->ofs;
+               fb->free = (unsigned long)block;
+               if (!add_alloc_set(fb->context, VIDEO_TYPE, fb->free)) {
                        DRM_DEBUG("adding to allocation set fails\n");
-                       mmFreeMem((PMemBlock) fb.free);
-                       retval = DRM_ERR(EINVAL);
+                       mmFreeMem((PMemBlock) fb->free);
+                       retval = -EINVAL;
                }
        } else {
-               fb.offset = 0;
-               fb.size = 0;
-               fb.free = 0;
+               fb->offset = 0;
+               fb->size = 0;
+               fb->free = 0;
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
-
-       DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
+       DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb->size, fb->offset);
 
        return retval;
 }
 
-static int sis_fb_free(DRM_IOCTL_ARGS)
+static int sis_fb_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t fb;
+       drm_sis_mem_t *fb = data;
 
        if (dev_priv == NULL || dev_priv->FBHeap == NULL)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
+       if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb->free))
+               return -EINVAL;
 
-       if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
-               return DRM_ERR(EINVAL);
+       if (!del_alloc_set(fb->context, VIDEO_TYPE, fb->free))
+               return -EINVAL;
+       mmFreeMem((PMemBlock) fb->free);
 
-       if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
-               return DRM_ERR(EINVAL);
-       mmFreeMem((PMemBlock) fb.free);
-
-       DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
+       DRM_DEBUG("free fb, free = 0x%lx\n", fb->free);
 
        return 0;
 }
@@ -240,11 +221,10 @@ static int sis_fb_free(DRM_IOCTL_ARGS)
 
 /* agp memory management */
 
-static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
+static int sis_ioctl_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_agp_t agp;
+       drm_sis_agp_t *agp = data;
 
        if (dev_priv == NULL) {
                dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
@@ -255,75 +235,63 @@ static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
        }
 
        if (dev_priv->AGPHeap != NULL)
-               return DRM_ERR(EINVAL);
-
-       DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
-                                sizeof(agp));
+               return -EINVAL;
 
-       dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
+       dev_priv->AGPHeap = mmInit(agp->offset, agp->size);
 
-       DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+       DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size);
 
        return 0;
 }
 
-static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
+static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
-       drm_sis_mem_t agp;
+       drm_sis_mem_t *agp = data;
        PMemBlock block;
        int retval = 0;
 
        if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
-       DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
-
-       block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
+       block = mmAllocMem(dev_priv->AGPHeap, agp->size, 0, 0);
        if (block) {
                /* TODO */
-               agp.offset = block->ofs;
-               agp.free = (unsigned long)block;
-               if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
+               agp->offset = block->ofs;
+               agp->free = (unsigned long)block;
+               if (!add_alloc_set(agp->context, AGP_TYPE, agp->free)) {
                        DRM_DEBUG("adding to allocation set fails\n");
-                       mmFreeMem((PMemBlock) agp.free);
+                       mmFreeMem((PMemBlock) agp->free);
                        retval = -1;
                }
        } else {
-               agp.offset = 0;
-               agp.size = 0;
-               agp.free = 0;
+               agp->offset = 0;
+               agp->size = 0;
+               agp->free = 0;
        }
 
-       DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp));
-
-       DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
+       DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp->size,
+           agp->offset);
 
        return retval;
 }
 
-static int sis_ioctl_agp_free(DRM_IOCTL_ARGS)
+static int sis_ioctl_agp_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t agp;
+       drm_sis_mem_t *agp = data;
 
        if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
-               return DRM_ERR(EINVAL);
-
-       DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data,
-                                sizeof(agp));
+               return -EINVAL;
 
-       if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free))
-               return DRM_ERR(EINVAL);
+       if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp->free))
+               return -EINVAL;
 
-       mmFreeMem((PMemBlock) agp.free);
-       if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
-               return DRM_ERR(EINVAL);
+       mmFreeMem((PMemBlock) agp->free);
+       if (!del_alloc_set(agp->context, AGP_TYPE, agp->free))
+               return -EINVAL;
 
-       DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
+       DRM_DEBUG("free agp, free = 0x%lx\n", agp->free);
 
        return 0;
 }
@@ -407,12 +375,12 @@ int sis_final_context(struct drm_device *dev, int context)
 }
 
 drm_ioctl_desc_t sis_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}
+       DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_fb_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_ioctl_agp_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY)
 };
 
 int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
index 333c4bc..bd737a7 100644 (file)
@@ -139,7 +139,7 @@ static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
        return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
 }
 
-int via_dma_cleanup(drm_device_t * dev)
+int via_dma_cleanup(struct drm_device * dev)
 {
        if (dev->dev_private) {
                drm_via_private_t *dev_priv =
@@ -157,30 +157,30 @@ int via_dma_cleanup(drm_device_t * dev)
        return 0;
 }
 
-static int via_initialize(drm_device_t * dev,
+static int via_initialize(struct drm_device * dev,
                          drm_via_private_t * dev_priv,
                          drm_via_dma_init_t * init)
 {
        if (!dev_priv || !dev_priv->mmio) {
                DRM_ERROR("via_dma_init called before via_map_init\n");
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        if (dev_priv->ring.virtual_start != NULL) {
                DRM_ERROR("%s called again without calling cleanup\n",
                          __FUNCTION__);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        if (!dev->agp || !dev->agp->base) {
                DRM_ERROR("%s called with no agp memory available\n", 
                          __FUNCTION__);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        if (dev_priv->chipset == VIA_DX9_0) {
                DRM_ERROR("AGP DMA is not supported on this chip\n");
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        dev_priv->ring.map.offset = dev->agp->base + init->offset;
@@ -195,7 +195,7 @@ static int via_initialize(drm_device_t * dev,
                via_dma_cleanup(dev);
                DRM_ERROR("can not ioremap virtual address for"
                          " ring buffer\n");
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
@@ -215,35 +215,31 @@ static int via_initialize(drm_device_t * dev,
        return 0;
 }
 
-static int via_dma_init(DRM_IOCTL_ARGS)
+static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_dma_init_t init;
+       drm_via_dma_init_t *init = data;
        int retcode = 0;
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t __user *) data,
-                                sizeof(init));
-
-       switch (init.func) {
+       switch (init->func) {
        case VIA_INIT_DMA:
                if (!DRM_SUSER(DRM_CURPROC))
-                       retcode = DRM_ERR(EPERM);
+                       retcode = -EPERM;
                else
-                       retcode = via_initialize(dev, dev_priv, &init);
+                       retcode = via_initialize(dev, dev_priv, init);
                break;
        case VIA_CLEANUP_DMA:
                if (!DRM_SUSER(DRM_CURPROC))
-                       retcode = DRM_ERR(EPERM);
+                       retcode = -EPERM;
                else
                        retcode = via_dma_cleanup(dev);
                break;
        case VIA_DMA_INITIALIZED:
                retcode = (dev_priv->ring.virtual_start != NULL) ?
-                       0 : DRM_ERR(EFAULT);
+                       0 : -EFAULT;
                break;
        default:
-               retcode = DRM_ERR(EINVAL);
+               retcode = -EINVAL;
                break;
        }
 
@@ -252,7 +248,7 @@ static int via_dma_init(DRM_IOCTL_ARGS)
 
 
 
-static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
+static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * cmd)
 {
        drm_via_private_t *dev_priv;
        uint32_t *vb;
@@ -263,15 +259,15 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
        if (dev_priv->ring.virtual_start == NULL) {
                DRM_ERROR("%s called without initializing AGP ring buffer.\n",
                          __FUNCTION__);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
        if (cmd->size > VIA_PCI_BUF_SIZE) {
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
 
        if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
        /*
         * Running this function on AGP memory is dead slow. Therefore
@@ -287,7 +283,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
 
        vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
        if (vb == NULL) {
-               return DRM_ERR(EAGAIN);
+               return -EAGAIN;
        }
 
        memcpy(vb, dev_priv->pci_buf, cmd->size);
@@ -306,39 +302,35 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
        return 0;
 }
 
-int via_driver_dma_quiescent(drm_device_t * dev)
+int via_driver_dma_quiescent(struct drm_device * dev)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
 
        if (!via_wait_idle(dev_priv)) {
-               return DRM_ERR(EBUSY);
+               return -EBUSY;
        }
        return 0;
 }
 
-static int via_flush_ioctl(DRM_IOCTL_ARGS)
+static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return via_driver_dma_quiescent(dev);
 }
 
-static int via_cmdbuffer(DRM_IOCTL_ARGS)
+static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_cmdbuffer_t cmdbuf;
+       drm_via_cmdbuffer_t *cmdbuf = data;
        int ret;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
-                                sizeof(cmdbuf));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
+       DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf->buf,
+                 cmdbuf->size);
 
-       ret = via_dispatch_cmdbuffer(dev, &cmdbuf);
+       ret = via_dispatch_cmdbuffer(dev, cmdbuf);
        if (ret) {
                return ret;
        }
@@ -346,17 +338,17 @@ static int via_cmdbuffer(DRM_IOCTL_ARGS)
        return 0;
 }
 
-static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
+static int via_dispatch_pci_cmdbuffer(struct drm_device * dev,
                                      drm_via_cmdbuffer_t * cmd)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
        int ret;
 
        if (cmd->size > VIA_PCI_BUF_SIZE) {
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
        }
        if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
 
        if ((ret =
             via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
@@ -370,21 +362,17 @@ static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
        return ret;
 }
 
-static int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_cmdbuffer_t cmdbuf;
+       drm_via_cmdbuffer_t *cmdbuf = data;
        int ret;
 
-       LOCK_TEST_WITH_RETURN(dev, filp);
-
-       DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
-                                sizeof(cmdbuf));
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf,
-                 cmdbuf.size);
+       DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf->buf,
+                 cmdbuf->size);
 
-       ret = via_dispatch_pci_cmdbuffer(dev, &cmdbuf);
+       ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf);
        if (ret) {
                return ret;
        }
@@ -645,94 +633,87 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
  * User interface to the space and lag functions.
  */
 
-static int via_cmdbuf_size(DRM_IOCTL_ARGS)
+static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_cmdbuf_size_t d_siz;
+       drm_via_cmdbuf_size_t *d_siz = data;
        int ret = 0;
        uint32_t tmp_size, count;
        drm_via_private_t *dev_priv;
 
        DRM_DEBUG("via cmdbuf_size\n");
-       LOCK_TEST_WITH_RETURN( dev, filp );
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        dev_priv = (drm_via_private_t *) dev->dev_private;
 
        if (dev_priv->ring.virtual_start == NULL) {
                DRM_ERROR("%s called without initializing AGP ring buffer.\n",
                          __FUNCTION__);
-               return DRM_ERR(EFAULT);
+               return -EFAULT;
        }
 
-       DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t __user *) data,
-                                sizeof(d_siz));
-
-
        count = 1000000;
-       tmp_size = d_siz.size;
-       switch(d_siz.func) {
+       tmp_size = d_siz->size;
+       switch(d_siz->func) {
        case VIA_CMDBUF_SPACE:
-               while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size)
+               while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size)
                       && count--) {
-                       if (!d_siz.wait) {
+                       if (!d_siz->wait) {
                                break;
                        }
                }
                if (!count) {
                        DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
-                       ret = DRM_ERR(EAGAIN);
+                       ret = -EAGAIN;
                }
                break;
        case VIA_CMDBUF_LAG:
-               while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size)
+               while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size)
                       && count--) {
-                       if (!d_siz.wait) {
+                       if (!d_siz->wait) {
                                break;
                        }
                }
                if (!count) {
                        DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
-                       ret = DRM_ERR(EAGAIN);
+                       ret = -EAGAIN;
                }
                break;
        default:
-               ret = DRM_ERR(EFAULT);
+               ret = -EFAULT;
        }
-       d_siz.size = tmp_size;
+       d_siz->size = tmp_size;
 
-       DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t __user *) data, d_siz,
-                              sizeof(d_siz));
        return ret;
 }
 
 #ifndef VIA_HAVE_DMABLIT
 int 
-via_dma_blit_sync( DRM_IOCTL_ARGS ) {
+via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv ) {
        DRM_ERROR("PCI DMA BitBlt is not implemented for this system.\n");
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 int 
-via_dma_blit( DRM_IOCTL_ARGS ) {
+via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv ) {
        DRM_ERROR("PCI DMA BitBlt is not implemented for this system.\n");
-       return DRM_ERR(EINVAL);
+       return -EINVAL;
 }
 #endif
 
-drm_ioctl_desc_t via_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, DRM_AUTH|DRM_MASTER},
-       [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, DRM_AUTH|DRM_MASTER},
-       [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, DRM_AUTH|DRM_MASTER},
-       [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_DMA_BLIT)] = {via_dma_blit, DRM_AUTH},
-       [DRM_IOCTL_NR(DRM_VIA_BLIT_SYNC)] = {via_dma_blit_sync, DRM_AUTH}
+struct drm_ioctl_desc via_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
 };
 
 int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
index 635e463..b15785b 100644 (file)
@@ -54,7 +54,7 @@
 #define VIA_NR_XVMC_LOCKS             5
 #define VIA_MAX_CACHELINE_SIZE   64
 #define XVMCLOCKPTR(saPriv,lockNo)                                     \
-       ((volatile drm_hw_lock_t *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
+       ((volatile struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
                                      (VIA_MAX_CACHELINE_SIZE - 1)) &   \
                                     ~(VIA_MAX_CACHELINE_SIZE - 1)) +   \
                                    VIA_MAX_CACHELINE_SIZE*(lockNo)))
@@ -187,7 +187,7 @@ typedef struct _drm_via_tex_region {
 typedef struct _drm_via_sarea {
        unsigned int dirty;
        unsigned int nbox;
-       drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS];
+       struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS];
        drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
        int texAge;             /* last time texture was uploaded */
        int ctxOwner;           /* last context to upload state */
index 0a478fe..9f09955 100644 (file)
@@ -40,7 +40,7 @@ static struct pci_device_id pciidlist[] = {
 
 
 #ifdef VIA_HAVE_FENCE
-static drm_fence_driver_t via_fence_driver = {
+static struct drm_fence_driver via_fence_driver = {
        .num_classes = 1,
        .wrap_diff = (1 << 30),
        .flush_diff = (1 << 20),
@@ -65,7 +65,7 @@ static uint32_t via_mem_prios[] = {DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM
 static uint32_t via_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_PRIV0, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
 
 
-static drm_bo_driver_t via_bo_driver = {
+static struct drm_bo_driver via_bo_driver = {
        .mem_type_prio = via_mem_prios,
        .mem_busy_prio = via_busy_prios,
        .num_mem_type_prio = ARRAY_SIZE(via_mem_prios),
index baafbbf..0b47484 100644 (file)
@@ -116,7 +116,7 @@ typedef struct drm_via_private {
        /* Memory manager stuff */
 #ifdef VIA_HAVE_CORE_MM
        unsigned int idle_fault;
-       drm_sman_t sman;
+       struct drm_sman sman;
        int vram_initialized;
        int agp_initialized;
        unsigned long vram_offset;
@@ -148,54 +148,55 @@ enum via_family {
 #define VIA_READ8(reg)         DRM_READ8(VIA_BASE, reg)
 #define VIA_WRITE8(reg,val)    DRM_WRITE8(VIA_BASE, reg, val)
 
-extern drm_ioctl_desc_t via_ioctls[];
+extern struct drm_ioctl_desc via_ioctls[];
 extern int via_max_ioctl;
 
-extern int via_fb_init(DRM_IOCTL_ARGS);
-extern int via_mem_alloc(DRM_IOCTL_ARGS);
-extern int via_mem_free(DRM_IOCTL_ARGS);
-extern int via_agp_init(DRM_IOCTL_ARGS);
-extern int via_map_init(DRM_IOCTL_ARGS);
-extern int via_decoder_futex(DRM_IOCTL_ARGS);
-extern int via_wait_irq(DRM_IOCTL_ARGS);
-extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
-extern int via_dma_blit( DRM_IOCTL_ARGS );
+extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv );
+extern int via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv );
 
-extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
-extern int via_driver_unload(drm_device_t *dev);
-extern int via_final_context(drm_device_t * dev, int context);
+extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int via_driver_unload(struct drm_device *dev);
+extern int via_final_context(struct drm_device * dev, int context);
 
-extern int via_do_cleanup_map(drm_device_t * dev);
-extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern int via_do_cleanup_map(struct drm_device * dev);
+extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 
 extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
-extern void via_driver_irq_preinstall(drm_device_t * dev);
-extern void via_driver_irq_postinstall(drm_device_t * dev);
-extern void via_driver_irq_uninstall(drm_device_t * dev);
+extern void via_driver_irq_preinstall(struct drm_device * dev);
+extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern void via_driver_irq_uninstall(struct drm_device * dev);
 
-extern int via_dma_cleanup(drm_device_t * dev);
+extern int via_dma_cleanup(struct drm_device * dev);
 extern void via_init_command_verifier(void);
-extern int via_driver_dma_quiescent(drm_device_t * dev);
+extern int via_driver_dma_quiescent(struct drm_device * dev);
 extern void via_init_futex(drm_via_private_t *dev_priv);
 extern void via_cleanup_futex(drm_via_private_t *dev_priv);
 extern void via_release_futex(drm_via_private_t *dev_priv, int context);
 
 #ifdef VIA_HAVE_CORE_MM
-extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
-extern void via_lastclose(drm_device_t *dev);
+extern void via_reclaim_buffers_locked(struct drm_device *dev,
+                                      struct drm_file *file_priv);
+extern void via_lastclose(struct drm_device *dev);
 #else
-extern int via_init_context(drm_device_t * dev, int context);
+extern int via_init_context(struct drm_device * dev, int context);
 #endif
 
 #ifdef VIA_HAVE_DMABLIT
-extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
-extern void via_init_dmablit(drm_device_t *dev);
+extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
+extern void via_init_dmablit(struct drm_device *dev);
 #endif
 
 #ifdef VIA_HAVE_FENCE
 extern void via_fence_timer(unsigned long data);
-extern void via_poke_flush(drm_device_t * dev, uint32_t class);
-extern int via_fence_emit_sequence(drm_device_t * dev, uint32_t class,
+extern void via_poke_flush(struct drm_device * dev, uint32_t class);
+extern int via_fence_emit_sequence(struct drm_device * dev, uint32_t class,
                                   uint32_t flags,
                                   uint32_t * sequence,
                                   uint32_t * native_type);
@@ -204,14 +205,15 @@ extern int via_fence_has_irq(struct drm_device * dev, uint32_t class,
 #endif
 
 #ifdef VIA_HAVE_BUFFER
-extern drm_ttm_backend_t *via_create_ttm_backend_entry(drm_device_t *dev);
-extern int via_fence_types(drm_buffer_object_t *bo, uint32_t *class, uint32_t *type);
-extern int via_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags);
-extern int via_init_mem_type(drm_device_t *dev, uint32_t type,
-                              drm_mem_type_manager_t *man);
-extern uint32_t via_evict_mask(drm_buffer_object_t *bo);
-extern int via_move(drm_buffer_object_t *bo, int evict,
-               int no_wait, drm_bo_mem_reg_t *new_mem);
+extern struct drm_ttm_backend *via_create_ttm_backend_entry(struct drm_device *dev);
+extern int via_fence_types(struct drm_buffer_object *bo, uint32_t *fclass,
+                          uint32_t *type);
+extern int via_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
+extern int via_init_mem_type(struct drm_device *dev, uint32_t type,
+                              struct drm_mem_type_manager *man);
+extern uint32_t via_evict_mask(struct drm_buffer_object *bo);
+extern int via_move(struct drm_buffer_object *bo, int evict,
+               int no_wait, struct drm_bo_mem_reg *new_mem);
 #endif
 
 #endif
index 2ac8697..475b646 100644 (file)
@@ -99,7 +99,7 @@ static unsigned time_diff(struct timeval *now,struct timeval *then)
 
 irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
 {
-       drm_device_t *dev = (drm_device_t *) arg;
+       struct drm_device *dev = (struct drm_device *) arg;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
        int handled = 0;
@@ -171,7 +171,7 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
        }
 }
 
-int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        unsigned int cur_vblank;
@@ -199,7 +199,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
 }
 
 static int
-via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequence,
                    unsigned int *sequence)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -213,13 +213,13 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
 
        if (!dev_priv) {
                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        if (irq >= drm_via_irq_num ) {
                DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
                          irq);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
                
        real_irq = dev_priv->irq_map[irq];
@@ -227,7 +227,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
        if (real_irq < 0) {
                DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",
                          __FUNCTION__, irq);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
        masks = dev_priv->irq_masks;
@@ -253,7 +253,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
  * drm_dma.h hooks
  */
 
-void via_driver_irq_preinstall(drm_device_t * dev)
+void via_driver_irq_preinstall(struct drm_device * dev)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
@@ -302,7 +302,7 @@ void via_driver_irq_preinstall(drm_device_t * dev)
        }
 }
 
-void via_driver_irq_postinstall(drm_device_t * dev)
+void via_driver_irq_postinstall(struct drm_device * dev)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
@@ -321,7 +321,7 @@ void via_driver_irq_postinstall(drm_device_t * dev)
        }
 }
 
-void via_driver_irq_uninstall(drm_device_t * dev)
+void via_driver_irq_uninstall(struct drm_device * dev)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
@@ -340,11 +340,9 @@ void via_driver_irq_uninstall(drm_device_t * dev)
        }
 }
 
-int via_wait_irq(DRM_IOCTL_ARGS)
+int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_irqwait_t __user *argp = (void __user *)data;
-       drm_via_irqwait_t irqwait;
+       drm_via_irqwait_t *irqwait = data;
        struct timeval now;
        int ret = 0;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -352,46 +350,44 @@ int via_wait_irq(DRM_IOCTL_ARGS)
        int force_sequence;
 
        if (!dev->irq)
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
 
-       DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait));
-       if (irqwait.request.irq >= dev_priv->num_irqs) {
+       if (irqwait->request.irq >= dev_priv->num_irqs) {
                DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, 
-                         irqwait.request.irq);
-               return DRM_ERR(EINVAL);
+                         irqwait->request.irq);
+               return -EINVAL;
        }
 
-       cur_irq += irqwait.request.irq;
+       cur_irq += irqwait->request.irq;
 
-       switch (irqwait.request.type & ~VIA_IRQ_FLAGS_MASK) {
+       switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
        case VIA_IRQ_RELATIVE:
-               irqwait.request.sequence += atomic_read(&cur_irq->irq_received);
-               irqwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+               irqwait->request.sequence +=
+                       atomic_read(&cur_irq->irq_received);
+               irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
        case VIA_IRQ_ABSOLUTE:
                break;
        default:
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       if (irqwait.request.type & VIA_IRQ_SIGNAL) {
+       if (irqwait->request.type & VIA_IRQ_SIGNAL) {
                DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n", 
                          __FUNCTION__);
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
 
-       force_sequence = (irqwait.request.type & VIA_IRQ_FORCE_SEQUENCE);
+       force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE);
 
-       ret = via_driver_irq_wait(dev, irqwait.request.irq, force_sequence,
-                                 &irqwait.request.sequence);
+       ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
+                                 &irqwait->request.sequence);
 #ifdef __linux__
        do_gettimeofday(&now);
 #else
        microtime(&now);
 #endif
-       irqwait.reply.tval_sec = now.tv_sec;
-       irqwait.reply.tval_usec = now.tv_usec;
-
-       DRM_COPY_TO_USER_IOCTL(argp, irqwait, sizeof(irqwait));
+       irqwait->reply.tval_sec = now.tv_sec;
+       irqwait->reply.tval_usec = now.tv_usec;
 
        return ret;
 }
index 037a1c2..1623df6 100644 (file)
@@ -25,7 +25,7 @@
 #include "via_drm.h"
 #include "via_drv.h"
 
-static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
+static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
        int ret = 0;
@@ -83,7 +83,7 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
 
 }
 
-int via_do_cleanup_map(drm_device_t * dev)
+int via_do_cleanup_map(struct drm_device * dev)
 {
        via_dma_cleanup(dev);
 
@@ -91,19 +91,15 @@ int via_do_cleanup_map(drm_device_t * dev)
 }
 
 
-int via_map_init(DRM_IOCTL_ARGS)
+int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_init_t init;
+       drm_via_init_t *init = data;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t __user *) data,
-                                sizeof(init));
-
-       switch (init.func) {
+       switch (init->func) {
        case VIA_INIT_MAP:
-               return via_do_init_map(dev, &init);
+               return via_do_init_map(dev, init);
        case VIA_CLEANUP_MAP:
                return via_do_cleanup_map(dev);
        }
@@ -111,14 +107,14 @@ int via_map_init(DRM_IOCTL_ARGS)
        return -EINVAL;
 }
 
-int via_driver_load(drm_device_t *dev, unsigned long chipset)
+int via_driver_load(struct drm_device *dev, unsigned long chipset)
 {
        drm_via_private_t *dev_priv;
        int ret = 0;
 
        dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
        if (dev_priv == NULL)
-               return DRM_ERR(ENOMEM);
+               return -ENOMEM;
 
        dev->dev_private = (void *)dev_priv;
 
@@ -133,7 +129,7 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset)
        return ret;
 }
 
-int via_driver_unload(drm_device_t *dev)
+int via_driver_unload(struct drm_device *dev)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
 
index 8f175a7..45790dc 100644 (file)
@@ -72,17 +72,14 @@ static int del_alloc_set(int context, int type, unsigned long val)
 /* agp memory management */
 static memHeap_t *AgpHeap = NULL;
 
-int via_agp_init(DRM_IOCTL_ARGS)
+int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_via_agp_t agp;
+       drm_via_agp_t *agp = data;
 
-       DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
-                                sizeof(agp));
+       AgpHeap = via_mmInit(agp->offset, agp->size);
 
-       AgpHeap = via_mmInit(agp.offset, agp.size);
-
-       DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset,
-                 (unsigned long)agp.size);
+       DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp->offset,
+                 (unsigned long)agp->size);
 
        return 0;
 }
@@ -90,11 +87,9 @@ int via_agp_init(DRM_IOCTL_ARGS)
 /* fb memory management */
 static memHeap_t *FBHeap = NULL;
 
-int via_fb_init(DRM_IOCTL_ARGS)
+int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_via_fb_t fb;
-
-       DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
+       drm_via_fb_t *fb = data;
 
        FBHeap = via_mmInit(fb.offset, fb.size);
 
@@ -191,25 +186,18 @@ int via_final_context(struct drm_device *dev, int context)
        return 1;
 }
 
-int via_mem_alloc(DRM_IOCTL_ARGS)
+int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_via_mem_t mem;
-
-       DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
-                                sizeof(mem));
+       drm_via_mem_t *mem = data;
 
        switch (mem.type) {
        case VIA_MEM_VIDEO:
-               if (via_fb_alloc(&mem) < 0)
+               if (via_fb_alloc(mem) < 0)
                        return -EFAULT;
-               DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
-                                      sizeof(mem));
                return 0;
        case VIA_MEM_AGP:
-               if (via_agp_alloc(&mem) < 0)
+               if (via_agp_alloc(mem) < 0)
                        return -EFAULT;
-               DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
-                                      sizeof(mem));
                return 0;
        }
 
@@ -288,21 +276,18 @@ static int via_agp_alloc(drm_via_mem_t * mem)
        return retval;
 }
 
-int via_mem_free(DRM_IOCTL_ARGS)
+int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       drm_via_mem_t mem;
+       drm_via_mem_t *mem = data;
 
-       DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
-                                sizeof(mem));
-
-       switch (mem.type) {
+       switch (mem->type) {
 
        case VIA_MEM_VIDEO:
-               if (via_fb_free(&mem) == 0)
+               if (via_fb_free(mem) == 0)
                        return 0;
                break;
        case VIA_MEM_AGP:
-               if (via_agp_free(&mem) == 0)
+               if (via_agp_free(mem) == 0)
                        return 0;
                break;
        }
@@ -356,7 +341,7 @@ static int via_agp_free(drm_via_mem_t * mem)
                retval = -1;
        }
 
-       DRM_DEBUG("free agp, free = %ld\n", agp.free);
+       DRM_DEBUG("free agp, free = %ld\n", agp.nfree);
 
        return retval;
 }
index 4b844af..ded5c4e 100644 (file)
@@ -252,10 +252,10 @@ eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
 static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
                                                          unsigned long offset,
                                                          unsigned long size,
-                                                         drm_device_t * dev)
+                                                         struct drm_device * dev)
 {
 #ifdef __linux__
-       drm_map_list_t *r_list;
+       struct drm_map_list *r_list;
 #endif
        drm_local_map_t *map = seq->map_cache;
 
@@ -967,7 +967,7 @@ via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
 
 int
 via_verify_command_stream(const uint32_t * buf, unsigned int size,
-                         drm_device_t * dev, int agp)
+                         struct drm_device * dev, int agp)
 {
 
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -1031,18 +1031,18 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size,
                case state_error:
                default:
                        *hc_state = saved_state;
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
        if (state == state_error) {
                *hc_state = saved_state;
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        return 0;
 }
 
 int
-via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+via_parse_command_stream(struct drm_device * dev, const uint32_t * buf,
                         unsigned int size)
 {
 
@@ -1087,11 +1087,11 @@ via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
                        break;
                case state_error:
                default:
-                       return DRM_ERR(EINVAL);
+                       return -EINVAL;
                }
        }
        if (state == state_error) {
-               return DRM_ERR(EINVAL);
+               return -EINVAL;
        }
        return 0;
 }
index 84497c4..dac1db9 100644 (file)
@@ -49,7 +49,7 @@ typedef struct {
        drm_via_sequence_t unfinished;
        int agp_texture;
        int multitex;
-       drm_device_t *dev;
+       struct drm_device *dev;
        drm_local_map_t *map_cache;
        uint32_t vertex_count;
        int agp;
@@ -57,8 +57,8 @@ typedef struct {
 } drm_via_state_t;
 
 extern int via_verify_command_stream(const uint32_t * buf, unsigned int size, 
-                                   drm_device_t *dev, int agp);
-extern int via_parse_command_stream(drm_device_t *dev, const uint32_t * buf,
+                                   struct drm_device *dev, int agp);
+extern int via_parse_command_stream(struct drm_device *dev, const uint32_t * buf,
                                    unsigned int size);
 
 #endif
index 300ac61..c15e75b 100644 (file)
@@ -65,10 +65,9 @@ void via_release_futex(drm_via_private_t * dev_priv, int context)
        }
 }
 
-int via_decoder_futex(DRM_IOCTL_ARGS)
+int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       DRM_DEVICE;
-       drm_via_futex_t fx;
+       drm_via_futex_t *fx = data;
        volatile int *lock;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
@@ -76,21 +75,18 @@ int via_decoder_futex(DRM_IOCTL_ARGS)
 
        DRM_DEBUG("%s\n", __FUNCTION__);
 
-       DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t __user *) data,
-                                sizeof(fx));
-
-       if (fx.lock > VIA_NR_XVMC_LOCKS)
+       if (fx->lock > VIA_NR_XVMC_LOCKS)
                return -EFAULT;
 
-       lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock);
+       lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock);
 
-       switch (fx.func) {
+       switch (fx->func) {
        case VIA_FUTEX_WAIT:
-               DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock],
-                           (fx.ms / 10) * (DRM_HZ / 100), *lock != fx.val);
+               DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
+                           (fx->ms / 10) * (DRM_HZ / 100), *lock != fx->val);
                return ret;
        case VIA_FUTEX_WAKE:
-               DRM_WAKEUP(&(dev_priv->decoder_queue[fx.lock]));
+               DRM_WAKEUP(&(dev_priv->decoder_queue[fx->lock]));
                return 0;
        }
        return 0;
diff --git a/shared-core/xgi_drm.h b/shared-core/xgi_drm.h
new file mode 100644 (file)
index 0000000..de0fb53
--- /dev/null
@@ -0,0 +1,133 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, 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 on 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
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL XGI 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 _XGI_DRM_H_
+#define _XGI_DRM_H_
+
+#include <linux/types.h>
+#include <asm/ioctl.h>
+
+struct drm_xgi_sarea {
+       __u16 device_id;
+       __u16 vendor_id;
+
+       char device_name[32];
+
+       unsigned int scrn_start;
+       unsigned int scrn_xres;
+       unsigned int scrn_yres;
+       unsigned int scrn_bpp;
+       unsigned int scrn_pitch;
+};
+
+
+struct xgi_bootstrap {
+       /**
+        * Size of PCI-e GART range in megabytes.
+        */
+       struct drm_map gart;
+};
+
+
+enum xgi_mem_location {
+       XGI_MEMLOC_NON_LOCAL = 0,
+       XGI_MEMLOC_LOCAL = 1,
+       XGI_MEMLOC_INVALID = 0x7fffffff
+};
+
+struct xgi_mem_alloc {
+       /**
+        * Memory region to be used for allocation.
+        * 
+        * Must be one of XGI_MEMLOC_NON_LOCAL or XGI_MEMLOC_LOCAL.
+        */
+       unsigned int location;
+
+       /**
+        * Number of bytes request.
+        * 
+        * On successful allocation, set to the actual number of bytes
+        * allocated.
+        */
+       unsigned int size;
+
+       /**
+        * Address of the memory from the graphics hardware's point of view.
+        */
+       __u32 hw_addr;
+
+       /**
+        * Offset of the allocation in the mapping.
+        */
+       __u32 offset;
+
+       /**
+        * Magic handle used to release memory.
+        * 
+        * See also DRM_XGI_FREE ioctl.
+        */
+       __u32 index;
+};
+
+enum xgi_batch_type {
+       BTYPE_2D = 0,
+       BTYPE_3D = 1,
+       BTYPE_FLIP = 2,
+       BTYPE_CTRL = 3,
+       BTYPE_NONE = 0x7fffffff
+};
+
+struct xgi_cmd_info {
+       __u32 type;
+       __u32 hw_addr;
+       __u32 size;
+       __u32 id;
+};
+
+struct xgi_state_info {
+       unsigned int _fromState;
+       unsigned int _toState;
+};
+
+
+/*
+ * Ioctl definitions
+ */
+
+#define DRM_XGI_BOOTSTRAP           0
+#define DRM_XGI_ALLOC               1
+#define DRM_XGI_FREE                2
+#define DRM_XGI_SUBMIT_CMDLIST      3
+#define DRM_XGI_STATE_CHANGE        4
+
+#define XGI_IOCTL_BOOTSTRAP         DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_BOOTSTRAP, struct xgi_bootstrap)
+#define XGI_IOCTL_ALLOC             DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_ALLOC, struct xgi_mem_alloc)
+#define XGI_IOCTL_FREE              DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_FREE, __u32)
+#define XGI_IOCTL_SUBMIT_CMDLIST    DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_SUBMIT_CMDLIST, struct xgi_cmd_info)
+#define XGI_IOCTL_STATE_CHANGE      DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_STATE_CHANGE, struct xgi_state_info)
+
+#endif /* _XGI_DRM_H_ */
diff --git a/tests/Makefile b/tests/Makefile
deleted file mode 100644 (file)
index b406e0a..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-
-# These definitions are for handling dependencies in the out of kernel build.
-
-PROGS = dristat drmstat
-
-CLEANFILES = *.o *.ko $(PROGS) .depend .*.flags .*.d 
-
-# Build test utilities
-
-PRGCFLAGS = $(CFLAGS) -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \
-           -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \
-           -I. -I../libdrm -I../shared-core
-
-DRMSTATLIBS = -L../libdrm -ldrm
-
-
-programs: $(PROGS)
-
-dristat: dristat.c
-       $(CC) $(PRGCFLAGS) $< -o $@
-
-drmstat: drmstat.c
-       $(CC) $(PRGCFLAGS) $< -o $@ $(DRMSTATLIBS)
-
-clean:
-       rm -f $(CLEANFILES)
-
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644 (file)
index 0000000..dce1754
--- /dev/null
@@ -0,0 +1,29 @@
+AM_CFLAGS = \
+       -I $(top_srcdir)/shared-core \
+       -I $(top_srcdir)/libdrm
+
+noinst_PROGRAMS = \
+       dristat \
+       drmstat
+
+EXTRA_LTLIBRARIES = libdrmtest.la
+libdrmtest_la_SOURCES = \
+       drmtest.c \
+       drmtest.h
+libdrmtest_la_LIBADD = \
+       $(top_builddir)/libdrm/libdrm.la
+
+LDADD = libdrmtest.la
+
+TESTS = auth \
+       openclose \
+       getversion \
+       getclient \
+       getstats \
+       lock \
+       setversion \
+       updatedraw
+
+EXTRA_PROGRAMS = $(TESTS)
+CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES)
+
diff --git a/tests/auth.c b/tests/auth.c
new file mode 100644 (file)
index 0000000..9b6fca9
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <limits.h>
+#include "drmtest.h"
+
+enum auth_event {
+       SERVER_READY,
+       CLIENT_MAGIC,
+       CLIENT_DONE,
+};
+
+int commfd[2];
+
+static void wait_event(int pipe, enum auth_event expected_event)
+{
+       int ret;
+       enum auth_event event;
+       unsigned char in;
+
+       ret = read(commfd[pipe], &in, 1);
+       if (ret == -1)
+               err(1, "read error");
+       event = in;
+
+       if (event != expected_event)
+               errx(1, "unexpected event: %d\n", event);
+}
+
+static void
+send_event(int pipe, enum auth_event send_event)
+{
+       int ret;
+       unsigned char event;
+
+       event = send_event;
+       ret = write(commfd[pipe], &event, 1);
+       if (ret == -1)
+               err(1, "failed to send event %d", event);
+}
+
+static void client()
+{
+       struct drm_auth auth;
+       int drmfd, ret;
+
+       /* XXX: Should make sure we open the same DRM as the master */
+       wait_event(0, SERVER_READY);
+
+       drmfd = drm_open_any();
+
+       /* Get a client magic number and pass it to the master for auth. */
+       auth.magic = 0; /* Quiet valgrind */
+       ret = ioctl(drmfd, DRM_IOCTL_GET_MAGIC, &auth);
+       if (ret == -1)
+               err(1, "Couldn't get client magic");
+       send_event(0, CLIENT_MAGIC);
+       ret = write(commfd[0], &auth.magic, sizeof(auth.magic));
+       if (ret == -1)
+               err(1, "Couldn't write auth data");
+
+       /* Signal that the client is completely done. */
+       send_event(0, CLIENT_DONE);
+}
+
+static void server()
+{
+       int drmfd, ret;
+       struct drm_auth auth;
+
+       drmfd = drm_open_any_master();
+
+       auth.magic = 0xd0d0d0d0;
+       ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth);
+       if (ret != -1 || errno != EINVAL)
+               errx(1, "Authenticating bad magic succeeded\n");
+
+       send_event(1, SERVER_READY);
+
+       wait_event(1, CLIENT_MAGIC);
+       ret = read(commfd[1], &auth.magic, sizeof(auth.magic));
+       if (ret == -1)
+               err(1, "Failure to read client magic");
+
+       ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth);
+       if (ret == -1)
+               err(1, "Failure to authenticate client magic\n");
+
+       wait_event(1, CLIENT_DONE);
+}
+
+/**
+ * Checks DRM authentication mechanisms.
+ */
+int main(int argc, char **argv)
+{
+       int ret;
+
+       ret = pipe(commfd);
+       if (ret == -1)
+               err(1, "Couldn't create pipe");
+
+       ret = fork();
+       if (ret == -1)
+               err(1, "failure to fork client");
+       if (ret == 0)
+               client();
+       else
+               server();
+
+       return 0;
+}
+
diff --git a/tests/drmtest.c b/tests/drmtest.c
new file mode 100644 (file)
index 0000000..cae99a0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <fcntl.h>
+#include "drmtest.h"
+
+/** Open the first DRM device we can find, searching up to 16 device nodes */
+int drm_open_any(void)
+{
+       char name[20];
+       int i, fd;
+
+       for (i = 0; i < 16; i++) {
+               sprintf(name, "/dev/dri/card%d", i);
+               fd = open(name, O_RDWR);
+               if (fd != -1)
+                       return fd;
+       }
+       abort();
+}
+
+
+/**
+ * Open the first DRM device we can find where we end up being the master.
+ */
+int drm_open_any_master(void)
+{
+       char name[20];
+       int i, fd;
+
+       for (i = 0; i < 16; i++) {
+               drm_client_t client;
+               int ret;
+
+               sprintf(name, "/dev/dri/card%d", i);
+               fd = open(name, O_RDWR);
+               if (fd == -1)
+                       continue;
+
+               /* Check that we're the only opener and authed. */
+               client.idx = 0;
+               ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+               assert (ret == 0);
+               if (!client.auth) {
+                       close(fd);
+                       continue;
+               }
+               client.idx = 1;
+               ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+               if (ret != -1 || errno != EINVAL) {
+                       close(fd);
+                       continue;
+               }
+               return fd;
+       }
+       fprintf(stderr, "Couldn't find an un-controlled DRM device\n");
+       abort();
+}
+
diff --git a/tests/drmtest.h b/tests/drmtest.h
new file mode 100644 (file)
index 0000000..afa0df4
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "xf86drm.h"
+
+int drm_open_any(void);
+int drm_open_any_master(void);
diff --git a/tests/getclient.c b/tests/getclient.c
new file mode 100644 (file)
index 0000000..349c16e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <limits.h>
+#include "drmtest.h"
+
+/**
+ * Checks DRM_IOCTL_GET_CLIENT.
+ */
+int main(int argc, char **argv)
+{
+       int fd, ret;
+       drm_client_t client;
+
+       fd = drm_open_any();
+
+       /* Look for client index 0.  This should exist whether we're operating
+        * on an otherwise unused drm device, or the X Server is running on
+        * the device.
+        */
+       client.idx = 0;
+       ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+       assert(ret == 0);
+
+       /* Look for some absurd client index and make sure it's invalid.
+        * The DRM drivers currently always return data, so the user has
+        * no real way to detect when the list has terminated.  That's bad,
+        * and this test is XFAIL as a result.
+        */
+       client.idx = 0x7fffffff;
+       ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+       assert(ret == -1 && errno == EINVAL);
+
+       close(fd);
+       return 0;
+}
diff --git a/tests/getstats.c b/tests/getstats.c
new file mode 100644 (file)
index 0000000..bd55b12
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <limits.h>
+#include "drmtest.h"
+
+/**
+ * Checks DRM_IOCTL_GET_STATS.
+ *
+ * I don't care too much about the actual contents, just that the kernel
+ * doesn't crash.
+ */
+int main(int argc, char **argv)
+{
+       int fd, ret;
+       drm_stats_t stats;
+
+       fd = drm_open_any();
+
+       ret = ioctl(fd, DRM_IOCTL_GET_STATS, &stats);
+       assert(ret == 0);
+
+       assert(stats.count >= 0);
+
+       close(fd);
+       return 0;
+}
diff --git a/tests/getversion.c b/tests/getversion.c
new file mode 100644 (file)
index 0000000..3de90de
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "drmtest.h"
+
+/**
+ * Checks DRM_IOCTL_GET_VERSION and libdrm's drmGetVersion() interface to it.
+ */
+int main(int argc, char **argv)
+{
+       int fd;
+       drmVersionPtr v;
+
+       fd = drm_open_any();
+       v = drmGetVersion(fd);
+       assert(strlen(v->name) != 0);
+       assert(strlen(v->date) != 0);
+       assert(strlen(v->desc) != 0);
+       assert(v->version_major >= 1);
+       drmFree(v);
+       close(fd);
+       return 0;
+}
diff --git a/tests/lock.c b/tests/lock.c
new file mode 100644 (file)
index 0000000..86caa28
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file lock.c
+ * Tests various potential failures of the DRM locking mechanisms
+ */
+
+#include <limits.h>
+#include "drmtest.h"
+
+enum auth_event {
+       SERVER_READY,
+       CLIENT_MAGIC,
+       SERVER_LOCKED,
+       CLIENT_LOCKED,
+};
+
+int commfd[2];
+unsigned int lock1 = 0x00001111;
+unsigned int lock2 = 0x00002222;
+
+/* return time in milliseconds */
+static unsigned int
+get_millis()
+{
+       struct timeval tv;
+
+       gettimeofday(&tv, NULL);
+       return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+static void
+wait_event(int pipe, enum auth_event expected_event)
+{
+       int ret;
+       enum auth_event event;
+       unsigned char in;
+
+       ret = read(commfd[pipe], &in, 1);
+       if (ret == -1)
+               err(1, "read error");
+       event = in;
+
+       if (event != expected_event)
+               errx(1, "unexpected event: %d\n", event);
+}
+
+static void
+send_event(int pipe, enum auth_event send_event)
+{
+       int ret;
+       unsigned char event;
+
+       event = send_event;
+       ret = write(commfd[pipe], &event, 1);
+       if (ret == -1)
+               err(1, "failed to send event %d", event);
+}
+
+static void
+client_auth(int drmfd)
+{
+       struct drm_auth auth;
+       int ret;
+
+       /* Get a client magic number and pass it to the master for auth. */
+       ret = ioctl(drmfd, DRM_IOCTL_GET_MAGIC, &auth);
+       if (ret == -1)
+               err(1, "Couldn't get client magic");
+       send_event(0, CLIENT_MAGIC);
+       ret = write(commfd[0], &auth.magic, sizeof(auth.magic));
+       if (ret == -1)
+               err(1, "Couldn't write auth data");
+}
+
+static void
+server_auth(int drmfd)
+{
+       struct drm_auth auth;
+       int ret;
+
+       send_event(1, SERVER_READY);
+       wait_event(1, CLIENT_MAGIC);
+       ret = read(commfd[1], &auth.magic, sizeof(auth.magic));
+       if (ret == -1)
+               err(1, "Failure to read client magic");
+
+       ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth);
+       if (ret == -1)
+               err(1, "Failure to authenticate client magic\n");
+}
+
+/** Tests that locking is successful in normal conditions */
+static void
+test_lock_unlock(int drmfd)
+{
+       int ret;
+
+       ret = drmGetLock(drmfd, lock1, 0);
+       if (ret != 0)
+               err(1, "Locking failed");
+       ret = drmUnlock(drmfd, lock1);
+       if (ret != 0)
+               err(1, "Unlocking failed");
+}
+
+/** Tests that unlocking the lock while it's not held works correctly */
+static void
+test_unlock_unlocked(int drmfd)
+{
+       int ret;
+
+       ret = drmUnlock(drmfd, lock1);
+       if (ret == 0)
+               err(1, "Unlocking unlocked lock succeeded");
+}
+
+/** Tests that unlocking a lock held by another context fails appropriately */
+static void
+test_unlock_unowned(int drmfd)
+{
+       int ret;
+
+       ret = drmGetLock(drmfd, lock1, 0);
+       assert(ret == 0);
+       ret = drmUnlock(drmfd, lock2);
+       if (ret == 0)
+               errx(1, "Unlocking other context's lock succeeded");
+       ret = drmUnlock(drmfd, lock1);
+       assert(ret == 0);
+}
+
+/**
+ * Tests that an open/close by the same process doesn't result in the lock
+ * being dropped.
+ */
+static void test_open_close_locked(drmfd)
+{
+       int ret, tempfd;
+
+       ret = drmGetLock(drmfd, lock1, 0);
+       assert(ret == 0);
+       /* XXX: Need to make sure that this is the same device as drmfd */
+       tempfd = drm_open_any();
+       close(tempfd);
+       ret = drmUnlock(drmfd, lock1);
+       if (ret != 0)
+               errx(1, "lock lost during open/close by same pid");
+}
+
+static void client()
+{
+       int drmfd, ret;
+       unsigned int time;
+
+       wait_event(0, SERVER_READY);
+
+       /* XXX: Should make sure we open the same DRM as the master */
+       drmfd = drm_open_any();
+
+       client_auth(drmfd);
+
+       /* Wait for the server to grab the lock, then grab it ourselves (to
+        * contest it).  Hopefully we hit it within the window of when the
+        * server locks.
+        */
+       wait_event(0, SERVER_LOCKED);
+       ret = drmGetLock(drmfd, lock2, 0);
+       time = get_millis();
+       if (ret != 0)
+               err(1, "Failed to get lock on client\n");
+       drmUnlock(drmfd, lock2);
+
+       /* Tell the server that our locking completed, and when it did */
+       send_event(0, CLIENT_LOCKED);
+       ret = write(commfd[0], &time, sizeof(time));
+
+       close(drmfd);
+       exit(0);
+}
+
+static void server()
+{
+       int drmfd, tempfd, ret;
+       unsigned int client_time, unlock_time;
+
+       drmfd = drm_open_any_master();
+
+       test_lock_unlock(drmfd);
+       test_unlock_unlocked(drmfd);
+       test_unlock_unowned(drmfd);
+       test_open_close_locked(drmfd);
+
+       /* Perform the authentication sequence with the client. */
+       server_auth(drmfd);
+
+       /* Now, test that the client attempting to lock while the server
+        * holds the lock works correctly.
+        */
+       ret = drmGetLock(drmfd, lock1, 0);
+       assert(ret == 0);
+       send_event(1, SERVER_LOCKED);
+       /* Wait a while for the client to do its thing */
+       sleep(1);
+       ret = drmUnlock(drmfd, lock1);
+       assert(ret == 0);
+       unlock_time = get_millis();
+
+       wait_event(1, CLIENT_LOCKED);
+       ret = read(commfd[1], &client_time, sizeof(client_time));
+       if (ret == -1)
+               err(1, "Failure to read client magic");
+
+       if (client_time < unlock_time)
+               errx(1, "Client took lock before server released it");
+
+       close(drmfd);
+}
+
+int main(int argc, char **argv)
+{
+       int ret;
+
+
+       ret = pipe(commfd);
+       if (ret == -1)
+               err(1, "Couldn't create pipe");
+
+       ret = fork();
+       if (ret == -1)
+               err(1, "failure to fork client");
+       if (ret == 0)
+               client();
+       else
+               server();
+
+       return 0;
+}
+
diff --git a/tests/mode/Makefile b/tests/mode/Makefile
new file mode 100644 (file)
index 0000000..205c2ba
--- /dev/null
@@ -0,0 +1,11 @@
+
+all: modetest
+
+#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \
+#        -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \
+
+modetest: modetest.c
+       @gcc -o modetest -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modetest.c 
+
+clean:
+       @rm -f modetest
diff --git a/tests/mode/modetest.c b/tests/mode/modetest.c
new file mode 100644 (file)
index 0000000..bf1a516
--- /dev/null
@@ -0,0 +1,337 @@
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+const char* getConnectionText(drmModeConnection conn)
+{
+       switch (conn) {
+       case DRM_MODE_CONNECTED:
+               return "connected";
+       case DRM_MODE_DISCONNECTED:
+               return "disconnected";
+       default:
+               return "unknown";
+       }
+
+}
+
+struct drm_mode_modeinfo* findMode(drmModeResPtr res, uint32_t id)
+{
+       int i;
+       for (i = 0; i < res->count_modes; i++) {
+               if (res->modes[i].id == id)
+                       return &res->modes[i];
+       }
+
+       return 0;
+}
+
+int printMode(struct drm_mode_modeinfo *mode)
+{
+#if 0
+       printf("Mode: %s\n", mode->name);
+       printf("\tclock       : %i\n", mode->clock);
+       printf("\thdisplay    : %i\n", mode->hdisplay);
+       printf("\thsync_start : %i\n", mode->hsync_start);
+       printf("\thsync_end   : %i\n", mode->hsync_end);
+       printf("\thtotal      : %i\n", mode->htotal);
+       printf("\thskew       : %i\n", mode->hskew);
+       printf("\tvdisplay    : %i\n", mode->vdisplay);
+       printf("\tvsync_start : %i\n", mode->vsync_start);
+       printf("\tvsync_end   : %i\n", mode->vsync_end);
+       printf("\tvtotal      : %i\n", mode->vtotal);
+       printf("\tvscan       : %i\n", mode->vscan);
+       printf("\tvrefresh    : %i\n", mode->vrefresh);
+       printf("\tflags       : %i\n", mode->flags);
+#else
+       printf("Mode: %i \"%s\" %ix%i %.0f\n", mode->id, mode->name,
+               mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0);
+#endif
+       return 0;
+}
+
+int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
+{
+       int i = 0;
+       struct drm_mode_modeinfo *mode = NULL;
+
+       printf("Output: %s\n", output->name);
+       printf("\tid           : %i\n", id);
+       printf("\tcrtc id      : %i\n", output->crtc);
+       printf("\tconn         : %s\n", getConnectionText(output->connection));
+       printf("\tsize         : %ix%i (mm)\n", output->mmWidth, output->mmHeight);
+       printf("\tcount_crtcs  : %i\n", output->count_crtcs);
+       printf("\tcrtcs        : %i\n", output->crtcs);
+       printf("\tcount_clones : %i\n", output->count_clones);
+       printf("\tclones       : %i\n", output->clones);
+       printf("\tcount_modes  : %i\n", output->count_modes);
+
+       for (i = 0; i < output->count_modes; i++) {
+               mode = findMode(res, output->modes[i]);
+
+               if (mode)
+                       printf("\t\tmode: %i \"%s\" %ix%i %.0f\n", mode->id, mode->name,
+                               mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0);
+               else
+                       printf("\t\tmode: Invalid mode %i\n", output->modes[i]);
+       }
+
+       return 0;
+}
+
+int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id)
+{
+       printf("Crtc\n");
+       printf("\tid           : %i\n", id);
+       printf("\tx            : %i\n", crtc->x);
+       printf("\ty            : %i\n", crtc->y);
+       printf("\twidth        : %i\n", crtc->width);
+       printf("\theight       : %i\n", crtc->height);
+       printf("\tmode         : %i\n", crtc->mode);
+       printf("\tnum outputs  : %i\n", crtc->count_outputs);
+       printf("\toutputs      : %i\n", crtc->outputs);
+       printf("\tnum possible : %i\n", crtc->count_possibles);
+       printf("\tpossibles    : %i\n", crtc->possibles);
+
+       return 0;
+}
+
+int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb)
+{
+       printf("Framebuffer\n");
+       printf("\thandle    : %i\n", fb->handle);
+       printf("\twidth     : %i\n", fb->width);
+       printf("\theight    : %i\n", fb->height);
+       printf("\tpitch     : %i\n", fb->pitch);;
+       printf("\tbpp       : %i\n", fb->bpp);
+       printf("\tdepth     : %i\n", fb->depth);
+       printf("\tbuffer_id : %i\n", fb->buffer_id);
+
+       return 0;
+}
+
+int printRes(int fd, drmModeResPtr res)
+{
+       int i;
+       drmModeOutputPtr output;
+       drmModeCrtcPtr crtc;
+       drmModeFBPtr fb;
+
+       for (i = 0; i < res->count_modes; i++) {
+               printMode(&res->modes[i]);
+       }
+
+       for (i = 0; i < res->count_outputs; i++) {
+               output = drmModeGetOutput(fd, res->outputs[i]);
+
+               if (!output)
+                       printf("Could not get output %i\n", i);
+               else {
+                       printOutput(fd, res, output, res->outputs[i]);
+                       drmModeFreeOutput(output);
+               }
+       }
+
+       for (i = 0; i < res->count_crtcs; i++) {
+               crtc = drmModeGetCrtc(fd, res->crtcs[i]);
+
+               if (!crtc)
+                       printf("Could not get crtc %i\n", i);
+               else {
+                       printCrtc(fd, res, crtc, res->crtcs[i]);
+                       drmModeFreeCrtc(crtc);
+               }
+       }
+
+       for (i = 0; i < res->count_fbs; i++) {
+               fb = drmModeGetFB(fd, res->fbs[i]);
+
+               if (!fb)
+                       printf("Could not get fb %i\n", res->fbs[i]);
+               else {
+                       printFrameBuffer(fd, res, fb);
+                       drmModeFreeFB(fb);
+               }
+       }
+
+       return 0;
+}
+
+static struct drm_mode_modeinfo mode = {
+       .name = "Test mode",
+       .clock = 25200,
+       .hdisplay = 640,
+       .hsync_start = 656,
+       .hsync_end = 752,
+       .htotal = 800,
+       .hskew = 0,
+       .vdisplay = 480,
+       .vsync_start = 490,
+       .vsync_end = 492,
+       .vtotal = 525,
+       .vscan = 0,
+       .vrefresh = 60000, /* vertical refresh * 1000 */
+       .flags = 10,
+};
+
+int testMode(int fd, drmModeResPtr res)
+{
+       uint32_t output = res->outputs[0];
+       uint32_t newMode = 0;
+       int ret = 0;
+       int error = 0;
+
+       printf("Test: adding mode to output %i\n", output);
+
+       /* printMode(&mode); */
+
+       printf("\tAdding mode\n");
+       newMode = drmModeAddMode(fd, &mode);
+       if (!newMode)
+               goto err;
+
+       printf("\tAttaching mode %i to output %i\n", newMode, output);
+
+       ret = drmModeAttachMode(fd, output, newMode);
+
+       if (ret)
+               goto err_mode;
+
+       printf("\tDetaching mode %i from output %i\n", newMode, output);
+       ret = drmModeDetachMode(fd, output, newMode);
+
+       if (ret)
+               goto err_mode;
+
+       printf("\tRemoveing new mode %i\n", newMode);
+       ret = drmModeRmMode(fd, newMode);
+       if (ret)
+               goto err;
+
+       return 0;
+
+err_mode:
+       error = drmModeRmMode(fd, newMode);
+
+err:
+       printf("\tFailed\n");
+
+       if (error)
+               printf("\tFailed to delete mode %i\n", newMode);
+
+       return 1;
+}
+
+/*
+int testFrameBufferGet(int fd, uint32_t fb)
+{
+       drmModeFBPtr frame;
+
+       printf("Test: get framebuffer %i\n", fb);
+
+       frame = drmModeGetFB(fd, fb);
+
+       if (!frame) {
+               printf("\tFailed\n");
+       } else {
+               printFrameBuffer(fd, frame);
+               drmModeFreeFB(frame);
+       }
+
+       return 0;
+}
+*/
+
+int testFrameBufferAdd(int fd, drmModeResPtr res)
+{
+       uint32_t fb = 0;
+       int ret = 0;
+       drmModeFBPtr frame = 0;
+       drmBO bo;
+
+       printf("Test: adding framebuffer\n");
+
+       printf("\tCreating BO\n");
+
+       /* TODO */
+       ret = 1;
+       if (ret)
+               goto err;
+
+       printf("\tAdding FB\n");
+       ret = drmModeAddFB(fd, 640, 480, 32, 8, 0, &bo, &fb);
+       if (ret)
+               goto err_bo;
+
+       frame = drmModeGetFB(fd, fb);
+
+       if (!frame) {
+               printf("Couldn't retrive created framebuffer\n");
+       } else {
+               printFrameBuffer(fd, res, frame);
+               drmModeFreeFB(frame);
+       }
+
+       printf("\tRemoveing FB\n");
+
+       ret = drmModeRmFB(fd, fb);
+
+       if (ret) {
+               printf("\tFailed this shouldn't happen!\n");
+               goto err_bo;
+       }
+
+       printf("\tRemoveing BO\n");
+
+       ret = drmBODestroy(fb, &bo);
+
+       return 0;
+       
+err_bo:
+       drmBODestroy(fd, &bo);
+
+err:
+       printf("\tFailed\n");
+
+       return 1;
+}
+
+
+int main(int argc, char **argv)
+{
+       int fd;
+       const char *driver = "i915"; /* hardcoded for now */
+       drmModeResPtr res;
+
+       printf("Starting test\n");
+
+       fd = drmOpen(driver, NULL);
+
+       if (fd < 0) {
+               printf("Failed to open the card fb\n");
+               return 1;
+       }
+
+       res = drmModeGetResources(fd);
+       if (res == 0) {
+               printf("Failed to get resources from card\n");
+               drmClose(fd);
+               return 1;
+       }
+
+       printRes(fd, res);
+
+       testMode(fd, res);
+
+       testFrameBufferAdd(fd, res);
+
+       drmModeFreeResources(res);
+       printf("Ok\n");
+
+       return 0;
+}
diff --git a/tests/mode/test b/tests/mode/test
new file mode 100755 (executable)
index 0000000..fa155f4
--- /dev/null
@@ -0,0 +1 @@
+LD_PRELOAD=../../libdrm/.libs/libdrm.so ./modetest
diff --git a/tests/openclose.c b/tests/openclose.c
new file mode 100644 (file)
index 0000000..946a445
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "drmtest.h"
+
+int main(int argc, char **argv)
+{
+       int fd;
+
+       fd = drm_open_any();
+       close(fd);
+       return 0;
+}
diff --git a/tests/setversion.c b/tests/setversion.c
new file mode 100644 (file)
index 0000000..f4bfbfb
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <limits.h>
+#include "drmtest.h"
+
+/**
+ * Checks DRM_IOCTL_SET_VERSION.
+ *
+ * This tests that we can get the actual version out, and that setting invalid
+ * major/minor numbers fails appropriately.  It does not check the actual
+ * behavior differenses resulting from an increased DI version.
+ */
+int main(int argc, char **argv)
+{
+       int fd, ret;
+       drm_set_version_t sv, version;
+
+       fd = drm_open_any_master();
+
+       /* First, check that we can get the DD/DI versions. */
+       memset(&version, 0, sizeof(version));
+       version.drm_di_major = -1;
+       version.drm_di_minor = -1;
+       version.drm_dd_major = -1;
+       version.drm_dd_minor = -1;
+       ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &version);
+       assert(ret == 0);
+       assert(version.drm_di_major != -1);
+       assert(version.drm_di_minor != -1);
+       assert(version.drm_dd_major != -1);
+       assert(version.drm_dd_minor != -1);
+
+       /* Check that an invalid DI major fails */
+       sv = version;
+       sv.drm_di_major++;
+       ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv);
+       assert(ret == -1 && errno == EINVAL);
+
+       /* Check that an invalid DI minor fails */
+       sv = version;
+       sv.drm_di_major++;
+       ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv);
+       assert(ret == -1 && errno == EINVAL);
+
+       /* Check that an invalid DD major fails */
+       sv = version;
+       sv.drm_dd_major++;
+       ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv);
+       assert(ret == -1 && errno == EINVAL);
+
+       /* Check that an invalid DD minor fails */
+       sv = version;
+       sv.drm_dd_minor++;
+       ret = ioctl(fd, DRM_IOCTL_SET_VERSION, &sv);
+       assert(ret == -1 && errno == EINVAL);
+
+       close(fd);
+       return 0;
+}
diff --git a/tests/updatedraw.c b/tests/updatedraw.c
new file mode 100644 (file)
index 0000000..2f22fef
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "drmtest.h"
+
+static void
+set_draw_cliprects_empty(int fd, int drawable)
+{
+       int ret;
+       struct drm_update_draw update;
+
+       update.handle = drawable;
+       update.type = DRM_DRAWABLE_CLIPRECTS;
+       update.num = 0;
+       update.data = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update);
+       assert(ret == 0);
+}
+
+static void
+set_draw_cliprects_empty_fail(int fd, int drawable)
+{
+       int ret;
+       struct drm_update_draw update;
+
+       update.handle = drawable;
+       update.type = DRM_DRAWABLE_CLIPRECTS;
+       update.num = 0;
+       update.data = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update);
+       assert(ret == -1 && errno == EINVAL);
+}
+
+static void
+set_draw_cliprects_2(int fd, int drawable)
+{
+       int ret;
+       struct drm_update_draw update;
+       drm_clip_rect_t rects[2];
+
+       rects[0].x1 = 0;
+       rects[0].y1 = 0;
+       rects[0].x2 = 10;
+       rects[0].y2 = 10;
+
+       rects[1].x1 = 10;
+       rects[1].y1 = 10;
+       rects[1].x2 = 20;
+       rects[1].y2 = 20;
+
+       update.handle = drawable;
+       update.type = DRM_DRAWABLE_CLIPRECTS;
+       update.num = 2;
+       update.data = (unsigned long long)(uintptr_t)&rects;
+
+       ret = ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update);
+       assert(ret == 0);
+}
+
+static int add_drawable(int fd)
+{
+       drm_draw_t drawarg;
+       int ret;
+
+       /* Create a drawable.
+        * IOCTL_ADD_DRAW is RDWR, though it should really just be RD
+        */
+       drawarg.handle = 0;
+       ret = ioctl(fd, DRM_IOCTL_ADD_DRAW, &drawarg);
+       assert(ret == 0);
+       return drawarg.handle;
+}
+
+static int rm_drawable(int fd, int drawable, int fail)
+{
+       drm_draw_t drawarg;
+       int ret;
+
+       /* Create a drawable.
+        * IOCTL_ADD_DRAW is RDWR, though it should really just be RD
+        */
+       drawarg.handle = drawable;
+       ret = ioctl(fd, DRM_IOCTL_RM_DRAW, &drawarg);
+       if (!fail)
+               assert(ret == 0);
+       else
+               assert(ret == -1 && errno == EINVAL);
+
+       return drawarg.handle;
+}
+
+/**
+ * Tests drawable management: adding, removing, and updating the cliprects of
+ * drawables.
+ */
+int main(int argc, char **argv)
+{
+       int fd, ret, d1, d2;
+
+       fd = drm_open_any_master();
+
+       d1 = add_drawable(fd);
+       d2 = add_drawable(fd);
+       /* Do a series of cliprect updates */
+       set_draw_cliprects_empty(fd, d1);
+       set_draw_cliprects_empty(fd, d2);
+       set_draw_cliprects_2(fd, d1);
+       set_draw_cliprects_empty(fd, d1);
+
+       /* Remove our drawables */
+       rm_drawable(fd, d1, 0);
+       rm_drawable(fd, d2, 0);
+
+       /* Check that removing an unknown drawable returns error */
+       rm_drawable(fd, 0x7fffffff, 1);
+
+       /* Attempt to set cliprects on a nonexistent drawable */
+       set_draw_cliprects_empty_fail(fd, d1);
+
+       close(fd);
+       return 0;
+}