aboutsummaryrefslogtreecommitdiff
path: root/linux-core/xgi_drv.c
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2007-07-19 10:29:18 -0700
committerIan Romanick <idr@us.ibm.com>2007-07-19 10:29:18 -0700
commit5ba94c2ab8be350fee495e5cfe94afb8f663956a (patch)
tree609018b8c0060e00bd34a6bad37d6926f8de60cb /linux-core/xgi_drv.c
parent8d60bf2f199d57ec45feaab836b31832b9bbabb9 (diff)
Initial pass at converting driver to DRM infrastructure.
Diffstat (limited to 'linux-core/xgi_drv.c')
-rw-r--r--linux-core/xgi_drv.c1522
1 files changed, 195 insertions, 1327 deletions
diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c
index bd39dfdc..3b9f4cb1 100644
--- a/linux-core/xgi_drv.c
+++ b/linux-core/xgi_drv.c
@@ -25,96 +25,119 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
***************************************************************************/
-#include "xgi_linux.h"
+
+#include "drmP.h"
+#include "drm.h"
#include "xgi_drv.h"
#include "xgi_regs.h"
-#include "xgi_pcie.h"
#include "xgi_misc.h"
#include "xgi_cmdlist.h"
-/* for debug */
-static int xgi_temp = 1;
-/*
- * global parameters
- */
-static struct xgi_dev {
- u16 vendor;
- u16 device;
- const char *name;
-} xgidev_list[] = {
- {
- PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XP5, "XP5"}, {
- PCI_VENDOR_ID_XGI, PCI_DEVICE_ID_XG47, "XG47"}, {
- 0, 0, NULL}
-};
-
-int xgi_major = XGI_DEV_MAJOR; /* xgi reserved major device number. */
+#include "drm_pciids.h"
-static int xgi_num_devices = 0;
+static struct pci_device_id pciidlist[] = {
+ xgi_PCI_IDS
+};
-struct xgi_info xgi_devices[XGI_MAX_DEVICES];
+static int xgi_bootstrap(DRM_IOCTL_ARGS);
-#if defined(XGI_PM_SUPPORT_APM)
-static struct pm_dev *apm_xgi_dev[XGI_MAX_DEVICES] = { 0 };
-#endif
+static drm_ioctl_desc_t xgi_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_XGI_BOOTSTRAP)] = {xgi_bootstrap, DRM_AUTH},
-/* add one for the control device */
-struct xgi_info xgi_ctl_device;
-wait_queue_head_t xgi_ctl_waitqueue;
+ [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},
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry *proc_xgi;
-#endif
+ [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},
-#ifdef CONFIG_DEVFS_FS
-devfs_handle_t xgi_devfs_handles[XGI_MAX_DEVICES];
-#endif
+ [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},
+};
-struct list_head xgi_mempid_list;
+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 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,
+ .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,
-/* xgi_ functions.. do not take a state device parameter */
-static int xgi_post_vbios(struct xgi_ioctl_post_vbios * info);
-static void xgi_proc_create(void);
-static void xgi_proc_remove_all(struct proc_dir_entry *);
-static void xgi_proc_remove(void);
+};
-/* xgi_kern_ functions, interfaces used by linux kernel */
-int xgi_kern_probe(struct pci_dev *, const struct pci_device_id *);
+static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ return drm_get_dev(pdev, ent, &driver);
+}
-unsigned int xgi_kern_poll(struct file *, poll_table *);
-int xgi_kern_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
-int xgi_kern_mmap(struct file *, struct vm_area_struct *);
-int xgi_kern_open(struct inode *, struct file *);
-int xgi_kern_release(struct inode *inode, struct file *filp);
-void xgi_kern_vma_open(struct vm_area_struct *vma);
-void xgi_kern_vma_release(struct vm_area_struct *vma);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 1))
-struct page *xgi_kern_vma_nopage(struct vm_area_struct *vma,
- unsigned long address, int *type);
-#else
-struct page *xgi_kern_vma_nopage(struct vm_area_struct *vma,
- unsigned long address, int write_access);
-#endif
+static int __init xgi_init(void)
+{
+ driver.num_ioctls = xgi_max_ioctl;
+ return drm_init(&driver, pciidlist);
+}
-int xgi_kern_read_card_info(char *, char **, off_t off, int, int *, void *);
-int xgi_kern_read_status(char *, char **, off_t off, int, int *, void *);
-int xgi_kern_read_pcie_info(char *, char **, off_t off, int, int *, void *);
-int xgi_kern_read_version(char *, char **, off_t off, int, int *, void *);
+static void __exit xgi_exit(void)
+{
+ drm_exit(&driver);
+}
-int xgi_kern_ctl_open(struct inode *, struct file *);
-int xgi_kern_ctl_close(struct inode *, struct file *);
-unsigned int xgi_kern_ctl_poll(struct file *, poll_table *);
+module_init(xgi_init);
+module_exit(xgi_exit);
-void xgi_kern_isr_bh(unsigned long);
-irqreturn_t xgi_kern_isr(int, void *, struct pt_regs *);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
-static void xgi_lock_init(struct xgi_info * info);
-#if defined(XGI_PM_SUPPORT_ACPI)
-int xgi_kern_acpi_standby(struct pci_dev *, u32);
-int xgi_kern_acpi_resume(struct pci_dev *);
-#endif
+void xgi_kern_isr_bh(struct drm_device *dev);
/*
* verify access to pci config space wasn't disabled behind our back
@@ -129,1361 +152,206 @@ int xgi_kern_acpi_resume(struct pci_dev *);
static inline void xgi_check_pci_config(struct xgi_info * info, int line)
{
- unsigned short cmd, flag = 0;
-
- // don't do this on the control device, only the actual devices
- if (info->flags & XGI_FLAG_CONTROL)
- return;
+ u16 cmd;
+ bool flag = 0;
- pci_read_config_word(info->dev, PCI_COMMAND, &cmd);
+ pci_read_config_word(info->dev->pdev, PCI_COMMAND, &cmd);
if (!(cmd & PCI_COMMAND_MASTER)) {
- XGI_INFO("restoring bus mastering! (%d)\n", line);
+ DRM_INFO("restoring bus mastering! (%d)\n", line);
cmd |= PCI_COMMAND_MASTER;
flag = 1;
}
if (!(cmd & PCI_COMMAND_MEMORY)) {
- XGI_INFO("restoring MEM access! (%d)\n", line);
+ DRM_INFO("restoring MEM access! (%d)\n", line);
cmd |= PCI_COMMAND_MEMORY;
flag = 1;
}
if (flag)
- pci_write_config_word(info->dev, PCI_COMMAND, cmd);
+ pci_write_config_word(info->dev->pdev, PCI_COMMAND, cmd);
}
-/*
- * struct pci_device_id {
- * unsigned int vendor, device; // Vendor and device ID or PCI_ANY_ID
- * unsigned int subvendor, subdevice; // Subsystem ID's or PCI_ANY_ID
- * unsigned int class, class_mask; // (class,subclass,prog-if) triplet
- * unsigned long driver_data; // Data private to the driver
- * };
- */
-static struct pci_device_id xgi_dev_table[] = {
- {
- .vendor = PCI_VENDOR_ID_XGI,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .class = (PCI_CLASS_DISPLAY_VGA << 8),
- .class_mask = ~0,
- },
- {}
-};
-
-/*
- * #define MODULE_DEVICE_TABLE(type,name) \
- * MODULE_GENERIC_TABLE(type##_device,name)
- */
-MODULE_DEVICE_TABLE(pci, xgi_dev_table);
-
-/*
- * struct pci_driver {
- * struct list_head node;
- * char *name;
- * const struct pci_device_id *id_table; // NULL if wants all devices
- * int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); // New device inserted
- * void (*remove)(struct pci_dev *dev); // Device removed (NULL if not a hot-plug capable driver)
- * int (*save_state)(struct pci_dev *dev, u32 state); // Save Device Context
- * int (*suspend)(struct pci_dev *dev, u32 state); // Device suspended
- * int (*resume)(struct pci_dev *dev); // Device woken up
- * int (*enable_wake)(struct pci_dev *dev, u32 state, int enable); // Enable wake event
- * };
- */
-static struct pci_driver xgi_pci_driver = {
- .name = "xgi",
- .id_table = xgi_dev_table,
- .probe = xgi_kern_probe,
-#if defined(XGI_SUPPORT_ACPI)
- .suspend = xgi_kern_acpi_standby,
- .resume = xgi_kern_acpi_resume,
-#endif
-};
-
-/*
- * find xgi devices and set initial state
- */
-int xgi_kern_probe(struct pci_dev *dev, const struct pci_device_id *id_table)
+int xgi_bootstrap(DRM_IOCTL_ARGS)
{
- struct xgi_info *info;
-
- if ((dev->vendor != PCI_VENDOR_ID_XGI)
- || (dev->class != (PCI_CLASS_DISPLAY_VGA << 8))) {
- return -1;
- }
-
- if (xgi_num_devices == XGI_MAX_DEVICES) {
- XGI_INFO("maximum device number (%d) reached!\n",
- xgi_num_devices);
- return -1;
- }
-
- /* enable io, mem, and bus-mastering in pci config space */
- if (pci_enable_device(dev) != 0) {
- XGI_INFO("pci_enable_device failed, aborting\n");
- return -1;
- }
-
- XGI_INFO("maximum device number (%d) reached \n", xgi_num_devices);
-
- pci_set_master(dev);
-
- info = &xgi_devices[xgi_num_devices];
- info->dev = dev;
+ DRM_DEVICE;
+ struct xgi_info *info = dev->dev_private;
+ struct xgi_bootstrap bs;
+ int err;
- xgi_lock_init(info);
- info->mmio.base = XGI_PCI_RESOURCE_START(dev, 1);
- info->mmio.size = XGI_PCI_RESOURCE_SIZE(dev, 1);
+ DRM_COPY_FROM_USER_IOCTL(bs, (struct xgi_bootstrap __user *) data,
+ sizeof(bs));
- /* check IO region */
- if (!request_mem_region(info->mmio.base, info->mmio.size, "xgi")) {
- XGI_ERROR("cannot reserve MMIO memory\n");
- goto error_disable_dev;
+ if (info->bootstrap_done) {
+ return 0;
}
- XGI_INFO("info->mmio.base: 0x%lx \n", info->mmio.base);
- XGI_INFO("info->mmio.size: 0x%lx \n", info->mmio.size);
-
- info->mmio.vbase = ioremap_nocache(info->mmio.base, info->mmio.size);
- if (!info->mmio.vbase) {
- release_mem_region(info->mmio.base, info->mmio.size);
- XGI_ERROR("info->mmio.vbase failed\n");
- goto error_disable_dev;
- }
xgi_enable_mmio(info);
- //xgi_enable_ge(info);
-
- XGI_INFO("info->mmio.vbase: 0x%p \n", info->mmio.vbase);
-
- info->fb.base = XGI_PCI_RESOURCE_START(dev, 0);
- info->fb.size = XGI_PCI_RESOURCE_SIZE(dev, 0);
-
- XGI_INFO("info->fb.base: 0x%lx \n", info->fb.base);
- XGI_INFO("info->fb.size: 0x%lx \n", info->fb.size);
-
- info->fb.size = bIn3cf(0x54) * 8 * 1024 * 1024;
- XGI_INFO("info->fb.size: 0x%lx \n", info->fb.size);
-
- /* check frame buffer region
- if (!request_mem_region(info->fb.base, info->fb.size, "xgi"))
- {
- release_mem_region(info->mmio.base, info->mmio.size);
- XGI_ERROR("cannot reserve frame buffer memory\n");
- goto error_disable_dev;
- }
-
- info->fb.vbase = ioremap_nocache(info->fb.base, info->fb.size);
-
- if (!info->fb.vbase)
- {
- release_mem_region(info->mmio.base, info->mmio.size);
- release_mem_region(info->fb.base, info->fb.size);
- XGI_ERROR("info->fb.vbase failed\n");
- goto error_disable_dev;
- }
- */
- info->fb.vbase = NULL;
- XGI_INFO("info->fb.vbase: 0x%p \n", info->fb.vbase);
-
-
- /* check common error condition */
- if (info->dev->irq == 0) {
- XGI_ERROR("Can't find an IRQ for your XGI card! \n");
- goto error_zero_dev;
- }
- XGI_INFO("info->irq: %lx \n", info->dev->irq);
-
- //xgi_enable_dvi_interrupt(info);
-
- /* sanity check the IO apertures */
- if ((info->mmio.base == 0) || (info->mmio.size == 0)
- || (info->fb.base == 0) || (info->fb.size == 0)) {
- XGI_ERROR("The IO regions for your XGI card are invalid.\n");
-
- if ((info->mmio.base == 0) || (info->mmio.size == 0)) {
- XGI_ERROR("mmio appears to be wrong: 0x%lx 0x%lx\n",
- info->mmio.base, info->mmio.size);
- }
-
- if ((info->fb.base == 0) || (info->fb.size == 0)) {
- XGI_ERROR
- ("frame buffer appears to be wrong: 0x%lx 0x%lx\n",
- info->fb.base, info->fb.size);
- }
-
- goto error_zero_dev;
- }
- //xgi_num_devices++;
-
- return 0;
-
- error_zero_dev:
- release_mem_region(info->fb.base, info->fb.size);
- release_mem_region(info->mmio.base, info->mmio.size);
-
- error_disable_dev:
- pci_disable_device(dev);
- return -1;
+ info->pcie.size = bs.gart_size * (1024 * 1024);
-}
-
-/*
- * vma operations...
- * this is only called when the vmas are duplicated. this
- * appears to only happen when the process is cloned to create
- * a new process, and not when the process is threaded.
- *
- * increment the usage count for the physical pages, so when
- * this clone unmaps the mappings, the pages are not
- * deallocated under the original process.
- */
-struct vm_operations_struct xgi_vm_ops = {
- .open = xgi_kern_vma_open,
- .close = xgi_kern_vma_release,
- .nopage = xgi_kern_vma_nopage,
-};
-
-void xgi_kern_vma_open(struct vm_area_struct *vma)
-{
- XGI_INFO("VM: vma_open for 0x%lx - 0x%lx, offset 0x%lx\n",
- vma->vm_start, vma->vm_end, XGI_VMA_OFFSET(vma));
-
- if (XGI_VMA_PRIVATE(vma)) {
- struct xgi_pcie_block *block =
- (struct xgi_pcie_block *) XGI_VMA_PRIVATE(vma);
- XGI_ATOMIC_INC(block->use_count);
- }
-}
-
-void xgi_kern_vma_release(struct vm_area_struct *vma)
-{
- XGI_INFO("VM: vma_release for 0x%lx - 0x%lx, offset 0x%lx\n",
- vma->vm_start, vma->vm_end, XGI_VMA_OFFSET(vma));
-
- if (XGI_VMA_PRIVATE(vma)) {
- struct xgi_pcie_block *block =
- (struct xgi_pcie_block *) XGI_VMA_PRIVATE(vma);
- XGI_ATOMIC_DEC(block->use_count);
-
- /*
- * if use_count is down to 0, the kernel virtual mapping was freed
- * but the underlying physical pages were not, we need to clear the
- * bit and free the physical pages.
- */
- if (XGI_ATOMIC_READ(block->use_count) == 0) {
- // Need TO Finish
- XGI_VMA_PRIVATE(vma) = NULL;
- }
- }
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 1))
-struct page *xgi_kern_vma_nopage(struct vm_area_struct *vma,
- unsigned long address, int *type)
-{
- struct xgi_pcie_block *block = (struct xgi_pcie_block *) XGI_VMA_PRIVATE(vma);
- struct page *page = NOPAGE_SIGBUS;
- unsigned long offset = 0;
- unsigned long page_addr = 0;
-/*
- XGI_INFO("VM: mmap([0x%lx-0x%lx] off=0x%lx) address: 0x%lx \n",
- vma->vm_start,
- vma->vm_end,
- XGI_VMA_OFFSET(vma),
- address);
-*/
- offset = (address - vma->vm_start) + XGI_VMA_OFFSET(vma);
-
- offset = offset - block->bus_addr;
-
- offset >>= PAGE_SHIFT;
-
- page_addr = block->page_table[offset].virt_addr;
-
- if (xgi_temp) {
- XGI_INFO("block->bus_addr: 0x%lx block->hw_addr: 0x%lx"
- "block->page_count: 0x%lx block->page_order: 0x%lx"
- "block->page_table[0x%lx].virt_addr: 0x%lx\n",
- block->bus_addr, block->hw_addr,
- block->page_count, block->page_order,
- offset, block->page_table[offset].virt_addr);
- xgi_temp = 0;
- }
-
- if (!page_addr)
- goto out; /* hole or end-of-file */
- page = virt_to_page(page_addr);
-
- /* got it, now increment the count */
- get_page(page);
- out:
- return page;
-
-}
-#else
-struct page *xgi_kern_vma_nopage(struct vm_area_struct *vma,
- unsigned long address, int write_access)
-{
- struct xgi_pcie_block *block = (struct xgi_pcie_block *) XGI_VMA_PRIVATE(vma);
- struct page *page = NOPAGE_SIGBUS;
- unsigned long offset = 0;
- unsigned long page_addr = 0;
-/*
- XGI_INFO("VM: mmap([0x%lx-0x%lx] off=0x%lx) address: 0x%lx \n",
- vma->vm_start,
- vma->vm_end,
- XGI_VMA_OFFSET(vma),
- address);
-*/
- offset = (address - vma->vm_start) + XGI_VMA_OFFSET(vma);
-
- offset = offset - block->bus_addr;
-
- offset >>= PAGE_SHIFT;
-
- page_addr = block->page_table[offset].virt_addr;
-
- if (xgi_temp) {
- XGI_INFO("block->bus_addr: 0x%lx block->hw_addr: 0x%lx"
- "block->page_count: 0x%lx block->page_order: 0x%lx"
- "block->page_table[0x%lx].virt_addr: 0x%lx\n",
- block->bus_addr, block->hw_addr,
- block->page_count, block->page_order,
- offset, block->page_table[offset].virt_addr);
- xgi_temp = 0;
- }
-
- if (!page_addr)
- goto out; /* hole or end-of-file */
- page = virt_to_page(page_addr);
-
- /* got it, now increment the count */
- get_page(page);
- out:
- return page;
-}
-#endif
-
-#if 0
-static struct file_operations xgi_fops = {
- /* owner: THIS_MODULE, */
- poll:xgi_kern_poll,
- ioctl:xgi_kern_ioctl,
- mmap:xgi_kern_mmap,
- open:xgi_kern_open,
- release:xgi_kern_release,
-};
-#endif
-
-static struct file_operations xgi_fops = {
- .owner = THIS_MODULE,
- .poll = xgi_kern_poll,
- .ioctl = xgi_kern_ioctl,
- .mmap = xgi_kern_mmap,
- .open = xgi_kern_open,
- .release = xgi_kern_release,
-};
-
-static struct xgi_file_private *xgi_alloc_file_private(void)
-{
- struct xgi_file_private *fp;
-
- XGI_KMALLOC(fp, sizeof(struct xgi_file_private));
- if (!fp)
- return NULL;
-
- memset(fp, 0, sizeof(struct xgi_file_private));
-
- /* initialize this file's event queue */
- init_waitqueue_head(&fp->wait_queue);
-
- xgi_init_lock(fp->fp_lock);
-
- return fp;
-}
-
-static void xgi_free_file_private(struct xgi_file_private * fp)
-{
- if (fp == NULL)
- return;
-
- XGI_KFREE(fp, sizeof(struct xgi_file_private));
-}
-
-int xgi_kern_open(struct inode *inode, struct file *filp)
-{
- struct xgi_info *info = NULL;
- int dev_num;
- int result = 0, status;
-
- /*
- * the type and num values are only valid if we are not using devfs.
- * However, since we use them to retrieve the device pointer, we
- * don't need them with devfs as filp->private_data is already
- * initialized
- */
- filp->private_data = xgi_alloc_file_private();
- if (filp->private_data == NULL)
- return -ENOMEM;
-
- XGI_INFO("filp->private_data %p\n", filp->private_data);
- /*
- * for control device, just jump to its open routine
- * after setting up the private data
- */
- if (XGI_IS_CONTROL_DEVICE(inode))
- return xgi_kern_ctl_open(inode, filp);
-
- /* what device are we talking about? */
- dev_num = XGI_DEVICE_NUMBER(inode);
- if (dev_num >= XGI_MAX_DEVICES) {
- xgi_free_file_private(filp->private_data);
- filp->private_data = NULL;
- return -ENODEV;
- }
-
- info = &xgi_devices[dev_num];
-
- XGI_INFO("Jong-xgi_kern_open on device %d\n", dev_num);
-
- xgi_down(info->info_sem);
- XGI_CHECK_PCI_CONFIG(info);
-
- XGI_INFO_FROM_FP(filp) = info;
-
- /*
- * map the memory and allocate isr on first open
- */
-
- if (!(info->flags & XGI_FLAG_OPEN)) {
- XGI_INFO("info->flags & XGI_FLAG_OPEN \n");
-
- if (info->dev->device == 0) {
- XGI_INFO("open of nonexistent device %d\n", dev_num);
- result = -ENXIO;
- goto failed;
- }
-
- /* initialize struct irqaction */
- status = request_irq(info->dev->irq, xgi_kern_isr,
- SA_INTERRUPT | SA_SHIRQ, "xgi",
- (void *)info);
- if (status != 0) {
- if (info->dev->irq && (status == -EBUSY)) {
- XGI_ERROR
- ("Tried to get irq %d, but another driver",
- (unsigned int)info->dev->irq);
- XGI_ERROR("has it and is not sharing it.\n");
- }
- XGI_ERROR("isr request failed 0x%x\n", status);
- result = -EIO;
- goto failed;
- }
-
- /*
- * #define DECLARE_TASKLET(name, func, data) \
- * struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
- */
- info->tasklet.func = xgi_kern_isr_bh;
- info->tasklet.data = (unsigned long)info;
- tasklet_enable(&info->tasklet);
-
- /* Alloc 1M bytes for cmdbuffer which is flush2D batch array */
- xgi_cmdlist_initialize(info, 0x100000);
-
- info->flags |= XGI_FLAG_OPEN;
- }
-
- XGI_ATOMIC_INC(info->use_count);
-
- failed:
- xgi_up(info->info_sem);
-
- if ((result) && filp->private_data) {
- xgi_free_file_private(filp->private_data);
- filp->private_data = NULL;
- }
-
- return result;
-}
-
-int xgi_kern_release(struct inode *inode, struct file *filp)
-{
- struct xgi_info *info = XGI_INFO_FROM_FP(filp);
-
- XGI_CHECK_PCI_CONFIG(info);
-
- /*
- * for control device, just jump to its open routine
- * after setting up the private data
- */
- if (XGI_IS_CONTROL_DEVICE(inode))
- return xgi_kern_ctl_close(inode, filp);
-
- XGI_INFO("Jong-xgi_kern_release on device %d\n",
- XGI_DEVICE_NUMBER(inode));
-
- xgi_down(info->info_sem);
- if (XGI_ATOMIC_DEC_AND_TEST(info->use_count)) {
-
- /*
- * The usage count for this device has dropped to zero, it can be shut
- * down safely; disable its interrupts.
- */
-
- /*
- * Disable this device's tasklet to make sure that no bottom half will
- * run with undefined device state.
- */
- tasklet_disable(&info->tasklet);
-
- /*
- * Free the IRQ, which may block until all pending interrupt processing
- * has completed.
- */
- free_irq(info->dev->irq, (void *)info);
-
- xgi_cmdlist_cleanup(info);
-
- /* leave INIT flag alone so we don't reinit every time */
- info->flags &= ~XGI_FLAG_OPEN;
- }
-
- xgi_up(info->info_sem);
-
- if (FILE_PRIVATE(filp)) {
- xgi_free_file_private(FILE_PRIVATE(filp));
- FILE_PRIVATE(filp) = NULL;
- }
-
- return 0;
-}
-
-int xgi_kern_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- //struct inode *inode = INODE_FROM_FP(filp);
- struct xgi_info *info = XGI_INFO_FROM_FP(filp);
- struct xgi_pcie_block *block;
- int pages = 0;
- unsigned long prot;
-
- XGI_INFO("Jong-VM: mmap([0x%lx-0x%lx] off=0x%lx)\n",
- vma->vm_start, vma->vm_end, XGI_VMA_OFFSET(vma));
-
- XGI_CHECK_PCI_CONFIG(info);
-
- if (XGI_MASK_OFFSET(vma->vm_start)
- || XGI_MASK_OFFSET(vma->vm_end)) {
- XGI_ERROR("VM: bad mmap range: %lx - %lx\n",
- vma->vm_start, vma->vm_end);
- return -ENXIO;
- }
-
- pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-
- vma->vm_ops = &xgi_vm_ops;
-
- /* XGI IO(reg) space */
- if (IS_IO_OFFSET
- (info, XGI_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) {
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- if (XGI_REMAP_PAGE_RANGE(vma->vm_start,
- XGI_VMA_OFFSET(vma),
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- /* mark it as IO so that we don't dump it on core dump */
- vma->vm_flags |= VM_IO;
- XGI_INFO("VM: mmap io space \n");
- }
- /* XGI fb space */
- /* Jong 06/14/2006; moved behind PCIE or modify IS_FB_OFFSET */
- else if (IS_FB_OFFSET
- (info, XGI_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) {
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- if (XGI_REMAP_PAGE_RANGE(vma->vm_start,
- XGI_VMA_OFFSET(vma),
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- // mark it as IO so that we don't dump it on core dump
- vma->vm_flags |= VM_IO;
- XGI_INFO("VM: mmap fb space \n");
- }
- /* PCIE allocator */
- /* XGI_VMA_OFFSET(vma) is offset based on pcie.base (HW address space) */
- else if (IS_PCIE_OFFSET
- (info, XGI_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) {
- xgi_down(info->pcie_sem);
-
- block = xgi_find_pcie_block(info, XGI_VMA_OFFSET(vma));
-
- if (block == NULL) {
- XGI_ERROR("couldn't find pre-allocated PCIE memory!\n");
- xgi_up(info->pcie_sem);
- return -EAGAIN;
- }
-
- if (block->page_count != pages) {
- XGI_ERROR
- ("pre-allocated PCIE memory has wrong number of pages!\n");
- xgi_up(info->pcie_sem);
- return -EAGAIN;
- }
-
- vma->vm_private_data = block;
- XGI_ATOMIC_INC(block->use_count);
- xgi_up(info->pcie_sem);
-
- /*
- * prevent the swapper from swapping it out
- * mark the memory i/o so the buffers aren't
- * dumped on core dumps */
- vma->vm_flags |= (VM_LOCKED | VM_IO);
-
- /* un-cached */
- prot = pgprot_val(vma->vm_page_prot);
- /*
- if (boot_cpu_data.x86 > 3)
- prot |= _PAGE_PCD | _PAGE_PWT;
- */
- vma->vm_page_prot = __pgprot(prot);
-
- XGI_INFO("VM: mmap pcie space \n");
- }
-#if 0
- else if (IS_FB_OFFSET
- (info, XGI_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) {
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- if (XGI_REMAP_PAGE_RANGE(vma->vm_start,
- XGI_VMA_OFFSET(vma),
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- // mark it as IO so that we don't dump it on core dump
- vma->vm_flags |= VM_IO;
- XGI_INFO("VM: mmap fb space \n");
- }
-#endif
- else {
- vma->vm_flags |= (VM_IO | VM_LOCKED);
- XGI_ERROR("VM: mmap wrong range \n");
- }
-
- vma->vm_file = filp;
-
- return 0;
-}
-
-unsigned int xgi_kern_poll(struct file *filp, struct poll_table_struct *wait)
-{
- struct xgi_file_private *fp;
- struct xgi_info *info;
- unsigned int mask = 0;
- unsigned long eflags;
-
- info = XGI_INFO_FROM_FP(filp);
-
- if (info->device_number == XGI_CONTROL_DEVICE_NUMBER)
- return xgi_kern_ctl_poll(filp, wait);
-
- fp = XGI_GET_FP(filp);
-
- if (!(filp->f_flags & O_NONBLOCK)) {
- /* add us to the list */
- poll_wait(filp, &fp->wait_queue, wait);
- }
-
- xgi_lock_irqsave(fp->fp_lock, eflags);
-
- /* wake the user on any event */
- if (fp->num_events) {
- XGI_INFO("Hey, an event occured!\n");
- /*
- * trigger the client, when they grab the event,
- * we'll decrement the event count
- */
- mask |= (POLLPRI | POLLIN);
- }
- xgi_unlock_irqsave(fp->fp_lock, eflags);
-
- return mask;
-}
-
-int xgi_kern_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- struct xgi_info *info;
- struct xgi_mem_alloc *alloc = NULL;
-
- int status = 0;
- void *arg_copy;
- int arg_size;
- int err = 0;
-
- info = XGI_INFO_FROM_FP(filp);
-
- XGI_INFO("Jong-ioctl(0x%x, 0x%x, 0x%lx, 0x%x)\n", _IOC_TYPE(cmd),
- _IOC_NR(cmd), arg, _IOC_SIZE(cmd));
- /*
- * extract the type and number bitfields, and don't decode
- * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
- */
- if (_IOC_TYPE(cmd) != XGI_IOCTL_MAGIC)
- return -ENOTTY;
- if (_IOC_NR(cmd) > XGI_IOCTL_MAXNR)
- return -ENOTTY;
-
- /*
- * the direction is a bitmask, and VERIFY_WRITE catches R/W
- * transfers. `Type' is user-oriented, while
- * access_ok is kernel-oriented, so the concept of "read" and
- * "write" is reversed
- */
- if (_IOC_DIR(cmd) & _IOC_READ) {
- err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
- } else if (_IOC_DIR(cmd) & _IOC_WRITE) {
- err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
- }
- if (err)
- return -EFAULT;
-
- XGI_CHECK_PCI_CONFIG(info);
-
- arg_size = _IOC_SIZE(cmd);
- XGI_KMALLOC(arg_copy, arg_size);
- if (arg_copy == NULL) {
- XGI_ERROR("failed to allocate ioctl memory\n");
- return -ENOMEM;
- }
-
- /* Jong 05/25/2006 */
- /* copy_from_user(arg_copy, (void *)arg, arg_size); */
- if (copy_from_user(arg_copy, (void *)arg, arg_size)) {
- XGI_ERROR("failed to copyin ioctl data\n");
- XGI_INFO("Jong-copy_from_user-fail! \n");
- } else
- XGI_INFO("Jong-copy_from_user-OK! \n");
-
- alloc = (struct xgi_mem_alloc *) arg_copy;
- XGI_INFO("Jong-succeeded in copy_from_user 0x%lx, 0x%x bytes.\n", arg,
- arg_size);
-
- switch (_IOC_NR(cmd)) {
- case XGI_ESC_POST_VBIOS:
- XGI_INFO("Jong-xgi_ioctl_post_vbios \n");
- break;
- case XGI_ESC_FB_ALLOC:
- XGI_INFO("Jong-xgi_ioctl_fb_alloc \n");
- xgi_fb_alloc(info, alloc, 0);
- break;
- case XGI_ESC_FB_FREE:
- XGI_INFO("Jong-xgi_ioctl_fb_free \n");
- xgi_fb_free(info, *(unsigned long *)arg_copy);
- break;
- case XGI_ESC_PCIE_ALLOC:
- XGI_INFO("Jong-xgi_ioctl_pcie_alloc \n");
- xgi_pcie_alloc(info, alloc, 0);
- break;
- case XGI_ESC_PCIE_FREE:
- XGI_INFO("Jong-xgi_ioctl_pcie_free: bus_addr = 0x%lx \n",
- *((unsigned long *)arg_copy));
- xgi_pcie_free(info, *((unsigned long *)arg_copy));
- break;
- case XGI_ESC_GE_RESET:
- XGI_INFO("Jong-xgi_ioctl_ge_reset \n");
- xgi_ge_reset(info);
- break;
- case XGI_ESC_DUMP_REGISTER:
- XGI_INFO("Jong-xgi_ioctl_dump_register \n");
- xgi_dump_register(info);
- break;
- case XGI_ESC_DEBUG_INFO:
- XGI_INFO("Jong-xgi_ioctl_restore_registers \n");
- xgi_restore_registers(info);
- break;
- case XGI_ESC_SUBMIT_CMDLIST:
- XGI_INFO("Jong-xgi_ioctl_submit_cmdlist \n");
- xgi_submit_cmdlist(info, (struct xgi_cmd_info *) arg_copy);
- break;
- case XGI_ESC_TEST_RWINKERNEL:
- XGI_INFO("Jong-xgi_test_rwinkernel \n");
- xgi_test_rwinkernel(info, *(unsigned long *)arg_copy);
- break;
- case XGI_ESC_STATE_CHANGE:
- XGI_INFO("Jong-xgi_state_change \n");
- xgi_state_change(info, (struct xgi_state_info *) arg_copy);
- break;
- default:
- XGI_INFO("Jong-xgi_ioctl_default \n");
- status = -EINVAL;
- break;
- }
-
- if (copy_to_user((void *)arg, arg_copy, arg_size)) {
- XGI_ERROR("failed to copyout ioctl data\n");
- XGI_INFO("Jong-copy_to_user-fail! \n");
- } else
- XGI_INFO("Jong-copy_to_user-OK! \n");
-
- XGI_KFREE(arg_copy, arg_size);
- return status;
-}
-
-/*
- * xgi control driver operations defined here
- */
-int xgi_kern_ctl_open(struct inode *inode, struct file *filp)
-{
- struct xgi_info *info = &xgi_ctl_device;
-
- int rc = 0;
-
- XGI_INFO("Jong-xgi_kern_ctl_open\n");
-
- xgi_down(info->info_sem);
- info->device_number = XGI_CONTROL_DEVICE_NUMBER;
-
- /* save the xgi info in file->private_data */
- filp->private_data = info;
-
- if (XGI_ATOMIC_READ(info->use_count) == 0) {
- init_waitqueue_head(&xgi_ctl_waitqueue);
- }
-
- info->flags |= XGI_FLAG_OPEN + XGI_FLAG_CONTROL;
-
- XGI_ATOMIC_INC(info->use_count);
- xgi_up(info->info_sem);
-
- return rc;
-}
-
-int xgi_kern_ctl_close(struct inode *inode, struct file *filp)
-{
- struct xgi_info *info = XGI_INFO_FROM_FP(filp);
-
- XGI_INFO("Jong-xgi_kern_ctl_close\n");
-
- xgi_down(info->info_sem);
- if (XGI_ATOMIC_DEC_AND_TEST(info->use_count)) {
- info->flags = 0;
- }
- xgi_up(info->info_sem);
-
- if (FILE_PRIVATE(filp)) {
- xgi_free_file_private(FILE_PRIVATE(filp));
- FILE_PRIVATE(filp) = NULL;
- }
-
- return 0;
-}
-
-unsigned int xgi_kern_ctl_poll(struct file *filp, poll_table * wait)
-{
- //struct xgi_info *info = XGI_INFO_FROM_FP(filp);;
- unsigned int ret = 0;
-
- if (!(filp->f_flags & O_NONBLOCK)) {
- poll_wait(filp, &xgi_ctl_waitqueue, wait);
- }
-
- return ret;
-}
-
-/*
- * xgi proc system
- */
-static u8 xgi_find_pcie_capability(struct pci_dev *dev)
-{
- u16 status;
- u8 cap_ptr, cap_id;
-
- pci_read_config_word(dev, PCI_STATUS, &status);
- status &= PCI_STATUS_CAP_LIST;
- if (!status)
- return 0;
-
- switch (dev->hdr_type) {
- case PCI_HEADER_TYPE_NORMAL:
- case PCI_HEADER_TYPE_BRIDGE:
- pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr);
- break;
- default:
- return 0;
+ /* Init the resource manager */
+ err = xgi_pcie_heap_init(info);
+ if (err) {
+ DRM_ERROR("xgi_pcie_heap_init() failed\n");
+ return err;
}
- do {
- cap_ptr &= 0xFC;
- pci_read_config_byte(dev, cap_ptr + PCI_CAP_LIST_ID, &cap_id);
- pci_read_config_byte(dev, cap_ptr + PCI_CAP_LIST_NEXT,
- &cap_ptr);
- } while (cap_ptr && cap_id != 0xFF);
-
- return 0;
-}
-
-int xgi_kern_read_card_info(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- struct pci_dev *dev;
- char *type;
- int len = 0;
-
- struct xgi_info *info;
- info = (struct xgi_info *) data;
-
- dev = info->dev;
- if (!dev)
- return 0;
-
- type = xgi_find_pcie_capability(dev) ? "PCIE" : "PCI";
- len += sprintf(page + len, "Card Type: \t %s\n", type);
-
- XGI_PCI_DEV_PUT(dev);
- return len;
-}
-
-int xgi_kern_read_version(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len = 0;
-
- len += sprintf(page + len, "XGI version: %s\n", "1.0");
- len += sprintf(page + len, "GCC version: %s\n", "3.0");
+ /* Alloc 1M bytes for cmdbuffer which is flush2D batch array */
+ xgi_cmdlist_initialize(info, 0x100000);
- return len;
-}
-
-int xgi_kern_read_pcie_info(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
+ info->bootstrap_done = 1;
return 0;
}
-int xgi_kern_read_status(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-static void xgi_proc_create(void)
+void xgi_driver_preclose(struct drm_device * dev, DRMFILE filp)
{
-#ifdef CONFIG_PROC_FS
-
- struct pci_dev *dev;
- int i = 0;
- char name[6];
-
- struct proc_dir_entry *entry;
- struct proc_dir_entry *proc_xgi_pcie, *proc_xgi_cards;
-
- struct xgi_info *info;
- struct xgi_info *xgi_max_devices;
-
- /* world readable directory */
- int flags = S_IFDIR | S_IRUGO | S_IXUGO;
-
- proc_xgi = create_proc_entry("xgi", flags, proc_root_driver);
- if (!proc_xgi)
- goto failed;
-
- proc_xgi_cards = create_proc_entry("cards", flags, proc_xgi);
- if (!proc_xgi_cards)
- goto failed;
-
- proc_xgi_pcie = create_proc_entry("pcie", flags, proc_xgi);
- if (!proc_xgi_pcie)
- goto failed;
-
- /*
- * Set the module owner to ensure that the reference
- * count reflects accesses to the proc files.
- */
- proc_xgi->owner = THIS_MODULE;
- proc_xgi_cards->owner = THIS_MODULE;
- proc_xgi_pcie->owner = THIS_MODULE;
-
- xgi_max_devices = xgi_devices + XGI_MAX_DEVICES;
- for (info = xgi_devices; info < xgi_max_devices; info++) {
- /* world readable file */
- flags = S_IFREG | S_IRUGO;
-
- dev = info->dev;
- if (!dev)
- break;
-
- sprintf(name, "%d", i++);
- entry = create_proc_entry(name, flags, proc_xgi_cards);
- if (!entry) {
- XGI_PCI_DEV_PUT(dev);
- goto failed;
- }
-
- entry->data = info;
- entry->read_proc = xgi_kern_read_card_info;
- entry->owner = THIS_MODULE;
-
- if (xgi_find_pcie_capability(dev)) {
- entry =
- create_proc_entry("status", flags, proc_xgi_pcie);
- if (!entry) {
- XGI_PCI_DEV_PUT(dev);
- goto failed;
- }
-
- entry->data = info;
- entry->read_proc = xgi_kern_read_status;
- entry->owner = THIS_MODULE;
-
- entry = create_proc_entry("card", flags, proc_xgi_pcie);
- if (!entry) {
- XGI_PCI_DEV_PUT(dev);
- goto failed;
- }
-
- entry->data = info;
- entry->read_proc = xgi_kern_read_pcie_info;
- entry->owner = THIS_MODULE;
- }
-
- XGI_PCI_DEV_PUT(dev);
- }
-
- entry = create_proc_entry("version", flags, proc_xgi);
- if (!entry)
- goto failed;
-
- entry->read_proc = xgi_kern_read_version;
- entry->owner = THIS_MODULE;
-
- entry = create_proc_entry("host-bridge", flags, proc_xgi_pcie);
- if (!entry)
- goto failed;
+ struct xgi_info * info = dev->dev_private;
- entry->data = NULL;
- entry->read_proc = xgi_kern_read_pcie_info;
- entry->owner = THIS_MODULE;
-
- return;
-
- failed:
- XGI_ERROR("failed to create /proc entries!\n");
- xgi_proc_remove_all(proc_xgi);
-#endif
+ xgi_pcie_free_all(info, filp);
+ xgi_fb_free_all(info, filp);
}
-#ifdef CONFIG_PROC_FS
-static void xgi_proc_remove_all(struct proc_dir_entry *entry)
-{
- while (entry) {
- struct proc_dir_entry *next = entry->next;
- if (entry->subdir)
- xgi_proc_remove_all(entry->subdir);
- remove_proc_entry(entry->name, entry->parent);
- if (entry == proc_xgi)
- break;
- entry = next;
- }
-}
-#endif
-
-static void xgi_proc_remove(void)
-{
-#ifdef CONFIG_PROC_FS
- xgi_proc_remove_all(proc_xgi);
-#endif
-}
/*
* driver receives an interrupt if someone waiting, then hand it off.
*/
-irqreturn_t xgi_kern_isr(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS)
{
- struct xgi_info *info = (struct xgi_info *) dev_id;
+ struct drm_device *dev = (struct drm_device *) arg;
+// struct xgi_info *info = dev->dev_private;
u32 need_to_run_bottom_half = 0;
- //XGI_INFO("xgi_kern_isr \n");
+ //DRM_INFO("xgi_kern_isr \n");
//XGI_CHECK_PCI_CONFIG(info);
//xgi_dvi_irq_handler(info);
if (need_to_run_bottom_half) {
- tasklet_schedule(&info->tasklet);
+ drm_locked_tasklet(dev, xgi_kern_isr_bh);
}
return IRQ_HANDLED;
}
-void xgi_kern_isr_bh(unsigned long data)
+void xgi_kern_isr_bh(struct drm_device *dev)
{
- struct xgi_info *info = (struct xgi_info *) data;
+ struct xgi_info *info = dev->dev_private;
- XGI_INFO("xgi_kern_isr_bh \n");
+ DRM_INFO("xgi_kern_isr_bh \n");
//xgi_dvi_irq_handler(info);
XGI_CHECK_PCI_CONFIG(info);
}
-static void xgi_lock_init(struct xgi_info * info)
+int xgi_driver_load(struct drm_device *dev, unsigned long flags)
{
- if (info == NULL)
- return;
-
- spin_lock_init(&info->info_lock);
-
- sema_init(&info->info_sem, 1);
- sema_init(&info->fb_sem, 1);
- sema_init(&info->pcie_sem, 1);
-
- XGI_ATOMIC_SET(info->use_count, 0);
-}
+ struct xgi_info *info;
+ int err;
-static void xgi_dev_init(struct xgi_info * info)
-{
- struct pci_dev *pdev = NULL;
- struct xgi_dev *dev;
- int found = 0;
- u16 pci_cmd;
- XGI_INFO("Enter xgi_dev_init \n");
+ info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER);
+ if (!info)
+ return DRM_ERR(ENOMEM);
- //XGI_PCI_FOR_EACH_DEV(pdev)
- {
- for (dev = xgidev_list; dev->vendor; dev++) {
- if ((dev->vendor == pdev->vendor)
- && (dev->device == pdev->device)) {
- u8 rev_id;
+ (void) memset(info, 0, sizeof(*info));
+ dev->dev_private = info;
+ info->dev = dev;
- XGI_INFO("dev->vendor = pdev->vendor= %x \n",
- dev->vendor);
- XGI_INFO("dev->device = pdev->device= %x \n",
- dev->device);
+ sema_init(&info->fb_sem, 1);
+ sema_init(&info->pcie_sem, 1);
- xgi_devices[found].dev = pdev;
+ info->mmio.base = drm_get_resource_start(dev, 1);
+ info->mmio.size = drm_get_resource_len(dev, 1);
- pci_read_config_byte(pdev, PCI_REVISION_ID,
- rev_id);
+ DRM_INFO("mmio base: 0x%lx, size: 0x%x\n",
+ (unsigned long) info->mmio.base, info->mmio.size);
- XGI_INFO("PCI_REVISION_ID= %x \n", rev_id);
- pci_read_config_word(pdev, PCI_COMMAND,
- &pci_cmd);
+ 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);
+ }
- XGI_INFO("PCI_COMMAND = %x \n", pci_cmd);
- break;
- }
- }
+ err = drm_addmap(dev, info->mmio.base, info->mmio.size,
+ _DRM_REGISTERS, _DRM_KERNEL | _DRM_READ_ONLY,
+ &info->mmio_map);
+ if (err) {
+ DRM_ERROR("Unable to map MMIO region: %d\n", err);
+ return err;
}
-}
-/*
- * Export to Linux Kernel
- */
+ xgi_enable_mmio(info);
+ //xgi_enable_ge(info);
-static int __init xgi_init_module(void)
-{
- struct xgi_info *info = &xgi_devices[xgi_num_devices];
- int i, result;
+ info->fb.base = drm_get_resource_start(dev, 0);
+ info->fb.size = drm_get_resource_len(dev, 0);
- XGI_INFO("Jong-xgi kernel driver %s initializing\n", XGI_DRV_VERSION);
- //SET_MODULE_OWNER(&xgi_fops);
+ DRM_INFO("fb base: 0x%lx, size: 0x%x\n",
+ (unsigned long) info->fb.base, info->fb.size);
- memset(xgi_devices, 0, sizeof(xgi_devices));
+ info->fb.size = IN3CFB(info->mmio_map, 0x54) * 8 * 1024 * 1024;
- if (pci_register_driver(&xgi_pci_driver) < 0) {
- pci_unregister_driver(&xgi_pci_driver);
- XGI_ERROR("no XGI graphics adapter found\n");
- return -ENODEV;
- }
+ DRM_INFO("fb base: 0x%lx, size: 0x%x (probed)\n",
+ (unsigned long) info->fb.base, info->fb.size);
- XGI_INFO("Jong-xgi_devices[%d].fb.base.: 0x%lx \n", xgi_num_devices,
- xgi_devices[xgi_num_devices].fb.base);
- XGI_INFO("Jong-xgi_devices[%d].fb.size.: 0x%lx \n", xgi_num_devices,
- xgi_devices[xgi_num_devices].fb.size);
-/* Jong 07/27/2006; test for ubuntu */
-/*
-#ifdef CONFIG_DEVFS_FS
-
- XGI_INFO("Jong-Use devfs \n");
- do
- {
- xgi_devfs_handles[0] = XGI_DEVFS_REGISTER("xgi", 0);
- if (xgi_devfs_handles[0] == NULL)
- {
- result = -ENOMEM;
- XGI_ERROR("devfs register failed\n");
- goto failed;
- }
- } while(0);
- #else *//* no devfs, do it the "classic" way */
-
- XGI_INFO("Jong-Use non-devfs \n");
- /*
- * Register your major, and accept a dynamic number. This is the
- * first thing to do, in order to avoid releasing other module's
- * fops in scull_cleanup_module()
- */
- result = XGI_REGISTER_CHRDEV(xgi_major, "xgi", &xgi_fops);
- if (result < 0) {
- XGI_ERROR("register chrdev failed\n");
- pci_unregister_driver(&xgi_pci_driver);
- return result;
+ if ((info->fb.base == 0) || (info->fb.size == 0)) {
+ DRM_ERROR("frame buffer appears to be wrong: 0x%lx 0x%x\n",
+ (unsigned long) info->fb.base, info->fb.size);
+ return DRM_ERR(EINVAL);
}
- if (xgi_major == 0)
- xgi_major = result; /* dynamic */
- /* #endif *//* CONFIG_DEVFS_FS */
- XGI_INFO("Jong-major number %d\n", xgi_major);
- /* instantiate tasklets */
- for (i = 0; i < XGI_MAX_DEVICES; i++) {
- /*
- * We keep one tasklet per card to avoid latency issues with more
- * than one device; no two instances of a single tasklet are ever
- * executed concurrently.
- */
- XGI_ATOMIC_SET(xgi_devices[i].tasklet.count, 1);
+ 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);
}
- /* init the xgi control device */
- {
- struct xgi_info *info_ctl = &xgi_ctl_device;
- xgi_lock_init(info_ctl);
- }
/* Init the resource manager */
- INIT_LIST_HEAD(&xgi_mempid_list);
- if (!xgi_fb_heap_init(info)) {
- XGI_ERROR("xgi_fb_heap_init() failed\n");
- result = -EIO;
- goto failed;
+ err = xgi_fb_heap_init(info);
+ if (err) {
+ DRM_ERROR("xgi_fb_heap_init() failed\n");
+ return err;
}
- /* Init the resource manager */
- if (!xgi_pcie_heap_init(info)) {
- XGI_ERROR("xgi_pcie_heap_init() failed\n");
- result = -EIO;
- goto failed;
- }
-
- /* create /proc/driver/xgi */
- xgi_proc_create();
-
-#if defined(DEBUG)
- inter_module_register("xgi_devices", THIS_MODULE, xgi_devices);
-#endif
-
return 0;
-
- failed:
-#ifdef CONFIG_DEVFS_FS
- XGI_DEVFS_REMOVE_CONTROL();
- XGI_DEVFS_REMOVE_DEVICE(xgi_num_devices);
-#endif
-
- if (XGI_UNREGISTER_CHRDEV(xgi_major, "xgi") < 0)
- XGI_ERROR("unregister xgi chrdev failed\n");
-
- for (i = 0; i < xgi_num_devices; i++) {
- if (xgi_devices[i].dev) {
- release_mem_region(xgi_devices[i].fb.base,
- xgi_devices[i].fb.size);
- release_mem_region(xgi_devices[i].mmio.base,
- xgi_devices[i].mmio.size);
- }
- }
-
- pci_unregister_driver(&xgi_pci_driver);
- return result;
-
- return 1;
}
-void __exit xgi_exit_module(void)
+int xgi_driver_unload(struct drm_device *dev)
{
- int i;
-
-#ifdef CONFIG_DEVFS_FS
- XGI_DEVFS_REMOVE_DEVICE(xgi_num_devices);
-#endif
-
- if (XGI_UNREGISTER_CHRDEV(xgi_major, "xgi") < 0)
- XGI_ERROR("unregister xgi chrdev failed\n");
-
- XGI_INFO("Jong-unregister xgi chrdev scceeded\n");
- for (i = 0; i < XGI_MAX_DEVICES; i++) {
- if (xgi_devices[i].dev) {
- /* clean up the flush2D batch array */
- xgi_cmdlist_cleanup(&xgi_devices[i]);
-
- if (xgi_devices[i].fb.vbase != NULL) {
- iounmap(xgi_devices[i].fb.vbase);
- xgi_devices[i].fb.vbase = NULL;
- }
- if (xgi_devices[i].mmio.vbase != NULL) {
- iounmap(xgi_devices[i].mmio.vbase);
- xgi_devices[i].mmio.vbase = NULL;
- }
- //release_mem_region(xgi_devices[i].fb.base, xgi_devices[i].fb.size);
- //XGI_INFO("release frame buffer mem region scceeded\n");
-
- release_mem_region(xgi_devices[i].mmio.base,
- xgi_devices[i].mmio.size);
- XGI_INFO("release MMIO mem region scceeded\n");
-
- xgi_fb_heap_cleanup(&xgi_devices[i]);
- XGI_INFO("xgi_fb_heap_cleanup scceeded\n");
-
- xgi_pcie_heap_cleanup(&xgi_devices[i]);
- XGI_INFO("xgi_pcie_heap_cleanup scceeded\n");
-
- XGI_PCI_DISABLE_DEVICE(xgi_devices[i].dev);
- }
- }
-
- pci_unregister_driver(&xgi_pci_driver);
-
- /* remove /proc/driver/xgi */
- xgi_proc_remove();
+ struct xgi_info * info = dev->dev_private;
-#if defined(DEBUG)
- inter_module_unregister("xgi_devices");
-#endif
-}
+ xgi_cmdlist_cleanup(info);
+ if (info->fb_map != NULL) {
+ drm_rmmap(info->dev, info->fb_map);
+ }
-module_init(xgi_init_module);
-module_exit(xgi_exit_module);
+ if (info->mmio_map != NULL) {
+ drm_rmmap(info->dev, info->mmio_map);
+ }
-#if defined(XGI_PM_SUPPORT_ACPI)
-int xgi_acpi_event(struct pci_dev *dev, u32 state)
-{
- return 1;
-}
+ xgi_mem_heap_cleanup(&info->fb_heap);
+ xgi_mem_heap_cleanup(&info->pcie_heap);
+ xgi_pcie_lut_cleanup(info);
-int xgi_kern_acpi_standby(struct pci_dev *dev, u32 state)
-{
- return 1;
-}
+ if (xgi_mem_block_cache) {
+ kmem_cache_destroy(xgi_mem_block_cache);
+ xgi_mem_block_cache = NULL;
+ }
-int xgi_kern_acpi_resume(struct pci_dev *dev)
-{
- return 1;
+ return 0;
}
-#endif
-
-MODULE_AUTHOR("Andrea Zhang <andrea_zhang@macrosynergy.com>");
-MODULE_DESCRIPTION("xgi kernel driver for xgi cards");
-MODULE_LICENSE("GPL");