Merge branch 'master' of ssh+git://git.freedesktop.org/git/mesa/drm into xgi-0-0-2
authorIan Romanick <idr@us.ibm.com>
Thu, 26 Jul 2007 23:58:28 +0000 (16:58 -0700)
committerIan Romanick <idr@us.ibm.com>
Thu, 26 Jul 2007 23:58:28 +0000 (16:58 -0700)
Conflicts:

linux-core/drmP.h
linux-core/drm_scatter.c

15 files changed:
linux-core/Makefile
linux-core/Makefile.kernel
linux-core/xgi_cmdlist.c [new file with mode: 0644]
linux-core/xgi_cmdlist.h [new file with mode: 0644]
linux-core/xgi_drm.h [new symlink]
linux-core/xgi_drv.c [new file with mode: 0644]
linux-core/xgi_drv.h [new file with mode: 0644]
linux-core/xgi_fb.c [new file with mode: 0644]
linux-core/xgi_misc.c [new file with mode: 0644]
linux-core/xgi_misc.h [new file with mode: 0644]
linux-core/xgi_pcie.c [new file with mode: 0644]
linux-core/xgi_regs.h [new file with mode: 0644]
shared-core/Makefile.am
shared-core/drm_pciids.txt
shared-core/xgi_drm.h [new file with mode: 0644]

index 1758777..55e2525 100644 (file)
@@ -58,7 +58,7 @@ endif
 
 # Modules for all architectures
 MODULE_LIST := drm.o tdfx.o r128.o radeon.o mga.o sis.o savage.o via.o \
-               mach64.o nv.o nouveau.o
+               mach64.o nv.o nouveau.o xgi.o
 
 # Modules only for ix86 architectures
 ifneq (,$(findstring 86,$(MACHINE)))
@@ -91,6 +91,7 @@ MACH64HEADERS = mach64_drv.h mach64_drm.h $(DRMHEADERS)
 NVHEADERS =     nv_drv.h $(DRMHEADERS)
 FFBHEADERS =   ffb_drv.h $(DRMHEADERS)
 NOUVEAUHEADERS = nouveau_drv.h nouveau_drm.h nouveau_reg.h $(DRMHEADERS)
+XGIHEADERS = xgi_cmdlist.h xgi_drv.h xgi_misc.h xgi_regs.h $(DRMHEADERS)
 
 PROGS = dristat drmstat
 
@@ -284,6 +285,7 @@ CONFIG_DRM_VIA := n
 CONFIG_DRM_MACH64 := n
 CONFIG_DRM_NV := n
 CONFIG_DRM_NOUVEAU := n
+CONFIG_DRM_XGI := n
 
 # Enable module builds for the modules requested/supported.
 
@@ -320,6 +322,9 @@ endif
 ifneq (,$(findstring nouveau,$(DRM_MODULES)))
 CONFIG_DRM_NOUVEAU := m
 endif
+ifneq (,$(findstring xgi,$(DRM_MODULES)))
+CONFIG_DRM_XGI := m
+endif
 
 # These require AGP support
 
@@ -347,6 +352,7 @@ $(via-objs):        $(VIAHEADERS)
 $(mach64-objs): $(MACH64HEADERS)
 $(nv-objs):     $(NVHEADERS)
 $(nouveau-objs): $(NOUVEAUHEADERS)
+$(xgi-objs):    $(XGIHEADERS)
 
 endif
 
index 5aa589c..c898206 100644 (file)
@@ -38,6 +38,7 @@ via-objs    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o \
                via_video.o via_dmablit.o via_fence.o via_buffer.o
 mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o
 nv-objs := nv_drv.o
+xgi-objs    := xgi_cmdlist.o xgi_drv.o xgi_fb.o xgi_misc.o xgi_pcie.o
 
 ifeq ($(CONFIG_COMPAT),y)
 drm-objs    += drm_ioc32.o
@@ -62,3 +63,4 @@ obj-$(CONFIG_DRM_VIA)   += via.o
 obj-$(CONFIG_DRM_MACH64)+= mach64.o
 obj-$(CONFIG_DRM_NV)    += nv.o
 obj-$(CONFIG_DRM_NOUVEAU) += nouveau.o
+obj-$(CONFIG_DRM_XGI)   += xgi.o
\ No newline at end of file
diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c
new file mode 100644 (file)
index 0000000..490e9f3
--- /dev/null
@@ -0,0 +1,264 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#include "xgi_drv.h"
+#include "xgi_regs.h"
+#include "xgi_misc.h"
+#include "xgi_cmdlist.h"
+
+static void addFlush2D(struct xgi_info * info);
+static unsigned int get_batch_command(enum xgi_batch_type type);
+static void triggerHWCommandList(struct xgi_info * info);
+static void xgi_cmdlist_reset(struct xgi_info * info);
+
+int xgi_cmdlist_initialize(struct xgi_info * info, size_t size)
+{
+       struct xgi_mem_alloc mem_alloc = {
+               .size = size,
+               .owner = PCIE_2D,
+       };
+       int err;
+
+       err = xgi_pcie_alloc(info, &mem_alloc, 0);
+       if (err) {
+               return err;
+       }
+
+       info->cmdring.ptr = xgi_find_pcie_virt(info, mem_alloc.hw_addr);
+       info->cmdring.size = mem_alloc.size;
+       info->cmdring.ring_hw_base = mem_alloc.hw_addr;
+       info->cmdring.ring_gart_base = mem_alloc.offset;
+       info->cmdring.last_ptr = NULL;
+       info->cmdring.ring_offset = 0;
+
+       return 0;
+}
+
+
+/**
+ * get_batch_command - Get the command ID for the current begin type.
+ * @type: Type of the current batch
+ *
+ * See section 3.2.2 "Begin" (page 15) of the 3D SPG.
+ * 
+ * This function assumes that @type is on the range [0,3].
+ */
+unsigned int get_batch_command(enum xgi_batch_type type)
+{
+       static const unsigned int ports[4] = {
+               0x30 >> 2, 0x40 >> 2, 0x50 >> 2, 0x20 >> 2
+       };
+       
+       return ports[type];
+}
+
+
+static void xgi_submit_cmdlist(struct xgi_info * info,
+                              const struct xgi_cmd_info * pCmdInfo)
+{
+       const unsigned int cmd = get_batch_command(pCmdInfo->type);
+       u32 begin[4];
+
+
+       begin[0] = (cmd << 24) | BEGIN_VALID_MASK
+               | (BEGIN_BEGIN_IDENTIFICATION_MASK & pCmdInfo->id);
+       begin[1] = BEGIN_LINK_ENABLE_MASK | pCmdInfo->size;
+       begin[2] = pCmdInfo->hw_addr >> 4;
+       begin[3] = 0;
+
+       if (info->cmdring.last_ptr == NULL) {
+               const unsigned int portOffset = BASE_3D_ENG + (cmd << 2);
+
+
+               /* Enable PCI Trigger Mode
+                */
+               dwWriteReg(info->mmio_map,
+                          BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS,
+                          (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) |
+                          M2REG_CLEAR_COUNTERS_MASK | 0x08 |
+                          M2REG_PCI_TRIGGER_MODE_MASK);
+
+               dwWriteReg(info->mmio_map,
+                          BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS,
+                          (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | 0x08 |
+                          M2REG_PCI_TRIGGER_MODE_MASK);
+
+
+               /* Send PCI begin command
+                */
+               dwWriteReg(info->mmio_map, portOffset,      begin[0]);
+               dwWriteReg(info->mmio_map, portOffset +  4, begin[1]);
+               dwWriteReg(info->mmio_map, portOffset +  8, begin[2]);
+               dwWriteReg(info->mmio_map, portOffset + 12, begin[3]);
+       } else {
+               DRM_DEBUG("info->cmdring.last_ptr != NULL\n");
+
+               if (pCmdInfo->type == BTYPE_3D) {
+                       addFlush2D(info);
+               }
+
+               info->cmdring.last_ptr[1] = begin[1];
+               info->cmdring.last_ptr[2] = begin[2];
+               info->cmdring.last_ptr[3] = begin[3];
+               wmb();
+               info->cmdring.last_ptr[0] = begin[0];
+
+               triggerHWCommandList(info);
+       }
+
+       info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr);
+}
+
+
+int xgi_submit_cmdlist_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_cmd_info  cmd_list;
+       struct xgi_info *info = dev->dev_private;
+
+       DRM_COPY_FROM_USER_IOCTL(cmd_list, 
+                                (struct xgi_cmd_info __user *) data,
+                                sizeof(cmd_list));
+
+       if (cmd_list.type > BTYPE_CTRL) {
+               return DRM_ERR(EINVAL);
+       }
+
+       xgi_submit_cmdlist(info, &cmd_list);
+       return 0;
+}
+
+
+/*
+    state:      0 - console
+                1 - graphic
+                2 - fb
+                3 - logout
+*/
+int xgi_state_change(struct xgi_info * info, unsigned int to, 
+                    unsigned int from)
+{
+#define STATE_CONSOLE   0
+#define STATE_GRAPHIC   1
+#define STATE_FBTERM    2
+#define STATE_LOGOUT    3
+#define STATE_REBOOT    4
+#define STATE_SHUTDOWN  5
+
+       if ((from == STATE_GRAPHIC) && (to == STATE_CONSOLE)) {
+               DRM_INFO("Leaving graphical mode (probably VT switch)\n");
+       } else if ((from == STATE_CONSOLE) && (to == STATE_GRAPHIC)) {
+               DRM_INFO("Entering graphical mode (probably VT switch)\n");
+               xgi_cmdlist_reset(info);
+       } else if ((from == STATE_GRAPHIC)
+                  && ((to == STATE_LOGOUT)
+                      || (to == STATE_REBOOT)
+                      || (to == STATE_SHUTDOWN))) {
+               DRM_INFO("Leaving graphical mode (probably X shutting down)\n");
+       } else {
+               DRM_ERROR("Invalid state change.\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       return 0;
+}
+
+
+int xgi_state_change_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_state_info  state;
+       struct xgi_info *info = dev->dev_private;
+
+       DRM_COPY_FROM_USER_IOCTL(state, (struct xgi_state_info __user *) data,
+                                sizeof(state));
+
+       return xgi_state_change(info, state._toState, state._fromState);
+}
+
+
+void xgi_cmdlist_reset(struct xgi_info * info)
+{
+       info->cmdring.last_ptr = NULL;
+       info->cmdring.ring_offset = 0;
+}
+
+void xgi_cmdlist_cleanup(struct xgi_info * info)
+{
+       if (info->cmdring.ring_hw_base != 0) {
+               xgi_pcie_free(info, info->cmdring.ring_gart_base, NULL);
+               info->cmdring.ring_hw_base = 0;
+               info->cmdring.ring_offset = 0;
+               info->cmdring.size = 0;
+       }
+}
+
+static void triggerHWCommandList(struct xgi_info * info)
+{
+       static unsigned int s_triggerID = 1;
+
+       dwWriteReg(info->mmio_map,
+                  BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS,
+                  0x05000000 + (0x0ffff & s_triggerID++));
+}
+
+
+static void addFlush2D(struct xgi_info * info)
+{
+       u32 *flushBatchVirtAddr;
+       u32 flushBatchHWAddr;
+
+       /* check buf is large enough to contain a new flush batch */
+       if ((info->cmdring.ring_offset + 0x20) >= info->cmdring.size) {
+               info->cmdring.ring_offset = 0;
+       }
+
+       flushBatchHWAddr = info->cmdring.ring_hw_base + info->cmdring.ring_offset;
+       flushBatchVirtAddr = info->cmdring.ptr 
+               + (info->cmdring.ring_offset / 4);
+
+       /* not using memcpy for I assume the address is discrete */
+       *(flushBatchVirtAddr + 0) = 0x10000000;
+       *(flushBatchVirtAddr + 1) = 0x80000004; /* size = 0x04 dwords */
+       *(flushBatchVirtAddr + 2) = 0x00000000;
+       *(flushBatchVirtAddr + 3) = 0x00000000;
+       *(flushBatchVirtAddr + 4) = FLUSH_2D;
+       *(flushBatchVirtAddr + 5) = FLUSH_2D;
+       *(flushBatchVirtAddr + 6) = FLUSH_2D;
+       *(flushBatchVirtAddr + 7) = FLUSH_2D;
+
+       info->cmdring.last_ptr[1] = BEGIN_LINK_ENABLE_MASK + 0x08;
+       info->cmdring.last_ptr[2] = flushBatchHWAddr >> 4;
+       info->cmdring.last_ptr[3] = 0;
+       wmb();
+       info->cmdring.last_ptr[0] = (get_batch_command(BTYPE_CTRL) << 24) 
+               | (BEGIN_VALID_MASK);
+
+       triggerHWCommandList(info);
+
+       info->cmdring.ring_offset += 0x20;
+       info->cmdring.last_ptr = flushBatchVirtAddr;
+}
diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h
new file mode 100644 (file)
index 0000000..604c9aa
--- /dev/null
@@ -0,0 +1,98 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#ifndef _XGI_CMDLIST_H_
+#define _XGI_CMDLIST_H_
+
+#define                ONE_BIT_MASK                                                    0x1
+#define                TWENTY_BIT_MASK                                                 0xfffff
+#define        M2REG_FLUSH_2D_ENGINE_MASK                              (ONE_BIT_MASK<<20)
+#define        M2REG_FLUSH_3D_ENGINE_MASK                              TWENTY_BIT_MASK
+#define        M2REG_FLUSH_FLIP_ENGINE_MASK                    (ONE_BIT_MASK<<21)
+#define     BASE_3D_ENG                             0x2800
+#define     M2REG_AUTO_LINK_SETTING_ADDRESS         0x10
+#define        M2REG_CLEAR_COUNTERS_MASK                               (ONE_BIT_MASK<<4)
+#define        M2REG_PCI_TRIGGER_MODE_MASK                             (ONE_BIT_MASK<<1)
+#define        BEGIN_VALID_MASK                        (ONE_BIT_MASK<<20)
+#define        BEGIN_LINK_ENABLE_MASK                  (ONE_BIT_MASK<<31)
+#define        BEGIN_BEGIN_IDENTIFICATION_MASK         (TWENTY_BIT_MASK<<0)
+#define     M2REG_PCI_TRIGGER_REGISTER_ADDRESS      0x14
+
+typedef enum {
+       FLUSH_2D = M2REG_FLUSH_2D_ENGINE_MASK,
+       FLUSH_3D = M2REG_FLUSH_3D_ENGINE_MASK,
+       FLUSH_FLIP = M2REG_FLUSH_FLIP_ENGINE_MASK
+} FLUSH_CODE;
+
+typedef enum {
+       AGPCMDLIST_SCRATCH_SIZE = 0x100,
+       AGPCMDLIST_BEGIN_SIZE = 0x004,
+       AGPCMDLIST_3D_SCRATCH_CMD_SIZE = 0x004,
+       AGPCMDLIST_2D_SCRATCH_CMD_SIZE = 0x00c,
+       AGPCMDLIST_FLUSH_CMD_LEN = 0x004,
+       AGPCMDLIST_DUMY_END_BATCH_LEN = AGPCMDLIST_BEGIN_SIZE
+} CMD_SIZE;
+
+struct xgi_cmdring_info {
+       /**
+        * Kernel space pointer to the base of the command ring.
+        */
+       u32 * ptr;
+
+       /**
+        * Size, in bytes, of the command ring.
+        */
+       unsigned int size;
+
+       /**
+        * Base address of the command ring from the hardware's PoV.
+        */
+       unsigned int ring_hw_base;
+
+       /**
+        * Offset, in bytes, from the base of PCI-e GART space to the start
+        * of the ring.
+        */
+       unsigned long ring_gart_base;
+
+       u32 * last_ptr;
+
+       /**
+        * Offset, in bytes, from the start of the ring to the next available
+        * location to store a command.
+        */
+       unsigned int ring_offset;
+};
+
+struct xgi_info;
+extern int xgi_cmdlist_initialize(struct xgi_info * info, size_t size);
+
+extern int xgi_state_change(struct xgi_info * info, unsigned int to,
+       unsigned int from);
+
+extern void xgi_cmdlist_cleanup(struct xgi_info * info);
+
+#endif                         /* _XGI_CMDLIST_H_ */
diff --git a/linux-core/xgi_drm.h b/linux-core/xgi_drm.h
new file mode 120000 (symlink)
index 0000000..677586d
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/xgi_drm.h
\ No newline at end of file
diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c
new file mode 100644 (file)
index 0000000..2c3384b
--- /dev/null
@@ -0,0 +1,362 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#include "drmP.h"
+#include "drm.h"
+#include "xgi_drv.h"
+#include "xgi_regs.h"
+#include "xgi_misc.h"
+#include "xgi_cmdlist.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       xgi_PCI_IDS
+};
+
+static int xgi_bootstrap(DRM_IOCTL_ARGS);
+
+static drm_ioctl_desc_t xgi_ioctls[] = {
+       [DRM_IOCTL_NR(DRM_XGI_BOOTSTRAP)] = {xgi_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+
+       [DRM_IOCTL_NR(DRM_XGI_FB_ALLOC)] = {xgi_fb_alloc_ioctl, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_XGI_FB_FREE)] = {xgi_fb_free_ioctl, DRM_AUTH},
+
+       [DRM_IOCTL_NR(DRM_XGI_PCIE_ALLOC)] = {xgi_pcie_alloc_ioctl, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_XGI_PCIE_FREE)] = {xgi_pcie_free_ioctl, DRM_AUTH},
+
+       [DRM_IOCTL_NR(DRM_XGI_GE_RESET)] = {xgi_ge_reset_ioctl, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_XGI_DUMP_REGISTER)] = {xgi_dump_register_ioctl, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_XGI_DEBUG_INFO)] = {xgi_restore_registers_ioctl, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_XGI_SUBMIT_CMDLIST)] = {xgi_submit_cmdlist_ioctl, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_XGI_TEST_RWINKERNEL)] = {xgi_test_rwinkernel_ioctl, DRM_AUTH},
+       [DRM_IOCTL_NR(DRM_XGI_STATE_CHANGE)] = {xgi_state_change_ioctl, DRM_AUTH|DRM_MASTER},
+};
+
+static const int xgi_max_ioctl = DRM_ARRAY_SIZE(xgi_ioctls);
+
+static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int xgi_driver_load(struct drm_device *dev, unsigned long flags);
+static int xgi_driver_unload(struct drm_device *dev);
+static void xgi_driver_preclose(struct drm_device * dev, DRMFILE filp);
+static void xgi_driver_lastclose(drm_device_t * dev);
+static irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS);
+
+
+static struct drm_driver driver = {
+       .driver_features =
+               DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ |
+               DRIVER_IRQ_SHARED | DRIVER_SG,
+       .dev_priv_size = sizeof(struct xgi_info),
+       .load = xgi_driver_load,
+       .unload = xgi_driver_unload,
+       .preclose = xgi_driver_preclose,
+       .lastclose = xgi_driver_lastclose,
+       .dma_quiescent = NULL,
+       .irq_preinstall = NULL,
+       .irq_postinstall = NULL,
+       .irq_uninstall = NULL,
+       .irq_handler = xgi_kern_isr,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = xgi_ioctls,
+       .dma_ioctl = NULL,
+
+       .fops = {
+               .owner = THIS_MODULE,
+               .open = drm_open,
+               .release = drm_release,
+               .ioctl = drm_ioctl,
+               .mmap = drm_mmap,
+               .poll = drm_poll,
+               .fasync = drm_fasync,
+       },
+
+       .pci_driver = {
+               .name = DRIVER_NAME,
+               .id_table = pciidlist,
+               .probe = probe,
+               .remove = __devexit_p(drm_cleanup_pci),
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+
+};
+
+static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       return drm_get_dev(pdev, ent, &driver);
+}
+
+
+static int __init xgi_init(void)
+{
+       driver.num_ioctls = xgi_max_ioctl;
+       return drm_init(&driver, pciidlist);
+}
+
+static void __exit xgi_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(xgi_init);
+module_exit(xgi_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
+
+
+void xgi_kern_isr_bh(struct drm_device *dev);
+
+int xgi_bootstrap(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_info *info = dev->dev_private;
+       struct xgi_bootstrap bs;
+       struct drm_map_list *maplist;
+       int err;
+
+
+       DRM_COPY_FROM_USER_IOCTL(bs, (struct xgi_bootstrap __user *) data,
+                                sizeof(bs));
+
+       if (info->mmio_map == NULL) {
+               err = drm_addmap(dev, info->mmio.base, info->mmio.size,
+                                _DRM_REGISTERS, _DRM_KERNEL,
+                                &info->mmio_map);
+               if (err) {
+                       DRM_ERROR("Unable to map MMIO region: %d\n", err);
+                       return err;
+               }
+
+               xgi_enable_mmio(info);
+       }
+
+
+       info->fb.size = IN3CFB(info->mmio_map, 0x54) * 8 * 1024 * 1024;
+
+       DRM_INFO("fb   base: 0x%lx, size: 0x%x (probed)\n",
+                (unsigned long) info->fb.base, info->fb.size);
+
+
+       if ((info->fb.base == 0) || (info->fb.size == 0)) {
+               DRM_ERROR("framebuffer appears to be wrong: 0x%lx 0x%x\n",
+                         (unsigned long) info->fb.base, info->fb.size);
+               return DRM_ERR(EINVAL);
+       }
+
+
+       /* Init the resource manager */
+       if (!info->fb_heap.initialized) {
+               err = xgi_fb_heap_init(info);
+               if (err) {
+                       DRM_ERROR("Unable to initialize FB heap.\n");
+                       return err;
+               }
+       }
+
+
+       info->pcie.size = bs.gart.size;
+
+       /* Init the resource manager */
+       if (!info->pcie_heap.initialized) {
+               err = xgi_pcie_heap_init(info);
+               if (err) {
+                       DRM_ERROR("Unable to initialize GART heap.\n");
+                       return err;
+               }
+
+               /* Alloc 1M bytes for cmdbuffer which is flush2D batch array */
+               err = xgi_cmdlist_initialize(info, 0x100000);
+               if (err) {
+                       DRM_ERROR("xgi_cmdlist_initialize() failed\n");
+                       return err;
+               }
+       }
+
+
+       if (info->pcie_map == NULL) {
+               err = drm_addmap(info->dev, 0, info->pcie.size,
+                                _DRM_SCATTER_GATHER, _DRM_LOCKED,
+                                & info->pcie_map);
+               if (err) {
+                       DRM_ERROR("Could not add map for GART backing "
+                                 "store.\n");
+                       return err;
+               }
+       }
+
+
+       maplist = drm_find_matching_map(dev, info->pcie_map);
+       if (maplist == NULL) {
+               DRM_ERROR("Could not find GART backing store map.\n");
+               return DRM_ERR(EINVAL);
+       }
+
+       bs.gart = *info->pcie_map;
+       bs.gart.handle = (void *)(unsigned long) maplist->user_token;
+       DRM_COPY_TO_USER_IOCTL((struct xgi_bootstrap __user *) data,
+                              bs, sizeof(bs));
+
+       return 0;
+}
+
+
+void xgi_driver_preclose(struct drm_device * dev, DRMFILE filp)
+{
+       struct xgi_info * info = dev->dev_private;
+
+       xgi_pcie_free_all(info, filp);
+       xgi_fb_free_all(info, filp);
+}
+
+
+void xgi_driver_lastclose(drm_device_t * dev)
+{
+       struct xgi_info * info = dev->dev_private;
+
+       if (info != NULL) {
+               /* The core DRM lastclose routine will destroy all of our
+                * mappings for us.  NULL out the pointers here so that
+                * xgi_bootstrap can do the right thing.
+                */
+               info->pcie_map = NULL;
+               info->mmio_map = NULL;
+               info->fb_map = NULL;
+
+               xgi_cmdlist_cleanup(info);
+
+               if (info->fb_heap.initialized) {
+                       xgi_mem_heap_cleanup(&info->fb_heap);
+               }
+
+               if (info->pcie_heap.initialized) {
+                       xgi_mem_heap_cleanup(&info->pcie_heap);
+                       xgi_pcie_lut_cleanup(info);
+               }
+       }
+}
+
+
+/*
+ * driver receives an interrupt if someone waiting, then hand it off.
+ */
+irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+//     struct xgi_info *info = dev->dev_private;
+       u32 need_to_run_bottom_half = 0;
+
+       //DRM_INFO("xgi_kern_isr \n");
+
+       //xgi_dvi_irq_handler(info);
+
+       if (need_to_run_bottom_half) {
+               drm_locked_tasklet(dev, xgi_kern_isr_bh);
+       }
+
+       return IRQ_HANDLED;
+}
+
+void xgi_kern_isr_bh(struct drm_device *dev)
+{
+       struct xgi_info *info = dev->dev_private;
+
+       DRM_INFO("xgi_kern_isr_bh \n");
+
+       //xgi_dvi_irq_handler(info);
+}
+
+int xgi_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       struct xgi_info *info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER);
+
+       if (!info)
+               return DRM_ERR(ENOMEM);
+
+       (void) memset(info, 0, sizeof(*info));
+       dev->dev_private = info;
+       info->dev = dev;
+
+       sema_init(&info->fb_sem, 1);
+       sema_init(&info->pcie_sem, 1);
+
+       info->mmio.base = drm_get_resource_start(dev, 1);
+       info->mmio.size = drm_get_resource_len(dev, 1);
+
+       DRM_INFO("mmio base: 0x%lx, size: 0x%x\n",
+                (unsigned long) info->mmio.base, info->mmio.size);
+
+
+       if ((info->mmio.base == 0) || (info->mmio.size == 0)) {
+               DRM_ERROR("mmio appears to be wrong: 0x%lx 0x%x\n",
+                         (unsigned long) info->mmio.base, info->mmio.size);
+               return DRM_ERR(EINVAL);
+       }
+
+
+       info->fb.base = drm_get_resource_start(dev, 0);
+       info->fb.size = drm_get_resource_len(dev, 0);
+
+       DRM_INFO("fb   base: 0x%lx, size: 0x%x\n",
+                (unsigned long) info->fb.base, info->fb.size);
+
+
+       xgi_mem_block_cache = kmem_cache_create("xgi_mem_block",
+                                               sizeof(struct xgi_mem_block),
+                                               0,
+                                               SLAB_HWCACHE_ALIGN,
+                                               NULL, NULL);
+       if (xgi_mem_block_cache == NULL) {
+               return DRM_ERR(ENOMEM);
+       }
+
+
+       return 0;
+}
+
+int xgi_driver_unload(struct drm_device *dev)
+{
+       struct xgi_info * info = dev->dev_private;
+
+       if (xgi_mem_block_cache) {
+               kmem_cache_destroy(xgi_mem_block_cache);
+               xgi_mem_block_cache = NULL;
+       }
+
+       drm_free(info, sizeof(*info), DRM_MEM_DRIVER);
+       dev->dev_private = NULL;
+
+       return 0;
+}
diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h
new file mode 100644 (file)
index 0000000..2061189
--- /dev/null
@@ -0,0 +1,152 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#ifndef _XGI_DRV_H_
+#define _XGI_DRV_H_
+
+#include "drmP.h"
+#include "drm.h"
+
+#define DRIVER_AUTHOR          "Andrea Zhang <andrea_zhang@macrosynergy.com>"
+
+#define DRIVER_NAME            "xgi"
+#define DRIVER_DESC            "XGI XP5 / XP10 / XG47"
+#define DRIVER_DATE            "20070723"
+
+#define DRIVER_MAJOR           0
+#define DRIVER_MINOR           10
+#define DRIVER_PATCHLEVEL      0
+
+#include "xgi_cmdlist.h"
+#include "xgi_drm.h"
+
+struct xgi_aperture {
+       dma_addr_t base;
+       unsigned int size;
+};
+
+struct xgi_mem_block {
+       struct list_head list;
+       unsigned long offset;
+       unsigned long size;
+       DRMFILE filp;
+
+       unsigned int owner;
+};
+
+struct xgi_mem_heap {
+       struct list_head free_list;
+       struct list_head used_list;
+       struct list_head sort_list;
+       unsigned long max_freesize;
+
+       bool initialized;
+};
+
+struct xgi_info {
+       struct drm_device *dev;
+
+       bool bootstrap_done;
+
+       /* physical characteristics */
+       struct xgi_aperture mmio;
+       struct xgi_aperture fb;
+       struct xgi_aperture pcie;
+
+       struct drm_map *mmio_map;
+       struct drm_map *pcie_map;
+       struct drm_map *fb_map;
+
+       /* look up table parameters */
+       struct drm_dma_handle *lut_handle;
+       unsigned int lutPageSize;
+
+       struct xgi_mem_heap fb_heap;
+       struct xgi_mem_heap pcie_heap;
+
+       struct semaphore fb_sem;
+       struct semaphore pcie_sem;
+
+       struct xgi_cmdring_info cmdring;
+};
+
+enum PcieOwner {
+       PCIE_2D = 0,
+       /*
+          PCIE_3D should not begin with 1,
+          2D alloc pcie memory will use owner 1.
+        */
+       PCIE_3D = 11,           /*vetex buf */
+       PCIE_3D_CMDLIST = 12,
+       PCIE_3D_SCRATCHPAD = 13,
+       PCIE_3D_TEXTURE = 14,
+       PCIE_INVALID = 0x7fffffff
+};
+
+
+extern struct kmem_cache *xgi_mem_block_cache;
+extern struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap,
+       unsigned long size, enum PcieOwner owner);
+extern int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset,
+       DRMFILE filp);
+extern int xgi_mem_heap_init(struct xgi_mem_heap * heap, unsigned int start,
+       unsigned int end);
+extern void xgi_mem_heap_cleanup(struct xgi_mem_heap * heap);
+
+extern int xgi_fb_heap_init(struct xgi_info * info);
+
+extern int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,
+       DRMFILE filp);
+
+extern int xgi_fb_free(struct xgi_info * info, unsigned long offset,
+       DRMFILE filp);
+
+extern int xgi_pcie_heap_init(struct xgi_info * info);
+extern void xgi_pcie_lut_cleanup(struct xgi_info * info);
+
+extern int xgi_pcie_alloc(struct xgi_info * info,
+                         struct xgi_mem_alloc * alloc, DRMFILE filp);
+
+extern int xgi_pcie_free(struct xgi_info * info, unsigned long offset,
+       DRMFILE filp);
+
+extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address);
+
+extern void xgi_pcie_free_all(struct xgi_info *, DRMFILE);
+extern void xgi_fb_free_all(struct xgi_info *, DRMFILE);
+
+extern int xgi_fb_alloc_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_fb_free_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_pcie_alloc_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_pcie_free_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_ge_reset_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_dump_register_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_restore_registers_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_submit_cmdlist_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS);
+extern int xgi_state_change_ioctl(DRM_IOCTL_ARGS);
+
+#endif
diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c
new file mode 100644 (file)
index 0000000..3d3b2ae
--- /dev/null
@@ -0,0 +1,370 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#include "xgi_drv.h"
+
+#define XGI_FB_HEAP_START 0x1000000
+
+struct kmem_cache *xgi_mem_block_cache = NULL;
+
+static struct xgi_mem_block *xgi_mem_new_node(void);
+
+
+int xgi_mem_heap_init(struct xgi_mem_heap *heap, unsigned int start,
+                     unsigned int end)
+{
+       struct xgi_mem_block *block;
+
+       INIT_LIST_HEAD(&heap->free_list);
+       INIT_LIST_HEAD(&heap->used_list);
+       INIT_LIST_HEAD(&heap->sort_list);
+       heap->initialized = TRUE;
+
+       block = kmem_cache_alloc(xgi_mem_block_cache, GFP_KERNEL);
+       if (!block) {
+               return DRM_ERR(ENOMEM);
+       }
+
+       block->offset = start;
+       block->size = end - start;
+
+       list_add(&block->list, &heap->free_list);
+
+       heap->max_freesize = end - start;
+
+       return 0;
+}
+
+
+void xgi_mem_heap_cleanup(struct xgi_mem_heap * heap)
+{
+       struct list_head *free_list;
+       struct xgi_mem_block *block;
+       struct xgi_mem_block *next;
+       int i;
+
+       free_list = &heap->free_list;
+       for (i = 0; i < 3; i++, free_list++) {
+               list_for_each_entry_safe(block, next, free_list, list) {
+                       DRM_INFO
+                               ("No. %d block->offset: 0x%lx block->size: 0x%lx \n",
+                                i, block->offset, block->size);
+                       kmem_cache_free(xgi_mem_block_cache, block);
+                       block = NULL;
+               }
+       }
+       
+       heap->initialized = 0;
+}
+
+
+struct xgi_mem_block *xgi_mem_new_node(void)
+{
+       struct xgi_mem_block *block =
+               kmem_cache_alloc(xgi_mem_block_cache, GFP_KERNEL);
+
+       if (!block) {
+               DRM_ERROR("kmem_cache_alloc failed\n");
+               return NULL;
+       }
+
+       block->offset = 0;
+       block->size = 0;
+       block->owner = PCIE_INVALID;
+       block->filp = (DRMFILE) -1;
+
+       return block;
+}
+
+
+struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap,
+                                   unsigned long originalSize,
+                                   enum PcieOwner owner)
+{
+       struct xgi_mem_block *block, *free_block, *used_block;
+       unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK;
+
+
+       DRM_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n",
+                originalSize, size);
+
+       if (size == 0) {
+               DRM_ERROR("size == 0\n");
+               return (NULL);
+       }
+       DRM_INFO("max_freesize: 0x%lx \n", heap->max_freesize);
+       if (size > heap->max_freesize) {
+               DRM_ERROR
+                   ("size: 0x%lx is bigger than frame buffer total free size: 0x%lx !\n",
+                    size, heap->max_freesize);
+               return (NULL);
+       }
+
+       list_for_each_entry(block, &heap->free_list, list) {
+               DRM_INFO("block: 0x%px \n", block);
+               if (size <= block->size) {
+                       break;
+               }
+       }
+
+       if (&block->list == &heap->free_list) {
+               DRM_ERROR
+                   ("Can't allocate %ldk size from frame buffer memory !\n",
+                    size / 1024);
+               return (NULL);
+       }
+
+       free_block = block;
+       DRM_INFO("alloc size: 0x%lx from offset: 0x%lx size: 0x%lx \n",
+                size, free_block->offset, free_block->size);
+
+       if (size == free_block->size) {
+               used_block = free_block;
+               DRM_INFO("size == free_block->size: free_block = 0x%p\n",
+                        free_block);
+               list_del(&free_block->list);
+       } else {
+               used_block = xgi_mem_new_node();
+
+               if (used_block == NULL)
+                       return (NULL);
+
+               if (used_block == free_block) {
+                       DRM_ERROR("used_block == free_block = 0x%p\n",
+                                 used_block);
+               }
+
+               used_block->offset = free_block->offset;
+               used_block->size = size;
+
+               free_block->offset += size;
+               free_block->size -= size;
+       }
+
+       heap->max_freesize -= size;
+
+       list_add(&used_block->list, &heap->used_list);
+       used_block->owner = owner;
+
+       return (used_block);
+}
+
+int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset,
+                DRMFILE filp)
+{
+       struct xgi_mem_block *used_block = NULL, *block;
+       struct xgi_mem_block *prev, *next;
+
+       unsigned long upper;
+       unsigned long lower;
+
+       list_for_each_entry(block, &heap->used_list, list) {
+               if (block->offset == offset) {
+                       break;
+               }
+       }
+
+       if (&block->list == &heap->used_list) {
+               DRM_ERROR("can't find block: 0x%lx to free!\n", offset);
+               return DRM_ERR(ENOENT);
+       }
+
+       if (block->filp != filp) {
+               return DRM_ERR(EPERM);
+       }
+
+       used_block = block;
+       DRM_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx\n",
+                used_block, used_block->offset, used_block->size);
+
+       heap->max_freesize += used_block->size;
+
+       prev = next = NULL;
+       upper = used_block->offset + used_block->size;
+       lower = used_block->offset;
+
+       list_for_each_entry(block, &heap->free_list, list) {
+               if (block->offset == upper) {
+                       next = block;
+               } else if ((block->offset + block->size) == lower) {
+                       prev = block;
+               }
+       }
+
+       DRM_INFO("next = 0x%p, prev = 0x%p\n", next, prev);
+       list_del(&used_block->list);
+
+       if (prev && next) {
+               prev->size += (used_block->size + next->size);
+               list_del(&next->list);
+               DRM_INFO("free node 0x%p\n", next);
+               kmem_cache_free(xgi_mem_block_cache, next);
+               kmem_cache_free(xgi_mem_block_cache, used_block);
+       }
+       else if (prev) {
+               prev->size += used_block->size;
+               DRM_INFO("free node 0x%p\n", used_block);
+               kmem_cache_free(xgi_mem_block_cache, used_block);
+       }
+       else if (next) {
+               next->size += used_block->size;
+               next->offset = used_block->offset;
+               DRM_INFO("free node 0x%p\n", used_block);
+               kmem_cache_free(xgi_mem_block_cache, used_block);
+       }
+       else {
+               list_add(&used_block->list, &heap->free_list);
+               DRM_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n",
+                        used_block, used_block->offset, used_block->size);
+       }
+
+       return 0;
+}
+
+
+int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,
+                DRMFILE filp)
+{
+       struct xgi_mem_block *block;
+
+       if (alloc->is_front) {
+               alloc->location = XGI_MEMLOC_LOCAL;
+               alloc->offset = 0;
+               alloc->hw_addr = 0;
+               DRM_INFO
+                   ("Video RAM allocation on front buffer successfully! \n");
+       } else {
+               down(&info->fb_sem);
+               block = xgi_mem_alloc(&info->fb_heap, alloc->size, PCIE_2D);
+               up(&info->fb_sem);
+
+               if (block == NULL) {
+                       alloc->location = XGI_MEMLOC_LOCAL;
+                       alloc->size = 0;
+                       DRM_ERROR("Video RAM allocation failed\n");
+                       return DRM_ERR(ENOMEM);
+               } else {
+                       DRM_INFO("Video RAM allocation succeeded: 0x%p\n",
+                                (char *)block->offset);
+                       alloc->location = XGI_MEMLOC_LOCAL;
+                       alloc->size = block->size;
+                       alloc->offset = block->offset;
+                       alloc->hw_addr = block->offset;
+
+                       block->filp = filp;
+               }
+       }
+
+       return 0;
+}
+
+
+int xgi_fb_alloc_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_mem_alloc alloc;
+       struct xgi_info *info = dev->dev_private;
+       int err;
+
+       DRM_COPY_FROM_USER_IOCTL(alloc, (struct xgi_mem_alloc __user *) data,
+                                sizeof(alloc));
+
+       err = xgi_fb_alloc(info, & alloc, filp);
+       if (err) {
+               return err;
+       }
+
+       DRM_COPY_TO_USER_IOCTL((struct xgi_mem_alloc __user *) data,
+                              alloc, sizeof(alloc));
+
+       return 0;
+}
+
+
+int xgi_fb_free(struct xgi_info * info, unsigned long offset, DRMFILE filp)
+{
+       int err = 0;
+
+       if (offset == 0) {
+               DRM_INFO("free onscreen frame buffer successfully !\n");
+       } else {
+               down(&info->fb_sem);
+               err = xgi_mem_free(&info->fb_heap, offset, filp);
+               up(&info->fb_sem);
+       }
+
+       return err;
+}
+
+
+int xgi_fb_free_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_info *info = dev->dev_private;
+       u32 offset;
+
+       DRM_COPY_FROM_USER_IOCTL(offset, (unsigned long __user *) data,
+                                sizeof(offset));
+
+       return xgi_fb_free(info, offset, filp);
+}
+
+
+int xgi_fb_heap_init(struct xgi_info * info)
+{
+       return xgi_mem_heap_init(&info->fb_heap, XGI_FB_HEAP_START,
+                                info->fb.size);
+}
+
+/**
+ * Free all blocks associated with a particular file handle.
+ */
+void xgi_fb_free_all(struct xgi_info * info, DRMFILE filp)
+{
+       if (!info->fb_heap.initialized) {
+               return;
+       }
+
+       down(&info->fb_sem);
+
+       do {
+               struct xgi_mem_block *block;
+
+               list_for_each_entry(block, &info->fb_heap.used_list, list) {
+                       if (block->filp == filp) {
+                               break;
+                       }
+               }
+
+               if (&block->list == &info->fb_heap.used_list) {
+                       break;
+               }
+
+               (void) xgi_mem_free(&info->fb_heap, block->offset, filp);
+       } while(1);
+
+       up(&info->fb_sem);
+}
diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c
new file mode 100644 (file)
index 0000000..5e8c3da
--- /dev/null
@@ -0,0 +1,474 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#include "xgi_drv.h"
+#include "xgi_regs.h"
+
+int xgi_ge_reset_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_info *info = dev->dev_private;
+
+       xgi_disable_ge(info);
+       xgi_enable_ge(info);
+
+       return 0;
+}
+
+
+/*
+ * irq functions
+ */
+#define STALL_INTERRUPT_RESET_THRESHOLD 0xffff
+
+static unsigned int s_invalid_begin = 0;
+
+static bool xgi_validate_signal(volatile u8 *mmio_vbase)
+{
+       volatile u32 *const ge_3d_status = 
+               (volatile u32 *)(mmio_vbase + 0x2800);
+       const u32 old_ge_status = ge_3d_status[0x00];
+
+       if (old_ge_status & 0x001c0000) {
+               u16 check;
+
+               /* Check Read back status */
+               *(mmio_vbase + 0x235c) = 0x80;
+               check = *((volatile u16 *)(mmio_vbase + 0x2360));
+
+               if ((check & 0x3f) != ((check & 0x3f00) >> 8)) {
+                       return FALSE;
+               }
+
+               /* Check RO channel */
+               *(mmio_vbase + 0x235c) = 0x83;
+               check = *((volatile u16 *)(mmio_vbase + 0x2360));
+               if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
+                       return FALSE;
+               }
+
+               /* Check RW channel */
+               *(mmio_vbase + 0x235c) = 0x88;
+               check = *((volatile u16 *)(mmio_vbase + 0x2360));
+               if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
+                       return FALSE;
+               }
+
+               /* Check RO channel outstanding */
+               *(mmio_vbase + 0x235c) = 0x8f;
+               check = *((volatile u16 *)(mmio_vbase + 0x2360));
+               if (0 != (check & 0x3ff)) {
+                       return FALSE;
+               }
+
+               /* Check RW channel outstanding */
+               *(mmio_vbase + 0x235c) = 0x90;
+               check = *((volatile u16 *)(mmio_vbase + 0x2360));
+               if (0 != (check & 0x3ff)) {
+                       return FALSE;
+               }
+
+               /* No pending PCIE request. GE stall. */
+       }
+
+       return TRUE;
+}
+
+
+static void xgi_ge_hang_reset(volatile u8 *mmio_vbase)
+{
+       volatile u32 *const ge_3d_status =
+               (volatile u32 *)(mmio_vbase + 0x2800);
+       int time_out = 0xffff;
+
+       *(mmio_vbase + 0xb057) = 8;
+       while (0 != (ge_3d_status[0x00] & 0xf0000000)) {
+               while (0 != ((--time_out) & 0xfff)) 
+                       /* empty */ ;
+
+               if (0 == time_out) {
+                       u8 old_3ce;
+                       u8 old_3cf;
+                       u8 old_index;
+                       u8 old_36;
+
+                       DRM_INFO("Can not reset back 0x%x!\n",
+                                ge_3d_status[0x00]);
+
+                       *(mmio_vbase + 0xb057) = 0;
+
+                       /* Have to use 3x5.36 to reset. */
+                       /* Save and close dynamic gating */
+
+                       old_3ce = *(mmio_vbase + 0x3ce);
+                       *(mmio_vbase + 0x3ce) = 0x2a;
+                       old_3cf = *(mmio_vbase + 0x3cf);
+                       *(mmio_vbase + 0x3cf) = old_3cf & 0xfe;
+
+                       /* Reset GE */
+                       old_index = *(mmio_vbase + 0x3d4);
+                       *(mmio_vbase + 0x3d4) = 0x36;
+                       old_36 = *(mmio_vbase + 0x3d5);
+                       *(mmio_vbase + 0x3d5) = old_36 | 0x10;
+
+                       while (0 != ((--time_out) & 0xfff)) 
+                               /* empty */ ;
+
+                       *(mmio_vbase + 0x3d5) = old_36;
+                       *(mmio_vbase + 0x3d4) = old_index;
+
+                       /* Restore dynamic gating */
+                       *(mmio_vbase + 0x3cf) = old_3cf; 
+                       *(mmio_vbase + 0x3ce) = old_3ce;
+                       break;
+               }
+       }
+
+       *(mmio_vbase + 0xb057) = 0;
+}
+
+       
+bool xgi_ge_irq_handler(struct xgi_info * info)
+{
+       volatile u8 *const mmio_vbase = info->mmio_map->handle;
+       volatile u32 *const ge_3d_status =
+               (volatile u32 *)(mmio_vbase + 0x2800);
+       const u32 int_status = ge_3d_status[4];
+       bool is_support_auto_reset = FALSE;
+
+       /* Check GE on/off */
+       if (0 == (0xffffc0f0 & int_status)) {
+               u32 old_pcie_cmd_fetch_Addr = ge_3d_status[0x0a];
+
+               if (0 != (0x1000 & int_status)) {
+                       /* We got GE stall interrupt. 
+                        */
+                       ge_3d_status[0x04] = int_status | 0x04000000;
+
+                       if (is_support_auto_reset) {
+                               static cycles_t last_tick;
+                               static unsigned continue_int_count = 0;
+
+                               /* OE II is busy. */
+
+                               if (!xgi_validate_signal(mmio_vbase)) {
+                                       /* Nothing but skip. */
+                               } else if (0 == continue_int_count++) {
+                                       last_tick = get_cycles();
+                               } else {
+                                       const cycles_t new_tick = get_cycles();
+                                       if ((new_tick - last_tick) >
+                                           STALL_INTERRUPT_RESET_THRESHOLD) {
+                                               continue_int_count = 0;
+                                       } else if (continue_int_count >= 3) {
+                                               continue_int_count = 0;
+
+                                               /* GE Hung up, need reset. */
+                                               DRM_INFO("Reset GE!\n");
+
+                                               xgi_ge_hang_reset(mmio_vbase);
+                                       }
+                               }
+                       }
+               } else if (0 != (0x1 & int_status)) {
+                       s_invalid_begin++;
+                       ge_3d_status[0x04] = (int_status & ~0x01) | 0x04000000;
+               }
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+bool xgi_crt_irq_handler(struct xgi_info * info)
+{
+       bool ret = FALSE;
+       u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
+
+       if (IN3CFB(info->mmio_map, 0x37) & 0x01)        // CRT1 interrupt just happened
+       {
+               u8 op3cf_3d;
+               u8 op3cf_37;
+
+               // What happened?
+               op3cf_37 = IN3CFB(info->mmio_map, 0x37);
+
+               // Clear CRT interrupt
+               op3cf_3d = IN3CFB(info->mmio_map, 0x3d);
+               OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d | 0x04));
+               OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d & ~0x04));
+               ret = TRUE;
+       }
+       DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
+
+       return (ret);
+}
+
+bool xgi_dvi_irq_handler(struct xgi_info * info)
+{
+       bool ret = FALSE;
+       const u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
+
+       if (IN3CFB(info->mmio_map, 0x38) & 0x20) {      // DVI interrupt just happened
+               const u8 save_3x4 = DRM_READ8(info->mmio_map, 0x3d4);
+               u8 op3cf_39;
+               u8 op3cf_37;
+               u8 op3x5_5a;
+
+               // What happened?
+               op3cf_37 = IN3CFB(info->mmio_map, 0x37);
+
+               //Notify BIOS that DVI plug/unplug happened
+               op3x5_5a = IN3X5B(info->mmio_map, 0x5a);
+               OUT3X5B(info->mmio_map, 0x5a, op3x5_5a & 0xf7);
+
+               DRM_WRITE8(info->mmio_map, 0x3d4, save_3x4);
+
+               // Clear DVI interrupt
+               op3cf_39 = IN3CFB(info->mmio_map, 0x39);
+               OUT3C5B(info->mmio_map, 0x39, (op3cf_39 & ~0x01));      //Set 3cf.39 bit 0 to 0
+               OUT3C5B(info->mmio_map, 0x39, (op3cf_39 | 0x01));       //Set 3cf.39 bit 0 to 1
+
+               ret = TRUE;
+       }
+       DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
+
+       return (ret);
+}
+
+
+void xgi_dump_register(struct xgi_info * info)
+{
+       int i, j;
+       unsigned char temp;
+
+       // 0x3C5
+       printk("\r\n=====xgi_dump_register========0x%x===============\r\n",
+              0x3C5);
+
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0x10; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = IN3C5B(info->mmio_map, i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+
+       // 0x3D5
+       printk("\r\n====xgi_dump_register=========0x%x===============\r\n",
+              0x3D5);
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0x10; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = IN3X5B(info->mmio_map, i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+
+       // 0x3CF
+       printk("\r\n=========xgi_dump_register====0x%x===============\r\n",
+              0x3CF);
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0x10; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = IN3CFB(info->mmio_map, i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+
+       printk("\r\n=====xgi_dump_register======0x%x===============\r\n",
+              0xB000);
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0x5; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = DRM_READ8(info->mmio_map, 0xB000 + i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+
+       printk("\r\n==================0x%x===============\r\n", 0x2200);
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0xB; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = DRM_READ8(info->mmio_map, 0x2200 + i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+
+       printk("\r\n==================0x%x===============\r\n", 0x2300);
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0x7; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = DRM_READ8(info->mmio_map, 0x2300 + i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+
+       printk("\r\n==================0x%x===============\r\n", 0x2400);
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0x10; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = DRM_READ8(info->mmio_map, 0x2400 + i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+
+       printk("\r\n==================0x%x===============\r\n", 0x2800);
+       for (i = 0; i < 0x10; i++) {
+               if (i == 0) {
+                       printk("%5x", i);
+               } else {
+                       printk("%3x", i);
+               }
+       }
+       printk("\r\n");
+
+       for (i = 0; i < 0x10; i++) {
+               printk("%1x ", i);
+
+               for (j = 0; j < 0x10; j++) {
+                       temp = DRM_READ8(info->mmio_map, 0x2800 + i * 0x10 + j);
+                       printk("%3x", temp);
+               }
+               printk("\r\n");
+       }
+}
+
+
+int xgi_dump_register_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_info *info = dev->dev_private;
+
+       xgi_dump_register(info);
+
+       return 0;
+}
+
+
+int xgi_restore_registers_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_info *info = dev->dev_private;
+
+       OUT3X5B(info->mmio_map, 0x13, 0);
+       OUT3X5B(info->mmio_map, 0x8b, 2);
+
+       return 0;
+}
+
+void xgi_waitfor_pci_idle(struct xgi_info * info)
+{
+#define WHOLD_GE_STATUS             0x2800
+#define IDLE_MASK                   ~0x90200000
+
+       int idleCount = 0;
+       while (idleCount < 5) {
+               if (DRM_READ32(info->mmio_map, WHOLD_GE_STATUS) & IDLE_MASK) {
+                       idleCount = 0;
+               } else {
+                       idleCount++;
+               }
+       }
+}
diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h
new file mode 100644 (file)
index 0000000..af19a11
--- /dev/null
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.                  
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#ifndef _XGI_MISC_H_
+#define _XGI_MISC_H_
+
+extern void xgi_dump_register(struct xgi_info * info);
+
+extern bool xgi_ge_irq_handler(struct xgi_info * info);
+extern bool xgi_crt_irq_handler(struct xgi_info * info);
+extern bool xgi_dvi_irq_handler(struct xgi_info * info);
+extern void xgi_waitfor_pci_idle(struct xgi_info * info);
+
+#endif
diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c
new file mode 100644 (file)
index 0000000..537e82f
--- /dev/null
@@ -0,0 +1,348 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#include "xgi_drv.h"
+#include "xgi_regs.h"
+#include "xgi_misc.h"
+
+static struct xgi_mem_block *xgi_pcie_vertex_block = NULL;
+static struct xgi_mem_block *xgi_pcie_cmdlist_block = NULL;
+static struct xgi_mem_block *xgi_pcie_scratchpad_block = NULL;
+
+static int xgi_pcie_free_locked(struct xgi_info * info,
+        unsigned long offset, DRMFILE filp);
+
+static int xgi_pcie_lut_init(struct xgi_info * info)
+{
+       u8 temp = 0;
+       int err;
+       unsigned i;
+       struct drm_scatter_gather request;
+       struct drm_sg_mem *sg;
+       u32 *lut;
+
+
+       /* Get current FB aperture size */
+       temp = IN3X5B(info->mmio_map, 0x27);
+       DRM_INFO("In3x5(0x27): 0x%x \n", temp);
+
+       if (temp & 0x01) {      /* 256MB; Jong 06/05/2006; 0x10000000 */
+               info->pcie.base = 256 * 1024 * 1024;
+       } else {                /* 128MB; Jong 06/05/2006; 0x08000000 */
+               info->pcie.base = 128 * 1024 * 1024;
+       }
+
+
+       DRM_INFO("info->pcie.base: 0x%lx\n", (unsigned long) info->pcie.base);
+
+       /* Get current lookup table page size */
+       temp = DRM_READ8(info->mmio_map, 0xB00C);
+       if (temp & 0x04) {      /* 8KB */
+               info->lutPageSize = 8 * 1024;
+       } else {                /* 4KB */
+               info->lutPageSize = 4 * 1024;
+       }
+
+       DRM_INFO("info->lutPageSize: 0x%x \n", info->lutPageSize);
+
+
+       request.size = info->pcie.size;
+       err = drm_sg_alloc(info->dev, & request);
+       if (err) {
+               DRM_ERROR("cannot allocate PCIE GART backing store!  "
+                         "size = %d\n", info->pcie.size);
+               return err;
+       }
+
+       sg = info->dev->sg;
+
+       info->lut_handle = drm_pci_alloc(info->dev, 
+                                        sizeof(u32) * sg->pages,
+                                        PAGE_SIZE,
+                                        DMA_31BIT_MASK);
+       if (info->lut_handle == NULL) {
+               DRM_ERROR("cannot allocate PCIE lut page!\n");
+               return DRM_ERR(ENOMEM);
+       }
+
+       lut = info->lut_handle->vaddr;
+       for (i = 0; i < sg->pages; i++) {
+               info->dev->sg->busaddr[i] = pci_map_page(info->dev->pdev,
+                                                        sg->pagelist[i],
+                                                        0,
+                                                        PAGE_SIZE,
+                                                        DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(info->dev->sg->busaddr[i])) {
+                       DRM_ERROR("cannot map GART backing store for DMA!\n");
+                       return DRM_ERR(-(info->dev->sg->busaddr[i]));
+               }
+
+               lut[i] = info->dev->sg->busaddr[i];
+       }
+
+#if defined(__i386__) || defined(__x86_64__)
+       asm volatile ("wbinvd":::"memory");
+#else
+       mb();
+#endif
+
+       /* Set GART in SFB */
+       temp = DRM_READ8(info->mmio_map, 0xB00C);
+       DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02);
+
+       /* Set GART base address to HW */
+       dwWriteReg(info->mmio_map, 0xB034, info->lut_handle->busaddr);
+
+       return 0;
+}
+
+void xgi_pcie_lut_cleanup(struct xgi_info * info)
+{
+       if (info->dev->sg) {
+               drm_sg_free(info->dev, info->dev->sg->handle);
+       }
+
+       if (info->lut_handle) {
+               drm_pci_free(info->dev, info->lut_handle);
+               info->lut_handle = NULL;
+       }
+}
+
+int xgi_pcie_heap_init(struct xgi_info * info)
+{
+       int err;
+
+       err = xgi_pcie_lut_init(info);
+       if (err) {
+               DRM_ERROR("xgi_pcie_lut_init failed\n");
+               return err;
+       }
+
+
+       err = xgi_mem_heap_init(&info->pcie_heap, 0, info->pcie.size);
+       if (err) {
+               xgi_pcie_lut_cleanup(info);
+       }
+
+       return err;
+}
+
+
+int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc,
+                  DRMFILE filp)
+{
+       struct xgi_mem_block *block;
+
+       down(&info->pcie_sem);
+       if ((alloc->owner == PCIE_3D) && (xgi_pcie_vertex_block)) {
+               DRM_INFO("PCIE Vertex has been created, return directly.\n");
+               block = xgi_pcie_vertex_block;
+       }
+       else if ((alloc->owner == PCIE_3D_CMDLIST) && (xgi_pcie_cmdlist_block)) {
+               DRM_INFO("PCIE Cmdlist has been created, return directly.\n");
+               block = xgi_pcie_cmdlist_block;
+       }
+       else if ((alloc->owner == PCIE_3D_SCRATCHPAD) && (xgi_pcie_scratchpad_block)) {
+               DRM_INFO("PCIE Scratchpad has been created, return directly.\n");
+               block = xgi_pcie_scratchpad_block;
+       }
+       else {
+               block = xgi_mem_alloc(&info->pcie_heap, alloc->size, alloc->owner);
+
+               if (alloc->owner == PCIE_3D) {
+                       xgi_pcie_vertex_block = block;
+               }
+               else if (alloc->owner == PCIE_3D_CMDLIST) {
+                       xgi_pcie_cmdlist_block = block;
+               }
+               else if (alloc->owner == PCIE_3D_SCRATCHPAD) {
+                       xgi_pcie_scratchpad_block = block;
+               }
+       }
+       up(&info->pcie_sem);
+
+       if (block == NULL) {
+               alloc->location = XGI_MEMLOC_INVALID;
+               alloc->size = 0;
+               DRM_ERROR("PCIE RAM allocation failed\n");
+               return DRM_ERR(ENOMEM);
+       } else {
+               DRM_INFO("PCIE RAM allocation succeeded: offset = 0x%lx\n",
+                        block->offset);
+               alloc->location = XGI_MEMLOC_NON_LOCAL;
+               alloc->size = block->size;
+               alloc->hw_addr = block->offset + info->pcie.base;
+               alloc->offset = block->offset;
+
+               block->filp = filp;
+               return 0;
+       }
+}
+
+
+int xgi_pcie_alloc_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_mem_alloc alloc;
+       struct xgi_info *info = dev->dev_private;
+       int err;
+
+       DRM_COPY_FROM_USER_IOCTL(alloc, (struct xgi_mem_alloc __user *) data,
+                                sizeof(alloc));
+
+       err = xgi_pcie_alloc(info, & alloc, filp);
+       if (err) {
+               return err;
+       }
+       
+       DRM_COPY_TO_USER_IOCTL((struct xgi_mem_alloc __user *) data,
+                              alloc, sizeof(alloc));
+
+       return 0;
+}
+
+
+/**
+ * Free all blocks associated with a particular file handle.
+ */
+void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp)
+{
+       if (!info->pcie_heap.initialized) {
+               return;
+       }
+
+       down(&info->pcie_sem);
+
+       do {
+               struct xgi_mem_block *block;
+
+               list_for_each_entry(block, &info->pcie_heap.used_list, list) {
+                       if (block->filp == filp) {
+                               break;
+                       }
+               }
+
+               if (&block->list == &info->pcie_heap.used_list) {
+                       break;
+               }
+
+               (void) xgi_pcie_free_locked(info, block->offset, filp);
+       } while(1);
+
+       up(&info->pcie_sem);
+}
+
+
+int xgi_pcie_free_locked(struct xgi_info * info,
+                        unsigned long offset, DRMFILE filp)
+{
+       const bool isvertex = (xgi_pcie_vertex_block
+                              && (xgi_pcie_vertex_block->offset == offset));
+       int err = xgi_mem_free(&info->pcie_heap, offset, filp);
+
+       if (!err && isvertex)
+               xgi_pcie_vertex_block = NULL;
+
+       return err;
+}
+
+
+int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp)
+{
+       int err;
+
+       down(&info->pcie_sem);
+       err = xgi_pcie_free_locked(info, offset, filp);
+       up(&info->pcie_sem);
+
+       if (err) {
+               DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset);
+       }
+
+       return err;
+}
+
+
+int xgi_pcie_free_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_info *info = dev->dev_private;
+       u32 offset;
+
+       DRM_COPY_FROM_USER_IOCTL(offset, (unsigned long __user *) data,
+                                sizeof(offset));
+
+       return xgi_pcie_free(info, offset, filp);
+}
+
+
+/**
+ * xgi_find_pcie_virt
+ * @address: GE HW address
+ *
+ * Returns CPU virtual address.  Assumes the CPU VAddr is continuous in not
+ * the same block
+ */
+void *xgi_find_pcie_virt(struct xgi_info * info, u32 address)
+{
+       const unsigned long offset = address - info->pcie.base;
+
+       return ((u8 *) info->dev->sg->virtual) + offset;
+}
+
+/*
+    address -- GE hw address
+*/
+int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       struct xgi_info *info = dev->dev_private;
+       u32 address;
+       u32 *virtaddr = 0;
+
+       DRM_COPY_FROM_USER_IOCTL(address, (unsigned long __user *) data,
+                                sizeof(address));
+
+       DRM_INFO("input GE HW addr is 0x%x\n", address);
+
+       if (address == 0) {
+               return DRM_ERR(EFAULT);
+       }
+
+       virtaddr = (u32 *)xgi_find_pcie_virt(info, address);
+
+       DRM_INFO("convert to CPU virt addr 0x%p\n", virtaddr);
+
+       if (virtaddr != NULL) {
+               DRM_INFO("original [virtaddr] = 0x%x\n", *virtaddr);
+               *virtaddr = 0x00f00fff;
+               DRM_INFO("modified [virtaddr] = 0x%x\n", *virtaddr);
+       } else {
+               return DRM_ERR(EFAULT);
+       }
+
+       return 0;
+}
diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h
new file mode 100644 (file)
index 0000000..34268a5
--- /dev/null
@@ -0,0 +1,216 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the     
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#ifndef _XGI_REGS_H_
+#define _XGI_REGS_H_
+
+#include "drmP.h"
+#include "drm.h"
+
+
+/* Hardware access functions */
+static inline void OUT3C5B(struct drm_map * map, u8 index, u8 data)
+{
+       DRM_WRITE8(map, 0x3C4, index);
+       DRM_WRITE8(map, 0x3C5, data);
+}
+
+static inline void OUT3X5B(struct drm_map * map, u8 index, u8 data)
+{
+       DRM_WRITE8(map, 0x3D4, index);
+       DRM_WRITE8(map, 0x3D5, data);
+}
+
+static inline void OUT3CFB(struct drm_map * map, u8 index, u8 data)
+{
+       DRM_WRITE8(map, 0x3CE, index);
+       DRM_WRITE8(map, 0x3CF, data);
+}
+
+static inline u8 IN3C5B(struct drm_map * map, u8 index)
+{
+       DRM_WRITE8(map, 0x3C4, index);
+       return DRM_READ8(map, 0x3C5);
+}
+
+static inline u8 IN3X5B(struct drm_map * map, u8 index)
+{
+       DRM_WRITE8(map, 0x3D4, index);
+       return DRM_READ8(map, 0x3D5);
+}
+
+static inline u8 IN3CFB(struct drm_map * map, u8 index)
+{
+       DRM_WRITE8(map, 0x3CE, index);
+       return DRM_READ8(map, 0x3CF);
+}
+
+
+/*
+ * Graphic engine register (2d/3d) acessing interface
+ */
+static inline void dwWriteReg(struct drm_map * map, u32 addr, u32 data)
+{
+#ifdef XGI_MMIO_DEBUG
+       DRM_INFO("mmio_map->handle = 0x%p, addr = 0x%x, data = 0x%x\n",
+                map->handle, addr, data);
+#endif
+       DRM_WRITE32(map, addr, data);
+}
+
+
+static inline void xgi_enable_mmio(struct xgi_info * info)
+{
+       u8 protect = 0;
+       u8 temp;
+
+       /* Unprotect registers */
+       DRM_WRITE8(info->mmio_map, 0x3C4, 0x11);
+       protect = DRM_READ8(info->mmio_map, 0x3C5);
+       DRM_WRITE8(info->mmio_map, 0x3C5, 0x92);
+
+       DRM_WRITE8(info->mmio_map, 0x3D4, 0x3A);
+       temp = DRM_READ8(info->mmio_map, 0x3D5);
+       DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x20);
+
+       /* Enable MMIO */
+       DRM_WRITE8(info->mmio_map, 0x3D4, 0x39);
+       temp = DRM_READ8(info->mmio_map, 0x3D5);
+       DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x01);
+
+       /* Protect registers */
+       OUT3C5B(info->mmio_map, 0x11, protect);
+}
+
+static inline void xgi_disable_mmio(struct xgi_info * info)
+{
+       u8 protect = 0;
+       u8 temp;
+
+       /* Unprotect registers */
+       DRM_WRITE8(info->mmio_map, 0x3C4, 0x11);
+       protect = DRM_READ8(info->mmio_map, 0x3C5);
+       DRM_WRITE8(info->mmio_map, 0x3C5, 0x92);
+
+       /* Disable MMIO access */
+       DRM_WRITE8(info->mmio_map, 0x3D4, 0x39);
+       temp = DRM_READ8(info->mmio_map, 0x3D5);
+       DRM_WRITE8(info->mmio_map, 0x3D5, temp & 0xFE);
+
+       /* Protect registers */
+       OUT3C5B(info->mmio_map, 0x11, protect);
+}
+
+static inline void xgi_enable_ge(struct xgi_info * info)
+{
+       unsigned char bOld3cf2a = 0;
+       int wait = 0;
+
+       // Enable GE
+       DRM_WRITE16(info->mmio_map, 0x3C4, 0x9211);
+
+       // Save and close dynamic gating
+       bOld3cf2a = IN3CFB(info->mmio_map, 0x2a);
+       OUT3CFB(info->mmio_map, 0x2a, bOld3cf2a & 0xfe);
+
+       // Reset both 3D and 2D engine
+       OUT3X5B(info->mmio_map, 0x36, 0x84);
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+       OUT3X5B(info->mmio_map, 0x36, 0x94);
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+       OUT3X5B(info->mmio_map, 0x36, 0x84);
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+       // Enable 2D engine only
+       OUT3X5B(info->mmio_map, 0x36, 0x80);
+
+       // Enable 2D+3D engine
+       OUT3X5B(info->mmio_map, 0x36, 0x84);
+
+       // Restore dynamic gating
+       OUT3CFB(info->mmio_map, 0x2a, bOld3cf2a);
+}
+
+static inline void xgi_disable_ge(struct xgi_info * info)
+{
+       int wait = 0;
+
+       // Reset both 3D and 2D engine
+       OUT3X5B(info->mmio_map, 0x36, 0x84);
+
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+       OUT3X5B(info->mmio_map, 0x36, 0x94);
+
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+       OUT3X5B(info->mmio_map, 0x36, 0x84);
+
+       wait = 10;
+       while (wait--) {
+               DRM_READ8(info->mmio_map, 0x36);
+       }
+
+       // Disable 2D engine only
+       OUT3X5B(info->mmio_map, 0x36, 0);
+}
+
+static inline void xgi_enable_dvi_interrupt(struct xgi_info * info)
+{
+       OUT3CFB(info->mmio_map, 0x39, IN3CFB(info->mmio_map, 0x39) & ~0x01);    //Set 3cf.39 bit 0 to 0
+       OUT3CFB(info->mmio_map, 0x39, IN3CFB(info->mmio_map, 0x39) | 0x01);     //Set 3cf.39 bit 0 to 1
+       OUT3CFB(info->mmio_map, 0x39, IN3CFB(info->mmio_map, 0x39) | 0x02);
+}
+static inline void xgi_disable_dvi_interrupt(struct xgi_info * info)
+{
+       OUT3CFB(info->mmio_map, 0x39, IN3CFB(info->mmio_map, 0x39) & ~0x02);
+}
+
+static inline void xgi_enable_crt1_interrupt(struct xgi_info * info)
+{
+       OUT3CFB(info->mmio_map, 0x3d, IN3CFB(info->mmio_map, 0x3d) | 0x04);
+       OUT3CFB(info->mmio_map, 0x3d, IN3CFB(info->mmio_map, 0x3d) & ~0x04);
+       OUT3CFB(info->mmio_map, 0x3d, IN3CFB(info->mmio_map, 0x3d) | 0x08);
+}
+
+static inline void xgi_disable_crt1_interrupt(struct xgi_info * info)
+{
+       OUT3CFB(info->mmio_map, 0x3d, IN3CFB(info->mmio_map, 0x3d) & ~0x08);
+}
+
+#endif
index f0ebf2a..7193e52 100644 (file)
@@ -36,4 +36,5 @@ klibdrminclude_HEADERS = \
                          sis_drm.h \
                          via_drm.h \
                          r300_reg.h \
-                         via_3d_reg.h
+                         via_3d_reg.h \
+                        xgi_drm.h
index 126974d..4504cf7 100644 (file)
 0x12d2 0x002c NV_04 "VTNT2"
 0x12d2 0x00a0 NV_04 "ITNT2"
 
+[xgi]
+0x18ca 0x2200 0 "XP5"
+0x18ca 0x0047 0 "XP10 / XG47"
diff --git a/shared-core/xgi_drm.h b/shared-core/xgi_drm.h
new file mode 100644 (file)
index 0000000..adce706
--- /dev/null
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL XGI AND/OR
+ * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ***************************************************************************/
+
+#ifndef _XGI_DRM_H_
+#define _XGI_DRM_H_
+
+#include <linux/types.h>
+#include <asm/ioctl.h>
+
+struct drm_xgi_sarea {
+       __u16 device_id;
+       __u16 vendor_id;
+
+       char device_name[32];
+
+       unsigned int scrn_start;
+       unsigned int scrn_xres;
+       unsigned int scrn_yres;
+       unsigned int scrn_bpp;
+       unsigned int scrn_pitch;
+};
+
+
+struct xgi_bootstrap {
+       /**
+        * Size of PCI-e GART range in megabytes.
+        */
+       struct drm_map gart;
+};
+
+
+enum xgi_mem_location {
+       XGI_MEMLOC_NON_LOCAL = 0,
+       XGI_MEMLOC_LOCAL = 1,
+       XGI_MEMLOC_INVALID = 0x7fffffff
+};
+
+struct xgi_mem_alloc {
+       unsigned int location;
+       unsigned int size;
+       unsigned int is_front;
+       unsigned int owner;
+
+       /**
+        * Address of the memory from the graphics hardware's point of view.
+        */
+       __u32 hw_addr;
+
+       /**
+        * Offset of the allocation in the mapping.
+        */
+       __u32 offset;
+};
+
+enum xgi_batch_type {
+       BTYPE_2D = 0,
+       BTYPE_3D = 1,
+       BTYPE_FLIP = 2,
+       BTYPE_CTRL = 3,
+       BTYPE_NONE = 0x7fffffff
+};
+
+struct xgi_cmd_info {
+       __u32 type;
+       __u32 hw_addr;
+       __u32 size;
+       __u32 id;
+};
+
+struct xgi_state_info {
+       unsigned int _fromState;
+       unsigned int _toState;
+};
+
+
+/*
+ * Ioctl definitions
+ */
+
+#define DRM_XGI_BOOTSTRAP           0
+#define DRM_XGI_FB_ALLOC            1
+#define DRM_XGI_FB_FREE             2
+#define DRM_XGI_PCIE_ALLOC          3
+#define DRM_XGI_PCIE_FREE           4
+#define DRM_XGI_SUBMIT_CMDLIST      5
+#define DRM_XGI_GE_RESET            6
+#define DRM_XGI_DUMP_REGISTER       7
+#define DRM_XGI_DEBUG_INFO          8
+#define DRM_XGI_TEST_RWINKERNEL     9
+#define DRM_XGI_STATE_CHANGE        10
+
+#define XGI_IOCTL_BOOTSTRAP         DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_BOOTSTRAP, struct xgi_bootstrap)
+
+#define XGI_IOCTL_FB_ALLOC          DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_FB_ALLOC, struct xgi_mem_alloc)
+#define XGI_IOCTL_FB_FREE           DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_FB_FREE, __u32)
+
+#define XGI_IOCTL_PCIE_ALLOC        DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_PCIE_ALLOC, struct xgi_mem_alloc)
+#define XGI_IOCTL_PCIE_FREE         DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_PCIE_FREE, __u32)
+
+#define XGI_IOCTL_GE_RESET          DRM_IO(DRM_COMMAND_BASE + DRM_XGI_GE_RESET)
+#define XGI_IOCTL_DUMP_REGISTER     DRM_IO(DRM_COMMAND_BASE + DRM_XGI_DUMP_REGISTER)
+#define XGI_IOCTL_DEBUG_INFO        DRM_IO(DRM_COMMAND_BASE + DRM_XGI_DEBUG_INFO)
+#define XGI_IOCTL_SUBMIT_CMDLIST    DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_SUBMIT_CMDLIST, struct xgi_cmd_info)
+#define XGI_IOCTL_TEST_RWINKERNEL   DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_TEST_RWINKERNEL, __u32)
+#define XGI_IOCTL_STATE_CHANGE      DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_STATE_CHANGE, struct xgi_state_info)
+
+#endif /* _XGI_DRM_H_ */