Merge refs/heads/upstream from master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
authorLinus Torvalds <torvalds@g5.osdl.org>
Tue, 30 Aug 2005 18:16:30 +0000 (11:16 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 30 Aug 2005 18:16:30 +0000 (11:16 -0700)
146 files changed:
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
arch/i386/pci/common.c
arch/i386/pci/i386.c
arch/ppc/syslib/m8xx_setup.c
drivers/char/drm/Kconfig
drivers/char/drm/Makefile
drivers/char/drm/drm.h
drivers/char/drm/drmP.h
drivers/char/drm/drm_agpsupport.c
drivers/char/drm/drm_bufs.c
drivers/char/drm/drm_context.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_fops.c
drivers/char/drm/drm_ioctl.c
drivers/char/drm/drm_memory.c
drivers/char/drm/drm_pci.c
drivers/char/drm/drm_pciids.h
drivers/char/drm/drm_proc.c
drivers/char/drm/drm_scatter.c
drivers/char/drm/drm_stub.c
drivers/char/drm/drm_vm.c
drivers/char/drm/ffb_drv.c
drivers/char/drm/gamma_context.h [deleted file]
drivers/char/drm/gamma_dma.c [deleted file]
drivers/char/drm/gamma_drm.h [deleted file]
drivers/char/drm/gamma_drv.c [deleted file]
drivers/char/drm/gamma_drv.h [deleted file]
drivers/char/drm/gamma_lists.h [deleted file]
drivers/char/drm/gamma_lock.h [deleted file]
drivers/char/drm/gamma_old_dma.h [deleted file]
drivers/char/drm/i810_dma.c
drivers/char/drm/i810_drv.c
drivers/char/drm/i810_drv.h
drivers/char/drm/i830_dma.c
drivers/char/drm/i830_drv.c
drivers/char/drm/i830_drv.h
drivers/char/drm/i915_dma.c
drivers/char/drm/i915_drv.c
drivers/char/drm/i915_drv.h
drivers/char/drm/mga_dma.c
drivers/char/drm/mga_drm.h
drivers/char/drm/mga_drv.c
drivers/char/drm/mga_drv.h
drivers/char/drm/mga_ioc32.c
drivers/char/drm/mga_irq.c
drivers/char/drm/mga_state.c
drivers/char/drm/mga_warp.c
drivers/char/drm/r128_cce.c
drivers/char/drm/r128_drm.h
drivers/char/drm/r300_cmdbuf.c [new file with mode: 0644]
drivers/char/drm/r300_reg.h [new file with mode: 0644]
drivers/char/drm/radeon_cp.c
drivers/char/drm/radeon_drm.h
drivers/char/drm/radeon_drv.c
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_state.c
drivers/char/drm/savage_bci.c [new file with mode: 0644]
drivers/char/drm/savage_drm.h [new file with mode: 0644]
drivers/char/drm/savage_drv.c [new file with mode: 0644]
drivers/char/drm/savage_drv.h [new file with mode: 0644]
drivers/char/drm/savage_state.c [new file with mode: 0644]
drivers/pci/setup-bus.c
fs/jfs/namei.c
include/linux/sound.h
include/sound/ac97_codec.h
include/sound/ad1816a.h
include/sound/asound.h
include/sound/cs46xx.h
include/sound/emu10k1.h
include/sound/gus.h
include/sound/pcm.h
include/sound/version.h
include/sound/ymfpci.h
sound/arm/pxa2xx-ac97.c
sound/core/memalloc.c
sound/core/memory.c
sound/core/oss/pcm_oss.c
sound/core/pcm_compat.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/core/sound_oss.c
sound/core/timer.c
sound/drivers/vx/vx_mixer.c
sound/drivers/vx/vx_pcm.c
sound/isa/ad1816a/ad1816a.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/ad1848/ad1848_lib.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231_lib.c
sound/isa/gus/gus_io.c
sound/isa/opl3sa2.c
sound/isa/sb/sb16_main.c
sound/pci/Kconfig
sound/pci/ac97/Makefile
sound/pci/ac97/ac97_bus.c [new file with mode: 0644]
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ac97_patch.h
sound/pci/ali5451/ali5451.c
sound/pci/atiixp.c
sound/pci/au88x0/au88x0_pcm.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/cmipci.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emupcm.c
sound/pci/ens1370.c
sound/pci/fm801.c
sound/pci/hda/Makefile
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_patch.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cmedia.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_si3054.c [new file with mode: 0644]
sound/pci/ice1712/delta.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1724.c
sound/pci/intel8x0.c
sound/pci/korg1212/korg1212.c
sound/pci/nm256/nm256.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/vx/vxpocket.c
sound/sound_core.c
sound/synth/emux/emux_synth.c
sound/usb/usbaudio.c
sound/usb/usbmidi.c
sound/usb/usx2y/usx2yhwdeppcm.c

index a18ecb92b356798513d417b609ea3952c573f9cc..5c49ba07e709625516952f4d1147f0ae61464a37 100644 (file)
@@ -132,6 +132,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     mpu_irq    - IRQ # for MPU-401 UART (PnP setup)
     dma1       - first DMA # for AD1816A chip (PnP setup)
     dma2       - second DMA # for AD1816A chip (PnP setup)
+    clockfreq   - Clock frequency for AD1816A chip (default = 0, 33000Hz)
     
     Module supports up to 8 cards, autoprobe and PnP.
     
index db0b7d2dc477cfc01aa0bc10282c850e0c10ae9f..0475478c2484c90c3b14b6c74a4a8efe8fa4941b 100644 (file)
@@ -3422,10 +3422,17 @@ struct _snd_pcm_runtime {
 
       <para>
         The <structfield>iface</structfield> field specifies the type of
-      the control,
-      <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>. There are
-      <constant>MIXER</constant>, <constant>PCM</constant>,
-      <constant>CARD</constant>, etc.
+      the control, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
+      is usually <constant>MIXER</constant>.
+      Use <constant>CARD</constant> for global controls that are not
+      logically part of the mixer.
+      If the control is closely associated with some specific device on
+      the sound card, use <constant>HWDEP</constant>,
+      <constant>PCM</constant>, <constant>RAWMIDI</constant>,
+      <constant>TIMER</constant>, or <constant>SEQUENCER</constant>, and
+      specify the device number with the
+      <structfield>device</structfield> and
+      <structfield>subdevice</structfield> fields.
       </para>
 
       <para>
index ade5bc57c34ceffc54c0e1f3a79f52879bc062e9..c96bea14b98f51301c0ec5a2be83d6142a1b646c 100644 (file)
@@ -165,7 +165,6 @@ static int __init pcibios_init(void)
        if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
                pcibios_sort();
 #endif
-       pci_assign_unassigned_resources();
        return 0;
 }
 
index 93a364c82150cddbe8886f8fc35d026120ae0e75..3cc480998a47d4000013cd093aeb0e26b7a5d2ff 100644 (file)
@@ -170,43 +170,26 @@ static void __init pcibios_allocate_resources(int pass)
 static int __init pcibios_assign_resources(void)
 {
        struct pci_dev *dev = NULL;
-       int idx;
-       struct resource *r;
-
-       for_each_pci_dev(dev) {
-               int class = dev->class >> 8;
-
-               /* Don't touch classless devices and host bridges */
-               if (!class || class == PCI_CLASS_BRIDGE_HOST)
-                       continue;
-
-               for(idx=0; idx<6; idx++) {
-                       r = &dev->resource[idx];
-
-                       /*
-                        *  Don't touch IDE controllers and I/O ports of video cards!
-                        */
-                       if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
-                           (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
-                               continue;
-
-                       /*
-                        *  We shall assign a new address to this resource, either because
-                        *  the BIOS forgot to do so or because we have decided the old
-                        *  address was unusable for some reason.
-                        */
-                       if (!r->start && r->end)
-                               pci_assign_resource(dev, idx);
-               }
+       struct resource *r, *pr;
 
-               if (pci_probe & PCI_ASSIGN_ROMS) {
+       if (!(pci_probe & PCI_ASSIGN_ROMS)) {
+               /* Try to use BIOS settings for ROMs, otherwise let
+                  pci_assign_unassigned_resources() allocate the new
+                  addresses. */
+               for_each_pci_dev(dev) {
                        r = &dev->resource[PCI_ROM_RESOURCE];
-                       r->end -= r->start;
-                       r->start = 0;
-                       if (r->end)
-                               pci_assign_resource(dev, PCI_ROM_RESOURCE);
+                       if (!r->flags || !r->start)
+                               continue;
+                       pr = pci_find_parent_resource(dev, r);
+                       if (!pr || request_resource(pr, r) < 0) {
+                               r->end -= r->start;
+                               r->start = 0;
+                       }
                }
        }
+
+       pci_assign_unassigned_resources();
+
        return 0;
 }
 
index a3702cfe8f7c70ff25c546b76f8b8cddc01e47eb..4c888da89b3c117c4aa709fc94a36b1165a7e150 100644 (file)
@@ -57,7 +57,7 @@ unsigned char __res[sizeof(bd_t)];
 extern void m8xx_ide_init(void);
 
 extern unsigned long find_available_memory(void);
-extern void m8xx_cpm_reset();
+extern void m8xx_cpm_reset(void);
 extern void m8xx_wdt_handler_install(bd_t *bp);
 extern void rpxfb_alloc_pages(void);
 extern void cpm_interrupt_init(void);
@@ -266,8 +266,8 @@ m8xx_show_percpuinfo(struct seq_file *m, int i)
 
        bp = (bd_t *)__res;
 
-       seq_printf(m, "clock\t\t: %ldMHz\n"
-                  "bus clock\t: %ldMHz\n",
+       seq_printf(m, "clock\t\t: %uMHz\n"
+                  "bus clock\t: %uMHz\n",
                   bp->bi_intfreq / 1000000,
                   bp->bi_busfreq / 1000000);
 
index 123417e430405285dbe282fd3a5d99dd0e53910f..56ace9d5e2aef75b4cd095b3424e4cbc00094b23 100644 (file)
@@ -23,13 +23,6 @@ config DRM_TDFX
          Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
          graphics card.  If M is selected, the module will be called tdfx.
 
-config DRM_GAMMA
-       tristate "3dlabs GMX 2000"
-       depends on DRM && BROKEN
-       help
-         This is the old gamma driver, please tell me if it might actually
-         work.
-
 config DRM_R128
        tristate "ATI Rage 128"
        depends on DRM && PCI
@@ -82,7 +75,7 @@ endchoice
 
 config DRM_MGA
        tristate "Matrox g200/g400"
-       depends on DRM && AGP
+       depends on DRM
        help
          Choose this option if you have a Matrox G200, G400 or G450 graphics
          card.  If M is selected, the module will be called mga.  AGP
@@ -103,3 +96,10 @@ config DRM_VIA
          Choose this option if you have a Via unichrome or compatible video
          chipset. If M is selected the module will be called via.
 
+config DRM_SAVAGE
+       tristate "Savage video cards"
+       depends on DRM
+       help
+         Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
+         chipset. If M is selected the module will be called savage.
+
index ddd941045b1f96478742450ae26a1550f941a8df..e41060c76226cd66038d9abfe31b025245b25c72 100644 (file)
@@ -8,16 +8,16 @@ drm-objs    :=        drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
                drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
                drm_sysfs.o
 
-gamma-objs  := gamma_drv.o gamma_dma.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
 i830-objs   := i830_drv.o i830_dma.o i830_irq.o
 i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
-radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
 ffb-objs    := ffb_drv.o ffb_context.o
 sis-objs    := sis_drv.o sis_ds.o sis_mm.o
+savage-objs := savage_drv.o savage_bci.o savage_state.o
 via-objs    := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o
 
 ifeq ($(CONFIG_COMPAT),y)
@@ -29,7 +29,6 @@ i915-objs   += i915_ioc32.o
 endif
 
 obj-$(CONFIG_DRM)      += drm.o
-obj-$(CONFIG_DRM_GAMMA) += gamma.o
 obj-$(CONFIG_DRM_TDFX) += tdfx.o
 obj-$(CONFIG_DRM_R128) += r128.o
 obj-$(CONFIG_DRM_RADEON)+= radeon.o
@@ -39,5 +38,7 @@ obj-$(CONFIG_DRM_I830)        += i830.o
 obj-$(CONFIG_DRM_I915)  += i915.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
 obj-$(CONFIG_DRM_SIS)   += sis.o
+obj-$(CONFIG_DRM_SAVAGE)+= savage.o
 obj-$(CONFIG_DRM_VIA)  +=via.o
 
+
index e8371dd87fbca0867953f1e53c07b5ec8b5a19d5..fc6598a81acdd5888fd11893f941e75fa0d13d70 100644 (file)
@@ -98,7 +98,7 @@
 #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
 
 
-typedef unsigned long drm_handle_t;
+typedef unsigned int  drm_handle_t;
 typedef unsigned int  drm_context_t;
 typedef unsigned int  drm_drawable_t;
 typedef unsigned int  drm_magic_t;
@@ -209,7 +209,8 @@ typedef enum drm_map_type {
        _DRM_REGISTERS      = 1,  /**< no caching, no core dump */
        _DRM_SHM            = 2,  /**< shared, cached */
        _DRM_AGP            = 3,  /**< AGP/GART */
-       _DRM_SCATTER_GATHER = 4   /**< Scatter/gather memory for PCI DMA */
+       _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
+       _DRM_CONSISTENT     = 5,  /**< Consistent memory for PCI DMA */
 } drm_map_type_t;
 
 
@@ -368,7 +369,8 @@ typedef struct drm_buf_desc {
        enum {
                _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
                _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
-               _DRM_SG_BUFFER  = 0x04  /**< Scatter/gather memory buffer */
+               _DRM_SG_BUFFER  = 0x04, /**< Scatter/gather memory buffer */
+               _DRM_FB_BUFFER  = 0x08  /**< Buffer is in frame buffer */
        }             flags;
        unsigned long agp_start; /**< 
                                  * Start address of where the AGP buffers are
index 5df09cc8c6db62a7eab1a2a3e1d6061bbb54c997..6f98701dfe15da844eb19aa5e1483f6b73b21a97 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/pci.h>
-#include <linux/version.h>
 #include <linux/jiffies.h>
 #include <linux/smp_lock.h>    /* For (un)lock_kernel */
 #include <linux/mm.h>
@@ -96,6 +95,7 @@
 #define DRIVER_IRQ_SHARED  0x80
 #define DRIVER_IRQ_VBL     0x100
 #define DRIVER_DMA_QUEUE   0x200
+#define DRIVER_FB_DMA      0x400
 
 /***********************************************************************/
 /** \name Begin the DRM... */
 #define pte_unmap(pte)
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
-static inline struct page * vmalloc_to_page(void * vmalloc_addr)
-{
-       unsigned long addr = (unsigned long) vmalloc_addr;
-       struct page *page = NULL;
-       pgd_t *pgd = pgd_offset_k(addr);
-       pmd_t *pmd;
-       pte_t *ptep, pte;
-  
-       if (!pgd_none(*pgd)) {
-               pmd = pmd_offset(pgd, addr);
-               if (!pmd_none(*pmd)) {
-                       preempt_disable();
-                       ptep = pte_offset_map(pmd, addr);
-                       pte = *ptep;
-                       if (pte_present(pte))
-                               page = pte_page(pte);
-                       pte_unmap(ptep);
-                       preempt_enable();
-               }
-       }
-       return page;
-}
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#define DRM_RPR_ARG(vma)
-#else
 #define DRM_RPR_ARG(vma) vma,
-#endif
 
 #define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
 
@@ -474,7 +445,8 @@ typedef struct drm_device_dma {
        unsigned long     byte_count;
        enum {
                _DRM_DMA_USE_AGP = 0x01,
-               _DRM_DMA_USE_SG  = 0x02
+               _DRM_DMA_USE_SG  = 0x02,
+               _DRM_DMA_USE_FB  = 0x04
        } flags;
 
 } drm_device_dma_t;
@@ -525,12 +497,19 @@ typedef struct drm_sigdata {
        drm_hw_lock_t *lock;
 } drm_sigdata_t;
 
+typedef struct drm_dma_handle {
+       dma_addr_t busaddr;
+       void *vaddr;
+       size_t size;
+} drm_dma_handle_t;
+
 /**
  * Mappings list
  */
 typedef struct drm_map_list {
        struct list_head        head;   /**< list head */
        drm_map_t               *map;   /**< mapping */
+       unsigned int user_token;
 } drm_map_list_t;
 
 typedef drm_map_t drm_local_map_t;
@@ -578,7 +557,22 @@ struct drm_driver {
        int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
        void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock);
        int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+       
+       /**
+        * Called by \c drm_device_is_agp.  Typically used to determine if a
+        * card is really attached to AGP or not.
+        *
+        * \param dev  DRM device handle
+        *
+        * \returns
+        * One of three values is returned depending on whether or not the
+        * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
+        * (return of 1), or may or may not be AGP (return of 2).
+        */
+       int (*device_is_agp) (struct drm_device * dev);
+
        /* these have to be filled in */
+  
        int (*postinit)(struct drm_device *, unsigned long flags);
        irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
        void (*irq_preinstall)(struct drm_device *dev);
@@ -722,11 +716,7 @@ typedef struct drm_device {
        int               pci_slot;     /**< PCI slot number */
        int               pci_func;     /**< PCI function number */
 #ifdef __alpha__
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
-       struct pci_controler *hose;
-#else
        struct pci_controller *hose;
-#endif
 #endif
        drm_sg_mem_t      *sg;  /**< Scatter gather memory */
        unsigned long     *ctx_bitmap;  /**< context bitmap */
@@ -736,6 +726,7 @@ typedef struct drm_device {
 
        struct            drm_driver *driver;
        drm_local_map_t   *agp_buffer_map;
+       unsigned int agp_buffer_token;
        drm_head_t primary;             /**< primary screen head */
 } drm_device_t;
 
@@ -806,7 +797,7 @@ extern void      *drm_ioremap_nocache(unsigned long offset, unsigned long size,
                                           drm_device_t *dev);
 extern void         drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
 
-extern DRM_AGP_MEM   *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type);
+extern DRM_AGP_MEM   *drm_alloc_agp(drm_device_t *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);
@@ -881,11 +872,19 @@ extern int             drm_lock_free(drm_device_t *dev,
                                    unsigned int context);
 
                                /* 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_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_order( unsigned long size );
-extern int          drm_addmap( struct inode *inode, struct file *filp,
-                                 unsigned int cmd, unsigned long arg );
-extern int          drm_rmmap( 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,
@@ -896,6 +895,10 @@ 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 unsigned long drm_get_resource_start(drm_device_t *dev,
+                                           unsigned int resource);
+extern unsigned long drm_get_resource_len(drm_device_t *dev,
+                                         unsigned int resource);
 
                                /* DMA support (drm_dma.h) */
 extern int          drm_dma_setup(drm_device_t *dev);
@@ -919,15 +922,18 @@ extern void          drm_vbl_send_signals( drm_device_t *dev );
 
                                /* AGP/GART support (drm_agpsupport.h) */
 extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
-extern int            drm_agp_acquire(struct inode *inode, struct file *filp,
-                                      unsigned int cmd, unsigned long arg);
-extern void           drm_agp_do_release(drm_device_t *dev);
-extern int            drm_agp_release(struct inode *inode, struct file *filp,
-                                      unsigned int cmd, unsigned long arg);
-extern int            drm_agp_enable(struct inode *inode, struct file *filp,
-                                     unsigned int cmd, unsigned long arg);
-extern int            drm_agp_info(struct inode *inode, struct file *filp,
-                                   unsigned int cmd, unsigned long arg);
+extern int drm_agp_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(struct inode *inode, struct file *filp,
                                     unsigned int cmd, unsigned long arg);
 extern int            drm_agp_free(struct inode *inode, struct file *filp,
@@ -976,12 +982,10 @@ extern int            drm_ati_pcigart_cleanup(drm_device_t *dev,
                                               unsigned long addr,
                                               dma_addr_t bus_addr);
 
-extern void *drm_pci_alloc(drm_device_t * dev, size_t size,
-                          size_t align, dma_addr_t maxaddr,
-                          dma_addr_t * busaddr);
-
-extern void drm_pci_free(drm_device_t * dev, size_t size,
-                        void *vaddr, dma_addr_t busaddr);
+extern drm_dma_handle_t *drm_pci_alloc(drm_device_t *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);
 
                               /* sysfs support (drm_sysfs.c) */
 struct drm_sysfs_class;
@@ -1012,17 +1016,26 @@ static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_devi
                drm_ioremapfree( map->handle, map->size, dev );
 }
 
-static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned int token)
 {
-       struct list_head *_list;
-       list_for_each( _list, &dev->maplist->head ) {
-               drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
-               if ( _entry->map &&
-                    _entry->map->offset == offset ) {
+       drm_map_list_t *_entry;
+       list_for_each_entry(_entry, &dev->maplist->head, head)
+               if (_entry->user_token == token)
                        return _entry->map;
+       return NULL;
+}
+
+static __inline__ int drm_device_is_agp(drm_device_t *dev)
+{
+       if ( dev->driver->device_is_agp != NULL ) {
+               int err = (*dev->driver->device_is_agp)( dev );
+       
+               if (err != 2) {
+                       return err;
                }
        }
-       return NULL;
+
+       return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
 
 static __inline__ void drm_core_dropmap(struct drm_map *map)
index 8d94c0b5fa44f00c0859b3c63e1103d5876bc6bc..8c215adcb4b2b623e4848b50fba212a66956799a 100644 (file)
@@ -37,7 +37,7 @@
 #if __OS_HAS_AGP
 
 /**
- * AGP information ioctl.
+ * Get AGP information.
  *
  * \param inode device inode.
  * \param filp file pointer.
  * 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(struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
+int drm_agp_info(drm_device_t *dev, drm_agp_info_t *info)
 {
-       drm_file_t       *priv   = filp->private_data;
-       drm_device_t     *dev    = priv->head->dev;
        DRM_AGP_KERN     *kern;
-       drm_agp_info_t   info;
 
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
 
        kern                   = &dev->agp->agp_info;
-       info.agp_version_major = kern->version.major;
-       info.agp_version_minor = kern->version.minor;
-       info.mode              = kern->mode;
-       info.aperture_base     = kern->aper_base;
-       info.aperture_size     = kern->aper_size * 1024 * 1024;
-       info.memory_allowed    = kern->max_memory << PAGE_SHIFT;
-       info.memory_used       = kern->current_memory << PAGE_SHIFT;
-       info.id_vendor         = kern->device->vendor;
-       info.id_device         = kern->device->device;
-
-       if (copy_to_user((drm_agp_info_t __user *)arg, &info, sizeof(info)))
+       info->agp_version_major = kern->version.major;
+       info->agp_version_minor = kern->version.minor;
+       info->mode              = kern->mode;
+       info->aperture_base     = kern->aper_base;
+       info->aperture_size     = kern->aper_size * 1024 * 1024;
+       info->memory_allowed    = kern->max_memory << PAGE_SHIFT;
+       info->memory_used       = kern->current_memory << PAGE_SHIFT;
+       info->id_vendor         = kern->device->vendor;
+       info->id_device         = kern->device->device;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_agp_info);
+
+int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
+                unsigned int cmd, unsigned long arg)
+{
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
+       drm_agp_info_t info;
+       int err;
+
+       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;
 }
 
 /**
- * Acquire the AGP device (ioctl).
+ * Acquire the AGP device.
  *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument.
+ * \param dev DRM device that is to acquire AGP
  * \return zero on success or a negative number on failure. 
  *
  * Verifies the AGP device hasn't been acquired before and calls
- * agp_acquire().
+ * \c agp_backend_acquire.
  */
-int drm_agp_acquire(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+int drm_agp_acquire(drm_device_t *dev)
 {
-       drm_file_t       *priv   = filp->private_data;
-       drm_device_t     *dev    = priv->head->dev;
-
        if (!dev->agp)
                return -ENODEV;
        if (dev->agp->acquired)
@@ -102,9 +107,10 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
        dev->agp->acquired = 1;
        return 0;
 }
+EXPORT_SYMBOL(drm_agp_acquire);
 
 /**
- * Release the AGP device (ioctl).
+ * Acquire the AGP device (ioctl).
  *
  * \param inode device inode.
  * \param filp file pointer.
@@ -112,63 +118,80 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
  * \param arg user argument.
  * \return zero on success or a negative number on failure.
  *
- * Verifies the AGP device has been acquired and calls agp_backend_release().
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
  */
-int drm_agp_release(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg)
 {
-       drm_file_t       *priv   = filp->private_data;
-       drm_device_t     *dev    = priv->head->dev;
+       drm_file_t *priv = filp->private_data;
+       
+       return drm_agp_acquire( (drm_device_t *) priv->head->dev );
+}
 
+/**
+ * Release the AGP device.
+ *
+ * \param dev DRM device that is to release AGP
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired and calls \c agp_backend_release.
+ */
+int drm_agp_release(drm_device_t *dev)
+{
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
        agp_backend_release(dev->agp->bridge);
        dev->agp->acquired = 0;
        return 0;
-
 }
+EXPORT_SYMBOL(drm_agp_release);
 
-/**
- * Release the AGP device.
- *
- * Calls agp_backend_release().
- */
-void drm_agp_do_release(drm_device_t *dev)
+int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
+                         unsigned int cmd, unsigned long arg)
 {
-  agp_backend_release(dev->agp->bridge);
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
+       
+       return drm_agp_release(dev);
 }
 
 /**
  * Enable the AGP bus.
  * 
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg pointer to a drm_agp_mode structure.
+ * \param dev DRM device that has previously acquired AGP.
+ * \param mode Requested AGP mode.
  * \return zero on success or a negative number on failure.
  *
  * Verifies the AGP device has been acquired but not enabled, and calls
- * agp_enable().
+ * \c agp_enable.
  */
-int drm_agp_enable(struct inode *inode, struct file *filp,
-                   unsigned int cmd, unsigned long arg)
+int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
 {
-       drm_file_t       *priv   = filp->private_data;
-       drm_device_t     *dev    = priv->head->dev;
-       drm_agp_mode_t   mode;
-
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
 
-       if (copy_from_user(&mode, (drm_agp_mode_t __user *)arg, sizeof(mode)))
-               return -EFAULT;
-
        dev->agp->mode    = mode.mode;
        agp_enable(dev->agp->bridge, mode.mode);
        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)
+{
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
+       drm_agp_mode_t mode;
+
+
+       if (copy_from_user(&mode, (drm_agp_mode_t __user *) arg, sizeof(mode)))
+               return -EFAULT;
+
+       return drm_agp_enable(dev, mode);
+}
 
 /**
  * Allocate AGP memory.
@@ -206,7 +229,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
        pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
        type = (u32) request.type;
 
-       if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) {
+       if (!(memory = drm_alloc_agp(dev, pages, type))) {
                drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
                return -ENOMEM;
        }
@@ -403,13 +426,8 @@ drm_agp_head_t *drm_agp_init(drm_device_t *dev)
                return NULL;
        }
        head->memory = NULL;
-#if LINUX_VERSION_CODE <= 0x020408
-       head->cant_use_aperture = 0;
-       head->page_mask = ~(0xfff);
-#else
        head->cant_use_aperture = head->agp_info.cant_use_aperture;
        head->page_mask = head->agp_info.page_mask;
-#endif
 
        return head;
 }
@@ -436,6 +454,7 @@ int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start)
                return -EINVAL;
        return agp_bind_memory(handle, start);
 }
+EXPORT_SYMBOL(drm_agp_bind_memory);
 
 /** Calls agp_unbind_memory() */
 int drm_agp_unbind_memory(DRM_AGP_MEM *handle)
index 4c6191d231b8e06e20d876af0287d03df9335153..e0743ebbe4bdfd9f5b32064bed2492279671d3d9 100644 (file)
 #include <linux/vmalloc.h>
 #include "drmP.h"
 
-/**
- * Compute size order.  Returns the exponent of the smaller power of two which
- * is greater or equal to given number.
- * 
- * \param size size.
- * \return order.
- *
- * \todo Can be made faster.
- */
-int drm_order( unsigned long size )
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
 {
-       int order;
-       unsigned long tmp;
+       return pci_resource_start(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_start);
 
-       for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
-               ;
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+{
+       return pci_resource_len(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_len);
 
-       if (size & (size - 1))
-               ++order;
+static drm_local_map_t *drm_find_matching_map(drm_device_t *dev,
+                                             drm_local_map_t *map)
+{
+       struct list_head *list;
 
-       return order;
+       list_for_each(list, &dev->maplist->head) {
+               drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
+               if (entry->map && map->type == entry->map->type &&
+                   entry->map->offset == map->offset) {
+                       return entry->map;
+               }
+       }
+
+       return NULL;
 }
-EXPORT_SYMBOL(drm_order);
 
-#ifdef CONFIG_COMPAT
 /*
- * Used to allocate 32-bit handles for _DRM_SHM regions
- * The 0x10000000 value is chosen to be out of the way of
- * FB/register and GART physical addresses.
+ * Used to allocate 32-bit handles for mappings.
  */
-static unsigned int map32_handle = 0x10000000;
+#define START_RANGE 0x10000000
+#define END_RANGE 0x40000000
+
+#ifdef _LP64
+static __inline__ unsigned int HandleID(unsigned long lhandle, drm_device_t *dev) 
+{
+       static unsigned int map32_handle = START_RANGE;
+       unsigned int hash;
+
+       if (lhandle & 0xffffffff00000000) {
+               hash = map32_handle;
+               map32_handle += PAGE_SIZE;
+               if (map32_handle > END_RANGE)
+                       map32_handle = START_RANGE;
+       } else 
+               hash = lhandle;
+
+       while (1) {
+               drm_map_list_t *_entry;
+               list_for_each_entry(_entry, &dev->maplist->head,head) {
+                       if (_entry->user_token == hash)
+                               break;
+               }
+               if (&_entry->head == &dev->maplist->head)
+                       return hash;
+
+               hash += PAGE_SIZE;
+               map32_handle += PAGE_SIZE;
+       }
+}
+#else
+# define HandleID(x,dev) (unsigned int)(x)
 #endif
 
 /**
@@ -82,25 +114,23 @@ static unsigned int map32_handle = 0x10000000;
  * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
  * applicable and if supported by the kernel.
  */
-int drm_addmap( struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg )
+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)
 {
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->head->dev;
        drm_map_t *map;
-       drm_map_t __user *argp = (void __user *)arg;
        drm_map_list_t *list;
-
-       if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
+       drm_dma_handle_t *dmah;
+       drm_local_map_t *found_map;
 
        map = drm_alloc( sizeof(*map), DRM_MEM_MAPS );
        if ( !map )
                return -ENOMEM;
 
-       if ( copy_from_user( map, argp, sizeof(*map) ) ) {
-               drm_free( map, sizeof(*map), DRM_MEM_MAPS );
-               return -EFAULT;
-       }
+       map->offset = offset;
+       map->size = size;
+       map->flags = flags;
+       map->type = type;
 
        /* Only allow shared memory to be removable since we only keep enough
         * book keeping information about shared memory to allow for removal
@@ -122,7 +152,7 @@ int drm_addmap( struct inode *inode, struct file *filp,
        switch ( map->type ) {
        case _DRM_REGISTERS:
        case _DRM_FRAME_BUFFER:
-#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__)
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
                if ( map->offset + map->size < map->offset ||
                     map->offset < virt_to_phys(high_memory) ) {
                        drm_free( map, sizeof(*map), DRM_MEM_MAPS );
@@ -132,6 +162,24 @@ int drm_addmap( struct inode *inode, struct file *filp,
 #ifdef __alpha__
                map->offset += dev->hose->mem_space->start;
 #endif
+               /* Some drivers preinitialize some maps, without the X Server
+                * needing to be aware of it.  Therefore, we just return success
+                * when the server tries to create a duplicate map.
+                */
+               found_map = drm_find_matching_map(dev, map);
+               if (found_map != NULL) {
+                       if (found_map->size != map->size) {
+                               DRM_DEBUG("Matching maps of type %d with "
+                                  "mismatched sizes, (%ld vs %ld)\n",
+                                   map->type, map->size, found_map->size);
+                               found_map->size = map->size;
+                       }
+
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       *map_ptr = found_map;
+                       return 0;
+               }
+
                if (drm_core_has_MTRR(dev)) {
                        if ( map->type == _DRM_FRAME_BUFFER ||
                             (map->flags & _DRM_WRITE_COMBINING) ) {
@@ -178,9 +226,22 @@ int drm_addmap( struct inode *inode, struct file *filp,
                        drm_free(map, sizeof(*map), DRM_MEM_MAPS);
                        return -EINVAL;
                }
-               map->offset += dev->sg->handle;
+               map->offset += (unsigned long)dev->sg->virtual;
+               break;
+       case _DRM_CONSISTENT: 
+               /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+                * As we're limiting the address to 2^32-1 (or less),
+                * casting it down to 32 bits is no problem, but we
+                * need to point to a 64bit variable first. */
+               dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+               if (!dmah) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -ENOMEM;
+               }
+               map->handle = dmah->vaddr;
+               map->offset = (unsigned long)dmah->busaddr;
+               kfree(dmah);
                break;
-
        default:
                drm_free( map, sizeof(*map), DRM_MEM_MAPS );
                return -EINVAL;
@@ -196,17 +257,56 @@ int drm_addmap( struct inode *inode, struct file *filp,
 
        down(&dev->struct_sem);
        list_add(&list->head, &dev->maplist->head);
-#ifdef CONFIG_COMPAT
-       /* Assign a 32-bit handle for _DRM_SHM mappings */
+       /* Assign a 32-bit handle */
        /* We do it here so that dev->struct_sem protects the increment */
-       if (map->type == _DRM_SHM)
-               map->offset = map32_handle += PAGE_SIZE;
-#endif
+       list->user_token = HandleID(map->type==_DRM_SHM
+                                   ? (unsigned long)map->handle
+                                   : map->offset, dev);
        up(&dev->struct_sem);
 
-       if ( copy_to_user( argp, map, sizeof(*map) ) )
+       *map_ptr = map;
+       return 0;
+}
+EXPORT_SYMBOL(drm_addmap);
+
+int drm_addmap_ioctl(struct inode *inode, struct file *filp,
+                    unsigned int cmd, unsigned long arg)
+{
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
+       drm_map_t map;
+       drm_map_t *map_ptr;
+       drm_map_t __user *argp = (void __user *)arg;
+       int err;
+       unsigned long handle = 0;
+
+       if (!(filp->f_mode & 3))
+               return -EACCES; /* Require read/write */
+
+       if (copy_from_user(& map, argp, sizeof(map))) {
+               return -EFAULT;
+       }
+
+       err = drm_addmap(dev, map.offset, map.size, map.type, map.flags,
+                        &map_ptr);
+
+       if (err) {
+               return err;
+       }
+
+       {
+               drm_map_list_t *_entry;
+               list_for_each_entry(_entry, &dev->maplist->head, head) {
+                       if (_entry->map == map_ptr)
+                               handle = _entry->user_token;
+               }
+               if (!handle)
+                       return -EFAULT;
+       }
+
+       if (copy_to_user(argp, map_ptr, sizeof(*map_ptr)))
                return -EFAULT;
-       if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))
+       if (put_user(handle, &argp->handle))
                return -EFAULT;
        return 0;
 }
@@ -226,81 +326,138 @@ int drm_addmap( struct inode *inode, struct file *filp,
  * its being used, and free any associate resource (such as MTRR's) if it's not
  * being on use.
  *
- * \sa addmap().
+ * \sa drm_addmap
  */
-int drm_rmmap(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
 {
-       drm_file_t      *priv   = filp->private_data;
-       drm_device_t    *dev    = priv->head->dev;
        struct list_head *list;
        drm_map_list_t *r_list = NULL;
-       drm_vma_entry_t *pt, *prev;
-       drm_map_t *map;
+       drm_dma_handle_t dmah;
+
+       /* Find the list entry for the map and remove it */
+       list_for_each(list, &dev->maplist->head) {
+               r_list = list_entry(list, drm_map_list_t, head);
+
+               if (r_list->map == map) {
+                       list_del(list);
+                       drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+                       break;
+               }
+       }
+
+       /* List has wrapped around to the head pointer, or it's empty and we
+        * didn't find anything.
+        */
+       if (list == (&dev->maplist->head)) {
+               return -EINVAL;
+       }
+
+       switch (map->type) {
+       case _DRM_REGISTERS:
+               drm_ioremapfree(map->handle, map->size, dev);
+               /* FALLTHROUGH */
+       case _DRM_FRAME_BUFFER:
+               if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
+                       int retcode;
+                       retcode = mtrr_del(map->mtrr, map->offset,
+                                          map->size);
+                       DRM_DEBUG ("mtrr_del=%d\n", retcode);
+               }
+               break;
+       case _DRM_SHM:
+               vfree(map->handle);
+               break;
+       case _DRM_AGP:
+       case _DRM_SCATTER_GATHER:
+               break;
+       case _DRM_CONSISTENT:
+               dmah.vaddr = map->handle;
+               dmah.busaddr = map->offset;
+               dmah.size = map->size;
+               __drm_pci_free(dev, &dmah);
+               break;
+       }
+       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_rmmap_locked);
+
+int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
+{
+       int ret;
+
+       down(&dev->struct_sem);
+       ret = drm_rmmap_locked(dev, map);
+       up(&dev->struct_sem);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_rmmap);
+
+/* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
+ * the last close of the device, and this is necessary for cleanup when things
+ * exit uncleanly.  Therefore, having userland manually remove mappings seems
+ * like a pointless exercise since they're going away anyway.
+ *
+ * One use case might be after addmap is allowed for normal users for SHM and
+ * 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)
+{
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
        drm_map_t request;
-       int found_maps = 0;
+       drm_local_map_t *map = NULL;
+       struct list_head *list;
+       int ret;
 
-       if (copy_from_user(&request, (drm_map_t __user *)arg,
-                          sizeof(request))) {
+       if (copy_from_user(&request, (drm_map_t __user *)arg, sizeof(request))) {
                return -EFAULT;
        }
 
        down(&dev->struct_sem);
-       list = &dev->maplist->head;
        list_for_each(list, &dev->maplist->head) {
-               r_list = list_entry(list, drm_map_list_t, head);
+               drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
 
-               if(r_list->map &&
-                  r_list->map->offset == (unsigned long) request.handle &&
-                  r_list->map->flags & _DRM_REMOVABLE) break;
+               if (r_list->map &&
+                   r_list->user_token == (unsigned long) request.handle &&
+                   r_list->map->flags & _DRM_REMOVABLE) {
+                       map = r_list->map;
+                       break;
+               }
        }
 
        /* List has wrapped around to the head pointer, or its empty we didn't
         * find anything.
         */
-       if(list == (&dev->maplist->head)) {
+       if (list == (&dev->maplist->head)) {
                up(&dev->struct_sem);
                return -EINVAL;
        }
-       map = r_list->map;
-       list_del(list);
-       drm_free(list, sizeof(*list), DRM_MEM_MAPS);
 
-       for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
-               if (pt->vma->vm_private_data == map) found_maps++;
-       }
+       if (!map)
+               return -EINVAL;
 
-       if(!found_maps) {
-               switch (map->type) {
-               case _DRM_REGISTERS:
-               case _DRM_FRAME_BUFFER:
-                 if (drm_core_has_MTRR(dev)) {
-                               if (map->mtrr >= 0) {
-                                       int retcode;
-                                       retcode = mtrr_del(map->mtrr,
-                                                          map->offset,
-                                                          map->size);
-                                       DRM_DEBUG("mtrr_del = %d\n", retcode);
-                               }
-                       }
-                       drm_ioremapfree(map->handle, map->size, dev);
-                       break;
-               case _DRM_SHM:
-                       vfree(map->handle);
-                       break;
-               case _DRM_AGP:
-               case _DRM_SCATTER_GATHER:
-                       break;
-               }
-               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+       /* Register and framebuffer maps are permanent */
+       if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
+               up(&dev->struct_sem);
+               return 0;
        }
+
+       ret = drm_rmmap_locked(dev, map);
+
        up(&dev->struct_sem);
-       return 0;
+
+       return ret;
 }
 
 /**
  * Cleanup after an error on one of the addbufs() functions.
  *
+ * \param dev DRM device.
  * \param entry buffer entry where the error occurred.
  *
  * Frees any pages and buffers associated with the given entry.
@@ -344,25 +501,19 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
 
 #if __OS_HAS_AGP
 /**
- * Add AGP buffers for DMA transfers (ioctl).
+ * Add AGP buffers for DMA transfers.
  *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg pointer to a drm_buf_desc_t request.
+ * \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.
  * \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.
  */
-static int drm_addbufs_agp( struct inode *inode, struct file *filp,
-                           unsigned int cmd, unsigned long arg )
+int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
 {
-       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;
        drm_buf_entry_t *entry;
        drm_buf_t *buf;
        unsigned long offset;
@@ -376,25 +527,20 @@ static int drm_addbufs_agp( struct inode *inode, struct file *filp,
        int byte_count;
        int i;
        drm_buf_t **temp_buflist;
-       drm_buf_desc_t __user *argp = (void __user *)arg;
 
        if ( !dma ) return -EINVAL;
 
-       if ( copy_from_user( &request, argp,
-                            sizeof(request) ) )
-               return -EFAULT;
-
-       count = request.count;
-       order = drm_order( request.size );
+       count = request->count;
+       order = drm_order(request->size);
        size = 1 << order;
 
-       alignment  = (request.flags & _DRM_PAGE_ALIGN)
+       alignment  = (request->flags & _DRM_PAGE_ALIGN)
                ? PAGE_ALIGN(size) : size;
        page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
        total = PAGE_SIZE << page_order;
 
        byte_count = 0;
-       agp_offset = dev->agp->base + request.agp_start;
+       agp_offset = dev->agp->base + request->agp_start;
 
        DRM_DEBUG( "count:      %d\n",  count );
        DRM_DEBUG( "order:      %d\n",  order );
@@ -508,26 +654,20 @@ static int drm_addbufs_agp( struct inode *inode, struct file *filp,
 
        up( &dev->struct_sem );
 
-       request.count = entry->buf_count;
-       request.size = size;
-
-       if ( copy_to_user( argp, &request, sizeof(request) ) )
-               return -EFAULT;
+       request->count = entry->buf_count;
+       request->size = size;
 
        dma->flags = _DRM_DMA_USE_AGP;
 
        atomic_dec( &dev->buf_alloc );
        return 0;
 }
+EXPORT_SYMBOL(drm_addbufs_agp);
 #endif /* __OS_HAS_AGP */
 
-static int drm_addbufs_pci( struct inode *inode, struct file *filp,
-                           unsigned int cmd, unsigned long arg )
+int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
 {
-       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;
        int count;
        int order;
        int size;
@@ -543,26 +683,22 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp,
        int page_count;
        unsigned long *temp_pagelist;
        drm_buf_t **temp_buflist;
-       drm_buf_desc_t __user *argp = (void __user *)arg;
 
        if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
        if ( !dma ) return -EINVAL;
 
-       if ( copy_from_user( &request, argp, sizeof(request) ) )
-               return -EFAULT;
-
-       count = request.count;
-       order = drm_order( request.size );
+       count = request->count;
+       order = drm_order(request->size);
        size = 1 << order;
 
        DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
-                  request.count, request.size, size,
+                  request->count, request->size, size,
                   order, dev->queue_count );
 
        if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
        if ( dev->queue_count ) return -EBUSY; /* Not while in use */
 
-       alignment = (request.flags & _DRM_PAGE_ALIGN)
+       alignment = (request->flags & _DRM_PAGE_ALIGN)
                ? PAGE_ALIGN(size) : size;
        page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
        total = PAGE_SIZE << page_order;
@@ -740,25 +876,18 @@ static int drm_addbufs_pci( struct inode *inode, struct file *filp,
 
        up( &dev->struct_sem );
 
-       request.count = entry->buf_count;
-       request.size = size;
-
-       if ( copy_to_user( argp, &request, sizeof(request) ) )
-               return -EFAULT;
+       request->count = entry->buf_count;
+       request->size = size;
 
        atomic_dec( &dev->buf_alloc );
        return 0;
 
 }
+EXPORT_SYMBOL(drm_addbufs_pci);
 
-static int drm_addbufs_sg( struct inode *inode, struct file *filp,
-                          unsigned int cmd, unsigned long arg )
+static int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
 {
-       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 __user *argp = (void __user *)arg;
-       drm_buf_desc_t request;
        drm_buf_entry_t *entry;
        drm_buf_t *buf;
        unsigned long offset;
@@ -777,20 +906,17 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
        
        if ( !dma ) return -EINVAL;
 
-       if ( copy_from_user( &request, argp, sizeof(request) ) )
-               return -EFAULT;
-
-       count = request.count;
-       order = drm_order( request.size );
+       count = request->count;
+       order = drm_order(request->size);
        size = 1 << order;
 
-       alignment  = (request.flags & _DRM_PAGE_ALIGN)
+       alignment  = (request->flags & _DRM_PAGE_ALIGN)
                        ? PAGE_ALIGN(size) : size;
        page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
        total = PAGE_SIZE << page_order;
 
        byte_count = 0;
-       agp_offset = request.agp_start;
+       agp_offset = request->agp_start;
 
        DRM_DEBUG( "count:      %d\n",  count );
        DRM_DEBUG( "order:      %d\n",  order );
@@ -848,7 +974,8 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
 
                buf->offset  = (dma->byte_count + offset);
                buf->bus_address = agp_offset + offset;
-               buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+               buf->address = (void *)(agp_offset + offset 
+                                       + (unsigned long)dev->sg->virtual);
                buf->next    = NULL;
                buf->waiting = 0;
                buf->pending = 0;
@@ -905,11 +1032,8 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
 
        up( &dev->struct_sem );
 
-       request.count = entry->buf_count;
-       request.size = size;
-
-       if ( copy_to_user( argp, &request, sizeof(request) ) )
-               return -EFAULT;
+       request->count = entry->buf_count;
+       request->size = size;
 
        dma->flags = _DRM_DMA_USE_SG;
 
@@ -917,6 +1041,161 @@ static int drm_addbufs_sg( struct inode *inode, struct file *filp,
        return 0;
 }
 
+int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request)
+{
+       drm_device_dma_t *dma = dev->dma;
+       drm_buf_entry_t *entry;
+       drm_buf_t *buf;
+       unsigned long offset;
+       unsigned long agp_offset;
+       int count;
+       int order;
+       int size;
+       int alignment;
+       int page_order;
+       int total;
+       int byte_count;
+       int i;
+       drm_buf_t **temp_buflist;
+
+       if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
+               return -EINVAL;
+    
+       if (!dma)
+               return -EINVAL;
+
+       count = request->count;
+       order = drm_order(request->size);
+       size = 1 << order;
+
+       alignment = (request->flags & _DRM_PAGE_ALIGN)
+           ? PAGE_ALIGN(size) : size;
+       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+       total = PAGE_SIZE << page_order;
+
+       byte_count = 0;
+       agp_offset = request->agp_start;
+
+       DRM_DEBUG("count:      %d\n", count);
+       DRM_DEBUG("order:      %d\n", order);
+       DRM_DEBUG("size:       %d\n", size);
+       DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+       DRM_DEBUG("alignment:  %d\n", alignment);
+       DRM_DEBUG("page_order: %d\n", page_order);
+       DRM_DEBUG("total:      %d\n", total);
+
+       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+               return -EINVAL;
+       if (dev->queue_count)
+               return -EBUSY;  /* Not while in use */
+
+       spin_lock(&dev->count_lock);
+       if (dev->buf_use) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       atomic_inc(&dev->buf_alloc);
+       spin_unlock(&dev->count_lock);
+
+       down(&dev->struct_sem);
+       entry = &dma->bufs[order];
+       if (entry->buf_count) {
+               up(&dev->struct_sem);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM; /* May only call once for each order */
+       }
+
+       if (count < 0 || count > 4096) {
+               up(&dev->struct_sem);
+               atomic_dec(&dev->buf_alloc);
+               return -EINVAL;
+       }
+
+       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+                                  DRM_MEM_BUFS);
+       if (!entry->buflist) {
+               up(&dev->struct_sem);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+       entry->buf_size = size;
+       entry->page_order = page_order;
+
+       offset = 0;
+
+       while (entry->buf_count < count) {
+               buf = &entry->buflist[entry->buf_count];
+               buf->idx = dma->buf_count + entry->buf_count;
+               buf->total = alignment;
+               buf->order = order;
+               buf->used = 0;
+
+               buf->offset = (dma->byte_count + offset);
+               buf->bus_address = agp_offset + offset;
+               buf->address = (void *)(agp_offset + offset);
+               buf->next = NULL;
+               buf->waiting = 0;
+               buf->pending = 0;
+               init_waitqueue_head(&buf->dma_wait);
+               buf->filp = NULL;
+
+               buf->dev_priv_size = dev->driver->dev_priv_size;
+               buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+               if (!buf->dev_private) {
+                       /* Set count correctly so we free the proper amount. */
+                       entry->buf_count = count;
+                       drm_cleanup_buf_error(dev, entry);
+                       up(&dev->struct_sem);
+                       atomic_dec(&dev->buf_alloc);
+                       return -ENOMEM;
+               }
+               memset(buf->dev_private, 0, buf->dev_priv_size);
+
+               DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+               offset += alignment;
+               entry->buf_count++;
+               byte_count += PAGE_SIZE << page_order;
+       }
+
+       DRM_DEBUG("byte_count: %d\n", byte_count);
+
+       temp_buflist = drm_realloc(dma->buflist,
+                                  dma->buf_count * sizeof(*dma->buflist),
+                                  (dma->buf_count + entry->buf_count)
+                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
+       if (!temp_buflist) {
+               /* Free the entry because it isn't valid */
+               drm_cleanup_buf_error(dev, entry);
+               up(&dev->struct_sem);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       dma->buflist = temp_buflist;
+
+       for (i = 0; i < entry->buf_count; i++) {
+               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+       }
+
+       dma->buf_count += entry->buf_count;
+       dma->byte_count += byte_count;
+
+       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+       up(&dev->struct_sem);
+
+       request->count = entry->buf_count;
+       request->size = size;
+
+       dma->flags = _DRM_DMA_USE_FB;
+
+       atomic_dec(&dev->buf_alloc);
+       return 0;
+}
+
 /**
  * Add buffers for DMA transfers (ioctl).
  *
@@ -937,6 +1216,7 @@ int drm_addbufs( struct inode *inode, struct file *filp,
        drm_buf_desc_t request;
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->head->dev;
+       int ret;
        
        if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
                return -EINVAL;
@@ -947,13 +1227,23 @@ int drm_addbufs( struct inode *inode, struct file *filp,
 
 #if __OS_HAS_AGP
        if ( request.flags & _DRM_AGP_BUFFER )
-               return drm_addbufs_agp( inode, filp, cmd, arg );
+               ret=drm_addbufs_agp(dev, &request);
        else
 #endif
        if ( request.flags & _DRM_SG_BUFFER )
-               return drm_addbufs_sg( inode, filp, cmd, arg );
+               ret=drm_addbufs_sg(dev, &request);
+       else if ( request.flags & _DRM_FB_BUFFER)
+               ret=drm_addbufs_fb(dev, &request);
        else
-               return drm_addbufs_pci( inode, filp, cmd, arg );
+               ret=drm_addbufs_pci(dev, &request);
+
+       if (ret==0) {
+               if (copy_to_user((void __user *)arg, &request,
+                                sizeof(request))) {
+                       ret = -EFAULT;
+               }
+       }
+       return ret;
 }
 
 
@@ -1196,43 +1486,31 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
                return -EFAULT;
 
        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)) ) {
+               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;
+                       unsigned long token = dev->agp_buffer_token;
 
                        if ( !map ) {
                                retcode = -EINVAL;
                                goto done;
                        }
 
-#if LINUX_VERSION_CODE <= 0x020402
-                       down( &current->mm->mmap_sem );
-#else
                        down_write( &current->mm->mmap_sem );
-#endif
                        virtual = do_mmap( filp, 0, map->size,
                                           PROT_READ | PROT_WRITE,
                                           MAP_SHARED,
-                                          (unsigned long)map->offset );
-#if LINUX_VERSION_CODE <= 0x020402
-                       up( &current->mm->mmap_sem );
-#else
+                                          token );
                        up_write( &current->mm->mmap_sem );
-#endif
                } else {
-#if LINUX_VERSION_CODE <= 0x020402
-                       down( &current->mm->mmap_sem );
-#else
                        down_write( &current->mm->mmap_sem );
-#endif
                        virtual = do_mmap( filp, 0, dma->byte_count,
                                           PROT_READ | PROT_WRITE,
                                           MAP_SHARED, 0 );
-#if LINUX_VERSION_CODE <= 0x020402
-                       up( &current->mm->mmap_sem );
-#else
                        up_write( &current->mm->mmap_sem );
-#endif
                }
                if ( virtual > -1024UL ) {
                        /* Real error */
@@ -1279,3 +1557,26 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
        return retcode;
 }
 
+/**
+ * Compute size order.  Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ * 
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
+ */
+int drm_order( unsigned long size )
+{
+       int order;
+       unsigned long tmp;
+
+       for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++)
+               ;
+
+       if (size & (size - 1))
+               ++order;
+
+       return order;
+}
+EXPORT_SYMBOL(drm_order);
index a7cfabd1ca2e9d0801c3e8c10b12cc1acbb0601c..f515567e5b6f3b9545b8023f365c471b55b9db2d 100644 (file)
@@ -212,6 +212,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
        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;
 
        if (copy_from_user(&request, argp, sizeof(request)))
                return -EFAULT;
@@ -225,7 +226,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
        map = dev->context_sareas[request.ctx_id];
        up(&dev->struct_sem);
 
-       request.handle = (void *) map->offset;
+       request.handle = 0;
+       list_for_each_entry(_entry, &dev->maplist->head,head) {
+               if (_entry->map == map) {
+                       request.handle = (void *)(unsigned long)_entry->user_token;
+                       break;
+               }
+       }
+       if (request.handle == 0)
+               return -EINVAL;
+
+
        if (copy_to_user(argp, &request, sizeof(request)))
                return -EFAULT;
        return 0;
@@ -262,7 +273,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
        list_for_each(list, &dev->maplist->head) {
                r_list = list_entry(list, drm_map_list_t, head);
                if (r_list->map
-                   && r_list->map->offset == (unsigned long) request.handle)
+                   && r_list->user_token == (unsigned long) request.handle)
                        goto found;
        }
 bad:
@@ -369,7 +380,7 @@ int drm_resctx( struct inode *inode, struct file *filp,
                for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
                        ctx.handle = i;
                        if ( copy_to_user( &res.contexts[i],
-                                          &i, sizeof(i) ) )
+                                          &ctx, sizeof(ctx) ) )
                                return -EFAULT;
                }
        }
index 3333c250c4d9995848053d4f8a3ecf1286b1ed6b..6ba48f346fcf2407d400e1d7217f10b2d72e0c7a 100644 (file)
@@ -70,8 +70,8 @@ static drm_ioctl_desc_t                 drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { drm_noop,        1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { drm_authmagic,   1, 1 },
 
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { drm_addmap,      1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { drm_rmmap,       1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { drm_addmap_ioctl,1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { drm_rmmap_ioctl, 1, 0 },
 
        [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { drm_setsareactx, 1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { drm_getsareactx, 1, 0 },
@@ -102,10 +102,10 @@ static drm_ioctl_desc_t             drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { drm_control,     1, 1 },
 
 #if __OS_HAS_AGP
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { drm_agp_acquire, 1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { drm_agp_release, 1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { drm_agp_enable 1, 1 },
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { drm_agp_info,    1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { drm_agp_acquire_ioctl, 1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { drm_agp_release_ioctl, 1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { drm_agp_enable_ioctl, 1, 1 },
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { drm_agp_info_ioctl, 1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { drm_agp_alloc,   1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { drm_agp_free,    1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { drm_agp_bind,    1, 1 },
@@ -127,14 +127,12 @@ static drm_ioctl_desc_t             drm_ioctls[] = {
  *
  * Frees every resource in \p dev.
  *
- * \sa drm_device and setup().
+ * \sa drm_device
  */
 int drm_takedown( drm_device_t *dev )
 {
        drm_magic_entry_t *pt, *next;
-       drm_map_t *map;
        drm_map_list_t *r_list;
-       struct list_head *list, *list_next;
        drm_vma_entry_t *vma, *vma_next;
        int i;
 
@@ -142,6 +140,7 @@ int drm_takedown( drm_device_t *dev )
 
        if (dev->driver->pretakedown)
          dev->driver->pretakedown(dev);
+       DRM_DEBUG("driver pretakedown completed\n");
 
        if (dev->unique) {
                drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
@@ -178,11 +177,16 @@ int drm_takedown( drm_device_t *dev )
                }
                dev->agp->memory = NULL;
 
-               if ( dev->agp->acquired ) drm_agp_do_release(dev);
+               if (dev->agp->acquired)
+                 drm_agp_release(dev);
 
                dev->agp->acquired = 0;
                dev->agp->enabled  = 0;
        }
+       if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
+               drm_sg_cleanup(dev->sg);
+               dev->sg = NULL;
+       }
 
                                /* Clear vma list (only built for debugging) */
        if ( dev->vmalist ) {
@@ -194,48 +198,11 @@ int drm_takedown( drm_device_t *dev )
        }
 
        if( dev->maplist ) {
-               list_for_each_safe( list, list_next, &dev->maplist->head ) {
-                       r_list = (drm_map_list_t *)list;
-
-                       if ( ( map = r_list->map ) ) {
-                               switch ( map->type ) {
-                               case _DRM_REGISTERS:
-                               case _DRM_FRAME_BUFFER:
-                                       if (drm_core_has_MTRR(dev)) {
-                                               if ( map->mtrr >= 0 ) {
-                                                       int retcode;
-                                                       retcode = mtrr_del( map->mtrr,
-                                                                           map->offset,
-                                                                           map->size );
-                                                       DRM_DEBUG( "mtrr_del=%d\n", retcode );
-                                               }
-                                       }
-                                       drm_ioremapfree( map->handle, map->size, dev );
-                                       break;
-                               case _DRM_SHM:
-                                       vfree(map->handle);
-                                       break;
-
-                               case _DRM_AGP:
-                                       /* Do nothing here, because this is all
-                                        * handled in the AGP/GART driver.
-                                        */
-                                       break;
-                               case _DRM_SCATTER_GATHER:
-                                       /* Handle it */
-                                       if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
-                                               drm_sg_cleanup(dev->sg);
-                                               dev->sg = NULL;
-                                       }
-                                       break;
-                               }
-                               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       }
-                       list_del( list );
-                       drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
-               }
-               drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
-               dev->maplist = NULL;
+               while (!list_empty(&dev->maplist->head)) {
+                       struct list_head *list = dev->maplist->head.next;
+                       r_list = list_entry(list, drm_map_list_t, head);
+                       drm_rmmap_locked(dev, r_list->map);
+               }
        }
 
        if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
@@ -264,6 +231,7 @@ int drm_takedown( drm_device_t *dev )
        }
        up( &dev->struct_sem );
 
+       DRM_DEBUG("takedown completed\n");
        return 0;
 }
 
@@ -312,7 +280,7 @@ EXPORT_SYMBOL(drm_init);
  *
  * Cleans up all DRM device, calling takedown().
  * 
- * \sa drm_init().
+ * \sa drm_init
  */
 static void drm_cleanup( drm_device_t *dev )
 {
@@ -325,6 +293,11 @@ static void drm_cleanup( drm_device_t *dev )
 
        drm_takedown( dev );    
 
+       if (dev->maplist) {
+               drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+               dev->maplist = NULL;
+       }
+
        drm_ctxbitmap_cleanup( dev );
        
        if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
index 10e64fde8d782ca23dbc3ef57a3348f97a40d87d..a1f4e9cd64edd17406cf2b6349c37a2039a9fac2 100644 (file)
@@ -71,12 +71,6 @@ static int drm_setup( drm_device_t *dev )
                dev->magiclist[i].tail = NULL;
        }
 
-       dev->maplist = drm_alloc(sizeof(*dev->maplist),
-                                 DRM_MEM_MAPS);
-       if(dev->maplist == NULL) return -ENOMEM;
-       memset(dev->maplist, 0, sizeof(*dev->maplist));
-       INIT_LIST_HEAD(&dev->maplist->head);
-
        dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
                                  DRM_MEM_CTXLIST);
        if(dev->ctxlist == NULL) return -ENOMEM;
index 39afda0ccabe36d803e5bc89772d4b19edec6d94..d2ed3ba5aca9647259bfc932f3363adfec77ee26 100644 (file)
@@ -208,7 +208,7 @@ int drm_getmap( struct inode *inode, struct file *filp,
        map.size   = r_list->map->size;
        map.type   = r_list->map->type;
        map.flags  = r_list->map->flags;
-       map.handle = r_list->map->handle;
+       map.handle = (void *)(unsigned long) r_list->user_token;
        map.mtrr   = r_list->map->mtrr;
        up(&dev->struct_sem);
 
index ace3d42f4407e5df458d6578b79f0aaaa742127c..ff483fb418aae85e2d1d987747efc511a9b415a0 100644 (file)
@@ -142,27 +142,31 @@ void drm_free_pages(unsigned long address, int order, int area)
 
 #if __OS_HAS_AGP
 /** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(drm_device_t *dev, int pages, u32 type)
 {
-       return drm_agp_allocate_memory(bridge, pages, type);
+       return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
 }
+EXPORT_SYMBOL(drm_alloc_agp);
 
 /** Wrapper around agp_free_memory() */
 int drm_free_agp(DRM_AGP_MEM *handle, int pages)
 {
        return drm_agp_free_memory(handle) ? 0 : -EINVAL;
 }
+EXPORT_SYMBOL(drm_free_agp);
 
 /** Wrapper around agp_bind_memory() */
 int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start)
 {
        return drm_agp_bind_memory(handle, start);
 }
+EXPORT_SYMBOL(drm_bind_agp);
 
 /** Wrapper around agp_unbind_memory() */
 int drm_unbind_agp(DRM_AGP_MEM *handle)
 {
        return drm_agp_unbind_memory(handle);
 }
+EXPORT_SYMBOL(drm_unbind_agp);
 #endif /* agp */
 #endif /* debug_memory */
index 192e8762571c890b0b10d536234d326b0bfcac06..09ed712c1a7fe0c0d1dc4038d83db079517a9eb8 100644 (file)
 /**
  * \brief Allocate a PCI consistent memory block, for DMA.
  */
-void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
-                   dma_addr_t maxaddr, dma_addr_t * busaddr)
+drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
+                               dma_addr_t maxaddr)
 {
-       void *address;
-#if DRM_DEBUG_MEMORY
+       drm_dma_handle_t *dmah;
+#ifdef DRM_DEBUG_MEMORY
        int area = DRM_MEM_DMA;
 
        spin_lock(&drm_mem_lock);
@@ -74,13 +74,19 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
                return NULL;
        }
 
-       address = pci_alloc_consistent(dev->pdev, size, busaddr);
+       dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
+       if (!dmah)
+               return NULL;
+       
+       dmah->size = size;
+       dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr);
 
-#if DRM_DEBUG_MEMORY
-       if (address == NULL) {
+#ifdef DRM_DEBUG_MEMORY
+       if (dmah->vaddr == NULL) {
                spin_lock(&drm_mem_lock);
                ++drm_mem_stats[area].fail_count;
                spin_unlock(&drm_mem_lock);
+               kfree(dmah);
                return NULL;
        }
 
@@ -90,37 +96,42 @@ void *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
        drm_ram_used += size;
        spin_unlock(&drm_mem_lock);
 #else
-       if (address == NULL)
+       if (dmah->vaddr == NULL) {
+               kfree(dmah);
                return NULL;
+       }
 #endif
 
-       memset(address, 0, size);
+       memset(dmah->vaddr, 0, size);
 
-       return address;
+       return dmah;
 }
 EXPORT_SYMBOL(drm_pci_alloc);
 
 /**
- * \brief Free a PCI consistent memory block.
+ * \brief Free a PCI consistent memory block with freeing its descriptor.
+ *
+ * This function is for internal use in the Linux-specific DRM core code.
  */
 void
-drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
+__drm_pci_free(drm_device_t * dev, drm_dma_handle_t *dmah)
 {
-#if DRM_DEBUG_MEMORY
+#ifdef DRM_DEBUG_MEMORY
        int area = DRM_MEM_DMA;
        int alloc_count;
        int free_count;
 #endif
 
-       if (!vaddr) {
-#if DRM_DEBUG_MEMORY
+       if (!dmah->vaddr) {
+#ifdef DRM_DEBUG_MEMORY
                DRM_MEM_ERROR(area, "Attempt to free address 0\n");
 #endif
        } else {
-               pci_free_consistent(dev->pdev, size, vaddr, busaddr);
+               pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr,
+                                   dmah->busaddr);
        }
 
-#if DRM_DEBUG_MEMORY
+#ifdef DRM_DEBUG_MEMORY
        spin_lock(&drm_mem_lock);
        free_count = ++drm_mem_stats[area].free_count;
        alloc_count = drm_mem_stats[area].succeed_count;
@@ -135,6 +146,16 @@ drm_pci_free(drm_device_t * dev, size_t size, void *vaddr, dma_addr_t busaddr)
 #endif
 
 }
+
+/**
+ * \brief Free a PCI consistent memory block
+ */
+void
+drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
+{
+       __drm_pci_free(dev, dmah);
+       kfree(dmah);
+}
 EXPORT_SYMBOL(drm_pci_free);
 
 /*@}*/
index 70ca4fa55c9dd2433a37951095e7661240402e18..58b1747cd44033f1056f2982d7e3c8a9e04803d6 100644 (file)
@@ -25,6 +25,8 @@
        {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
        {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
        {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \
+       {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
+       {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
        {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
        {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \
        {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \
        {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
        {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
        {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \
+       {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
        {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+       {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
+       {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
        {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
        {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
        {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
@@ -56,6 +68,7 @@
        {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
        {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
        {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
+       {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
        {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
        {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \
        {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \
        {0, 0, 0}
 
 #define mga_PCI_IDS \
-       {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x102b, 0x0520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+       {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+       {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G400}, \
+       {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G550}, \
        {0, 0, 0}
 
 #define mach64_PCI_IDS \
 
 #define viadrv_PCI_IDS \
        {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0, 0, 0}
 
 #define i810_PCI_IDS \
        {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0, 0, 0}
 
-#define gamma_PCI_IDS \
-       {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
 #define savage_PCI_IDS \
-       {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+       {0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+       {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+       {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+       {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+       {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+       {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+       {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+       {0x5333, 0x8d03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
+       {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
        {0, 0, 0}
 
 #define ffb_PCI_IDS \
        {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
        {0, 0, 0}
 
-#define viadrv_PCI_IDS \
-       {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
index 4774087d2e9e82c64d0d05511d02743d9371375f..32d2bb99462c67d7b9ef4416abd3147445afc36e 100644 (file)
@@ -210,8 +210,8 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
 
                                /* Hardcoded from _DRM_FRAME_BUFFER,
                                    _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
-                                   _DRM_SCATTER_GATHER. */
-       const char   *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
+                                   _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+       const char   *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
        const char   *type;
        int          i;
 
@@ -229,16 +229,19 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
        if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
                r_list = list_entry(list, drm_map_list_t, head);
                map = r_list->map;
-               if(!map) continue;
-               if (map->type < 0 || map->type > 4) type = "??";
-               else                                type = types[map->type];
-               DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
+               if(!map)
+                       continue;
+               if (map->type < 0 || map->type > 5)
+                       type = "??";
+               else    
+                       type = types[map->type];
+               DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08x ",
                               i,
                               map->offset,
                               map->size,
                               type,
                               map->flags,
-                              (unsigned long)map->handle);
+                              r_list->user_token);
                if (map->mtrr < 0) {
                        DRM_PROC_PRINT("none\n");
                } else {
index 54fddb6ea2d1398f1da3263c4105097ee2cbd63f..ed267d49bc6aa9c4dee72c006a41a61f9991e35b 100644 (file)
@@ -61,6 +61,12 @@ void drm_sg_cleanup( drm_sg_mem_t *entry )
                   DRM_MEM_SGLISTS );
 }
 
+#ifdef _LP64
+# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
+#else
+# define ScatterHandle(x) (unsigned int)(x)
+#endif
+
 int drm_sg_alloc( struct inode *inode, struct file *filp,
                   unsigned int cmd, unsigned long arg )
 {
@@ -133,12 +139,13 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
         */
        memset( entry->virtual, 0, pages << PAGE_SHIFT );
 
-       entry->handle = (unsigned long)entry->virtual;
+       entry->handle = ScatterHandle((unsigned long)entry->virtual);
 
        DRM_DEBUG( "sg alloc handle  = %08lx\n", entry->handle );
        DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
 
-       for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
+       for (i = (unsigned long)entry->virtual, j = 0; j < pages; 
+               i += PAGE_SIZE, j++) {
                entry->pagelist[j] = vmalloc_to_page((void *)i);
                if (!entry->pagelist[j])
                        goto failed;
index 48829a1a086a94cba10327d6896f8e1dbfdc5e95..95a976c96eb8303c9df9cc249c8c3d9e99cc999c 100644 (file)
@@ -75,6 +75,11 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
        dev->pci_func = PCI_FUNC(pdev->devfn);
        dev->irq = pdev->irq;
 
+       dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
+       if (dev->maplist == NULL)
+               return -ENOMEM;
+       INIT_LIST_HEAD(&dev->maplist->head);
+
        /* the DRM has 6 basic counters */
        dev->counters = 6;
        dev->types[0]  = _DRM_STAT_LOCK;
@@ -91,7 +96,8 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
                        goto error_out_unreg;
 
        if (drm_core_has_AGP(dev)) {
-               dev->agp = drm_agp_init(dev);
+               if (drm_device_is_agp(dev))
+                       dev->agp = drm_agp_init(dev);
                if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
                        DRM_ERROR( "Cannot initialize the agpgart module.\n" );
                        retcode = -EINVAL;
index 621220f3f37207492ed8bfccdcef7d5e94cc0fda..ced4215e2275e71dad67a2db787054bb03bfc12f 100644 (file)
@@ -73,12 +73,13 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
                r_list = list_entry(list, drm_map_list_t, head);
                map = r_list->map;
                if (!map) continue;
-               if (map->offset == VM_OFFSET(vma)) break;
+               if (r_list->user_token == VM_OFFSET(vma))
+                       break;
        }
 
        if (map && map->type == _DRM_AGP) {
                unsigned long offset = address - vma->vm_start;
-               unsigned long baddr = VM_OFFSET(vma) + offset;
+               unsigned long baddr = map->offset + offset;
                struct drm_agp_mem *agpmem;
                struct page *page;
 
@@ -210,6 +211,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
                }
 
                if(!found_maps) {
+                       drm_dma_handle_t dmah;
+
                        switch (map->type) {
                        case _DRM_REGISTERS:
                        case _DRM_FRAME_BUFFER:
@@ -228,6 +231,12 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
                        case _DRM_AGP:
                        case _DRM_SCATTER_GATHER:
                                break;
+                       case _DRM_CONSISTENT:
+                               dmah.vaddr = map->handle;
+                               dmah.busaddr = map->offset;
+                               dmah.size = map->size;
+                               __drm_pci_free(dev, &dmah);
+                               break;
                        }
                        drm_free(map, sizeof(*map), DRM_MEM_MAPS);
                }
@@ -296,7 +305,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
 
 
        offset = address - vma->vm_start;
-       map_offset = map->offset - dev->sg->handle;
+       map_offset = map->offset - (unsigned long)dev->sg->virtual;
        page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
        page = entry->pagelist[page_offset];
        get_page(page);
@@ -305,8 +314,6 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
 }
 
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
-
 static struct page *drm_vm_nopage(struct vm_area_struct *vma,
                                   unsigned long address,
                                   int *type) {
@@ -335,35 +342,6 @@ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
        return drm_do_vm_sg_nopage(vma, address);
 }
 
-#else  /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */
-
-static struct page *drm_vm_nopage(struct vm_area_struct *vma,
-                                  unsigned long address,
-                                  int unused) {
-       return drm_do_vm_nopage(vma, address);
-}
-
-static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
-                                      unsigned long address,
-                                      int unused) {
-       return drm_do_vm_shm_nopage(vma, address);
-}
-
-static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
-                                      unsigned long address,
-                                      int unused) {
-       return drm_do_vm_dma_nopage(vma, address);
-}
-
-static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma,
-                                     unsigned long address,
-                                     int unused) {
-       return drm_do_vm_sg_nopage(vma, address);
-}
-
-#endif
-
-
 /** AGP virtual memory operations */
 static struct vm_operations_struct   drm_vm_ops = {
        .nopage = drm_vm_nopage,
@@ -487,11 +465,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 
        vma->vm_ops   = &drm_vm_dma_ops;
 
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
-       vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-#else
        vma->vm_flags |= VM_RESERVED; /* Don't swap */
-#endif
 
        vma->vm_file  =  filp;  /* Needed for drm_vm_open() */
        drm_vm_open(vma);
@@ -560,13 +534,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                                   for performance, even if the list was a
                                   bit longer. */
        list_for_each(list, &dev->maplist->head) {
-               unsigned long off;
 
                r_list = list_entry(list, drm_map_list_t, head);
                map = r_list->map;
                if (!map) continue;
-               off = dev->driver->get_map_ofs(map);
-               if (off == VM_OFFSET(vma)) break;
+               if (r_list->user_token == VM_OFFSET(vma))
+                       break;
        }
 
        if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
@@ -605,17 +578,17 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                 /* fall through to _DRM_FRAME_BUFFER... */        
        case _DRM_FRAME_BUFFER:
        case _DRM_REGISTERS:
-               if (VM_OFFSET(vma) >= __pa(high_memory)) {
 #if defined(__i386__) || defined(__x86_64__)
-                       if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
-                               pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-                               pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
-                       }
+               if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
+                       pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+                       pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
+               }
 #elif defined(__powerpc__)
-                       pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+               pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+               if (map->type == _DRM_REGISTERS)
+                       pgprot_val(vma->vm_page_prot) |= _PAGE_GUARDED;
 #endif
-                       vma->vm_flags |= VM_IO; /* not in core dump */
-               }
+               vma->vm_flags |= VM_IO; /* not in core dump */
 #if defined(__ia64__)
                if (efi_range_is_wc(vma->vm_start, vma->vm_end -
                                    vma->vm_start))
@@ -628,12 +601,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                offset = dev->driver->get_reg_ofs(dev);
 #ifdef __sparc__
                if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
-                                       (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
+                                       (map->offset + offset) >> PAGE_SHIFT,
                                        vma->vm_end - vma->vm_start,
                                        vma->vm_page_prot))
 #else
                if (io_remap_pfn_range(vma, vma->vm_start,
-                                    (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
+                                    (map->offset + offset) >> PAGE_SHIFT,
                                     vma->vm_end - vma->vm_start,
                                     vma->vm_page_prot))
 #endif
@@ -641,37 +614,28 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
                DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
                          " offset = 0x%lx\n",
                          map->type,
-                         vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
+                         vma->vm_start, vma->vm_end, map->offset + offset);
                vma->vm_ops = &drm_vm_ops;
                break;
        case _DRM_SHM:
+       case _DRM_CONSISTENT:
+               /* Consistent memory is really like shared memory. It's only
+                * allocate in a different way */
                vma->vm_ops = &drm_vm_shm_ops;
                vma->vm_private_data = (void *)map;
                                /* Don't let this area swap.  Change when
                                   DRM_KERNEL advisory is supported. */
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
-               vma->vm_flags |= VM_LOCKED;
-#else
                vma->vm_flags |= VM_RESERVED;
-#endif
                break;
        case _DRM_SCATTER_GATHER:
                vma->vm_ops = &drm_vm_sg_ops;
                vma->vm_private_data = (void *)map;
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
-               vma->vm_flags |= VM_LOCKED;
-#else
                vma->vm_flags |= VM_RESERVED;
-#endif
                 break;
        default:
                return -EINVAL; /* This should never happen. */
        }
-#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
-       vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-#else
        vma->vm_flags |= VM_RESERVED; /* Don't swap */
-#endif
 
        vma->vm_file  =  filp;  /* Needed for drm_vm_open() */
        drm_vm_open(vma);
index ec614fff8f0481d7f6f6044373328a3012c5196d..1bd0d55ee0f0b4f98cb5eb93c0b112dfd074e4f4 100644 (file)
@@ -152,14 +152,11 @@ static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
                return NULL;
 
        list_for_each(list, &dev->maplist->head) {
-               unsigned long uoff;
-
                r_list = (drm_map_list_t *)list;
                map = r_list->map;
                if (!map)
                        continue;
-               uoff = (map->offset & 0xffffffff);
-               if (uoff == off)
+               if (r_list->user_token == off)
                        return map;
        }
 
diff --git a/drivers/char/drm/gamma_context.h b/drivers/char/drm/gamma_context.h
deleted file mode 100644 (file)
index d11b507..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/* 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.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- * ChangeLog:
- *  2001-11-16 Torsten Duwe <duwe@caldera.de>
- *             added context constructor/destructor hooks,
- *             needed by SiS driver's memory management.
- */
-
-/* ================================================================
- * Old-style context support -- only used by gamma.  
- */
-
-
-/* The drm_read and drm_write_string code (especially that which manages
-   the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
-   DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
-
-ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
-{
-       drm_file_t    *priv   = filp->private_data;
-       drm_device_t  *dev    = priv->dev;
-       int           left;
-       int           avail;
-       int           send;
-       int           cur;
-
-       DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
-
-       while (dev->buf_rp == dev->buf_wp) {
-               DRM_DEBUG("  sleeping\n");
-               if (filp->f_flags & O_NONBLOCK) {
-                       return -EAGAIN;
-               }
-               interruptible_sleep_on(&dev->buf_readers);
-               if (signal_pending(current)) {
-                       DRM_DEBUG("  interrupted\n");
-                       return -ERESTARTSYS;
-               }
-               DRM_DEBUG("  awake\n");
-       }
-
-       left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
-       avail = DRM_BSZ - left;
-       send  = DRM_MIN(avail, count);
-
-       while (send) {
-               if (dev->buf_wp > dev->buf_rp) {
-                       cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
-               } else {
-                       cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
-               }
-               if (copy_to_user(buf, dev->buf_rp, cur))
-                       return -EFAULT;
-               dev->buf_rp += cur;
-               if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
-               send -= cur;
-       }
-
-       wake_up_interruptible(&dev->buf_writers);
-       return DRM_MIN(avail, count);
-}
-
-
-/* In an incredibly convoluted setup, the kernel module actually calls
- * back into the X server to perform context switches on behalf of the
- * 3d clients.
- */
-int DRM(write_string)(drm_device_t *dev, const char *s)
-{
-       int left   = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
-       int send   = strlen(s);
-       int count;
-
-       DRM_DEBUG("%d left, %d to send (%p, %p)\n",
-                 left, send, dev->buf_rp, dev->buf_wp);
-
-       if (left == 1 || dev->buf_wp != dev->buf_rp) {
-               DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
-                         left,
-                         dev->buf_wp,
-                         dev->buf_rp);
-       }
-
-       while (send) {
-               if (dev->buf_wp >= dev->buf_rp) {
-                       count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
-                       if (count == left) --count; /* Leave a hole */
-               } else {
-                       count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
-               }
-               strncpy(dev->buf_wp, s, count);
-               dev->buf_wp += count;
-               if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
-               send -= count;
-       }
-
-       if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
-
-       DRM_DEBUG("waking\n");
-       wake_up_interruptible(&dev->buf_readers);
-       return 0;
-}
-
-unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait)
-{
-       drm_file_t   *priv = filp->private_data;
-       drm_device_t *dev  = priv->dev;
-
-       poll_wait(filp, &dev->buf_readers, wait);
-       if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-int DRM(context_switch)(drm_device_t *dev, int old, int new)
-{
-       char        buf[64];
-       drm_queue_t *q;
-
-       if (test_and_set_bit(0, &dev->context_flag)) {
-               DRM_ERROR("Reentering -- FIXME\n");
-               return -EBUSY;
-       }
-
-       DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-       if (new >= dev->queue_count) {
-               clear_bit(0, &dev->context_flag);
-               return -EINVAL;
-       }
-
-       if (new == dev->last_context) {
-               clear_bit(0, &dev->context_flag);
-               return 0;
-       }
-
-       q = dev->queuelist[new];
-       atomic_inc(&q->use_count);
-       if (atomic_read(&q->use_count) == 1) {
-               atomic_dec(&q->use_count);
-               clear_bit(0, &dev->context_flag);
-               return -EINVAL;
-       }
-
-       /* This causes the X server to wake up & do a bunch of hardware
-        * interaction to actually effect the context switch.
-        */
-       sprintf(buf, "C %d %d\n", old, new);
-       DRM(write_string)(dev, buf);
-
-       atomic_dec(&q->use_count);
-
-       return 0;
-}
-
-int DRM(context_switch_complete)(drm_device_t *dev, int new)
-{
-       drm_device_dma_t *dma = dev->dma;
-
-       dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
-       dev->last_switch  = jiffies;
-
-       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-               DRM_ERROR("Lock isn't held after context switch\n");
-       }
-
-       if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
-               if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
-                                 DRM_KERNEL_CONTEXT)) {
-                       DRM_ERROR("Cannot free lock\n");
-               }
-       }
-
-       clear_bit(0, &dev->context_flag);
-       wake_up_interruptible(&dev->context_wait);
-
-       return 0;
-}
-
-static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
-{
-       DRM_DEBUG("\n");
-
-       if (atomic_read(&q->use_count) != 1
-           || atomic_read(&q->finalization)
-           || atomic_read(&q->block_count)) {
-               DRM_ERROR("New queue is already in use: u%d f%d b%d\n",
-                         atomic_read(&q->use_count),
-                         atomic_read(&q->finalization),
-                         atomic_read(&q->block_count));
-       }
-
-       atomic_set(&q->finalization,  0);
-       atomic_set(&q->block_count,   0);
-       atomic_set(&q->block_read,    0);
-       atomic_set(&q->block_write,   0);
-       atomic_set(&q->total_queued,  0);
-       atomic_set(&q->total_flushed, 0);
-       atomic_set(&q->total_locks,   0);
-
-       init_waitqueue_head(&q->write_queue);
-       init_waitqueue_head(&q->read_queue);
-       init_waitqueue_head(&q->flush_queue);
-
-       q->flags = ctx->flags;
-
-       DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
-
-       return 0;
-}
-
-
-/* drm_alloc_queue:
-PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
-       disappear (so all deallocation must be done after IOCTLs are off)
-     2) dev->queue_count < dev->queue_slots
-     3) dev->queuelist[i].use_count == 0 and
-       dev->queuelist[i].finalization == 0 if i not in use
-POST: 1) dev->queuelist[i].use_count == 1
-      2) dev->queue_count < dev->queue_slots */
-
-static int DRM(alloc_queue)(drm_device_t *dev)
-{
-       int         i;
-       drm_queue_t *queue;
-       int         oldslots;
-       int         newslots;
-                               /* Check for a free queue */
-       for (i = 0; i < dev->queue_count; i++) {
-               atomic_inc(&dev->queuelist[i]->use_count);
-               if (atomic_read(&dev->queuelist[i]->use_count) == 1
-                   && !atomic_read(&dev->queuelist[i]->finalization)) {
-                       DRM_DEBUG("%d (free)\n", i);
-                       return i;
-               }
-               atomic_dec(&dev->queuelist[i]->use_count);
-       }
-                               /* Allocate a new queue */
-       down(&dev->struct_sem);
-
-       queue = DRM(alloc)(sizeof(*queue), DRM_MEM_QUEUES);
-       memset(queue, 0, sizeof(*queue));
-       atomic_set(&queue->use_count, 1);
-
-       ++dev->queue_count;
-       if (dev->queue_count >= dev->queue_slots) {
-               oldslots = dev->queue_slots * sizeof(*dev->queuelist);
-               if (!dev->queue_slots) dev->queue_slots = 1;
-               dev->queue_slots *= 2;
-               newslots = dev->queue_slots * sizeof(*dev->queuelist);
-
-               dev->queuelist = DRM(realloc)(dev->queuelist,
-                                             oldslots,
-                                             newslots,
-                                             DRM_MEM_QUEUES);
-               if (!dev->queuelist) {
-                       up(&dev->struct_sem);
-                       DRM_DEBUG("out of memory\n");
-                       return -ENOMEM;
-               }
-       }
-       dev->queuelist[dev->queue_count-1] = queue;
-
-       up(&dev->struct_sem);
-       DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
-       return dev->queue_count - 1;
-}
-
-int DRM(resctx)(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
-{
-       drm_ctx_res_t __user *argp = (void __user *)arg;
-       drm_ctx_res_t   res;
-       drm_ctx_t       ctx;
-       int             i;
-
-       DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
-       if (copy_from_user(&res, argp, sizeof(res)))
-               return -EFAULT;
-       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],
-                                        &i,
-                                        sizeof(i)))
-                               return -EFAULT;
-               }
-       }
-       res.count = DRM_RESERVED_CONTEXTS;
-       if (copy_to_user(argp, &res, sizeof(res)))
-               return -EFAULT;
-       return 0;
-}
-
-int DRM(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;
-       drm_ctx_t       ctx;
-       drm_ctx_t       __user *argp = (void __user *)arg;
-
-       if (copy_from_user(&ctx, argp, sizeof(ctx)))
-               return -EFAULT;
-       if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
-                               /* Init kernel's context and get a new one. */
-               DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
-               ctx.handle = DRM(alloc_queue)(dev);
-       }
-       DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
-       DRM_DEBUG("%d\n", ctx.handle);
-       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)
-{
-       drm_file_t      *priv   = filp->private_data;
-       drm_device_t    *dev    = priv->dev;
-       drm_ctx_t       ctx;
-       drm_queue_t     *q;
-
-       if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
-               return -EFAULT;
-
-       DRM_DEBUG("%d\n", ctx.handle);
-
-       if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL;
-       q = dev->queuelist[ctx.handle];
-
-       atomic_inc(&q->use_count);
-       if (atomic_read(&q->use_count) == 1) {
-                               /* No longer in use */
-               atomic_dec(&q->use_count);
-               return -EINVAL;
-       }
-
-       if (DRM_BUFCOUNT(&q->waitlist)) {
-               atomic_dec(&q->use_count);
-               return -EBUSY;
-       }
-
-       q->flags = ctx.flags;
-
-       atomic_dec(&q->use_count);
-       return 0;
-}
-
-int DRM(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;
-       drm_ctx_t       __user *argp = (void __user *)arg;
-       drm_ctx_t       ctx;
-       drm_queue_t     *q;
-
-       if (copy_from_user(&ctx, argp, sizeof(ctx)))
-               return -EFAULT;
-
-       DRM_DEBUG("%d\n", ctx.handle);
-
-       if (ctx.handle >= dev->queue_count) return -EINVAL;
-       q = dev->queuelist[ctx.handle];
-
-       atomic_inc(&q->use_count);
-       if (atomic_read(&q->use_count) == 1) {
-                               /* No longer in use */
-               atomic_dec(&q->use_count);
-               return -EINVAL;
-       }
-
-       ctx.flags = q->flags;
-       atomic_dec(&q->use_count);
-
-       if (copy_to_user(argp, &ctx, sizeof(ctx)))
-               return -EFAULT;
-
-       return 0;
-}
-
-int DRM(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;
-       drm_ctx_t       ctx;
-
-       if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
-               return -EFAULT;
-       DRM_DEBUG("%d\n", ctx.handle);
-       return DRM(context_switch)(dev, dev->last_context, ctx.handle);
-}
-
-int DRM(newctx)(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
-{
-       drm_file_t      *priv   = filp->private_data;
-       drm_device_t    *dev    = priv->dev;
-       drm_ctx_t       ctx;
-
-       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);
-
-       return 0;
-}
-
-int DRM(rmctx)(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
-{
-       drm_file_t      *priv   = filp->private_data;
-       drm_device_t    *dev    = priv->dev;
-       drm_ctx_t       ctx;
-       drm_queue_t     *q;
-       drm_buf_t       *buf;
-
-       if (copy_from_user(&ctx, (drm_ctx_t __user *)arg, sizeof(ctx)))
-               return -EFAULT;
-       DRM_DEBUG("%d\n", ctx.handle);
-
-       if (ctx.handle >= dev->queue_count) return -EINVAL;
-       q = dev->queuelist[ctx.handle];
-
-       atomic_inc(&q->use_count);
-       if (atomic_read(&q->use_count) == 1) {
-                               /* No longer in use */
-               atomic_dec(&q->use_count);
-               return -EINVAL;
-       }
-
-       atomic_inc(&q->finalization); /* Mark queue in finalization state */
-       atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
-                                        finalization) */
-
-       while (test_and_set_bit(0, &dev->interrupt_flag)) {
-               schedule();
-               if (signal_pending(current)) {
-                       clear_bit(0, &dev->interrupt_flag);
-                       return -EINTR;
-               }
-       }
-                               /* Remove queued buffers */
-       while ((buf = DRM(waitlist_get)(&q->waitlist))) {
-               DRM(free_buffer)(dev, buf);
-       }
-       clear_bit(0, &dev->interrupt_flag);
-
-                               /* Wakeup blocked processes */
-       wake_up_interruptible(&q->read_queue);
-       wake_up_interruptible(&q->write_queue);
-       wake_up_interruptible(&q->flush_queue);
-
-                               /* Finalization over.  Queue is made
-                                  available when both use_count and
-                                  finalization become 0, which won't
-                                  happen until all the waiting processes
-                                  stop waiting. */
-       atomic_dec(&q->finalization);
-       return 0;
-}
-
diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
deleted file mode 100644 (file)
index e486fb8..0000000
+++ /dev/null
@@ -1,946 +0,0 @@
-/* gamma_dma.c -- DMA support for GMX 2000 -*- linux-c -*-
- * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#include "gamma.h"
-#include "drmP.h"
-#include "drm.h"
-#include "gamma_drm.h"
-#include "gamma_drv.h"
-
-#include <linux/interrupt.h>   /* For task queue support */
-#include <linux/delay.h>
-
-static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
-                                     unsigned long length)
-{
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-       mb();
-       while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
-               cpu_relax();
-
-       GAMMA_WRITE(GAMMA_DMAADDRESS, address);
-
-       while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
-               cpu_relax();
-
-       GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
-}
-
-void gamma_dma_quiescent_single(drm_device_t *dev)
-{
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-       while (GAMMA_READ(GAMMA_DMACOUNT))
-               cpu_relax();
-
-       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
-               cpu_relax();
-
-       GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
-       GAMMA_WRITE(GAMMA_SYNC, 0);
-
-       do {
-               while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
-                       cpu_relax();
-       } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-}
-
-void gamma_dma_quiescent_dual(drm_device_t *dev)
-{
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-       while (GAMMA_READ(GAMMA_DMACOUNT))
-               cpu_relax();
-
-       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-               cpu_relax();
-
-       GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
-       GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
-       GAMMA_WRITE(GAMMA_SYNC, 0);
-
-       /* Read from first MX */
-       do {
-               while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
-                       cpu_relax();
-       } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-
-       /* Read from second MX */
-       do {
-               while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
-                       cpu_relax();
-       } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
-}
-
-void gamma_dma_ready(drm_device_t *dev)
-{
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-       while (GAMMA_READ(GAMMA_DMACOUNT))
-               cpu_relax();
-}
-
-static inline int gamma_dma_is_ready(drm_device_t *dev)
-{
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-       return (!GAMMA_READ(GAMMA_DMACOUNT));
-}
-
-irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS )
-{
-       drm_device_t     *dev = (drm_device_t *)arg;
-       drm_device_dma_t *dma = dev->dma;
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-
-       /* FIXME: should check whether we're actually interested in the interrupt? */
-       atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
-
-       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-               cpu_relax();
-
-       GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
-       GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
-       GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
-       if (gamma_dma_is_ready(dev)) {
-                               /* Free previous buffer */
-               if (test_and_set_bit(0, &dev->dma_flag))
-                       return IRQ_HANDLED;
-               if (dma->this_buffer) {
-                       gamma_free_buffer(dev, dma->this_buffer);
-                       dma->this_buffer = NULL;
-               }
-               clear_bit(0, &dev->dma_flag);
-
-               /* Dispatch new buffer */
-               schedule_work(&dev->work);
-       }
-       return IRQ_HANDLED;
-}
-
-/* Only called by gamma_dma_schedule. */
-static int gamma_do_dma(drm_device_t *dev, int locked)
-{
-       unsigned long    address;
-       unsigned long    length;
-       drm_buf_t        *buf;
-       int              retcode = 0;
-       drm_device_dma_t *dma = dev->dma;
-
-       if (test_and_set_bit(0, &dev->dma_flag)) return -EBUSY;
-
-
-       if (!dma->next_buffer) {
-               DRM_ERROR("No next_buffer\n");
-               clear_bit(0, &dev->dma_flag);
-               return -EINVAL;
-       }
-
-       buf     = dma->next_buffer;
-       /* WE NOW ARE ON LOGICAL PAGES!! - using page table setup in dma_init */
-       /* So we pass the buffer index value into the physical page offset */
-       address = buf->idx << 12;
-       length  = buf->used;
-
-       DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
-                 buf->context, buf->idx, length);
-
-       if (buf->list == DRM_LIST_RECLAIM) {
-               gamma_clear_next_buffer(dev);
-               gamma_free_buffer(dev, buf);
-               clear_bit(0, &dev->dma_flag);
-               return -EINVAL;
-       }
-
-       if (!length) {
-               DRM_ERROR("0 length buffer\n");
-               gamma_clear_next_buffer(dev);
-               gamma_free_buffer(dev, buf);
-               clear_bit(0, &dev->dma_flag);
-               return 0;
-       }
-
-       if (!gamma_dma_is_ready(dev)) {
-               clear_bit(0, &dev->dma_flag);
-               return -EBUSY;
-       }
-
-       if (buf->while_locked) {
-               if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-                       DRM_ERROR("Dispatching buffer %d from pid %d"
-                                 " \"while locked\", but no lock held\n",
-                                 buf->idx, current->pid);
-               }
-       } else {
-               if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
-                                             DRM_KERNEL_CONTEXT)) {
-                       clear_bit(0, &dev->dma_flag);
-                       return -EBUSY;
-               }
-       }
-
-       if (dev->last_context != buf->context
-           && !(dev->queuelist[buf->context]->flags
-                & _DRM_CONTEXT_PRESERVED)) {
-                               /* PRE: dev->last_context != buf->context */
-               if (DRM(context_switch)(dev, dev->last_context,
-                                       buf->context)) {
-                       DRM(clear_next_buffer)(dev);
-                       DRM(free_buffer)(dev, buf);
-               }
-               retcode = -EBUSY;
-               goto cleanup;
-
-                               /* POST: we will wait for the context
-                                  switch and will dispatch on a later call
-                                  when dev->last_context == buf->context.
-                                  NOTE WE HOLD THE LOCK THROUGHOUT THIS
-                                  TIME! */
-       }
-
-       gamma_clear_next_buffer(dev);
-       buf->pending     = 1;
-       buf->waiting     = 0;
-       buf->list        = DRM_LIST_PEND;
-
-       /* WE NOW ARE ON LOGICAL PAGES!!! - overriding address */
-       address = buf->idx << 12;
-
-       gamma_dma_dispatch(dev, address, length);
-       gamma_free_buffer(dev, dma->this_buffer);
-       dma->this_buffer = buf;
-
-       atomic_inc(&dev->counts[7]); /* _DRM_STAT_DMA */
-       atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
-
-       if (!buf->while_locked && !dev->context_flag && !locked) {
-               if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
-                                 DRM_KERNEL_CONTEXT)) {
-                       DRM_ERROR("\n");
-               }
-       }
-cleanup:
-
-       clear_bit(0, &dev->dma_flag);
-
-
-       return retcode;
-}
-
-static void gamma_dma_timer_bh(unsigned long dev)
-{
-       gamma_dma_schedule((drm_device_t *)dev, 0);
-}
-
-void gamma_irq_immediate_bh(void *dev)
-{
-       gamma_dma_schedule(dev, 0);
-}
-
-int gamma_dma_schedule(drm_device_t *dev, int locked)
-{
-       int              next;
-       drm_queue_t      *q;
-       drm_buf_t        *buf;
-       int              retcode   = 0;
-       int              processed = 0;
-       int              missed;
-       int              expire    = 20;
-       drm_device_dma_t *dma      = dev->dma;
-
-       if (test_and_set_bit(0, &dev->interrupt_flag)) {
-                               /* Not reentrant */
-               atomic_inc(&dev->counts[10]); /* _DRM_STAT_MISSED */
-               return -EBUSY;
-       }
-       missed = atomic_read(&dev->counts[10]);
-
-
-again:
-       if (dev->context_flag) {
-               clear_bit(0, &dev->interrupt_flag);
-               return -EBUSY;
-       }
-       if (dma->next_buffer) {
-                               /* Unsent buffer that was previously
-                                  selected, but that couldn't be sent
-                                  because the lock could not be obtained
-                                  or the DMA engine wasn't ready.  Try
-                                  again. */
-               if (!(retcode = gamma_do_dma(dev, locked))) ++processed;
-       } else {
-               do {
-                       next = gamma_select_queue(dev, gamma_dma_timer_bh);
-                       if (next >= 0) {
-                               q   = dev->queuelist[next];
-                               buf = gamma_waitlist_get(&q->waitlist);
-                               dma->next_buffer = buf;
-                               dma->next_queue  = q;
-                               if (buf && buf->list == DRM_LIST_RECLAIM) {
-                                       gamma_clear_next_buffer(dev);
-                                       gamma_free_buffer(dev, buf);
-                               }
-                       }
-               } while (next >= 0 && !dma->next_buffer);
-               if (dma->next_buffer) {
-                       if (!(retcode = gamma_do_dma(dev, locked))) {
-                               ++processed;
-                       }
-               }
-       }
-
-       if (--expire) {
-               if (missed != atomic_read(&dev->counts[10])) {
-                       if (gamma_dma_is_ready(dev)) goto again;
-               }
-               if (processed && gamma_dma_is_ready(dev)) {
-                       processed = 0;
-                       goto again;
-               }
-       }
-
-       clear_bit(0, &dev->interrupt_flag);
-
-       return retcode;
-}
-
-static int gamma_dma_priority(struct file *filp, 
-                             drm_device_t *dev, drm_dma_t *d)
-{
-       unsigned long     address;
-       unsigned long     length;
-       int               must_free = 0;
-       int               retcode   = 0;
-       int               i;
-       int               idx;
-       drm_buf_t         *buf;
-       drm_buf_t         *last_buf = NULL;
-       drm_device_dma_t  *dma      = dev->dma;
-       int               *send_indices = NULL;
-       int               *send_sizes = NULL;
-
-       DECLARE_WAITQUEUE(entry, current);
-
-                               /* Turn off interrupt handling */
-       while (test_and_set_bit(0, &dev->interrupt_flag)) {
-               schedule();
-               if (signal_pending(current)) return -EINTR;
-       }
-       if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
-               while (!gamma_lock_take(&dev->lock.hw_lock->lock,
-                                     DRM_KERNEL_CONTEXT)) {
-                       schedule();
-                       if (signal_pending(current)) {
-                               clear_bit(0, &dev->interrupt_flag);
-                               return -EINTR;
-                       }
-               }
-               ++must_free;
-       }
-
-       send_indices = DRM(alloc)(d->send_count * sizeof(*send_indices),
-                                 DRM_MEM_DRIVER);
-       if (send_indices == NULL)
-               return -ENOMEM;
-       if (copy_from_user(send_indices, d->send_indices, 
-                          d->send_count * sizeof(*send_indices))) {
-               retcode = -EFAULT;
-                goto cleanup;
-       }
-       
-       send_sizes = DRM(alloc)(d->send_count * sizeof(*send_sizes),
-                               DRM_MEM_DRIVER);
-       if (send_sizes == NULL)
-               return -ENOMEM;
-       if (copy_from_user(send_sizes, d->send_sizes, 
-                          d->send_count * sizeof(*send_sizes))) {
-               retcode = -EFAULT;
-                goto cleanup;
-       }
-
-       for (i = 0; i < d->send_count; i++) {
-               idx = send_indices[i];
-               if (idx < 0 || idx >= dma->buf_count) {
-                       DRM_ERROR("Index %d (of %d max)\n",
-                                 send_indices[i], dma->buf_count - 1);
-                       continue;
-               }
-               buf = dma->buflist[ idx ];
-               if (buf->filp != filp) {
-                       DRM_ERROR("Process %d using buffer not owned\n",
-                                 current->pid);
-                       retcode = -EINVAL;
-                       goto cleanup;
-               }
-               if (buf->list != DRM_LIST_NONE) {
-                       DRM_ERROR("Process %d using buffer on list %d\n",
-                                 current->pid, buf->list);
-                       retcode = -EINVAL;
-                       goto cleanup;
-               }
-                               /* This isn't a race condition on
-                                  buf->list, since our concern is the
-                                  buffer reclaim during the time the
-                                  process closes the /dev/drm? handle, so
-                                  it can't also be doing DMA. */
-               buf->list         = DRM_LIST_PRIO;
-               buf->used         = send_sizes[i];
-               buf->context      = d->context;
-               buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
-               address           = (unsigned long)buf->address;
-               length            = buf->used;
-               if (!length) {
-                       DRM_ERROR("0 length buffer\n");
-               }
-               if (buf->pending) {
-                       DRM_ERROR("Sending pending buffer:"
-                                 " buffer %d, offset %d\n",
-                                 send_indices[i], i);
-                       retcode = -EINVAL;
-                       goto cleanup;
-               }
-               if (buf->waiting) {
-                       DRM_ERROR("Sending waiting buffer:"
-                                 " buffer %d, offset %d\n",
-                                 send_indices[i], i);
-                       retcode = -EINVAL;
-                       goto cleanup;
-               }
-               buf->pending = 1;
-
-               if (dev->last_context != buf->context
-                   && !(dev->queuelist[buf->context]->flags
-                        & _DRM_CONTEXT_PRESERVED)) {
-                       add_wait_queue(&dev->context_wait, &entry);
-                       current->state = TASK_INTERRUPTIBLE;
-                               /* PRE: dev->last_context != buf->context */
-                       DRM(context_switch)(dev, dev->last_context,
-                                           buf->context);
-                               /* POST: we will wait for the context
-                                  switch and will dispatch on a later call
-                                  when dev->last_context == buf->context.
-                                  NOTE WE HOLD THE LOCK THROUGHOUT THIS
-                                  TIME! */
-                       schedule();
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(&dev->context_wait, &entry);
-                       if (signal_pending(current)) {
-                               retcode = -EINTR;
-                               goto cleanup;
-                       }
-                       if (dev->last_context != buf->context) {
-                               DRM_ERROR("Context mismatch: %d %d\n",
-                                         dev->last_context,
-                                         buf->context);
-                       }
-               }
-
-               gamma_dma_dispatch(dev, address, length);
-               atomic_inc(&dev->counts[9]); /* _DRM_STAT_SPECIAL */
-               atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
-
-               if (last_buf) {
-                       gamma_free_buffer(dev, last_buf);
-               }
-               last_buf = buf;
-       }
-
-
-cleanup:
-       if (last_buf) {
-               gamma_dma_ready(dev);
-               gamma_free_buffer(dev, last_buf);
-       }
-       if (send_indices)
-               DRM(free)(send_indices, d->send_count * sizeof(*send_indices), 
-                         DRM_MEM_DRIVER);
-       if (send_sizes)
-               DRM(free)(send_sizes, d->send_count * sizeof(*send_sizes), 
-                         DRM_MEM_DRIVER);
-
-       if (must_free && !dev->context_flag) {
-               if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
-                                 DRM_KERNEL_CONTEXT)) {
-                       DRM_ERROR("\n");
-               }
-       }
-       clear_bit(0, &dev->interrupt_flag);
-       return retcode;
-}
-
-static int gamma_dma_send_buffers(struct file *filp,
-                                 drm_device_t *dev, drm_dma_t *d)
-{
-       DECLARE_WAITQUEUE(entry, current);
-       drm_buf_t         *last_buf = NULL;
-       int               retcode   = 0;
-       drm_device_dma_t  *dma      = dev->dma;
-       int               send_index;
-
-       if (get_user(send_index, &d->send_indices[d->send_count-1]))
-               return -EFAULT;
-
-       if (d->flags & _DRM_DMA_BLOCK) {
-               last_buf = dma->buflist[send_index];
-               add_wait_queue(&last_buf->dma_wait, &entry);
-       }
-
-       if ((retcode = gamma_dma_enqueue(filp, d))) {
-               if (d->flags & _DRM_DMA_BLOCK)
-                       remove_wait_queue(&last_buf->dma_wait, &entry);
-               return retcode;
-       }
-
-       gamma_dma_schedule(dev, 0);
-
-       if (d->flags & _DRM_DMA_BLOCK) {
-               DRM_DEBUG("%d waiting\n", current->pid);
-               for (;;) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       if (!last_buf->waiting && !last_buf->pending)
-                               break; /* finished */
-                       schedule();
-                       if (signal_pending(current)) {
-                               retcode = -EINTR; /* Can't restart */
-                               break;
-                       }
-               }
-               current->state = TASK_RUNNING;
-               DRM_DEBUG("%d running\n", current->pid);
-               remove_wait_queue(&last_buf->dma_wait, &entry);
-               if (!retcode
-                   || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
-                       if (!waitqueue_active(&last_buf->dma_wait)) {
-                               gamma_free_buffer(dev, last_buf);
-                       }
-               }
-               if (retcode) {
-                       DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d pid:%d\n",
-                                 d->context,
-                                 last_buf->waiting,
-                                 last_buf->pending,
-                                 (long)DRM_WAITCOUNT(dev, d->context),
-                                 last_buf->idx,
-                                 last_buf->list,
-                                 current->pid);
-               }
-       }
-       return retcode;
-}
-
-int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
-             unsigned long arg)
-{
-       drm_file_t        *priv     = filp->private_data;
-       drm_device_t      *dev      = priv->dev;
-       drm_device_dma_t  *dma      = dev->dma;
-       int               retcode   = 0;
-       drm_dma_t         __user *argp = (void __user *)arg;
-       drm_dma_t         d;
-
-       if (copy_from_user(&d, argp, sizeof(d)))
-               return -EFAULT;
-
-       if (d.send_count < 0 || d.send_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
-                         current->pid, d.send_count, dma->buf_count);
-               return -EINVAL;
-       }
-
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         current->pid, d.request_count, dma->buf_count);
-               return -EINVAL;
-       }
-
-       if (d.send_count) {
-               if (d.flags & _DRM_DMA_PRIORITY)
-                       retcode = gamma_dma_priority(filp, dev, &d);
-               else
-                       retcode = gamma_dma_send_buffers(filp, dev, &d);
-       }
-
-       d.granted_count = 0;
-
-       if (!retcode && d.request_count) {
-               retcode = gamma_dma_get_buffers(filp, &d);
-       }
-
-       DRM_DEBUG("%d returning, granted = %d\n",
-                 current->pid, d.granted_count);
-       if (copy_to_user(argp, &d, sizeof(d)))
-               return -EFAULT;
-
-       return retcode;
-}
-
-/* =============================================================
- * DMA initialization, cleanup
- */
-
-static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
-{
-       drm_gamma_private_t *dev_priv;
-       drm_device_dma_t    *dma = dev->dma;
-       drm_buf_t           *buf;
-       int i;
-       struct list_head    *list;
-       unsigned long       *pgt;
-
-       DRM_DEBUG( "%s\n", __FUNCTION__ );
-
-       dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t),
-                                                       DRM_MEM_DRIVER );
-       if ( !dev_priv )
-               return -ENOMEM;
-
-       dev->dev_private = (void *)dev_priv;
-
-       memset( dev_priv, 0, sizeof(drm_gamma_private_t) );
-
-       dev_priv->num_rast = init->num_rast;
-
-       list_for_each(list, &dev->maplist->head) {
-               drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
-               if( r_list->map &&
-                   r_list->map->type == _DRM_SHM &&
-                   r_list->map->flags & _DRM_CONTAINS_LOCK ) {
-                       dev_priv->sarea = r_list->map;
-                       break;
-               }
-       }
-       
-       dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);
-       dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);
-       dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);
-       dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);
-       
-       dev_priv->sarea_priv = (drm_gamma_sarea_t *)
-               ((u8 *)dev_priv->sarea->handle +
-                init->sarea_priv_offset);
-
-       if (init->pcimode) {
-               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
-               pgt = buf->address;
-
-               for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
-                       buf = dma->buflist[i];
-                       *pgt = virt_to_phys((void*)buf->address) | 0x07;
-                       pgt++;
-               }
-
-               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
-       } else {
-               dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
-               drm_core_ioremap( dev->agp_buffer_map, dev);
-
-               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
-               pgt = buf->address;
-
-               for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
-                       buf = dma->buflist[i];
-                       *pgt = (unsigned long)buf->address + 0x07;
-                       pgt++;
-               }
-
-               buf = dma->buflist[GLINT_DRI_BUF_COUNT];
-
-               while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1);
-               GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe);
-       }
-       while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
-       GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) );
-       GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 );
-
-       return 0;
-}
-
-int gamma_do_cleanup_dma( drm_device_t *dev )
-{
-       DRM_DEBUG( "%s\n", __FUNCTION__ );
-
-       /* 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.
-        */
-       if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-               if ( dev->irq_enabled ) 
-                       DRM(irq_uninstall)(dev);
-
-       if ( dev->dev_private ) {
-
-               if ( dev->agp_buffer_map != NULL )
-                       drm_core_ioremapfree( dev->agp_buffer_map, dev );
-
-               DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
-                          DRM_MEM_DRIVER );
-               dev->dev_private = NULL;
-       }
-
-       return 0;
-}
-
-int gamma_dma_init( struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg )
-{
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->dev;
-       drm_gamma_init_t init;
-
-       LOCK_TEST_WITH_RETURN( dev, filp );
-
-       if ( copy_from_user( &init, (drm_gamma_init_t __user *)arg, sizeof(init) ) )
-               return -EFAULT;
-
-       switch ( init.func ) {
-       case GAMMA_INIT_DMA:
-               return gamma_do_init_dma( dev, &init );
-       case GAMMA_CLEANUP_DMA:
-               return gamma_do_cleanup_dma( dev );
-       }
-
-       return -EINVAL;
-}
-
-static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy )
-{
-       drm_device_dma_t    *dma = dev->dma;
-       unsigned int        *screenbuf;
-
-       DRM_DEBUG( "%s\n", __FUNCTION__ );
-
-       /* We've DRM_RESTRICTED this DMA buffer */
-
-       screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address;
-
-#if 0
-       *buffer++ = 0x180;      /* Tag (FilterMode) */
-       *buffer++ = 0x200;      /* Allow FBColor through */
-       *buffer++ = 0x53B;      /* Tag */
-       *buffer++ = copy->Pitch;
-       *buffer++ = 0x53A;      /* Tag */
-       *buffer++ = copy->SrcAddress;
-       *buffer++ = 0x539;      /* Tag */
-       *buffer++ = copy->WidthHeight; /* Initiates transfer */
-       *buffer++ = 0x53C;      /* Tag - DMAOutputAddress */
-       *buffer++ = virt_to_phys((void*)screenbuf);
-       *buffer++ = 0x53D;      /* Tag - DMAOutputCount */
-       *buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/
-
-       /* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */
-       /* Now put it back to the screen */
-
-       *buffer++ = 0x180;      /* Tag (FilterMode) */
-       *buffer++ = 0x400;      /* Allow Sync through */
-       *buffer++ = 0x538;      /* Tag - DMARectangleReadTarget */
-       *buffer++ = 0x155;      /* FBSourceData | count */
-       *buffer++ = 0x537;      /* Tag */
-       *buffer++ = copy->Pitch;
-       *buffer++ = 0x536;      /* Tag */
-       *buffer++ = copy->DstAddress;
-       *buffer++ = 0x535;      /* Tag */
-       *buffer++ = copy->WidthHeight; /* Initiates transfer */
-       *buffer++ = 0x530;      /* Tag - DMAAddr */
-       *buffer++ = virt_to_phys((void*)screenbuf);
-       *buffer++ = 0x531;
-       *buffer++ = copy->Count; /* initiates DMA transfer of color data */
-#endif
-
-       /* need to dispatch it now */
-
-       return 0;
-}
-
-int gamma_dma_copy( struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg )
-{
-       drm_file_t *priv = filp->private_data;
-       drm_device_t *dev = priv->dev;
-       drm_gamma_copy_t copy;
-
-       if ( copy_from_user( &copy, (drm_gamma_copy_t __user *)arg, sizeof(copy) ) )
-               return -EFAULT;
-
-       return gamma_do_copy_dma( dev, &copy );
-}
-
-/* =============================================================
- * Per Context SAREA Support
- */
-
-int gamma_getsareactx(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
-{
-       drm_file_t      *priv   = filp->private_data;
-       drm_device_t    *dev    = priv->dev;
-       drm_ctx_priv_map_t __user *argp = (void __user *)arg;
-       drm_ctx_priv_map_t request;
-       drm_map_t *map;
-
-       if (copy_from_user(&request, argp, sizeof(request)))
-               return -EFAULT;
-
-       down(&dev->struct_sem);
-       if ((int)request.ctx_id >= dev->max_context) {
-               up(&dev->struct_sem);
-               return -EINVAL;
-       }
-
-       map = dev->context_sareas[request.ctx_id];
-       up(&dev->struct_sem);
-
-       request.handle = map->handle;
-       if (copy_to_user(argp, &request, sizeof(request)))
-               return -EFAULT;
-       return 0;
-}
-
-int gamma_setsareactx(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
-{
-       drm_file_t      *priv   = filp->private_data;
-       drm_device_t    *dev    = priv->dev;
-       drm_ctx_priv_map_t request;
-       drm_map_t *map = NULL;
-       drm_map_list_t *r_list;
-       struct list_head *list;
-
-       if (copy_from_user(&request,
-                          (drm_ctx_priv_map_t __user *)arg,
-                          sizeof(request)))
-               return -EFAULT;
-
-       down(&dev->struct_sem);
-       r_list = NULL;
-       list_for_each(list, &dev->maplist->head) {
-               r_list = list_entry(list, drm_map_list_t, head);
-               if(r_list->map &&
-                  r_list->map->handle == request.handle) break;
-       }
-       if (list == &(dev->maplist->head)) {
-               up(&dev->struct_sem);
-               return -EINVAL;
-       }
-       map = r_list->map;
-       up(&dev->struct_sem);
-
-       if (!map) return -EINVAL;
-
-       down(&dev->struct_sem);
-       if ((int)request.ctx_id >= dev->max_context) {
-               up(&dev->struct_sem);
-               return -EINVAL;
-       }
-       dev->context_sareas[request.ctx_id] = map;
-       up(&dev->struct_sem);
-       return 0;
-}
-
-void gamma_driver_irq_preinstall( drm_device_t *dev ) {
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-
-       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2)
-               cpu_relax();
-
-       GAMMA_WRITE( GAMMA_GCOMMANDMODE,        0x00000004 );
-       GAMMA_WRITE( GAMMA_GDMACONTROL,         0x00000000 );
-}
-
-void gamma_driver_irq_postinstall( drm_device_t *dev ) {
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-
-       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-               cpu_relax();
-
-       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00002001 );
-       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000008 );
-       GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00039090 );
-}
-
-void gamma_driver_irq_uninstall( drm_device_t *dev ) {
-       drm_gamma_private_t *dev_priv =
-                               (drm_gamma_private_t *)dev->dev_private;
-       if (!dev_priv)
-               return;
-
-       while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-               cpu_relax();
-
-       GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00000000 );
-       GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000000 );
-       GAMMA_WRITE( GAMMA_GINTENABLE,          0x00000000 );
-}
-
-extern drm_ioctl_desc_t DRM(ioctls)[];
-
-static int gamma_driver_preinit(drm_device_t *dev)
-{
-       /* reset the finish ioctl */
-       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);
-       return 0;
-}
-
-static void gamma_driver_pretakedown(drm_device_t *dev)
-{
-       gamma_do_cleanup_dma(dev);
-}
-
-static void gamma_driver_dma_ready(drm_device_t *dev)
-{
-       gamma_dma_ready(dev);
-}
-
-static int gamma_driver_dma_quiescent(drm_device_t *dev)
-{
-       drm_gamma_private_t *dev_priv = (
-               drm_gamma_private_t *)dev->dev_private;
-       if (dev_priv->num_rast == 2)
-               gamma_dma_quiescent_dual(dev);
-       else gamma_dma_quiescent_single(dev);
-       return 0;
-}
-
-void gamma_driver_register_fns(drm_device_t *dev)
-{
-       dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
-       DRM(fops).read = gamma_fops_read;
-       DRM(fops).poll = gamma_fops_poll;
-       dev->driver.preinit = gamma_driver_preinit;
-       dev->driver.pretakedown = gamma_driver_pretakedown;
-       dev->driver.dma_ready = gamma_driver_dma_ready;
-       dev->driver.dma_quiescent = gamma_driver_dma_quiescent;
-       dev->driver.dma_flush_block_and_flush = gamma_flush_block_and_flush;
-       dev->driver.dma_flush_unblock = gamma_flush_unblock;
-}
diff --git a/drivers/char/drm/gamma_drm.h b/drivers/char/drm/gamma_drm.h
deleted file mode 100644 (file)
index 20819de..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef _GAMMA_DRM_H_
-#define _GAMMA_DRM_H_
-
-typedef struct _drm_gamma_tex_region {
-       unsigned char next, prev; /* indices to form a circular LRU  */
-       unsigned char in_use;   /* owned by a client, or free? */
-       int age;                /* tracked by clients to update local LRU's */
-} drm_gamma_tex_region_t;
-
-typedef struct {
-       unsigned int    GDeltaMode;
-       unsigned int    GDepthMode;
-       unsigned int    GGeometryMode;
-       unsigned int    GTransformMode;
-} drm_gamma_context_regs_t;
-
-typedef struct _drm_gamma_sarea {
-       drm_gamma_context_regs_t context_state;
-
-       unsigned int dirty;
-
-
-       /* Maintain an LRU of contiguous regions of texture space.  If
-        * you think you own a region of texture memory, and it has an
-        * age different to the one you set, then you are mistaken and
-        * it has been stolen by another client.  If global texAge
-        * hasn't changed, there is no need to walk the list.
-        *
-        * These regions can be used as a proxy for the fine-grained
-        * texture information of other clients - by maintaining them
-        * in the same lru which is used to age their own textures,
-        * clients have an approximate lru for the whole of global
-        * texture space, and can make informed decisions as to which
-        * areas to kick out.  There is no need to choose whether to
-        * kick out your own texture or someone else's - simply eject
-        * them all in LRU order.  
-        */
-   
-#define GAMMA_NR_TEX_REGIONS 64
-       drm_gamma_tex_region_t texList[GAMMA_NR_TEX_REGIONS+1]; 
-                               /* Last elt is sentinal */
-        int texAge;            /* last time texture was uploaded */
-        int last_enqueue;      /* last time a buffer was enqueued */
-       int last_dispatch;      /* age of the most recently dispatched buffer */
-       int last_quiescent;     /*  */
-       int ctxOwner;           /* last context to upload state */
-
-       int vertex_prim;
-} drm_gamma_sarea_t;
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmGamma.h)
- */
-
-/* Gamma specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_IOCTL_GAMMA_INIT           DRM_IOW( 0x40, drm_gamma_init_t)
-#define DRM_IOCTL_GAMMA_COPY           DRM_IOW( 0x41, drm_gamma_copy_t)
-
-typedef struct drm_gamma_copy {
-       unsigned int    DMAOutputAddress;
-       unsigned int    DMAOutputCount;
-       unsigned int    DMAReadGLINTSource;
-       unsigned int    DMARectangleWriteAddress;
-       unsigned int    DMARectangleWriteLinePitch;
-       unsigned int    DMARectangleWrite;
-       unsigned int    DMARectangleReadAddress;
-       unsigned int    DMARectangleReadLinePitch;
-       unsigned int    DMARectangleRead;
-       unsigned int    DMARectangleReadTarget;
-} drm_gamma_copy_t;
-
-typedef struct drm_gamma_init {
-       enum {
-               GAMMA_INIT_DMA    = 0x01,
-               GAMMA_CLEANUP_DMA = 0x02
-       } func;
-
-       int sarea_priv_offset;
-       int pcimode;
-       unsigned int mmio0;
-       unsigned int mmio1;
-       unsigned int mmio2;
-       unsigned int mmio3;
-       unsigned int buffers_offset;
-       int num_rast;
-} drm_gamma_init_t;
-
-#endif /* _GAMMA_DRM_H_ */
diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
deleted file mode 100644 (file)
index e7e64b6..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* gamma.c -- 3dlabs GMX 2000 driver -*- linux-c -*-
- * Created: Mon Jan  4 08:58:31 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include <linux/config.h>
-#include "gamma.h"
-#include "drmP.h"
-#include "drm.h"
-#include "gamma_drm.h"
-#include "gamma_drv.h"
-
-#include "drm_auth.h"
-#include "drm_agpsupport.h"
-#include "drm_bufs.h"
-#include "gamma_context.h"     /* NOTE! */
-#include "drm_dma.h"
-#include "gamma_old_dma.h"     /* NOTE */
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "gamma_lists.h"        /* NOTE */
-#include "drm_lock.h"
-#include "gamma_lock.h"                /* NOTE */
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
-#include "drm_scatter.h"
diff --git a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h
deleted file mode 100644 (file)
index 146fcc6..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* gamma_drv.h -- Private header for 3dlabs GMX 2000 driver -*- linux-c -*-
- * Created: Mon Jan  4 10:05:05 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#ifndef _GAMMA_DRV_H_
-#define _GAMMA_DRV_H_
-
-typedef struct drm_gamma_private {
-       drm_gamma_sarea_t *sarea_priv;
-       drm_map_t *sarea;
-       drm_map_t *mmio0;
-       drm_map_t *mmio1;
-       drm_map_t *mmio2;
-       drm_map_t *mmio3;
-       int num_rast;
-} drm_gamma_private_t;
-
-                               /* gamma_dma.c */
-extern int gamma_dma_init( struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg );
-extern int gamma_dma_copy( struct inode *inode, struct file *filp,
-                        unsigned int cmd, unsigned long arg );
-
-extern int gamma_do_cleanup_dma( drm_device_t *dev );
-extern void gamma_dma_ready(drm_device_t *dev);
-extern void gamma_dma_quiescent_single(drm_device_t *dev);
-extern void gamma_dma_quiescent_dual(drm_device_t *dev);
-
-                               /* gamma_dma.c */
-extern int  gamma_dma_schedule(drm_device_t *dev, int locked);
-extern int  gamma_dma(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
-extern int  gamma_find_devices(void);
-extern int  gamma_found(void);
-
-/* Gamma-specific code pulled from drm_fops.h:
- */
-extern int          DRM(finish)(struct inode *inode, struct file *filp,
-                                unsigned int cmd, unsigned long arg);
-extern int          DRM(flush_unblock)(drm_device_t *dev, int context,
-                                       drm_lock_flags_t flags);
-extern int          DRM(flush_block_and_flush)(drm_device_t *dev, int context,
-                                               drm_lock_flags_t flags);
-
-/* Gamma-specific code pulled from drm_dma.h:
- */
-extern void         DRM(clear_next_buffer)(drm_device_t *dev);
-extern int          DRM(select_queue)(drm_device_t *dev,
-                                      void (*wrapper)(unsigned long));
-extern int          DRM(dma_enqueue)(struct file *filp, drm_dma_t *dma);
-extern int          DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma);
-
-
-/* Gamma-specific code pulled from drm_lists.h (now renamed gamma_lists.h):
- */
-extern int          DRM(waitlist_create)(drm_waitlist_t *bl, int count);
-extern int          DRM(waitlist_destroy)(drm_waitlist_t *bl);
-extern int          DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf);
-extern drm_buf_t     *DRM(waitlist_get)(drm_waitlist_t *bl);
-extern int          DRM(freelist_create)(drm_freelist_t *bl, int count);
-extern int          DRM(freelist_destroy)(drm_freelist_t *bl);
-extern int          DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
-                                      drm_buf_t *buf);
-extern drm_buf_t     *DRM(freelist_get)(drm_freelist_t *bl, int block);
-
-/* externs for gamma changes to the ops */
-extern struct file_operations DRM(fops);
-extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait);
-extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
-
-
-#define GLINT_DRI_BUF_COUNT 256
-
-#define GAMMA_OFF(reg)                                            \
-       ((reg < 0x1000)                                            \
-        ? reg                                                     \
-        : ((reg < 0x10000)                                        \
-           ? (reg - 0x1000)                                       \
-           : ((reg < 0x11000)                                     \
-              ? (reg - 0x10000)                                   \
-              : (reg - 0x11000))))
-
-#define GAMMA_BASE(reg)         ((unsigned long)                                    \
-                         ((reg < 0x1000)    ? dev_priv->mmio0->handle :     \
-                          ((reg < 0x10000)  ? dev_priv->mmio1->handle :     \
-                           ((reg < 0x11000) ? dev_priv->mmio2->handle :     \
-                                              dev_priv->mmio3->handle))))
-#define GAMMA_ADDR(reg)         (GAMMA_BASE(reg) + GAMMA_OFF(reg))
-#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
-#define GAMMA_READ(reg)         GAMMA_DEREF(reg)
-#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
-
-#define GAMMA_BROADCASTMASK    0x9378
-#define GAMMA_COMMANDINTENABLE 0x0c48
-#define GAMMA_DMAADDRESS       0x0028
-#define GAMMA_DMACOUNT        0x0030
-#define GAMMA_FILTERMODE       0x8c00
-#define GAMMA_GCOMMANDINTFLAGS 0x0c50
-#define GAMMA_GCOMMANDMODE     0x0c40
-#define                GAMMA_QUEUED_DMA_MODE           1<<1
-#define GAMMA_GCOMMANDSTATUS   0x0c60
-#define GAMMA_GDELAYTIMER      0x0c38
-#define GAMMA_GDMACONTROL      0x0060
-#define        GAMMA_USE_AGP                   1<<1
-#define GAMMA_GINTENABLE       0x0808
-#define GAMMA_GINTFLAGS               0x0810
-#define GAMMA_INFIFOSPACE      0x0018
-#define GAMMA_OUTFIFOWORDS     0x0020
-#define GAMMA_OUTPUTFIFO       0x2000
-#define GAMMA_SYNC            0x8c40
-#define GAMMA_SYNC_TAG        0x0188
-#define GAMMA_PAGETABLEADDR    0x0C00
-#define GAMMA_PAGETABLELENGTH  0x0C08
-
-#define GAMMA_PASSTHROUGH      0x1FE
-#define GAMMA_DMAADDRTAG       0x530
-#define GAMMA_DMACOUNTTAG      0x531
-#define GAMMA_COMMANDINTTAG    0x532
-
-#endif
diff --git a/drivers/char/drm/gamma_lists.h b/drivers/char/drm/gamma_lists.h
deleted file mode 100644 (file)
index 2d93f41..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* drm_lists.h -- Buffer list handling routines -*- linux-c -*-
- * Created: Mon Apr 19 20:54:22 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-
-
-int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
-{
-       if (bl->count) return -EINVAL;
-
-       bl->bufs       = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
-                                   DRM_MEM_BUFLISTS);
-
-       if(!bl->bufs) return -ENOMEM;
-       memset(bl->bufs, 0, sizeof(*bl->bufs));
-       bl->count      = count;
-       bl->rp         = bl->bufs;
-       bl->wp         = bl->bufs;
-       bl->end        = &bl->bufs[bl->count+1];
-       spin_lock_init(&bl->write_lock);
-       spin_lock_init(&bl->read_lock);
-       return 0;
-}
-
-int DRM(waitlist_destroy)(drm_waitlist_t *bl)
-{
-       if (bl->rp != bl->wp) return -EINVAL;
-       if (bl->bufs) DRM(free)(bl->bufs,
-                               (bl->count + 2) * sizeof(*bl->bufs),
-                               DRM_MEM_BUFLISTS);
-       bl->count = 0;
-       bl->bufs  = NULL;
-       bl->rp    = NULL;
-       bl->wp    = NULL;
-       bl->end   = NULL;
-       return 0;
-}
-
-int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
-{
-       int           left;
-       unsigned long flags;
-
-       left = DRM_LEFTCOUNT(bl);
-       if (!left) {
-               DRM_ERROR("Overflow while adding buffer %d from filp %p\n",
-                         buf->idx, buf->filp);
-               return -EINVAL;
-       }
-       buf->list        = DRM_LIST_WAIT;
-
-       spin_lock_irqsave(&bl->write_lock, flags);
-       *bl->wp = buf;
-       if (++bl->wp >= bl->end) bl->wp = bl->bufs;
-       spin_unlock_irqrestore(&bl->write_lock, flags);
-
-       return 0;
-}
-
-drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
-{
-       drm_buf_t     *buf;
-       unsigned long flags;
-
-       spin_lock_irqsave(&bl->read_lock, flags);
-       buf = *bl->rp;
-       if (bl->rp == bl->wp) {
-               spin_unlock_irqrestore(&bl->read_lock, flags);
-               return NULL;
-       }
-       if (++bl->rp >= bl->end) bl->rp = bl->bufs;
-       spin_unlock_irqrestore(&bl->read_lock, flags);
-
-       return buf;
-}
-
-int DRM(freelist_create)(drm_freelist_t *bl, int count)
-{
-       atomic_set(&bl->count, 0);
-       bl->next      = NULL;
-       init_waitqueue_head(&bl->waiting);
-       bl->low_mark  = 0;
-       bl->high_mark = 0;
-       atomic_set(&bl->wfh,   0);
-       spin_lock_init(&bl->lock);
-       ++bl->initialized;
-       return 0;
-}
-
-int DRM(freelist_destroy)(drm_freelist_t *bl)
-{
-       atomic_set(&bl->count, 0);
-       bl->next = NULL;
-       return 0;
-}
-
-int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
-{
-       drm_device_dma_t *dma  = dev->dma;
-
-       if (!dma) {
-               DRM_ERROR("No DMA support\n");
-               return 1;
-       }
-
-       if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
-               DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
-                         buf->idx, buf->waiting, buf->pending, buf->list);
-       }
-       if (!bl) return 1;
-       buf->list       = DRM_LIST_FREE;
-
-       spin_lock(&bl->lock);
-       buf->next       = bl->next;
-       bl->next        = buf;
-       spin_unlock(&bl->lock);
-
-       atomic_inc(&bl->count);
-       if (atomic_read(&bl->count) > dma->buf_count) {
-               DRM_ERROR("%d of %d buffers free after addition of %d\n",
-                         atomic_read(&bl->count), dma->buf_count, buf->idx);
-               return 1;
-       }
-                               /* Check for high water mark */
-       if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
-               atomic_set(&bl->wfh, 0);
-               wake_up_interruptible(&bl->waiting);
-       }
-       return 0;
-}
-
-static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
-{
-       drm_buf_t         *buf;
-
-       if (!bl) return NULL;
-
-                               /* Get buffer */
-       spin_lock(&bl->lock);
-       if (!bl->next) {
-               spin_unlock(&bl->lock);
-               return NULL;
-       }
-       buf       = bl->next;
-       bl->next  = bl->next->next;
-       spin_unlock(&bl->lock);
-
-       atomic_dec(&bl->count);
-       buf->next = NULL;
-       buf->list = DRM_LIST_NONE;
-       if (buf->waiting || buf->pending) {
-               DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
-                         buf->idx, buf->waiting, buf->pending, buf->list);
-       }
-
-       return buf;
-}
-
-drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
-{
-       drm_buf_t         *buf  = NULL;
-       DECLARE_WAITQUEUE(entry, current);
-
-       if (!bl || !bl->initialized) return NULL;
-
-                               /* Check for low water mark */
-       if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
-               atomic_set(&bl->wfh, 1);
-       if (atomic_read(&bl->wfh)) {
-               if (block) {
-                       add_wait_queue(&bl->waiting, &entry);
-                       for (;;) {
-                               current->state = TASK_INTERRUPTIBLE;
-                               if (!atomic_read(&bl->wfh)
-                                   && (buf = DRM(freelist_try)(bl))) break;
-                               schedule();
-                               if (signal_pending(current)) break;
-                       }
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(&bl->waiting, &entry);
-               }
-               return buf;
-       }
-
-       return DRM(freelist_try)(bl);
-}
-
diff --git a/drivers/char/drm/gamma_lock.h b/drivers/char/drm/gamma_lock.h
deleted file mode 100644 (file)
index ddec67e..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/* 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.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-
-/* Gamma-specific code extracted from drm_lock.h:
- */
-static int DRM(flush_queue)(drm_device_t *dev, int context)
-{
-       DECLARE_WAITQUEUE(entry, current);
-       int               ret   = 0;
-       drm_queue_t       *q    = dev->queuelist[context];
-
-       DRM_DEBUG("\n");
-
-       atomic_inc(&q->use_count);
-       if (atomic_read(&q->use_count) > 1) {
-               atomic_inc(&q->block_write);
-               add_wait_queue(&q->flush_queue, &entry);
-               atomic_inc(&q->block_count);
-               for (;;) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       if (!DRM_BUFCOUNT(&q->waitlist)) break;
-                       schedule();
-                       if (signal_pending(current)) {
-                               ret = -EINTR; /* Can't restart */
-                               break;
-                       }
-               }
-               atomic_dec(&q->block_count);
-               current->state = TASK_RUNNING;
-               remove_wait_queue(&q->flush_queue, &entry);
-       }
-       atomic_dec(&q->use_count);
-
-                               /* NOTE: block_write is still incremented!
-                                  Use drm_flush_unlock_queue to decrement. */
-       return ret;
-}
-
-static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
-{
-       drm_queue_t       *q    = dev->queuelist[context];
-
-       DRM_DEBUG("\n");
-
-       atomic_inc(&q->use_count);
-       if (atomic_read(&q->use_count) > 1) {
-               if (atomic_read(&q->block_write)) {
-                       atomic_dec(&q->block_write);
-                       wake_up_interruptible(&q->write_queue);
-               }
-       }
-       atomic_dec(&q->use_count);
-       return 0;
-}
-
-int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
-                              drm_lock_flags_t flags)
-{
-       int ret = 0;
-       int i;
-
-       DRM_DEBUG("\n");
-
-       if (flags & _DRM_LOCK_FLUSH) {
-               ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
-               if (!ret) ret = DRM(flush_queue)(dev, context);
-       }
-       if (flags & _DRM_LOCK_FLUSH_ALL) {
-               for (i = 0; !ret && i < dev->queue_count; i++) {
-                       ret = DRM(flush_queue)(dev, i);
-               }
-       }
-       return ret;
-}
-
-int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
-{
-       int ret = 0;
-       int i;
-
-       DRM_DEBUG("\n");
-
-       if (flags & _DRM_LOCK_FLUSH) {
-               ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
-               if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
-       }
-       if (flags & _DRM_LOCK_FLUSH_ALL) {
-               for (i = 0; !ret && i < dev->queue_count; i++) {
-                       ret = DRM(flush_unblock_queue)(dev, i);
-               }
-       }
-
-       return ret;
-}
-
-int DRM(finish)(struct inode *inode, struct file *filp, unsigned int cmd,
-               unsigned long arg)
-{
-       drm_file_t        *priv   = filp->private_data;
-       drm_device_t      *dev    = priv->dev;
-       int               ret     = 0;
-       drm_lock_t        lock;
-
-       DRM_DEBUG("\n");
-
-       if (copy_from_user(&lock, (drm_lock_t __user *)arg, sizeof(lock)))
-               return -EFAULT;
-       ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
-       DRM(flush_unblock)(dev, lock.context, lock.flags);
-       return ret;
-}
diff --git a/drivers/char/drm/gamma_old_dma.h b/drivers/char/drm/gamma_old_dma.h
deleted file mode 100644 (file)
index abdd454..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/* 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.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-
-/* Gamma-specific code pulled from drm_dma.h:
- */
-
-void DRM(clear_next_buffer)(drm_device_t *dev)
-{
-       drm_device_dma_t *dma = dev->dma;
-
-       dma->next_buffer = NULL;
-       if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
-               wake_up_interruptible(&dma->next_queue->flush_queue);
-       }
-       dma->next_queue  = NULL;
-}
-
-int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
-{
-       int        i;
-       int        candidate = -1;
-       int        j         = jiffies;
-
-       if (!dev) {
-               DRM_ERROR("No device\n");
-               return -1;
-       }
-       if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
-                               /* This only happens between the time the
-                                  interrupt is initialized and the time
-                                  the queues are initialized. */
-               return -1;
-       }
-
-                               /* Doing "while locked" DMA? */
-       if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
-               return DRM_KERNEL_CONTEXT;
-       }
-
-                               /* If there are buffers on the last_context
-                                  queue, and we have not been executing
-                                  this context very long, continue to
-                                  execute this context. */
-       if (dev->last_switch <= j
-           && dev->last_switch + DRM_TIME_SLICE > j
-           && DRM_WAITCOUNT(dev, dev->last_context)) {
-               return dev->last_context;
-       }
-
-                               /* Otherwise, find a candidate */
-       for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
-               if (DRM_WAITCOUNT(dev, i)) {
-                       candidate = dev->last_checked = i;
-                       break;
-               }
-       }
-
-       if (candidate < 0) {
-               for (i = 0; i < dev->queue_count; i++) {
-                       if (DRM_WAITCOUNT(dev, i)) {
-                               candidate = dev->last_checked = i;
-                               break;
-                       }
-               }
-       }
-
-       if (wrapper
-           && candidate >= 0
-           && candidate != dev->last_context
-           && dev->last_switch <= j
-           && dev->last_switch + DRM_TIME_SLICE > j) {
-               if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
-                       del_timer(&dev->timer);
-                       dev->timer.function = wrapper;
-                       dev->timer.data     = (unsigned long)dev;
-                       dev->timer.expires  = dev->last_switch+DRM_TIME_SLICE;
-                       add_timer(&dev->timer);
-               }
-               return -1;
-       }
-
-       return candidate;
-}
-
-
-int DRM(dma_enqueue)(struct file *filp, drm_dma_t *d)
-{
-       drm_file_t    *priv   = filp->private_data;
-       drm_device_t  *dev    = priv->dev;
-       int               i;
-       drm_queue_t       *q;
-       drm_buf_t         *buf;
-       int               idx;
-       int               while_locked = 0;
-       drm_device_dma_t  *dma = dev->dma;
-       int               *ind;
-       int               err;
-       DECLARE_WAITQUEUE(entry, current);
-
-       DRM_DEBUG("%d\n", d->send_count);
-
-       if (d->flags & _DRM_DMA_WHILE_LOCKED) {
-               int context = dev->lock.hw_lock->lock;
-
-               if (!_DRM_LOCK_IS_HELD(context)) {
-                       DRM_ERROR("No lock held during \"while locked\""
-                                 " request\n");
-                       return -EINVAL;
-               }
-               if (d->context != _DRM_LOCKING_CONTEXT(context)
-                   && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
-                       DRM_ERROR("Lock held by %d while %d makes"
-                                 " \"while locked\" request\n",
-                                 _DRM_LOCKING_CONTEXT(context),
-                                 d->context);
-                       return -EINVAL;
-               }
-               q = dev->queuelist[DRM_KERNEL_CONTEXT];
-               while_locked = 1;
-       } else {
-               q = dev->queuelist[d->context];
-       }
-
-
-       atomic_inc(&q->use_count);
-       if (atomic_read(&q->block_write)) {
-               add_wait_queue(&q->write_queue, &entry);
-               atomic_inc(&q->block_count);
-               for (;;) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       if (!atomic_read(&q->block_write)) break;
-                       schedule();
-                       if (signal_pending(current)) {
-                               atomic_dec(&q->use_count);
-                               remove_wait_queue(&q->write_queue, &entry);
-                               return -EINTR;
-                       }
-               }
-               atomic_dec(&q->block_count);
-               current->state = TASK_RUNNING;
-               remove_wait_queue(&q->write_queue, &entry);
-       }
-
-       ind = DRM(alloc)(d->send_count * sizeof(int), DRM_MEM_DRIVER);
-       if (!ind)
-               return -ENOMEM;
-
-       if (copy_from_user(ind, d->send_indices, d->send_count * sizeof(int))) {
-               err = -EFAULT;
-                goto out;
-       }
-
-       err = -EINVAL;
-       for (i = 0; i < d->send_count; i++) {
-               idx = ind[i];
-               if (idx < 0 || idx >= dma->buf_count) {
-                       DRM_ERROR("Index %d (of %d max)\n",
-                                 ind[i], dma->buf_count - 1);
-                       goto out;
-               }
-               buf = dma->buflist[ idx ];
-               if (buf->filp != filp) {
-                       DRM_ERROR("Process %d using buffer not owned\n",
-                                 current->pid);
-                       goto out;
-               }
-               if (buf->list != DRM_LIST_NONE) {
-                       DRM_ERROR("Process %d using buffer %d on list %d\n",
-                                 current->pid, buf->idx, buf->list);
-                       goto out;
-               }
-               buf->used         = ind[i];
-               buf->while_locked = while_locked;
-               buf->context      = d->context;
-               if (!buf->used) {
-                       DRM_ERROR("Queueing 0 length buffer\n");
-               }
-               if (buf->pending) {
-                       DRM_ERROR("Queueing pending buffer:"
-                                 " buffer %d, offset %d\n",
-                                 ind[i], i);
-                       goto out;
-               }
-               if (buf->waiting) {
-                       DRM_ERROR("Queueing waiting buffer:"
-                                 " buffer %d, offset %d\n",
-                                 ind[i], i);
-                       goto out;
-               }
-               buf->waiting = 1;
-               if (atomic_read(&q->use_count) == 1
-                   || atomic_read(&q->finalization)) {
-                       DRM(free_buffer)(dev, buf);
-               } else {
-                       DRM(waitlist_put)(&q->waitlist, buf);
-                       atomic_inc(&q->total_queued);
-               }
-       }
-       atomic_dec(&q->use_count);
-
-       return 0;
-
-out:
-       DRM(free)(ind, d->send_count * sizeof(int), DRM_MEM_DRIVER);
-       atomic_dec(&q->use_count);
-       return err;
-}
-
-static int DRM(dma_get_buffers_of_order)(struct file *filp, drm_dma_t *d,
-                                        int order)
-{
-       drm_file_t    *priv   = filp->private_data;
-       drm_device_t  *dev    = priv->dev;
-       int               i;
-       drm_buf_t         *buf;
-       drm_device_dma_t  *dma = dev->dma;
-
-       for (i = d->granted_count; i < d->request_count; i++) {
-               buf = DRM(freelist_get)(&dma->bufs[order].freelist,
-                                       d->flags & _DRM_DMA_WAIT);
-               if (!buf) break;
-               if (buf->pending || buf->waiting) {
-                       DRM_ERROR("Free buffer %d in use: filp %p (w%d, p%d)\n",
-                                 buf->idx,
-                                 buf->filp,
-                                 buf->waiting,
-                                 buf->pending);
-               }
-               buf->filp     = filp;
-               if (copy_to_user(&d->request_indices[i],
-                                &buf->idx,
-                                sizeof(buf->idx)))
-                       return -EFAULT;
-
-               if (copy_to_user(&d->request_sizes[i],
-                                &buf->total,
-                                sizeof(buf->total)))
-                       return -EFAULT;
-
-               ++d->granted_count;
-       }
-       return 0;
-}
-
-
-int DRM(dma_get_buffers)(struct file *filp, drm_dma_t *dma)
-{
-       int               order;
-       int               retcode = 0;
-       int               tmp_order;
-
-       order = DRM(order)(dma->request_size);
-
-       dma->granted_count = 0;
-       retcode            = DRM(dma_get_buffers_of_order)(filp, dma, order);
-
-       if (dma->granted_count < dma->request_count
-           && (dma->flags & _DRM_DMA_SMALLER_OK)) {
-               for (tmp_order = order - 1;
-                    !retcode
-                            && dma->granted_count < dma->request_count
-                            && tmp_order >= DRM_MIN_ORDER;
-                    --tmp_order) {
-
-                       retcode = DRM(dma_get_buffers_of_order)(filp, dma,
-                                                               tmp_order);
-               }
-       }
-
-       if (dma->granted_count < dma->request_count
-           && (dma->flags & _DRM_DMA_LARGER_OK)) {
-               for (tmp_order = order + 1;
-                    !retcode
-                            && dma->granted_count < dma->request_count
-                            && tmp_order <= DRM_MAX_ORDER;
-                    ++tmp_order) {
-
-                       retcode = DRM(dma_get_buffers_of_order)(filp, dma,
-                                                               tmp_order);
-               }
-       }
-       return 0;
-}
-
index 18e0b76228937d5236f4f55ee820b573353ed819..2f1659b96fd13771e64b24ad67c854baab4418a1 100644 (file)
 #define I810_BUF_UNMAPPED 0
 #define I810_BUF_MAPPED   1
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
-#define down_write down
-#define up_write up
-#endif
-
 static drm_buf_t *i810_freelist_get(drm_device_t *dev)
 {
        drm_device_dma_t *dma = dev->dma;
@@ -351,6 +346,7 @@ static int i810_dma_initialize(drm_device_t *dev,
                DRM_ERROR("can not find mmio map!\n");
                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) {
                dev->dev_private = (void *)dev_priv;
@@ -1383,3 +1379,19 @@ drm_ioctl_desc_t i810_ioctls[] = {
 };
 
 int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i810 is AGP.
+ */
+int i810_driver_device_is_agp(drm_device_t * dev)
+{
+       return 1;
+}
index ff51b3259af9268ef4ac34e1743ed4d634ed43b9..00609329d5786be3e0671483dc07a5dacbd26116 100644 (file)
@@ -84,6 +84,7 @@ static struct drm_driver driver = {
        .dev_priv_size = sizeof(drm_i810_buf_priv_t),
        .pretakedown = i810_driver_pretakedown,
        .prerelease = i810_driver_prerelease,
+       .device_is_agp = i810_driver_device_is_agp,
        .release = i810_driver_release,
        .dma_quiescent = i810_driver_dma_quiescent,
        .reclaim_buffers = i810_reclaim_buffers,
index 1b40538d1725041d3dff8c603ef54b7adf4d1552..62ee4f58c59a97d7ab5186a0de5b6ad4719ea438 100644 (file)
@@ -120,6 +120,7 @@ extern int i810_driver_dma_quiescent(drm_device_t *dev);
 extern void i810_driver_release(drm_device_t *dev, struct file *filp);
 extern void i810_driver_pretakedown(drm_device_t *dev);
 extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern int i810_driver_device_is_agp(drm_device_t * dev);
 
 #define I810_BASE(reg)         ((unsigned long) \
                                dev_priv->mmio_map->handle)
index dc7733035864d9e2e058e0b86766bec7d1e11643..6f89d5796ef3b58f8d0e5bf113e6bb691de0e450 100644 (file)
 #define I830_BUF_UNMAPPED 0
 #define I830_BUF_MAPPED   1
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
-#define down_write down
-#define up_write up
-#endif
-
 static drm_buf_t *i830_freelist_get(drm_device_t *dev)
 {
        drm_device_dma_t *dma = dev->dma;
@@ -358,6 +353,7 @@ static int i830_dma_initialize(drm_device_t *dev,
                DRM_ERROR("can not find mmio map!\n");
                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) {
                dev->dev_private = (void *)dev_priv;
@@ -1586,3 +1582,19 @@ drm_ioctl_desc_t i830_ioctls[] = {
 };
 
 int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i8xx is AGP.
+ */
+int i830_driver_device_is_agp(drm_device_t * dev)
+{
+       return 1;
+}
index bc36be76b8b238f79f13b4cdf0125fa7513a0cce..0da9cd19919e619369a480ae9bb707fa19b835a7 100644 (file)
@@ -88,6 +88,7 @@ static struct drm_driver driver = {
        .dev_priv_size = sizeof(drm_i830_buf_priv_t),
        .pretakedown = i830_driver_pretakedown,
        .prerelease = i830_driver_prerelease,
+       .device_is_agp = i830_driver_device_is_agp,
        .release = i830_driver_release,
        .dma_quiescent = i830_driver_dma_quiescent,
        .reclaim_buffers = i830_reclaim_buffers,
index df7746131dea80b1866d938c72cfda6c4e24e9a2..63f96a8b6a4a5bd77190ed07b49d69fe471f4b80 100644 (file)
@@ -137,6 +137,7 @@ extern void i830_driver_pretakedown(drm_device_t *dev);
 extern void i830_driver_release(drm_device_t *dev, struct file *filp);
 extern int i830_driver_dma_quiescent(drm_device_t *dev);
 extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern int i830_driver_device_is_agp(drm_device_t * dev);
 
 #define I830_BASE(reg)         ((unsigned long) \
                                dev_priv->mmio_map->handle)
index acf9e52a9507ff9293d0cd629a450289487d9774..34f552f90c4a82aaa857f8955e909c15c0ef28a3 100644 (file)
@@ -95,9 +95,8 @@ static int i915_dma_cleanup(drm_device_t * dev)
                        drm_core_ioremapfree( &dev_priv->ring.map, dev);
                }
 
-               if (dev_priv->hw_status_page) {
-                       drm_pci_free(dev, PAGE_SIZE, dev_priv->hw_status_page,
-                                    dev_priv->dma_status_page);
+               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);
                }
@@ -174,16 +173,18 @@ static int i915_initialize(drm_device_t * dev,
        dev_priv->allow_batchbuffer = 1;
 
        /* Program Hardware Status Page */
-       dev_priv->hw_status_page = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
-                                                0xffffffff, 
-                                                &dev_priv->dma_status_page);
+       dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
+                                                  0xffffffff);
 
-       if (!dev_priv->hw_status_page) {
+       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);
 
@@ -731,3 +732,19 @@ drm_ioctl_desc_t i915_ioctls[] = {
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i9x5 is AGP.
+ */
+int i915_driver_device_is_agp(drm_device_t * dev)
+{
+       return 1;
+}
index 1f59d3fc79bcdabcbf0715556c3010c5be60a1b3..106b9ec022133316f67e9c5ae3d05c4764f09f5b 100644 (file)
@@ -79,6 +79,7 @@ static struct drm_driver driver = {
                                DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
        .pretakedown = i915_driver_pretakedown,
        .prerelease = i915_driver_prerelease,
+       .device_is_agp = i915_driver_device_is_agp,
        .irq_preinstall = i915_driver_irq_preinstall,
        .irq_postinstall = i915_driver_irq_postinstall,
        .irq_uninstall = i915_driver_irq_uninstall,
index 9c37d2367dd578bc6b6851c47cc5a82b560598d3..70ed4e68eac81e32158b762c4652b23eef2da905 100644 (file)
@@ -79,9 +79,10 @@ typedef struct drm_i915_private {
        drm_i915_sarea_t *sarea_priv;
        drm_i915_ring_buffer_t ring;
 
+       drm_dma_handle_t *status_page_dmah;
        void *hw_status_page;
-       unsigned long counter;
        dma_addr_t dma_status_page;
+       unsigned long counter;
 
        int back_offset;
        int front_offset;
@@ -102,6 +103,7 @@ typedef struct drm_i915_private {
 extern void i915_kernel_lost_context(drm_device_t * dev);
 extern void i915_driver_pretakedown(drm_device_t *dev);
 extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
+extern int i915_driver_device_is_agp(drm_device_t *dev);
 
 /* i915_irq.c */
 extern int i915_irq_emit(DRM_IOCTL_ARGS);
index 832eaf8a5068db6ebe5d57e624ed76c4e32b5b93..567b425b784fc1695065fb652d8388d6a56f4f1c 100644 (file)
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Jeff Hartmann <jhartmann@valinux.com>
- *    Keith Whitwell <keith@tungstengraphics.com>
- *
- * Rewritten by:
- *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/**
+ * \file mga_dma.c
+ * DMA support for MGA G200 / G400.
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Jeff Hartmann <jhartmann@valinux.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_sarea.h"
 #include "mga_drm.h"
 #include "mga_drv.h"
 
@@ -148,7 +151,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv )
        DRM_DEBUG( "  space = 0x%06x\n", primary->space );
 
        mga_flush_write_combine();
-       MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+       MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
 
        DRM_DEBUG( "done.\n" );
 }
@@ -190,7 +193,7 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
        DRM_DEBUG( "  space = 0x%06x\n", primary->space );
 
        mga_flush_write_combine();
-       MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+       MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
 
        set_bit( 0, &primary->wrapped );
        DRM_DEBUG( "done.\n" );
@@ -396,23 +399,383 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
  * DMA initialization, cleanup
  */
 
+
+int mga_driver_preinit(drm_device_t *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);
+
+       dev->dev_private = (void *)dev_priv;
+       memset(dev_priv, 0, sizeof(drm_mga_private_t));
+
+       dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
+       dev_priv->chipset = flags;
+
+       return 0;
+}
+
+/**
+ * Bootstrap the driver for AGP DMA.
+ * 
+ * \todo
+ * Investigate whether there is any benifit to storing the WARP microcode in
+ * AGP memory.  If not, the microcode may as well always be put in PCI
+ * memory.
+ *
+ * \todo
+ * This routine needs to set dma_bs->agp_mode to the mode actually configured
+ * in the hardware.  Looking just at the Linux AGP driver code, I don't see
+ * an easy way to determine this.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
+ */
+static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+                                   drm_mga_dma_bootstrap_t * dma_bs)
+{
+       drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
+       const unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+       int err;
+       unsigned  offset;
+       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;
+
+       
+       /* Acquire AGP. */
+       err = drm_agp_acquire(dev);
+       if (err) {
+               DRM_ERROR("Unable to acquire AGP\n");
+               return err;
+       }
+
+       err = drm_agp_info(dev, &info);
+       if (err) {
+               DRM_ERROR("Unable to get AGP info\n");
+               return err;
+       }
+
+       mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
+       err = drm_agp_enable(dev, mode);
+       if (err) {
+               DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
+               return err;
+       }
+
+
+       /* In addition to the usual AGP mode configuration, the G200 AGP cards
+        * need to have the AGP mode "manually" set.
+        */
+
+       if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
+               if (mode.mode & 0x02) {
+                       MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
+               }
+               else {
+                       MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
+               }
+       }
+
+
+       /* Allocate and bind AGP memory. */
+       dev_priv->agp_pages = agp_size / PAGE_SIZE;
+       dev_priv->agp_mem = drm_alloc_agp( dev, dev_priv->agp_pages, 0 );
+       if (dev_priv->agp_mem == NULL) {
+               dev_priv->agp_pages = 0;
+               DRM_ERROR("Unable to allocate %uMB AGP memory\n",
+                         dma_bs->agp_size);
+               return DRM_ERR(ENOMEM);
+       }
+               
+       err = drm_bind_agp( dev_priv->agp_mem, 0 );
+       if (err) {
+               DRM_ERROR("Unable to bind AGP memory\n");
+               return err;
+       }
+
+       offset = 0;
+       err = drm_addmap( dev, offset, warp_size,
+                         _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp );
+       if (err) {
+               DRM_ERROR("Unable to map WARP microcode\n");
+               return err;
+       }
+
+       offset += warp_size;
+       err = drm_addmap( dev, offset, dma_bs->primary_size,
+                         _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary );
+       if (err) {
+               DRM_ERROR("Unable to map primary DMA region\n");
+               return err;
+       }
+
+       offset += dma_bs->primary_size;
+       err = drm_addmap( dev, offset, secondary_size,
+                         _DRM_AGP, 0, & dev->agp_buffer_map );
+       if (err) {
+               DRM_ERROR("Unable to map secondary DMA region\n");
+               return err;
+       }
+
+       (void) memset( &req, 0, sizeof(req) );
+       req.count = dma_bs->secondary_bin_count;
+       req.size = dma_bs->secondary_bin_size;
+       req.flags = _DRM_AGP_BUFFER;
+       req.agp_start = offset;
+
+       err = drm_addbufs_agp( dev, & req );
+       if (err) {
+               DRM_ERROR("Unable to add secondary DMA buffers\n");
+               return err;
+       }
+
+       offset += secondary_size;
+       err = drm_addmap( dev, offset, agp_size - offset,
+                         _DRM_AGP, 0, & dev_priv->agp_textures );
+       if (err) {
+               DRM_ERROR("Unable to map AGP texture region\n");
+               return err;
+       }
+
+       drm_core_ioremap(dev_priv->warp, dev);
+       drm_core_ioremap(dev_priv->primary, dev);
+       drm_core_ioremap(dev->agp_buffer_map, dev);
+
+       if (!dev_priv->warp->handle ||
+           !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
+               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);
+       }
+
+       dev_priv->dma_access = MGA_PAGPXFER;
+       dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+       DRM_INFO("Initialized card for AGP DMA.\n");
+       return 0;
+}
+
+/**
+ * Bootstrap the driver for PCI DMA.
+ * 
+ * \todo
+ * The algorithm for decreasing the size of the primary DMA buffer could be
+ * better.  The size should be rounded up to the nearest page size, then
+ * decrease the request size by a single page each pass through the loop.
+ *
+ * \todo
+ * Determine whether the maximum address passed to drm_pci_alloc is correct.
+ * The same goes for drm_addbufs_pci.
+ * 
+ * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
+ */
+static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+                                   drm_mga_dma_bootstrap_t * dma_bs)
+{
+       drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
+       const unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+       unsigned int primary_size;
+       unsigned int bin_count;
+       int err;
+       drm_buf_desc_t req;
+
+       
+       if (dev->dma == NULL) {
+               DRM_ERROR("dev->dma is NULL\n");
+               return DRM_ERR(EFAULT);
+       }
+
+       /* The proper alignment is 0x100 for this mapping */
+       err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
+                        _DRM_READ_ONLY, &dev_priv->warp);
+       if (err != 0) {
+               DRM_ERROR("Unable to create mapping for WARP microcode\n");
+               return err;
+       }
+
+       /* Other than the bottom two bits being used to encode other
+        * information, there don't appear to be any restrictions on the
+        * alignment of the primary or secondary DMA buffers.
+        */
+
+       for ( primary_size = dma_bs->primary_size
+             ; primary_size != 0
+             ; primary_size >>= 1 ) {
+               /* The proper alignment for this mapping is 0x04 */
+               err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
+                                _DRM_READ_ONLY, &dev_priv->primary);
+               if (!err)
+                       break;
+       }
+
+       if (err != 0) {
+               DRM_ERROR("Unable to allocate primary DMA region\n");
+               return DRM_ERR(ENOMEM);
+       }
+
+       if (dev_priv->primary->size != dma_bs->primary_size) {
+               DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
+                        dma_bs->primary_size, 
+                        (unsigned) dev_priv->primary->size);
+               dma_bs->primary_size = dev_priv->primary->size;
+       }
+
+       for ( bin_count = dma_bs->secondary_bin_count
+             ; bin_count > 0 
+             ; bin_count-- ) {
+               (void) memset( &req, 0, sizeof(req) );
+               req.count = bin_count;
+               req.size = dma_bs->secondary_bin_size;
+
+               err = drm_addbufs_pci( dev, & req );
+               if (!err) {
+                       break;
+               }
+       }
+       
+       if (bin_count == 0) {
+               DRM_ERROR("Unable to add secondary DMA buffers\n");
+               return err;
+       }
+
+       if (bin_count != dma_bs->secondary_bin_count) {
+               DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
+                        "to %u.\n", dma_bs->secondary_bin_count, bin_count);
+
+               dma_bs->secondary_bin_count = bin_count;
+       }
+
+       dev_priv->dma_access = 0;
+       dev_priv->wagp_enable = 0;
+
+       dma_bs->agp_mode = 0;
+
+       DRM_INFO("Initialized card for PCI DMA.\n");
+       return 0;
+}
+
+
+static int mga_do_dma_bootstrap(drm_device_t * dev,
+                               drm_mga_dma_bootstrap_t * dma_bs)
+{
+       const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+       int err;
+       drm_mga_private_t * const dev_priv =
+               (drm_mga_private_t *) dev->dev_private;
+
+
+       dev_priv->used_new_dma_init = 1;
+
+       /* The first steps are the same for both PCI and AGP based DMA.  Map
+        * the cards MMIO registers and map a status page.
+        */
+       err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size,
+                         _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio );
+       if (err) {
+               DRM_ERROR("Unable to map MMIO region\n");
+               return err;
+       }
+
+
+       err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM,
+                         _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
+                         & dev_priv->status );
+       if (err) {
+               DRM_ERROR("Unable to map status region\n");
+               return err;
+       }
+
+
+       /* The DMA initialization procedure is slightly different for PCI and
+        * AGP cards.  AGP cards just allocate a large block of AGP memory and
+        * carve off portions of it for internal uses.  The remaining memory
+        * is returned to user-mode to be used for AGP textures.
+        */
+
+       if (is_agp) {
+               err = mga_do_agp_dma_bootstrap(dev, dma_bs);
+       }
+       
+       /* If we attempted to initialize the card for AGP DMA but failed,
+        * clean-up any mess that may have been created.
+        */
+
+       if (err) {
+               mga_do_cleanup_dma(dev);
+       }
+
+
+       /* Not only do we want to try and initialized PCI cards for PCI DMA,
+        * but we also try to initialized AGP cards that could not be
+        * initialized for AGP DMA.  This covers the case where we have an AGP
+        * card in a system with an unsupported AGP chipset.  In that case the
+        * card will be detected as AGP, but we won't be able to allocate any
+        * AGP memory, etc.
+        */
+
+       if (!is_agp || err) {
+               err = mga_do_pci_dma_bootstrap(dev, dma_bs);
+       }
+
+
+       return err;
+}
+
+int mga_dma_bootstrap(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_mga_dma_bootstrap_t bootstrap;
+       int err;
+
+
+       DRM_COPY_FROM_USER_IOCTL(bootstrap,
+                                (drm_mga_dma_bootstrap_t __user *) data,
+                                sizeof(bootstrap));
+
+       err = mga_do_dma_bootstrap(dev, & bootstrap);
+       if (! 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;
+
+               if (dev_priv->agp_textures != NULL) {
+                       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.agp_mode = modes[ bootstrap.agp_mode & 0x07 ];
+               if (DRM_COPY_TO_USER( (void __user *) data, & bootstrap,
+                                    sizeof(bootstrap))) {
+                       err = DRM_ERR(EFAULT);
+               }
+       }
+       else {
+               mga_do_cleanup_dma(dev);
+       }
+
+       return err;
+}
+
 static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 {
        drm_mga_private_t *dev_priv;
        int ret;
        DRM_DEBUG( "\n" );
 
-       dev_priv = drm_alloc( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
-       if ( !dev_priv )
-               return DRM_ERR(ENOMEM);
-
-       memset( dev_priv, 0, sizeof(drm_mga_private_t) );
 
-       dev_priv->chipset = init->chipset;
+       dev_priv = dev->dev_private;
 
-       dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
-
-       if ( init->sgram ) {
+       if (init->sgram) {
                dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
        } else {
                dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
@@ -436,88 +799,66 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 
        DRM_GETSAREA();
 
-       if(!dev_priv->sarea) {
-               DRM_ERROR( "failed to find sarea!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
+       if (!dev_priv->sarea) {
+               DRM_ERROR("failed to find sarea!\n");
                return DRM_ERR(EINVAL);
        }
 
-       dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
-       if(!dev_priv->mmio) {
-               DRM_ERROR( "failed to find mmio region!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
-               return DRM_ERR(EINVAL);
-       }
-       dev_priv->status = drm_core_findmap(dev, init->status_offset);
-       if(!dev_priv->status) {
-               DRM_ERROR( "failed to find status page!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
-               return DRM_ERR(EINVAL);
-       }
-       dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
-       if(!dev_priv->warp) {
-               DRM_ERROR( "failed to find warp microcode region!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
-               return DRM_ERR(EINVAL);
-       }
-       dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
-       if(!dev_priv->primary) {
-               DRM_ERROR( "failed to find primary dma region!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
-               return DRM_ERR(EINVAL);
-       }
-       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" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
-               return DRM_ERR(EINVAL);
+       if (! dev_priv->used_new_dma_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);
+               }
+               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);
+               }
+               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);
+               }
+               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);
+               }
+               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);
+               }
+
+               drm_core_ioremap(dev_priv->warp, dev);
+               drm_core_ioremap(dev_priv->primary, dev);
+               drm_core_ioremap(dev->agp_buffer_map, dev);
        }
 
        dev_priv->sarea_priv =
                (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
                                    init->sarea_priv_offset);
 
-       drm_core_ioremap( dev_priv->warp, dev );
-       drm_core_ioremap( dev_priv->primary, dev );
-       drm_core_ioremap( dev->agp_buffer_map, dev );
-
-       if(!dev_priv->warp->handle ||
-          !dev_priv->primary->handle ||
-          !dev->agp_buffer_map->handle ) {
-               DRM_ERROR( "failed to ioremap agp regions!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
+       if (!dev_priv->warp->handle ||
+           !dev_priv->primary->handle ||
+           ((dev_priv->dma_access != 0) &&
+            ((dev->agp_buffer_map == NULL) ||
+             (dev->agp_buffer_map->handle == NULL)))) {
+               DRM_ERROR("failed to ioremap agp regions!\n");
                return DRM_ERR(ENOMEM);
        }
 
-       ret = mga_warp_install_microcode( dev_priv );
-       if ( ret < 0 ) {
-               DRM_ERROR( "failed to install WARP ucode!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
+       ret = mga_warp_install_microcode(dev_priv);
+       if (ret < 0) {
+               DRM_ERROR("failed to install WARP ucode!\n");
                return ret;
        }
 
-       ret = mga_warp_init( dev_priv );
-       if ( ret < 0 ) {
-               DRM_ERROR( "failed to init WARP engine!\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
+       ret = mga_warp_init(dev_priv);
+       if (ret < 0) {
+               DRM_ERROR("failed to init WARP engine!\n");
                return ret;
        }
 
@@ -557,22 +898,18 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
        dev_priv->sarea_priv->last_frame.head = 0;
        dev_priv->sarea_priv->last_frame.wrap = 0;
 
-       if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
-               DRM_ERROR( "could not initialize freelist\n" );
-               /* Assign dev_private so we can do cleanup. */
-               dev->dev_private = (void *)dev_priv;
-               mga_do_cleanup_dma( dev );
+       if (mga_freelist_init(dev, dev_priv) < 0) {
+               DRM_ERROR("could not initialize freelist\n");
                return DRM_ERR(ENOMEM);
        }
 
-       /* Make dev_private visable to others. */
-       dev->dev_private = (void *)dev_priv;
        return 0;
 }
 
 static int mga_do_cleanup_dma( drm_device_t *dev )
 {
-       DRM_DEBUG( "\n" );
+       int err = 0;
+       DRM_DEBUG("\n");
 
        /* Make sure interrupts are disabled here because the uninstall ioctl
         * may not have been called from userspace and after dev_private
@@ -583,20 +920,49 @@ static int mga_do_cleanup_dma( drm_device_t *dev )
        if ( dev->dev_private ) {
                drm_mga_private_t *dev_priv = dev->dev_private;
 
-               if ( dev_priv->warp != NULL )
-                       drm_core_ioremapfree( dev_priv->warp, dev );
-               if ( dev_priv->primary != NULL )
-                       drm_core_ioremapfree( dev_priv->primary, dev );
-               if ( dev->agp_buffer_map != NULL )
-                       drm_core_ioremapfree( dev->agp_buffer_map, dev );
+               if ((dev_priv->warp != NULL) 
+                   && (dev_priv->mmio->type != _DRM_CONSISTENT))
+                       drm_core_ioremapfree(dev_priv->warp, dev);
+
+               if ((dev_priv->primary != NULL) 
+                   && (dev_priv->primary->type != _DRM_CONSISTENT))
+                       drm_core_ioremapfree(dev_priv->primary, dev);
 
-               if ( dev_priv->head != NULL ) {
-                       mga_freelist_cleanup( dev );
+               if (dev->agp_buffer_map != NULL)
+                       drm_core_ioremapfree(dev->agp_buffer_map, dev);
+
+               if (dev_priv->used_new_dma_init) {
+                       if (dev_priv->agp_mem != NULL) {
+                               dev_priv->agp_textures = NULL;
+                               drm_unbind_agp(dev_priv->agp_mem);
+
+                               drm_free_agp(dev_priv->agp_mem, dev_priv->agp_pages);
+                               dev_priv->agp_pages = 0;
+                               dev_priv->agp_mem = NULL;
+                       }
+
+                       if ((dev->agp != NULL) && dev->agp->acquired) {
+                               err = drm_agp_release(dev);
+                       }
+
+                       dev_priv->used_new_dma_init = 0;
                }
 
-               drm_free( dev->dev_private, sizeof(drm_mga_private_t),
-                          DRM_MEM_DRIVER );
-               dev->dev_private = NULL;
+               dev_priv->warp = NULL;
+               dev_priv->primary = NULL;
+               dev_priv->mmio = NULL;
+               dev_priv->status = NULL;
+               dev_priv->sarea = NULL;
+               dev_priv->sarea_priv = NULL;
+               dev->agp_buffer_map = NULL;
+
+               memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
+               dev_priv->warp_pipe = 0;
+               memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+               if (dev_priv->head != NULL) {
+                       mga_freelist_cleanup(dev);
+               }
        }
 
        return 0;
@@ -606,14 +972,20 @@ int mga_dma_init( DRM_IOCTL_ARGS )
 {
        DRM_DEVICE;
        drm_mga_init_t init;
+       int err;
 
        LOCK_TEST_WITH_RETURN( dev, filp );
 
-       DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t __user *)data, sizeof(init) );
+       DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
+                                sizeof(init));
 
        switch ( init.func ) {
        case MGA_INIT_DMA:
-               return mga_do_init_dma( dev, &init );
+               err = mga_do_init_dma(dev, &init);
+               if (err) {
+                       (void) mga_do_cleanup_dma(dev);
+               }
+               return err;
        case MGA_CLEANUP_DMA:
                return mga_do_cleanup_dma( dev );
        }
@@ -742,7 +1114,21 @@ int mga_dma_buffers( DRM_IOCTL_ARGS )
        return ret;
 }
 
-void mga_driver_pretakedown(drm_device_t *dev)
+/**
+ * Called just before the module is unloaded.
+ */
+int mga_driver_postcleanup(drm_device_t * dev)
+{
+       drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+       dev->dev_private = NULL;
+
+       return 0;
+}
+
+/**
+ * Called when the last opener of the device is closed.
+ */
+void mga_driver_pretakedown(drm_device_t * dev)
 {
        mga_do_cleanup_dma( dev );
 }
index 521d4451d012fd17dc3d852631535c0403ce6c84..d20aab3bd57bb66fdf6086f2d27a1d45cb0b1c6b 100644 (file)
@@ -73,7 +73,8 @@
 
 #define MGA_CARD_TYPE_G200     1
 #define MGA_CARD_TYPE_G400     2
-
+#define MGA_CARD_TYPE_G450     3       /* not currently used */
+#define MGA_CARD_TYPE_G550     4
 
 #define MGA_FRONT              0x1
 #define MGA_BACK               0x2
@@ -225,10 +226,6 @@ typedef struct _drm_mga_sarea {
 } drm_mga_sarea_t;
 
 
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmMga.h)
- */
-
 /* MGA specific ioctls
  * The device specific ioctl range is 0x40 to 0x79.
  */
@@ -243,6 +240,14 @@ typedef struct _drm_mga_sarea {
 #define DRM_MGA_BLIT     0x08
 #define DRM_MGA_GETPARAM 0x09
 
+/* 3.2:
+ * ioctls for operating on fences.
+ */
+#define DRM_MGA_SET_FENCE      0x0a
+#define DRM_MGA_WAIT_FENCE     0x0b
+#define DRM_MGA_DMA_BOOTSTRAP  0x0c
+
+
 #define DRM_IOCTL_MGA_INIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
 #define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
 #define DRM_IOCTL_MGA_RESET    DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_RESET)
@@ -253,6 +258,9 @@ typedef struct _drm_mga_sarea {
 #define DRM_IOCTL_MGA_ILOAD    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
 #define DRM_IOCTL_MGA_BLIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
 #define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
+#define DRM_IOCTL_MGA_SET_FENCE     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_WAIT_FENCE    DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
 
 typedef struct _drm_mga_warp_index {
        int installed;
@@ -291,12 +299,72 @@ typedef struct drm_mga_init {
        unsigned long buffers_offset;
 } drm_mga_init_t;
 
-typedef struct drm_mga_fullscreen {
-       enum {
-               MGA_INIT_FULLSCREEN    = 0x01,
-               MGA_CLEANUP_FULLSCREEN = 0x02
-       } func;
-} drm_mga_fullscreen_t;
+typedef struct drm_mga_dma_bootstrap {
+       /**
+        * \name AGP texture region
+        * 
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
+        * be filled in with the actual AGP texture settings.
+        * 
+        * \warning
+        * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
+        * is zero, it means that PCI memory (most likely through the use of
+        * an IOMMU) is being used for "AGP" textures.
+        */
+       /*@{*/
+       unsigned long texture_handle; /**< Handle used to map AGP textures. */
+       uint32_t     texture_size;    /**< Size of the AGP texture region. */
+       /*@}*/
+
+
+       /**
+        * Requested size of the primary DMA region.
+        * 
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+        * filled in with the actual AGP mode.  If AGP was not available
+        */
+       uint32_t primary_size;
+
+
+       /**
+        * Requested number of secondary DMA buffers.
+        * 
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+        * filled in with the actual number of secondary DMA buffers
+        * allocated.  Particularly when PCI DMA is used, this may be
+        * (subtantially) less than the number requested.
+        */
+       uint32_t secondary_bin_count;
+       
+       
+       /**
+        * Requested size of each secondary DMA buffer.
+        * 
+        * While the kernel \b is free to reduce
+        * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
+        * to reduce dma_mga_dma_bootstrap::secondary_bin_size.
+        */
+       uint32_t secondary_bin_size;
+
+
+       /**
+        * Bit-wise mask of AGPSTAT2_* values.  Currently only \c AGPSTAT2_1X,
+        * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported.  If this value is
+        * zero, it means that PCI DMA should be used, even if AGP is
+        * possible.
+        * 
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+        * filled in with the actual AGP mode.  If AGP was not available
+        * (i.e., PCI DMA was used), this value will be zero.
+        */
+       uint32_t agp_mode;
+
+
+       /**
+        * Desired AGP GART size, measured in megabytes.
+        */
+       uint8_t agp_size;
+} drm_mga_dma_bootstrap_t;
 
 typedef struct drm_mga_clear {
        unsigned int flags;
@@ -341,6 +409,14 @@ typedef struct _drm_mga_blit {
  */
 #define MGA_PARAM_IRQ_NR            1
 
+/* 3.2: Query the actual card type.  The DDX only distinguishes between
+ * G200 chips and non-G200 chips, which it calls G400.  It turns out that
+ * there are some very sublte differences between the G4x0 chips and the G550
+ * chips.  Using this parameter query, a client-side driver can detect the
+ * difference between a G4x0 and a G550.
+ */
+#define MGA_PARAM_CARD_TYPE         2
+
 typedef struct drm_mga_getparam {
        int param;
        void __user *value;
index 844cca9cb29dfa65cf0d8bb3a44171846875c942..daabbba3b29789de0e1b662306e3fcbb9873e94e 100644 (file)
   
 #include "drm_pciids.h"
 
+static int mga_driver_device_is_agp(drm_device_t * dev);
 static int postinit( struct drm_device *dev, unsigned long flags )
 {
+       drm_mga_private_t * const dev_priv =
+               (drm_mga_private_t *) dev->dev_private;
+
+       dev_priv->mmio_base = pci_resource_start(dev->pdev, 1);
+       dev_priv->mmio_size = pci_resource_len(dev->pdev, 1);
+
        dev->counters += 3;
        dev->types[6] = _DRM_STAT_IRQ;
        dev->types[7] = _DRM_STAT_PRIMARY;
@@ -79,8 +86,11 @@ extern int mga_max_ioctl;
 
 static struct drm_driver driver = {
        .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+       .preinit = mga_driver_preinit,
+       .postcleanup = mga_driver_postcleanup,
        .pretakedown = mga_driver_pretakedown,
        .dma_quiescent = mga_driver_dma_quiescent,
+       .device_is_agp = mga_driver_device_is_agp,
        .vblank_wait = mga_driver_vblank_wait,
        .irq_preinstall = mga_driver_irq_preinstall,
        .irq_postinstall = mga_driver_irq_postinstall,
@@ -128,3 +138,38 @@ module_exit(mga_exit);
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL and additional rights");
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * In addition to the usual tests performed by \c drm_device_is_agp, this
+ * function detects PCI G450 cards that appear to the system exactly like
+ * AGP G450 cards.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
+ */
+int mga_driver_device_is_agp(drm_device_t * dev)
+{
+       const struct pci_dev * const pdev = dev->pdev;
+
+
+       /* There are PCI versions of the G450.  These cards have the
+        * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
+        * bridge chip.  We detect these cards, which are not currently
+        * supported by this driver, by looking at the device ID of the
+        * bus the "card" is on.  If vendor is 0x3388 (Hint Corp) and the
+        * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
+        * device.
+        */
+       
+       if ( (pdev->device == 0x0525)
+            && (pdev->bus->self->vendor == 0x3388)
+            && (pdev->bus->self->device == 0x0021) ) {
+               return 0;
+       }
+
+       return 2;
+}
index 9412e2816eb720d1794aeeb948c74b6ce274c495..b22fdbd4f830b561d058584383d107d42468144b 100644 (file)
 
 #define DRIVER_NAME            "mga"
 #define DRIVER_DESC            "Matrox G200/G400"
-#define DRIVER_DATE            "20021029"
+#define DRIVER_DATE            "20050607"
 
 #define DRIVER_MAJOR           3
-#define DRIVER_MINOR           1
+#define DRIVER_MINOR           2
 #define DRIVER_PATCHLEVEL      0
 
 typedef struct drm_mga_primary_buffer {
@@ -87,9 +87,43 @@ typedef struct drm_mga_private {
        int chipset;
        int usec_timeout;
 
+       /**
+        * If set, the new DMA initialization sequence was used.  This is
+        * primarilly used to select how the driver should uninitialized its
+        * internal DMA structures.
+        */
+       int used_new_dma_init;
+
+       /**
+        * If AGP memory is used for DMA buffers, this will be the value
+        * \c MGA_PAGPXFER.  Otherwise, it will be zero (for a PCI transfer).
+        */
+       u32 dma_access;
+
+       /**
+        * If AGP memory is used for DMA buffers, this will be the value
+        * \c MGA_WAGP_ENABLE.  Otherwise, it will be zero (for a PCI
+        * transfer).
+        */
+       u32 wagp_enable;
+
+       /**
+        * \name MMIO region parameters.
+        * 
+        * \sa drm_mga_private_t::mmio
+        */
+       /*@{*/
+       u32 mmio_base;             /**< Bus address of base of MMIO. */
+       u32 mmio_size;             /**< Size of the MMIO region. */
+       /*@}*/
+
        u32 clear_cmd;
        u32 maccess;
 
+       wait_queue_head_t fence_queue;
+       atomic_t last_fence_retired;
+       u32 next_fence_to_post;
+
        unsigned int fb_cpp;
        unsigned int front_offset;
        unsigned int front_pitch;
@@ -108,35 +142,43 @@ typedef struct drm_mga_private {
        drm_local_map_t *status;
        drm_local_map_t *warp;
        drm_local_map_t *primary;
-       drm_local_map_t *buffers;
        drm_local_map_t *agp_textures;
+       
+       DRM_AGP_MEM *agp_mem;
+       unsigned int agp_pages;
 } drm_mga_private_t;
 
                                /* mga_dma.c */
-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 void mga_driver_pretakedown(drm_device_t *dev);
-extern int mga_driver_dma_quiescent(drm_device_t *dev);
-
-extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
-
-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_driver_preinit(drm_device_t * dev, unsigned long flags);
+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_postcleanup(drm_device_t * dev);
+extern void mga_driver_pretakedown(drm_device_t * dev);
+extern int mga_driver_dma_quiescent(drm_device_t * dev);
+
+extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
+
+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 );
 
                                /* mga_warp.c */
-extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
-extern int mga_warp_init( drm_mga_private_t *dev_priv );
-
-extern int mga_driver_vblank_wait(drm_device_t *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 unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
+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 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 long mga_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
 
@@ -527,6 +569,12 @@ do {                                                                       \
  */
 #define MGA_EXEC                       0x0100
 
+/* AGP PLL encoding (for G200 only).
+ */
+#define MGA_AGP_PLL                    0x1e4c
+#      define MGA_AGP2XPLL_DISABLE             (0 << 0)
+#      define MGA_AGP2XPLL_ENABLE              (1 << 0)
+
 /* Warp registers
  */
 #define MGA_WR0                                0x2d00
index bc745cfa2095dc7e5370ed909063bbeb8fcb1921..77d738e75a4df598b8a0a97d5d4377a0170efab7 100644 (file)
@@ -129,9 +129,76 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd,
                         DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
 }
 
+typedef struct drm_mga_drm_bootstrap32 {
+       u32 texture_handle;
+       u32 texture_size;
+       u32 primary_size;
+       u32 secondary_bin_count;
+       u32 secondary_bin_size;
+       u32 agp_mode;
+       u8 agp_size;
+} drm_mga_dma_bootstrap32_t;
+
+static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
+                                   unsigned long arg)
+{
+       drm_mga_dma_bootstrap32_t dma_bootstrap32;
+       drm_mga_dma_bootstrap_t __user *dma_bootstrap;
+       int err;
+
+       if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
+                          sizeof(dma_bootstrap32)))
+               return -EFAULT;
+
+       dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
+       if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
+           || __put_user(dma_bootstrap32.texture_handle,
+                         &dma_bootstrap->texture_handle)
+           || __put_user(dma_bootstrap32.texture_size,
+                         &dma_bootstrap->texture_size)
+           || __put_user(dma_bootstrap32.primary_size,
+                         &dma_bootstrap->primary_size)
+           || __put_user(dma_bootstrap32.secondary_bin_count,
+                         &dma_bootstrap->secondary_bin_count)
+           || __put_user(dma_bootstrap32.secondary_bin_size,
+                         &dma_bootstrap->secondary_bin_size)
+           || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
+           || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_dentry->d_inode, file,
+                       DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+                       (unsigned long)dma_bootstrap);
+       if (err)
+               return err;
+
+       if (__get_user(dma_bootstrap32.texture_handle,
+                      &dma_bootstrap->texture_handle)
+           || __get_user(dma_bootstrap32.texture_size,
+                         &dma_bootstrap->texture_size)
+           || __get_user(dma_bootstrap32.primary_size,
+                         &dma_bootstrap->primary_size)
+           || __get_user(dma_bootstrap32.secondary_bin_count,
+                         &dma_bootstrap->secondary_bin_count)
+           || __get_user(dma_bootstrap32.secondary_bin_size,
+                         &dma_bootstrap->secondary_bin_size)
+           || __get_user(dma_bootstrap32.agp_mode,
+                         &dma_bootstrap->agp_mode)
+           || __get_user(dma_bootstrap32.agp_size,
+                         &dma_bootstrap->agp_size))
+               return -EFAULT;
+
+       if (copy_to_user((void __user *)arg, &dma_bootstrap32,
+                        sizeof(dma_bootstrap32)))
+               return -EFAULT;
+
+       return 0;
+}
+
 drm_ioctl_compat_t *mga_compat_ioctls[] = {
        [DRM_MGA_INIT] = compat_mga_init,
        [DRM_MGA_GETPARAM] = compat_mga_getparam,
+       [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
 };
 
 /**
index bc0b6b5d43a6de1de438d9ad5ce1e3ce2988cfc8..52eaa4e788f91f2cef5548b149ca648eed2b6550 100644 (file)
@@ -41,15 +41,40 @@ irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS )
        drm_mga_private_t *dev_priv = 
           (drm_mga_private_t *)dev->dev_private;
        int status;
+       int handled = 0;
+
+       status = MGA_READ(MGA_STATUS);
 
-       status = MGA_READ( MGA_STATUS );
-       
        /* VBLANK interrupt */
        if ( status & MGA_VLINEPEN ) {
                MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
                atomic_inc(&dev->vbl_received);
                DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals( dev );
+               drm_vbl_send_signals(dev);
+               handled = 1;
+       }
+
+       /* SOFTRAP interrupt */
+       if (status & MGA_SOFTRAPEN) {
+               const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
+               const u32 prim_end   = MGA_READ(MGA_PRIMEND);
+
+
+               MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
+
+               /* In addition to clearing the interrupt-pending bit, we
+                * have to write to MGA_PRIMEND to re-start the DMA operation.
+                */
+               if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) {
+                       MGA_WRITE(MGA_PRIMEND, prim_end);
+               }
+
+               atomic_inc(&dev_priv->last_fence_retired);
+               DRM_WAKEUP(&dev_priv->fence_queue);
+               handled = 1;
+       }
+
+       if ( handled ) {
                return IRQ_HANDLED;
        }
        return IRQ_NONE;
@@ -73,9 +98,28 @@ int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
        return ret;
 }
 
-void mga_driver_irq_preinstall( drm_device_t *dev ) {
-       drm_mga_private_t *dev_priv = 
-          (drm_mga_private_t *)dev->dev_private;
+int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       unsigned int cur_fence;
+       int ret = 0;
+
+       /* Assume that the user has missed the current sequence number
+        * by about a day rather than she wants to wait for years
+        * using fences.
+        */
+       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+                   (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
+                     - *sequence) <= (1 << 23)));
+
+       *sequence = cur_fence;
+
+       return ret;
+}
+
+void mga_driver_irq_preinstall(drm_device_t * dev)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
        /* Disable *all* interrupts */
        MGA_WRITE( MGA_IEN, 0 );
@@ -83,12 +127,14 @@ void mga_driver_irq_preinstall( drm_device_t *dev ) {
        MGA_WRITE( MGA_ICLEAR, ~0 );
 }
 
-void mga_driver_irq_postinstall( drm_device_t *dev ) {
-       drm_mga_private_t *dev_priv = 
-          (drm_mga_private_t *)dev->dev_private;
+void mga_driver_irq_postinstall(drm_device_t * dev)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+       DRM_INIT_WAITQUEUE( &dev_priv->fence_queue );
 
-       /* Turn on VBL interrupt */
-       MGA_WRITE( MGA_IEN, MGA_VLINEIEN );
+       /* Turn on vertical blank interrupt and soft trap interrupt. */
+       MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
 }
 
 void mga_driver_irq_uninstall( drm_device_t *dev ) {
@@ -98,5 +144,7 @@ void mga_driver_irq_uninstall( drm_device_t *dev ) {
                return;
 
        /* Disable *all* interrupts */
-       MGA_WRITE( MGA_IEN, 0 );
+       MGA_WRITE(MGA_IEN, 0);
+       
+       dev->irq_enabled = 0;
 }
index 3c7a8f5ba50133e3289971b05e52402418935a82..05bbb4719376ac9fe1f424f8633d29a5643c2005 100644 (file)
@@ -53,16 +53,16 @@ static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
 
        /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
         */
-       if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
-               DMA_BLOCK( MGA_DWGCTL,          ctx->dwgctl,
-                          MGA_LEN + MGA_EXEC,  0x80000000,
-                          MGA_DWGCTL,          ctx->dwgctl,
-                          MGA_LEN + MGA_EXEC,  0x80000000 );
+       if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
+               DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
+                         MGA_LEN + MGA_EXEC, 0x80000000,
+                         MGA_DWGCTL, ctx->dwgctl,
+                         MGA_LEN + MGA_EXEC, 0x80000000);
        }
-       DMA_BLOCK( MGA_DMAPAD,  0x00000000,
-                  MGA_CXBNDRY, (box->x2 << 16) | box->x1,
-                  MGA_YTOP,    box->y1 * pitch,
-                  MGA_YBOT,    box->y2 * pitch );
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+                 MGA_YTOP, box->y1 * pitch,
+                 MGA_YBOT, (box->y2 - 1) * pitch);
 
        ADVANCE_DMA();
 }
@@ -260,12 +260,11 @@ static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
 
        /* Padding required to to hardware bug.
         */
-       DMA_BLOCK( MGA_DMAPAD,  0xffffffff,
-                  MGA_DMAPAD,  0xffffffff,
-                  MGA_DMAPAD,  0xffffffff,
-                  MGA_WIADDR,  (dev_priv->warp_pipe_phys[pipe] |
-                                MGA_WMODE_START |
-                                MGA_WAGP_ENABLE) );
+       DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
+                              MGA_WMODE_START | dev_priv->wagp_enable));
 
        ADVANCE_DMA();
 }
@@ -342,12 +341,11 @@ static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
                   MGA_WR60,    MGA_G400_WR_MAGIC );    /* tex1 height       */
 
        /* Padding required to to hardware bug */
-       DMA_BLOCK( MGA_DMAPAD,  0xffffffff,
-                  MGA_DMAPAD,  0xffffffff,
-                  MGA_DMAPAD,  0xffffffff,
-                  MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
-                                MGA_WMODE_START |
-                                MGA_WAGP_ENABLE) );
+       DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
+                               MGA_WMODE_START | dev_priv->wagp_enable));
 
        ADVANCE_DMA();
 }
@@ -459,9 +457,9 @@ static int mga_verify_state( drm_mga_private_t *dev_priv )
        if ( dirty & MGA_UPLOAD_TEX0 )
                ret |= mga_verify_tex( dev_priv, 0 );
 
-       if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
-               if ( dirty & MGA_UPLOAD_TEX1 )
-                       ret |= mga_verify_tex( dev_priv, 1 );
+       if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+               if (dirty & MGA_UPLOAD_TEX1)
+                       ret |= mga_verify_tex(dev_priv, 1);
 
                if ( dirty & MGA_UPLOAD_PIPE )
                        ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
@@ -686,12 +684,12 @@ static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
 
                        BEGIN_DMA( 1 );
 
-                       DMA_BLOCK( MGA_DMAPAD,          0x00000000,
-                                  MGA_DMAPAD,          0x00000000,
-                                  MGA_SECADDRESS,      (address |
-                                                        MGA_DMA_VERTEX),
-                                  MGA_SECEND,          ((address + length) |
-                                                        MGA_PAGPXFER) );
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_DMAPAD, 0x00000000,
+                                 MGA_SECADDRESS, (address |
+                                                  MGA_DMA_VERTEX),
+                                 MGA_SECEND, ((address + length) |
+                                              dev_priv->dma_access));
 
                        ADVANCE_DMA();
                } while ( ++i < sarea_priv->nbox );
@@ -733,11 +731,11 @@ static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
 
                        BEGIN_DMA( 1 );
 
-                       DMA_BLOCK( MGA_DMAPAD,          0x00000000,
-                                  MGA_DMAPAD,          0x00000000,
-                                  MGA_SETUPADDRESS,    address + start,
-                                  MGA_SETUPEND,        ((address + end) |
-                                                        MGA_PAGPXFER) );
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_DMAPAD, 0x00000000,
+                                 MGA_SETUPADDRESS, address + start,
+                                 MGA_SETUPEND, ((address + end) |
+                                                dev_priv->dma_access));
 
                        ADVANCE_DMA();
                } while ( ++i < sarea_priv->nbox );
@@ -764,7 +762,7 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
        drm_mga_private_t *dev_priv = dev->dev_private;
        drm_mga_buf_priv_t *buf_priv = buf->dev_private;
        drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
-       u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
+       u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
        u32 y2;
        DMA_LOCALS;
        DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used );
@@ -1095,6 +1093,9 @@ static int mga_getparam( DRM_IOCTL_ARGS )
        case MGA_PARAM_IRQ_NR:
                value = dev->irq;
                break;
+       case MGA_PARAM_CARD_TYPE:
+               value = dev_priv->chipset;
+               break;
        default:
                return DRM_ERR(EINVAL);
        }
@@ -1107,17 +1108,82 @@ static int mga_getparam( DRM_IOCTL_ARGS )
        return 0;
 }
 
+static int mga_set_fence(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       u32 temp;
+       DMA_LOCALS;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+       /* I would normal do this assignment in the declaration of temp,
+        * but dev_priv may be NULL.
+        */
+
+       temp = dev_priv->next_fence_to_post;
+       dev_priv->next_fence_to_post++;
+
+       BEGIN_DMA(1);
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_SOFTRAP, 0x00000000);
+       ADVANCE_DMA();
+
+       if (DRM_COPY_TO_USER( (u32 __user *) data, & temp, sizeof(u32))) {
+               DRM_ERROR("copy_to_user\n");
+               return DRM_ERR(EFAULT);
+       }
+
+       return 0;
+}
+
+static int mga_wait_fence(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       u32 fence;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(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);
+
+       if (DRM_COPY_TO_USER( (u32 __user *) data, & fence, sizeof(u32))) {
+               DRM_ERROR("copy_to_user\n");
+               return DRM_ERR(EFAULT);
+       }
+
+       return 0;
+}
+