From 7af9d670371de868f0642148fe2d594bc9a7dea3 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:05:29 -0700 Subject: Initial XP10 code drop from XGI. See attachment 10246 on https://bugs.freedesktop.org/show_bug.cgi?id=5921 --- linux-core/xgi_cmdlist.c | 348 ++++++++++ linux-core/xgi_cmdlist.h | 79 +++ linux-core/xgi_drv.c | 1610 ++++++++++++++++++++++++++++++++++++++++++++++ linux-core/xgi_drv.h | 364 +++++++++++ linux-core/xgi_fb.c | 528 +++++++++++++++ linux-core/xgi_fb.h | 71 ++ linux-core/xgi_linux.h | 596 +++++++++++++++++ linux-core/xgi_misc.c | 657 +++++++++++++++++++ linux-core/xgi_misc.h | 49 ++ linux-core/xgi_pcie.c | 1060 ++++++++++++++++++++++++++++++ linux-core/xgi_pcie.h | 73 +++ linux-core/xgi_regs.h | 410 ++++++++++++ linux-core/xgi_types.h | 68 ++ 13 files changed, 5913 insertions(+) create mode 100644 linux-core/xgi_cmdlist.c create mode 100644 linux-core/xgi_cmdlist.h create mode 100644 linux-core/xgi_drv.c create mode 100644 linux-core/xgi_drv.h create mode 100644 linux-core/xgi_fb.c create mode 100644 linux-core/xgi_fb.h create mode 100644 linux-core/xgi_linux.h create mode 100644 linux-core/xgi_misc.c create mode 100644 linux-core/xgi_misc.h create mode 100644 linux-core/xgi_pcie.c create mode 100644 linux-core/xgi_pcie.h create mode 100644 linux-core/xgi_regs.h create mode 100644 linux-core/xgi_types.h (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c new file mode 100644 index 00000000..024b021c --- /dev/null +++ b/linux-core/xgi_cmdlist.c @@ -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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_misc.h" +#include "xgi_cmdlist.h" + + + +U32 s_emptyBegin[AGPCMDLIST_BEGIN_SIZE] = +{ + 0x10000000, // 3D Type Begin, Invalid + 0x80000004, // Length = 4; + 0x00000000, + 0x00000000 +}; + +U32 s_flush2D[AGPCMDLIST_FLUSH_CMD_LEN] = +{ + FLUSH_2D, + FLUSH_2D, + FLUSH_2D, + FLUSH_2D +}; + +xgi_cmdring_info_t s_cmdring; + +static void addFlush2D(xgi_info_t *info); +static U32 getCurBatchBeginPort(xgi_cmd_info_t *pCmdInfo); +static void triggerHWCommandList(xgi_info_t *info, U32 triggerCounter); +static void xgi_cmdlist_reset(void); + +int xgi_cmdlist_initialize(xgi_info_t *info, U32 size) +{ + //xgi_mem_req_t mem_req; + xgi_mem_alloc_t mem_alloc; + + //mem_req.size = size; + + xgi_pcie_alloc(info, size, PCIE_2D, &mem_alloc); + + if ((mem_alloc.size == 0) && (mem_alloc.hw_addr == 0)) + { + return -1; + } + + s_cmdring._cmdRingSize = mem_alloc.size; + s_cmdring._cmdRingBuffer = mem_alloc.hw_addr; + s_cmdring._cmdRingBusAddr = mem_alloc.bus_addr; + s_cmdring._lastBatchStartAddr = 0; + s_cmdring._cmdRingOffset = 0; + + return 1; +} + +void xgi_submit_cmdlist(xgi_info_t *info, xgi_cmd_info_t *pCmdInfo) +{ + U32 beginPort; + /** XGI_INFO("Jong-xgi_submit_cmdlist-Begin \n"); **/ + + /* Jong 05/25/2006 */ + /* return; */ + + beginPort = getCurBatchBeginPort(pCmdInfo); + XGI_INFO("Jong-xgi_submit_cmdlist-After getCurBatchBeginPort() \n"); + + /* Jong 05/25/2006 */ + /* return; */ + + if (s_cmdring._lastBatchStartAddr == 0) + { + U32 portOffset; + + /* Jong 06/13/2006; remove marked for system hang test */ + /* xgi_waitfor_pci_idle(info); */ + + /* Jong 06132006; BASE_3D_ENG=0x2800 */ + /* beginPort: 2D: 0x30 */ + portOffset = BASE_3D_ENG + beginPort; + + // Enable PCI Trigger Mode + XGI_INFO("Jong-xgi_submit_cmdlist-Enable PCI Trigger Mode \n"); + + /* Jong 05/25/2006 */ + /* return; */ + + /* Jong 06/13/2006; M2REG_AUTO_LINK_SETTING_ADDRESS=0x10 */ + XGI_INFO("Jong-M2REG_AUTO_LINK_SETTING_ADDRESS=0x%lx \n", M2REG_AUTO_LINK_SETTING_ADDRESS); + XGI_INFO("Jong-M2REG_CLEAR_COUNTERS_MASK=0x%lx \n", M2REG_CLEAR_COUNTERS_MASK); + XGI_INFO("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)=0x%lx \n", (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)); + XGI_INFO("Jong-M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n\n", M2REG_PCI_TRIGGER_MODE_MASK); + + /* Jong 06/14/2006; 0x400001a */ + XGI_INFO("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|M2REG_CLEAR_COUNTERS_MASK|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|M2REG_CLEAR_COUNTERS_MASK|0x08|M2REG_PCI_TRIGGER_MODE_MASK); + dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | + M2REG_CLEAR_COUNTERS_MASK | + 0x08 | + M2REG_PCI_TRIGGER_MODE_MASK); + + /* Jong 05/25/2006 */ + XGI_INFO("Jong-xgi_submit_cmdlist-After dwWriteReg() \n"); + /* return; */ /* OK */ + + /* Jong 06/14/2006; 0x400000a */ + XGI_INFO("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|0x08|M2REG_PCI_TRIGGER_MODE_MASK); + dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | + 0x08 | + M2REG_PCI_TRIGGER_MODE_MASK); + + // Send PCI begin command + XGI_INFO("Jong-xgi_submit_cmdlist-Send PCI begin command \n"); + /* return; */ + + XGI_INFO("Jong-xgi_submit_cmdlist-portOffset=%d \n", portOffset); + XGI_INFO("Jong-xgi_submit_cmdlist-beginPort=%d \n", beginPort); + + /* beginPort = 48; */ + /* 0xc100000 */ + dwWriteReg(portOffset, (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); + XGI_INFO("Jong-(beginPort<<22)=0x%lx \n", (beginPort<<22)); + XGI_INFO("Jong-(BEGIN_VALID_MASK)=0x%lx \n", BEGIN_VALID_MASK); + XGI_INFO("Jong- pCmdInfo->_curDebugID=0x%lx \n", pCmdInfo->_curDebugID); + XGI_INFO("Jong- (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID=0x%lx \n", (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); + XGI_INFO("Jong-xgi_submit_cmdlist-Send PCI begin command- After \n"); + /* return; */ /* OK */ + + /* 0x80000024 */ + dwWriteReg(portOffset+4, BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); + XGI_INFO("Jong- BEGIN_LINK_ENABLE_MASK=0x%lx \n", BEGIN_LINK_ENABLE_MASK); + XGI_INFO("Jong- pCmdInfo->_firstSize=0x%lx \n", pCmdInfo->_firstSize); + XGI_INFO("Jong- BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize=0x%lx \n", BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); + XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-1 \n"); + + /* 0x1010000 */ + dwWriteReg(portOffset+8, (pCmdInfo->_firstBeginAddr >> 4)); + XGI_INFO("Jong- pCmdInfo->_firstBeginAddr=0x%lx \n", pCmdInfo->_firstBeginAddr); + XGI_INFO("Jong- (pCmdInfo->_firstBeginAddr >> 4)=0x%lx \n", (pCmdInfo->_firstBeginAddr >> 4)); + XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-2 \n"); + + /* Jong 06/13/2006 */ + xgi_dump_register(info); + + /* Jong 06/12/2006; system hang; marked for test */ + dwWriteReg(portOffset+12, 0); + XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-3 \n"); + + /* Jong 06/13/2006; remove marked for system hang test */ + /* xgi_waitfor_pci_idle(info); */ + } + else + { + XGI_INFO("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 \n"); + U32 *lastBatchVirtAddr; + + /* Jong 05/25/2006 */ + /* return; */ + + if (pCmdInfo->_firstBeginType == BTYPE_3D) + { + addFlush2D(info); + } + + lastBatchVirtAddr = (U32*) xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); + + lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize; + lastBatchVirtAddr[2] = pCmdInfo->_firstBeginAddr >> 4; + lastBatchVirtAddr[3] = 0; + //barrier(); + lastBatchVirtAddr[0] = (beginPort<<22) + (BEGIN_VALID_MASK) + (0xffff & pCmdInfo->_curDebugID); + + /* Jong 06/12/2006; system hang; marked for test */ + triggerHWCommandList(info, pCmdInfo->_beginCount); + + XGI_INFO("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 - End\n"); + } + + s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; + XGI_INFO("Jong-xgi_submit_cmdlist-End \n"); +} + + +/* + state: 0 - console + 1 - graphic + 2 - fb + 3 - logout +*/ +void xgi_state_change(xgi_info_t *info, xgi_state_info_t *pStateInfo) +{ +#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 ((pStateInfo->_fromState == STATE_GRAPHIC) + && (pStateInfo->_toState == STATE_CONSOLE)) + { + XGI_INFO("[kd] I see, now is to leaveVT\n"); + // stop to received batch + } + else if ((pStateInfo->_fromState == STATE_CONSOLE) + && (pStateInfo->_toState == STATE_GRAPHIC)) + { + XGI_INFO("[kd] I see, now is to enterVT\n"); + xgi_cmdlist_reset(); + } + else if ((pStateInfo->_fromState == STATE_GRAPHIC) + && ( (pStateInfo->_toState == STATE_LOGOUT) + ||(pStateInfo->_toState == STATE_REBOOT) + ||(pStateInfo->_toState == STATE_SHUTDOWN))) + { + XGI_INFO("[kd] I see, not is to exit from X\n"); + // stop to received batch + } + else + { + XGI_ERROR("[kd] Should not happen\n"); + } + +} + +void xgi_cmdlist_reset(void) +{ + s_cmdring._lastBatchStartAddr = 0; + s_cmdring._cmdRingOffset = 0; +} + +void xgi_cmdlist_cleanup(xgi_info_t *info) +{ + if (s_cmdring._cmdRingBuffer != 0) + { + xgi_pcie_free(info, s_cmdring._cmdRingBusAddr); + s_cmdring._cmdRingBuffer = 0; + s_cmdring._cmdRingOffset = 0; + s_cmdring._cmdRingSize = 0; + } +} + +static void triggerHWCommandList(xgi_info_t *info, U32 triggerCounter) +{ + static U32 s_triggerID = 1; + + //Fix me, currently we just trigger one time + while (triggerCounter--) + { + dwWriteReg(BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, + 0x05000000 + (0xffff & s_triggerID++)); + // xgi_waitfor_pci_idle(info); + } +} + +static U32 getCurBatchBeginPort(xgi_cmd_info_t *pCmdInfo) +{ + // Convert the batch type to begin port ID + switch(pCmdInfo->_firstBeginType) + { + case BTYPE_2D: + return 0x30; + case BTYPE_3D: + return 0x40; + case BTYPE_FLIP: + return 0x50; + case BTYPE_CTRL: + return 0x20; + default: + //ASSERT(0); + return 0xff; + } +} + +static void addFlush2D(xgi_info_t *info) +{ + U32 *flushBatchVirtAddr; + U32 flushBatchHWAddr; + + U32 *lastBatchVirtAddr; + + /* check buf is large enough to contain a new flush batch */ + if ((s_cmdring._cmdRingOffset + 0x20) >= s_cmdring._cmdRingSize) + { + s_cmdring._cmdRingOffset = 0; + } + + flushBatchHWAddr = s_cmdring._cmdRingBuffer + s_cmdring._cmdRingOffset; + flushBatchVirtAddr = (U32*) xgi_find_pcie_virt(info, flushBatchHWAddr); + + /* 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; + + // ASSERT(s_cmdring._lastBatchStartAddr != NULL); + lastBatchVirtAddr = (U32*) xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); + + lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; + lastBatchVirtAddr[2] = flushBatchHWAddr >> 4; + lastBatchVirtAddr[3] = 0; + + //barrier(); + + // BTYPE_CTRL & NO debugID + lastBatchVirtAddr[0] = (0x20<<22) + (BEGIN_VALID_MASK); + + triggerHWCommandList(info, 1); + + s_cmdring._cmdRingOffset += 0x20; + s_cmdring._lastBatchStartAddr = flushBatchHWAddr; +} diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h new file mode 100644 index 00000000..1b0c4965 --- /dev/null +++ b/linux-core/xgi_cmdlist.h @@ -0,0 +1,79 @@ + +/**************************************************************************** + * 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 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; + +typedef struct xgi_cmdring_info_s +{ + U32 _cmdRingSize; + U32 _cmdRingBuffer; + U32 _cmdRingBusAddr; + U32 _lastBatchStartAddr; + U32 _cmdRingOffset; +}xgi_cmdring_info_t; + +extern int xgi_cmdlist_initialize(xgi_info_t *info, U32 size); + +extern void xgi_submit_cmdlist(xgi_info_t *info, xgi_cmd_info_t * pCmdInfo); + +extern void xgi_state_change(xgi_info_t *info, xgi_state_info_t * pStateInfo); + +extern void xgi_cmdlist_cleanup(xgi_info_t *info); + +#endif /* _XGI_CMDLIST_H_ */ diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c new file mode 100644 index 00000000..5e80d417 --- /dev/null +++ b/linux-core/xgi_drv.c @@ -0,0 +1,1610 @@ + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.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. */ + +static int xgi_num_devices = 0; + +xgi_info_t xgi_devices[XGI_MAX_DEVICES]; + +#if defined(XGI_PM_SUPPORT_APM) +static struct pm_dev *apm_xgi_dev[XGI_MAX_DEVICES] = { 0 }; +#endif + +/* add one for the control device */ +xgi_info_t xgi_ctl_device; +wait_queue_head_t xgi_ctl_waitqueue; + +#ifdef CONFIG_PROC_FS +struct proc_dir_entry *proc_xgi; +#endif + +#ifdef CONFIG_DEVFS_FS +devfs_handle_t xgi_devfs_handles[XGI_MAX_DEVICES]; +#endif + +struct list_head xgi_mempid_list; + +/* xgi_ functions.. do not take a state device parameter */ +static int xgi_post_vbios(xgi_ioctl_post_vbios_t *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 *); + +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 + +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 *); + +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 *); + +void xgi_kern_isr_bh(unsigned long); +irqreturn_t xgi_kern_isr(int, void *, struct pt_regs *); + +static void xgi_lock_init(xgi_info_t *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 + +/* + * verify access to pci config space wasn't disabled behind our back + * unfortunately, XFree86 enables/disables memory access in pci config space at + * various times (such as restoring initial pci config space settings during vt + * switches or when doing mulicard). As a result, all of our register accesses + * are garbage at this point. add a check to see if access was disabled and + * reenable any such access. + */ +#define XGI_CHECK_PCI_CONFIG(xgi) \ + xgi_check_pci_config(xgi, __LINE__) + +static inline void xgi_check_pci_config(xgi_info_t *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; + + pci_read_config_word(info->dev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MASTER)) + { + XGI_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); + cmd |= PCI_COMMAND_MEMORY; + flag = 1; + } + + if (flag) + pci_write_config_word(info->dev, PCI_COMMAND, cmd); +} + +static int xgi_post_vbios(xgi_ioctl_post_vbios_t *info) +{ + return 1; +} + +/* + * 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) +{ + xgi_info_t *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; + info->vendor_id = dev->vendor; + info->device_id = dev->device; + info->bus = dev->bus->number; + info->slot = PCI_SLOT((dev)->devfn); + + xgi_lock_init(info); + + info->mmio.base = XGI_PCI_RESOURCE_START(dev, 1); + info->mmio.size = XGI_PCI_RESOURCE_SIZE(dev, 1); + + /* 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; + } + + 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 = (unsigned char *)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 = (unsigned char *)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); + + info->irq = dev->irq; + + /* check common error condition */ + if (info->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->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; + +} + +/* + * 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)) + { + xgi_pcie_block_t *block = (xgi_pcie_block_t *)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)) + { + xgi_pcie_block_t *block = (xgi_pcie_block_t *)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) +{ + xgi_pcie_block_t *block = (xgi_pcie_block_t *)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) +{ + xgi_pcie_block_t *block = (xgi_pcie_block_t *)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 xgi_file_private_t * xgi_alloc_file_private(void) +{ + xgi_file_private_t *fp; + + XGI_KMALLOC(fp, sizeof(xgi_file_private_t)); + if (!fp) + return NULL; + + memset(fp, 0, sizeof(xgi_file_private_t)); + + /* 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(xgi_file_private_t *fp) +{ + if (fp == NULL) + return; + + XGI_KFREE(fp, sizeof(xgi_file_private_t)); +} + +int xgi_kern_open(struct inode *inode, struct file *filp) +{ + xgi_info_t *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->device_id == 0) + { + XGI_INFO("open of nonexistent device %d\n", dev_num); + result = -ENXIO; + goto failed; + } + + /* initialize struct irqaction */ + status = request_irq(info->irq, xgi_kern_isr, + SA_INTERRUPT | SA_SHIRQ, "xgi", + (void *) info); + if (status != 0) + { + if (info->irq && (status == -EBUSY)) + { + XGI_ERROR("Tried to get irq %d, but another driver", + (unsigned int) info->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) +{ + xgi_info_t *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->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); + xgi_info_t *info = XGI_INFO_FROM_FP(filp); + xgi_pcie_block_t *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_pcie_block_t *)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) +{ + xgi_file_private_t *fp; + xgi_info_t *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) +{ + xgi_info_t *info; + xgi_mem_alloc_t *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 = (xgi_mem_alloc_t *)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_DEVICE_INFO: + XGI_INFO("Jong-xgi_ioctl_get_device_info \n"); + xgi_get_device_info(info, (struct xgi_chip_info_s *) arg_copy); + break; + 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, (struct xgi_mem_req_s *)arg_copy, alloc); + 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_MEM_COLLECT: + XGI_INFO("Jong-xgi_ioctl_mem_collect \n"); + xgi_mem_collect(info, (unsigned int *) arg_copy); + break; + case XGI_ESC_PCIE_ALLOC: + XGI_INFO("Jong-xgi_ioctl_pcie_alloc \n"); + xgi_pcie_alloc(info, ((xgi_mem_req_t *)arg_copy)->size, + ((xgi_mem_req_t *)arg_copy)->owner, alloc); + 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_PCIE_CHECK: + XGI_INFO("Jong-xgi_pcie_heap_check \n"); + xgi_pcie_heap_check(); + break; + case XGI_ESC_GET_SCREEN_INFO: + XGI_INFO("Jong-xgi_get_screen_info \n"); + xgi_get_screen_info(info, (struct xgi_screen_info_s *) arg_copy); + break; + case XGI_ESC_PUT_SCREEN_INFO: + XGI_INFO("Jong-xgi_put_screen_info \n"); + xgi_put_screen_info(info, (struct xgi_screen_info_s *) arg_copy); + break; + case XGI_ESC_MMIO_INFO: + XGI_INFO("Jong-xgi_ioctl_get_mmio_info \n"); + xgi_get_mmio_info(info, (struct xgi_mmio_info_s *) arg_copy); + break; + case XGI_ESC_GE_RESET: + XGI_INFO("Jong-xgi_ioctl_ge_reset \n"); + xgi_ge_reset(info); + break; + case XGI_ESC_SAREA_INFO: + XGI_INFO("Jong-xgi_ioctl_sarea_info \n"); + xgi_sarea_info(info, (struct xgi_sarea_info_s *) arg_copy); + 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); + //xgi_write_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); + //xgi_read_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); + break; + case XGI_ESC_SUBMIT_CMDLIST: + XGI_INFO("Jong-xgi_ioctl_submit_cmdlist \n"); + xgi_submit_cmdlist(info, (xgi_cmd_info_t *) 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, (xgi_state_info_t *) arg_copy); + break; + case XGI_ESC_CPUID: + XGI_INFO("Jong-XGI_ESC_CPUID \n"); + xgi_get_cpu_id((struct cpu_info_s*) 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) +{ + xgi_info_t *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) +{ + xgi_info_t *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) +{ + //xgi_info_t *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; + } + + 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; +} + +static struct pci_dev* xgi_get_pci_device(xgi_info_t *info) +{ + struct pci_dev *dev; + + dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, NULL); + while (dev) + { + if (XGI_PCI_SLOT_NUMBER(dev) == info->slot + && XGI_PCI_BUS_NUMBER(dev) == info->bus) + return dev; + dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, dev); + } + + return NULL; +} + +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; + + xgi_info_t *info; + info = (xgi_info_t *) data; + + dev = xgi_get_pci_device(info); + 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"); + + return len; +} + +int xgi_kern_read_pcie_info(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + 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) +{ +#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; + + xgi_info_t *info; + xgi_info_t *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++) + { + if (info->device_id == 0) + break; + + /* world readable file */ + flags = S_IFREG | S_IRUGO; + + dev = xgi_get_pci_device(info); + 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; + + 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 +} + +#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) +{ + xgi_info_t *info = (xgi_info_t *) dev_id; + u32 need_to_run_bottom_half = 0; + + //XGI_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); + } + + return IRQ_HANDLED; +} + +void xgi_kern_isr_bh(unsigned long data) +{ + xgi_info_t *info = (xgi_info_t *) data; + + XGI_INFO("xgi_kern_isr_bh \n"); + + //xgi_dvi_irq_handler(info); + + XGI_CHECK_PCI_CONFIG(info); +} + +static void xgi_lock_init(xgi_info_t *info) +{ + 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); +} + +static void xgi_dev_init(xgi_info_t *info) +{ + struct pci_dev *pdev = NULL; + struct xgi_dev *dev; + int found = 0; + u16 pci_cmd; + + XGI_INFO("Enter xgi_dev_init \n"); + + //XGI_PCI_FOR_EACH_DEV(pdev) + { + for (dev = xgidev_list; dev->vendor; dev++) + { + if ((dev->vendor == pdev->vendor) && (dev->device == pdev->device)) + { + XGI_INFO("dev->vendor = pdev->vendor= %x \n", dev->vendor); + XGI_INFO("dev->device = pdev->device= %x \n", dev->device); + + xgi_devices[found].device_id = pdev->device; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_devices[found].revision_id); + + XGI_INFO("PCI_REVISION_ID= %x \n", xgi_devices[found].revision_id); + + pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); + + XGI_INFO("PCI_COMMAND = %x \n", pci_cmd); + + break; + } + } + } +} +/* + * Export to Linux Kernel + */ + +static int __init xgi_init_module(void) +{ + xgi_info_t *info = &xgi_devices[xgi_num_devices]; + int i, result; + + XGI_INFO("Jong-xgi kernel driver %s initializing\n", XGI_DRV_VERSION); + //SET_MODULE_OWNER(&xgi_fops); + + memset(xgi_devices, 0, sizeof(xgi_devices)); + + if (pci_register_driver(&xgi_pci_driver) < 0) + { + pci_unregister_driver(&xgi_pci_driver); + XGI_ERROR("no XGI graphics adapter found\n"); + return -ENODEV; + } + + 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 (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); + } + + /* init the xgi control device */ + { + xgi_info_t *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; + } + + /* 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 i; + xgi_info_t *info, *max_devices; + +#ifdef CONFIG_DEVFS_FS + /* + XGI_DEVFS_REMOVE_CONTROL(); + for (i = 0; i < XGI_MAX_DEVICES; i++) + XGI_DEVFS_REMOVE_DEVICE(i); + */ + 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((void *)xgi_devices[i].fb.vbase); + xgi_devices[i].fb.vbase = NULL; + } + if(xgi_devices[i].mmio.vbase != NULL) + { + iounmap((void *)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(); + +#if defined(DEBUG) + inter_module_unregister("xgi_devices"); +#endif +} + +module_init(xgi_init_module); +module_exit(xgi_exit_module); + +#if defined(XGI_PM_SUPPORT_ACPI) +int xgi_acpi_event(struct pci_dev *dev, u32 state) +{ + return 1; +} + +int xgi_kern_acpi_standby(struct pci_dev *dev, u32 state) +{ + return 1; +} + +int xgi_kern_acpi_resume(struct pci_dev *dev) +{ + return 1; +} +#endif + +MODULE_AUTHOR("Andrea Zhang "); +MODULE_DESCRIPTION("xgi kernel driver for xgi cards"); +MODULE_LICENSE("GPL"); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h new file mode 100644 index 00000000..568a7af1 --- /dev/null +++ b/linux-core/xgi_drv.h @@ -0,0 +1,364 @@ + +/**************************************************************************** + * 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_ + +#define XGI_MAJOR_VERSION 0 +#define XGI_MINOR_VERSION 7 +#define XGI_PATCHLEVEL 5 + +#define XGI_DRV_VERSION "0.7.5" + +#ifndef XGI_DRV_NAME +#define XGI_DRV_NAME "xgi" +#endif + +/* + * xgi reserved major device number, Set this to 0 to + * request dynamic major number allocation. + */ +#ifndef XGI_DEV_MAJOR +#define XGI_DEV_MAJOR 0 +#endif + +#ifndef XGI_MAX_DEVICES +#define XGI_MAX_DEVICES 1 +#endif + +/* Jong 06/06/2006 */ +/* #define XGI_DEBUG */ + +#ifndef PCI_VENDOR_ID_XGI +/* +#define PCI_VENDOR_ID_XGI 0x1023 +*/ +#define PCI_VENDOR_ID_XGI 0x18CA + +#endif + +#ifndef PCI_DEVICE_ID_XP5 +#define PCI_DEVICE_ID_XP5 0x2200 +#endif + +#ifndef PCI_DEVICE_ID_XG47 +#define PCI_DEVICE_ID_XG47 0x0047 +#endif + +/* Macros to make printk easier */ +#define XGI_ERROR(fmt, arg...) \ + printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) + +#define XGI_MEM_ERROR(area, fmt, arg...) \ + printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) + +/* #define XGI_DEBUG */ + +#ifdef XGI_DEBUG +#define XGI_INFO(fmt, arg...) \ + printk(KERN_ALERT "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) +/* printk(KERN_INFO "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) */ +#else +#define XGI_INFO(fmt, arg...) do { } while (0) +#endif + +/* device name length; must be atleast 8 */ +#define XGI_DEVICE_NAME_LENGTH 40 + +/* need a fake device number for control device; just to flag it for msgs */ +#define XGI_CONTROL_DEVICE_NUMBER 100 + +typedef struct { + U32 base; // pcie base is different from fb base + U32 size; + U8 *vbase; +} xgi_aperture_t; + +typedef struct xgi_screen_info_s { + U32 scrn_start; + U32 scrn_xres; + U32 scrn_yres; + U32 scrn_bpp; + U32 scrn_pitch; +} xgi_screen_info_t; + +typedef struct xgi_sarea_info_s { + U32 bus_addr; + U32 size; +} xgi_sarea_info_t; + +typedef struct xgi_info_s { + struct pci_dev *dev; + int flags; + int device_number; + int bus; /* PCI config info */ + int slot; + int vendor_id; + U32 device_id; + U8 revision_id; + + /* physical characteristics */ + xgi_aperture_t mmio; + xgi_aperture_t fb; + xgi_aperture_t pcie; + xgi_screen_info_t scrn_info; + xgi_sarea_info_t sarea_info; + + /* look up table parameters */ + U32 *lut_base; + U32 lutPageSize; + U32 lutPageOrder; + U32 isLUTInLFB; + U32 sdfbPageSize; + + U32 pcie_config; + U32 pcie_status; + U32 irq; + + atomic_t use_count; + + /* keep track of any pending bottom halfes */ + struct tasklet_struct tasklet; + + spinlock_t info_lock; + + struct semaphore info_sem; + struct semaphore fb_sem; + struct semaphore pcie_sem; +} xgi_info_t; + +typedef struct xgi_ioctl_post_vbios { + U32 bus; + U32 slot; +} xgi_ioctl_post_vbios_t; + +typedef enum xgi_mem_location_s +{ + NON_LOCAL = 0, + LOCAL = 1, + INVALID = 0x7fffffff +} xgi_mem_location_t; + +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 +}; + +typedef struct xgi_mem_req_s { + xgi_mem_location_t location; + unsigned long size; + unsigned long is_front; + enum PcieOwner owner; + unsigned long pid; +} xgi_mem_req_t; + +typedef struct xgi_mem_alloc_s { + xgi_mem_location_t location; + unsigned long size; + unsigned long bus_addr; + unsigned long hw_addr; + unsigned long pid; +} xgi_mem_alloc_t; + +typedef struct xgi_chip_info_s { + U32 device_id; + char device_name[32]; + U32 vendor_id; + U32 curr_display_mode; //Singe, DualView(Contained), MHS + U32 fb_size; + U32 sarea_bus_addr; + U32 sarea_size; +} xgi_chip_info_t; + +typedef struct xgi_opengl_cmd_s { + U32 cmd; +} xgi_opengl_cmd_t; + +typedef struct xgi_mmio_info_s { + xgi_opengl_cmd_t cmd_head; + void *mmioBase; + int size; +} xgi_mmio_info_t; + +typedef enum { + BTYPE_2D = 0, + BTYPE_3D = 1, + BTYPE_FLIP = 2, + BTYPE_CTRL = 3, + BTYPE_NONE = 0x7fffffff +}BATCH_TYPE; + +typedef struct xgi_cmd_info_s { + BATCH_TYPE _firstBeginType; + U32 _firstBeginAddr; + U32 _firstSize; + U32 _curDebugID; + U32 _lastBeginAddr; + U32 _beginCount; +} xgi_cmd_info_t; + +typedef struct xgi_state_info_s { + U32 _fromState; + U32 _toState; +} xgi_state_info_t; + +typedef struct cpu_info_s { + U32 _eax; + U32 _ebx; + U32 _ecx; + U32 _edx; +} cpu_info_t; + +typedef struct xgi_mem_pid_s { + struct list_head list; + xgi_mem_location_t location; + unsigned long bus_addr; + unsigned long pid; +} xgi_mem_pid_t; + +/* + * Ioctl definitions + */ + +#define XGI_IOCTL_MAGIC 'x' /* use 'x' as magic number */ + +#define XGI_IOCTL_BASE 0 +#define XGI_ESC_DEVICE_INFO (XGI_IOCTL_BASE + 0) +#define XGI_ESC_POST_VBIOS (XGI_IOCTL_BASE + 1) + +#define XGI_ESC_FB_INIT (XGI_IOCTL_BASE + 2) +#define XGI_ESC_FB_ALLOC (XGI_IOCTL_BASE + 3) +#define XGI_ESC_FB_FREE (XGI_IOCTL_BASE + 4) +#define XGI_ESC_PCIE_INIT (XGI_IOCTL_BASE + 5) +#define XGI_ESC_PCIE_ALLOC (XGI_IOCTL_BASE + 6) +#define XGI_ESC_PCIE_FREE (XGI_IOCTL_BASE + 7) +#define XGI_ESC_SUBMIT_CMDLIST (XGI_IOCTL_BASE + 8) +#define XGI_ESC_PUT_SCREEN_INFO (XGI_IOCTL_BASE + 9) +#define XGI_ESC_GET_SCREEN_INFO (XGI_IOCTL_BASE + 10) +#define XGI_ESC_GE_RESET (XGI_IOCTL_BASE + 11) +#define XGI_ESC_SAREA_INFO (XGI_IOCTL_BASE + 12) +#define XGI_ESC_DUMP_REGISTER (XGI_IOCTL_BASE + 13) +#define XGI_ESC_DEBUG_INFO (XGI_IOCTL_BASE + 14) +#define XGI_ESC_TEST_RWINKERNEL (XGI_IOCTL_BASE + 16) +#define XGI_ESC_STATE_CHANGE (XGI_IOCTL_BASE + 17) +#define XGI_ESC_MMIO_INFO (XGI_IOCTL_BASE + 18) +#define XGI_ESC_PCIE_CHECK (XGI_IOCTL_BASE + 19) +#define XGI_ESC_CPUID (XGI_IOCTL_BASE + 20) +#define XGI_ESC_MEM_COLLECT (XGI_IOCTL_BASE + 21) + +#define XGI_IOCTL_DEVICE_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_DEVICE_INFO, xgi_chip_info_t) +#define XGI_IOCTL_POST_VBIOS _IO(XGI_IOCTL_MAGIC, XGI_ESC_POST_VBIOS) + +#define XGI_IOCTL_FB_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_FB_INIT) +#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, xgi_mem_req_t) +#define XGI_IOCTL_FB_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_FB_FREE, unsigned long) + +#define XGI_IOCTL_PCIE_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_INIT) +#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, xgi_mem_req_t) +#define XGI_IOCTL_PCIE_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_FREE, unsigned long) + +#define XGI_IOCTL_PUT_SCREEN_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PUT_SCREEN_INFO, xgi_screen_info_t) +#define XGI_IOCTL_GET_SCREEN_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_GET_SCREEN_INFO, xgi_screen_info_t) + +#define XGI_IOCTL_GE_RESET _IO(XGI_IOCTL_MAGIC, XGI_ESC_GE_RESET) +#define XGI_IOCTL_SAREA_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_SAREA_INFO, xgi_sarea_info_t) +#define XGI_IOCTL_DUMP_REGISTER _IO(XGI_IOCTL_MAGIC, XGI_ESC_DUMP_REGISTER) +#define XGI_IOCTL_DEBUG_INFO _IO(XGI_IOCTL_MAGIC, XGI_ESC_DEBUG_INFO) +#define XGI_IOCTL_MMIO_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_MMIO_INFO, xgi_mmio_info_t) + +#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, xgi_cmd_info_t) +#define XGI_IOCTL_TEST_RWINKERNEL _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_TEST_RWINKERNEL, unsigned long) +#define XGI_IOCTL_STATE_CHANGE _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_STATE_CHANGE, xgi_state_info_t) + +#define XGI_IOCTL_PCIE_CHECK _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_CHECK) +#define XGI_IOCTL_CPUID _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_CPUID, cpu_info_t) +#define XGI_IOCTL_MAXNR 30 + +/* + * flags + */ +#define XGI_FLAG_OPEN 0x0001 +#define XGI_FLAG_NEEDS_POSTING 0x0002 +#define XGI_FLAG_WAS_POSTED 0x0004 +#define XGI_FLAG_CONTROL 0x0010 +#define XGI_FLAG_MAP_REGS_EARLY 0x0200 + +/* mmap(2) offsets */ + +#define IS_IO_OFFSET(info, offset, length) \ + (((offset) >= (info)->mmio.base) \ + && (((offset) + (length)) <= (info)->mmio.base + (info)->mmio.size)) + +/* Jong 06/14/2006 */ +/* (info)->fb.base is a base address for physical (bus) address space */ +/* what's the definition of offest? on physical (bus) address space or HW address space */ +/* Jong 06/15/2006; use HW address space */ +#define IS_FB_OFFSET(info, offset, length) \ + (((offset) >= 0) \ + && (((offset) + (length)) <= (info)->fb.size)) +#if 0 +#define IS_FB_OFFSET(info, offset, length) \ + (((offset) >= (info)->fb.base) \ + && (((offset) + (length)) <= (info)->fb.base + (info)->fb.size)) +#endif + +#define IS_PCIE_OFFSET(info, offset, length) \ + (((offset) >= (info)->pcie.base) \ + && (((offset) + (length)) <= (info)->pcie.base + (info)->pcie.size)) + +extern int xgi_fb_heap_init(xgi_info_t *info); +extern void xgi_fb_heap_cleanup(xgi_info_t *info); + +extern void xgi_fb_alloc(xgi_info_t *info, xgi_mem_req_t *req, xgi_mem_alloc_t *alloc); +extern void xgi_fb_free(xgi_info_t *info, unsigned long offset); +extern void xgi_mem_collect(xgi_info_t *info, unsigned int *pcnt); + +extern int xgi_pcie_heap_init(xgi_info_t *info); +extern void xgi_pcie_heap_cleanup(xgi_info_t *info); + +extern void xgi_pcie_alloc(xgi_info_t *info, unsigned long size, enum PcieOwner owner, xgi_mem_alloc_t *alloc); +extern void xgi_pcie_free(xgi_info_t *info, unsigned long offset); +extern void xgi_pcie_heap_check(void); +extern void *xgi_find_pcie_block(xgi_info_t *info, unsigned long address); +extern void *xgi_find_pcie_virt(xgi_info_t *info, unsigned long address); + +extern void xgi_read_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req); +extern void xgi_write_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req); + +extern void xgi_test_rwinkernel(xgi_info_t *info, unsigned long address); + +#endif diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c new file mode 100644 index 00000000..67fdfe17 --- /dev/null +++ b/linux-core/xgi_fb.c @@ -0,0 +1,528 @@ + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_fb.h" + +#define XGI_FB_HEAP_START 0x1000000 + +static xgi_mem_heap_t *xgi_fb_heap; +static kmem_cache_t *xgi_fb_cache_block = NULL; +extern struct list_head xgi_mempid_list; + +static xgi_mem_block_t *xgi_mem_new_node(void); +static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t *info, unsigned long size); +static xgi_mem_block_t *xgi_mem_free(xgi_info_t *info, unsigned long offset); + +void xgi_fb_alloc(xgi_info_t *info, + xgi_mem_req_t *req, + xgi_mem_alloc_t *alloc) +{ + xgi_mem_block_t *block; + xgi_mem_pid_t *mempid_block; + + if (req->is_front) + { + alloc->location = LOCAL; + alloc->bus_addr = info->fb.base; + alloc->hw_addr = 0; + XGI_INFO("Video RAM allocation on front buffer successfully! \n"); + } + else + { + xgi_down(info->fb_sem); + block = xgi_mem_alloc(info, req->size); + xgi_up(info->fb_sem); + + if (block == NULL) + { + alloc->location = LOCAL; + alloc->size = 0; + alloc->bus_addr = 0; + alloc->hw_addr = 0; + XGI_ERROR("Video RAM allocation failed\n"); + } + else + { + XGI_INFO("Video RAM allocation succeeded: 0x%p\n", + (char *) block->offset); + alloc->location = LOCAL; + alloc->size = block->size; + alloc->bus_addr = info->fb.base + block->offset; + alloc->hw_addr = block->offset; + + /* manage mempid */ + mempid_block = kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + mempid_block->location = LOCAL; + mempid_block->bus_addr = alloc->bus_addr; + mempid_block->pid = alloc->pid; + + if (!mempid_block) + XGI_ERROR("mempid_block alloc failed\n"); + + XGI_INFO("Memory ProcessID add one fb block pid:%ld successfully! \n", mempid_block->pid); + list_add(&mempid_block->list, &xgi_mempid_list); + } + } +} + +void xgi_fb_free(xgi_info_t *info, unsigned long bus_addr) +{ + xgi_mem_block_t *block; + unsigned long offset = bus_addr - info->fb.base; + xgi_mem_pid_t *mempid_block; + xgi_mem_pid_t *mempid_freeblock = NULL; + struct list_head *mempid_list; + + if (offset < 0) + { + XGI_INFO("free onscreen frame buffer successfully !\n"); + } + else + { + xgi_down(info->fb_sem); + block = xgi_mem_free(info, offset); + xgi_up(info->fb_sem); + + if (block == NULL) + { + XGI_ERROR("xgi_mem_free() failed at base 0x%lx\n", offset); + } + + /* manage mempid */ + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) + { + mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == LOCAL && mempid_block->bus_addr == bus_addr) + { + mempid_freeblock = mempid_block; + break; + } + mempid_list = mempid_list->next; + } + if (mempid_freeblock) + { + list_del(&mempid_freeblock->list); + XGI_INFO("Memory ProcessID delete one fb block pid:%ld successfully! \n", mempid_freeblock->pid); + kfree(mempid_freeblock); + } + } +} + +int xgi_fb_heap_init(xgi_info_t *info) +{ + xgi_mem_block_t *block; + + xgi_fb_heap = kmalloc(sizeof(xgi_mem_heap_t), GFP_KERNEL); + if (!xgi_fb_heap) + { + XGI_ERROR("xgi_fb_heap alloc failed\n"); + return 0; + } + + INIT_LIST_HEAD(&xgi_fb_heap->free_list); + INIT_LIST_HEAD(&xgi_fb_heap->used_list); + INIT_LIST_HEAD(&xgi_fb_heap->sort_list); + + xgi_fb_cache_block = kmem_cache_create("xgi_fb_block", sizeof(xgi_mem_block_t), + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (NULL == xgi_fb_cache_block) + { + XGI_ERROR("Fail to creat xgi_fb_block\n"); + goto fail1; + } + + block = (xgi_mem_block_t *)kmem_cache_alloc(xgi_fb_cache_block, GFP_KERNEL); + if (!block) + { + XGI_ERROR("kmem_cache_alloc failed\n"); + goto fail2; + } + + block->offset = XGI_FB_HEAP_START; + block->size = info->fb.size - XGI_FB_HEAP_START; + + list_add(&block->list, &xgi_fb_heap->free_list); + + xgi_fb_heap->max_freesize = info->fb.size - XGI_FB_HEAP_START; + + XGI_INFO("fb start offset: 0x%lx, memory size : 0x%lx\n", block->offset, block->size); + XGI_INFO("xgi_fb_heap->max_freesize: 0x%lx \n", xgi_fb_heap->max_freesize); + + return 1; + +fail2: + if (xgi_fb_cache_block) + { + kmem_cache_destroy(xgi_fb_cache_block); + xgi_fb_cache_block = NULL; + } +fail1: + if(xgi_fb_heap) + { + kfree(xgi_fb_heap); + xgi_fb_heap = NULL; + } + return 0; +} + +void xgi_fb_heap_cleanup(xgi_info_t *info) +{ + struct list_head *free_list, *temp; + xgi_mem_block_t *block; + int i; + + if (xgi_fb_heap) + { + free_list = &xgi_fb_heap->free_list; + for (i = 0; i < 3; i++, free_list++) + { + temp = free_list->next; + while (temp != free_list) + { + block = list_entry(temp, struct xgi_mem_block_s, list); + temp = temp->next; + + XGI_INFO("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + i, block->offset, block->size); + //XGI_INFO("No. %d free block: 0x%p \n", i, block); + kmem_cache_free(xgi_fb_cache_block, block); + block = NULL; + } + } + XGI_INFO("xgi_fb_heap: 0x%p \n", xgi_fb_heap); + kfree(xgi_fb_heap); + xgi_fb_heap = NULL; + } + + if (xgi_fb_cache_block) + { + kmem_cache_destroy(xgi_fb_cache_block); + xgi_fb_cache_block = NULL; + } +} + +static xgi_mem_block_t * xgi_mem_new_node(void) +{ + xgi_mem_block_t *block; + + block = (xgi_mem_block_t *)kmem_cache_alloc(xgi_fb_cache_block, GFP_KERNEL); + if (!block) + { + XGI_ERROR("kmem_cache_alloc failed\n"); + return NULL; + } + + return block; +} + +#if 0 +static void xgi_mem_insert_node_after(xgi_mem_list_t *list, + xgi_mem_block_t *current, + xgi_mem_block_t *block); +static void xgi_mem_insert_node_before(xgi_mem_list_t *list, + xgi_mem_block_t *current, + xgi_mem_block_t *block); +static void xgi_mem_insert_node_head(xgi_mem_list_t *list, + xgi_mem_block_t *block); +static void xgi_mem_insert_node_tail(xgi_mem_list_t *list, + xgi_mem_block_t *block); +static void xgi_mem_delete_node(xgi_mem_list_t *list, + xgi_mem_block_t *block); +/* + * insert node:block after node:current + */ +static void xgi_mem_insert_node_after(xgi_mem_list_t *list, + xgi_mem_block_t *current, + xgi_mem_block_t *block) +{ + block->prev = current; + block->next = current->next; + current->next = block; + + if (current == list->tail) + { + list->tail = block; + } + else + { + block->next->prev = block; + } +} + +/* + * insert node:block before node:current + */ +static void xgi_mem_insert_node_before(xgi_mem_list_t *list, + xgi_mem_block_t *current, + xgi_mem_block_t *block) +{ + block->prev = current->prev; + block->next = current; + current->prev = block; + if (current == list->head) + { + list->head = block; + } + else + { + block->prev->next = block; + } +} +void xgi_mem_insert_node_head(xgi_mem_list_t *list, + xgi_mem_block_t *block) +{ + block->next = list->head; + block->prev = NULL; + + if (NULL == list->head) + { + list->tail = block; + } + else + { + list->head->prev = block; + } + list->head = block; +} + +static void xgi_mem_insert_node_tail(xgi_mem_list_t *list, + xgi_mem_block_t *block) + +{ + block->next = NULL; + block->prev = list->tail; + if (NULL == list->tail) + { + list->head = block; + } + else + { + list->tail->next = block; + } + list->tail = block; +} + +static void xgi_mem_delete_node(xgi_mem_list_t *list, + xgi_mem_block_t *block) +{ + if (block == list->head) + { + list->head = block->next; + } + if (block == list->tail) + { + list->tail = block->prev; + } + + if (block->prev) + { + block->prev->next = block->next; + } + if (block->next) + { + block->next->prev = block->prev; + } + + block->next = block->prev = NULL; +} +#endif +static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t *info, unsigned long originalSize) +{ + struct list_head *free_list; + xgi_mem_block_t *block, *free_block, *used_block; + + unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; + + XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", originalSize, size); + + if (size == 0) + { + XGI_ERROR("size == 0\n"); + return (NULL); + } + XGI_INFO("max_freesize: 0x%lx \n", xgi_fb_heap->max_freesize); + if (size > xgi_fb_heap->max_freesize) + { + XGI_ERROR("size: 0x%lx is bigger than frame buffer total free size: 0x%lx !\n", + size, xgi_fb_heap->max_freesize); + return (NULL); + } + + free_list = xgi_fb_heap->free_list.next; + + while (free_list != &xgi_fb_heap->free_list) + { + XGI_INFO("free_list: 0x%px \n", free_list); + block = list_entry(free_list, struct xgi_mem_block_s, list); + if (size <= block->size) + { + break; + } + free_list = free_list->next; + } + + if (free_list == &xgi_fb_heap->free_list) + { + XGI_ERROR("Can't allocate %ldk size from frame buffer memory !\n", size/1024); + return (NULL); + } + + free_block = block; + XGI_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; + XGI_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) + { + XGI_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; + } + + xgi_fb_heap->max_freesize -= size; + + list_add(&used_block->list, &xgi_fb_heap->used_list); + + return (used_block); +} + +static xgi_mem_block_t *xgi_mem_free(xgi_info_t *info, unsigned long offset) +{ + struct list_head *free_list, *used_list; + xgi_mem_block_t *used_block = NULL, *block = NULL; + xgi_mem_block_t *prev, *next; + + unsigned long upper; + unsigned long lower; + + used_list = xgi_fb_heap->used_list.next; + while (used_list != &xgi_fb_heap->used_list) + { + block = list_entry(used_list, struct xgi_mem_block_s, list); + if (block->offset == offset) + { + break; + } + used_list = used_list->next; + } + + if (used_list == &xgi_fb_heap->used_list) + { + XGI_ERROR("can't find block: 0x%lx to free!\n", offset); + return (NULL); + } + + used_block = block; + XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + + xgi_fb_heap->max_freesize += used_block->size; + + prev = next = NULL; + upper = used_block->offset + used_block->size; + lower = used_block->offset; + + free_list = xgi_fb_heap->free_list.next; + while (free_list != &xgi_fb_heap->free_list) + { + block = list_entry(free_list, struct xgi_mem_block_s, list); + + if (block->offset == upper) + { + next = block; + } + else if ((block->offset + block->size) == lower) + { + prev = block; + } + free_list = free_list->next; + } + + XGI_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); + XGI_INFO("free node 0x%p\n", next); + kmem_cache_free(xgi_fb_cache_block, next); + kmem_cache_free(xgi_fb_cache_block, used_block); + + next = NULL; + used_block = NULL; + return (prev); + } + + if (prev) + { + prev->size += used_block->size; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_fb_cache_block, used_block); + used_block = NULL; + return (prev); + } + + if (next) + { + next->size += used_block->size; + next->offset = used_block->offset; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_fb_cache_block, used_block); + used_block = NULL; + return (next); + } + + list_add(&used_block->list, &xgi_fb_heap->free_list); + XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + + return (used_block); +} + diff --git a/linux-core/xgi_fb.h b/linux-core/xgi_fb.h new file mode 100644 index 00000000..4b7ec2f2 --- /dev/null +++ b/linux-core/xgi_fb.h @@ -0,0 +1,71 @@ + +/**************************************************************************** + * 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_FB_H_ +#define _XGI_FB_H_ + +typedef struct xgi_mem_block_s { + struct list_head list; + unsigned long offset; + unsigned long size; + atomic_t use_count; +} xgi_mem_block_t; + +typedef struct xgi_mem_heap_s { + struct list_head free_list; + struct list_head used_list; + struct list_head sort_list; + unsigned long max_freesize; + spinlock_t lock; +} xgi_mem_heap_t; + +#if 0 +typedef struct xgi_mem_block_s { + struct xgi_mem_block_s *next; + struct xgi_mem_block_s *prev; + unsigned long offset; + unsigned long size; + atomic_t use_count; +} xgi_mem_block_t; + +typedef struct xgi_mem_list_s { + xgi_mem_block_t *head; + xgi_mem_block_t *tail; +} xgi_mem_list_t; + +typedef struct xgi_mem_heap_s { + xgi_mem_list_t *free_list; + xgi_mem_list_t *used_list; + xgi_mem_list_t *sort_list; + unsigned long max_freesize; + spinlock_t lock; +} xgi_mem_heap_t; +#endif + +#endif + diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h new file mode 100644 index 00000000..f207a4f6 --- /dev/null +++ b/linux-core/xgi_linux.h @@ -0,0 +1,596 @@ + +/**************************************************************************** + * 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_LINUX_H_ +#define _XGI_LINUX_H_ + +#include + +#ifndef LINUX_VERSION_CODE +#include +#endif + +#ifndef KERNEL_VERSION /* pre-2.1.90 didn't have it */ +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +# error "This driver does not support pre-2.4 kernels!" +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) +#define KERNEL_2_4 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +# error "This driver does not support 2.5 kernels!" +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0) +#define KERNEL_2_6 +#else +# error "This driver does not support development kernels!" +#endif + +#if defined (CONFIG_SMP) && !defined (__SMP__) +#define __SMP__ +#endif + +#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) +#define MODVERSIONS +#endif + +#if defined (MODVERSIONS) && !defined (KERNEL_2_6) +#include +#endif + +#include /* printk */ +#include + +#include /* module_init, module_exit */ +#include /* pic_t, size_t, __u32, etc */ +#include /* error codes */ +#include /* circular linked list */ +#include /* NULL, offsetof */ +#include /* wait queues */ + +#include /* kmalloc, kfree, etc */ +#include /* vmalloc, vfree, etc */ + +#include /* poll_wait */ +#include /* mdelay, udelay */ +#include /* rdtsc rdtscl */ + +#include /* suser(), capable() replacement + for_each_task, for_each_process */ +#ifdef for_each_process +#define XGI_SCAN_PROCESS(p) for_each_process(p) +#else +#define XGI_SCAN_PROCESS(p) for_each_task(p) +#endif + +#ifdef KERNEL_2_6 +#include /* module_param() */ +#include /* kernel_locked */ +#include /* flush_tlb(), flush_tlb_all() */ +#include /* page table entry lookup */ +#endif + +#include /* pci_find_class, etc */ +#include /* tasklets, interrupt helpers */ +#include + +#include /* cli, sli, save_flags */ +#include /* ioremap, virt_to_phys */ +#include /* access_ok */ +#include /* PAGE_OFFSET */ +#include /* pte bit definitions */ + +#include +#include +#include + +#ifdef CONFIG_PROC_FS +#include +#endif + +#ifdef CONFIG_DEVFS_FS +#include +#endif + +#ifdef CONFIG_KMOD +#include +#endif + +#ifdef CONFIG_PM +#include +#endif + +#ifdef CONFIG_MTRR +#include +#endif + +#ifdef CONFIG_KDB +#include +#include +#endif + +#if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE) +#define AGPGART +#include +#include +#endif + +#ifndef MAX_ORDER +#ifdef KERNEL_2_4 +#define MAX_ORDER 10 +#endif +#ifdef KERNEL_2_6 +#define MAX_ORDER 11 +#endif +#endif + +#ifndef module_init +#define module_init(x) int init_module(void) { return x(); } +#define module_exit(x) void cleanup_module(void) { x(); } +#endif + +#ifndef minor +#define minor(x) MINOR(x) +#endif + +#ifndef IRQ_HANDLED +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) +#endif + +#if !defined (list_for_each) +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) +#endif + +#ifdef KERNEL_2_4 +#define XGI_PCI_FOR_EACH_DEV(dev) pci_for_each_dev(dev) +#endif +#ifdef KERNEL_2_6 +extern struct list_head pci_devices; /* list of all devices */ +#define XGI_PCI_FOR_EACH_DEV(dev) \ + for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next)) +#endif + +/* + * the following macro causes problems when used in the same module + * as module_param(); undef it so we don't accidentally mix the two + */ +#if defined (KERNEL_2_6) +#undef MODULE_PARM +#endif + +#ifdef EXPORT_NO_SYMBOLS +EXPORT_NO_SYMBOLS; +#endif + +#if defined (KERNEL_2_4) +#define XGI_IS_SUSER() suser() +#define XGI_PCI_DEVICE_NAME(dev) ((dev)->name) +#define XGI_NUM_CPUS() smp_num_cpus +#define XGI_CLI() __cli() +#define XGI_SAVE_FLAGS(eflags) __save_flags(eflags) +#define XGI_RESTORE_FLAGS(eflags) __restore_flags(eflags) +#define XGI_MAY_SLEEP() (!in_interrupt()) +#define XGI_MODULE_PARAMETER(x) MODULE_PARM(x, "i") +#endif + +#if defined (KERNEL_2_6) +#define XGI_IS_SUSER() capable(CAP_SYS_ADMIN) +#define XGI_PCI_DEVICE_NAME(dev) ((dev)->pretty_name) +#define XGI_NUM_CPUS() num_online_cpus() +#define XGI_CLI() local_irq_disable() +#define XGI_SAVE_FLAGS(eflags) local_save_flags(eflags) +#define XGI_RESTORE_FLAGS(eflags) local_irq_restore(eflags) +#define XGI_MAY_SLEEP() (!in_interrupt() && !in_atomic()) +#define XGI_MODULE_PARAMETER(x) module_param(x, int, 0) +#endif + +/* Earlier 2.4.x kernels don't have pci_disable_device() */ +#ifdef XGI_PCI_DISABLE_DEVICE_PRESENT +#define XGI_PCI_DISABLE_DEVICE(dev) pci_disable_device(dev) +#else +#define XGI_PCI_DISABLE_DEVICE(dev) +#endif + +/* common defines */ +#define GET_MODULE_SYMBOL(mod,sym) (const void *) inter_module_get(sym) +#define PUT_MODULE_SYMBOL(sym) inter_module_put((char *) sym) + +#define XGI_GET_PAGE_STRUCT(phys_page) virt_to_page(__va(phys_page)) +#define XGI_VMA_OFFSET(vma) (((vma)->vm_pgoff) << PAGE_SHIFT) +#define XGI_VMA_PRIVATE(vma) ((vma)->vm_private_data) + +#define XGI_DEVICE_NUMBER(x) minor((x)->i_rdev) +#define XGI_IS_CONTROL_DEVICE(x) (minor((x)->i_rdev) == 255) + +#define XGI_PCI_RESOURCE_START(dev, bar) ((dev)->resource[bar].start) +#define XGI_PCI_RESOURCE_SIZE(dev, bar) ((dev)->resource[bar].end - (dev)->resource[bar].start + 1) + +#define XGI_PCI_BUS_NUMBER(dev) (dev)->bus->number +#define XGI_PCI_SLOT_NUMBER(dev) PCI_SLOT((dev)->devfn) + +#ifdef XGI_PCI_GET_CLASS_PRESENT +#define XGI_PCI_DEV_PUT(dev) pci_dev_put(dev) +#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_get_device(vendor,device,from) +#define XGI_PCI_GET_SLOT(bus,devfn) pci_get_slot(pci_find_bus(0,bus),devfn) +#define XGI_PCI_GET_CLASS(class,from) pci_get_class(class,from) +#else +#define XGI_PCI_DEV_PUT(dev) +#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_find_device(vendor,device,from) +#define XGI_PCI_GET_SLOT(bus,devfn) pci_find_slot(bus,devfn) +#define XGI_PCI_GET_CLASS(class,from) pci_find_class(class,from) +#endif + +/* + * acpi support has been back-ported to the 2.4 kernel, but the 2.4 driver + * model is not sufficient for full acpi support. it may work in some cases, + * but not enough for us to officially support this configuration. + */ +#if defined(CONFIG_ACPI) && defined(KERNEL_2_6) +#define XGI_PM_SUPPORT_ACPI +#endif + +#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) +#define XGI_PM_SUPPORT_APM +#endif + + +#if defined(CONFIG_DEVFS_FS) +#if defined(KERNEL_2_6) +typedef void* devfs_handle_t; +#define XGI_DEVFS_REGISTER(_name, _minor) \ + ({ \ + devfs_handle_t __handle = NULL; \ + if (devfs_mk_cdev(MKDEV(XGI_DEV_MAJOR, _minor), \ + S_IFCHR | S_IRUGO | S_IWUGO, _name) == 0) \ + { \ + __handle = (void *) 1; /* XXX Fix me! (boolean) */ \ + } \ + __handle; \ + }) +/* +#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi%d", i) +*/ +#define XGI_DEVFS_REMOVE_CONTROL() devfs_remove("xgi_ctl") +#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi") +#else // defined(KERNEL_2_4) +#define XGI_DEVFS_REGISTER(_name, _minor) \ + ({ \ + devfs_handle_t __handle = devfs_register(NULL, _name, DEVFS_FL_AUTO_DEVNUM, \ + XGI_DEV_MAJOR, _minor, \ + S_IFCHR | S_IRUGO | S_IWUGO, &xgi_fops, NULL); \ + __handle; \ + }) + +#define XGI_DEVFS_REMOVE_DEVICE(i) \ + ({ \ + if (xgi_devfs_handles[i] != NULL) \ + { \ + devfs_unregister(xgi_devfs_handles[i]); \ + } \ + }) +#define XGI_DEVFS_REMOVE_CONTROL() \ + ({ \ + if (xgi_devfs_handles[0] != NULL) \ + { \ + devfs_unregister(xgi_devfs_handles[0]); \ + } \ + }) +#endif /* defined(KERNEL_2_4) */ +#endif /* defined(CONFIG_DEVFS_FS) */ + +#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) +#define XGI_REGISTER_CHRDEV(x...) devfs_register_chrdev(x) +#define XGI_UNREGISTER_CHRDEV(x...) devfs_unregister_chrdev(x) +#else +#define XGI_REGISTER_CHRDEV(x...) register_chrdev(x) +#define XGI_UNREGISTER_CHRDEV(x...) unregister_chrdev(x) +#endif + +#if defined(XGI_REMAP_PFN_RANGE_PRESENT) +#define XGI_REMAP_PAGE_RANGE(from, offset, x...) \ + remap_pfn_range(vma, from, ((offset) >> PAGE_SHIFT), x) +#elif defined(XGI_REMAP_PAGE_RANGE_5) +#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) +#elif defined(XGI_REMAP_PAGE_RANGE_4) +#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(x) +#else +#warning "xgi_configure.sh failed, assuming remap_page_range(5)!" +#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) +#endif + +#if defined(pmd_offset_map) +#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ + { \ + pg_mid_dir = pmd_offset_map(pg_dir, address); \ + } +#define XGI_PMD_UNMAP(pg_mid_dir) \ + { \ + pmd_unmap(pg_mid_dir); \ + } +#else +#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ + { \ + pg_mid_dir = pmd_offset(pg_dir, address); \ + } +#define XGI_PMD_UNMAP(pg_mid_dir) +#endif + +#define XGI_PMD_PRESENT(pg_mid_dir) \ + ({ \ + if ((pg_mid_dir) && (pmd_none(*pg_mid_dir))) \ + { \ + XGI_PMD_UNMAP(pg_mid_dir); \ + pg_mid_dir = NULL; \ + } \ + pg_mid_dir != NULL; \ + }) + +#if defined(pte_offset_atomic) +#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ + { \ + pte = pte_offset_atomic(pg_mid_dir, address); \ + XGI_PMD_UNMAP(pg_mid_dir); \ + } +#define XGI_PTE_UNMAP(pte) \ + { \ + pte_kunmap(pte); \ + } +#elif defined(pte_offset) +#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ + { \ + pte = pte_offset(pg_mid_dir, address); \ + XGI_PMD_UNMAP(pg_mid_dir); \ + } +#define XGI_PTE_UNMAP(pte) +#else +#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ + { \ + pte = pte_offset_map(pg_mid_dir, address); \ + XGI_PMD_UNMAP(pg_mid_dir); \ + } +#define XGI_PTE_UNMAP(pte) \ + { \ + pte_unmap(pte); \ + } +#endif + +#define XGI_PTE_PRESENT(pte) \ + ({ \ + if (pte) \ + { \ + if (!pte_present(*pte)) \ + { \ + XGI_PTE_UNMAP(pte); pte = NULL; \ + } \ + } \ + pte != NULL; \ + }) + +#define XGI_PTE_VALUE(pte) \ + ({ \ + unsigned long __pte_value = pte_val(*pte); \ + XGI_PTE_UNMAP(pte); \ + __pte_value; \ + }) + +#define XGI_PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) / PAGE_SIZE) +#define XGI_MASK_OFFSET(addr) ((addr) & (PAGE_SIZE - 1)) + +#if !defined (pgprot_noncached) +static inline pgprot_t pgprot_noncached(pgprot_t old_prot) + { + pgprot_t new_prot = old_prot; + if (boot_cpu_data.x86 > 3) + new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_PCD); + return new_prot; + } +#endif + +#if defined(XGI_BUILD_XGI_PAT_SUPPORT) && !defined (pgprot_writecombined) +/* Added define for write combining page, only valid if pat enabled. */ +#define _PAGE_WRTCOMB _PAGE_PWT +#define __PAGE_KERNEL_WRTCOMB \ + (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_WRTCOMB | _PAGE_ACCESSED) +#define PAGE_KERNEL_WRTCOMB MAKE_GLOBAL(__PAGE_KERNEL_WRTCOMB) + +static inline pgprot_t pgprot_writecombined(pgprot_t old_prot) + { + pgprot_t new_prot = old_prot; + if (boot_cpu_data.x86 > 3) + { + pgprot_val(old_prot) &= ~(_PAGE_PCD | _PAGE_PWT); + new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_WRTCOMB); + } + return new_prot; + } +#endif + +#if !defined(page_to_pfn) +#define page_to_pfn(page) ((page) - mem_map) +#endif + +#define XGI_VMALLOC(ptr, size) \ + { \ + (ptr) = vmalloc_32(size); \ + } + +#define XGI_VFREE(ptr, size) \ + { \ + vfree((void *) (ptr)); \ + } + +#define XGI_IOREMAP(ptr, physaddr, size) \ + { \ + (ptr) = ioremap(physaddr, size); \ + } + +#define XGI_IOREMAP_NOCACHE(ptr, physaddr, size) \ + { \ + (ptr) = ioremap_nocache(physaddr, size); \ + } + +#define XGI_IOUNMAP(ptr, size) \ + { \ + iounmap(ptr); \ + } + +/* + * only use this because GFP_KERNEL may sleep.. + * GFP_ATOMIC is ok, it won't sleep + */ +#define XGI_KMALLOC(ptr, size) \ + { \ + (ptr) = kmalloc(size, GFP_KERNEL); \ + } + +#define XGI_KMALLOC_ATOMIC(ptr, size) \ + { \ + (ptr) = kmalloc(size, GFP_ATOMIC); \ + } + +#define XGI_KFREE(ptr, size) \ + { \ + kfree((void *) (ptr)); \ + } + +#define XGI_GET_FREE_PAGES(ptr, order) \ + { \ + (ptr) = __get_free_pages(GFP_KERNEL, order); \ + } + +#define XGI_FREE_PAGES(ptr, order) \ + { \ + free_pages(ptr, order); \ + } + +typedef struct xgi_pte_s { + unsigned long phys_addr; + unsigned long virt_addr; +} xgi_pte_t; + +/* + * AMD Athlon processors expose a subtle bug in the Linux + * kernel, that may lead to AGP memory corruption. Recent + * kernel versions had a workaround for this problem, but + * 2.4.20 is the first kernel to address it properly. The + * page_attr API provides the means to solve the problem. + */ +#if defined(XGI_CHANGE_PAGE_ATTR_PRESENT) +static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(xgi_pte_t *page_ptr) + { + struct page *page = virt_to_page(__va(page_ptr->phys_addr)); + change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); + } +static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t *page_ptr) + { + struct page *page = virt_to_page(__va(page_ptr->phys_addr)); + change_page_attr(page, 1, PAGE_KERNEL); + } +#else +#define XGI_SET_PAGE_ATTRIB_UNCACHED(page_list) +#define XGI_SET_PAGE_ATTRIB_CACHED(page_list) +#endif + +#ifdef KERNEL_2_4 +#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) +#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) +#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) +#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) + +#define XGILockPage(page) set_bit(PG_locked, &(page)->flags) +#define XGIUnlockPage(page) clear_bit(PG_locked, &(page)->flags) +#endif + +#ifdef KERNEL_2_6 +/* add for SUSE 9, Jill*/ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4) +#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) +#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) +#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) +#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) +#else +#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->_count) +#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->_count) +#define XGI_PAGE_COUNT(page) atomic_read(&(page)->_count) +#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->_count, v) +#endif +#define XGILockPage(page) SetPageLocked(page) +#define XGIUnlockPage(page) ClearPageLocked(page) +#endif + + +/* + * hide a pointer to struct xgi_info_t in a file-private info + */ + +typedef struct +{ + void *info; + U32 num_events; + spinlock_t fp_lock; + wait_queue_head_t wait_queue; +} xgi_file_private_t; + +#define FILE_PRIVATE(filp) ((filp)->private_data) + +#define XGI_GET_FP(filp) ((xgi_file_private_t *) FILE_PRIVATE(filp)) + +/* for the card devices */ +#define XGI_INFO_FROM_FP(filp) (XGI_GET_FP(filp)->info) + +#ifdef KERNEL_2_0 +#define INODE_FROM_FP(filp) ((filp)->f_inode) +#else +#define INODE_FROM_FP(filp) ((filp)->f_dentry->d_inode) +#endif + +#define XGI_ATOMIC_SET(data,val) atomic_set(&(data), (val)) +#define XGI_ATOMIC_INC(data) atomic_inc(&(data)) +#define XGI_ATOMIC_DEC(data) atomic_dec(&(data)) +#define XGI_ATOMIC_DEC_AND_TEST(data) atomic_dec_and_test(&(data)) +#define XGI_ATOMIC_READ(data) atomic_read(&(data)) + +/* + * lock-related functions that should only be called from this file + */ +#define xgi_init_lock(lock) spin_lock_init(&lock) +#define xgi_lock(lock) spin_lock(&lock) +#define xgi_unlock(lock) spin_unlock(&lock) +#define xgi_down(lock) down(&lock) +#define xgi_up(lock) up(&lock) + +#define xgi_lock_irqsave(lock,flags) spin_lock_irqsave(&lock,flags) +#define xgi_unlock_irqsave(lock,flags) spin_unlock_irqrestore(&lock,flags) + +#endif diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c new file mode 100644 index 00000000..b15c7ecf --- /dev/null +++ b/linux-core/xgi_misc.c @@ -0,0 +1,657 @@ + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_pcie.h" + +void xgi_get_device_info(xgi_info_t *info, xgi_chip_info_t *req) +{ + req->device_id = info->device_id; + req->device_name[0] = 'x'; + req->device_name[1] = 'g'; + req->device_name[2] = '4'; + req->device_name[3] = '7'; + req->vendor_id = info->vendor_id; + req->curr_display_mode = 0; + req->fb_size = info->fb.size; + req->sarea_bus_addr = info->sarea_info.bus_addr; + req->sarea_size = info->sarea_info.size; +} + +void xgi_get_mmio_info(xgi_info_t *info, xgi_mmio_info_t *req) +{ + req->mmioBase = (void *)info->mmio.base; + req->size = info->mmio.size; +} + +void xgi_put_screen_info(xgi_info_t *info, xgi_screen_info_t *req) +{ + info->scrn_info.scrn_start = req->scrn_start; + info->scrn_info.scrn_xres = req->scrn_xres; + info->scrn_info.scrn_yres = req->scrn_yres; + info->scrn_info.scrn_bpp = req->scrn_bpp; + info->scrn_info.scrn_pitch = req->scrn_pitch; + + XGI_INFO("info->scrn_info.scrn_start: 0x%lx" + "info->scrn_info.scrn_xres: 0x%lx" + "info->scrn_info.scrn_yres: 0x%lx" + "info->scrn_info.scrn_bpp: 0x%lx" + "info->scrn_info.scrn_pitch: 0x%lx\n", + info->scrn_info.scrn_start, + info->scrn_info.scrn_xres, + info->scrn_info.scrn_yres, + info->scrn_info.scrn_bpp, + info->scrn_info.scrn_pitch); +} + +void xgi_get_screen_info(xgi_info_t *info, xgi_screen_info_t *req) +{ + req->scrn_start = info->scrn_info.scrn_start; + req->scrn_xres = info->scrn_info.scrn_xres; + req->scrn_yres = info->scrn_info.scrn_yres; + req->scrn_bpp = info->scrn_info.scrn_bpp; + req->scrn_pitch = info->scrn_info.scrn_pitch; + + XGI_INFO("req->scrn_start: 0x%lx" + "req->scrn_xres: 0x%lx" + "req->scrn_yres: 0x%lx" + "req->scrn_bpp: 0x%lx" + "req->scrn_pitch: 0x%lx\n", + req->scrn_start, + req->scrn_xres, + req->scrn_yres, + req->scrn_bpp, + req->scrn_pitch); +} + +void xgi_ge_reset(xgi_info_t *info) +{ + xgi_disable_ge(info); + xgi_enable_ge(info); +} + +void xgi_sarea_info(xgi_info_t *info, xgi_sarea_info_t *req) +{ + info->sarea_info.bus_addr = req->bus_addr; + info->sarea_info.size = req->size; + XGI_INFO("info->sarea_info.bus_addr: 0x%lx" + "info->sarea_info.size: 0x%lx\n", + info->sarea_info.bus_addr, + info->sarea_info.size); +} + +/* + * irq functions + */ +#define STALL_INTERRUPT_RESET_THRESHOLD 0xffff + +static U32 s_invalid_begin = 0; + +BOOL xgi_ge_irq_handler(xgi_info_t *info) +{ + volatile U8 *mmio_vbase = info->mmio.vbase; + volatile U32 *ge_3d_status = (volatile U32 *)(mmio_vbase + 0x2800); + U32 int_status = ge_3d_status[4]; // interrupt status + U32 auto_reset_count = 0; + BOOL is_support_auto_reset = FALSE; + + // Check GE on/off + if (0 == (0xffffc0f0 & int_status)) + { + U32 old_ge_status = ge_3d_status[0x00]; + 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 (TRUE == is_support_auto_reset) + { + BOOL is_wrong_signal = FALSE; + static U32 last_int_tick_low, last_int_tick_high; + static U32 new_int_tick_low, new_int_tick_high; + static U32 continoue_int_count = 0; + // OE II is busy. + while (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)) + { + is_wrong_signal = TRUE; + break; + } + // Check RO channel + *(mmio_vbase + 0x235c) = 0x83; + check = *((volatile U16*)(mmio_vbase + 0x2360)); + if ((check & 0x0f) != ((check & 0xf0) >> 4)) + { + is_wrong_signal = TRUE; + break; + } + // Check RW channel + *(mmio_vbase + 0x235c) = 0x88; + check = *((volatile U16*)(mmio_vbase + 0x2360)); + if ((check & 0x0f) != ((check & 0xf0) >> 4)) + { + is_wrong_signal = TRUE; + break; + } + // Check RO channel outstanding + *(mmio_vbase + 0x235c) = 0x8f; + check = *((volatile U16*)(mmio_vbase + 0x2360)); + if (0 != (check & 0x3ff)) + { + is_wrong_signal = TRUE; + break; + } + // Check RW channel outstanding + *(mmio_vbase + 0x235c) = 0x90; + check = *((volatile U16*)(mmio_vbase + 0x2360)); + if (0 != (check & 0x3ff)) + { + is_wrong_signal = TRUE; + break; + } + // No pending PCIE request. GE stall. + break; + } + + if (is_wrong_signal) + { + // Nothing but skip. + } + else if (0 == continoue_int_count++) + { + rdtsc(last_int_tick_low, last_int_tick_high); + } + else + { + rdtscl(new_int_tick_low); + if ((new_int_tick_low - last_int_tick_low) > STALL_INTERRUPT_RESET_THRESHOLD) + { + continoue_int_count = 0; + } + else if (continoue_int_count >= 3) + { + continoue_int_count = 0; + + // GE Hung up, need reset. + XGI_INFO("Reset GE!\n"); + + *(mmio_vbase + 0xb057) = 8; + int time_out = 0xffff; + while (0 != (ge_3d_status[0x00] & 0xf0000000)) + { + while (0 != ((--time_out) & 0xfff)); + if (0 == time_out) + { + XGI_INFO("Can not reset back 0x%lx!\n", ge_3d_status[0x00]); + *(mmio_vbase + 0xb057) = 0; + // Have to use 3x5.36 to reset. + // Save and close dynamic gating + U8 old_3ce = *(mmio_vbase + 0x3ce); + *(mmio_vbase + 0x3ce) = 0x2a; + U8 old_3cf = *(mmio_vbase + 0x3cf); + *(mmio_vbase + 0x3cf) = old_3cf & 0xfe; + // Reset GE + U8 old_index = *(mmio_vbase + 0x3d4); + *(mmio_vbase + 0x3d4) = 0x36; + U8 old_36 = *(mmio_vbase + 0x3d5); + *(mmio_vbase + 0x3d5) = old_36 | 0x10; + while (0 != ((--time_out) & 0xfff)); + *(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; + + // Increase Reset counter + auto_reset_count++; + } + } + } + return TRUE; + } + 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(xgi_info_t *info) +{ + BOOL ret = FALSE; + U8 *mmio_vbase = info->mmio.vbase; + U32 device_status = 0; + U32 hw_status = 0; + U8 save_3ce = bReadReg(0x3ce); + + + if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened + { + U8 op3cf_3d; + U8 op3cf_37; + + // What happened? + op3cf_37 = bIn3cf(0x37); + +#if 0 + if (op3cf_37 & 0x04) + device_status |= GDEVST_CONNECT; + else + device_status &= ~GDEVST_CONNECT; + + device_status |= GDEVST_DEVICE_CHANGED; + hw_status |= HWST_DEVICE_CHANGED; +#endif + // Clear CRT interrupt + op3cf_3d = bIn3cf(0x3d); + bOut3cf(0x3d, (op3cf_3d | 0x04)); + bOut3cf(0x3d, (op3cf_3d & ~0x04)); + ret = TRUE; + } + bWriteReg(0x3ce, save_3ce); + + return (ret); +} + +BOOL xgi_dvi_irq_handler(xgi_info_t *info) +{ + BOOL ret = FALSE; + U8 *mmio_vbase = info->mmio.vbase; + U32 device_status = 0; + U32 hw_status = 0; + U8 save_3ce = bReadReg(0x3ce); + + if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened + { + U8 op3cf_39; + U8 op3cf_37; + U8 op3x5_5a; + U8 save_3x4 = bReadReg(0x3d4);; + + // What happened? + op3cf_37 = bIn3cf(0x37); +#if 0 + //Also update our internal flag + if (op3cf_37 & 0x10) // Second Monitor plugged In + { + device_status |= GDEVST_CONNECT; + //Because currenly we cannot determine if DVI digital + //or DVI analog is connected according to DVI interrupt + //We should still call BIOS to check it when utility ask us + device_status &= ~GDEVST_CHECKED; + } + else + { + device_status &= ~GDEVST_CONNECT; + } +#endif + //Notify BIOS that DVI plug/unplug happened + op3x5_5a = bIn3x5(0x5a); + bOut3x5(0x5a, op3x5_5a & 0xf7); + + bWriteReg(0x3d4, save_3x4); + + //device_status |= GDEVST_DEVICE_CHANGED; + //hw_status |= HWST_DEVICE_CHANGED; + + // Clear DVI interrupt + op3cf_39 = bIn3cf(0x39); + bOut3c5(0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0 + bOut3c5(0x39, (op3cf_39 | 0x01 )); //Set 3cf.39 bit 0 to 1 + + ret = TRUE; + } + bWriteReg(0x3ce, save_3ce); + + return (ret); +} + +void xgi_dump_register(xgi_info_t *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 = bIn3c5(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 = bIn3x5(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 = bIn3cf(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 = bReadReg(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 = bReadReg(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 = bReadReg(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 = bReadReg(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 = bReadReg(0x2800 + i*0x10 + j); + printk("%3x", temp); + } + printk("\r\n"); + } +} + +void xgi_restore_registers(xgi_info_t *info) +{ + bOut3x5(0x13, 0); + bOut3x5(0x8b, 2); +} + +void xgi_waitfor_pci_idle(xgi_info_t *info) +{ +#define WHOLD_GE_STATUS 0x2800 +#define IDLE_MASK ~0x90200000 + + int idleCount = 0; + while(idleCount < 5) + { + if (dwReadReg(WHOLD_GE_STATUS) & IDLE_MASK) + { + idleCount = 0; + } + else + { + idleCount ++; + } + } +} + +int xgi_get_cpu_id(struct cpu_info_s *arg) +{ + int op = arg->_eax; + __asm__("cpuid" + : "=a" (arg->_eax), + "=b" (arg->_ebx), + "=c" (arg->_ecx), + "=d" (arg->_edx) + : "0" (op)); + + XGI_INFO("opCode = 0x%x, eax = 0x%x, ebx = 0x%x, ecx = 0x%x, edx = 0x%x \n", + op, arg->_eax, arg->_ebx, arg->_ecx, arg->_edx); +} + +/*memory collect function*/ +extern struct list_head xgi_mempid_list; +void xgi_mem_collect(xgi_info_t *info, unsigned int *pcnt) +{ + xgi_mem_pid_t *mempid_block; + struct list_head *mempid_list; + struct task_struct *p,*find; + unsigned int cnt = 0; + + mempid_list = xgi_mempid_list.next; + + while (mempid_list != &xgi_mempid_list) + { + mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); + mempid_list = mempid_list->next; + + find = NULL; + XGI_SCAN_PROCESS(p) + { + if (p->pid == mempid_block->pid) + { + XGI_INFO("[!]Find active pid:%ld state:%ld location:%d addr:0x%lx! \n", mempid_block->pid, p->state, mempid_block->location, mempid_block->bus_addr); + find = p; + if (mempid_block->bus_addr == 0xFFFFFFFF) + ++cnt; + break; + } + } + if (!find) + { + if (mempid_block->location == LOCAL) + { + XGI_INFO("Memory ProcessID free fb and delete one block pid:%ld addr:0x%lx successfully! \n", mempid_block->pid, mempid_block->bus_addr); + xgi_fb_free(info, mempid_block->bus_addr); + } + else if (mempid_block->bus_addr != 0xFFFFFFFF) + { + XGI_INFO("Memory ProcessID free pcie and delete one block pid:%ld addr:0x%lx successfully! \n", mempid_block->pid, mempid_block->bus_addr); + xgi_pcie_free(info, mempid_block->bus_addr); + } + else + { + /*only delete the memory block*/ + list_del(&mempid_block->list); + XGI_INFO("Memory ProcessID delete one pcie block pid:%ld successfully! \n", mempid_block->pid); + kfree(mempid_block); + } + } + } + *pcnt = cnt; +} diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h new file mode 100644 index 00000000..ac4daaa1 --- /dev/null +++ b/linux-core/xgi_misc.h @@ -0,0 +1,49 @@ + +/**************************************************************************** + * 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(xgi_info_t *info); +extern void xgi_get_device_info(xgi_info_t *info, xgi_chip_info_t * req); +extern void xgi_get_mmio_info(xgi_info_t *info, xgi_mmio_info_t *req); +extern void xgi_get_screen_info(xgi_info_t *info, xgi_screen_info_t *req); +extern void xgi_put_screen_info(xgi_info_t *info, xgi_screen_info_t *req); +extern void xgi_ge_reset(xgi_info_t *info); +extern void xgi_sarea_info(xgi_info_t *info, xgi_sarea_info_t *req); +extern int xgi_get_cpu_id(struct cpu_info_s *arg); + +extern void xgi_restore_registers(xgi_info_t *info); +extern BOOL xgi_ge_irq_handler(xgi_info_t *info); +extern BOOL xgi_crt_irq_handler(xgi_info_t *info); +extern BOOL xgi_dvi_irq_handler(xgi_info_t *info); +extern void xgi_waitfor_pci_idle(xgi_info_t *info); + + +#endif diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c new file mode 100644 index 00000000..62e2323f --- /dev/null +++ b/linux-core/xgi_pcie.c @@ -0,0 +1,1060 @@ + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_pcie.h" +#include "xgi_misc.h" + +static xgi_pcie_heap_t *xgi_pcie_heap = NULL; +static kmem_cache_t *xgi_pcie_cache_block = NULL; +static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; +static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; +static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; +extern struct list_head xgi_mempid_list; + +static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) +{ + struct page *page; + unsigned long page_addr = 0; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + + if (page_addr == 0UL) + { + XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", + page_count); + return 0; + } + + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) + { + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + } + + XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", + page_count, page_order, page_addr); + return page_addr; +} + +static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) +{ + struct page *page; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) + { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + + free_pages(page_addr, page_order); +} + +static int xgi_pcie_lut_init(xgi_info_t *info) +{ + unsigned char *page_addr = NULL; + unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; + unsigned long count = 0; + u8 temp = 0; + + /* Jong 06/06/2006 */ + unsigned long pcie_aperture_size; + + info->pcie.size = 128 * 1024 * 1024; + + /* Get current FB aperture size */ + temp = In3x5(0x27); + XGI_INFO("In3x5(0x27): 0x%x \n", temp); + + if (temp & 0x01) /* 256MB; Jong 06/05/2006; 0x10000000 */ + { + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size=256 * 1024 * 1024; + /* info->pcie.base = 256 * 1024 * 1024; */ /* pcie base is different from fb base */ + } + else /* 128MB; Jong 06/05/2006; 0x08000000 */ + { + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size=128 * 1024 * 1024; + /* info->pcie.base = 128 * 1024 * 1024; */ + } + + /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ + /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ + /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ + /* info->pcie.base=ioremap(0x0F000000, 0x10000000); */ /* Cause system hang */ + info->pcie.base=pcie_aperture_size; /* works */ + /* info->pcie.base=info->fb.base + info->fb.size; */ /* System hang */ + /* info->pcie.base=128 * 1024 * 1024;*/ /* System hang */ + + XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); + + + /* Get current lookup table page size */ + temp = bReadReg(0xB00C); + if (temp & 0x04) /* 8KB */ + { + info->lutPageSize = 8 * 1024; + } + else /* 4KB */ + { + info->lutPageSize = 4 * 1024; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + +#if 0 + /* Get current lookup table location */ + temp = bReadReg(0xB00C); + if (temp & 0x02) /* LFB */ + { + info->isLUTInLFB = TRUE; + /* Current we only support lookup table in LFB */ + temp &= 0xFD; + bWriteReg(0xB00C, temp); + info->isLUTInLFB = FALSE; + } + else /* SFB */ + { + info->isLUTInLFB = FALSE; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + + /* Get current SDFB page size */ + temp = bReadReg(0xB00C); + if (temp & 0x08) /* 8MB */ + { + info->sdfbPageSize = 8 * 1024 * 1024; + } + else /* 4MB */ + { + info->sdfbPageSize = 4 * 1024 * 1024; + } +#endif + pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; + + /* + * Allocate memory for PCIE GART table; + */ + lutEntryNum = pciePageCount; + lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; + + /* get page_order base on page_count */ + count = lutPageCount; + for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder); + + if ((lutPageCount << 1) == (1 << lutPageOrder)) + { + lutPageOrder -= 1; + } + + XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", + lutEntryNum, lutPageCount, lutPageOrder); + + info->lutPageOrder = lutPageOrder; + page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); + + if (!page_addr) + { + XGI_ERROR("cannot allocate PCIE lut page!\n"); + goto fail; + } + info->lut_base = (unsigned long *)page_addr; + + XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", + page_addr, virt_to_phys(page_addr)); + + XGI_INFO("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", + info->lut_base, __pa(info->lut_base), info->lutPageOrder); + + /* + * clean all PCIE GART Entry + */ + memset(page_addr, 0, PAGE_SIZE << lutPageOrder); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ( "wbinvd" ::: "memory" ); +#else + mb(); +#endif + + /* Set GART in SFB */ + bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); + /* Set GART base address to HW */ + dwWriteReg(0xB034, __pa(info->lut_base)); + + return 1; +fail: + return 0; +} + +static void xgi_pcie_lut_cleanup(xgi_info_t *info) +{ + if (info->lut_base) + { + XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", + info->lut_base, info->lutPageOrder); + xgi_pcie_lut_free((unsigned long)info->lut_base, info->lutPageOrder); + info->lut_base = NULL; + } +} + +static xgi_pcie_block_t *xgi_pcie_new_node(void) +{ + xgi_pcie_block_t *block = (xgi_pcie_block_t *)kmem_cache_alloc(xgi_pcie_cache_block, GFP_KERNEL); + if (block == NULL) + { + return NULL; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = 0; /* The block size. */ + block->bus_addr = 0; /* CPU access address/bus address */ + block->hw_addr = 0; /* GE access address */ + block->page_count = 0; + block->page_order = 0; + block->page_block = NULL; + block->page_table = NULL; + block->owner = PCIE_INVALID; + + return block; +} + +static void xgi_pcie_block_stuff_free(xgi_pcie_block_t *block) +{ + struct page *page; + xgi_page_block_t *page_block = block->page_block; + xgi_page_block_t *free_block; + unsigned long page_count = 0; + int i; + + //XGI_INFO("block->page_block: 0x%p \n", block->page_block); + while (page_block) + { + page_count = page_block->page_count; + + page = virt_to_page(page_block->virt_addr); + for (i = 0; i < page_count; i++, page++) + { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + free_pages(page_block->virt_addr, page_block->page_order); + + page_block->phys_addr = 0; + page_block->virt_addr = 0; + page_block->page_count = 0; + page_block->page_order = 0; + + free_block = page_block; + page_block = page_block->next; + //XGI_INFO("free free_block: 0x%p \n", free_block); + kfree(free_block); + free_block = NULL; + } + + if (block->page_table) + { + //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); + kfree(block->page_table); + block->page_table = NULL; + } +} + +int xgi_pcie_heap_init(xgi_info_t *info) +{ + xgi_pcie_block_t *block; + + if (!xgi_pcie_lut_init(info)) + { + XGI_ERROR("xgi_pcie_lut_init failed\n"); + return 0; + } + + xgi_pcie_heap = (xgi_pcie_heap_t *)kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); + if(!xgi_pcie_heap) + { + XGI_ERROR("xgi_pcie_heap alloc failed\n"); + goto fail1; + } + INIT_LIST_HEAD(&xgi_pcie_heap->free_list); + INIT_LIST_HEAD(&xgi_pcie_heap->used_list); + INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); + + xgi_pcie_heap->max_freesize = info->pcie.size; + + xgi_pcie_cache_block = kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (NULL == xgi_pcie_cache_block) + { + XGI_ERROR("Fail to creat xgi_pcie_block\n"); + goto fail2; + } + + block = (xgi_pcie_block_t *)xgi_pcie_new_node(); + if (!block) + { + XGI_ERROR("xgi_pcie_new_node failed\n"); + goto fail3; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = info->pcie.size; + + list_add(&block->list, &xgi_pcie_heap->free_list); + + XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", block->offset, block->size); + return 1; +fail3: + if (xgi_pcie_cache_block) + { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } + +fail2: + if(xgi_pcie_heap) + { + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } +fail1: + xgi_pcie_lut_cleanup(info); + return 0; +} + +void xgi_pcie_heap_check(void) +{ + struct list_head *useList, *temp; + xgi_pcie_block_t *block; + unsigned int ownerIndex; + char *ownerStr[6] = {"2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE"}; + + if (xgi_pcie_heap) + { + useList = &xgi_pcie_heap->used_list; + temp = useList->next; + XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); + while (temp != useList) + { + block = list_entry(temp, struct xgi_pcie_block_s, list); + if (block->owner == PCIE_2D) + ownerIndex = 0; + else if (block->owner > PCIE_3D_TEXTURE || block->owner < PCIE_2D || block->owner < PCIE_3D) + ownerIndex = 5; + else + ownerIndex = block->owner - PCIE_3D + 1; + XGI_INFO("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", + ownerStr[ownerIndex], block->offset, block->size); + temp = temp->next; + } + + } +} + + +void xgi_pcie_heap_cleanup(xgi_info_t *info) +{ + struct list_head *free_list, *temp; + xgi_pcie_block_t *block; + int j; + + xgi_pcie_lut_cleanup(info); + XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); + + if (xgi_pcie_heap) + { + free_list = &xgi_pcie_heap->free_list; + for (j = 0; j < 3; j++, free_list++) + { + temp = free_list->next; + + while (temp != free_list) + { + block = list_entry(temp, struct xgi_pcie_block_s, list); + XGI_INFO("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + j, block->offset, block->size); + xgi_pcie_block_stuff_free(block); + block->bus_addr = 0; + block->hw_addr = 0; + + temp = temp->next; + //XGI_INFO("No. %d free block: 0x%p \n", j, block); + kmem_cache_free(xgi_pcie_cache_block, block); + block = NULL; + } + } + + XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } + + if (xgi_pcie_cache_block) + { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } +} + + +static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t *info, + unsigned long originalSize, + enum PcieOwner owner) +{ + struct list_head *free_list; + xgi_pcie_block_t *block, *used_block, *free_block; + xgi_page_block_t *page_block, *prev_page_block; + struct page *page; + unsigned long page_order = 0, count = 0, index =0; + unsigned long page_addr = 0; + unsigned long *lut_addr = NULL; + unsigned long lut_id = 0; + unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; + int i, j, page_count = 0; + int temp = 0; + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); + XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", originalSize, size); + + if (owner == PCIE_3D) + { + if (xgi_pcie_vertex_block) + { + XGI_INFO("PCIE Vertex has been created, return directly.\n"); + return xgi_pcie_vertex_block; + } + } + + if (owner == PCIE_3D_CMDLIST) + { + if (xgi_pcie_cmdlist_block) + { + XGI_INFO("PCIE Cmdlist has been created, return directly.\n"); + return xgi_pcie_cmdlist_block; + } + } + + if (owner == PCIE_3D_SCRATCHPAD) + { + if (xgi_pcie_scratchpad_block) + { + XGI_INFO("PCIE Scratchpad has been created, return directly.\n"); + return xgi_pcie_scratchpad_block; + } + } + + if (size == 0) + { + XGI_ERROR("size == 0 \n"); + return (NULL); + } + + XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); + if (size > xgi_pcie_heap->max_freesize) + { + XGI_ERROR("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", + size, xgi_pcie_heap->max_freesize); + return (NULL); + } + + /* Jong 05/30/2006; find next free list which has enough space*/ + free_list = xgi_pcie_heap->free_list.next; + while (free_list != &xgi_pcie_heap->free_list) + { + //XGI_INFO("free_list: 0x%px \n", free_list); + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (size <= block->size) + { + break; + } + free_list = free_list->next; + } + + if (free_list == &xgi_pcie_heap->free_list) + { + XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", size/1024); + return (NULL); + } + + free_block = block; + XGI_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; + XGI_INFO("size==free_block->size: free_block = 0x%p\n", free_block); + list_del(&free_block->list); + } + else + { + used_block = xgi_pcie_new_node(); + if (used_block == NULL) + { + return NULL; + } + + if (used_block == free_block) + { + XGI_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; + } + + xgi_pcie_heap->max_freesize -= size; + + used_block->bus_addr = info->pcie.base + used_block->offset; + used_block->hw_addr = info->pcie.base + used_block->offset; + used_block->page_count = page_count = size / PAGE_SIZE; + + /* get page_order base on page_count */ + for (used_block->page_order = 0; page_count; page_count >>= 1) + { + ++used_block->page_order; + } + + if ((used_block->page_count << 1) == (1 << used_block->page_order)) + { + used_block->page_order--; + } + XGI_INFO("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", + used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr, used_block->page_count, used_block->page_order); + + used_block->page_block = NULL; + //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); + //if (!used_block->page_block) return NULL; + //used_block->page_block->next = NULL; + + used_block->page_table = (xgi_pte_t *)kmalloc(sizeof(xgi_pte_t) * used_block->page_count, GFP_KERNEL); + if (used_block->page_table == NULL) + { + goto fail; + } + + lut_id = (used_block->offset >> PAGE_SHIFT); + lut_addr = info->lut_base; + lut_addr += lut_id; + XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); + + /* alloc free pages from system */ + page_count = used_block->page_count; + page_block = used_block->page_block; + prev_page_block = used_block->page_block; + for (i = 0; page_count > 0; i++) + { + /* if size is bigger than 2M bytes, it should be split */ + if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) + { + page_order = XGI_PCIE_ALLOC_MAX_ORDER; + } + else + { + count = page_count; + for (page_order = 0; count; count >>= 1, ++page_order); + + if ((page_count << 1) == (1 << page_order)) + { + page_order -= 1; + } + } + + count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", page_addr); + + if (!page_addr) + { + XGI_ERROR("No: %d :Can't get free pages: 0x%lx from system memory !\n", + i, count); + goto fail; + } + + /* Jong 05/30/2006; test */ + memset((unsigned char *)page_addr, 0xFF, PAGE_SIZE << page_order); + /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ + + if (page_block == NULL) + { + page_block = (xgi_page_block_t *)kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); + if (!page_block) + { + XGI_ERROR("Can't get memory for page_block! \n"); + goto fail; + } + } + + if (prev_page_block == NULL) + { + used_block->page_block = page_block; + prev_page_block = page_block; + } + else + { + prev_page_block->next = page_block; + prev_page_block = page_block; + } + + page_block->next = NULL; + page_block->phys_addr = __pa(page_addr); + page_block->virt_addr = page_addr; + page_block->page_count = count; + page_block->page_order = page_order; + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", page_block->phys_addr); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", page_block->virt_addr); + + page = virt_to_page(page_addr); + + //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" + // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", + // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); + + for (j = 0 ; j < count; j++, page++, lut_addr++) + { + used_block->page_table[index + j].phys_addr = __pa(page_address(page)); + used_block->page_table[index + j].virt_addr = (unsigned long)page_address(page); + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", used_block->page_table[index + j].phys_addr); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", used_block->page_table[index + j].virt_addr); + + *lut_addr = __pa(page_address(page)); + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + + if (temp) + { + XGI_INFO("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", + __pa(page_address(page)), lut_addr, j, *lut_addr); + temp--; + } + } + + page_block = page_block->next; + page_count -= count; + index += count; + temp = 0; + } + + used_block->owner = owner; + list_add(&used_block->list, &xgi_pcie_heap->used_list); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ( "wbinvd" ::: "memory" ); +#else + mb(); +#endif + + /* Flush GART Table */ + bWriteReg(0xB03F, 0x40); + bWriteReg(0xB03F, 0x00); + + if (owner == PCIE_3D) + { + xgi_pcie_vertex_block = used_block; + } + + if (owner == PCIE_3D_CMDLIST) + { + xgi_pcie_cmdlist_block = used_block; + } + + if (owner == PCIE_3D_SCRATCHPAD) + { + xgi_pcie_scratchpad_block = used_block; + } + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); + return (used_block); + +fail: + xgi_pcie_block_stuff_free(used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + return NULL; +} + +static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t *info, unsigned long offset) +{ + struct list_head *free_list, *used_list; + xgi_pcie_block_t *used_block, *block = NULL; + xgi_pcie_block_t *prev, *next; + unsigned long upper, lower; + + used_list = xgi_pcie_heap->used_list.next; + while (used_list != &xgi_pcie_heap->used_list) + { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + if (block->offset == offset) + { + break; + } + used_list = used_list->next; + } + + if (used_list == &xgi_pcie_heap->used_list) + { + XGI_ERROR("can't find block: 0x%lx to free!\n", offset); + return (NULL); + } + + used_block = block; + XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", + used_block, used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr); + + xgi_pcie_block_stuff_free(used_block); + + /* update xgi_pcie_heap */ + xgi_pcie_heap->max_freesize += used_block->size; + + prev = next = NULL; + upper = used_block->offset + used_block->size; + lower = used_block->offset; + + free_list = xgi_pcie_heap->free_list.next; + + while (free_list != &xgi_pcie_heap->free_list) + { + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (block->offset == upper) + { + next = block; + } + else if ((block->offset + block->size) == lower) + { + prev = block; + } + free_list = free_list->next; + } + + XGI_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); + XGI_INFO("free node 0x%p\n", next); + kmem_cache_free(xgi_pcie_cache_block, next); + kmem_cache_free(xgi_pcie_cache_block, used_block); + next = NULL; + used_block = NULL; + return (prev); + } + + if (prev) + { + prev->size += used_block->size; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (prev); + } + + if (next) + { + next->size += used_block->size; + next->offset = used_block->offset; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (next); + } + + used_block->bus_addr = 0; + used_block->hw_addr = 0; + used_block->page_count = 0; + used_block->page_order = 0; + list_add(&used_block->list, &xgi_pcie_heap->free_list); + XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + return (used_block); +} + +void xgi_pcie_alloc(xgi_info_t *info, unsigned long size, + enum PcieOwner owner, xgi_mem_alloc_t *alloc) +{ + xgi_pcie_block_t *block; + xgi_mem_pid_t *mempid_block; + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_alloc(info, size, owner); + xgi_up(info->pcie_sem); + + if (block == NULL) + { + alloc->location = INVALID; + alloc->size = 0; + alloc->bus_addr = 0; + alloc->hw_addr = 0; + XGI_ERROR("PCIE RAM allocation failed\n"); + } + else + { + XGI_INFO("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", + block->offset, block->bus_addr); + alloc->location = NON_LOCAL; + alloc->size = block->size; + alloc->bus_addr = block->bus_addr; + alloc->hw_addr = block->hw_addr; + + /* + manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. + PCIE_3D request means a opengl process created. + PCIE_3D_TEXTURE request means texture cannot alloc from fb. + */ + if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) + { + mempid_block = kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + if (!mempid_block) + XGI_ERROR("mempid_block alloc failed\n"); + mempid_block->location = NON_LOCAL; + if (owner == PCIE_3D) + mempid_block->bus_addr = 0xFFFFFFFF;/*xgi_pcie_vertex_block has the address*/ + else + mempid_block->bus_addr = alloc->bus_addr; + mempid_block->pid = alloc->pid; + + XGI_INFO("Memory ProcessID add one pcie block pid:%ld successfully! \n", mempid_block->pid); + list_add(&mempid_block->list, &xgi_mempid_list); + } + } +} + +void xgi_pcie_free(xgi_info_t *info, unsigned long bus_addr) +{ + xgi_pcie_block_t *block; + unsigned long offset = bus_addr - info->pcie.base; + xgi_mem_pid_t *mempid_block; + xgi_mem_pid_t *mempid_freeblock = NULL; + struct list_head *mempid_list; + char isvertex = 0; + int processcnt; + + if (xgi_pcie_vertex_block && xgi_pcie_vertex_block->bus_addr == bus_addr) + isvertex = 1; + + if (isvertex) + { + /*check is there any other process using vertex*/ + processcnt = 0; + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) + { + mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) + { + ++processcnt; + } + mempid_list = mempid_list->next; + } + if (processcnt > 1) + { + return; + } + } + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_free(info, offset); + xgi_up(info->pcie_sem); + + if (block == NULL) + { + XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); + } + + if (isvertex) + xgi_pcie_vertex_block = NULL; + + /* manage mempid */ + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) + { + mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) + { + mempid_freeblock = mempid_block; + break; + } + mempid_list = mempid_list->next; + } + if (mempid_freeblock) + { + list_del(&mempid_freeblock->list); + XGI_INFO("Memory ProcessID delete one pcie block pid:%ld successfully! \n", mempid_freeblock->pid); + kfree(mempid_freeblock); + } +} + +/* + * given a bus address, fid the pcie mem block + * uses the bus address as the key. + */ +void *xgi_find_pcie_block(xgi_info_t *info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + int i; + + used_list = xgi_pcie_heap->used_list.next; + + while (used_list != &xgi_pcie_heap->used_list) + { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + + if (block->bus_addr == address) + { + return block; + } + + if (block->page_table) + { + for (i = 0; i < block->page_count; i++) + { + unsigned long offset = block->bus_addr; + if ( (address >= offset) && (address < (offset + PAGE_SIZE))) + { + return block; + } + } + } + used_list = used_list->next; + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + + return NULL; +} + +/* + address -- GE HW address + return -- CPU virtual address + + assume the CPU VAddr is continuous in not the same block +*/ +void *xgi_find_pcie_virt(xgi_info_t *info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + unsigned long offset_in_page; + unsigned long loc_in_pagetable; + void * ret; + + XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); + + used_list = xgi_pcie_heap->used_list.next; + XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); + + offset_in_page = address & (PAGE_SIZE-1); + XGI_INFO("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", address, PAGE_SIZE-1, offset_in_page); + + while (used_list != &xgi_pcie_heap->used_list) + { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + XGI_INFO("Jong_05292006-block=0x%px\n", block); + XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", block->hw_addr); + XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); + + if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) + { + loc_in_pagetable = (address - block->hw_addr) >> PAGE_SHIFT; + ret = (void*)(block->page_table[loc_in_pagetable].virt_addr + offset_in_page); + + XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); + XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", loc_in_pagetable); + XGI_INFO("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", block->page_table[loc_in_pagetable].virt_addr); + XGI_INFO("Jong_05292006-offset_in_page=%d\n", offset_in_page); + XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", ret); + + return ret ; + } + else + { + XGI_INFO("Jong_05292006-used_list = used_list->next;\n"); + used_list = used_list->next; + } + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + return NULL; +} + + +void xgi_read_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) +{ + +} + +void xgi_write_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) +{ +} + +/* + address -- GE hw address +*/ +void xgi_test_rwinkernel(xgi_info_t *info, unsigned long address) +{ + unsigned long * virtaddr = 0; + if (address == 0) + { + XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); + return; + } + + virtaddr = (unsigned long *) xgi_find_pcie_virt(info, address); + + XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); + XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); + XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); + if (virtaddr != NULL) + { + *virtaddr = 0x00f00fff; + } + + XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); +} + diff --git a/linux-core/xgi_pcie.h b/linux-core/xgi_pcie.h new file mode 100644 index 00000000..cd5f85b8 --- /dev/null +++ b/linux-core/xgi_pcie.h @@ -0,0 +1,73 @@ + +/**************************************************************************** + * 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_PCIE_H_ +#define _XGI_PCIE_H_ + +#ifndef XGI_PCIE_ALLOC_MAX_ORDER +#define XGI_PCIE_ALLOC_MAX_ORDER 1 /* 8K in Kernel 2.4.* */ +#endif + +typedef struct xgi_page_block_s { + struct xgi_page_block_s *next; + unsigned long phys_addr; + unsigned long virt_addr; + unsigned long page_count; + unsigned long page_order; +} xgi_page_block_t; + +typedef struct xgi_pcie_block_s { + struct list_head list; + unsigned long offset; /* block's offset in pcie memory, begin from 0 */ + unsigned long size; /* The block size. */ + unsigned long bus_addr; /* CPU access address/bus address */ + unsigned long hw_addr; /* GE access address */ + + unsigned long page_count; + unsigned long page_order; + xgi_page_block_t *page_block; + xgi_pte_t *page_table; /* list of physical pages allocated */ + + atomic_t use_count; + enum PcieOwner owner; + unsigned long processID; +} xgi_pcie_block_t; + +typedef struct xgi_pcie_list_s { + xgi_pcie_block_t *head; + xgi_pcie_block_t *tail; +} xgi_pcie_list_t; + +typedef struct xgi_pcie_heap_s { + struct list_head free_list; + struct list_head used_list; + struct list_head sort_list; + unsigned long max_freesize; +} xgi_pcie_heap_t; + +#endif diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h new file mode 100644 index 00000000..18448139 --- /dev/null +++ b/linux-core/xgi_regs.h @@ -0,0 +1,410 @@ + +/**************************************************************************** + * 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_ + +#ifndef XGI_MMIO + #define XGI_MMIO 1 +#endif + +#if XGI_MMIO +#define OUTB(port, value) writeb(value, info->mmio.vbase + port) +#define INB(port) readb(info->mmio.vbase + port) +#define OUTW(port, value) writew(value, info->mmio.vbase + port) +#define INW(port) readw(info->mmio.vbase + port) +#define OUTDW(port, value) writel(value, info->mmio.vbase + port) +#define INDW(port) readl(info->mmio.vbase + port) +#else +#define OUTB(port, value) outb(value, port) +#define INB(port) inb(port) +#define OUTW(port, value) outw(value, port) +#define INW(port) inw(port) +#define OUTDW(port, value) outl(value, port) +#define INDW(port) inl(port) +#endif + +/* Hardware access functions */ +static inline void OUT3C5B(xgi_info_t *info, u8 index, u8 data) +{ + OUTB(0x3C4, index); + OUTB(0x3C5, data); +} + +static inline void OUT3X5B(xgi_info_t *info, u8 index, u8 data) +{ + OUTB(0x3D4, index); + OUTB(0x3D5, data); +} + +static inline void OUT3CFB(xgi_info_t *info, u8 index, u8 data) +{ + OUTB(0x3CE, index); + OUTB(0x3CF, data); +} + +static inline u8 IN3C5B(xgi_info_t *info, u8 index) +{ + volatile u8 data=0; + OUTB(0x3C4, index); + data = INB(0x3C5); + return data; +} + +static inline u8 IN3X5B(xgi_info_t *info, u8 index) +{ + volatile u8 data=0; + OUTB(0x3D4, index); + data = INB(0x3D5); + return data; +} + +static inline u8 IN3CFB(xgi_info_t *info, u8 index) +{ + volatile u8 data=0; + OUTB(0x3CE, index); + data = INB(0x3CF); + return data; +} + +static inline void OUT3C5W(xgi_info_t *info, u8 index, u16 data) +{ + OUTB(0x3C4, index); + OUTB(0x3C5, data); +} + +static inline void OUT3X5W(xgi_info_t *info, u8 index, u16 data) +{ + OUTB(0x3D4, index); + OUTB(0x3D5, data); +} + +static inline void OUT3CFW(xgi_info_t *info, u8 index, u8 data) +{ + OUTB(0x3CE, index); + OUTB(0x3CF, data); +} + +static inline u8 IN3C5W(xgi_info_t *info, u8 index) +{ + volatile u8 data=0; + OUTB(0x3C4, index); + data = INB(0x3C5); + return data; +} + +static inline u8 IN3X5W(xgi_info_t *info, u8 index) +{ + volatile u8 data=0; + OUTB(0x3D4, index); + data = INB(0x3D5); + return data; +} + +static inline u8 IN3CFW(xgi_info_t *info, u8 index) +{ + volatile u8 data=0; + OUTB(0x3CE, index); + data = INB(0x3CF); + return data; +} + +static inline u8 readAttr(xgi_info_t *info, u8 index) +{ + INB(0x3DA); /* flip-flop to index */ + OUTB(0x3C0, index); + return INB(0x3C1); +} + +static inline void writeAttr(xgi_info_t *info, u8 index, u8 value) +{ + INB(0x3DA); /* flip-flop to index */ + OUTB(0x3C0, index); + OUTB(0x3C0, value); +} + +/* + * Graphic engine register (2d/3d) acessing interface + */ +static inline void WriteRegDWord(xgi_info_t *info, u32 addr, u32 data) +{ + /* Jong 05/25/2006 */ + XGI_INFO("Jong-WriteRegDWord()-Begin \n"); + XGI_INFO("Jong-WriteRegDWord()-info->mmio.vbase=0x%lx \n", info->mmio.vbase); + XGI_INFO("Jong-WriteRegDWord()-addr=0x%lx \n", addr); + XGI_INFO("Jong-WriteRegDWord()-data=0x%lx \n", data); + /* return; */ + + *(volatile u32*)(info->mmio.vbase + addr) = (data); + XGI_INFO("Jong-WriteRegDWord()-End \n"); +} + +static inline void WriteRegWord(xgi_info_t *info, u32 addr, u16 data) +{ + *(volatile u16*)(info->mmio.vbase + addr) = (data); +} + +static inline void WriteRegByte(xgi_info_t *info, u32 addr, u8 data) +{ + *(volatile u8*)(info->mmio.vbase + addr) = (data); +} + +static inline u32 ReadRegDWord(xgi_info_t *info, u32 addr) +{ + volatile u32 data; + data = *(volatile u32*)(info->mmio.vbase + addr); + return data; +} + +static inline u16 ReadRegWord(xgi_info_t *info, u32 addr) +{ + volatile u16 data; + data = *(volatile u16*)(info->mmio.vbase + addr); + return data; +} + +static inline u8 ReadRegByte(xgi_info_t *info, u32 addr) +{ + volatile u8 data; + data = *(volatile u8*)(info->mmio.vbase + addr); + return data; +} +#if 0 +extern void OUT3C5B(xgi_info_t *info, u8 index, u8 data); +extern void OUT3X5B(xgi_info_t *info, u8 index, u8 data); +extern void OUT3CFB(xgi_info_t *info, u8 index, u8 data); +extern u8 IN3C5B(xgi_info_t *info, u8 index); +extern u8 IN3X5B(xgi_info_t *info, u8 index); +extern u8 IN3CFB(xgi_info_t *info, u8 index); +extern void OUT3C5W(xgi_info_t *info, u8 index, u8 data); +extern void OUT3X5W(xgi_info_t *info, u8 index, u8 data); +extern void OUT3CFW(xgi_info_t *info, u8 index, u8 data); +extern u8 IN3C5W(xgi_info_t *info, u8 index); +extern u8 IN3X5W(xgi_info_t *info, u8 index); +extern u8 IN3CFW(xgi_info_t *info, u8 index); + +extern void WriteRegDWord(xgi_info_t *info, u32 addr, u32 data); +extern void WriteRegWord(xgi_info_t *info, u32 addr, u16 data); +extern void WriteRegByte(xgi_info_t *info, u32 addr, u8 data); +extern u32 ReadRegDWord(xgi_info_t *info, u32 addr); +extern u16 ReadRegWord(xgi_info_t *info, u32 addr); +extern u8 ReadRegByte(xgi_info_t *info, u32 addr); + +extern void EnableProtect(); +extern void DisableProtect(); +#endif + +#define Out(port, data) OUTB(port, data) +#define bOut(port, data) OUTB(port, data) +#define wOut(port, data) OUTW(port, data) +#define dwOut(port, data) OUTDW(port, data) + +#define Out3x5(index, data) OUT3X5B(info, index, data) +#define bOut3x5(index, data) OUT3X5B(info, index, data) +#define wOut3x5(index, data) OUT3X5W(info, index, data) + +#define Out3c5(index, data) OUT3C5B(info, index, data) +#define bOut3c5(index, data) OUT3C5B(info, index, data) +#define wOut3c5(index, data) OUT3C5W(info, index, data) + +#define Out3cf(index, data) OUT3CFB(info, index, data) +#define bOut3cf(index, data) OUT3CFB(info, index, data) +#define wOut3cf(index, data) OUT3CFW(info, index, data) + +#define In(port) INB(port) +#define bIn(port) INB(port) +#define wIn(port) INW(port) +#define dwIn(port) INDW(port) + +#define In3x5(index) IN3X5B(info, index) +#define bIn3x5(index) IN3X5B(info, index) +#define wIn3x5(index) IN3X5W(info, index) + +#define In3c5(index) IN3C5B(info, index) +#define bIn3c5(index) IN3C5B(info, index) +#define wIn3c5(index) IN3C5W(info, index) + +#define In3cf(index) IN3CFB(info, index) +#define bIn3cf(index) IN3CFB(info, index) +#define wIn3cf(index) IN3CFW(info, index) + +#define dwWriteReg(addr, data) WriteRegDWord(info, addr, data) +#define wWriteReg(addr, data) WriteRegWord(info, addr, data) +#define bWriteReg(addr, data) WriteRegByte(info, addr, data) +#define dwReadReg(addr) ReadRegDWord(info, addr) +#define wReadReg(addr) ReadRegWord(info, addr) +#define bReadReg(addr) ReadRegByte(info, addr) + +static inline void xgi_protect_all(xgi_info_t *info) +{ + OUTB(0x3C4, 0x11); + OUTB(0x3C5, 0x92); +} + +static inline void xgi_unprotect_all(xgi_info_t *info) +{ + OUTB(0x3C4, 0x11); + OUTB(0x3C5, 0x92); +} + +static inline void xgi_enable_mmio(xgi_info_t *info) +{ + u8 protect = 0; + + /* Unprotect registers */ + outb(0x11, 0x3C4); + protect = inb(0x3C5); + outb(0x92, 0x3C5); + + outb(0x3A, 0x3D4); + outb(inb(0x3D5) | 0x20, 0x3D5); + + /* Enable MMIO */ + outb(0x39, 0x3D4); + outb(inb(0x3D5) | 0x01, 0x3D5); + + OUTB(0x3C4, 0x11); + OUTB(0x3C5, protect); +} + +static inline void xgi_disable_mmio(xgi_info_t *info) +{ + u8 protect = 0; + + /* unprotect registers */ + OUTB(0x3C4, 0x11); + protect = INB(0x3C5); + OUTB(0x3C5, 0x92); + + /* Disable MMIO access */ + OUTB(0x3D4, 0x39); + OUTB(0x3D5, INB(0x3D5) & 0xFE); + + /* Protect registers */ + outb(0x11, 0x3C4); + outb(protect, 0x3C5); +} + +static inline void xgi_enable_ge(xgi_info_t *info) +{ + unsigned char bOld3cf2a = 0; + int wait = 0; + + // Enable GE + OUTW(0x3C4, 0x9211); + + // Save and close dynamic gating + bOld3cf2a = bIn3cf(0x2a); + bOut3cf(0x2a, bOld3cf2a & 0xfe); + + // Reset both 3D and 2D engine + bOut3x5(0x36, 0x84); + wait = 10; + while (wait--) + { + bIn(0x36); + } + bOut3x5(0x36, 0x94); + wait = 10; + while (wait--) + { + bIn(0x36); + } + bOut3x5(0x36, 0x84); + wait = 10; + while (wait--) + { + bIn(0x36); + } + // Enable 2D engine only + bOut3x5(0x36, 0x80); + + // Enable 2D+3D engine + bOut3x5(0x36, 0x84); + + // Restore dynamic gating + bOut3cf(0x2a, bOld3cf2a); +} + +static inline void xgi_disable_ge(xgi_info_t *info) +{ + int wait = 0; + + // Reset both 3D and 2D engine + bOut3x5(0x36, 0x84); + + wait = 10; + while (wait--) + { + bIn(0x36); + } + bOut3x5(0x36, 0x94); + + wait = 10; + while (wait--) + { + bIn(0x36); + } + bOut3x5(0x36, 0x84); + + wait = 10; + while (wait--) + { + bIn(0x36); + } + + // Disable 2D engine only + bOut3x5(0x36, 0); +} + +static inline void xgi_enable_dvi_interrupt(xgi_info_t *info) +{ + Out3cf(0x39, In3cf(0x39) & ~0x01); //Set 3cf.39 bit 0 to 0 + Out3cf(0x39, In3cf(0x39) | 0x01); //Set 3cf.39 bit 0 to 1 + Out3cf(0x39, In3cf(0x39) | 0x02); +} +static inline void xgi_disable_dvi_interrupt(xgi_info_t *info) +{ + Out3cf(0x39,In3cf(0x39) & ~0x02); +} + +static inline void xgi_enable_crt1_interrupt(xgi_info_t *info) +{ + Out3cf(0x3d,In3cf(0x3d) | 0x04); + Out3cf(0x3d,In3cf(0x3d) & ~0x04); + Out3cf(0x3d,In3cf(0x3d) | 0x08); +} + +static inline void xgi_disable_crt1_interrupt(xgi_info_t *info) +{ + Out3cf(0x3d,In3cf(0x3d) & ~0x08); +} + +#endif + diff --git a/linux-core/xgi_types.h b/linux-core/xgi_types.h new file mode 100644 index 00000000..24cb8f3c --- /dev/null +++ b/linux-core/xgi_types.h @@ -0,0 +1,68 @@ + +/**************************************************************************** + * 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_TYPES_H_ +#define _XGI_TYPES_H_ + +/**************************************************************************** + * Typedefs * + ***************************************************************************/ + +typedef unsigned char V8; /* "void": enumerated or multiple fields */ +typedef unsigned short V16; /* "void": enumerated or multiple fields */ +typedef unsigned char U8; /* 0 to 255 */ +typedef unsigned short U16; /* 0 to 65535 */ +typedef signed char S8; /* -128 to 127 */ +typedef signed short S16; /* -32768 to 32767 */ +typedef float F32; /* IEEE Single Precision (S1E8M23) */ +typedef double F64; /* IEEE Double Precision (S1E11M52) */ +typedef unsigned long BOOL; +/* + * mainly for 64-bit linux, where long is 64 bits + * and win9x, where int is 16 bit. + */ +#if defined(vxworks) +typedef unsigned int V32; /* "void": enumerated or multiple fields */ +typedef unsigned int U32; /* 0 to 4294967295 */ +typedef signed int S32; /* -2147483648 to 2147483647 */ +#else +typedef unsigned long V32; /* "void": enumerated or multiple fields */ +typedef unsigned long U32; /* 0 to 4294967295 */ +typedef signed long S32; /* -2147483648 to 2147483647 */ +#endif + +#ifndef TRUE +#define TRUE 1UL +#endif + +#ifndef FALSE +#define FALSE 0UL +#endif + +#endif + -- cgit v1.2.3 From 434657a2582362367ba2a94f827511252001368f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:10:30 -0700 Subject: dos2unix and Lindent --- linux-core/xgi_cmdlist.c | 705 +++++----- linux-core/xgi_cmdlist.h | 155 ++- linux-core/xgi_drv.c | 3174 +++++++++++++++++++++++----------------------- linux-core/xgi_drv.h | 728 +++++------ linux-core/xgi_fb.c | 1019 +++++++-------- linux-core/xgi_fb.h | 141 +- linux-core/xgi_linux.h | 1187 +++++++++-------- linux-core/xgi_misc.c | 1287 +++++++++---------- linux-core/xgi_misc.h | 96 +- linux-core/xgi_pcie.c | 2091 +++++++++++++++--------------- linux-core/xgi_pcie.h | 146 +-- linux-core/xgi_regs.h | 814 ++++++------ linux-core/xgi_types.h | 135 +- 13 files changed, 5765 insertions(+), 5913 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 024b021c..e00ea228 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -1,348 +1,357 @@ - -/**************************************************************************** - * 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_types.h" -#include "xgi_linux.h" -#include "xgi_drv.h" -#include "xgi_regs.h" -#include "xgi_misc.h" -#include "xgi_cmdlist.h" - - - -U32 s_emptyBegin[AGPCMDLIST_BEGIN_SIZE] = -{ - 0x10000000, // 3D Type Begin, Invalid - 0x80000004, // Length = 4; - 0x00000000, - 0x00000000 -}; - -U32 s_flush2D[AGPCMDLIST_FLUSH_CMD_LEN] = -{ - FLUSH_2D, - FLUSH_2D, - FLUSH_2D, - FLUSH_2D -}; - -xgi_cmdring_info_t s_cmdring; - -static void addFlush2D(xgi_info_t *info); -static U32 getCurBatchBeginPort(xgi_cmd_info_t *pCmdInfo); -static void triggerHWCommandList(xgi_info_t *info, U32 triggerCounter); -static void xgi_cmdlist_reset(void); - -int xgi_cmdlist_initialize(xgi_info_t *info, U32 size) -{ - //xgi_mem_req_t mem_req; - xgi_mem_alloc_t mem_alloc; - - //mem_req.size = size; - - xgi_pcie_alloc(info, size, PCIE_2D, &mem_alloc); - - if ((mem_alloc.size == 0) && (mem_alloc.hw_addr == 0)) - { - return -1; - } - - s_cmdring._cmdRingSize = mem_alloc.size; - s_cmdring._cmdRingBuffer = mem_alloc.hw_addr; - s_cmdring._cmdRingBusAddr = mem_alloc.bus_addr; - s_cmdring._lastBatchStartAddr = 0; - s_cmdring._cmdRingOffset = 0; - - return 1; -} - -void xgi_submit_cmdlist(xgi_info_t *info, xgi_cmd_info_t *pCmdInfo) -{ - U32 beginPort; - /** XGI_INFO("Jong-xgi_submit_cmdlist-Begin \n"); **/ - - /* Jong 05/25/2006 */ - /* return; */ - - beginPort = getCurBatchBeginPort(pCmdInfo); - XGI_INFO("Jong-xgi_submit_cmdlist-After getCurBatchBeginPort() \n"); - - /* Jong 05/25/2006 */ - /* return; */ - - if (s_cmdring._lastBatchStartAddr == 0) - { - U32 portOffset; - - /* Jong 06/13/2006; remove marked for system hang test */ - /* xgi_waitfor_pci_idle(info); */ - - /* Jong 06132006; BASE_3D_ENG=0x2800 */ - /* beginPort: 2D: 0x30 */ - portOffset = BASE_3D_ENG + beginPort; - - // Enable PCI Trigger Mode - XGI_INFO("Jong-xgi_submit_cmdlist-Enable PCI Trigger Mode \n"); - - /* Jong 05/25/2006 */ - /* return; */ - - /* Jong 06/13/2006; M2REG_AUTO_LINK_SETTING_ADDRESS=0x10 */ - XGI_INFO("Jong-M2REG_AUTO_LINK_SETTING_ADDRESS=0x%lx \n", M2REG_AUTO_LINK_SETTING_ADDRESS); - XGI_INFO("Jong-M2REG_CLEAR_COUNTERS_MASK=0x%lx \n", M2REG_CLEAR_COUNTERS_MASK); - XGI_INFO("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)=0x%lx \n", (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)); - XGI_INFO("Jong-M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n\n", M2REG_PCI_TRIGGER_MODE_MASK); - - /* Jong 06/14/2006; 0x400001a */ - XGI_INFO("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|M2REG_CLEAR_COUNTERS_MASK|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", - (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|M2REG_CLEAR_COUNTERS_MASK|0x08|M2REG_PCI_TRIGGER_MODE_MASK); - dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, - (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | - M2REG_CLEAR_COUNTERS_MASK | - 0x08 | - M2REG_PCI_TRIGGER_MODE_MASK); - - /* Jong 05/25/2006 */ - XGI_INFO("Jong-xgi_submit_cmdlist-After dwWriteReg() \n"); - /* return; */ /* OK */ - - /* Jong 06/14/2006; 0x400000a */ - XGI_INFO("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", - (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|0x08|M2REG_PCI_TRIGGER_MODE_MASK); - dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, - (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | - 0x08 | - M2REG_PCI_TRIGGER_MODE_MASK); - - // Send PCI begin command - XGI_INFO("Jong-xgi_submit_cmdlist-Send PCI begin command \n"); - /* return; */ - - XGI_INFO("Jong-xgi_submit_cmdlist-portOffset=%d \n", portOffset); - XGI_INFO("Jong-xgi_submit_cmdlist-beginPort=%d \n", beginPort); - - /* beginPort = 48; */ - /* 0xc100000 */ - dwWriteReg(portOffset, (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); - XGI_INFO("Jong-(beginPort<<22)=0x%lx \n", (beginPort<<22)); - XGI_INFO("Jong-(BEGIN_VALID_MASK)=0x%lx \n", BEGIN_VALID_MASK); - XGI_INFO("Jong- pCmdInfo->_curDebugID=0x%lx \n", pCmdInfo->_curDebugID); - XGI_INFO("Jong- (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID=0x%lx \n", (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); - XGI_INFO("Jong-xgi_submit_cmdlist-Send PCI begin command- After \n"); - /* return; */ /* OK */ - - /* 0x80000024 */ - dwWriteReg(portOffset+4, BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); - XGI_INFO("Jong- BEGIN_LINK_ENABLE_MASK=0x%lx \n", BEGIN_LINK_ENABLE_MASK); - XGI_INFO("Jong- pCmdInfo->_firstSize=0x%lx \n", pCmdInfo->_firstSize); - XGI_INFO("Jong- BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize=0x%lx \n", BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); - XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-1 \n"); - - /* 0x1010000 */ - dwWriteReg(portOffset+8, (pCmdInfo->_firstBeginAddr >> 4)); - XGI_INFO("Jong- pCmdInfo->_firstBeginAddr=0x%lx \n", pCmdInfo->_firstBeginAddr); - XGI_INFO("Jong- (pCmdInfo->_firstBeginAddr >> 4)=0x%lx \n", (pCmdInfo->_firstBeginAddr >> 4)); - XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-2 \n"); - - /* Jong 06/13/2006 */ - xgi_dump_register(info); - - /* Jong 06/12/2006; system hang; marked for test */ - dwWriteReg(portOffset+12, 0); - XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-3 \n"); - - /* Jong 06/13/2006; remove marked for system hang test */ - /* xgi_waitfor_pci_idle(info); */ - } - else - { - XGI_INFO("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 \n"); - U32 *lastBatchVirtAddr; - - /* Jong 05/25/2006 */ - /* return; */ - - if (pCmdInfo->_firstBeginType == BTYPE_3D) - { - addFlush2D(info); - } - - lastBatchVirtAddr = (U32*) xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); - - lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize; - lastBatchVirtAddr[2] = pCmdInfo->_firstBeginAddr >> 4; - lastBatchVirtAddr[3] = 0; - //barrier(); - lastBatchVirtAddr[0] = (beginPort<<22) + (BEGIN_VALID_MASK) + (0xffff & pCmdInfo->_curDebugID); - - /* Jong 06/12/2006; system hang; marked for test */ - triggerHWCommandList(info, pCmdInfo->_beginCount); - - XGI_INFO("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 - End\n"); - } - - s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; - XGI_INFO("Jong-xgi_submit_cmdlist-End \n"); -} - - -/* - state: 0 - console - 1 - graphic - 2 - fb - 3 - logout -*/ -void xgi_state_change(xgi_info_t *info, xgi_state_info_t *pStateInfo) -{ -#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 ((pStateInfo->_fromState == STATE_GRAPHIC) - && (pStateInfo->_toState == STATE_CONSOLE)) - { - XGI_INFO("[kd] I see, now is to leaveVT\n"); - // stop to received batch - } - else if ((pStateInfo->_fromState == STATE_CONSOLE) - && (pStateInfo->_toState == STATE_GRAPHIC)) - { - XGI_INFO("[kd] I see, now is to enterVT\n"); - xgi_cmdlist_reset(); - } - else if ((pStateInfo->_fromState == STATE_GRAPHIC) - && ( (pStateInfo->_toState == STATE_LOGOUT) - ||(pStateInfo->_toState == STATE_REBOOT) - ||(pStateInfo->_toState == STATE_SHUTDOWN))) - { - XGI_INFO("[kd] I see, not is to exit from X\n"); - // stop to received batch - } - else - { - XGI_ERROR("[kd] Should not happen\n"); - } - -} - -void xgi_cmdlist_reset(void) -{ - s_cmdring._lastBatchStartAddr = 0; - s_cmdring._cmdRingOffset = 0; -} - -void xgi_cmdlist_cleanup(xgi_info_t *info) -{ - if (s_cmdring._cmdRingBuffer != 0) - { - xgi_pcie_free(info, s_cmdring._cmdRingBusAddr); - s_cmdring._cmdRingBuffer = 0; - s_cmdring._cmdRingOffset = 0; - s_cmdring._cmdRingSize = 0; - } -} - -static void triggerHWCommandList(xgi_info_t *info, U32 triggerCounter) -{ - static U32 s_triggerID = 1; - - //Fix me, currently we just trigger one time - while (triggerCounter--) - { - dwWriteReg(BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, - 0x05000000 + (0xffff & s_triggerID++)); - // xgi_waitfor_pci_idle(info); - } -} - -static U32 getCurBatchBeginPort(xgi_cmd_info_t *pCmdInfo) -{ - // Convert the batch type to begin port ID - switch(pCmdInfo->_firstBeginType) - { - case BTYPE_2D: - return 0x30; - case BTYPE_3D: - return 0x40; - case BTYPE_FLIP: - return 0x50; - case BTYPE_CTRL: - return 0x20; - default: - //ASSERT(0); - return 0xff; - } -} - -static void addFlush2D(xgi_info_t *info) -{ - U32 *flushBatchVirtAddr; - U32 flushBatchHWAddr; - - U32 *lastBatchVirtAddr; - - /* check buf is large enough to contain a new flush batch */ - if ((s_cmdring._cmdRingOffset + 0x20) >= s_cmdring._cmdRingSize) - { - s_cmdring._cmdRingOffset = 0; - } - - flushBatchHWAddr = s_cmdring._cmdRingBuffer + s_cmdring._cmdRingOffset; - flushBatchVirtAddr = (U32*) xgi_find_pcie_virt(info, flushBatchHWAddr); - - /* 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; - - // ASSERT(s_cmdring._lastBatchStartAddr != NULL); - lastBatchVirtAddr = (U32*) xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); - - lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; - lastBatchVirtAddr[2] = flushBatchHWAddr >> 4; - lastBatchVirtAddr[3] = 0; - - //barrier(); - - // BTYPE_CTRL & NO debugID - lastBatchVirtAddr[0] = (0x20<<22) + (BEGIN_VALID_MASK); - - triggerHWCommandList(info, 1); - - s_cmdring._cmdRingOffset += 0x20; - s_cmdring._lastBatchStartAddr = flushBatchHWAddr; -} + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_misc.h" +#include "xgi_cmdlist.h" + +U32 s_emptyBegin[AGPCMDLIST_BEGIN_SIZE] = { + 0x10000000, // 3D Type Begin, Invalid + 0x80000004, // Length = 4; + 0x00000000, + 0x00000000 +}; + +U32 s_flush2D[AGPCMDLIST_FLUSH_CMD_LEN] = { + FLUSH_2D, + FLUSH_2D, + FLUSH_2D, + FLUSH_2D +}; + +xgi_cmdring_info_t s_cmdring; + +static void addFlush2D(xgi_info_t * info); +static U32 getCurBatchBeginPort(xgi_cmd_info_t * pCmdInfo); +static void triggerHWCommandList(xgi_info_t * info, U32 triggerCounter); +static void xgi_cmdlist_reset(void); + +int xgi_cmdlist_initialize(xgi_info_t * info, U32 size) +{ + //xgi_mem_req_t mem_req; + xgi_mem_alloc_t mem_alloc; + + //mem_req.size = size; + + xgi_pcie_alloc(info, size, PCIE_2D, &mem_alloc); + + if ((mem_alloc.size == 0) && (mem_alloc.hw_addr == 0)) { + return -1; + } + + s_cmdring._cmdRingSize = mem_alloc.size; + s_cmdring._cmdRingBuffer = mem_alloc.hw_addr; + s_cmdring._cmdRingBusAddr = mem_alloc.bus_addr; + s_cmdring._lastBatchStartAddr = 0; + s_cmdring._cmdRingOffset = 0; + + return 1; +} + +void xgi_submit_cmdlist(xgi_info_t * info, xgi_cmd_info_t * pCmdInfo) +{ + U32 beginPort; + /** XGI_INFO("Jong-xgi_submit_cmdlist-Begin \n"); **/ + + /* Jong 05/25/2006 */ + /* return; */ + + beginPort = getCurBatchBeginPort(pCmdInfo); + XGI_INFO("Jong-xgi_submit_cmdlist-After getCurBatchBeginPort() \n"); + + /* Jong 05/25/2006 */ + /* return; */ + + if (s_cmdring._lastBatchStartAddr == 0) { + U32 portOffset; + + /* Jong 06/13/2006; remove marked for system hang test */ + /* xgi_waitfor_pci_idle(info); */ + + /* Jong 06132006; BASE_3D_ENG=0x2800 */ + /* beginPort: 2D: 0x30 */ + portOffset = BASE_3D_ENG + beginPort; + + // Enable PCI Trigger Mode + XGI_INFO("Jong-xgi_submit_cmdlist-Enable PCI Trigger Mode \n"); + + /* Jong 05/25/2006 */ + /* return; */ + + /* Jong 06/13/2006; M2REG_AUTO_LINK_SETTING_ADDRESS=0x10 */ + XGI_INFO("Jong-M2REG_AUTO_LINK_SETTING_ADDRESS=0x%lx \n", + M2REG_AUTO_LINK_SETTING_ADDRESS); + XGI_INFO("Jong-M2REG_CLEAR_COUNTERS_MASK=0x%lx \n", + M2REG_CLEAR_COUNTERS_MASK); + XGI_INFO + ("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)=0x%lx \n", + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)); + XGI_INFO("Jong-M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n\n", + M2REG_PCI_TRIGGER_MODE_MASK); + + /* Jong 06/14/2006; 0x400001a */ + XGI_INFO + ("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|M2REG_CLEAR_COUNTERS_MASK|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | + M2REG_CLEAR_COUNTERS_MASK | 0x08 | + M2REG_PCI_TRIGGER_MODE_MASK); + dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | + M2REG_CLEAR_COUNTERS_MASK | 0x08 | + M2REG_PCI_TRIGGER_MODE_MASK); + + /* Jong 05/25/2006 */ + XGI_INFO("Jong-xgi_submit_cmdlist-After dwWriteReg() \n"); + /* return; *//* OK */ + + /* Jong 06/14/2006; 0x400000a */ + XGI_INFO + ("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | 0x08 | + M2REG_PCI_TRIGGER_MODE_MASK); + dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, + (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | 0x08 | + M2REG_PCI_TRIGGER_MODE_MASK); + + // Send PCI begin command + XGI_INFO("Jong-xgi_submit_cmdlist-Send PCI begin command \n"); + /* return; */ + + XGI_INFO("Jong-xgi_submit_cmdlist-portOffset=%d \n", + portOffset); + XGI_INFO("Jong-xgi_submit_cmdlist-beginPort=%d \n", beginPort); + + /* beginPort = 48; */ + /* 0xc100000 */ + dwWriteReg(portOffset, + (beginPort << 22) + (BEGIN_VALID_MASK) + + pCmdInfo->_curDebugID); + XGI_INFO("Jong-(beginPort<<22)=0x%lx \n", (beginPort << 22)); + XGI_INFO("Jong-(BEGIN_VALID_MASK)=0x%lx \n", BEGIN_VALID_MASK); + XGI_INFO("Jong- pCmdInfo->_curDebugID=0x%lx \n", + pCmdInfo->_curDebugID); + XGI_INFO + ("Jong- (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID=0x%lx \n", + (beginPort << 22) + (BEGIN_VALID_MASK) + + pCmdInfo->_curDebugID); + XGI_INFO + ("Jong-xgi_submit_cmdlist-Send PCI begin command- After \n"); + /* return; *//* OK */ + + /* 0x80000024 */ + dwWriteReg(portOffset + 4, + BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); + XGI_INFO("Jong- BEGIN_LINK_ENABLE_MASK=0x%lx \n", + BEGIN_LINK_ENABLE_MASK); + XGI_INFO("Jong- pCmdInfo->_firstSize=0x%lx \n", + pCmdInfo->_firstSize); + XGI_INFO + ("Jong- BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize=0x%lx \n", + BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); + XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-1 \n"); + + /* 0x1010000 */ + dwWriteReg(portOffset + 8, (pCmdInfo->_firstBeginAddr >> 4)); + XGI_INFO("Jong- pCmdInfo->_firstBeginAddr=0x%lx \n", + pCmdInfo->_firstBeginAddr); + XGI_INFO("Jong- (pCmdInfo->_firstBeginAddr >> 4)=0x%lx \n", + (pCmdInfo->_firstBeginAddr >> 4)); + XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-2 \n"); + + /* Jong 06/13/2006 */ + xgi_dump_register(info); + + /* Jong 06/12/2006; system hang; marked for test */ + dwWriteReg(portOffset + 12, 0); + XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-3 \n"); + + /* Jong 06/13/2006; remove marked for system hang test */ + /* xgi_waitfor_pci_idle(info); */ + } else { + XGI_INFO + ("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 \n"); + U32 *lastBatchVirtAddr; + + /* Jong 05/25/2006 */ + /* return; */ + + if (pCmdInfo->_firstBeginType == BTYPE_3D) { + addFlush2D(info); + } + + lastBatchVirtAddr = + (U32 *) xgi_find_pcie_virt(info, + s_cmdring._lastBatchStartAddr); + + lastBatchVirtAddr[1] = + BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize; + lastBatchVirtAddr[2] = pCmdInfo->_firstBeginAddr >> 4; + lastBatchVirtAddr[3] = 0; + //barrier(); + lastBatchVirtAddr[0] = + (beginPort << 22) + (BEGIN_VALID_MASK) + + (0xffff & pCmdInfo->_curDebugID); + + /* Jong 06/12/2006; system hang; marked for test */ + triggerHWCommandList(info, pCmdInfo->_beginCount); + + XGI_INFO + ("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 - End\n"); + } + + s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; + XGI_INFO("Jong-xgi_submit_cmdlist-End \n"); +} + +/* + state: 0 - console + 1 - graphic + 2 - fb + 3 - logout +*/ +void xgi_state_change(xgi_info_t * info, xgi_state_info_t * pStateInfo) +{ +#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 ((pStateInfo->_fromState == STATE_GRAPHIC) + && (pStateInfo->_toState == STATE_CONSOLE)) { + XGI_INFO("[kd] I see, now is to leaveVT\n"); + // stop to received batch + } else if ((pStateInfo->_fromState == STATE_CONSOLE) + && (pStateInfo->_toState == STATE_GRAPHIC)) { + XGI_INFO("[kd] I see, now is to enterVT\n"); + xgi_cmdlist_reset(); + } else if ((pStateInfo->_fromState == STATE_GRAPHIC) + && ((pStateInfo->_toState == STATE_LOGOUT) + || (pStateInfo->_toState == STATE_REBOOT) + || (pStateInfo->_toState == STATE_SHUTDOWN))) { + XGI_INFO("[kd] I see, not is to exit from X\n"); + // stop to received batch + } else { + XGI_ERROR("[kd] Should not happen\n"); + } + +} + +void xgi_cmdlist_reset(void) +{ + s_cmdring._lastBatchStartAddr = 0; + s_cmdring._cmdRingOffset = 0; +} + +void xgi_cmdlist_cleanup(xgi_info_t * info) +{ + if (s_cmdring._cmdRingBuffer != 0) { + xgi_pcie_free(info, s_cmdring._cmdRingBusAddr); + s_cmdring._cmdRingBuffer = 0; + s_cmdring._cmdRingOffset = 0; + s_cmdring._cmdRingSize = 0; + } +} + +static void triggerHWCommandList(xgi_info_t * info, U32 triggerCounter) +{ + static U32 s_triggerID = 1; + + //Fix me, currently we just trigger one time + while (triggerCounter--) { + dwWriteReg(BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, + 0x05000000 + (0xffff & s_triggerID++)); + // xgi_waitfor_pci_idle(info); + } +} + +static U32 getCurBatchBeginPort(xgi_cmd_info_t * pCmdInfo) +{ + // Convert the batch type to begin port ID + switch (pCmdInfo->_firstBeginType) { + case BTYPE_2D: + return 0x30; + case BTYPE_3D: + return 0x40; + case BTYPE_FLIP: + return 0x50; + case BTYPE_CTRL: + return 0x20; + default: + //ASSERT(0); + return 0xff; + } +} + +static void addFlush2D(xgi_info_t * info) +{ + U32 *flushBatchVirtAddr; + U32 flushBatchHWAddr; + + U32 *lastBatchVirtAddr; + + /* check buf is large enough to contain a new flush batch */ + if ((s_cmdring._cmdRingOffset + 0x20) >= s_cmdring._cmdRingSize) { + s_cmdring._cmdRingOffset = 0; + } + + flushBatchHWAddr = s_cmdring._cmdRingBuffer + s_cmdring._cmdRingOffset; + flushBatchVirtAddr = (U32 *) xgi_find_pcie_virt(info, flushBatchHWAddr); + + /* 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; + + // ASSERT(s_cmdring._lastBatchStartAddr != NULL); + lastBatchVirtAddr = + (U32 *) xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); + + lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; + lastBatchVirtAddr[2] = flushBatchHWAddr >> 4; + lastBatchVirtAddr[3] = 0; + + //barrier(); + + // BTYPE_CTRL & NO debugID + lastBatchVirtAddr[0] = (0x20 << 22) + (BEGIN_VALID_MASK); + + triggerHWCommandList(info, 1); + + s_cmdring._cmdRingOffset += 0x20; + s_cmdring._lastBatchStartAddr = flushBatchHWAddr; +} diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 1b0c4965..5fe1de71 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -1,79 +1,76 @@ - -/**************************************************************************** - * 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 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; - -typedef struct xgi_cmdring_info_s -{ - U32 _cmdRingSize; - U32 _cmdRingBuffer; - U32 _cmdRingBusAddr; - U32 _lastBatchStartAddr; - U32 _cmdRingOffset; -}xgi_cmdring_info_t; - -extern int xgi_cmdlist_initialize(xgi_info_t *info, U32 size); - -extern void xgi_submit_cmdlist(xgi_info_t *info, xgi_cmd_info_t * pCmdInfo); - -extern void xgi_state_change(xgi_info_t *info, xgi_state_info_t * pStateInfo); - -extern void xgi_cmdlist_cleanup(xgi_info_t *info); - -#endif /* _XGI_CMDLIST_H_ */ + +/**************************************************************************** + * 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 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; + +typedef struct xgi_cmdring_info_s { + U32 _cmdRingSize; + U32 _cmdRingBuffer; + U32 _cmdRingBusAddr; + U32 _lastBatchStartAddr; + U32 _cmdRingOffset; +} xgi_cmdring_info_t; + +extern int xgi_cmdlist_initialize(xgi_info_t * info, U32 size); + +extern void xgi_submit_cmdlist(xgi_info_t * info, xgi_cmd_info_t * pCmdInfo); + +extern void xgi_state_change(xgi_info_t * info, xgi_state_info_t * pStateInfo); + +extern void xgi_cmdlist_cleanup(xgi_info_t * info); + +#endif /* _XGI_CMDLIST_H_ */ diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 5e80d417..0c37d00e 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -1,1610 +1,1564 @@ - -/**************************************************************************** - * 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_types.h" -#include "xgi_linux.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. */ - -static int xgi_num_devices = 0; - -xgi_info_t xgi_devices[XGI_MAX_DEVICES]; - -#if defined(XGI_PM_SUPPORT_APM) -static struct pm_dev *apm_xgi_dev[XGI_MAX_DEVICES] = { 0 }; -#endif - -/* add one for the control device */ -xgi_info_t xgi_ctl_device; -wait_queue_head_t xgi_ctl_waitqueue; - -#ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_xgi; -#endif - -#ifdef CONFIG_DEVFS_FS -devfs_handle_t xgi_devfs_handles[XGI_MAX_DEVICES]; -#endif - -struct list_head xgi_mempid_list; - -/* xgi_ functions.. do not take a state device parameter */ -static int xgi_post_vbios(xgi_ioctl_post_vbios_t *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 *); - -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 - -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 *); - -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 *); - -void xgi_kern_isr_bh(unsigned long); -irqreturn_t xgi_kern_isr(int, void *, struct pt_regs *); - -static void xgi_lock_init(xgi_info_t *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 - -/* - * verify access to pci config space wasn't disabled behind our back - * unfortunately, XFree86 enables/disables memory access in pci config space at - * various times (such as restoring initial pci config space settings during vt - * switches or when doing mulicard). As a result, all of our register accesses - * are garbage at this point. add a check to see if access was disabled and - * reenable any such access. - */ -#define XGI_CHECK_PCI_CONFIG(xgi) \ - xgi_check_pci_config(xgi, __LINE__) - -static inline void xgi_check_pci_config(xgi_info_t *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; - - pci_read_config_word(info->dev, PCI_COMMAND, &cmd); - if (!(cmd & PCI_COMMAND_MASTER)) - { - XGI_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); - cmd |= PCI_COMMAND_MEMORY; - flag = 1; - } - - if (flag) - pci_write_config_word(info->dev, PCI_COMMAND, cmd); -} - -static int xgi_post_vbios(xgi_ioctl_post_vbios_t *info) -{ - return 1; -} - -/* - * 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) -{ - xgi_info_t *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; - info->vendor_id = dev->vendor; - info->device_id = dev->device; - info->bus = dev->bus->number; - info->slot = PCI_SLOT((dev)->devfn); - - xgi_lock_init(info); - - info->mmio.base = XGI_PCI_RESOURCE_START(dev, 1); - info->mmio.size = XGI_PCI_RESOURCE_SIZE(dev, 1); - - /* 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; - } - - 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 = (unsigned char *)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 = (unsigned char *)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); - - info->irq = dev->irq; - - /* check common error condition */ - if (info->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->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; - -} - -/* - * 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)) - { - xgi_pcie_block_t *block = (xgi_pcie_block_t *)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)) - { - xgi_pcie_block_t *block = (xgi_pcie_block_t *)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) -{ - xgi_pcie_block_t *block = (xgi_pcie_block_t *)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) -{ - xgi_pcie_block_t *block = (xgi_pcie_block_t *)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 xgi_file_private_t * xgi_alloc_file_private(void) -{ - xgi_file_private_t *fp; - - XGI_KMALLOC(fp, sizeof(xgi_file_private_t)); - if (!fp) - return NULL; - - memset(fp, 0, sizeof(xgi_file_private_t)); - - /* 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(xgi_file_private_t *fp) -{ - if (fp == NULL) - return; - - XGI_KFREE(fp, sizeof(xgi_file_private_t)); -} - -int xgi_kern_open(struct inode *inode, struct file *filp) -{ - xgi_info_t *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->device_id == 0) - { - XGI_INFO("open of nonexistent device %d\n", dev_num); - result = -ENXIO; - goto failed; - } - - /* initialize struct irqaction */ - status = request_irq(info->irq, xgi_kern_isr, - SA_INTERRUPT | SA_SHIRQ, "xgi", - (void *) info); - if (status != 0) - { - if (info->irq && (status == -EBUSY)) - { - XGI_ERROR("Tried to get irq %d, but another driver", - (unsigned int) info->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) -{ - xgi_info_t *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->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); - xgi_info_t *info = XGI_INFO_FROM_FP(filp); - xgi_pcie_block_t *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_pcie_block_t *)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) -{ - xgi_file_private_t *fp; - xgi_info_t *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) -{ - xgi_info_t *info; - xgi_mem_alloc_t *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 = (xgi_mem_alloc_t *)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_DEVICE_INFO: - XGI_INFO("Jong-xgi_ioctl_get_device_info \n"); - xgi_get_device_info(info, (struct xgi_chip_info_s *) arg_copy); - break; - 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, (struct xgi_mem_req_s *)arg_copy, alloc); - 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_MEM_COLLECT: - XGI_INFO("Jong-xgi_ioctl_mem_collect \n"); - xgi_mem_collect(info, (unsigned int *) arg_copy); - break; - case XGI_ESC_PCIE_ALLOC: - XGI_INFO("Jong-xgi_ioctl_pcie_alloc \n"); - xgi_pcie_alloc(info, ((xgi_mem_req_t *)arg_copy)->size, - ((xgi_mem_req_t *)arg_copy)->owner, alloc); - 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_PCIE_CHECK: - XGI_INFO("Jong-xgi_pcie_heap_check \n"); - xgi_pcie_heap_check(); - break; - case XGI_ESC_GET_SCREEN_INFO: - XGI_INFO("Jong-xgi_get_screen_info \n"); - xgi_get_screen_info(info, (struct xgi_screen_info_s *) arg_copy); - break; - case XGI_ESC_PUT_SCREEN_INFO: - XGI_INFO("Jong-xgi_put_screen_info \n"); - xgi_put_screen_info(info, (struct xgi_screen_info_s *) arg_copy); - break; - case XGI_ESC_MMIO_INFO: - XGI_INFO("Jong-xgi_ioctl_get_mmio_info \n"); - xgi_get_mmio_info(info, (struct xgi_mmio_info_s *) arg_copy); - break; - case XGI_ESC_GE_RESET: - XGI_INFO("Jong-xgi_ioctl_ge_reset \n"); - xgi_ge_reset(info); - break; - case XGI_ESC_SAREA_INFO: - XGI_INFO("Jong-xgi_ioctl_sarea_info \n"); - xgi_sarea_info(info, (struct xgi_sarea_info_s *) arg_copy); - 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); - //xgi_write_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); - //xgi_read_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); - break; - case XGI_ESC_SUBMIT_CMDLIST: - XGI_INFO("Jong-xgi_ioctl_submit_cmdlist \n"); - xgi_submit_cmdlist(info, (xgi_cmd_info_t *) 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, (xgi_state_info_t *) arg_copy); - break; - case XGI_ESC_CPUID: - XGI_INFO("Jong-XGI_ESC_CPUID \n"); - xgi_get_cpu_id((struct cpu_info_s*) 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) -{ - xgi_info_t *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) -{ - xgi_info_t *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) -{ - //xgi_info_t *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; - } - - 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; -} - -static struct pci_dev* xgi_get_pci_device(xgi_info_t *info) -{ - struct pci_dev *dev; - - dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, NULL); - while (dev) - { - if (XGI_PCI_SLOT_NUMBER(dev) == info->slot - && XGI_PCI_BUS_NUMBER(dev) == info->bus) - return dev; - dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, dev); - } - - return NULL; -} - -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; - - xgi_info_t *info; - info = (xgi_info_t *) data; - - dev = xgi_get_pci_device(info); - 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"); - - return len; -} - -int xgi_kern_read_pcie_info(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - 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) -{ -#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; - - xgi_info_t *info; - xgi_info_t *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++) - { - if (info->device_id == 0) - break; - - /* world readable file */ - flags = S_IFREG | S_IRUGO; - - dev = xgi_get_pci_device(info); - 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; - - 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 -} - -#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) -{ - xgi_info_t *info = (xgi_info_t *) dev_id; - u32 need_to_run_bottom_half = 0; - - //XGI_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); - } - - return IRQ_HANDLED; -} - -void xgi_kern_isr_bh(unsigned long data) -{ - xgi_info_t *info = (xgi_info_t *) data; - - XGI_INFO("xgi_kern_isr_bh \n"); - - //xgi_dvi_irq_handler(info); - - XGI_CHECK_PCI_CONFIG(info); -} - -static void xgi_lock_init(xgi_info_t *info) -{ - 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); -} - -static void xgi_dev_init(xgi_info_t *info) -{ - struct pci_dev *pdev = NULL; - struct xgi_dev *dev; - int found = 0; - u16 pci_cmd; - - XGI_INFO("Enter xgi_dev_init \n"); - - //XGI_PCI_FOR_EACH_DEV(pdev) - { - for (dev = xgidev_list; dev->vendor; dev++) - { - if ((dev->vendor == pdev->vendor) && (dev->device == pdev->device)) - { - XGI_INFO("dev->vendor = pdev->vendor= %x \n", dev->vendor); - XGI_INFO("dev->device = pdev->device= %x \n", dev->device); - - xgi_devices[found].device_id = pdev->device; - - pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_devices[found].revision_id); - - XGI_INFO("PCI_REVISION_ID= %x \n", xgi_devices[found].revision_id); - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - - XGI_INFO("PCI_COMMAND = %x \n", pci_cmd); - - break; - } - } - } -} -/* - * Export to Linux Kernel - */ - -static int __init xgi_init_module(void) -{ - xgi_info_t *info = &xgi_devices[xgi_num_devices]; - int i, result; - - XGI_INFO("Jong-xgi kernel driver %s initializing\n", XGI_DRV_VERSION); - //SET_MODULE_OWNER(&xgi_fops); - - memset(xgi_devices, 0, sizeof(xgi_devices)); - - if (pci_register_driver(&xgi_pci_driver) < 0) - { - pci_unregister_driver(&xgi_pci_driver); - XGI_ERROR("no XGI graphics adapter found\n"); - return -ENODEV; - } - - 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 (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); - } - - /* init the xgi control device */ - { - xgi_info_t *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; - } - - /* 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 i; - xgi_info_t *info, *max_devices; - -#ifdef CONFIG_DEVFS_FS - /* - XGI_DEVFS_REMOVE_CONTROL(); - for (i = 0; i < XGI_MAX_DEVICES; i++) - XGI_DEVFS_REMOVE_DEVICE(i); - */ - 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((void *)xgi_devices[i].fb.vbase); - xgi_devices[i].fb.vbase = NULL; - } - if(xgi_devices[i].mmio.vbase != NULL) - { - iounmap((void *)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(); - -#if defined(DEBUG) - inter_module_unregister("xgi_devices"); -#endif -} - -module_init(xgi_init_module); -module_exit(xgi_exit_module); - -#if defined(XGI_PM_SUPPORT_ACPI) -int xgi_acpi_event(struct pci_dev *dev, u32 state) -{ - return 1; -} - -int xgi_kern_acpi_standby(struct pci_dev *dev, u32 state) -{ - return 1; -} - -int xgi_kern_acpi_resume(struct pci_dev *dev) -{ - return 1; -} -#endif - -MODULE_AUTHOR("Andrea Zhang "); -MODULE_DESCRIPTION("xgi kernel driver for xgi cards"); -MODULE_LICENSE("GPL"); + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.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. */ + +static int xgi_num_devices = 0; + +xgi_info_t xgi_devices[XGI_MAX_DEVICES]; + +#if defined(XGI_PM_SUPPORT_APM) +static struct pm_dev *apm_xgi_dev[XGI_MAX_DEVICES] = { 0 }; +#endif + +/* add one for the control device */ +xgi_info_t xgi_ctl_device; +wait_queue_head_t xgi_ctl_waitqueue; + +#ifdef CONFIG_PROC_FS +struct proc_dir_entry *proc_xgi; +#endif + +#ifdef CONFIG_DEVFS_FS +devfs_handle_t xgi_devfs_handles[XGI_MAX_DEVICES]; +#endif + +struct list_head xgi_mempid_list; + +/* xgi_ functions.. do not take a state device parameter */ +static int xgi_post_vbios(xgi_ioctl_post_vbios_t * 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 *); + +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 + +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 *); + +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 *); + +void xgi_kern_isr_bh(unsigned long); +irqreturn_t xgi_kern_isr(int, void *, struct pt_regs *); + +static void xgi_lock_init(xgi_info_t * 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 + +/* + * verify access to pci config space wasn't disabled behind our back + * unfortunately, XFree86 enables/disables memory access in pci config space at + * various times (such as restoring initial pci config space settings during vt + * switches or when doing mulicard). As a result, all of our register accesses + * are garbage at this point. add a check to see if access was disabled and + * reenable any such access. + */ +#define XGI_CHECK_PCI_CONFIG(xgi) \ + xgi_check_pci_config(xgi, __LINE__) + +static inline void xgi_check_pci_config(xgi_info_t * 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; + + pci_read_config_word(info->dev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_MASTER)) { + XGI_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); + cmd |= PCI_COMMAND_MEMORY; + flag = 1; + } + + if (flag) + pci_write_config_word(info->dev, PCI_COMMAND, cmd); +} + +static int xgi_post_vbios(xgi_ioctl_post_vbios_t * info) +{ + return 1; +} + +/* + * 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) +{ + xgi_info_t *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; + info->vendor_id = dev->vendor; + info->device_id = dev->device; + info->bus = dev->bus->number; + info->slot = PCI_SLOT((dev)->devfn); + + xgi_lock_init(info); + + info->mmio.base = XGI_PCI_RESOURCE_START(dev, 1); + info->mmio.size = XGI_PCI_RESOURCE_SIZE(dev, 1); + + /* 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; + } + + 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 = (unsigned char *)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 = (unsigned char *)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); + + info->irq = dev->irq; + + /* check common error condition */ + if (info->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->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; + +} + +/* + * 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)) { + xgi_pcie_block_t *block = + (xgi_pcie_block_t *) 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)) { + xgi_pcie_block_t *block = + (xgi_pcie_block_t *) 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) +{ + xgi_pcie_block_t *block = (xgi_pcie_block_t *) 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) +{ + xgi_pcie_block_t *block = (xgi_pcie_block_t *) 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 xgi_file_private_t *xgi_alloc_file_private(void) +{ + xgi_file_private_t *fp; + + XGI_KMALLOC(fp, sizeof(xgi_file_private_t)); + if (!fp) + return NULL; + + memset(fp, 0, sizeof(xgi_file_private_t)); + + /* 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(xgi_file_private_t * fp) +{ + if (fp == NULL) + return; + + XGI_KFREE(fp, sizeof(xgi_file_private_t)); +} + +int xgi_kern_open(struct inode *inode, struct file *filp) +{ + xgi_info_t *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->device_id == 0) { + XGI_INFO("open of nonexistent device %d\n", dev_num); + result = -ENXIO; + goto failed; + } + + /* initialize struct irqaction */ + status = request_irq(info->irq, xgi_kern_isr, + SA_INTERRUPT | SA_SHIRQ, "xgi", + (void *)info); + if (status != 0) { + if (info->irq && (status == -EBUSY)) { + XGI_ERROR + ("Tried to get irq %d, but another driver", + (unsigned int)info->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) +{ + xgi_info_t *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->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); + xgi_info_t *info = XGI_INFO_FROM_FP(filp); + xgi_pcie_block_t *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_pcie_block_t *) 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) +{ + xgi_file_private_t *fp; + xgi_info_t *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) +{ + xgi_info_t *info; + xgi_mem_alloc_t *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 = (xgi_mem_alloc_t *) 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_DEVICE_INFO: + XGI_INFO("Jong-xgi_ioctl_get_device_info \n"); + xgi_get_device_info(info, (struct xgi_chip_info_s *)arg_copy); + break; + 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, (struct xgi_mem_req_s *)arg_copy, alloc); + 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_MEM_COLLECT: + XGI_INFO("Jong-xgi_ioctl_mem_collect \n"); + xgi_mem_collect(info, (unsigned int *)arg_copy); + break; + case XGI_ESC_PCIE_ALLOC: + XGI_INFO("Jong-xgi_ioctl_pcie_alloc \n"); + xgi_pcie_alloc(info, ((xgi_mem_req_t *) arg_copy)->size, + ((xgi_mem_req_t *) arg_copy)->owner, alloc); + 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_PCIE_CHECK: + XGI_INFO("Jong-xgi_pcie_heap_check \n"); + xgi_pcie_heap_check(); + break; + case XGI_ESC_GET_SCREEN_INFO: + XGI_INFO("Jong-xgi_get_screen_info \n"); + xgi_get_screen_info(info, (struct xgi_screen_info_s *)arg_copy); + break; + case XGI_ESC_PUT_SCREEN_INFO: + XGI_INFO("Jong-xgi_put_screen_info \n"); + xgi_put_screen_info(info, (struct xgi_screen_info_s *)arg_copy); + break; + case XGI_ESC_MMIO_INFO: + XGI_INFO("Jong-xgi_ioctl_get_mmio_info \n"); + xgi_get_mmio_info(info, (struct xgi_mmio_info_s *)arg_copy); + break; + case XGI_ESC_GE_RESET: + XGI_INFO("Jong-xgi_ioctl_ge_reset \n"); + xgi_ge_reset(info); + break; + case XGI_ESC_SAREA_INFO: + XGI_INFO("Jong-xgi_ioctl_sarea_info \n"); + xgi_sarea_info(info, (struct xgi_sarea_info_s *)arg_copy); + 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); + //xgi_write_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); + //xgi_read_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); + break; + case XGI_ESC_SUBMIT_CMDLIST: + XGI_INFO("Jong-xgi_ioctl_submit_cmdlist \n"); + xgi_submit_cmdlist(info, (xgi_cmd_info_t *) 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, (xgi_state_info_t *) arg_copy); + break; + case XGI_ESC_CPUID: + XGI_INFO("Jong-XGI_ESC_CPUID \n"); + xgi_get_cpu_id((struct cpu_info_s *)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) +{ + xgi_info_t *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) +{ + xgi_info_t *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) +{ + //xgi_info_t *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; + } + + 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; +} + +static struct pci_dev *xgi_get_pci_device(xgi_info_t * info) +{ + struct pci_dev *dev; + + dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, NULL); + while (dev) { + if (XGI_PCI_SLOT_NUMBER(dev) == info->slot + && XGI_PCI_BUS_NUMBER(dev) == info->bus) + return dev; + dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, dev); + } + + return NULL; +} + +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; + + xgi_info_t *info; + info = (xgi_info_t *) data; + + dev = xgi_get_pci_device(info); + 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"); + + return len; +} + +int xgi_kern_read_pcie_info(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + 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) +{ +#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; + + xgi_info_t *info; + xgi_info_t *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++) { + if (info->device_id == 0) + break; + + /* world readable file */ + flags = S_IFREG | S_IRUGO; + + dev = xgi_get_pci_device(info); + 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; + + 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 +} + +#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) +{ + xgi_info_t *info = (xgi_info_t *) dev_id; + u32 need_to_run_bottom_half = 0; + + //XGI_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); + } + + return IRQ_HANDLED; +} + +void xgi_kern_isr_bh(unsigned long data) +{ + xgi_info_t *info = (xgi_info_t *) data; + + XGI_INFO("xgi_kern_isr_bh \n"); + + //xgi_dvi_irq_handler(info); + + XGI_CHECK_PCI_CONFIG(info); +} + +static void xgi_lock_init(xgi_info_t * info) +{ + 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); +} + +static void xgi_dev_init(xgi_info_t * info) +{ + struct pci_dev *pdev = NULL; + struct xgi_dev *dev; + int found = 0; + u16 pci_cmd; + + XGI_INFO("Enter xgi_dev_init \n"); + + //XGI_PCI_FOR_EACH_DEV(pdev) + { + for (dev = xgidev_list; dev->vendor; dev++) { + if ((dev->vendor == pdev->vendor) + && (dev->device == pdev->device)) { + XGI_INFO("dev->vendor = pdev->vendor= %x \n", + dev->vendor); + XGI_INFO("dev->device = pdev->device= %x \n", + dev->device); + + xgi_devices[found].device_id = pdev->device; + + pci_read_config_byte(pdev, PCI_REVISION_ID, + &xgi_devices[found]. + revision_id); + + XGI_INFO("PCI_REVISION_ID= %x \n", + xgi_devices[found].revision_id); + + pci_read_config_word(pdev, PCI_COMMAND, + &pci_cmd); + + XGI_INFO("PCI_COMMAND = %x \n", pci_cmd); + + break; + } + } + } +} + +/* + * Export to Linux Kernel + */ + +static int __init xgi_init_module(void) +{ + xgi_info_t *info = &xgi_devices[xgi_num_devices]; + int i, result; + + XGI_INFO("Jong-xgi kernel driver %s initializing\n", XGI_DRV_VERSION); + //SET_MODULE_OWNER(&xgi_fops); + + memset(xgi_devices, 0, sizeof(xgi_devices)); + + if (pci_register_driver(&xgi_pci_driver) < 0) { + pci_unregister_driver(&xgi_pci_driver); + XGI_ERROR("no XGI graphics adapter found\n"); + return -ENODEV; + } + + 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 (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); + } + + /* init the xgi control device */ + { + xgi_info_t *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; + } + + /* 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 i; + xgi_info_t *info, *max_devices; + +#ifdef CONFIG_DEVFS_FS + /* + XGI_DEVFS_REMOVE_CONTROL(); + for (i = 0; i < XGI_MAX_DEVICES; i++) + XGI_DEVFS_REMOVE_DEVICE(i); + */ + 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((void *)xgi_devices[i].fb.vbase); + xgi_devices[i].fb.vbase = NULL; + } + if (xgi_devices[i].mmio.vbase != NULL) { + iounmap((void *)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(); + +#if defined(DEBUG) + inter_module_unregister("xgi_devices"); +#endif +} + +module_init(xgi_init_module); +module_exit(xgi_exit_module); + +#if defined(XGI_PM_SUPPORT_ACPI) +int xgi_acpi_event(struct pci_dev *dev, u32 state) +{ + return 1; +} + +int xgi_kern_acpi_standby(struct pci_dev *dev, u32 state) +{ + return 1; +} + +int xgi_kern_acpi_resume(struct pci_dev *dev) +{ + return 1; +} +#endif + +MODULE_AUTHOR("Andrea Zhang "); +MODULE_DESCRIPTION("xgi kernel driver for xgi cards"); +MODULE_LICENSE("GPL"); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 568a7af1..429719a7 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -1,364 +1,364 @@ - -/**************************************************************************** - * 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_ - -#define XGI_MAJOR_VERSION 0 -#define XGI_MINOR_VERSION 7 -#define XGI_PATCHLEVEL 5 - -#define XGI_DRV_VERSION "0.7.5" - -#ifndef XGI_DRV_NAME -#define XGI_DRV_NAME "xgi" -#endif - -/* - * xgi reserved major device number, Set this to 0 to - * request dynamic major number allocation. - */ -#ifndef XGI_DEV_MAJOR -#define XGI_DEV_MAJOR 0 -#endif - -#ifndef XGI_MAX_DEVICES -#define XGI_MAX_DEVICES 1 -#endif - -/* Jong 06/06/2006 */ -/* #define XGI_DEBUG */ - -#ifndef PCI_VENDOR_ID_XGI -/* -#define PCI_VENDOR_ID_XGI 0x1023 -*/ -#define PCI_VENDOR_ID_XGI 0x18CA - -#endif - -#ifndef PCI_DEVICE_ID_XP5 -#define PCI_DEVICE_ID_XP5 0x2200 -#endif - -#ifndef PCI_DEVICE_ID_XG47 -#define PCI_DEVICE_ID_XG47 0x0047 -#endif - -/* Macros to make printk easier */ -#define XGI_ERROR(fmt, arg...) \ - printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) - -#define XGI_MEM_ERROR(area, fmt, arg...) \ - printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) - -/* #define XGI_DEBUG */ - -#ifdef XGI_DEBUG -#define XGI_INFO(fmt, arg...) \ - printk(KERN_ALERT "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) -/* printk(KERN_INFO "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) */ -#else -#define XGI_INFO(fmt, arg...) do { } while (0) -#endif - -/* device name length; must be atleast 8 */ -#define XGI_DEVICE_NAME_LENGTH 40 - -/* need a fake device number for control device; just to flag it for msgs */ -#define XGI_CONTROL_DEVICE_NUMBER 100 - -typedef struct { - U32 base; // pcie base is different from fb base - U32 size; - U8 *vbase; -} xgi_aperture_t; - -typedef struct xgi_screen_info_s { - U32 scrn_start; - U32 scrn_xres; - U32 scrn_yres; - U32 scrn_bpp; - U32 scrn_pitch; -} xgi_screen_info_t; - -typedef struct xgi_sarea_info_s { - U32 bus_addr; - U32 size; -} xgi_sarea_info_t; - -typedef struct xgi_info_s { - struct pci_dev *dev; - int flags; - int device_number; - int bus; /* PCI config info */ - int slot; - int vendor_id; - U32 device_id; - U8 revision_id; - - /* physical characteristics */ - xgi_aperture_t mmio; - xgi_aperture_t fb; - xgi_aperture_t pcie; - xgi_screen_info_t scrn_info; - xgi_sarea_info_t sarea_info; - - /* look up table parameters */ - U32 *lut_base; - U32 lutPageSize; - U32 lutPageOrder; - U32 isLUTInLFB; - U32 sdfbPageSize; - - U32 pcie_config; - U32 pcie_status; - U32 irq; - - atomic_t use_count; - - /* keep track of any pending bottom halfes */ - struct tasklet_struct tasklet; - - spinlock_t info_lock; - - struct semaphore info_sem; - struct semaphore fb_sem; - struct semaphore pcie_sem; -} xgi_info_t; - -typedef struct xgi_ioctl_post_vbios { - U32 bus; - U32 slot; -} xgi_ioctl_post_vbios_t; - -typedef enum xgi_mem_location_s -{ - NON_LOCAL = 0, - LOCAL = 1, - INVALID = 0x7fffffff -} xgi_mem_location_t; - -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 -}; - -typedef struct xgi_mem_req_s { - xgi_mem_location_t location; - unsigned long size; - unsigned long is_front; - enum PcieOwner owner; - unsigned long pid; -} xgi_mem_req_t; - -typedef struct xgi_mem_alloc_s { - xgi_mem_location_t location; - unsigned long size; - unsigned long bus_addr; - unsigned long hw_addr; - unsigned long pid; -} xgi_mem_alloc_t; - -typedef struct xgi_chip_info_s { - U32 device_id; - char device_name[32]; - U32 vendor_id; - U32 curr_display_mode; //Singe, DualView(Contained), MHS - U32 fb_size; - U32 sarea_bus_addr; - U32 sarea_size; -} xgi_chip_info_t; - -typedef struct xgi_opengl_cmd_s { - U32 cmd; -} xgi_opengl_cmd_t; - -typedef struct xgi_mmio_info_s { - xgi_opengl_cmd_t cmd_head; - void *mmioBase; - int size; -} xgi_mmio_info_t; - -typedef enum { - BTYPE_2D = 0, - BTYPE_3D = 1, - BTYPE_FLIP = 2, - BTYPE_CTRL = 3, - BTYPE_NONE = 0x7fffffff -}BATCH_TYPE; - -typedef struct xgi_cmd_info_s { - BATCH_TYPE _firstBeginType; - U32 _firstBeginAddr; - U32 _firstSize; - U32 _curDebugID; - U32 _lastBeginAddr; - U32 _beginCount; -} xgi_cmd_info_t; - -typedef struct xgi_state_info_s { - U32 _fromState; - U32 _toState; -} xgi_state_info_t; - -typedef struct cpu_info_s { - U32 _eax; - U32 _ebx; - U32 _ecx; - U32 _edx; -} cpu_info_t; - -typedef struct xgi_mem_pid_s { - struct list_head list; - xgi_mem_location_t location; - unsigned long bus_addr; - unsigned long pid; -} xgi_mem_pid_t; - -/* - * Ioctl definitions - */ - -#define XGI_IOCTL_MAGIC 'x' /* use 'x' as magic number */ - -#define XGI_IOCTL_BASE 0 -#define XGI_ESC_DEVICE_INFO (XGI_IOCTL_BASE + 0) -#define XGI_ESC_POST_VBIOS (XGI_IOCTL_BASE + 1) - -#define XGI_ESC_FB_INIT (XGI_IOCTL_BASE + 2) -#define XGI_ESC_FB_ALLOC (XGI_IOCTL_BASE + 3) -#define XGI_ESC_FB_FREE (XGI_IOCTL_BASE + 4) -#define XGI_ESC_PCIE_INIT (XGI_IOCTL_BASE + 5) -#define XGI_ESC_PCIE_ALLOC (XGI_IOCTL_BASE + 6) -#define XGI_ESC_PCIE_FREE (XGI_IOCTL_BASE + 7) -#define XGI_ESC_SUBMIT_CMDLIST (XGI_IOCTL_BASE + 8) -#define XGI_ESC_PUT_SCREEN_INFO (XGI_IOCTL_BASE + 9) -#define XGI_ESC_GET_SCREEN_INFO (XGI_IOCTL_BASE + 10) -#define XGI_ESC_GE_RESET (XGI_IOCTL_BASE + 11) -#define XGI_ESC_SAREA_INFO (XGI_IOCTL_BASE + 12) -#define XGI_ESC_DUMP_REGISTER (XGI_IOCTL_BASE + 13) -#define XGI_ESC_DEBUG_INFO (XGI_IOCTL_BASE + 14) -#define XGI_ESC_TEST_RWINKERNEL (XGI_IOCTL_BASE + 16) -#define XGI_ESC_STATE_CHANGE (XGI_IOCTL_BASE + 17) -#define XGI_ESC_MMIO_INFO (XGI_IOCTL_BASE + 18) -#define XGI_ESC_PCIE_CHECK (XGI_IOCTL_BASE + 19) -#define XGI_ESC_CPUID (XGI_IOCTL_BASE + 20) -#define XGI_ESC_MEM_COLLECT (XGI_IOCTL_BASE + 21) - -#define XGI_IOCTL_DEVICE_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_DEVICE_INFO, xgi_chip_info_t) -#define XGI_IOCTL_POST_VBIOS _IO(XGI_IOCTL_MAGIC, XGI_ESC_POST_VBIOS) - -#define XGI_IOCTL_FB_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_FB_INIT) -#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, xgi_mem_req_t) -#define XGI_IOCTL_FB_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_FB_FREE, unsigned long) - -#define XGI_IOCTL_PCIE_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_INIT) -#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, xgi_mem_req_t) -#define XGI_IOCTL_PCIE_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_FREE, unsigned long) - -#define XGI_IOCTL_PUT_SCREEN_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PUT_SCREEN_INFO, xgi_screen_info_t) -#define XGI_IOCTL_GET_SCREEN_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_GET_SCREEN_INFO, xgi_screen_info_t) - -#define XGI_IOCTL_GE_RESET _IO(XGI_IOCTL_MAGIC, XGI_ESC_GE_RESET) -#define XGI_IOCTL_SAREA_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_SAREA_INFO, xgi_sarea_info_t) -#define XGI_IOCTL_DUMP_REGISTER _IO(XGI_IOCTL_MAGIC, XGI_ESC_DUMP_REGISTER) -#define XGI_IOCTL_DEBUG_INFO _IO(XGI_IOCTL_MAGIC, XGI_ESC_DEBUG_INFO) -#define XGI_IOCTL_MMIO_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_MMIO_INFO, xgi_mmio_info_t) - -#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, xgi_cmd_info_t) -#define XGI_IOCTL_TEST_RWINKERNEL _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_TEST_RWINKERNEL, unsigned long) -#define XGI_IOCTL_STATE_CHANGE _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_STATE_CHANGE, xgi_state_info_t) - -#define XGI_IOCTL_PCIE_CHECK _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_CHECK) -#define XGI_IOCTL_CPUID _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_CPUID, cpu_info_t) -#define XGI_IOCTL_MAXNR 30 - -/* - * flags - */ -#define XGI_FLAG_OPEN 0x0001 -#define XGI_FLAG_NEEDS_POSTING 0x0002 -#define XGI_FLAG_WAS_POSTED 0x0004 -#define XGI_FLAG_CONTROL 0x0010 -#define XGI_FLAG_MAP_REGS_EARLY 0x0200 - -/* mmap(2) offsets */ - -#define IS_IO_OFFSET(info, offset, length) \ - (((offset) >= (info)->mmio.base) \ - && (((offset) + (length)) <= (info)->mmio.base + (info)->mmio.size)) - -/* Jong 06/14/2006 */ -/* (info)->fb.base is a base address for physical (bus) address space */ -/* what's the definition of offest? on physical (bus) address space or HW address space */ -/* Jong 06/15/2006; use HW address space */ -#define IS_FB_OFFSET(info, offset, length) \ - (((offset) >= 0) \ - && (((offset) + (length)) <= (info)->fb.size)) -#if 0 -#define IS_FB_OFFSET(info, offset, length) \ - (((offset) >= (info)->fb.base) \ - && (((offset) + (length)) <= (info)->fb.base + (info)->fb.size)) -#endif - -#define IS_PCIE_OFFSET(info, offset, length) \ - (((offset) >= (info)->pcie.base) \ - && (((offset) + (length)) <= (info)->pcie.base + (info)->pcie.size)) - -extern int xgi_fb_heap_init(xgi_info_t *info); -extern void xgi_fb_heap_cleanup(xgi_info_t *info); - -extern void xgi_fb_alloc(xgi_info_t *info, xgi_mem_req_t *req, xgi_mem_alloc_t *alloc); -extern void xgi_fb_free(xgi_info_t *info, unsigned long offset); -extern void xgi_mem_collect(xgi_info_t *info, unsigned int *pcnt); - -extern int xgi_pcie_heap_init(xgi_info_t *info); -extern void xgi_pcie_heap_cleanup(xgi_info_t *info); - -extern void xgi_pcie_alloc(xgi_info_t *info, unsigned long size, enum PcieOwner owner, xgi_mem_alloc_t *alloc); -extern void xgi_pcie_free(xgi_info_t *info, unsigned long offset); -extern void xgi_pcie_heap_check(void); -extern void *xgi_find_pcie_block(xgi_info_t *info, unsigned long address); -extern void *xgi_find_pcie_virt(xgi_info_t *info, unsigned long address); - -extern void xgi_read_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req); -extern void xgi_write_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req); - -extern void xgi_test_rwinkernel(xgi_info_t *info, unsigned long address); - -#endif + +/**************************************************************************** + * 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_ + +#define XGI_MAJOR_VERSION 0 +#define XGI_MINOR_VERSION 7 +#define XGI_PATCHLEVEL 5 + +#define XGI_DRV_VERSION "0.7.5" + +#ifndef XGI_DRV_NAME +#define XGI_DRV_NAME "xgi" +#endif + +/* + * xgi reserved major device number, Set this to 0 to + * request dynamic major number allocation. + */ +#ifndef XGI_DEV_MAJOR +#define XGI_DEV_MAJOR 0 +#endif + +#ifndef XGI_MAX_DEVICES +#define XGI_MAX_DEVICES 1 +#endif + +/* Jong 06/06/2006 */ +/* #define XGI_DEBUG */ + +#ifndef PCI_VENDOR_ID_XGI +/* +#define PCI_VENDOR_ID_XGI 0x1023 +*/ +#define PCI_VENDOR_ID_XGI 0x18CA + +#endif + +#ifndef PCI_DEVICE_ID_XP5 +#define PCI_DEVICE_ID_XP5 0x2200 +#endif + +#ifndef PCI_DEVICE_ID_XG47 +#define PCI_DEVICE_ID_XG47 0x0047 +#endif + +/* Macros to make printk easier */ +#define XGI_ERROR(fmt, arg...) \ + printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) + +#define XGI_MEM_ERROR(area, fmt, arg...) \ + printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) + +/* #define XGI_DEBUG */ + +#ifdef XGI_DEBUG +#define XGI_INFO(fmt, arg...) \ + printk(KERN_ALERT "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) +/* printk(KERN_INFO "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) */ +#else +#define XGI_INFO(fmt, arg...) do { } while (0) +#endif + +/* device name length; must be atleast 8 */ +#define XGI_DEVICE_NAME_LENGTH 40 + +/* need a fake device number for control device; just to flag it for msgs */ +#define XGI_CONTROL_DEVICE_NUMBER 100 + +typedef struct { + U32 base; // pcie base is different from fb base + U32 size; + U8 *vbase; +} xgi_aperture_t; + +typedef struct xgi_screen_info_s { + U32 scrn_start; + U32 scrn_xres; + U32 scrn_yres; + U32 scrn_bpp; + U32 scrn_pitch; +} xgi_screen_info_t; + +typedef struct xgi_sarea_info_s { + U32 bus_addr; + U32 size; +} xgi_sarea_info_t; + +typedef struct xgi_info_s { + struct pci_dev *dev; + int flags; + int device_number; + int bus; /* PCI config info */ + int slot; + int vendor_id; + U32 device_id; + U8 revision_id; + + /* physical characteristics */ + xgi_aperture_t mmio; + xgi_aperture_t fb; + xgi_aperture_t pcie; + xgi_screen_info_t scrn_info; + xgi_sarea_info_t sarea_info; + + /* look up table parameters */ + U32 *lut_base; + U32 lutPageSize; + U32 lutPageOrder; + U32 isLUTInLFB; + U32 sdfbPageSize; + + U32 pcie_config; + U32 pcie_status; + U32 irq; + + atomic_t use_count; + + /* keep track of any pending bottom halfes */ + struct tasklet_struct tasklet; + + spinlock_t info_lock; + + struct semaphore info_sem; + struct semaphore fb_sem; + struct semaphore pcie_sem; +} xgi_info_t; + +typedef struct xgi_ioctl_post_vbios { + U32 bus; + U32 slot; +} xgi_ioctl_post_vbios_t; + +typedef enum xgi_mem_location_s { + NON_LOCAL = 0, + LOCAL = 1, + INVALID = 0x7fffffff +} xgi_mem_location_t; + +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 +}; + +typedef struct xgi_mem_req_s { + xgi_mem_location_t location; + unsigned long size; + unsigned long is_front; + enum PcieOwner owner; + unsigned long pid; +} xgi_mem_req_t; + +typedef struct xgi_mem_alloc_s { + xgi_mem_location_t location; + unsigned long size; + unsigned long bus_addr; + unsigned long hw_addr; + unsigned long pid; +} xgi_mem_alloc_t; + +typedef struct xgi_chip_info_s { + U32 device_id; + char device_name[32]; + U32 vendor_id; + U32 curr_display_mode; //Singe, DualView(Contained), MHS + U32 fb_size; + U32 sarea_bus_addr; + U32 sarea_size; +} xgi_chip_info_t; + +typedef struct xgi_opengl_cmd_s { + U32 cmd; +} xgi_opengl_cmd_t; + +typedef struct xgi_mmio_info_s { + xgi_opengl_cmd_t cmd_head; + void *mmioBase; + int size; +} xgi_mmio_info_t; + +typedef enum { + BTYPE_2D = 0, + BTYPE_3D = 1, + BTYPE_FLIP = 2, + BTYPE_CTRL = 3, + BTYPE_NONE = 0x7fffffff +} BATCH_TYPE; + +typedef struct xgi_cmd_info_s { + BATCH_TYPE _firstBeginType; + U32 _firstBeginAddr; + U32 _firstSize; + U32 _curDebugID; + U32 _lastBeginAddr; + U32 _beginCount; +} xgi_cmd_info_t; + +typedef struct xgi_state_info_s { + U32 _fromState; + U32 _toState; +} xgi_state_info_t; + +typedef struct cpu_info_s { + U32 _eax; + U32 _ebx; + U32 _ecx; + U32 _edx; +} cpu_info_t; + +typedef struct xgi_mem_pid_s { + struct list_head list; + xgi_mem_location_t location; + unsigned long bus_addr; + unsigned long pid; +} xgi_mem_pid_t; + +/* + * Ioctl definitions + */ + +#define XGI_IOCTL_MAGIC 'x' /* use 'x' as magic number */ + +#define XGI_IOCTL_BASE 0 +#define XGI_ESC_DEVICE_INFO (XGI_IOCTL_BASE + 0) +#define XGI_ESC_POST_VBIOS (XGI_IOCTL_BASE + 1) + +#define XGI_ESC_FB_INIT (XGI_IOCTL_BASE + 2) +#define XGI_ESC_FB_ALLOC (XGI_IOCTL_BASE + 3) +#define XGI_ESC_FB_FREE (XGI_IOCTL_BASE + 4) +#define XGI_ESC_PCIE_INIT (XGI_IOCTL_BASE + 5) +#define XGI_ESC_PCIE_ALLOC (XGI_IOCTL_BASE + 6) +#define XGI_ESC_PCIE_FREE (XGI_IOCTL_BASE + 7) +#define XGI_ESC_SUBMIT_CMDLIST (XGI_IOCTL_BASE + 8) +#define XGI_ESC_PUT_SCREEN_INFO (XGI_IOCTL_BASE + 9) +#define XGI_ESC_GET_SCREEN_INFO (XGI_IOCTL_BASE + 10) +#define XGI_ESC_GE_RESET (XGI_IOCTL_BASE + 11) +#define XGI_ESC_SAREA_INFO (XGI_IOCTL_BASE + 12) +#define XGI_ESC_DUMP_REGISTER (XGI_IOCTL_BASE + 13) +#define XGI_ESC_DEBUG_INFO (XGI_IOCTL_BASE + 14) +#define XGI_ESC_TEST_RWINKERNEL (XGI_IOCTL_BASE + 16) +#define XGI_ESC_STATE_CHANGE (XGI_IOCTL_BASE + 17) +#define XGI_ESC_MMIO_INFO (XGI_IOCTL_BASE + 18) +#define XGI_ESC_PCIE_CHECK (XGI_IOCTL_BASE + 19) +#define XGI_ESC_CPUID (XGI_IOCTL_BASE + 20) +#define XGI_ESC_MEM_COLLECT (XGI_IOCTL_BASE + 21) + +#define XGI_IOCTL_DEVICE_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_DEVICE_INFO, xgi_chip_info_t) +#define XGI_IOCTL_POST_VBIOS _IO(XGI_IOCTL_MAGIC, XGI_ESC_POST_VBIOS) + +#define XGI_IOCTL_FB_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_FB_INIT) +#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, xgi_mem_req_t) +#define XGI_IOCTL_FB_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_FB_FREE, unsigned long) + +#define XGI_IOCTL_PCIE_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_INIT) +#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, xgi_mem_req_t) +#define XGI_IOCTL_PCIE_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_FREE, unsigned long) + +#define XGI_IOCTL_PUT_SCREEN_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PUT_SCREEN_INFO, xgi_screen_info_t) +#define XGI_IOCTL_GET_SCREEN_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_GET_SCREEN_INFO, xgi_screen_info_t) + +#define XGI_IOCTL_GE_RESET _IO(XGI_IOCTL_MAGIC, XGI_ESC_GE_RESET) +#define XGI_IOCTL_SAREA_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_SAREA_INFO, xgi_sarea_info_t) +#define XGI_IOCTL_DUMP_REGISTER _IO(XGI_IOCTL_MAGIC, XGI_ESC_DUMP_REGISTER) +#define XGI_IOCTL_DEBUG_INFO _IO(XGI_IOCTL_MAGIC, XGI_ESC_DEBUG_INFO) +#define XGI_IOCTL_MMIO_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_MMIO_INFO, xgi_mmio_info_t) + +#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, xgi_cmd_info_t) +#define XGI_IOCTL_TEST_RWINKERNEL _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_TEST_RWINKERNEL, unsigned long) +#define XGI_IOCTL_STATE_CHANGE _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_STATE_CHANGE, xgi_state_info_t) + +#define XGI_IOCTL_PCIE_CHECK _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_CHECK) +#define XGI_IOCTL_CPUID _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_CPUID, cpu_info_t) +#define XGI_IOCTL_MAXNR 30 + +/* + * flags + */ +#define XGI_FLAG_OPEN 0x0001 +#define XGI_FLAG_NEEDS_POSTING 0x0002 +#define XGI_FLAG_WAS_POSTED 0x0004 +#define XGI_FLAG_CONTROL 0x0010 +#define XGI_FLAG_MAP_REGS_EARLY 0x0200 + +/* mmap(2) offsets */ + +#define IS_IO_OFFSET(info, offset, length) \ + (((offset) >= (info)->mmio.base) \ + && (((offset) + (length)) <= (info)->mmio.base + (info)->mmio.size)) + +/* Jong 06/14/2006 */ +/* (info)->fb.base is a base address for physical (bus) address space */ +/* what's the definition of offest? on physical (bus) address space or HW address space */ +/* Jong 06/15/2006; use HW address space */ +#define IS_FB_OFFSET(info, offset, length) \ + (((offset) >= 0) \ + && (((offset) + (length)) <= (info)->fb.size)) +#if 0 +#define IS_FB_OFFSET(info, offset, length) \ + (((offset) >= (info)->fb.base) \ + && (((offset) + (length)) <= (info)->fb.base + (info)->fb.size)) +#endif + +#define IS_PCIE_OFFSET(info, offset, length) \ + (((offset) >= (info)->pcie.base) \ + && (((offset) + (length)) <= (info)->pcie.base + (info)->pcie.size)) + +extern int xgi_fb_heap_init(xgi_info_t * info); +extern void xgi_fb_heap_cleanup(xgi_info_t * info); + +extern void xgi_fb_alloc(xgi_info_t * info, xgi_mem_req_t * req, + xgi_mem_alloc_t * alloc); +extern void xgi_fb_free(xgi_info_t * info, unsigned long offset); +extern void xgi_mem_collect(xgi_info_t * info, unsigned int *pcnt); + +extern int xgi_pcie_heap_init(xgi_info_t * info); +extern void xgi_pcie_heap_cleanup(xgi_info_t * info); + +extern void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, + enum PcieOwner owner, xgi_mem_alloc_t * alloc); +extern void xgi_pcie_free(xgi_info_t * info, unsigned long offset); +extern void xgi_pcie_heap_check(void); +extern void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address); +extern void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address); + +extern void xgi_read_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req); +extern void xgi_write_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req); + +extern void xgi_test_rwinkernel(xgi_info_t * info, unsigned long address); + +#endif diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 67fdfe17..fab99ae2 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -1,528 +1,491 @@ - -/**************************************************************************** - * 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_types.h" -#include "xgi_linux.h" -#include "xgi_drv.h" -#include "xgi_fb.h" - -#define XGI_FB_HEAP_START 0x1000000 - -static xgi_mem_heap_t *xgi_fb_heap; -static kmem_cache_t *xgi_fb_cache_block = NULL; -extern struct list_head xgi_mempid_list; - -static xgi_mem_block_t *xgi_mem_new_node(void); -static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t *info, unsigned long size); -static xgi_mem_block_t *xgi_mem_free(xgi_info_t *info, unsigned long offset); - -void xgi_fb_alloc(xgi_info_t *info, - xgi_mem_req_t *req, - xgi_mem_alloc_t *alloc) -{ - xgi_mem_block_t *block; - xgi_mem_pid_t *mempid_block; - - if (req->is_front) - { - alloc->location = LOCAL; - alloc->bus_addr = info->fb.base; - alloc->hw_addr = 0; - XGI_INFO("Video RAM allocation on front buffer successfully! \n"); - } - else - { - xgi_down(info->fb_sem); - block = xgi_mem_alloc(info, req->size); - xgi_up(info->fb_sem); - - if (block == NULL) - { - alloc->location = LOCAL; - alloc->size = 0; - alloc->bus_addr = 0; - alloc->hw_addr = 0; - XGI_ERROR("Video RAM allocation failed\n"); - } - else - { - XGI_INFO("Video RAM allocation succeeded: 0x%p\n", - (char *) block->offset); - alloc->location = LOCAL; - alloc->size = block->size; - alloc->bus_addr = info->fb.base + block->offset; - alloc->hw_addr = block->offset; - - /* manage mempid */ - mempid_block = kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); - mempid_block->location = LOCAL; - mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = alloc->pid; - - if (!mempid_block) - XGI_ERROR("mempid_block alloc failed\n"); - - XGI_INFO("Memory ProcessID add one fb block pid:%ld successfully! \n", mempid_block->pid); - list_add(&mempid_block->list, &xgi_mempid_list); - } - } -} - -void xgi_fb_free(xgi_info_t *info, unsigned long bus_addr) -{ - xgi_mem_block_t *block; - unsigned long offset = bus_addr - info->fb.base; - xgi_mem_pid_t *mempid_block; - xgi_mem_pid_t *mempid_freeblock = NULL; - struct list_head *mempid_list; - - if (offset < 0) - { - XGI_INFO("free onscreen frame buffer successfully !\n"); - } - else - { - xgi_down(info->fb_sem); - block = xgi_mem_free(info, offset); - xgi_up(info->fb_sem); - - if (block == NULL) - { - XGI_ERROR("xgi_mem_free() failed at base 0x%lx\n", offset); - } - - /* manage mempid */ - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) - { - mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); - if (mempid_block->location == LOCAL && mempid_block->bus_addr == bus_addr) - { - mempid_freeblock = mempid_block; - break; - } - mempid_list = mempid_list->next; - } - if (mempid_freeblock) - { - list_del(&mempid_freeblock->list); - XGI_INFO("Memory ProcessID delete one fb block pid:%ld successfully! \n", mempid_freeblock->pid); - kfree(mempid_freeblock); - } - } -} - -int xgi_fb_heap_init(xgi_info_t *info) -{ - xgi_mem_block_t *block; - - xgi_fb_heap = kmalloc(sizeof(xgi_mem_heap_t), GFP_KERNEL); - if (!xgi_fb_heap) - { - XGI_ERROR("xgi_fb_heap alloc failed\n"); - return 0; - } - - INIT_LIST_HEAD(&xgi_fb_heap->free_list); - INIT_LIST_HEAD(&xgi_fb_heap->used_list); - INIT_LIST_HEAD(&xgi_fb_heap->sort_list); - - xgi_fb_cache_block = kmem_cache_create("xgi_fb_block", sizeof(xgi_mem_block_t), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - if (NULL == xgi_fb_cache_block) - { - XGI_ERROR("Fail to creat xgi_fb_block\n"); - goto fail1; - } - - block = (xgi_mem_block_t *)kmem_cache_alloc(xgi_fb_cache_block, GFP_KERNEL); - if (!block) - { - XGI_ERROR("kmem_cache_alloc failed\n"); - goto fail2; - } - - block->offset = XGI_FB_HEAP_START; - block->size = info->fb.size - XGI_FB_HEAP_START; - - list_add(&block->list, &xgi_fb_heap->free_list); - - xgi_fb_heap->max_freesize = info->fb.size - XGI_FB_HEAP_START; - - XGI_INFO("fb start offset: 0x%lx, memory size : 0x%lx\n", block->offset, block->size); - XGI_INFO("xgi_fb_heap->max_freesize: 0x%lx \n", xgi_fb_heap->max_freesize); - - return 1; - -fail2: - if (xgi_fb_cache_block) - { - kmem_cache_destroy(xgi_fb_cache_block); - xgi_fb_cache_block = NULL; - } -fail1: - if(xgi_fb_heap) - { - kfree(xgi_fb_heap); - xgi_fb_heap = NULL; - } - return 0; -} - -void xgi_fb_heap_cleanup(xgi_info_t *info) -{ - struct list_head *free_list, *temp; - xgi_mem_block_t *block; - int i; - - if (xgi_fb_heap) - { - free_list = &xgi_fb_heap->free_list; - for (i = 0; i < 3; i++, free_list++) - { - temp = free_list->next; - while (temp != free_list) - { - block = list_entry(temp, struct xgi_mem_block_s, list); - temp = temp->next; - - XGI_INFO("No. %d block->offset: 0x%lx block->size: 0x%lx \n", - i, block->offset, block->size); - //XGI_INFO("No. %d free block: 0x%p \n", i, block); - kmem_cache_free(xgi_fb_cache_block, block); - block = NULL; - } - } - XGI_INFO("xgi_fb_heap: 0x%p \n", xgi_fb_heap); - kfree(xgi_fb_heap); - xgi_fb_heap = NULL; - } - - if (xgi_fb_cache_block) - { - kmem_cache_destroy(xgi_fb_cache_block); - xgi_fb_cache_block = NULL; - } -} - -static xgi_mem_block_t * xgi_mem_new_node(void) -{ - xgi_mem_block_t *block; - - block = (xgi_mem_block_t *)kmem_cache_alloc(xgi_fb_cache_block, GFP_KERNEL); - if (!block) - { - XGI_ERROR("kmem_cache_alloc failed\n"); - return NULL; - } - - return block; -} - -#if 0 -static void xgi_mem_insert_node_after(xgi_mem_list_t *list, - xgi_mem_block_t *current, - xgi_mem_block_t *block); -static void xgi_mem_insert_node_before(xgi_mem_list_t *list, - xgi_mem_block_t *current, - xgi_mem_block_t *block); -static void xgi_mem_insert_node_head(xgi_mem_list_t *list, - xgi_mem_block_t *block); -static void xgi_mem_insert_node_tail(xgi_mem_list_t *list, - xgi_mem_block_t *block); -static void xgi_mem_delete_node(xgi_mem_list_t *list, - xgi_mem_block_t *block); -/* - * insert node:block after node:current - */ -static void xgi_mem_insert_node_after(xgi_mem_list_t *list, - xgi_mem_block_t *current, - xgi_mem_block_t *block) -{ - block->prev = current; - block->next = current->next; - current->next = block; - - if (current == list->tail) - { - list->tail = block; - } - else - { - block->next->prev = block; - } -} - -/* - * insert node:block before node:current - */ -static void xgi_mem_insert_node_before(xgi_mem_list_t *list, - xgi_mem_block_t *current, - xgi_mem_block_t *block) -{ - block->prev = current->prev; - block->next = current; - current->prev = block; - if (current == list->head) - { - list->head = block; - } - else - { - block->prev->next = block; - } -} -void xgi_mem_insert_node_head(xgi_mem_list_t *list, - xgi_mem_block_t *block) -{ - block->next = list->head; - block->prev = NULL; - - if (NULL == list->head) - { - list->tail = block; - } - else - { - list->head->prev = block; - } - list->head = block; -} - -static void xgi_mem_insert_node_tail(xgi_mem_list_t *list, - xgi_mem_block_t *block) - -{ - block->next = NULL; - block->prev = list->tail; - if (NULL == list->tail) - { - list->head = block; - } - else - { - list->tail->next = block; - } - list->tail = block; -} - -static void xgi_mem_delete_node(xgi_mem_list_t *list, - xgi_mem_block_t *block) -{ - if (block == list->head) - { - list->head = block->next; - } - if (block == list->tail) - { - list->tail = block->prev; - } - - if (block->prev) - { - block->prev->next = block->next; - } - if (block->next) - { - block->next->prev = block->prev; - } - - block->next = block->prev = NULL; -} -#endif -static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t *info, unsigned long originalSize) -{ - struct list_head *free_list; - xgi_mem_block_t *block, *free_block, *used_block; - - unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; - - XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", originalSize, size); - - if (size == 0) - { - XGI_ERROR("size == 0\n"); - return (NULL); - } - XGI_INFO("max_freesize: 0x%lx \n", xgi_fb_heap->max_freesize); - if (size > xgi_fb_heap->max_freesize) - { - XGI_ERROR("size: 0x%lx is bigger than frame buffer total free size: 0x%lx !\n", - size, xgi_fb_heap->max_freesize); - return (NULL); - } - - free_list = xgi_fb_heap->free_list.next; - - while (free_list != &xgi_fb_heap->free_list) - { - XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_mem_block_s, list); - if (size <= block->size) - { - break; - } - free_list = free_list->next; - } - - if (free_list == &xgi_fb_heap->free_list) - { - XGI_ERROR("Can't allocate %ldk size from frame buffer memory !\n", size/1024); - return (NULL); - } - - free_block = block; - XGI_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; - XGI_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) - { - XGI_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; - } - - xgi_fb_heap->max_freesize -= size; - - list_add(&used_block->list, &xgi_fb_heap->used_list); - - return (used_block); -} - -static xgi_mem_block_t *xgi_mem_free(xgi_info_t *info, unsigned long offset) -{ - struct list_head *free_list, *used_list; - xgi_mem_block_t *used_block = NULL, *block = NULL; - xgi_mem_block_t *prev, *next; - - unsigned long upper; - unsigned long lower; - - used_list = xgi_fb_heap->used_list.next; - while (used_list != &xgi_fb_heap->used_list) - { - block = list_entry(used_list, struct xgi_mem_block_s, list); - if (block->offset == offset) - { - break; - } - used_list = used_list->next; - } - - if (used_list == &xgi_fb_heap->used_list) - { - XGI_ERROR("can't find block: 0x%lx to free!\n", offset); - return (NULL); - } - - used_block = block; - XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx\n", - used_block, used_block->offset, used_block->size); - - xgi_fb_heap->max_freesize += used_block->size; - - prev = next = NULL; - upper = used_block->offset + used_block->size; - lower = used_block->offset; - - free_list = xgi_fb_heap->free_list.next; - while (free_list != &xgi_fb_heap->free_list) - { - block = list_entry(free_list, struct xgi_mem_block_s, list); - - if (block->offset == upper) - { - next = block; - } - else if ((block->offset + block->size) == lower) - { - prev = block; - } - free_list = free_list->next; - } - - XGI_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); - XGI_INFO("free node 0x%p\n", next); - kmem_cache_free(xgi_fb_cache_block, next); - kmem_cache_free(xgi_fb_cache_block, used_block); - - next = NULL; - used_block = NULL; - return (prev); - } - - if (prev) - { - prev->size += used_block->size; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_fb_cache_block, used_block); - used_block = NULL; - return (prev); - } - - if (next) - { - next->size += used_block->size; - next->offset = used_block->offset; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_fb_cache_block, used_block); - used_block = NULL; - return (next); - } - - list_add(&used_block->list, &xgi_fb_heap->free_list); - XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", - used_block, used_block->offset, used_block->size); - - return (used_block); -} - + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_fb.h" + +#define XGI_FB_HEAP_START 0x1000000 + +static xgi_mem_heap_t *xgi_fb_heap; +static kmem_cache_t *xgi_fb_cache_block = NULL; +extern struct list_head xgi_mempid_list; + +static xgi_mem_block_t *xgi_mem_new_node(void); +static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t * info, unsigned long size); +static xgi_mem_block_t *xgi_mem_free(xgi_info_t * info, unsigned long offset); + +void xgi_fb_alloc(xgi_info_t * info, + xgi_mem_req_t * req, xgi_mem_alloc_t * alloc) +{ + xgi_mem_block_t *block; + xgi_mem_pid_t *mempid_block; + + if (req->is_front) { + alloc->location = LOCAL; + alloc->bus_addr = info->fb.base; + alloc->hw_addr = 0; + XGI_INFO + ("Video RAM allocation on front buffer successfully! \n"); + } else { + xgi_down(info->fb_sem); + block = xgi_mem_alloc(info, req->size); + xgi_up(info->fb_sem); + + if (block == NULL) { + alloc->location = LOCAL; + alloc->size = 0; + alloc->bus_addr = 0; + alloc->hw_addr = 0; + XGI_ERROR("Video RAM allocation failed\n"); + } else { + XGI_INFO("Video RAM allocation succeeded: 0x%p\n", + (char *)block->offset); + alloc->location = LOCAL; + alloc->size = block->size; + alloc->bus_addr = info->fb.base + block->offset; + alloc->hw_addr = block->offset; + + /* manage mempid */ + mempid_block = + kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + mempid_block->location = LOCAL; + mempid_block->bus_addr = alloc->bus_addr; + mempid_block->pid = alloc->pid; + + if (!mempid_block) + XGI_ERROR("mempid_block alloc failed\n"); + + XGI_INFO + ("Memory ProcessID add one fb block pid:%ld successfully! \n", + mempid_block->pid); + list_add(&mempid_block->list, &xgi_mempid_list); + } + } +} + +void xgi_fb_free(xgi_info_t * info, unsigned long bus_addr) +{ + xgi_mem_block_t *block; + unsigned long offset = bus_addr - info->fb.base; + xgi_mem_pid_t *mempid_block; + xgi_mem_pid_t *mempid_freeblock = NULL; + struct list_head *mempid_list; + + if (offset < 0) { + XGI_INFO("free onscreen frame buffer successfully !\n"); + } else { + xgi_down(info->fb_sem); + block = xgi_mem_free(info, offset); + xgi_up(info->fb_sem); + + if (block == NULL) { + XGI_ERROR("xgi_mem_free() failed at base 0x%lx\n", + offset); + } + + /* manage mempid */ + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) { + mempid_block = + list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == LOCAL + && mempid_block->bus_addr == bus_addr) { + mempid_freeblock = mempid_block; + break; + } + mempid_list = mempid_list->next; + } + if (mempid_freeblock) { + list_del(&mempid_freeblock->list); + XGI_INFO + ("Memory ProcessID delete one fb block pid:%ld successfully! \n", + mempid_freeblock->pid); + kfree(mempid_freeblock); + } + } +} + +int xgi_fb_heap_init(xgi_info_t * info) +{ + xgi_mem_block_t *block; + + xgi_fb_heap = kmalloc(sizeof(xgi_mem_heap_t), GFP_KERNEL); + if (!xgi_fb_heap) { + XGI_ERROR("xgi_fb_heap alloc failed\n"); + return 0; + } + + INIT_LIST_HEAD(&xgi_fb_heap->free_list); + INIT_LIST_HEAD(&xgi_fb_heap->used_list); + INIT_LIST_HEAD(&xgi_fb_heap->sort_list); + + xgi_fb_cache_block = + kmem_cache_create("xgi_fb_block", sizeof(xgi_mem_block_t), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (NULL == xgi_fb_cache_block) { + XGI_ERROR("Fail to creat xgi_fb_block\n"); + goto fail1; + } + + block = + (xgi_mem_block_t *) kmem_cache_alloc(xgi_fb_cache_block, + GFP_KERNEL); + if (!block) { + XGI_ERROR("kmem_cache_alloc failed\n"); + goto fail2; + } + + block->offset = XGI_FB_HEAP_START; + block->size = info->fb.size - XGI_FB_HEAP_START; + + list_add(&block->list, &xgi_fb_heap->free_list); + + xgi_fb_heap->max_freesize = info->fb.size - XGI_FB_HEAP_START; + + XGI_INFO("fb start offset: 0x%lx, memory size : 0x%lx\n", block->offset, + block->size); + XGI_INFO("xgi_fb_heap->max_freesize: 0x%lx \n", + xgi_fb_heap->max_freesize); + + return 1; + + fail2: + if (xgi_fb_cache_block) { + kmem_cache_destroy(xgi_fb_cache_block); + xgi_fb_cache_block = NULL; + } + fail1: + if (xgi_fb_heap) { + kfree(xgi_fb_heap); + xgi_fb_heap = NULL; + } + return 0; +} + +void xgi_fb_heap_cleanup(xgi_info_t * info) +{ + struct list_head *free_list, *temp; + xgi_mem_block_t *block; + int i; + + if (xgi_fb_heap) { + free_list = &xgi_fb_heap->free_list; + for (i = 0; i < 3; i++, free_list++) { + temp = free_list->next; + while (temp != free_list) { + block = + list_entry(temp, struct xgi_mem_block_s, + list); + temp = temp->next; + + XGI_INFO + ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + i, block->offset, block->size); + //XGI_INFO("No. %d free block: 0x%p \n", i, block); + kmem_cache_free(xgi_fb_cache_block, block); + block = NULL; + } + } + XGI_INFO("xgi_fb_heap: 0x%p \n", xgi_fb_heap); + kfree(xgi_fb_heap); + xgi_fb_heap = NULL; + } + + if (xgi_fb_cache_block) { + kmem_cache_destroy(xgi_fb_cache_block); + xgi_fb_cache_block = NULL; + } +} + +static xgi_mem_block_t *xgi_mem_new_node(void) +{ + xgi_mem_block_t *block; + + block = + (xgi_mem_block_t *) kmem_cache_alloc(xgi_fb_cache_block, + GFP_KERNEL); + if (!block) { + XGI_ERROR("kmem_cache_alloc failed\n"); + return NULL; + } + + return block; +} + +#if 0 +static void xgi_mem_insert_node_after(xgi_mem_list_t * list, + xgi_mem_block_t * current, + xgi_mem_block_t * block); +static void xgi_mem_insert_node_before(xgi_mem_list_t * list, + xgi_mem_block_t * current, + xgi_mem_block_t * block); +static void xgi_mem_insert_node_head(xgi_mem_list_t * list, + xgi_mem_block_t * block); +static void xgi_mem_insert_node_tail(xgi_mem_list_t * list, + xgi_mem_block_t * block); +static void xgi_mem_delete_node(xgi_mem_list_t * list, xgi_mem_block_t * block); +/* + * insert node:block after node:current + */ +static void xgi_mem_insert_node_after(xgi_mem_list_t * list, + xgi_mem_block_t * current, + xgi_mem_block_t * block) +{ + block->prev = current; + block->next = current->next; + current->next = block; + + if (current == list->tail) { + list->tail = block; + } else { + block->next->prev = block; + } +} + +/* + * insert node:block before node:current + */ +static void xgi_mem_insert_node_before(xgi_mem_list_t * list, + xgi_mem_block_t * current, + xgi_mem_block_t * block) +{ + block->prev = current->prev; + block->next = current; + current->prev = block; + if (current == list->head) { + list->head = block; + } else { + block->prev->next = block; + } +} +void xgi_mem_insert_node_head(xgi_mem_list_t * list, xgi_mem_block_t * block) +{ + block->next = list->head; + block->prev = NULL; + + if (NULL == list->head) { + list->tail = block; + } else { + list->head->prev = block; + } + list->head = block; +} + +static void xgi_mem_insert_node_tail(xgi_mem_list_t * list, + xgi_mem_block_t * block) +{ + block->next = NULL; + block->prev = list->tail; + if (NULL == list->tail) { + list->head = block; + } else { + list->tail->next = block; + } + list->tail = block; +} + +static void xgi_mem_delete_node(xgi_mem_list_t * list, xgi_mem_block_t * block) +{ + if (block == list->head) { + list->head = block->next; + } + if (block == list->tail) { + list->tail = block->prev; + } + + if (block->prev) { + block->prev->next = block->next; + } + if (block->next) { + block->next->prev = block->prev; + } + + block->next = block->prev = NULL; +} +#endif +static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t * info, + unsigned long originalSize) +{ + struct list_head *free_list; + xgi_mem_block_t *block, *free_block, *used_block; + + unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; + + XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", + originalSize, size); + + if (size == 0) { + XGI_ERROR("size == 0\n"); + return (NULL); + } + XGI_INFO("max_freesize: 0x%lx \n", xgi_fb_heap->max_freesize); + if (size > xgi_fb_heap->max_freesize) { + XGI_ERROR + ("size: 0x%lx is bigger than frame buffer total free size: 0x%lx !\n", + size, xgi_fb_heap->max_freesize); + return (NULL); + } + + free_list = xgi_fb_heap->free_list.next; + + while (free_list != &xgi_fb_heap->free_list) { + XGI_INFO("free_list: 0x%px \n", free_list); + block = list_entry(free_list, struct xgi_mem_block_s, list); + if (size <= block->size) { + break; + } + free_list = free_list->next; + } + + if (free_list == &xgi_fb_heap->free_list) { + XGI_ERROR + ("Can't allocate %ldk size from frame buffer memory !\n", + size / 1024); + return (NULL); + } + + free_block = block; + XGI_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; + XGI_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) { + XGI_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; + } + + xgi_fb_heap->max_freesize -= size; + + list_add(&used_block->list, &xgi_fb_heap->used_list); + + return (used_block); +} + +static xgi_mem_block_t *xgi_mem_free(xgi_info_t * info, unsigned long offset) +{ + struct list_head *free_list, *used_list; + xgi_mem_block_t *used_block = NULL, *block = NULL; + xgi_mem_block_t *prev, *next; + + unsigned long upper; + unsigned long lower; + + used_list = xgi_fb_heap->used_list.next; + while (used_list != &xgi_fb_heap->used_list) { + block = list_entry(used_list, struct xgi_mem_block_s, list); + if (block->offset == offset) { + break; + } + used_list = used_list->next; + } + + if (used_list == &xgi_fb_heap->used_list) { + XGI_ERROR("can't find block: 0x%lx to free!\n", offset); + return (NULL); + } + + used_block = block; + XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + + xgi_fb_heap->max_freesize += used_block->size; + + prev = next = NULL; + upper = used_block->offset + used_block->size; + lower = used_block->offset; + + free_list = xgi_fb_heap->free_list.next; + while (free_list != &xgi_fb_heap->free_list) { + block = list_entry(free_list, struct xgi_mem_block_s, list); + + if (block->offset == upper) { + next = block; + } else if ((block->offset + block->size) == lower) { + prev = block; + } + free_list = free_list->next; + } + + XGI_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); + XGI_INFO("free node 0x%p\n", next); + kmem_cache_free(xgi_fb_cache_block, next); + kmem_cache_free(xgi_fb_cache_block, used_block); + + next = NULL; + used_block = NULL; + return (prev); + } + + if (prev) { + prev->size += used_block->size; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_fb_cache_block, used_block); + used_block = NULL; + return (prev); + } + + if (next) { + next->size += used_block->size; + next->offset = used_block->offset; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_fb_cache_block, used_block); + used_block = NULL; + return (next); + } + + list_add(&used_block->list, &xgi_fb_heap->free_list); + XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + + return (used_block); +} diff --git a/linux-core/xgi_fb.h b/linux-core/xgi_fb.h index 4b7ec2f2..ae078ae0 100644 --- a/linux-core/xgi_fb.h +++ b/linux-core/xgi_fb.h @@ -1,71 +1,70 @@ - -/**************************************************************************** - * 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_FB_H_ -#define _XGI_FB_H_ - -typedef struct xgi_mem_block_s { - struct list_head list; - unsigned long offset; - unsigned long size; - atomic_t use_count; -} xgi_mem_block_t; - -typedef struct xgi_mem_heap_s { - struct list_head free_list; - struct list_head used_list; - struct list_head sort_list; - unsigned long max_freesize; - spinlock_t lock; -} xgi_mem_heap_t; - -#if 0 -typedef struct xgi_mem_block_s { - struct xgi_mem_block_s *next; - struct xgi_mem_block_s *prev; - unsigned long offset; - unsigned long size; - atomic_t use_count; -} xgi_mem_block_t; - -typedef struct xgi_mem_list_s { - xgi_mem_block_t *head; - xgi_mem_block_t *tail; -} xgi_mem_list_t; - -typedef struct xgi_mem_heap_s { - xgi_mem_list_t *free_list; - xgi_mem_list_t *used_list; - xgi_mem_list_t *sort_list; - unsigned long max_freesize; - spinlock_t lock; -} xgi_mem_heap_t; -#endif - -#endif - + +/**************************************************************************** + * 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_FB_H_ +#define _XGI_FB_H_ + +typedef struct xgi_mem_block_s { + struct list_head list; + unsigned long offset; + unsigned long size; + atomic_t use_count; +} xgi_mem_block_t; + +typedef struct xgi_mem_heap_s { + struct list_head free_list; + struct list_head used_list; + struct list_head sort_list; + unsigned long max_freesize; + spinlock_t lock; +} xgi_mem_heap_t; + +#if 0 +typedef struct xgi_mem_block_s { + struct xgi_mem_block_s *next; + struct xgi_mem_block_s *prev; + unsigned long offset; + unsigned long size; + atomic_t use_count; +} xgi_mem_block_t; + +typedef struct xgi_mem_list_s { + xgi_mem_block_t *head; + xgi_mem_block_t *tail; +} xgi_mem_list_t; + +typedef struct xgi_mem_heap_s { + xgi_mem_list_t *free_list; + xgi_mem_list_t *used_list; + xgi_mem_list_t *sort_list; + unsigned long max_freesize; + spinlock_t lock; +} xgi_mem_heap_t; +#endif + +#endif diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h index f207a4f6..67c1af82 100644 --- a/linux-core/xgi_linux.h +++ b/linux-core/xgi_linux.h @@ -1,596 +1,591 @@ - -/**************************************************************************** - * 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_LINUX_H_ -#define _XGI_LINUX_H_ - -#include - -#ifndef LINUX_VERSION_CODE -#include -#endif - -#ifndef KERNEL_VERSION /* pre-2.1.90 didn't have it */ -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -# error "This driver does not support pre-2.4 kernels!" -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -#define KERNEL_2_4 -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -# error "This driver does not support 2.5 kernels!" -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0) -#define KERNEL_2_6 -#else -# error "This driver does not support development kernels!" -#endif - -#if defined (CONFIG_SMP) && !defined (__SMP__) -#define __SMP__ -#endif - -#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) -#define MODVERSIONS -#endif - -#if defined (MODVERSIONS) && !defined (KERNEL_2_6) -#include -#endif - -#include /* printk */ -#include - -#include /* module_init, module_exit */ -#include /* pic_t, size_t, __u32, etc */ -#include /* error codes */ -#include /* circular linked list */ -#include /* NULL, offsetof */ -#include /* wait queues */ - -#include /* kmalloc, kfree, etc */ -#include /* vmalloc, vfree, etc */ - -#include /* poll_wait */ -#include /* mdelay, udelay */ -#include /* rdtsc rdtscl */ - -#include /* suser(), capable() replacement - for_each_task, for_each_process */ -#ifdef for_each_process -#define XGI_SCAN_PROCESS(p) for_each_process(p) -#else -#define XGI_SCAN_PROCESS(p) for_each_task(p) -#endif - -#ifdef KERNEL_2_6 -#include /* module_param() */ -#include /* kernel_locked */ -#include /* flush_tlb(), flush_tlb_all() */ -#include /* page table entry lookup */ -#endif - -#include /* pci_find_class, etc */ -#include /* tasklets, interrupt helpers */ -#include - -#include /* cli, sli, save_flags */ -#include /* ioremap, virt_to_phys */ -#include /* access_ok */ -#include /* PAGE_OFFSET */ -#include /* pte bit definitions */ - -#include -#include -#include - -#ifdef CONFIG_PROC_FS -#include -#endif - -#ifdef CONFIG_DEVFS_FS -#include -#endif - -#ifdef CONFIG_KMOD -#include -#endif - -#ifdef CONFIG_PM -#include -#endif - -#ifdef CONFIG_MTRR -#include -#endif - -#ifdef CONFIG_KDB -#include -#include -#endif - -#if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE) -#define AGPGART -#include -#include -#endif - -#ifndef MAX_ORDER -#ifdef KERNEL_2_4 -#define MAX_ORDER 10 -#endif -#ifdef KERNEL_2_6 -#define MAX_ORDER 11 -#endif -#endif - -#ifndef module_init -#define module_init(x) int init_module(void) { return x(); } -#define module_exit(x) void cleanup_module(void) { x(); } -#endif - -#ifndef minor -#define minor(x) MINOR(x) -#endif - -#ifndef IRQ_HANDLED -typedef void irqreturn_t; -#define IRQ_NONE -#define IRQ_HANDLED -#define IRQ_RETVAL(x) -#endif - -#if !defined (list_for_each) -#define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) -#endif - -#ifdef KERNEL_2_4 -#define XGI_PCI_FOR_EACH_DEV(dev) pci_for_each_dev(dev) -#endif -#ifdef KERNEL_2_6 -extern struct list_head pci_devices; /* list of all devices */ -#define XGI_PCI_FOR_EACH_DEV(dev) \ - for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next)) -#endif - -/* - * the following macro causes problems when used in the same module - * as module_param(); undef it so we don't accidentally mix the two - */ -#if defined (KERNEL_2_6) -#undef MODULE_PARM -#endif - -#ifdef EXPORT_NO_SYMBOLS -EXPORT_NO_SYMBOLS; -#endif - -#if defined (KERNEL_2_4) -#define XGI_IS_SUSER() suser() -#define XGI_PCI_DEVICE_NAME(dev) ((dev)->name) -#define XGI_NUM_CPUS() smp_num_cpus -#define XGI_CLI() __cli() -#define XGI_SAVE_FLAGS(eflags) __save_flags(eflags) -#define XGI_RESTORE_FLAGS(eflags) __restore_flags(eflags) -#define XGI_MAY_SLEEP() (!in_interrupt()) -#define XGI_MODULE_PARAMETER(x) MODULE_PARM(x, "i") -#endif - -#if defined (KERNEL_2_6) -#define XGI_IS_SUSER() capable(CAP_SYS_ADMIN) -#define XGI_PCI_DEVICE_NAME(dev) ((dev)->pretty_name) -#define XGI_NUM_CPUS() num_online_cpus() -#define XGI_CLI() local_irq_disable() -#define XGI_SAVE_FLAGS(eflags) local_save_flags(eflags) -#define XGI_RESTORE_FLAGS(eflags) local_irq_restore(eflags) -#define XGI_MAY_SLEEP() (!in_interrupt() && !in_atomic()) -#define XGI_MODULE_PARAMETER(x) module_param(x, int, 0) -#endif - -/* Earlier 2.4.x kernels don't have pci_disable_device() */ -#ifdef XGI_PCI_DISABLE_DEVICE_PRESENT -#define XGI_PCI_DISABLE_DEVICE(dev) pci_disable_device(dev) -#else -#define XGI_PCI_DISABLE_DEVICE(dev) -#endif - -/* common defines */ -#define GET_MODULE_SYMBOL(mod,sym) (const void *) inter_module_get(sym) -#define PUT_MODULE_SYMBOL(sym) inter_module_put((char *) sym) - -#define XGI_GET_PAGE_STRUCT(phys_page) virt_to_page(__va(phys_page)) -#define XGI_VMA_OFFSET(vma) (((vma)->vm_pgoff) << PAGE_SHIFT) -#define XGI_VMA_PRIVATE(vma) ((vma)->vm_private_data) - -#define XGI_DEVICE_NUMBER(x) minor((x)->i_rdev) -#define XGI_IS_CONTROL_DEVICE(x) (minor((x)->i_rdev) == 255) - -#define XGI_PCI_RESOURCE_START(dev, bar) ((dev)->resource[bar].start) -#define XGI_PCI_RESOURCE_SIZE(dev, bar) ((dev)->resource[bar].end - (dev)->resource[bar].start + 1) - -#define XGI_PCI_BUS_NUMBER(dev) (dev)->bus->number -#define XGI_PCI_SLOT_NUMBER(dev) PCI_SLOT((dev)->devfn) - -#ifdef XGI_PCI_GET_CLASS_PRESENT -#define XGI_PCI_DEV_PUT(dev) pci_dev_put(dev) -#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_get_device(vendor,device,from) -#define XGI_PCI_GET_SLOT(bus,devfn) pci_get_slot(pci_find_bus(0,bus),devfn) -#define XGI_PCI_GET_CLASS(class,from) pci_get_class(class,from) -#else -#define XGI_PCI_DEV_PUT(dev) -#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_find_device(vendor,device,from) -#define XGI_PCI_GET_SLOT(bus,devfn) pci_find_slot(bus,devfn) -#define XGI_PCI_GET_CLASS(class,from) pci_find_class(class,from) -#endif - -/* - * acpi support has been back-ported to the 2.4 kernel, but the 2.4 driver - * model is not sufficient for full acpi support. it may work in some cases, - * but not enough for us to officially support this configuration. - */ -#if defined(CONFIG_ACPI) && defined(KERNEL_2_6) -#define XGI_PM_SUPPORT_ACPI -#endif - -#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) -#define XGI_PM_SUPPORT_APM -#endif - - -#if defined(CONFIG_DEVFS_FS) -#if defined(KERNEL_2_6) -typedef void* devfs_handle_t; -#define XGI_DEVFS_REGISTER(_name, _minor) \ - ({ \ - devfs_handle_t __handle = NULL; \ - if (devfs_mk_cdev(MKDEV(XGI_DEV_MAJOR, _minor), \ - S_IFCHR | S_IRUGO | S_IWUGO, _name) == 0) \ - { \ - __handle = (void *) 1; /* XXX Fix me! (boolean) */ \ - } \ - __handle; \ - }) -/* -#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi%d", i) -*/ -#define XGI_DEVFS_REMOVE_CONTROL() devfs_remove("xgi_ctl") -#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi") -#else // defined(KERNEL_2_4) -#define XGI_DEVFS_REGISTER(_name, _minor) \ - ({ \ - devfs_handle_t __handle = devfs_register(NULL, _name, DEVFS_FL_AUTO_DEVNUM, \ - XGI_DEV_MAJOR, _minor, \ - S_IFCHR | S_IRUGO | S_IWUGO, &xgi_fops, NULL); \ - __handle; \ - }) - -#define XGI_DEVFS_REMOVE_DEVICE(i) \ - ({ \ - if (xgi_devfs_handles[i] != NULL) \ - { \ - devfs_unregister(xgi_devfs_handles[i]); \ - } \ - }) -#define XGI_DEVFS_REMOVE_CONTROL() \ - ({ \ - if (xgi_devfs_handles[0] != NULL) \ - { \ - devfs_unregister(xgi_devfs_handles[0]); \ - } \ - }) -#endif /* defined(KERNEL_2_4) */ -#endif /* defined(CONFIG_DEVFS_FS) */ - -#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) -#define XGI_REGISTER_CHRDEV(x...) devfs_register_chrdev(x) -#define XGI_UNREGISTER_CHRDEV(x...) devfs_unregister_chrdev(x) -#else -#define XGI_REGISTER_CHRDEV(x...) register_chrdev(x) -#define XGI_UNREGISTER_CHRDEV(x...) unregister_chrdev(x) -#endif - -#if defined(XGI_REMAP_PFN_RANGE_PRESENT) -#define XGI_REMAP_PAGE_RANGE(from, offset, x...) \ - remap_pfn_range(vma, from, ((offset) >> PAGE_SHIFT), x) -#elif defined(XGI_REMAP_PAGE_RANGE_5) -#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) -#elif defined(XGI_REMAP_PAGE_RANGE_4) -#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(x) -#else -#warning "xgi_configure.sh failed, assuming remap_page_range(5)!" -#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) -#endif - -#if defined(pmd_offset_map) -#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ - { \ - pg_mid_dir = pmd_offset_map(pg_dir, address); \ - } -#define XGI_PMD_UNMAP(pg_mid_dir) \ - { \ - pmd_unmap(pg_mid_dir); \ - } -#else -#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ - { \ - pg_mid_dir = pmd_offset(pg_dir, address); \ - } -#define XGI_PMD_UNMAP(pg_mid_dir) -#endif - -#define XGI_PMD_PRESENT(pg_mid_dir) \ - ({ \ - if ((pg_mid_dir) && (pmd_none(*pg_mid_dir))) \ - { \ - XGI_PMD_UNMAP(pg_mid_dir); \ - pg_mid_dir = NULL; \ - } \ - pg_mid_dir != NULL; \ - }) - -#if defined(pte_offset_atomic) -#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset_atomic(pg_mid_dir, address); \ - XGI_PMD_UNMAP(pg_mid_dir); \ - } -#define XGI_PTE_UNMAP(pte) \ - { \ - pte_kunmap(pte); \ - } -#elif defined(pte_offset) -#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset(pg_mid_dir, address); \ - XGI_PMD_UNMAP(pg_mid_dir); \ - } -#define XGI_PTE_UNMAP(pte) -#else -#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset_map(pg_mid_dir, address); \ - XGI_PMD_UNMAP(pg_mid_dir); \ - } -#define XGI_PTE_UNMAP(pte) \ - { \ - pte_unmap(pte); \ - } -#endif - -#define XGI_PTE_PRESENT(pte) \ - ({ \ - if (pte) \ - { \ - if (!pte_present(*pte)) \ - { \ - XGI_PTE_UNMAP(pte); pte = NULL; \ - } \ - } \ - pte != NULL; \ - }) - -#define XGI_PTE_VALUE(pte) \ - ({ \ - unsigned long __pte_value = pte_val(*pte); \ - XGI_PTE_UNMAP(pte); \ - __pte_value; \ - }) - -#define XGI_PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) / PAGE_SIZE) -#define XGI_MASK_OFFSET(addr) ((addr) & (PAGE_SIZE - 1)) - -#if !defined (pgprot_noncached) -static inline pgprot_t pgprot_noncached(pgprot_t old_prot) - { - pgprot_t new_prot = old_prot; - if (boot_cpu_data.x86 > 3) - new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_PCD); - return new_prot; - } -#endif - -#if defined(XGI_BUILD_XGI_PAT_SUPPORT) && !defined (pgprot_writecombined) -/* Added define for write combining page, only valid if pat enabled. */ -#define _PAGE_WRTCOMB _PAGE_PWT -#define __PAGE_KERNEL_WRTCOMB \ - (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_WRTCOMB | _PAGE_ACCESSED) -#define PAGE_KERNEL_WRTCOMB MAKE_GLOBAL(__PAGE_KERNEL_WRTCOMB) - -static inline pgprot_t pgprot_writecombined(pgprot_t old_prot) - { - pgprot_t new_prot = old_prot; - if (boot_cpu_data.x86 > 3) - { - pgprot_val(old_prot) &= ~(_PAGE_PCD | _PAGE_PWT); - new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_WRTCOMB); - } - return new_prot; - } -#endif - -#if !defined(page_to_pfn) -#define page_to_pfn(page) ((page) - mem_map) -#endif - -#define XGI_VMALLOC(ptr, size) \ - { \ - (ptr) = vmalloc_32(size); \ - } - -#define XGI_VFREE(ptr, size) \ - { \ - vfree((void *) (ptr)); \ - } - -#define XGI_IOREMAP(ptr, physaddr, size) \ - { \ - (ptr) = ioremap(physaddr, size); \ - } - -#define XGI_IOREMAP_NOCACHE(ptr, physaddr, size) \ - { \ - (ptr) = ioremap_nocache(physaddr, size); \ - } - -#define XGI_IOUNMAP(ptr, size) \ - { \ - iounmap(ptr); \ - } - -/* - * only use this because GFP_KERNEL may sleep.. - * GFP_ATOMIC is ok, it won't sleep - */ -#define XGI_KMALLOC(ptr, size) \ - { \ - (ptr) = kmalloc(size, GFP_KERNEL); \ - } - -#define XGI_KMALLOC_ATOMIC(ptr, size) \ - { \ - (ptr) = kmalloc(size, GFP_ATOMIC); \ - } - -#define XGI_KFREE(ptr, size) \ - { \ - kfree((void *) (ptr)); \ - } - -#define XGI_GET_FREE_PAGES(ptr, order) \ - { \ - (ptr) = __get_free_pages(GFP_KERNEL, order); \ - } - -#define XGI_FREE_PAGES(ptr, order) \ - { \ - free_pages(ptr, order); \ - } - -typedef struct xgi_pte_s { - unsigned long phys_addr; - unsigned long virt_addr; -} xgi_pte_t; - -/* - * AMD Athlon processors expose a subtle bug in the Linux - * kernel, that may lead to AGP memory corruption. Recent - * kernel versions had a workaround for this problem, but - * 2.4.20 is the first kernel to address it properly. The - * page_attr API provides the means to solve the problem. - */ -#if defined(XGI_CHANGE_PAGE_ATTR_PRESENT) -static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(xgi_pte_t *page_ptr) - { - struct page *page = virt_to_page(__va(page_ptr->phys_addr)); - change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); - } -static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t *page_ptr) - { - struct page *page = virt_to_page(__va(page_ptr->phys_addr)); - change_page_attr(page, 1, PAGE_KERNEL); - } -#else -#define XGI_SET_PAGE_ATTRIB_UNCACHED(page_list) -#define XGI_SET_PAGE_ATTRIB_CACHED(page_list) -#endif - -#ifdef KERNEL_2_4 -#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) -#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) -#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) -#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) - -#define XGILockPage(page) set_bit(PG_locked, &(page)->flags) -#define XGIUnlockPage(page) clear_bit(PG_locked, &(page)->flags) -#endif - -#ifdef KERNEL_2_6 -/* add for SUSE 9, Jill*/ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4) -#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) -#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) -#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) -#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) -#else -#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->_count) -#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->_count) -#define XGI_PAGE_COUNT(page) atomic_read(&(page)->_count) -#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->_count, v) -#endif -#define XGILockPage(page) SetPageLocked(page) -#define XGIUnlockPage(page) ClearPageLocked(page) -#endif - - -/* - * hide a pointer to struct xgi_info_t in a file-private info - */ - -typedef struct -{ - void *info; - U32 num_events; - spinlock_t fp_lock; - wait_queue_head_t wait_queue; -} xgi_file_private_t; - -#define FILE_PRIVATE(filp) ((filp)->private_data) - -#define XGI_GET_FP(filp) ((xgi_file_private_t *) FILE_PRIVATE(filp)) - -/* for the card devices */ -#define XGI_INFO_FROM_FP(filp) (XGI_GET_FP(filp)->info) - -#ifdef KERNEL_2_0 -#define INODE_FROM_FP(filp) ((filp)->f_inode) -#else -#define INODE_FROM_FP(filp) ((filp)->f_dentry->d_inode) -#endif - -#define XGI_ATOMIC_SET(data,val) atomic_set(&(data), (val)) -#define XGI_ATOMIC_INC(data) atomic_inc(&(data)) -#define XGI_ATOMIC_DEC(data) atomic_dec(&(data)) -#define XGI_ATOMIC_DEC_AND_TEST(data) atomic_dec_and_test(&(data)) -#define XGI_ATOMIC_READ(data) atomic_read(&(data)) - -/* - * lock-related functions that should only be called from this file - */ -#define xgi_init_lock(lock) spin_lock_init(&lock) -#define xgi_lock(lock) spin_lock(&lock) -#define xgi_unlock(lock) spin_unlock(&lock) -#define xgi_down(lock) down(&lock) -#define xgi_up(lock) up(&lock) - -#define xgi_lock_irqsave(lock,flags) spin_lock_irqsave(&lock,flags) -#define xgi_unlock_irqsave(lock,flags) spin_unlock_irqrestore(&lock,flags) - -#endif + +/**************************************************************************** + * 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_LINUX_H_ +#define _XGI_LINUX_H_ + +#include + +#ifndef LINUX_VERSION_CODE +#include +#endif + +#ifndef KERNEL_VERSION /* pre-2.1.90 didn't have it */ +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) +# error "This driver does not support pre-2.4 kernels!" +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) +#define KERNEL_2_4 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +# error "This driver does not support 2.5 kernels!" +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0) +#define KERNEL_2_6 +#else +# error "This driver does not support development kernels!" +#endif + +#if defined (CONFIG_SMP) && !defined (__SMP__) +#define __SMP__ +#endif + +#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) +#define MODVERSIONS +#endif + +#if defined (MODVERSIONS) && !defined (KERNEL_2_6) +#include +#endif + +#include /* printk */ +#include + +#include /* module_init, module_exit */ +#include /* pic_t, size_t, __u32, etc */ +#include /* error codes */ +#include /* circular linked list */ +#include /* NULL, offsetof */ +#include /* wait queues */ + +#include /* kmalloc, kfree, etc */ +#include /* vmalloc, vfree, etc */ + +#include /* poll_wait */ +#include /* mdelay, udelay */ +#include /* rdtsc rdtscl */ + +#include /* suser(), capable() replacement + for_each_task, for_each_process */ +#ifdef for_each_process +#define XGI_SCAN_PROCESS(p) for_each_process(p) +#else +#define XGI_SCAN_PROCESS(p) for_each_task(p) +#endif + +#ifdef KERNEL_2_6 +#include /* module_param() */ +#include /* kernel_locked */ +#include /* flush_tlb(), flush_tlb_all() */ +#include /* page table entry lookup */ +#endif + +#include /* pci_find_class, etc */ +#include /* tasklets, interrupt helpers */ +#include + +#include /* cli, sli, save_flags */ +#include /* ioremap, virt_to_phys */ +#include /* access_ok */ +#include /* PAGE_OFFSET */ +#include /* pte bit definitions */ + +#include +#include +#include + +#ifdef CONFIG_PROC_FS +#include +#endif + +#ifdef CONFIG_DEVFS_FS +#include +#endif + +#ifdef CONFIG_KMOD +#include +#endif + +#ifdef CONFIG_PM +#include +#endif + +#ifdef CONFIG_MTRR +#include +#endif + +#ifdef CONFIG_KDB +#include +#include +#endif + +#if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE) +#define AGPGART +#include +#include +#endif + +#ifndef MAX_ORDER +#ifdef KERNEL_2_4 +#define MAX_ORDER 10 +#endif +#ifdef KERNEL_2_6 +#define MAX_ORDER 11 +#endif +#endif + +#ifndef module_init +#define module_init(x) int init_module(void) { return x(); } +#define module_exit(x) void cleanup_module(void) { x(); } +#endif + +#ifndef minor +#define minor(x) MINOR(x) +#endif + +#ifndef IRQ_HANDLED +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) +#endif + +#if !defined (list_for_each) +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) +#endif + +#ifdef KERNEL_2_4 +#define XGI_PCI_FOR_EACH_DEV(dev) pci_for_each_dev(dev) +#endif +#ifdef KERNEL_2_6 +extern struct list_head pci_devices; /* list of all devices */ +#define XGI_PCI_FOR_EACH_DEV(dev) \ + for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next)) +#endif + +/* + * the following macro causes problems when used in the same module + * as module_param(); undef it so we don't accidentally mix the two + */ +#if defined (KERNEL_2_6) +#undef MODULE_PARM +#endif + +#ifdef EXPORT_NO_SYMBOLS +EXPORT_NO_SYMBOLS; +#endif + +#if defined (KERNEL_2_4) +#define XGI_IS_SUSER() suser() +#define XGI_PCI_DEVICE_NAME(dev) ((dev)->name) +#define XGI_NUM_CPUS() smp_num_cpus +#define XGI_CLI() __cli() +#define XGI_SAVE_FLAGS(eflags) __save_flags(eflags) +#define XGI_RESTORE_FLAGS(eflags) __restore_flags(eflags) +#define XGI_MAY_SLEEP() (!in_interrupt()) +#define XGI_MODULE_PARAMETER(x) MODULE_PARM(x, "i") +#endif + +#if defined (KERNEL_2_6) +#define XGI_IS_SUSER() capable(CAP_SYS_ADMIN) +#define XGI_PCI_DEVICE_NAME(dev) ((dev)->pretty_name) +#define XGI_NUM_CPUS() num_online_cpus() +#define XGI_CLI() local_irq_disable() +#define XGI_SAVE_FLAGS(eflags) local_save_flags(eflags) +#define XGI_RESTORE_FLAGS(eflags) local_irq_restore(eflags) +#define XGI_MAY_SLEEP() (!in_interrupt() && !in_atomic()) +#define XGI_MODULE_PARAMETER(x) module_param(x, int, 0) +#endif + +/* Earlier 2.4.x kernels don't have pci_disable_device() */ +#ifdef XGI_PCI_DISABLE_DEVICE_PRESENT +#define XGI_PCI_DISABLE_DEVICE(dev) pci_disable_device(dev) +#else +#define XGI_PCI_DISABLE_DEVICE(dev) +#endif + +/* common defines */ +#define GET_MODULE_SYMBOL(mod,sym) (const void *) inter_module_get(sym) +#define PUT_MODULE_SYMBOL(sym) inter_module_put((char *) sym) + +#define XGI_GET_PAGE_STRUCT(phys_page) virt_to_page(__va(phys_page)) +#define XGI_VMA_OFFSET(vma) (((vma)->vm_pgoff) << PAGE_SHIFT) +#define XGI_VMA_PRIVATE(vma) ((vma)->vm_private_data) + +#define XGI_DEVICE_NUMBER(x) minor((x)->i_rdev) +#define XGI_IS_CONTROL_DEVICE(x) (minor((x)->i_rdev) == 255) + +#define XGI_PCI_RESOURCE_START(dev, bar) ((dev)->resource[bar].start) +#define XGI_PCI_RESOURCE_SIZE(dev, bar) ((dev)->resource[bar].end - (dev)->resource[bar].start + 1) + +#define XGI_PCI_BUS_NUMBER(dev) (dev)->bus->number +#define XGI_PCI_SLOT_NUMBER(dev) PCI_SLOT((dev)->devfn) + +#ifdef XGI_PCI_GET_CLASS_PRESENT +#define XGI_PCI_DEV_PUT(dev) pci_dev_put(dev) +#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_get_device(vendor,device,from) +#define XGI_PCI_GET_SLOT(bus,devfn) pci_get_slot(pci_find_bus(0,bus),devfn) +#define XGI_PCI_GET_CLASS(class,from) pci_get_class(class,from) +#else +#define XGI_PCI_DEV_PUT(dev) +#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_find_device(vendor,device,from) +#define XGI_PCI_GET_SLOT(bus,devfn) pci_find_slot(bus,devfn) +#define XGI_PCI_GET_CLASS(class,from) pci_find_class(class,from) +#endif + +/* + * acpi support has been back-ported to the 2.4 kernel, but the 2.4 driver + * model is not sufficient for full acpi support. it may work in some cases, + * but not enough for us to officially support this configuration. + */ +#if defined(CONFIG_ACPI) && defined(KERNEL_2_6) +#define XGI_PM_SUPPORT_ACPI +#endif + +#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) +#define XGI_PM_SUPPORT_APM +#endif + +#if defined(CONFIG_DEVFS_FS) +#if defined(KERNEL_2_6) +typedef void *devfs_handle_t; +#define XGI_DEVFS_REGISTER(_name, _minor) \ + ({ \ + devfs_handle_t __handle = NULL; \ + if (devfs_mk_cdev(MKDEV(XGI_DEV_MAJOR, _minor), \ + S_IFCHR | S_IRUGO | S_IWUGO, _name) == 0) \ + { \ + __handle = (void *) 1; /* XXX Fix me! (boolean) */ \ + } \ + __handle; \ + }) +/* +#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi%d", i) +*/ +#define XGI_DEVFS_REMOVE_CONTROL() devfs_remove("xgi_ctl") +#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi") +#else // defined(KERNEL_2_4) +#define XGI_DEVFS_REGISTER(_name, _minor) \ + ({ \ + devfs_handle_t __handle = devfs_register(NULL, _name, DEVFS_FL_AUTO_DEVNUM, \ + XGI_DEV_MAJOR, _minor, \ + S_IFCHR | S_IRUGO | S_IWUGO, &xgi_fops, NULL); \ + __handle; \ + }) + +#define XGI_DEVFS_REMOVE_DEVICE(i) \ + ({ \ + if (xgi_devfs_handles[i] != NULL) \ + { \ + devfs_unregister(xgi_devfs_handles[i]); \ + } \ + }) +#define XGI_DEVFS_REMOVE_CONTROL() \ + ({ \ + if (xgi_devfs_handles[0] != NULL) \ + { \ + devfs_unregister(xgi_devfs_handles[0]); \ + } \ + }) +#endif /* defined(KERNEL_2_4) */ +#endif /* defined(CONFIG_DEVFS_FS) */ + +#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) +#define XGI_REGISTER_CHRDEV(x...) devfs_register_chrdev(x) +#define XGI_UNREGISTER_CHRDEV(x...) devfs_unregister_chrdev(x) +#else +#define XGI_REGISTER_CHRDEV(x...) register_chrdev(x) +#define XGI_UNREGISTER_CHRDEV(x...) unregister_chrdev(x) +#endif + +#if defined(XGI_REMAP_PFN_RANGE_PRESENT) +#define XGI_REMAP_PAGE_RANGE(from, offset, x...) \ + remap_pfn_range(vma, from, ((offset) >> PAGE_SHIFT), x) +#elif defined(XGI_REMAP_PAGE_RANGE_5) +#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) +#elif defined(XGI_REMAP_PAGE_RANGE_4) +#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(x) +#else +#warning "xgi_configure.sh failed, assuming remap_page_range(5)!" +#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) +#endif + +#if defined(pmd_offset_map) +#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ + { \ + pg_mid_dir = pmd_offset_map(pg_dir, address); \ + } +#define XGI_PMD_UNMAP(pg_mid_dir) \ + { \ + pmd_unmap(pg_mid_dir); \ + } +#else +#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ + { \ + pg_mid_dir = pmd_offset(pg_dir, address); \ + } +#define XGI_PMD_UNMAP(pg_mid_dir) +#endif + +#define XGI_PMD_PRESENT(pg_mid_dir) \ + ({ \ + if ((pg_mid_dir) && (pmd_none(*pg_mid_dir))) \ + { \ + XGI_PMD_UNMAP(pg_mid_dir); \ + pg_mid_dir = NULL; \ + } \ + pg_mid_dir != NULL; \ + }) + +#if defined(pte_offset_atomic) +#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ + { \ + pte = pte_offset_atomic(pg_mid_dir, address); \ + XGI_PMD_UNMAP(pg_mid_dir); \ + } +#define XGI_PTE_UNMAP(pte) \ + { \ + pte_kunmap(pte); \ + } +#elif defined(pte_offset) +#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ + { \ + pte = pte_offset(pg_mid_dir, address); \ + XGI_PMD_UNMAP(pg_mid_dir); \ + } +#define XGI_PTE_UNMAP(pte) +#else +#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ + { \ + pte = pte_offset_map(pg_mid_dir, address); \ + XGI_PMD_UNMAP(pg_mid_dir); \ + } +#define XGI_PTE_UNMAP(pte) \ + { \ + pte_unmap(pte); \ + } +#endif + +#define XGI_PTE_PRESENT(pte) \ + ({ \ + if (pte) \ + { \ + if (!pte_present(*pte)) \ + { \ + XGI_PTE_UNMAP(pte); pte = NULL; \ + } \ + } \ + pte != NULL; \ + }) + +#define XGI_PTE_VALUE(pte) \ + ({ \ + unsigned long __pte_value = pte_val(*pte); \ + XGI_PTE_UNMAP(pte); \ + __pte_value; \ + }) + +#define XGI_PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) / PAGE_SIZE) +#define XGI_MASK_OFFSET(addr) ((addr) & (PAGE_SIZE - 1)) + +#if !defined (pgprot_noncached) +static inline pgprot_t pgprot_noncached(pgprot_t old_prot) +{ + pgprot_t new_prot = old_prot; + if (boot_cpu_data.x86 > 3) + new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_PCD); + return new_prot; +} +#endif + +#if defined(XGI_BUILD_XGI_PAT_SUPPORT) && !defined (pgprot_writecombined) +/* Added define for write combining page, only valid if pat enabled. */ +#define _PAGE_WRTCOMB _PAGE_PWT +#define __PAGE_KERNEL_WRTCOMB \ + (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_WRTCOMB | _PAGE_ACCESSED) +#define PAGE_KERNEL_WRTCOMB MAKE_GLOBAL(__PAGE_KERNEL_WRTCOMB) + +static inline pgprot_t pgprot_writecombined(pgprot_t old_prot) +{ + pgprot_t new_prot = old_prot; + if (boot_cpu_data.x86 > 3) { + pgprot_val(old_prot) &= ~(_PAGE_PCD | _PAGE_PWT); + new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_WRTCOMB); + } + return new_prot; +} +#endif + +#if !defined(page_to_pfn) +#define page_to_pfn(page) ((page) - mem_map) +#endif + +#define XGI_VMALLOC(ptr, size) \ + { \ + (ptr) = vmalloc_32(size); \ + } + +#define XGI_VFREE(ptr, size) \ + { \ + vfree((void *) (ptr)); \ + } + +#define XGI_IOREMAP(ptr, physaddr, size) \ + { \ + (ptr) = ioremap(physaddr, size); \ + } + +#define XGI_IOREMAP_NOCACHE(ptr, physaddr, size) \ + { \ + (ptr) = ioremap_nocache(physaddr, size); \ + } + +#define XGI_IOUNMAP(ptr, size) \ + { \ + iounmap(ptr); \ + } + +/* + * only use this because GFP_KERNEL may sleep.. + * GFP_ATOMIC is ok, it won't sleep + */ +#define XGI_KMALLOC(ptr, size) \ + { \ + (ptr) = kmalloc(size, GFP_KERNEL); \ + } + +#define XGI_KMALLOC_ATOMIC(ptr, size) \ + { \ + (ptr) = kmalloc(size, GFP_ATOMIC); \ + } + +#define XGI_KFREE(ptr, size) \ + { \ + kfree((void *) (ptr)); \ + } + +#define XGI_GET_FREE_PAGES(ptr, order) \ + { \ + (ptr) = __get_free_pages(GFP_KERNEL, order); \ + } + +#define XGI_FREE_PAGES(ptr, order) \ + { \ + free_pages(ptr, order); \ + } + +typedef struct xgi_pte_s { + unsigned long phys_addr; + unsigned long virt_addr; +} xgi_pte_t; + +/* + * AMD Athlon processors expose a subtle bug in the Linux + * kernel, that may lead to AGP memory corruption. Recent + * kernel versions had a workaround for this problem, but + * 2.4.20 is the first kernel to address it properly. The + * page_attr API provides the means to solve the problem. + */ +#if defined(XGI_CHANGE_PAGE_ATTR_PRESENT) +static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(xgi_pte_t * page_ptr) +{ + struct page *page = virt_to_page(__va(page_ptr->phys_addr)); + change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); +} +static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr) +{ + struct page *page = virt_to_page(__va(page_ptr->phys_addr)); + change_page_attr(page, 1, PAGE_KERNEL); +} +#else +#define XGI_SET_PAGE_ATTRIB_UNCACHED(page_list) +#define XGI_SET_PAGE_ATTRIB_CACHED(page_list) +#endif + +#ifdef KERNEL_2_4 +#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) +#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) +#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) +#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) + +#define XGILockPage(page) set_bit(PG_locked, &(page)->flags) +#define XGIUnlockPage(page) clear_bit(PG_locked, &(page)->flags) +#endif + +#ifdef KERNEL_2_6 +/* add for SUSE 9, Jill*/ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4) +#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) +#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) +#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) +#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) +#else +#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->_count) +#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->_count) +#define XGI_PAGE_COUNT(page) atomic_read(&(page)->_count) +#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->_count, v) +#endif +#define XGILockPage(page) SetPageLocked(page) +#define XGIUnlockPage(page) ClearPageLocked(page) +#endif + +/* + * hide a pointer to struct xgi_info_t in a file-private info + */ + +typedef struct { + void *info; + U32 num_events; + spinlock_t fp_lock; + wait_queue_head_t wait_queue; +} xgi_file_private_t; + +#define FILE_PRIVATE(filp) ((filp)->private_data) + +#define XGI_GET_FP(filp) ((xgi_file_private_t *) FILE_PRIVATE(filp)) + +/* for the card devices */ +#define XGI_INFO_FROM_FP(filp) (XGI_GET_FP(filp)->info) + +#ifdef KERNEL_2_0 +#define INODE_FROM_FP(filp) ((filp)->f_inode) +#else +#define INODE_FROM_FP(filp) ((filp)->f_dentry->d_inode) +#endif + +#define XGI_ATOMIC_SET(data,val) atomic_set(&(data), (val)) +#define XGI_ATOMIC_INC(data) atomic_inc(&(data)) +#define XGI_ATOMIC_DEC(data) atomic_dec(&(data)) +#define XGI_ATOMIC_DEC_AND_TEST(data) atomic_dec_and_test(&(data)) +#define XGI_ATOMIC_READ(data) atomic_read(&(data)) + +/* + * lock-related functions that should only be called from this file + */ +#define xgi_init_lock(lock) spin_lock_init(&lock) +#define xgi_lock(lock) spin_lock(&lock) +#define xgi_unlock(lock) spin_unlock(&lock) +#define xgi_down(lock) down(&lock) +#define xgi_up(lock) up(&lock) + +#define xgi_lock_irqsave(lock,flags) spin_lock_irqsave(&lock,flags) +#define xgi_unlock_irqsave(lock,flags) spin_unlock_irqrestore(&lock,flags) + +#endif diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index b15c7ecf..61e40594 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -1,657 +1,630 @@ - -/**************************************************************************** - * 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_types.h" -#include "xgi_linux.h" -#include "xgi_drv.h" -#include "xgi_regs.h" -#include "xgi_pcie.h" - -void xgi_get_device_info(xgi_info_t *info, xgi_chip_info_t *req) -{ - req->device_id = info->device_id; - req->device_name[0] = 'x'; - req->device_name[1] = 'g'; - req->device_name[2] = '4'; - req->device_name[3] = '7'; - req->vendor_id = info->vendor_id; - req->curr_display_mode = 0; - req->fb_size = info->fb.size; - req->sarea_bus_addr = info->sarea_info.bus_addr; - req->sarea_size = info->sarea_info.size; -} - -void xgi_get_mmio_info(xgi_info_t *info, xgi_mmio_info_t *req) -{ - req->mmioBase = (void *)info->mmio.base; - req->size = info->mmio.size; -} - -void xgi_put_screen_info(xgi_info_t *info, xgi_screen_info_t *req) -{ - info->scrn_info.scrn_start = req->scrn_start; - info->scrn_info.scrn_xres = req->scrn_xres; - info->scrn_info.scrn_yres = req->scrn_yres; - info->scrn_info.scrn_bpp = req->scrn_bpp; - info->scrn_info.scrn_pitch = req->scrn_pitch; - - XGI_INFO("info->scrn_info.scrn_start: 0x%lx" - "info->scrn_info.scrn_xres: 0x%lx" - "info->scrn_info.scrn_yres: 0x%lx" - "info->scrn_info.scrn_bpp: 0x%lx" - "info->scrn_info.scrn_pitch: 0x%lx\n", - info->scrn_info.scrn_start, - info->scrn_info.scrn_xres, - info->scrn_info.scrn_yres, - info->scrn_info.scrn_bpp, - info->scrn_info.scrn_pitch); -} - -void xgi_get_screen_info(xgi_info_t *info, xgi_screen_info_t *req) -{ - req->scrn_start = info->scrn_info.scrn_start; - req->scrn_xres = info->scrn_info.scrn_xres; - req->scrn_yres = info->scrn_info.scrn_yres; - req->scrn_bpp = info->scrn_info.scrn_bpp; - req->scrn_pitch = info->scrn_info.scrn_pitch; - - XGI_INFO("req->scrn_start: 0x%lx" - "req->scrn_xres: 0x%lx" - "req->scrn_yres: 0x%lx" - "req->scrn_bpp: 0x%lx" - "req->scrn_pitch: 0x%lx\n", - req->scrn_start, - req->scrn_xres, - req->scrn_yres, - req->scrn_bpp, - req->scrn_pitch); -} - -void xgi_ge_reset(xgi_info_t *info) -{ - xgi_disable_ge(info); - xgi_enable_ge(info); -} - -void xgi_sarea_info(xgi_info_t *info, xgi_sarea_info_t *req) -{ - info->sarea_info.bus_addr = req->bus_addr; - info->sarea_info.size = req->size; - XGI_INFO("info->sarea_info.bus_addr: 0x%lx" - "info->sarea_info.size: 0x%lx\n", - info->sarea_info.bus_addr, - info->sarea_info.size); -} - -/* - * irq functions - */ -#define STALL_INTERRUPT_RESET_THRESHOLD 0xffff - -static U32 s_invalid_begin = 0; - -BOOL xgi_ge_irq_handler(xgi_info_t *info) -{ - volatile U8 *mmio_vbase = info->mmio.vbase; - volatile U32 *ge_3d_status = (volatile U32 *)(mmio_vbase + 0x2800); - U32 int_status = ge_3d_status[4]; // interrupt status - U32 auto_reset_count = 0; - BOOL is_support_auto_reset = FALSE; - - // Check GE on/off - if (0 == (0xffffc0f0 & int_status)) - { - U32 old_ge_status = ge_3d_status[0x00]; - 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 (TRUE == is_support_auto_reset) - { - BOOL is_wrong_signal = FALSE; - static U32 last_int_tick_low, last_int_tick_high; - static U32 new_int_tick_low, new_int_tick_high; - static U32 continoue_int_count = 0; - // OE II is busy. - while (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)) - { - is_wrong_signal = TRUE; - break; - } - // Check RO channel - *(mmio_vbase + 0x235c) = 0x83; - check = *((volatile U16*)(mmio_vbase + 0x2360)); - if ((check & 0x0f) != ((check & 0xf0) >> 4)) - { - is_wrong_signal = TRUE; - break; - } - // Check RW channel - *(mmio_vbase + 0x235c) = 0x88; - check = *((volatile U16*)(mmio_vbase + 0x2360)); - if ((check & 0x0f) != ((check & 0xf0) >> 4)) - { - is_wrong_signal = TRUE; - break; - } - // Check RO channel outstanding - *(mmio_vbase + 0x235c) = 0x8f; - check = *((volatile U16*)(mmio_vbase + 0x2360)); - if (0 != (check & 0x3ff)) - { - is_wrong_signal = TRUE; - break; - } - // Check RW channel outstanding - *(mmio_vbase + 0x235c) = 0x90; - check = *((volatile U16*)(mmio_vbase + 0x2360)); - if (0 != (check & 0x3ff)) - { - is_wrong_signal = TRUE; - break; - } - // No pending PCIE request. GE stall. - break; - } - - if (is_wrong_signal) - { - // Nothing but skip. - } - else if (0 == continoue_int_count++) - { - rdtsc(last_int_tick_low, last_int_tick_high); - } - else - { - rdtscl(new_int_tick_low); - if ((new_int_tick_low - last_int_tick_low) > STALL_INTERRUPT_RESET_THRESHOLD) - { - continoue_int_count = 0; - } - else if (continoue_int_count >= 3) - { - continoue_int_count = 0; - - // GE Hung up, need reset. - XGI_INFO("Reset GE!\n"); - - *(mmio_vbase + 0xb057) = 8; - int time_out = 0xffff; - while (0 != (ge_3d_status[0x00] & 0xf0000000)) - { - while (0 != ((--time_out) & 0xfff)); - if (0 == time_out) - { - XGI_INFO("Can not reset back 0x%lx!\n", ge_3d_status[0x00]); - *(mmio_vbase + 0xb057) = 0; - // Have to use 3x5.36 to reset. - // Save and close dynamic gating - U8 old_3ce = *(mmio_vbase + 0x3ce); - *(mmio_vbase + 0x3ce) = 0x2a; - U8 old_3cf = *(mmio_vbase + 0x3cf); - *(mmio_vbase + 0x3cf) = old_3cf & 0xfe; - // Reset GE - U8 old_index = *(mmio_vbase + 0x3d4); - *(mmio_vbase + 0x3d4) = 0x36; - U8 old_36 = *(mmio_vbase + 0x3d5); - *(mmio_vbase + 0x3d5) = old_36 | 0x10; - while (0 != ((--time_out) & 0xfff)); - *(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; - - // Increase Reset counter - auto_reset_count++; - } - } - } - return TRUE; - } - 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(xgi_info_t *info) -{ - BOOL ret = FALSE; - U8 *mmio_vbase = info->mmio.vbase; - U32 device_status = 0; - U32 hw_status = 0; - U8 save_3ce = bReadReg(0x3ce); - - - if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened - { - U8 op3cf_3d; - U8 op3cf_37; - - // What happened? - op3cf_37 = bIn3cf(0x37); - -#if 0 - if (op3cf_37 & 0x04) - device_status |= GDEVST_CONNECT; - else - device_status &= ~GDEVST_CONNECT; - - device_status |= GDEVST_DEVICE_CHANGED; - hw_status |= HWST_DEVICE_CHANGED; -#endif - // Clear CRT interrupt - op3cf_3d = bIn3cf(0x3d); - bOut3cf(0x3d, (op3cf_3d | 0x04)); - bOut3cf(0x3d, (op3cf_3d & ~0x04)); - ret = TRUE; - } - bWriteReg(0x3ce, save_3ce); - - return (ret); -} - -BOOL xgi_dvi_irq_handler(xgi_info_t *info) -{ - BOOL ret = FALSE; - U8 *mmio_vbase = info->mmio.vbase; - U32 device_status = 0; - U32 hw_status = 0; - U8 save_3ce = bReadReg(0x3ce); - - if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened - { - U8 op3cf_39; - U8 op3cf_37; - U8 op3x5_5a; - U8 save_3x4 = bReadReg(0x3d4);; - - // What happened? - op3cf_37 = bIn3cf(0x37); -#if 0 - //Also update our internal flag - if (op3cf_37 & 0x10) // Second Monitor plugged In - { - device_status |= GDEVST_CONNECT; - //Because currenly we cannot determine if DVI digital - //or DVI analog is connected according to DVI interrupt - //We should still call BIOS to check it when utility ask us - device_status &= ~GDEVST_CHECKED; - } - else - { - device_status &= ~GDEVST_CONNECT; - } -#endif - //Notify BIOS that DVI plug/unplug happened - op3x5_5a = bIn3x5(0x5a); - bOut3x5(0x5a, op3x5_5a & 0xf7); - - bWriteReg(0x3d4, save_3x4); - - //device_status |= GDEVST_DEVICE_CHANGED; - //hw_status |= HWST_DEVICE_CHANGED; - - // Clear DVI interrupt - op3cf_39 = bIn3cf(0x39); - bOut3c5(0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0 - bOut3c5(0x39, (op3cf_39 | 0x01 )); //Set 3cf.39 bit 0 to 1 - - ret = TRUE; - } - bWriteReg(0x3ce, save_3ce); - - return (ret); -} - -void xgi_dump_register(xgi_info_t *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 = bIn3c5(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 = bIn3x5(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 = bIn3cf(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 = bReadReg(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 = bReadReg(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 = bReadReg(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 = bReadReg(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 = bReadReg(0x2800 + i*0x10 + j); - printk("%3x", temp); - } - printk("\r\n"); - } -} - -void xgi_restore_registers(xgi_info_t *info) -{ - bOut3x5(0x13, 0); - bOut3x5(0x8b, 2); -} - -void xgi_waitfor_pci_idle(xgi_info_t *info) -{ -#define WHOLD_GE_STATUS 0x2800 -#define IDLE_MASK ~0x90200000 - - int idleCount = 0; - while(idleCount < 5) - { - if (dwReadReg(WHOLD_GE_STATUS) & IDLE_MASK) - { - idleCount = 0; - } - else - { - idleCount ++; - } - } -} - -int xgi_get_cpu_id(struct cpu_info_s *arg) -{ - int op = arg->_eax; - __asm__("cpuid" - : "=a" (arg->_eax), - "=b" (arg->_ebx), - "=c" (arg->_ecx), - "=d" (arg->_edx) - : "0" (op)); - - XGI_INFO("opCode = 0x%x, eax = 0x%x, ebx = 0x%x, ecx = 0x%x, edx = 0x%x \n", - op, arg->_eax, arg->_ebx, arg->_ecx, arg->_edx); -} - -/*memory collect function*/ -extern struct list_head xgi_mempid_list; -void xgi_mem_collect(xgi_info_t *info, unsigned int *pcnt) -{ - xgi_mem_pid_t *mempid_block; - struct list_head *mempid_list; - struct task_struct *p,*find; - unsigned int cnt = 0; - - mempid_list = xgi_mempid_list.next; - - while (mempid_list != &xgi_mempid_list) - { - mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); - mempid_list = mempid_list->next; - - find = NULL; - XGI_SCAN_PROCESS(p) - { - if (p->pid == mempid_block->pid) - { - XGI_INFO("[!]Find active pid:%ld state:%ld location:%d addr:0x%lx! \n", mempid_block->pid, p->state, mempid_block->location, mempid_block->bus_addr); - find = p; - if (mempid_block->bus_addr == 0xFFFFFFFF) - ++cnt; - break; - } - } - if (!find) - { - if (mempid_block->location == LOCAL) - { - XGI_INFO("Memory ProcessID free fb and delete one block pid:%ld addr:0x%lx successfully! \n", mempid_block->pid, mempid_block->bus_addr); - xgi_fb_free(info, mempid_block->bus_addr); - } - else if (mempid_block->bus_addr != 0xFFFFFFFF) - { - XGI_INFO("Memory ProcessID free pcie and delete one block pid:%ld addr:0x%lx successfully! \n", mempid_block->pid, mempid_block->bus_addr); - xgi_pcie_free(info, mempid_block->bus_addr); - } - else - { - /*only delete the memory block*/ - list_del(&mempid_block->list); - XGI_INFO("Memory ProcessID delete one pcie block pid:%ld successfully! \n", mempid_block->pid); - kfree(mempid_block); - } - } - } - *pcnt = cnt; -} + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_pcie.h" + +void xgi_get_device_info(xgi_info_t * info, xgi_chip_info_t * req) +{ + req->device_id = info->device_id; + req->device_name[0] = 'x'; + req->device_name[1] = 'g'; + req->device_name[2] = '4'; + req->device_name[3] = '7'; + req->vendor_id = info->vendor_id; + req->curr_display_mode = 0; + req->fb_size = info->fb.size; + req->sarea_bus_addr = info->sarea_info.bus_addr; + req->sarea_size = info->sarea_info.size; +} + +void xgi_get_mmio_info(xgi_info_t * info, xgi_mmio_info_t * req) +{ + req->mmioBase = (void *)info->mmio.base; + req->size = info->mmio.size; +} + +void xgi_put_screen_info(xgi_info_t * info, xgi_screen_info_t * req) +{ + info->scrn_info.scrn_start = req->scrn_start; + info->scrn_info.scrn_xres = req->scrn_xres; + info->scrn_info.scrn_yres = req->scrn_yres; + info->scrn_info.scrn_bpp = req->scrn_bpp; + info->scrn_info.scrn_pitch = req->scrn_pitch; + + XGI_INFO("info->scrn_info.scrn_start: 0x%lx" + "info->scrn_info.scrn_xres: 0x%lx" + "info->scrn_info.scrn_yres: 0x%lx" + "info->scrn_info.scrn_bpp: 0x%lx" + "info->scrn_info.scrn_pitch: 0x%lx\n", + info->scrn_info.scrn_start, + info->scrn_info.scrn_xres, + info->scrn_info.scrn_yres, + info->scrn_info.scrn_bpp, info->scrn_info.scrn_pitch); +} + +void xgi_get_screen_info(xgi_info_t * info, xgi_screen_info_t * req) +{ + req->scrn_start = info->scrn_info.scrn_start; + req->scrn_xres = info->scrn_info.scrn_xres; + req->scrn_yres = info->scrn_info.scrn_yres; + req->scrn_bpp = info->scrn_info.scrn_bpp; + req->scrn_pitch = info->scrn_info.scrn_pitch; + + XGI_INFO("req->scrn_start: 0x%lx" + "req->scrn_xres: 0x%lx" + "req->scrn_yres: 0x%lx" + "req->scrn_bpp: 0x%lx" + "req->scrn_pitch: 0x%lx\n", + req->scrn_start, + req->scrn_xres, + req->scrn_yres, req->scrn_bpp, req->scrn_pitch); +} + +void xgi_ge_reset(xgi_info_t * info) +{ + xgi_disable_ge(info); + xgi_enable_ge(info); +} + +void xgi_sarea_info(xgi_info_t * info, xgi_sarea_info_t * req) +{ + info->sarea_info.bus_addr = req->bus_addr; + info->sarea_info.size = req->size; + XGI_INFO("info->sarea_info.bus_addr: 0x%lx" + "info->sarea_info.size: 0x%lx\n", + info->sarea_info.bus_addr, info->sarea_info.size); +} + +/* + * irq functions + */ +#define STALL_INTERRUPT_RESET_THRESHOLD 0xffff + +static U32 s_invalid_begin = 0; + +BOOL xgi_ge_irq_handler(xgi_info_t * info) +{ + volatile U8 *mmio_vbase = info->mmio.vbase; + volatile U32 *ge_3d_status = (volatile U32 *)(mmio_vbase + 0x2800); + U32 int_status = ge_3d_status[4]; // interrupt status + U32 auto_reset_count = 0; + BOOL is_support_auto_reset = FALSE; + + // Check GE on/off + if (0 == (0xffffc0f0 & int_status)) { + U32 old_ge_status = ge_3d_status[0x00]; + 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 (TRUE == is_support_auto_reset) { + BOOL is_wrong_signal = FALSE; + static U32 last_int_tick_low, + last_int_tick_high; + static U32 new_int_tick_low, new_int_tick_high; + static U32 continoue_int_count = 0; + // OE II is busy. + while (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)) { + is_wrong_signal = TRUE; + break; + } + // Check RO channel + *(mmio_vbase + 0x235c) = 0x83; + check = + *((volatile U16 *)(mmio_vbase + + 0x2360)); + if ((check & 0x0f) != + ((check & 0xf0) >> 4)) { + is_wrong_signal = TRUE; + break; + } + // Check RW channel + *(mmio_vbase + 0x235c) = 0x88; + check = + *((volatile U16 *)(mmio_vbase + + 0x2360)); + if ((check & 0x0f) != + ((check & 0xf0) >> 4)) { + is_wrong_signal = TRUE; + break; + } + // Check RO channel outstanding + *(mmio_vbase + 0x235c) = 0x8f; + check = + *((volatile U16 *)(mmio_vbase + + 0x2360)); + if (0 != (check & 0x3ff)) { + is_wrong_signal = TRUE; + break; + } + // Check RW channel outstanding + *(mmio_vbase + 0x235c) = 0x90; + check = + *((volatile U16 *)(mmio_vbase + + 0x2360)); + if (0 != (check & 0x3ff)) { + is_wrong_signal = TRUE; + break; + } + // No pending PCIE request. GE stall. + break; + } + + if (is_wrong_signal) { + // Nothing but skip. + } else if (0 == continoue_int_count++) { + rdtsc(last_int_tick_low, + last_int_tick_high); + } else { + rdtscl(new_int_tick_low); + if ((new_int_tick_low - + last_int_tick_low) > + STALL_INTERRUPT_RESET_THRESHOLD) { + continoue_int_count = 0; + } else if (continoue_int_count >= 3) { + continoue_int_count = 0; + + // GE Hung up, need reset. + XGI_INFO("Reset GE!\n"); + + *(mmio_vbase + 0xb057) = 8; + int time_out = 0xffff; + while (0 != + (ge_3d_status[0x00] & + 0xf0000000)) { + while (0 != + ((--time_out) & + 0xfff)) ; + if (0 == time_out) { + XGI_INFO + ("Can not reset back 0x%lx!\n", + ge_3d_status + [0x00]); + *(mmio_vbase + + 0xb057) = 0; + // Have to use 3x5.36 to reset. + // Save and close dynamic gating + U8 old_3ce = + *(mmio_vbase + + 0x3ce); + *(mmio_vbase + + 0x3ce) = 0x2a; + U8 old_3cf = + *(mmio_vbase + + 0x3cf); + *(mmio_vbase + + 0x3cf) = + old_3cf & 0xfe; + // Reset GE + U8 old_index = + *(mmio_vbase + + 0x3d4); + *(mmio_vbase + + 0x3d4) = 0x36; + U8 old_36 = + *(mmio_vbase + + 0x3d5); + *(mmio_vbase + + 0x3d5) = + old_36 | 0x10; + while (0 != + ((--time_out) & 0xfff)) ; + *(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; + + // Increase Reset counter + auto_reset_count++; + } + } + } + return TRUE; + } 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(xgi_info_t * info) +{ + BOOL ret = FALSE; + U8 *mmio_vbase = info->mmio.vbase; + U32 device_status = 0; + U32 hw_status = 0; + U8 save_3ce = bReadReg(0x3ce); + + if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened + { + U8 op3cf_3d; + U8 op3cf_37; + + // What happened? + op3cf_37 = bIn3cf(0x37); + +#if 0 + if (op3cf_37 & 0x04) + device_status |= GDEVST_CONNECT; + else + device_status &= ~GDEVST_CONNECT; + + device_status |= GDEVST_DEVICE_CHANGED; + hw_status |= HWST_DEVICE_CHANGED; +#endif + // Clear CRT interrupt + op3cf_3d = bIn3cf(0x3d); + bOut3cf(0x3d, (op3cf_3d | 0x04)); + bOut3cf(0x3d, (op3cf_3d & ~0x04)); + ret = TRUE; + } + bWriteReg(0x3ce, save_3ce); + + return (ret); +} + +BOOL xgi_dvi_irq_handler(xgi_info_t * info) +{ + BOOL ret = FALSE; + U8 *mmio_vbase = info->mmio.vbase; + U32 device_status = 0; + U32 hw_status = 0; + U8 save_3ce = bReadReg(0x3ce); + + if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened + { + U8 op3cf_39; + U8 op3cf_37; + U8 op3x5_5a; + U8 save_3x4 = bReadReg(0x3d4);; + + // What happened? + op3cf_37 = bIn3cf(0x37); +#if 0 + //Also update our internal flag + if (op3cf_37 & 0x10) // Second Monitor plugged In + { + device_status |= GDEVST_CONNECT; + //Because currenly we cannot determine if DVI digital + //or DVI analog is connected according to DVI interrupt + //We should still call BIOS to check it when utility ask us + device_status &= ~GDEVST_CHECKED; + } else { + device_status &= ~GDEVST_CONNECT; + } +#endif + //Notify BIOS that DVI plug/unplug happened + op3x5_5a = bIn3x5(0x5a); + bOut3x5(0x5a, op3x5_5a & 0xf7); + + bWriteReg(0x3d4, save_3x4); + + //device_status |= GDEVST_DEVICE_CHANGED; + //hw_status |= HWST_DEVICE_CHANGED; + + // Clear DVI interrupt + op3cf_39 = bIn3cf(0x39); + bOut3c5(0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0 + bOut3c5(0x39, (op3cf_39 | 0x01)); //Set 3cf.39 bit 0 to 1 + + ret = TRUE; + } + bWriteReg(0x3ce, save_3ce); + + return (ret); +} + +void xgi_dump_register(xgi_info_t * 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 = bIn3c5(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 = bIn3x5(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 = bIn3cf(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 = bReadReg(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 = bReadReg(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 = bReadReg(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 = bReadReg(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 = bReadReg(0x2800 + i * 0x10 + j); + printk("%3x", temp); + } + printk("\r\n"); + } +} + +void xgi_restore_registers(xgi_info_t * info) +{ + bOut3x5(0x13, 0); + bOut3x5(0x8b, 2); +} + +void xgi_waitfor_pci_idle(xgi_info_t * info) +{ +#define WHOLD_GE_STATUS 0x2800 +#define IDLE_MASK ~0x90200000 + + int idleCount = 0; + while (idleCount < 5) { + if (dwReadReg(WHOLD_GE_STATUS) & IDLE_MASK) { + idleCount = 0; + } else { + idleCount++; + } + } +} + +int xgi_get_cpu_id(struct cpu_info_s *arg) +{ + int op = arg->_eax; + __asm__("cpuid":"=a"(arg->_eax), + "=b"(arg->_ebx), + "=c"(arg->_ecx), "=d"(arg->_edx) + : "0"(op)); + + XGI_INFO + ("opCode = 0x%x, eax = 0x%x, ebx = 0x%x, ecx = 0x%x, edx = 0x%x \n", + op, arg->_eax, arg->_ebx, arg->_ecx, arg->_edx); +} + +/*memory collect function*/ +extern struct list_head xgi_mempid_list; +void xgi_mem_collect(xgi_info_t * info, unsigned int *pcnt) +{ + xgi_mem_pid_t *mempid_block; + struct list_head *mempid_list; + struct task_struct *p, *find; + unsigned int cnt = 0; + + mempid_list = xgi_mempid_list.next; + + while (mempid_list != &xgi_mempid_list) { + mempid_block = + list_entry(mempid_list, struct xgi_mem_pid_s, list); + mempid_list = mempid_list->next; + + find = NULL; + XGI_SCAN_PROCESS(p) { + if (p->pid == mempid_block->pid) { + XGI_INFO + ("[!]Find active pid:%ld state:%ld location:%d addr:0x%lx! \n", + mempid_block->pid, p->state, + mempid_block->location, + mempid_block->bus_addr); + find = p; + if (mempid_block->bus_addr == 0xFFFFFFFF) + ++cnt; + break; + } + } + if (!find) { + if (mempid_block->location == LOCAL) { + XGI_INFO + ("Memory ProcessID free fb and delete one block pid:%ld addr:0x%lx successfully! \n", + mempid_block->pid, mempid_block->bus_addr); + xgi_fb_free(info, mempid_block->bus_addr); + } else if (mempid_block->bus_addr != 0xFFFFFFFF) { + XGI_INFO + ("Memory ProcessID free pcie and delete one block pid:%ld addr:0x%lx successfully! \n", + mempid_block->pid, mempid_block->bus_addr); + xgi_pcie_free(info, mempid_block->bus_addr); + } else { + /*only delete the memory block */ + list_del(&mempid_block->list); + XGI_INFO + ("Memory ProcessID delete one pcie block pid:%ld successfully! \n", + mempid_block->pid); + kfree(mempid_block); + } + } + } + *pcnt = cnt; +} diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h index ac4daaa1..37120aaa 100644 --- a/linux-core/xgi_misc.h +++ b/linux-core/xgi_misc.h @@ -1,49 +1,47 @@ - -/**************************************************************************** - * 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(xgi_info_t *info); -extern void xgi_get_device_info(xgi_info_t *info, xgi_chip_info_t * req); -extern void xgi_get_mmio_info(xgi_info_t *info, xgi_mmio_info_t *req); -extern void xgi_get_screen_info(xgi_info_t *info, xgi_screen_info_t *req); -extern void xgi_put_screen_info(xgi_info_t *info, xgi_screen_info_t *req); -extern void xgi_ge_reset(xgi_info_t *info); -extern void xgi_sarea_info(xgi_info_t *info, xgi_sarea_info_t *req); -extern int xgi_get_cpu_id(struct cpu_info_s *arg); - -extern void xgi_restore_registers(xgi_info_t *info); -extern BOOL xgi_ge_irq_handler(xgi_info_t *info); -extern BOOL xgi_crt_irq_handler(xgi_info_t *info); -extern BOOL xgi_dvi_irq_handler(xgi_info_t *info); -extern void xgi_waitfor_pci_idle(xgi_info_t *info); - - -#endif + +/**************************************************************************** + * 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(xgi_info_t * info); +extern void xgi_get_device_info(xgi_info_t * info, xgi_chip_info_t * req); +extern void xgi_get_mmio_info(xgi_info_t * info, xgi_mmio_info_t * req); +extern void xgi_get_screen_info(xgi_info_t * info, xgi_screen_info_t * req); +extern void xgi_put_screen_info(xgi_info_t * info, xgi_screen_info_t * req); +extern void xgi_ge_reset(xgi_info_t * info); +extern void xgi_sarea_info(xgi_info_t * info, xgi_sarea_info_t * req); +extern int xgi_get_cpu_id(struct cpu_info_s *arg); + +extern void xgi_restore_registers(xgi_info_t * info); +extern BOOL xgi_ge_irq_handler(xgi_info_t * info); +extern BOOL xgi_crt_irq_handler(xgi_info_t * info); +extern BOOL xgi_dvi_irq_handler(xgi_info_t * info); +extern void xgi_waitfor_pci_idle(xgi_info_t * info); + +#endif diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 62e2323f..9457770a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -1,1060 +1,1031 @@ - -/**************************************************************************** - * 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_types.h" -#include "xgi_linux.h" -#include "xgi_drv.h" -#include "xgi_regs.h" -#include "xgi_pcie.h" -#include "xgi_misc.h" - -static xgi_pcie_heap_t *xgi_pcie_heap = NULL; -static kmem_cache_t *xgi_pcie_cache_block = NULL; -static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; -static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; -static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; -extern struct list_head xgi_mempid_list; - -static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) -{ - struct page *page; - unsigned long page_addr = 0; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - - if (page_addr == 0UL) - { - XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", - page_count); - return 0; - } - - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) - { - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - } - - XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", - page_count, page_order, page_addr); - return page_addr; -} - -static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) -{ - struct page *page; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) - { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - - free_pages(page_addr, page_order); -} - -static int xgi_pcie_lut_init(xgi_info_t *info) -{ - unsigned char *page_addr = NULL; - unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; - unsigned long count = 0; - u8 temp = 0; - - /* Jong 06/06/2006 */ - unsigned long pcie_aperture_size; - - info->pcie.size = 128 * 1024 * 1024; - - /* Get current FB aperture size */ - temp = In3x5(0x27); - XGI_INFO("In3x5(0x27): 0x%x \n", temp); - - if (temp & 0x01) /* 256MB; Jong 06/05/2006; 0x10000000 */ - { - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size=256 * 1024 * 1024; - /* info->pcie.base = 256 * 1024 * 1024; */ /* pcie base is different from fb base */ - } - else /* 128MB; Jong 06/05/2006; 0x08000000 */ - { - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size=128 * 1024 * 1024; - /* info->pcie.base = 128 * 1024 * 1024; */ - } - - /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ - /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ - /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ - /* info->pcie.base=ioremap(0x0F000000, 0x10000000); */ /* Cause system hang */ - info->pcie.base=pcie_aperture_size; /* works */ - /* info->pcie.base=info->fb.base + info->fb.size; */ /* System hang */ - /* info->pcie.base=128 * 1024 * 1024;*/ /* System hang */ - - XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); - - - /* Get current lookup table page size */ - temp = bReadReg(0xB00C); - if (temp & 0x04) /* 8KB */ - { - info->lutPageSize = 8 * 1024; - } - else /* 4KB */ - { - info->lutPageSize = 4 * 1024; - } - - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); - -#if 0 - /* Get current lookup table location */ - temp = bReadReg(0xB00C); - if (temp & 0x02) /* LFB */ - { - info->isLUTInLFB = TRUE; - /* Current we only support lookup table in LFB */ - temp &= 0xFD; - bWriteReg(0xB00C, temp); - info->isLUTInLFB = FALSE; - } - else /* SFB */ - { - info->isLUTInLFB = FALSE; - } - - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); - - /* Get current SDFB page size */ - temp = bReadReg(0xB00C); - if (temp & 0x08) /* 8MB */ - { - info->sdfbPageSize = 8 * 1024 * 1024; - } - else /* 4MB */ - { - info->sdfbPageSize = 4 * 1024 * 1024; - } -#endif - pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; - - /* - * Allocate memory for PCIE GART table; - */ - lutEntryNum = pciePageCount; - lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; - - /* get page_order base on page_count */ - count = lutPageCount; - for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder); - - if ((lutPageCount << 1) == (1 << lutPageOrder)) - { - lutPageOrder -= 1; - } - - XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", - lutEntryNum, lutPageCount, lutPageOrder); - - info->lutPageOrder = lutPageOrder; - page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); - - if (!page_addr) - { - XGI_ERROR("cannot allocate PCIE lut page!\n"); - goto fail; - } - info->lut_base = (unsigned long *)page_addr; - - XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", - page_addr, virt_to_phys(page_addr)); - - XGI_INFO("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", - info->lut_base, __pa(info->lut_base), info->lutPageOrder); - - /* - * clean all PCIE GART Entry - */ - memset(page_addr, 0, PAGE_SIZE << lutPageOrder); - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ( "wbinvd" ::: "memory" ); -#else - mb(); -#endif - - /* Set GART in SFB */ - bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); - /* Set GART base address to HW */ - dwWriteReg(0xB034, __pa(info->lut_base)); - - return 1; -fail: - return 0; -} - -static void xgi_pcie_lut_cleanup(xgi_info_t *info) -{ - if (info->lut_base) - { - XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", - info->lut_base, info->lutPageOrder); - xgi_pcie_lut_free((unsigned long)info->lut_base, info->lutPageOrder); - info->lut_base = NULL; - } -} - -static xgi_pcie_block_t *xgi_pcie_new_node(void) -{ - xgi_pcie_block_t *block = (xgi_pcie_block_t *)kmem_cache_alloc(xgi_pcie_cache_block, GFP_KERNEL); - if (block == NULL) - { - return NULL; - } - - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = 0; /* The block size. */ - block->bus_addr = 0; /* CPU access address/bus address */ - block->hw_addr = 0; /* GE access address */ - block->page_count = 0; - block->page_order = 0; - block->page_block = NULL; - block->page_table = NULL; - block->owner = PCIE_INVALID; - - return block; -} - -static void xgi_pcie_block_stuff_free(xgi_pcie_block_t *block) -{ - struct page *page; - xgi_page_block_t *page_block = block->page_block; - xgi_page_block_t *free_block; - unsigned long page_count = 0; - int i; - - //XGI_INFO("block->page_block: 0x%p \n", block->page_block); - while (page_block) - { - page_count = page_block->page_count; - - page = virt_to_page(page_block->virt_addr); - for (i = 0; i < page_count; i++, page++) - { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - free_pages(page_block->virt_addr, page_block->page_order); - - page_block->phys_addr = 0; - page_block->virt_addr = 0; - page_block->page_count = 0; - page_block->page_order = 0; - - free_block = page_block; - page_block = page_block->next; - //XGI_INFO("free free_block: 0x%p \n", free_block); - kfree(free_block); - free_block = NULL; - } - - if (block->page_table) - { - //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); - kfree(block->page_table); - block->page_table = NULL; - } -} - -int xgi_pcie_heap_init(xgi_info_t *info) -{ - xgi_pcie_block_t *block; - - if (!xgi_pcie_lut_init(info)) - { - XGI_ERROR("xgi_pcie_lut_init failed\n"); - return 0; - } - - xgi_pcie_heap = (xgi_pcie_heap_t *)kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); - if(!xgi_pcie_heap) - { - XGI_ERROR("xgi_pcie_heap alloc failed\n"); - goto fail1; - } - INIT_LIST_HEAD(&xgi_pcie_heap->free_list); - INIT_LIST_HEAD(&xgi_pcie_heap->used_list); - INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); - - xgi_pcie_heap->max_freesize = info->pcie.size; - - xgi_pcie_cache_block = kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - if (NULL == xgi_pcie_cache_block) - { - XGI_ERROR("Fail to creat xgi_pcie_block\n"); - goto fail2; - } - - block = (xgi_pcie_block_t *)xgi_pcie_new_node(); - if (!block) - { - XGI_ERROR("xgi_pcie_new_node failed\n"); - goto fail3; - } - - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = info->pcie.size; - - list_add(&block->list, &xgi_pcie_heap->free_list); - - XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", block->offset, block->size); - return 1; -fail3: - if (xgi_pcie_cache_block) - { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; - } - -fail2: - if(xgi_pcie_heap) - { - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } -fail1: - xgi_pcie_lut_cleanup(info); - return 0; -} - -void xgi_pcie_heap_check(void) -{ - struct list_head *useList, *temp; - xgi_pcie_block_t *block; - unsigned int ownerIndex; - char *ownerStr[6] = {"2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE"}; - - if (xgi_pcie_heap) - { - useList = &xgi_pcie_heap->used_list; - temp = useList->next; - XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); - while (temp != useList) - { - block = list_entry(temp, struct xgi_pcie_block_s, list); - if (block->owner == PCIE_2D) - ownerIndex = 0; - else if (block->owner > PCIE_3D_TEXTURE || block->owner < PCIE_2D || block->owner < PCIE_3D) - ownerIndex = 5; - else - ownerIndex = block->owner - PCIE_3D + 1; - XGI_INFO("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", - ownerStr[ownerIndex], block->offset, block->size); - temp = temp->next; - } - - } -} - - -void xgi_pcie_heap_cleanup(xgi_info_t *info) -{ - struct list_head *free_list, *temp; - xgi_pcie_block_t *block; - int j; - - xgi_pcie_lut_cleanup(info); - XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); - - if (xgi_pcie_heap) - { - free_list = &xgi_pcie_heap->free_list; - for (j = 0; j < 3; j++, free_list++) - { - temp = free_list->next; - - while (temp != free_list) - { - block = list_entry(temp, struct xgi_pcie_block_s, list); - XGI_INFO("No. %d block->offset: 0x%lx block->size: 0x%lx \n", - j, block->offset, block->size); - xgi_pcie_block_stuff_free(block); - block->bus_addr = 0; - block->hw_addr = 0; - - temp = temp->next; - //XGI_INFO("No. %d free block: 0x%p \n", j, block); - kmem_cache_free(xgi_pcie_cache_block, block); - block = NULL; - } - } - - XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } - - if (xgi_pcie_cache_block) - { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; - } -} - - -static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t *info, - unsigned long originalSize, - enum PcieOwner owner) -{ - struct list_head *free_list; - xgi_pcie_block_t *block, *used_block, *free_block; - xgi_page_block_t *page_block, *prev_page_block; - struct page *page; - unsigned long page_order = 0, count = 0, index =0; - unsigned long page_addr = 0; - unsigned long *lut_addr = NULL; - unsigned long lut_id = 0; - unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; - int i, j, page_count = 0; - int temp = 0; - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); - XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", originalSize, size); - - if (owner == PCIE_3D) - { - if (xgi_pcie_vertex_block) - { - XGI_INFO("PCIE Vertex has been created, return directly.\n"); - return xgi_pcie_vertex_block; - } - } - - if (owner == PCIE_3D_CMDLIST) - { - if (xgi_pcie_cmdlist_block) - { - XGI_INFO("PCIE Cmdlist has been created, return directly.\n"); - return xgi_pcie_cmdlist_block; - } - } - - if (owner == PCIE_3D_SCRATCHPAD) - { - if (xgi_pcie_scratchpad_block) - { - XGI_INFO("PCIE Scratchpad has been created, return directly.\n"); - return xgi_pcie_scratchpad_block; - } - } - - if (size == 0) - { - XGI_ERROR("size == 0 \n"); - return (NULL); - } - - XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); - if (size > xgi_pcie_heap->max_freesize) - { - XGI_ERROR("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", - size, xgi_pcie_heap->max_freesize); - return (NULL); - } - - /* Jong 05/30/2006; find next free list which has enough space*/ - free_list = xgi_pcie_heap->free_list.next; - while (free_list != &xgi_pcie_heap->free_list) - { - //XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_pcie_block_s, list); - if (size <= block->size) - { - break; - } - free_list = free_list->next; - } - - if (free_list == &xgi_pcie_heap->free_list) - { - XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", size/1024); - return (NULL); - } - - free_block = block; - XGI_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; - XGI_INFO("size==free_block->size: free_block = 0x%p\n", free_block); - list_del(&free_block->list); - } - else - { - used_block = xgi_pcie_new_node(); - if (used_block == NULL) - { - return NULL; - } - - if (used_block == free_block) - { - XGI_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; - } - - xgi_pcie_heap->max_freesize -= size; - - used_block->bus_addr = info->pcie.base + used_block->offset; - used_block->hw_addr = info->pcie.base + used_block->offset; - used_block->page_count = page_count = size / PAGE_SIZE; - - /* get page_order base on page_count */ - for (used_block->page_order = 0; page_count; page_count >>= 1) - { - ++used_block->page_order; - } - - if ((used_block->page_count << 1) == (1 << used_block->page_order)) - { - used_block->page_order--; - } - XGI_INFO("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", - used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr, used_block->page_count, used_block->page_order); - - used_block->page_block = NULL; - //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); - //if (!used_block->page_block) return NULL; - //used_block->page_block->next = NULL; - - used_block->page_table = (xgi_pte_t *)kmalloc(sizeof(xgi_pte_t) * used_block->page_count, GFP_KERNEL); - if (used_block->page_table == NULL) - { - goto fail; - } - - lut_id = (used_block->offset >> PAGE_SHIFT); - lut_addr = info->lut_base; - lut_addr += lut_id; - XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); - - /* alloc free pages from system */ - page_count = used_block->page_count; - page_block = used_block->page_block; - prev_page_block = used_block->page_block; - for (i = 0; page_count > 0; i++) - { - /* if size is bigger than 2M bytes, it should be split */ - if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) - { - page_order = XGI_PCIE_ALLOC_MAX_ORDER; - } - else - { - count = page_count; - for (page_order = 0; count; count >>= 1, ++page_order); - - if ((page_count << 1) == (1 << page_order)) - { - page_order -= 1; - } - } - - count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", page_addr); - - if (!page_addr) - { - XGI_ERROR("No: %d :Can't get free pages: 0x%lx from system memory !\n", - i, count); - goto fail; - } - - /* Jong 05/30/2006; test */ - memset((unsigned char *)page_addr, 0xFF, PAGE_SIZE << page_order); - /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ - - if (page_block == NULL) - { - page_block = (xgi_page_block_t *)kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); - if (!page_block) - { - XGI_ERROR("Can't get memory for page_block! \n"); - goto fail; - } - } - - if (prev_page_block == NULL) - { - used_block->page_block = page_block; - prev_page_block = page_block; - } - else - { - prev_page_block->next = page_block; - prev_page_block = page_block; - } - - page_block->next = NULL; - page_block->phys_addr = __pa(page_addr); - page_block->virt_addr = page_addr; - page_block->page_count = count; - page_block->page_order = page_order; - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", page_block->phys_addr); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", page_block->virt_addr); - - page = virt_to_page(page_addr); - - //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" - // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", - // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); - - for (j = 0 ; j < count; j++, page++, lut_addr++) - { - used_block->page_table[index + j].phys_addr = __pa(page_address(page)); - used_block->page_table[index + j].virt_addr = (unsigned long)page_address(page); - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", used_block->page_table[index + j].phys_addr); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", used_block->page_table[index + j].virt_addr); - - *lut_addr = __pa(page_address(page)); - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - - if (temp) - { - XGI_INFO("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", - __pa(page_address(page)), lut_addr, j, *lut_addr); - temp--; - } - } - - page_block = page_block->next; - page_count -= count; - index += count; - temp = 0; - } - - used_block->owner = owner; - list_add(&used_block->list, &xgi_pcie_heap->used_list); - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ( "wbinvd" ::: "memory" ); -#else - mb(); -#endif - - /* Flush GART Table */ - bWriteReg(0xB03F, 0x40); - bWriteReg(0xB03F, 0x00); - - if (owner == PCIE_3D) - { - xgi_pcie_vertex_block = used_block; - } - - if (owner == PCIE_3D_CMDLIST) - { - xgi_pcie_cmdlist_block = used_block; - } - - if (owner == PCIE_3D_SCRATCHPAD) - { - xgi_pcie_scratchpad_block = used_block; - } - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); - return (used_block); - -fail: - xgi_pcie_block_stuff_free(used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - return NULL; -} - -static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t *info, unsigned long offset) -{ - struct list_head *free_list, *used_list; - xgi_pcie_block_t *used_block, *block = NULL; - xgi_pcie_block_t *prev, *next; - unsigned long upper, lower; - - used_list = xgi_pcie_heap->used_list.next; - while (used_list != &xgi_pcie_heap->used_list) - { - block = list_entry(used_list, struct xgi_pcie_block_s, list); - if (block->offset == offset) - { - break; - } - used_list = used_list->next; - } - - if (used_list == &xgi_pcie_heap->used_list) - { - XGI_ERROR("can't find block: 0x%lx to free!\n", offset); - return (NULL); - } - - used_block = block; - XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", - used_block, used_block->offset, used_block->size, used_block->bus_addr, used_block->hw_addr); - - xgi_pcie_block_stuff_free(used_block); - - /* update xgi_pcie_heap */ - xgi_pcie_heap->max_freesize += used_block->size; - - prev = next = NULL; - upper = used_block->offset + used_block->size; - lower = used_block->offset; - - free_list = xgi_pcie_heap->free_list.next; - - while (free_list != &xgi_pcie_heap->free_list) - { - block = list_entry(free_list, struct xgi_pcie_block_s, list); - if (block->offset == upper) - { - next = block; - } - else if ((block->offset + block->size) == lower) - { - prev = block; - } - free_list = free_list->next; - } - - XGI_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); - XGI_INFO("free node 0x%p\n", next); - kmem_cache_free(xgi_pcie_cache_block, next); - kmem_cache_free(xgi_pcie_cache_block, used_block); - next = NULL; - used_block = NULL; - return (prev); - } - - if (prev) - { - prev->size += used_block->size; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (prev); - } - - if (next) - { - next->size += used_block->size; - next->offset = used_block->offset; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (next); - } - - used_block->bus_addr = 0; - used_block->hw_addr = 0; - used_block->page_count = 0; - used_block->page_order = 0; - list_add(&used_block->list, &xgi_pcie_heap->free_list); - XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", - used_block, used_block->offset, used_block->size); - return (used_block); -} - -void xgi_pcie_alloc(xgi_info_t *info, unsigned long size, - enum PcieOwner owner, xgi_mem_alloc_t *alloc) -{ - xgi_pcie_block_t *block; - xgi_mem_pid_t *mempid_block; - - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_alloc(info, size, owner); - xgi_up(info->pcie_sem); - - if (block == NULL) - { - alloc->location = INVALID; - alloc->size = 0; - alloc->bus_addr = 0; - alloc->hw_addr = 0; - XGI_ERROR("PCIE RAM allocation failed\n"); - } - else - { - XGI_INFO("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", - block->offset, block->bus_addr); - alloc->location = NON_LOCAL; - alloc->size = block->size; - alloc->bus_addr = block->bus_addr; - alloc->hw_addr = block->hw_addr; - - /* - manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. - PCIE_3D request means a opengl process created. - PCIE_3D_TEXTURE request means texture cannot alloc from fb. - */ - if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) - { - mempid_block = kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); - if (!mempid_block) - XGI_ERROR("mempid_block alloc failed\n"); - mempid_block->location = NON_LOCAL; - if (owner == PCIE_3D) - mempid_block->bus_addr = 0xFFFFFFFF;/*xgi_pcie_vertex_block has the address*/ - else - mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = alloc->pid; - - XGI_INFO("Memory ProcessID add one pcie block pid:%ld successfully! \n", mempid_block->pid); - list_add(&mempid_block->list, &xgi_mempid_list); - } - } -} - -void xgi_pcie_free(xgi_info_t *info, unsigned long bus_addr) -{ - xgi_pcie_block_t *block; - unsigned long offset = bus_addr - info->pcie.base; - xgi_mem_pid_t *mempid_block; - xgi_mem_pid_t *mempid_freeblock = NULL; - struct list_head *mempid_list; - char isvertex = 0; - int processcnt; - - if (xgi_pcie_vertex_block && xgi_pcie_vertex_block->bus_addr == bus_addr) - isvertex = 1; - - if (isvertex) - { - /*check is there any other process using vertex*/ - processcnt = 0; - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) - { - mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); - if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) - { - ++processcnt; - } - mempid_list = mempid_list->next; - } - if (processcnt > 1) - { - return; - } - } - - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_free(info, offset); - xgi_up(info->pcie_sem); - - if (block == NULL) - { - XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); - } - - if (isvertex) - xgi_pcie_vertex_block = NULL; - - /* manage mempid */ - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) - { - mempid_block = list_entry(mempid_list, struct xgi_mem_pid_s, list); - if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) - { - mempid_freeblock = mempid_block; - break; - } - mempid_list = mempid_list->next; - } - if (mempid_freeblock) - { - list_del(&mempid_freeblock->list); - XGI_INFO("Memory ProcessID delete one pcie block pid:%ld successfully! \n", mempid_freeblock->pid); - kfree(mempid_freeblock); - } -} - -/* - * given a bus address, fid the pcie mem block - * uses the bus address as the key. - */ -void *xgi_find_pcie_block(xgi_info_t *info, unsigned long address) -{ - struct list_head *used_list; - xgi_pcie_block_t *block; - int i; - - used_list = xgi_pcie_heap->used_list.next; - - while (used_list != &xgi_pcie_heap->used_list) - { - block = list_entry(used_list, struct xgi_pcie_block_s, list); - - if (block->bus_addr == address) - { - return block; - } - - if (block->page_table) - { - for (i = 0; i < block->page_count; i++) - { - unsigned long offset = block->bus_addr; - if ( (address >= offset) && (address < (offset + PAGE_SIZE))) - { - return block; - } - } - } - used_list = used_list->next; - } - - XGI_ERROR("could not find map for vm 0x%lx\n", address); - - return NULL; -} - -/* - address -- GE HW address - return -- CPU virtual address - - assume the CPU VAddr is continuous in not the same block -*/ -void *xgi_find_pcie_virt(xgi_info_t *info, unsigned long address) -{ - struct list_head *used_list; - xgi_pcie_block_t *block; - unsigned long offset_in_page; - unsigned long loc_in_pagetable; - void * ret; - - XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); - - used_list = xgi_pcie_heap->used_list.next; - XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); - - offset_in_page = address & (PAGE_SIZE-1); - XGI_INFO("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", address, PAGE_SIZE-1, offset_in_page); - - while (used_list != &xgi_pcie_heap->used_list) - { - block = list_entry(used_list, struct xgi_pcie_block_s, list); - XGI_INFO("Jong_05292006-block=0x%px\n", block); - XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", block->hw_addr); - XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); - - if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) - { - loc_in_pagetable = (address - block->hw_addr) >> PAGE_SHIFT; - ret = (void*)(block->page_table[loc_in_pagetable].virt_addr + offset_in_page); - - XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); - XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", loc_in_pagetable); - XGI_INFO("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", block->page_table[loc_in_pagetable].virt_addr); - XGI_INFO("Jong_05292006-offset_in_page=%d\n", offset_in_page); - XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", ret); - - return ret ; - } - else - { - XGI_INFO("Jong_05292006-used_list = used_list->next;\n"); - used_list = used_list->next; - } - } - - XGI_ERROR("could not find map for vm 0x%lx\n", address); - return NULL; -} - - -void xgi_read_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) -{ - -} - -void xgi_write_pcie_mem(xgi_info_t *info, xgi_mem_req_t *req) -{ -} - -/* - address -- GE hw address -*/ -void xgi_test_rwinkernel(xgi_info_t *info, unsigned long address) -{ - unsigned long * virtaddr = 0; - if (address == 0) - { - XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); - return; - } - - virtaddr = (unsigned long *) xgi_find_pcie_virt(info, address); - - XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); - XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); - XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); - if (virtaddr != NULL) - { - *virtaddr = 0x00f00fff; - } - - XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); -} - + +/**************************************************************************** + * 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_types.h" +#include "xgi_linux.h" +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_pcie.h" +#include "xgi_misc.h" + +static xgi_pcie_heap_t *xgi_pcie_heap = NULL; +static kmem_cache_t *xgi_pcie_cache_block = NULL; +static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; +static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; +static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; +extern struct list_head xgi_mempid_list; + +static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) +{ + struct page *page; + unsigned long page_addr = 0; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + + if (page_addr == 0UL) { + XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", + page_count); + return 0; + } + + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) { + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + } + + XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", + page_count, page_order, page_addr); + return page_addr; +} + +static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) +{ + struct page *page; + unsigned long page_count = 0; + int i; + + page_count = (1 << page_order); + page = virt_to_page(page_addr); + + for (i = 0; i < page_count; i++, page++) { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + + free_pages(page_addr, page_order); +} + +static int xgi_pcie_lut_init(xgi_info_t * info) +{ + unsigned char *page_addr = NULL; + unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; + unsigned long count = 0; + u8 temp = 0; + + /* Jong 06/06/2006 */ + unsigned long pcie_aperture_size; + + info->pcie.size = 128 * 1024 * 1024; + + /* Get current FB aperture size */ + temp = In3x5(0x27); + XGI_INFO("In3x5(0x27): 0x%x \n", temp); + + if (temp & 0x01) { /* 256MB; Jong 06/05/2006; 0x10000000 */ + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size = 256 * 1024 * 1024; + /* info->pcie.base = 256 * 1024 * 1024; *//* pcie base is different from fb base */ + } else { /* 128MB; Jong 06/05/2006; 0x08000000 */ + + /* Jong 06/06/2006; allocate memory */ + pcie_aperture_size = 128 * 1024 * 1024; + /* info->pcie.base = 128 * 1024 * 1024; */ + } + + /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ + /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ + /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ + /* info->pcie.base=ioremap(0x0F000000, 0x10000000); *//* Cause system hang */ + info->pcie.base = pcie_aperture_size; /* works */ + /* info->pcie.base=info->fb.base + info->fb.size; *//* System hang */ + /* info->pcie.base=128 * 1024 * 1024; *//* System hang */ + + XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); + + /* Get current lookup table page size */ + temp = bReadReg(0xB00C); + if (temp & 0x04) { /* 8KB */ + info->lutPageSize = 8 * 1024; + } else { /* 4KB */ + + info->lutPageSize = 4 * 1024; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + +#if 0 + /* Get current lookup table location */ + temp = bReadReg(0xB00C); + if (temp & 0x02) { /* LFB */ + info->isLUTInLFB = TRUE; + /* Current we only support lookup table in LFB */ + temp &= 0xFD; + bWriteReg(0xB00C, temp); + info->isLUTInLFB = FALSE; + } else { /* SFB */ + + info->isLUTInLFB = FALSE; + } + + XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + + /* Get current SDFB page size */ + temp = bReadReg(0xB00C); + if (temp & 0x08) { /* 8MB */ + info->sdfbPageSize = 8 * 1024 * 1024; + } else { /* 4MB */ + + info->sdfbPageSize = 4 * 1024 * 1024; + } +#endif + pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; + + /* + * Allocate memory for PCIE GART table; + */ + lutEntryNum = pciePageCount; + lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; + + /* get page_order base on page_count */ + count = lutPageCount; + for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder) ; + + if ((lutPageCount << 1) == (1 << lutPageOrder)) { + lutPageOrder -= 1; + } + + XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", + lutEntryNum, lutPageCount, lutPageOrder); + + info->lutPageOrder = lutPageOrder; + page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); + + if (!page_addr) { + XGI_ERROR("cannot allocate PCIE lut page!\n"); + goto fail; + } + info->lut_base = (unsigned long *)page_addr; + + XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", + page_addr, virt_to_phys(page_addr)); + + XGI_INFO + ("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", + info->lut_base, __pa(info->lut_base), info->lutPageOrder); + + /* + * clean all PCIE GART Entry + */ + memset(page_addr, 0, PAGE_SIZE << lutPageOrder); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ("wbinvd":::"memory"); +#else + mb(); +#endif + + /* Set GART in SFB */ + bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); + /* Set GART base address to HW */ + dwWriteReg(0xB034, __pa(info->lut_base)); + + return 1; + fail: + return 0; +} + +static void xgi_pcie_lut_cleanup(xgi_info_t * info) +{ + if (info->lut_base) { + XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", + info->lut_base, info->lutPageOrder); + xgi_pcie_lut_free((unsigned long)info->lut_base, + info->lutPageOrder); + info->lut_base = NULL; + } +} + +static xgi_pcie_block_t *xgi_pcie_new_node(void) +{ + xgi_pcie_block_t *block = + (xgi_pcie_block_t *) kmem_cache_alloc(xgi_pcie_cache_block, + GFP_KERNEL); + if (block == NULL) { + return NULL; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = 0; /* The block size. */ + block->bus_addr = 0; /* CPU access address/bus address */ + block->hw_addr = 0; /* GE access address */ + block->page_count = 0; + block->page_order = 0; + block->page_block = NULL; + block->page_table = NULL; + block->owner = PCIE_INVALID; + + return block; +} + +static void xgi_pcie_block_stuff_free(xgi_pcie_block_t * block) +{ + struct page *page; + xgi_page_block_t *page_block = block->page_block; + xgi_page_block_t *free_block; + unsigned long page_count = 0; + int i; + + //XGI_INFO("block->page_block: 0x%p \n", block->page_block); + while (page_block) { + page_count = page_block->page_count; + + page = virt_to_page(page_block->virt_addr); + for (i = 0; i < page_count; i++, page++) { + XGI_DEC_PAGE_COUNT(page); + XGIUnlockPage(page); + } + free_pages(page_block->virt_addr, page_block->page_order); + + page_block->phys_addr = 0; + page_block->virt_addr = 0; + page_block->page_count = 0; + page_block->page_order = 0; + + free_block = page_block; + page_block = page_block->next; + //XGI_INFO("free free_block: 0x%p \n", free_block); + kfree(free_block); + free_block = NULL; + } + + if (block->page_table) { + //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); + kfree(block->page_table); + block->page_table = NULL; + } +} + +int xgi_pcie_heap_init(xgi_info_t * info) +{ + xgi_pcie_block_t *block; + + if (!xgi_pcie_lut_init(info)) { + XGI_ERROR("xgi_pcie_lut_init failed\n"); + return 0; + } + + xgi_pcie_heap = + (xgi_pcie_heap_t *) kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); + if (!xgi_pcie_heap) { + XGI_ERROR("xgi_pcie_heap alloc failed\n"); + goto fail1; + } + INIT_LIST_HEAD(&xgi_pcie_heap->free_list); + INIT_LIST_HEAD(&xgi_pcie_heap->used_list); + INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); + + xgi_pcie_heap->max_freesize = info->pcie.size; + + xgi_pcie_cache_block = + kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (NULL == xgi_pcie_cache_block) { + XGI_ERROR("Fail to creat xgi_pcie_block\n"); + goto fail2; + } + + block = (xgi_pcie_block_t *) xgi_pcie_new_node(); + if (!block) { + XGI_ERROR("xgi_pcie_new_node failed\n"); + goto fail3; + } + + block->offset = 0; /* block's offset in pcie memory, begin from 0 */ + block->size = info->pcie.size; + + list_add(&block->list, &xgi_pcie_heap->free_list); + + XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", + block->offset, block->size); + return 1; + fail3: + if (xgi_pcie_cache_block) { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } + + fail2: + if (xgi_pcie_heap) { + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } + fail1: + xgi_pcie_lut_cleanup(info); + return 0; +} + +void xgi_pcie_heap_check(void) +{ + struct list_head *useList, *temp; + xgi_pcie_block_t *block; + unsigned int ownerIndex; + char *ownerStr[6] = + { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; + + if (xgi_pcie_heap) { + useList = &xgi_pcie_heap->used_list; + temp = useList->next; + XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); + while (temp != useList) { + block = list_entry(temp, struct xgi_pcie_block_s, list); + if (block->owner == PCIE_2D) + ownerIndex = 0; + else if (block->owner > PCIE_3D_TEXTURE + || block->owner < PCIE_2D + || block->owner < PCIE_3D) + ownerIndex = 5; + else + ownerIndex = block->owner - PCIE_3D + 1; + XGI_INFO + ("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", + ownerStr[ownerIndex], block->offset, block->size); + temp = temp->next; + } + + } +} + +void xgi_pcie_heap_cleanup(xgi_info_t * info) +{ + struct list_head *free_list, *temp; + xgi_pcie_block_t *block; + int j; + + xgi_pcie_lut_cleanup(info); + XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); + + if (xgi_pcie_heap) { + free_list = &xgi_pcie_heap->free_list; + for (j = 0; j < 3; j++, free_list++) { + temp = free_list->next; + + while (temp != free_list) { + block = + list_entry(temp, struct xgi_pcie_block_s, + list); + XGI_INFO + ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + j, block->offset, block->size); + xgi_pcie_block_stuff_free(block); + block->bus_addr = 0; + block->hw_addr = 0; + + temp = temp->next; + //XGI_INFO("No. %d free block: 0x%p \n", j, block); + kmem_cache_free(xgi_pcie_cache_block, block); + block = NULL; + } + } + + XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); + kfree(xgi_pcie_heap); + xgi_pcie_heap = NULL; + } + + if (xgi_pcie_cache_block) { + kmem_cache_destroy(xgi_pcie_cache_block); + xgi_pcie_cache_block = NULL; + } +} + +static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, + unsigned long originalSize, + enum PcieOwner owner) +{ + struct list_head *free_list; + xgi_pcie_block_t *block, *used_block, *free_block; + xgi_page_block_t *page_block, *prev_page_block; + struct page *page; + unsigned long page_order = 0, count = 0, index = 0; + unsigned long page_addr = 0; + unsigned long *lut_addr = NULL; + unsigned long lut_id = 0; + unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; + int i, j, page_count = 0; + int temp = 0; + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); + XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", + originalSize, size); + + if (owner == PCIE_3D) { + if (xgi_pcie_vertex_block) { + XGI_INFO + ("PCIE Vertex has been created, return directly.\n"); + return xgi_pcie_vertex_block; + } + } + + if (owner == PCIE_3D_CMDLIST) { + if (xgi_pcie_cmdlist_block) { + XGI_INFO + ("PCIE Cmdlist has been created, return directly.\n"); + return xgi_pcie_cmdlist_block; + } + } + + if (owner == PCIE_3D_SCRATCHPAD) { + if (xgi_pcie_scratchpad_block) { + XGI_INFO + ("PCIE Scratchpad has been created, return directly.\n"); + return xgi_pcie_scratchpad_block; + } + } + + if (size == 0) { + XGI_ERROR("size == 0 \n"); + return (NULL); + } + + XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); + if (size > xgi_pcie_heap->max_freesize) { + XGI_ERROR + ("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", + size, xgi_pcie_heap->max_freesize); + return (NULL); + } + + /* Jong 05/30/2006; find next free list which has enough space */ + free_list = xgi_pcie_heap->free_list.next; + while (free_list != &xgi_pcie_heap->free_list) { + //XGI_INFO("free_list: 0x%px \n", free_list); + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (size <= block->size) { + break; + } + free_list = free_list->next; + } + + if (free_list == &xgi_pcie_heap->free_list) { + XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", + size / 1024); + return (NULL); + } + + free_block = block; + XGI_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; + XGI_INFO("size==free_block->size: free_block = 0x%p\n", + free_block); + list_del(&free_block->list); + } else { + used_block = xgi_pcie_new_node(); + if (used_block == NULL) { + return NULL; + } + + if (used_block == free_block) { + XGI_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; + } + + xgi_pcie_heap->max_freesize -= size; + + used_block->bus_addr = info->pcie.base + used_block->offset; + used_block->hw_addr = info->pcie.base + used_block->offset; + used_block->page_count = page_count = size / PAGE_SIZE; + + /* get page_order base on page_count */ + for (used_block->page_order = 0; page_count; page_count >>= 1) { + ++used_block->page_order; + } + + if ((used_block->page_count << 1) == (1 << used_block->page_order)) { + used_block->page_order--; + } + XGI_INFO + ("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", + used_block->offset, used_block->size, used_block->bus_addr, + used_block->hw_addr, used_block->page_count, + used_block->page_order); + + used_block->page_block = NULL; + //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); + //if (!used_block->page_block) return NULL; + //used_block->page_block->next = NULL; + + used_block->page_table = + (xgi_pte_t *) kmalloc(sizeof(xgi_pte_t) * used_block->page_count, + GFP_KERNEL); + if (used_block->page_table == NULL) { + goto fail; + } + + lut_id = (used_block->offset >> PAGE_SHIFT); + lut_addr = info->lut_base; + lut_addr += lut_id; + XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); + + /* alloc free pages from system */ + page_count = used_block->page_count; + page_block = used_block->page_block; + prev_page_block = used_block->page_block; + for (i = 0; page_count > 0; i++) { + /* if size is bigger than 2M bytes, it should be split */ + if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) { + page_order = XGI_PCIE_ALLOC_MAX_ORDER; + } else { + count = page_count; + for (page_order = 0; count; count >>= 1, ++page_order) ; + + if ((page_count << 1) == (1 << page_order)) { + page_order -= 1; + } + } + + count = (1 << page_order); + page_addr = __get_free_pages(GFP_KERNEL, page_order); + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", + page_addr); + + if (!page_addr) { + XGI_ERROR + ("No: %d :Can't get free pages: 0x%lx from system memory !\n", + i, count); + goto fail; + } + + /* Jong 05/30/2006; test */ + memset((unsigned char *)page_addr, 0xFF, + PAGE_SIZE << page_order); + /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ + + if (page_block == NULL) { + page_block = + (xgi_page_block_t *) + kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); + if (!page_block) { + XGI_ERROR + ("Can't get memory for page_block! \n"); + goto fail; + } + } + + if (prev_page_block == NULL) { + used_block->page_block = page_block; + prev_page_block = page_block; + } else { + prev_page_block->next = page_block; + prev_page_block = page_block; + } + + page_block->next = NULL; + page_block->phys_addr = __pa(page_addr); + page_block->virt_addr = page_addr; + page_block->page_count = count; + page_block->page_order = page_order; + + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", + page_block->phys_addr); + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", + page_block->virt_addr); + + page = virt_to_page(page_addr); + + //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" + // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", + // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); + + for (j = 0; j < count; j++, page++, lut_addr++) { + used_block->page_table[index + j].phys_addr = + __pa(page_address(page)); + used_block->page_table[index + j].virt_addr = + (unsigned long)page_address(page); + + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", + used_block->page_table[index + j].phys_addr); + XGI_INFO + ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", + used_block->page_table[index + j].virt_addr); + + *lut_addr = __pa(page_address(page)); + XGI_INC_PAGE_COUNT(page); + XGILockPage(page); + + if (temp) { + XGI_INFO + ("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", + __pa(page_address(page)), lut_addr, j, + *lut_addr); + temp--; + } + } + + page_block = page_block->next; + page_count -= count; + index += count; + temp = 0; + } + + used_block->owner = owner; + list_add(&used_block->list, &xgi_pcie_heap->used_list); + +#if defined(__i386__) || defined(__x86_64__) + asm volatile ("wbinvd":::"memory"); +#else + mb(); +#endif + + /* Flush GART Table */ + bWriteReg(0xB03F, 0x40); + bWriteReg(0xB03F, 0x00); + + if (owner == PCIE_3D) { + xgi_pcie_vertex_block = used_block; + } + + if (owner == PCIE_3D_CMDLIST) { + xgi_pcie_cmdlist_block = used_block; + } + + if (owner == PCIE_3D_SCRATCHPAD) { + xgi_pcie_scratchpad_block = used_block; + } + + XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); + return (used_block); + + fail: + xgi_pcie_block_stuff_free(used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + return NULL; +} + +static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, + unsigned long offset) +{ + struct list_head *free_list, *used_list; + xgi_pcie_block_t *used_block, *block = NULL; + xgi_pcie_block_t *prev, *next; + unsigned long upper, lower; + + used_list = xgi_pcie_heap->used_list.next; + while (used_list != &xgi_pcie_heap->used_list) { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + if (block->offset == offset) { + break; + } + used_list = used_list->next; + } + + if (used_list == &xgi_pcie_heap->used_list) { + XGI_ERROR("can't find block: 0x%lx to free!\n", offset); + return (NULL); + } + + used_block = block; + XGI_INFO + ("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", + used_block, used_block->offset, used_block->size, + used_block->bus_addr, used_block->hw_addr); + + xgi_pcie_block_stuff_free(used_block); + + /* update xgi_pcie_heap */ + xgi_pcie_heap->max_freesize += used_block->size; + + prev = next = NULL; + upper = used_block->offset + used_block->size; + lower = used_block->offset; + + free_list = xgi_pcie_heap->free_list.next; + + while (free_list != &xgi_pcie_heap->free_list) { + block = list_entry(free_list, struct xgi_pcie_block_s, list); + if (block->offset == upper) { + next = block; + } else if ((block->offset + block->size) == lower) { + prev = block; + } + free_list = free_list->next; + } + + XGI_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); + XGI_INFO("free node 0x%p\n", next); + kmem_cache_free(xgi_pcie_cache_block, next); + kmem_cache_free(xgi_pcie_cache_block, used_block); + next = NULL; + used_block = NULL; + return (prev); + } + + if (prev) { + prev->size += used_block->size; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (prev); + } + + if (next) { + next->size += used_block->size; + next->offset = used_block->offset; + XGI_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_pcie_cache_block, used_block); + used_block = NULL; + return (next); + } + + used_block->bus_addr = 0; + used_block->hw_addr = 0; + used_block->page_count = 0; + used_block->page_order = 0; + list_add(&used_block->list, &xgi_pcie_heap->free_list); + XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", + used_block, used_block->offset, used_block->size); + return (used_block); +} + +void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, + enum PcieOwner owner, xgi_mem_alloc_t * alloc) +{ + xgi_pcie_block_t *block; + xgi_mem_pid_t *mempid_block; + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_alloc(info, size, owner); + xgi_up(info->pcie_sem); + + if (block == NULL) { + alloc->location = INVALID; + alloc->size = 0; + alloc->bus_addr = 0; + alloc->hw_addr = 0; + XGI_ERROR("PCIE RAM allocation failed\n"); + } else { + XGI_INFO + ("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", + block->offset, block->bus_addr); + alloc->location = NON_LOCAL; + alloc->size = block->size; + alloc->bus_addr = block->bus_addr; + alloc->hw_addr = block->hw_addr; + + /* + manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. + PCIE_3D request means a opengl process created. + PCIE_3D_TEXTURE request means texture cannot alloc from fb. + */ + if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) { + mempid_block = + kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + if (!mempid_block) + XGI_ERROR("mempid_block alloc failed\n"); + mempid_block->location = NON_LOCAL; + if (owner == PCIE_3D) + mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ + else + mempid_block->bus_addr = alloc->bus_addr; + mempid_block->pid = alloc->pid; + + XGI_INFO + ("Memory ProcessID add one pcie block pid:%ld successfully! \n", + mempid_block->pid); + list_add(&mempid_block->list, &xgi_mempid_list); + } + } +} + +void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) +{ + xgi_pcie_block_t *block; + unsigned long offset = bus_addr - info->pcie.base; + xgi_mem_pid_t *mempid_block; + xgi_mem_pid_t *mempid_freeblock = NULL; + struct list_head *mempid_list; + char isvertex = 0; + int processcnt; + + if (xgi_pcie_vertex_block + && xgi_pcie_vertex_block->bus_addr == bus_addr) + isvertex = 1; + + if (isvertex) { + /*check is there any other process using vertex */ + processcnt = 0; + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) { + mempid_block = + list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL + && mempid_block->bus_addr == 0xFFFFFFFF) { + ++processcnt; + } + mempid_list = mempid_list->next; + } + if (processcnt > 1) { + return; + } + } + + xgi_down(info->pcie_sem); + block = xgi_pcie_mem_free(info, offset); + xgi_up(info->pcie_sem); + + if (block == NULL) { + XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); + } + + if (isvertex) + xgi_pcie_vertex_block = NULL; + + /* manage mempid */ + mempid_list = xgi_mempid_list.next; + while (mempid_list != &xgi_mempid_list) { + mempid_block = + list_entry(mempid_list, struct xgi_mem_pid_s, list); + if (mempid_block->location == NON_LOCAL + && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) + || (!isvertex && mempid_block->bus_addr == bus_addr))) { + mempid_freeblock = mempid_block; + break; + } + mempid_list = mempid_list->next; + } + if (mempid_freeblock) { + list_del(&mempid_freeblock->list); + XGI_INFO + ("Memory ProcessID delete one pcie block pid:%ld successfully! \n", + mempid_freeblock->pid); + kfree(mempid_freeblock); + } +} + +/* + * given a bus address, fid the pcie mem block + * uses the bus address as the key. + */ +void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + int i; + + used_list = xgi_pcie_heap->used_list.next; + + while (used_list != &xgi_pcie_heap->used_list) { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + + if (block->bus_addr == address) { + return block; + } + + if (block->page_table) { + for (i = 0; i < block->page_count; i++) { + unsigned long offset = block->bus_addr; + if ((address >= offset) + && (address < (offset + PAGE_SIZE))) { + return block; + } + } + } + used_list = used_list->next; + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + + return NULL; +} + +/* + address -- GE HW address + return -- CPU virtual address + + assume the CPU VAddr is continuous in not the same block +*/ +void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) +{ + struct list_head *used_list; + xgi_pcie_block_t *block; + unsigned long offset_in_page; + unsigned long loc_in_pagetable; + void *ret; + + XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); + + used_list = xgi_pcie_heap->used_list.next; + XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); + + offset_in_page = address & (PAGE_SIZE - 1); + XGI_INFO + ("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", + address, PAGE_SIZE - 1, offset_in_page); + + while (used_list != &xgi_pcie_heap->used_list) { + block = list_entry(used_list, struct xgi_pcie_block_s, list); + XGI_INFO("Jong_05292006-block=0x%px\n", block); + XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", + block->hw_addr); + XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); + + if ((address >= block->hw_addr) + && (address < (block->hw_addr + block->size))) { + loc_in_pagetable = + (address - block->hw_addr) >> PAGE_SHIFT; + ret = + (void *)(block->page_table[loc_in_pagetable]. + virt_addr + offset_in_page); + + XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); + XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", + loc_in_pagetable); + XGI_INFO + ("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", + block->page_table[loc_in_pagetable].virt_addr); + XGI_INFO("Jong_05292006-offset_in_page=%d\n", + offset_in_page); + XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", + ret); + + return ret; + } else { + XGI_INFO + ("Jong_05292006-used_list = used_list->next;\n"); + used_list = used_list->next; + } + } + + XGI_ERROR("could not find map for vm 0x%lx\n", address); + return NULL; +} + +void xgi_read_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +{ + +} + +void xgi_write_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +{ +} + +/* + address -- GE hw address +*/ +void xgi_test_rwinkernel(xgi_info_t * info, unsigned long address) +{ + unsigned long *virtaddr = 0; + if (address == 0) { + XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); + return; + } + + virtaddr = (unsigned long *)xgi_find_pcie_virt(info, address); + + XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); + XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); + XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); + if (virtaddr != NULL) { + *virtaddr = 0x00f00fff; + } + + XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); +} diff --git a/linux-core/xgi_pcie.h b/linux-core/xgi_pcie.h index cd5f85b8..32c2b584 100644 --- a/linux-core/xgi_pcie.h +++ b/linux-core/xgi_pcie.h @@ -1,73 +1,73 @@ - -/**************************************************************************** - * 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_PCIE_H_ -#define _XGI_PCIE_H_ - -#ifndef XGI_PCIE_ALLOC_MAX_ORDER -#define XGI_PCIE_ALLOC_MAX_ORDER 1 /* 8K in Kernel 2.4.* */ -#endif - -typedef struct xgi_page_block_s { - struct xgi_page_block_s *next; - unsigned long phys_addr; - unsigned long virt_addr; - unsigned long page_count; - unsigned long page_order; -} xgi_page_block_t; - -typedef struct xgi_pcie_block_s { - struct list_head list; - unsigned long offset; /* block's offset in pcie memory, begin from 0 */ - unsigned long size; /* The block size. */ - unsigned long bus_addr; /* CPU access address/bus address */ - unsigned long hw_addr; /* GE access address */ - - unsigned long page_count; - unsigned long page_order; - xgi_page_block_t *page_block; - xgi_pte_t *page_table; /* list of physical pages allocated */ - - atomic_t use_count; - enum PcieOwner owner; - unsigned long processID; -} xgi_pcie_block_t; - -typedef struct xgi_pcie_list_s { - xgi_pcie_block_t *head; - xgi_pcie_block_t *tail; -} xgi_pcie_list_t; - -typedef struct xgi_pcie_heap_s { - struct list_head free_list; - struct list_head used_list; - struct list_head sort_list; - unsigned long max_freesize; -} xgi_pcie_heap_t; - -#endif + +/**************************************************************************** + * 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_PCIE_H_ +#define _XGI_PCIE_H_ + +#ifndef XGI_PCIE_ALLOC_MAX_ORDER +#define XGI_PCIE_ALLOC_MAX_ORDER 1 /* 8K in Kernel 2.4.* */ +#endif + +typedef struct xgi_page_block_s { + struct xgi_page_block_s *next; + unsigned long phys_addr; + unsigned long virt_addr; + unsigned long page_count; + unsigned long page_order; +} xgi_page_block_t; + +typedef struct xgi_pcie_block_s { + struct list_head list; + unsigned long offset; /* block's offset in pcie memory, begin from 0 */ + unsigned long size; /* The block size. */ + unsigned long bus_addr; /* CPU access address/bus address */ + unsigned long hw_addr; /* GE access address */ + + unsigned long page_count; + unsigned long page_order; + xgi_page_block_t *page_block; + xgi_pte_t *page_table; /* list of physical pages allocated */ + + atomic_t use_count; + enum PcieOwner owner; + unsigned long processID; +} xgi_pcie_block_t; + +typedef struct xgi_pcie_list_s { + xgi_pcie_block_t *head; + xgi_pcie_block_t *tail; +} xgi_pcie_list_t; + +typedef struct xgi_pcie_heap_s { + struct list_head free_list; + struct list_head used_list; + struct list_head sort_list; + unsigned long max_freesize; +} xgi_pcie_heap_t; + +#endif diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 18448139..487a7e15 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -1,410 +1,404 @@ - -/**************************************************************************** - * 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_ - -#ifndef XGI_MMIO - #define XGI_MMIO 1 -#endif - -#if XGI_MMIO -#define OUTB(port, value) writeb(value, info->mmio.vbase + port) -#define INB(port) readb(info->mmio.vbase + port) -#define OUTW(port, value) writew(value, info->mmio.vbase + port) -#define INW(port) readw(info->mmio.vbase + port) -#define OUTDW(port, value) writel(value, info->mmio.vbase + port) -#define INDW(port) readl(info->mmio.vbase + port) -#else -#define OUTB(port, value) outb(value, port) -#define INB(port) inb(port) -#define OUTW(port, value) outw(value, port) -#define INW(port) inw(port) -#define OUTDW(port, value) outl(value, port) -#define INDW(port) inl(port) -#endif - -/* Hardware access functions */ -static inline void OUT3C5B(xgi_info_t *info, u8 index, u8 data) -{ - OUTB(0x3C4, index); - OUTB(0x3C5, data); -} - -static inline void OUT3X5B(xgi_info_t *info, u8 index, u8 data) -{ - OUTB(0x3D4, index); - OUTB(0x3D5, data); -} - -static inline void OUT3CFB(xgi_info_t *info, u8 index, u8 data) -{ - OUTB(0x3CE, index); - OUTB(0x3CF, data); -} - -static inline u8 IN3C5B(xgi_info_t *info, u8 index) -{ - volatile u8 data=0; - OUTB(0x3C4, index); - data = INB(0x3C5); - return data; -} - -static inline u8 IN3X5B(xgi_info_t *info, u8 index) -{ - volatile u8 data=0; - OUTB(0x3D4, index); - data = INB(0x3D5); - return data; -} - -static inline u8 IN3CFB(xgi_info_t *info, u8 index) -{ - volatile u8 data=0; - OUTB(0x3CE, index); - data = INB(0x3CF); - return data; -} - -static inline void OUT3C5W(xgi_info_t *info, u8 index, u16 data) -{ - OUTB(0x3C4, index); - OUTB(0x3C5, data); -} - -static inline void OUT3X5W(xgi_info_t *info, u8 index, u16 data) -{ - OUTB(0x3D4, index); - OUTB(0x3D5, data); -} - -static inline void OUT3CFW(xgi_info_t *info, u8 index, u8 data) -{ - OUTB(0x3CE, index); - OUTB(0x3CF, data); -} - -static inline u8 IN3C5W(xgi_info_t *info, u8 index) -{ - volatile u8 data=0; - OUTB(0x3C4, index); - data = INB(0x3C5); - return data; -} - -static inline u8 IN3X5W(xgi_info_t *info, u8 index) -{ - volatile u8 data=0; - OUTB(0x3D4, index); - data = INB(0x3D5); - return data; -} - -static inline u8 IN3CFW(xgi_info_t *info, u8 index) -{ - volatile u8 data=0; - OUTB(0x3CE, index); - data = INB(0x3CF); - return data; -} - -static inline u8 readAttr(xgi_info_t *info, u8 index) -{ - INB(0x3DA); /* flip-flop to index */ - OUTB(0x3C0, index); - return INB(0x3C1); -} - -static inline void writeAttr(xgi_info_t *info, u8 index, u8 value) -{ - INB(0x3DA); /* flip-flop to index */ - OUTB(0x3C0, index); - OUTB(0x3C0, value); -} - -/* - * Graphic engine register (2d/3d) acessing interface - */ -static inline void WriteRegDWord(xgi_info_t *info, u32 addr, u32 data) -{ - /* Jong 05/25/2006 */ - XGI_INFO("Jong-WriteRegDWord()-Begin \n"); - XGI_INFO("Jong-WriteRegDWord()-info->mmio.vbase=0x%lx \n", info->mmio.vbase); - XGI_INFO("Jong-WriteRegDWord()-addr=0x%lx \n", addr); - XGI_INFO("Jong-WriteRegDWord()-data=0x%lx \n", data); - /* return; */ - - *(volatile u32*)(info->mmio.vbase + addr) = (data); - XGI_INFO("Jong-WriteRegDWord()-End \n"); -} - -static inline void WriteRegWord(xgi_info_t *info, u32 addr, u16 data) -{ - *(volatile u16*)(info->mmio.vbase + addr) = (data); -} - -static inline void WriteRegByte(xgi_info_t *info, u32 addr, u8 data) -{ - *(volatile u8*)(info->mmio.vbase + addr) = (data); -} - -static inline u32 ReadRegDWord(xgi_info_t *info, u32 addr) -{ - volatile u32 data; - data = *(volatile u32*)(info->mmio.vbase + addr); - return data; -} - -static inline u16 ReadRegWord(xgi_info_t *info, u32 addr) -{ - volatile u16 data; - data = *(volatile u16*)(info->mmio.vbase + addr); - return data; -} - -static inline u8 ReadRegByte(xgi_info_t *info, u32 addr) -{ - volatile u8 data; - data = *(volatile u8*)(info->mmio.vbase + addr); - return data; -} -#if 0 -extern void OUT3C5B(xgi_info_t *info, u8 index, u8 data); -extern void OUT3X5B(xgi_info_t *info, u8 index, u8 data); -extern void OUT3CFB(xgi_info_t *info, u8 index, u8 data); -extern u8 IN3C5B(xgi_info_t *info, u8 index); -extern u8 IN3X5B(xgi_info_t *info, u8 index); -extern u8 IN3CFB(xgi_info_t *info, u8 index); -extern void OUT3C5W(xgi_info_t *info, u8 index, u8 data); -extern void OUT3X5W(xgi_info_t *info, u8 index, u8 data); -extern void OUT3CFW(xgi_info_t *info, u8 index, u8 data); -extern u8 IN3C5W(xgi_info_t *info, u8 index); -extern u8 IN3X5W(xgi_info_t *info, u8 index); -extern u8 IN3CFW(xgi_info_t *info, u8 index); - -extern void WriteRegDWord(xgi_info_t *info, u32 addr, u32 data); -extern void WriteRegWord(xgi_info_t *info, u32 addr, u16 data); -extern void WriteRegByte(xgi_info_t *info, u32 addr, u8 data); -extern u32 ReadRegDWord(xgi_info_t *info, u32 addr); -extern u16 ReadRegWord(xgi_info_t *info, u32 addr); -extern u8 ReadRegByte(xgi_info_t *info, u32 addr); - -extern void EnableProtect(); -extern void DisableProtect(); -#endif - -#define Out(port, data) OUTB(port, data) -#define bOut(port, data) OUTB(port, data) -#define wOut(port, data) OUTW(port, data) -#define dwOut(port, data) OUTDW(port, data) - -#define Out3x5(index, data) OUT3X5B(info, index, data) -#define bOut3x5(index, data) OUT3X5B(info, index, data) -#define wOut3x5(index, data) OUT3X5W(info, index, data) - -#define Out3c5(index, data) OUT3C5B(info, index, data) -#define bOut3c5(index, data) OUT3C5B(info, index, data) -#define wOut3c5(index, data) OUT3C5W(info, index, data) - -#define Out3cf(index, data) OUT3CFB(info, index, data) -#define bOut3cf(index, data) OUT3CFB(info, index, data) -#define wOut3cf(index, data) OUT3CFW(info, index, data) - -#define In(port) INB(port) -#define bIn(port) INB(port) -#define wIn(port) INW(port) -#define dwIn(port) INDW(port) - -#define In3x5(index) IN3X5B(info, index) -#define bIn3x5(index) IN3X5B(info, index) -#define wIn3x5(index) IN3X5W(info, index) - -#define In3c5(index) IN3C5B(info, index) -#define bIn3c5(index) IN3C5B(info, index) -#define wIn3c5(index) IN3C5W(info, index) - -#define In3cf(index) IN3CFB(info, index) -#define bIn3cf(index) IN3CFB(info, index) -#define wIn3cf(index) IN3CFW(info, index) - -#define dwWriteReg(addr, data) WriteRegDWord(info, addr, data) -#define wWriteReg(addr, data) WriteRegWord(info, addr, data) -#define bWriteReg(addr, data) WriteRegByte(info, addr, data) -#define dwReadReg(addr) ReadRegDWord(info, addr) -#define wReadReg(addr) ReadRegWord(info, addr) -#define bReadReg(addr) ReadRegByte(info, addr) - -static inline void xgi_protect_all(xgi_info_t *info) -{ - OUTB(0x3C4, 0x11); - OUTB(0x3C5, 0x92); -} - -static inline void xgi_unprotect_all(xgi_info_t *info) -{ - OUTB(0x3C4, 0x11); - OUTB(0x3C5, 0x92); -} - -static inline void xgi_enable_mmio(xgi_info_t *info) -{ - u8 protect = 0; - - /* Unprotect registers */ - outb(0x11, 0x3C4); - protect = inb(0x3C5); - outb(0x92, 0x3C5); - - outb(0x3A, 0x3D4); - outb(inb(0x3D5) | 0x20, 0x3D5); - - /* Enable MMIO */ - outb(0x39, 0x3D4); - outb(inb(0x3D5) | 0x01, 0x3D5); - - OUTB(0x3C4, 0x11); - OUTB(0x3C5, protect); -} - -static inline void xgi_disable_mmio(xgi_info_t *info) -{ - u8 protect = 0; - - /* unprotect registers */ - OUTB(0x3C4, 0x11); - protect = INB(0x3C5); - OUTB(0x3C5, 0x92); - - /* Disable MMIO access */ - OUTB(0x3D4, 0x39); - OUTB(0x3D5, INB(0x3D5) & 0xFE); - - /* Protect registers */ - outb(0x11, 0x3C4); - outb(protect, 0x3C5); -} - -static inline void xgi_enable_ge(xgi_info_t *info) -{ - unsigned char bOld3cf2a = 0; - int wait = 0; - - // Enable GE - OUTW(0x3C4, 0x9211); - - // Save and close dynamic gating - bOld3cf2a = bIn3cf(0x2a); - bOut3cf(0x2a, bOld3cf2a & 0xfe); - - // Reset both 3D and 2D engine - bOut3x5(0x36, 0x84); - wait = 10; - while (wait--) - { - bIn(0x36); - } - bOut3x5(0x36, 0x94); - wait = 10; - while (wait--) - { - bIn(0x36); - } - bOut3x5(0x36, 0x84); - wait = 10; - while (wait--) - { - bIn(0x36); - } - // Enable 2D engine only - bOut3x5(0x36, 0x80); - - // Enable 2D+3D engine - bOut3x5(0x36, 0x84); - - // Restore dynamic gating - bOut3cf(0x2a, bOld3cf2a); -} - -static inline void xgi_disable_ge(xgi_info_t *info) -{ - int wait = 0; - - // Reset both 3D and 2D engine - bOut3x5(0x36, 0x84); - - wait = 10; - while (wait--) - { - bIn(0x36); - } - bOut3x5(0x36, 0x94); - - wait = 10; - while (wait--) - { - bIn(0x36); - } - bOut3x5(0x36, 0x84); - - wait = 10; - while (wait--) - { - bIn(0x36); - } - - // Disable 2D engine only - bOut3x5(0x36, 0); -} - -static inline void xgi_enable_dvi_interrupt(xgi_info_t *info) -{ - Out3cf(0x39, In3cf(0x39) & ~0x01); //Set 3cf.39 bit 0 to 0 - Out3cf(0x39, In3cf(0x39) | 0x01); //Set 3cf.39 bit 0 to 1 - Out3cf(0x39, In3cf(0x39) | 0x02); -} -static inline void xgi_disable_dvi_interrupt(xgi_info_t *info) -{ - Out3cf(0x39,In3cf(0x39) & ~0x02); -} - -static inline void xgi_enable_crt1_interrupt(xgi_info_t *info) -{ - Out3cf(0x3d,In3cf(0x3d) | 0x04); - Out3cf(0x3d,In3cf(0x3d) & ~0x04); - Out3cf(0x3d,In3cf(0x3d) | 0x08); -} - -static inline void xgi_disable_crt1_interrupt(xgi_info_t *info) -{ - Out3cf(0x3d,In3cf(0x3d) & ~0x08); -} - -#endif - + +/**************************************************************************** + * 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_ + +#ifndef XGI_MMIO +#define XGI_MMIO 1 +#endif + +#if XGI_MMIO +#define OUTB(port, value) writeb(value, info->mmio.vbase + port) +#define INB(port) readb(info->mmio.vbase + port) +#define OUTW(port, value) writew(value, info->mmio.vbase + port) +#define INW(port) readw(info->mmio.vbase + port) +#define OUTDW(port, value) writel(value, info->mmio.vbase + port) +#define INDW(port) readl(info->mmio.vbase + port) +#else +#define OUTB(port, value) outb(value, port) +#define INB(port) inb(port) +#define OUTW(port, value) outw(value, port) +#define INW(port) inw(port) +#define OUTDW(port, value) outl(value, port) +#define INDW(port) inl(port) +#endif + +/* Hardware access functions */ +static inline void OUT3C5B(xgi_info_t * info, u8 index, u8 data) +{ + OUTB(0x3C4, index); + OUTB(0x3C5, data); +} + +static inline void OUT3X5B(xgi_info_t * info, u8 index, u8 data) +{ + OUTB(0x3D4, index); + OUTB(0x3D5, data); +} + +static inline void OUT3CFB(xgi_info_t * info, u8 index, u8 data) +{ + OUTB(0x3CE, index); + OUTB(0x3CF, data); +} + +static inline u8 IN3C5B(xgi_info_t * info, u8 index) +{ + volatile u8 data = 0; + OUTB(0x3C4, index); + data = INB(0x3C5); + return data; +} + +static inline u8 IN3X5B(xgi_info_t * info, u8 index) +{ + volatile u8 data = 0; + OUTB(0x3D4, index); + data = INB(0x3D5); + return data; +} + +static inline u8 IN3CFB(xgi_info_t * info, u8 index) +{ + volatile u8 data = 0; + OUTB(0x3CE, index); + data = INB(0x3CF); + return data; +} + +static inline void OUT3C5W(xgi_info_t * info, u8 index, u16 data) +{ + OUTB(0x3C4, index); + OUTB(0x3C5, data); +} + +static inline void OUT3X5W(xgi_info_t * info, u8 index, u16 data) +{ + OUTB(0x3D4, index); + OUTB(0x3D5, data); +} + +static inline void OUT3CFW(xgi_info_t * info, u8 index, u8 data) +{ + OUTB(0x3CE, index); + OUTB(0x3CF, data); +} + +static inline u8 IN3C5W(xgi_info_t * info, u8 index) +{ + volatile u8 data = 0; + OUTB(0x3C4, index); + data = INB(0x3C5); + return data; +} + +static inline u8 IN3X5W(xgi_info_t * info, u8 index) +{ + volatile u8 data = 0; + OUTB(0x3D4, index); + data = INB(0x3D5); + return data; +} + +static inline u8 IN3CFW(xgi_info_t * info, u8 index) +{ + volatile u8 data = 0; + OUTB(0x3CE, index); + data = INB(0x3CF); + return data; +} + +static inline u8 readAttr(xgi_info_t * info, u8 index) +{ + INB(0x3DA); /* flip-flop to index */ + OUTB(0x3C0, index); + return INB(0x3C1); +} + +static inline void writeAttr(xgi_info_t * info, u8 index, u8 value) +{ + INB(0x3DA); /* flip-flop to index */ + OUTB(0x3C0, index); + OUTB(0x3C0, value); +} + +/* + * Graphic engine register (2d/3d) acessing interface + */ +static inline void WriteRegDWord(xgi_info_t * info, u32 addr, u32 data) +{ + /* Jong 05/25/2006 */ + XGI_INFO("Jong-WriteRegDWord()-Begin \n"); + XGI_INFO("Jong-WriteRegDWord()-info->mmio.vbase=0x%lx \n", + info->mmio.vbase); + XGI_INFO("Jong-WriteRegDWord()-addr=0x%lx \n", addr); + XGI_INFO("Jong-WriteRegDWord()-data=0x%lx \n", data); + /* return; */ + + *(volatile u32 *)(info->mmio.vbase + addr) = (data); + XGI_INFO("Jong-WriteRegDWord()-End \n"); +} + +static inline void WriteRegWord(xgi_info_t * info, u32 addr, u16 data) +{ + *(volatile u16 *)(info->mmio.vbase + addr) = (data); +} + +static inline void WriteRegByte(xgi_info_t * info, u32 addr, u8 data) +{ + *(volatile u8 *)(info->mmio.vbase + addr) = (data); +} + +static inline u32 ReadRegDWord(xgi_info_t * info, u32 addr) +{ + volatile u32 data; + data = *(volatile u32 *)(info->mmio.vbase + addr); + return data; +} + +static inline u16 ReadRegWord(xgi_info_t * info, u32 addr) +{ + volatile u16 data; + data = *(volatile u16 *)(info->mmio.vbase + addr); + return data; +} + +static inline u8 ReadRegByte(xgi_info_t * info, u32 addr) +{ + volatile u8 data; + data = *(volatile u8 *)(info->mmio.vbase + addr); + return data; +} + +#if 0 +extern void OUT3C5B(xgi_info_t * info, u8 index, u8 data); +extern void OUT3X5B(xgi_info_t * info, u8 index, u8 data); +extern void OUT3CFB(xgi_info_t * info, u8 index, u8 data); +extern u8 IN3C5B(xgi_info_t * info, u8 index); +extern u8 IN3X5B(xgi_info_t * info, u8 index); +extern u8 IN3CFB(xgi_info_t * info, u8 index); +extern void OUT3C5W(xgi_info_t * info, u8 index, u8 data); +extern void OUT3X5W(xgi_info_t * info, u8 index, u8 data); +extern void OUT3CFW(xgi_info_t * info, u8 index, u8 data); +extern u8 IN3C5W(xgi_info_t * info, u8 index); +extern u8 IN3X5W(xgi_info_t * info, u8 index); +extern u8 IN3CFW(xgi_info_t * info, u8 index); + +extern void WriteRegDWord(xgi_info_t * info, u32 addr, u32 data); +extern void WriteRegWord(xgi_info_t * info, u32 addr, u16 data); +extern void WriteRegByte(xgi_info_t * info, u32 addr, u8 data); +extern u32 ReadRegDWord(xgi_info_t * info, u32 addr); +extern u16 ReadRegWord(xgi_info_t * info, u32 addr); +extern u8 ReadRegByte(xgi_info_t * info, u32 addr); + +extern void EnableProtect(); +extern void DisableProtect(); +#endif + +#define Out(port, data) OUTB(port, data) +#define bOut(port, data) OUTB(port, data) +#define wOut(port, data) OUTW(port, data) +#define dwOut(port, data) OUTDW(port, data) + +#define Out3x5(index, data) OUT3X5B(info, index, data) +#define bOut3x5(index, data) OUT3X5B(info, index, data) +#define wOut3x5(index, data) OUT3X5W(info, index, data) + +#define Out3c5(index, data) OUT3C5B(info, index, data) +#define bOut3c5(index, data) OUT3C5B(info, index, data) +#define wOut3c5(index, data) OUT3C5W(info, index, data) + +#define Out3cf(index, data) OUT3CFB(info, index, data) +#define bOut3cf(index, data) OUT3CFB(info, index, data) +#define wOut3cf(index, data) OUT3CFW(info, index, data) + +#define In(port) INB(port) +#define bIn(port) INB(port) +#define wIn(port) INW(port) +#define dwIn(port) INDW(port) + +#define In3x5(index) IN3X5B(info, index) +#define bIn3x5(index) IN3X5B(info, index) +#define wIn3x5(index) IN3X5W(info, index) + +#define In3c5(index) IN3C5B(info, index) +#define bIn3c5(index) IN3C5B(info, index) +#define wIn3c5(index) IN3C5W(info, index) + +#define In3cf(index) IN3CFB(info, index) +#define bIn3cf(index) IN3CFB(info, index) +#define wIn3cf(index) IN3CFW(info, index) + +#define dwWriteReg(addr, data) WriteRegDWord(info, addr, data) +#define wWriteReg(addr, data) WriteRegWord(info, addr, data) +#define bWriteReg(addr, data) WriteRegByte(info, addr, data) +#define dwReadReg(addr) ReadRegDWord(info, addr) +#define wReadReg(addr) ReadRegWord(info, addr) +#define bReadReg(addr) ReadRegByte(info, addr) + +static inline void xgi_protect_all(xgi_info_t * info) +{ + OUTB(0x3C4, 0x11); + OUTB(0x3C5, 0x92); +} + +static inline void xgi_unprotect_all(xgi_info_t * info) +{ + OUTB(0x3C4, 0x11); + OUTB(0x3C5, 0x92); +} + +static inline void xgi_enable_mmio(xgi_info_t * info) +{ + u8 protect = 0; + + /* Unprotect registers */ + outb(0x11, 0x3C4); + protect = inb(0x3C5); + outb(0x92, 0x3C5); + + outb(0x3A, 0x3D4); + outb(inb(0x3D5) | 0x20, 0x3D5); + + /* Enable MMIO */ + outb(0x39, 0x3D4); + outb(inb(0x3D5) | 0x01, 0x3D5); + + OUTB(0x3C4, 0x11); + OUTB(0x3C5, protect); +} + +static inline void xgi_disable_mmio(xgi_info_t * info) +{ + u8 protect = 0; + + /* unprotect registers */ + OUTB(0x3C4, 0x11); + protect = INB(0x3C5); + OUTB(0x3C5, 0x92); + + /* Disable MMIO access */ + OUTB(0x3D4, 0x39); + OUTB(0x3D5, INB(0x3D5) & 0xFE); + + /* Protect registers */ + outb(0x11, 0x3C4); + outb(protect, 0x3C5); +} + +static inline void xgi_enable_ge(xgi_info_t * info) +{ + unsigned char bOld3cf2a = 0; + int wait = 0; + + // Enable GE + OUTW(0x3C4, 0x9211); + + // Save and close dynamic gating + bOld3cf2a = bIn3cf(0x2a); + bOut3cf(0x2a, bOld3cf2a & 0xfe); + + // Reset both 3D and 2D engine + bOut3x5(0x36, 0x84); + wait = 10; + while (wait--) { + bIn(0x36); + } + bOut3x5(0x36, 0x94); + wait = 10; + while (wait--) { + bIn(0x36); + } + bOut3x5(0x36, 0x84); + wait = 10; + while (wait--) { + bIn(0x36); + } + // Enable 2D engine only + bOut3x5(0x36, 0x80); + + // Enable 2D+3D engine + bOut3x5(0x36, 0x84); + + // Restore dynamic gating + bOut3cf(0x2a, bOld3cf2a); +} + +static inline void xgi_disable_ge(xgi_info_t * info) +{ + int wait = 0; + + // Reset both 3D and 2D engine + bOut3x5(0x36, 0x84); + + wait = 10; + while (wait--) { + bIn(0x36); + } + bOut3x5(0x36, 0x94); + + wait = 10; + while (wait--) { + bIn(0x36); + } + bOut3x5(0x36, 0x84); + + wait = 10; + while (wait--) { + bIn(0x36); + } + + // Disable 2D engine only + bOut3x5(0x36, 0); +} + +static inline void xgi_enable_dvi_interrupt(xgi_info_t * info) +{ + Out3cf(0x39, In3cf(0x39) & ~0x01); //Set 3cf.39 bit 0 to 0 + Out3cf(0x39, In3cf(0x39) | 0x01); //Set 3cf.39 bit 0 to 1 + Out3cf(0x39, In3cf(0x39) | 0x02); +} +static inline void xgi_disable_dvi_interrupt(xgi_info_t * info) +{ + Out3cf(0x39, In3cf(0x39) & ~0x02); +} + +static inline void xgi_enable_crt1_interrupt(xgi_info_t * info) +{ + Out3cf(0x3d, In3cf(0x3d) | 0x04); + Out3cf(0x3d, In3cf(0x3d) & ~0x04); + Out3cf(0x3d, In3cf(0x3d) | 0x08); +} + +static inline void xgi_disable_crt1_interrupt(xgi_info_t * info) +{ + Out3cf(0x3d, In3cf(0x3d) & ~0x08); +} + +#endif diff --git a/linux-core/xgi_types.h b/linux-core/xgi_types.h index 24cb8f3c..65ec498b 100644 --- a/linux-core/xgi_types.h +++ b/linux-core/xgi_types.h @@ -1,68 +1,67 @@ - -/**************************************************************************** - * 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_TYPES_H_ -#define _XGI_TYPES_H_ - -/**************************************************************************** - * Typedefs * - ***************************************************************************/ - -typedef unsigned char V8; /* "void": enumerated or multiple fields */ -typedef unsigned short V16; /* "void": enumerated or multiple fields */ -typedef unsigned char U8; /* 0 to 255 */ -typedef unsigned short U16; /* 0 to 65535 */ -typedef signed char S8; /* -128 to 127 */ -typedef signed short S16; /* -32768 to 32767 */ -typedef float F32; /* IEEE Single Precision (S1E8M23) */ -typedef double F64; /* IEEE Double Precision (S1E11M52) */ -typedef unsigned long BOOL; -/* - * mainly for 64-bit linux, where long is 64 bits - * and win9x, where int is 16 bit. - */ -#if defined(vxworks) -typedef unsigned int V32; /* "void": enumerated or multiple fields */ -typedef unsigned int U32; /* 0 to 4294967295 */ -typedef signed int S32; /* -2147483648 to 2147483647 */ -#else -typedef unsigned long V32; /* "void": enumerated or multiple fields */ -typedef unsigned long U32; /* 0 to 4294967295 */ -typedef signed long S32; /* -2147483648 to 2147483647 */ -#endif - -#ifndef TRUE -#define TRUE 1UL -#endif - -#ifndef FALSE -#define FALSE 0UL -#endif - -#endif - + +/**************************************************************************** + * 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_TYPES_H_ +#define _XGI_TYPES_H_ + +/**************************************************************************** + * Typedefs * + ***************************************************************************/ + +typedef unsigned char V8; /* "void": enumerated or multiple fields */ +typedef unsigned short V16; /* "void": enumerated or multiple fields */ +typedef unsigned char U8; /* 0 to 255 */ +typedef unsigned short U16; /* 0 to 65535 */ +typedef signed char S8; /* -128 to 127 */ +typedef signed short S16; /* -32768 to 32767 */ +typedef float F32; /* IEEE Single Precision (S1E8M23) */ +typedef double F64; /* IEEE Double Precision (S1E11M52) */ +typedef unsigned long BOOL; +/* + * mainly for 64-bit linux, where long is 64 bits + * and win9x, where int is 16 bit. + */ +#if defined(vxworks) +typedef unsigned int V32; /* "void": enumerated or multiple fields */ +typedef unsigned int U32; /* 0 to 4294967295 */ +typedef signed int S32; /* -2147483648 to 2147483647 */ +#else +typedef unsigned long V32; /* "void": enumerated or multiple fields */ +typedef unsigned long U32; /* 0 to 4294967295 */ +typedef signed long S32; /* -2147483648 to 2147483647 */ +#endif + +#ifndef TRUE +#define TRUE 1UL +#endif + +#ifndef FALSE +#define FALSE 0UL +#endif + +#endif -- cgit v1.2.3 From ec9e494eb99d409a7e1e97bb6c5f71e9bb5a4486 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:15:22 -0700 Subject: Gut support for pre-2.6 kernels. --- linux-core/xgi_linux.h | 96 +++----------------------------------------------- 1 file changed, 4 insertions(+), 92 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h index 67c1af82..77660ee0 100644 --- a/linux-core/xgi_linux.h +++ b/linux-core/xgi_linux.h @@ -35,20 +35,8 @@ #include #endif -#ifndef KERNEL_VERSION /* pre-2.1.90 didn't have it */ -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -# error "This driver does not support pre-2.4 kernels!" -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -#define KERNEL_2_4 -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -# error "This driver does not support 2.5 kernels!" -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0) -#define KERNEL_2_6 -#else -# error "This driver does not support development kernels!" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +# error "This driver does not support pre-2.6 kernels!" #endif #if defined (CONFIG_SMP) && !defined (__SMP__) @@ -59,10 +47,6 @@ #define MODVERSIONS #endif -#if defined (MODVERSIONS) && !defined (KERNEL_2_6) -#include -#endif - #include /* printk */ #include @@ -88,12 +72,10 @@ #define XGI_SCAN_PROCESS(p) for_each_task(p) #endif -#ifdef KERNEL_2_6 #include /* module_param() */ #include /* kernel_locked */ #include /* flush_tlb(), flush_tlb_all() */ #include /* page table entry lookup */ -#endif #include /* pci_find_class, etc */ #include /* tasklets, interrupt helpers */ @@ -141,13 +123,8 @@ #endif #ifndef MAX_ORDER -#ifdef KERNEL_2_4 -#define MAX_ORDER 10 -#endif -#ifdef KERNEL_2_6 #define MAX_ORDER 11 #endif -#endif #ifndef module_init #define module_init(x) int init_module(void) { return x(); } @@ -171,39 +148,20 @@ typedef void irqreturn_t; pos = pos->next, prefetch(pos->next)) #endif -#ifdef KERNEL_2_4 -#define XGI_PCI_FOR_EACH_DEV(dev) pci_for_each_dev(dev) -#endif -#ifdef KERNEL_2_6 extern struct list_head pci_devices; /* list of all devices */ #define XGI_PCI_FOR_EACH_DEV(dev) \ for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next)) -#endif /* * the following macro causes problems when used in the same module * as module_param(); undef it so we don't accidentally mix the two */ -#if defined (KERNEL_2_6) #undef MODULE_PARM -#endif #ifdef EXPORT_NO_SYMBOLS EXPORT_NO_SYMBOLS; #endif -#if defined (KERNEL_2_4) -#define XGI_IS_SUSER() suser() -#define XGI_PCI_DEVICE_NAME(dev) ((dev)->name) -#define XGI_NUM_CPUS() smp_num_cpus -#define XGI_CLI() __cli() -#define XGI_SAVE_FLAGS(eflags) __save_flags(eflags) -#define XGI_RESTORE_FLAGS(eflags) __restore_flags(eflags) -#define XGI_MAY_SLEEP() (!in_interrupt()) -#define XGI_MODULE_PARAMETER(x) MODULE_PARM(x, "i") -#endif - -#if defined (KERNEL_2_6) #define XGI_IS_SUSER() capable(CAP_SYS_ADMIN) #define XGI_PCI_DEVICE_NAME(dev) ((dev)->pretty_name) #define XGI_NUM_CPUS() num_online_cpus() @@ -212,7 +170,7 @@ EXPORT_NO_SYMBOLS; #define XGI_RESTORE_FLAGS(eflags) local_irq_restore(eflags) #define XGI_MAY_SLEEP() (!in_interrupt() && !in_atomic()) #define XGI_MODULE_PARAMETER(x) module_param(x, int, 0) -#endif + /* Earlier 2.4.x kernels don't have pci_disable_device() */ #ifdef XGI_PCI_DISABLE_DEVICE_PRESENT @@ -255,7 +213,7 @@ EXPORT_NO_SYMBOLS; * model is not sufficient for full acpi support. it may work in some cases, * but not enough for us to officially support this configuration. */ -#if defined(CONFIG_ACPI) && defined(KERNEL_2_6) +#if defined(CONFIG_ACPI) #define XGI_PM_SUPPORT_ACPI #endif @@ -264,7 +222,6 @@ EXPORT_NO_SYMBOLS; #endif #if defined(CONFIG_DEVFS_FS) -#if defined(KERNEL_2_6) typedef void *devfs_handle_t; #define XGI_DEVFS_REGISTER(_name, _minor) \ ({ \ @@ -281,39 +238,10 @@ typedef void *devfs_handle_t; */ #define XGI_DEVFS_REMOVE_CONTROL() devfs_remove("xgi_ctl") #define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi") -#else // defined(KERNEL_2_4) -#define XGI_DEVFS_REGISTER(_name, _minor) \ - ({ \ - devfs_handle_t __handle = devfs_register(NULL, _name, DEVFS_FL_AUTO_DEVNUM, \ - XGI_DEV_MAJOR, _minor, \ - S_IFCHR | S_IRUGO | S_IWUGO, &xgi_fops, NULL); \ - __handle; \ - }) - -#define XGI_DEVFS_REMOVE_DEVICE(i) \ - ({ \ - if (xgi_devfs_handles[i] != NULL) \ - { \ - devfs_unregister(xgi_devfs_handles[i]); \ - } \ - }) -#define XGI_DEVFS_REMOVE_CONTROL() \ - ({ \ - if (xgi_devfs_handles[0] != NULL) \ - { \ - devfs_unregister(xgi_devfs_handles[0]); \ - } \ - }) -#endif /* defined(KERNEL_2_4) */ #endif /* defined(CONFIG_DEVFS_FS) */ -#if defined(CONFIG_DEVFS_FS) && !defined(KERNEL_2_6) -#define XGI_REGISTER_CHRDEV(x...) devfs_register_chrdev(x) -#define XGI_UNREGISTER_CHRDEV(x...) devfs_unregister_chrdev(x) -#else #define XGI_REGISTER_CHRDEV(x...) register_chrdev(x) #define XGI_UNREGISTER_CHRDEV(x...) unregister_chrdev(x) -#endif #if defined(XGI_REMAP_PFN_RANGE_PRESENT) #define XGI_REMAP_PAGE_RANGE(from, offset, x...) \ @@ -519,17 +447,6 @@ static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr) #define XGI_SET_PAGE_ATTRIB_CACHED(page_list) #endif -#ifdef KERNEL_2_4 -#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) -#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) -#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) -#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) - -#define XGILockPage(page) set_bit(PG_locked, &(page)->flags) -#define XGIUnlockPage(page) clear_bit(PG_locked, &(page)->flags) -#endif - -#ifdef KERNEL_2_6 /* add for SUSE 9, Jill*/ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4) #define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) @@ -544,7 +461,6 @@ static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr) #endif #define XGILockPage(page) SetPageLocked(page) #define XGIUnlockPage(page) ClearPageLocked(page) -#endif /* * hide a pointer to struct xgi_info_t in a file-private info @@ -564,11 +480,7 @@ typedef struct { /* for the card devices */ #define XGI_INFO_FROM_FP(filp) (XGI_GET_FP(filp)->info) -#ifdef KERNEL_2_0 -#define INODE_FROM_FP(filp) ((filp)->f_inode) -#else #define INODE_FROM_FP(filp) ((filp)->f_dentry->d_inode) -#endif #define XGI_ATOMIC_SET(data,val) atomic_set(&(data), (val)) #define XGI_ATOMIC_INC(data) atomic_inc(&(data)) -- cgit v1.2.3 From 7a053306a9f8152462fda521e1a8322ac2bdf9fd Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:16:04 -0700 Subject: linux/config.h is deprecated or gone. --- linux-core/xgi_linux.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h index 77660ee0..28349470 100644 --- a/linux-core/xgi_linux.h +++ b/linux-core/xgi_linux.h @@ -29,8 +29,6 @@ #ifndef _XGI_LINUX_H_ #define _XGI_LINUX_H_ -#include - #ifndef LINUX_VERSION_CODE #include #endif -- cgit v1.2.3 From 47bf6239aaefb977cc17e421af273c3278eb127c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:20:15 -0700 Subject: Clean up compile-time kernel feature detection. --- linux-core/xgi_linux.h | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h index 28349470..8cf304c7 100644 --- a/linux-core/xgi_linux.h +++ b/linux-core/xgi_linux.h @@ -37,6 +37,12 @@ # error "This driver does not support pre-2.6 kernels!" #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) +# define XGI_REMAP_PFN_RANGE_PRESENT +#else +# define XGI_REMAP_PAGE_RANGE_5 +#endif + #if defined (CONFIG_SMP) && !defined (__SMP__) #define __SMP__ #endif @@ -170,12 +176,7 @@ EXPORT_NO_SYMBOLS; #define XGI_MODULE_PARAMETER(x) module_param(x, int, 0) -/* Earlier 2.4.x kernels don't have pci_disable_device() */ -#ifdef XGI_PCI_DISABLE_DEVICE_PRESENT #define XGI_PCI_DISABLE_DEVICE(dev) pci_disable_device(dev) -#else -#define XGI_PCI_DISABLE_DEVICE(dev) -#endif /* common defines */ #define GET_MODULE_SYMBOL(mod,sym) (const void *) inter_module_get(sym) @@ -195,15 +196,9 @@ EXPORT_NO_SYMBOLS; #define XGI_PCI_SLOT_NUMBER(dev) PCI_SLOT((dev)->devfn) #ifdef XGI_PCI_GET_CLASS_PRESENT -#define XGI_PCI_DEV_PUT(dev) pci_dev_put(dev) #define XGI_PCI_GET_DEVICE(vendor,device,from) pci_get_device(vendor,device,from) -#define XGI_PCI_GET_SLOT(bus,devfn) pci_get_slot(pci_find_bus(0,bus),devfn) -#define XGI_PCI_GET_CLASS(class,from) pci_get_class(class,from) #else -#define XGI_PCI_DEV_PUT(dev) #define XGI_PCI_GET_DEVICE(vendor,device,from) pci_find_device(vendor,device,from) -#define XGI_PCI_GET_SLOT(bus,devfn) pci_find_slot(bus,devfn) -#define XGI_PCI_GET_CLASS(class,from) pci_find_class(class,from) #endif /* @@ -429,7 +424,6 @@ typedef struct xgi_pte_s { * 2.4.20 is the first kernel to address it properly. The * page_attr API provides the means to solve the problem. */ -#if defined(XGI_CHANGE_PAGE_ATTR_PRESENT) static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(xgi_pte_t * page_ptr) { struct page *page = virt_to_page(__va(page_ptr->phys_addr)); @@ -440,10 +434,6 @@ static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr) struct page *page = virt_to_page(__va(page_ptr->phys_addr)); change_page_attr(page, 1, PAGE_KERNEL); } -#else -#define XGI_SET_PAGE_ATTRIB_UNCACHED(page_list) -#define XGI_SET_PAGE_ATTRIB_CACHED(page_list) -#endif /* add for SUSE 9, Jill*/ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4) -- cgit v1.2.3 From 3a776fa01e61c1dc40a0a1803a80c98bf7e77164 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:26:10 -0700 Subject: Add XGI driver to Makefiles. --- linux-core/Makefile | 9 ++++++++- linux-core/Makefile.kernel | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/Makefile b/linux-core/Makefile index 1758777c..2052459d 100644 --- a/linux-core/Makefile +++ b/linux-core/Makefile @@ -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,8 @@ 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_fb.h xgi_linux.h xgi_misc.h \ + xgi_pcie.h xgi_regs.h xgi_types.h PROGS = dristat drmstat @@ -284,6 +286,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 +323,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 +353,7 @@ $(via-objs): $(VIAHEADERS) $(mach64-objs): $(MACH64HEADERS) $(nv-objs): $(NVHEADERS) $(nouveau-objs): $(NOUVEAUHEADERS) +$(xgi-objs): $(XGIHEADERS) endif diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 6f5b021b..d9865f5a 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -35,6 +35,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 @@ -59,3 +60,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 -- cgit v1.2.3 From 3547fbda63925217a5be24de5d5abec3b53d3fe1 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:29:28 -0700 Subject: Revert over-zealous change from previous commit. --- linux-core/xgi_linux.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux-core') diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h index 8cf304c7..465feb3c 100644 --- a/linux-core/xgi_linux.h +++ b/linux-core/xgi_linux.h @@ -195,9 +195,12 @@ EXPORT_NO_SYMBOLS; #define XGI_PCI_BUS_NUMBER(dev) (dev)->bus->number #define XGI_PCI_SLOT_NUMBER(dev) PCI_SLOT((dev)->devfn) +#define XGI_PCI_GET_CLASS_PRESENT #ifdef XGI_PCI_GET_CLASS_PRESENT +#define XGI_PCI_DEV_PUT(dev) pci_dev_put(dev) #define XGI_PCI_GET_DEVICE(vendor,device,from) pci_get_device(vendor,device,from) #else +#define XGI_PCI_DEV_PUT(dev) #define XGI_PCI_GET_DEVICE(vendor,device,from) pci_find_device(vendor,device,from) #endif -- cgit v1.2.3 From b9ef1467fed9e96c5e7bd453d01511f8ce98583c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:39:01 -0700 Subject: Clean up mixed declarations and code. --- linux-core/xgi_cmdlist.c | 3 ++- linux-core/xgi_misc.c | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index e00ea228..99be2145 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -196,9 +196,10 @@ void xgi_submit_cmdlist(xgi_info_t * info, xgi_cmd_info_t * pCmdInfo) /* Jong 06/13/2006; remove marked for system hang test */ /* xgi_waitfor_pci_idle(info); */ } else { + U32 *lastBatchVirtAddr; + XGI_INFO ("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 \n"); - U32 *lastBatchVirtAddr; /* Jong 05/25/2006 */ /* return; */ diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 61e40594..06cf0160 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -200,13 +200,15 @@ BOOL xgi_ge_irq_handler(xgi_info_t * info) STALL_INTERRUPT_RESET_THRESHOLD) { continoue_int_count = 0; } else if (continoue_int_count >= 3) { + int time_out; + continoue_int_count = 0; // GE Hung up, need reset. XGI_INFO("Reset GE!\n"); *(mmio_vbase + 0xb057) = 8; - int time_out = 0xffff; + time_out = 0xffff; while (0 != (ge_3d_status[0x00] & 0xf0000000)) { @@ -214,6 +216,11 @@ BOOL xgi_ge_irq_handler(xgi_info_t * info) ((--time_out) & 0xfff)) ; if (0 == time_out) { + U8 old_3ce; + U8 old_3cf; + U8 old_index; + U8 old_36; + XGI_INFO ("Can not reset back 0x%lx!\n", ge_3d_status @@ -222,24 +229,24 @@ BOOL xgi_ge_irq_handler(xgi_info_t * info) 0xb057) = 0; // Have to use 3x5.36 to reset. // Save and close dynamic gating - U8 old_3ce = + old_3ce = *(mmio_vbase + 0x3ce); *(mmio_vbase + 0x3ce) = 0x2a; - U8 old_3cf = + old_3cf = *(mmio_vbase + 0x3cf); *(mmio_vbase + 0x3cf) = old_3cf & 0xfe; // Reset GE - U8 old_index = + old_index = *(mmio_vbase + 0x3d4); *(mmio_vbase + 0x3d4) = 0x36; - U8 old_36 = + old_36 = *(mmio_vbase + 0x3d5); *(mmio_vbase + -- cgit v1.2.3 From 8cee7dca95bc2114eb90640cf83ac87c29243683 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 26 Jun 2007 13:46:36 -0700 Subject: Clean up warnings about unused variables and functions. --- linux-core/xgi_drv.c | 11 ----------- linux-core/xgi_misc.c | 34 ++-------------------------------- linux-core/xgi_pcie.c | 2 ++ 3 files changed, 4 insertions(+), 43 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 0c37d00e..75204283 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -153,11 +153,6 @@ static inline void xgi_check_pci_config(xgi_info_t * info, int line) pci_write_config_word(info->dev, PCI_COMMAND, cmd); } -static int xgi_post_vbios(xgi_ioctl_post_vbios_t * info) -{ - return 1; -} - /* * struct pci_device_id { * unsigned int vendor, device; // Vendor and device ID or PCI_ANY_ID @@ -1484,14 +1479,8 @@ static int __init xgi_init_module(void) void __exit xgi_exit_module(void) { int i; - xgi_info_t *info, *max_devices; #ifdef CONFIG_DEVFS_FS - /* - XGI_DEVFS_REMOVE_CONTROL(); - for (i = 0; i < XGI_MAX_DEVICES; i++) - XGI_DEVFS_REMOVE_DEVICE(i); - */ XGI_DEVFS_REMOVE_DEVICE(xgi_num_devices); #endif diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 06cf0160..8d0e81b6 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -131,7 +131,7 @@ BOOL xgi_ge_irq_handler(xgi_info_t * info) BOOL is_wrong_signal = FALSE; static U32 last_int_tick_low, last_int_tick_high; - static U32 new_int_tick_low, new_int_tick_high; + static U32 new_int_tick_low; static U32 continoue_int_count = 0; // OE II is busy. while (old_ge_status & 0x001c0000) { @@ -290,9 +290,6 @@ BOOL xgi_ge_irq_handler(xgi_info_t * info) BOOL xgi_crt_irq_handler(xgi_info_t * info) { BOOL ret = FALSE; - U8 *mmio_vbase = info->mmio.vbase; - U32 device_status = 0; - U32 hw_status = 0; U8 save_3ce = bReadReg(0x3ce); if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened @@ -303,15 +300,6 @@ BOOL xgi_crt_irq_handler(xgi_info_t * info) // What happened? op3cf_37 = bIn3cf(0x37); -#if 0 - if (op3cf_37 & 0x04) - device_status |= GDEVST_CONNECT; - else - device_status &= ~GDEVST_CONNECT; - - device_status |= GDEVST_DEVICE_CHANGED; - hw_status |= HWST_DEVICE_CHANGED; -#endif // Clear CRT interrupt op3cf_3d = bIn3cf(0x3d); bOut3cf(0x3d, (op3cf_3d | 0x04)); @@ -326,9 +314,6 @@ BOOL xgi_crt_irq_handler(xgi_info_t * info) BOOL xgi_dvi_irq_handler(xgi_info_t * info) { BOOL ret = FALSE; - U8 *mmio_vbase = info->mmio.vbase; - U32 device_status = 0; - U32 hw_status = 0; U8 save_3ce = bReadReg(0x3ce); if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened @@ -340,28 +325,13 @@ BOOL xgi_dvi_irq_handler(xgi_info_t * info) // What happened? op3cf_37 = bIn3cf(0x37); -#if 0 - //Also update our internal flag - if (op3cf_37 & 0x10) // Second Monitor plugged In - { - device_status |= GDEVST_CONNECT; - //Because currenly we cannot determine if DVI digital - //or DVI analog is connected according to DVI interrupt - //We should still call BIOS to check it when utility ask us - device_status &= ~GDEVST_CHECKED; - } else { - device_status &= ~GDEVST_CONNECT; - } -#endif + //Notify BIOS that DVI plug/unplug happened op3x5_5a = bIn3x5(0x5a); bOut3x5(0x5a, op3x5_5a & 0xf7); bWriteReg(0x3d4, save_3x4); - //device_status |= GDEVST_DEVICE_CHANGED; - //hw_status |= HWST_DEVICE_CHANGED; - // Clear DVI interrupt op3cf_39 = bIn3cf(0x39); bOut3c5(0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0 diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 9457770a..8b024e4a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -350,8 +350,10 @@ void xgi_pcie_heap_check(void) struct list_head *useList, *temp; xgi_pcie_block_t *block; unsigned int ownerIndex; +#ifdef XGI_DEBUG char *ownerStr[6] = { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; +#endif if (xgi_pcie_heap) { useList = &xgi_pcie_heap->used_list; -- cgit v1.2.3 From 11ffe4632a097e3d579d084634eeccc63348249b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 28 Jun 2007 22:20:13 -0700 Subject: Convert comment header of xgi_find_pcie_virt to kernel doc format. --- linux-core/xgi_pcie.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 8b024e4a..b29b083d 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -938,12 +938,13 @@ void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) return NULL; } -/* - address -- GE HW address - return -- CPU virtual address - - assume the CPU VAddr is continuous in not the same block -*/ +/** + * 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(xgi_info_t * info, unsigned long address) { struct list_head *used_list; -- cgit v1.2.3 From 9c85fb866dc7954092b7ffd0ca9f76eb5354ace8 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 28 Jun 2007 22:26:39 -0700 Subject: Clean up debug log messages in xgi_find_pcie_block. --- linux-core/xgi_pcie.c | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b29b083d..b449a5fd 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -953,22 +953,18 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) unsigned long loc_in_pagetable; void *ret; - XGI_INFO("Jong_05292006-xgi_find_pcie_virt-Begin\n"); - used_list = xgi_pcie_heap->used_list.next; - XGI_INFO("Jong_05292006-used_list=%ul\n", used_list); - offset_in_page = address & (PAGE_SIZE - 1); - XGI_INFO - ("Jong_05292006-address=0x%px, PAGE_SIZE-1=%ul, offset_in_page=%ul\n", - address, PAGE_SIZE - 1, offset_in_page); + + XGI_INFO("begin (used_list = 0x%p, address = 0x%lx, " + "PAGE_SIZE - 1 = %lu, offset_in_page = %lu)\n", + used_list, address, PAGE_SIZE - 1, offset_in_page); while (used_list != &xgi_pcie_heap->used_list) { block = list_entry(used_list, struct xgi_pcie_block_s, list); - XGI_INFO("Jong_05292006-block=0x%px\n", block); - XGI_INFO("Jong_05292006-block->hw_addr=0x%px\n", - block->hw_addr); - XGI_INFO("Jong_05292006- block->size=%ul\n", block->size); + + XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", + block, block->hw_addr, block->size); if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) { @@ -978,21 +974,15 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) (void *)(block->page_table[loc_in_pagetable]. virt_addr + offset_in_page); - XGI_INFO("Jong_05292006-PAGE_SHIFT=%d\n", PAGE_SHIFT); - XGI_INFO("Jong_05292006-loc_in_pagetable=0x%px\n", - loc_in_pagetable); - XGI_INFO - ("Jong_05292006-block->page_table[loc_in_pagetable].virt_addr=0x%px\n", - block->page_table[loc_in_pagetable].virt_addr); - XGI_INFO("Jong_05292006-offset_in_page=%d\n", - offset_in_page); - XGI_INFO("Jong_05292006-return(virt_addr)=0x%px\n", - ret); + XGI_INFO("PAGE_SHIFT = %d\n", PAGE_SHIFT); + XGI_INFO("block->page_table[0x%lx].virt_addr = 0x%lx\n", + loc_in_pagetable, + block->page_table[loc_in_pagetable].virt_addr); + XGI_INFO("return 0x%p\n", ret); return ret; } else { - XGI_INFO - ("Jong_05292006-used_list = used_list->next;\n"); + XGI_INFO("used_list = used_list->next;\n"); used_list = used_list->next; } } -- cgit v1.2.3 From 8fa24c53f5851a2d3ad2da31ee56a4fd5abbd543 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 28 Jun 2007 22:32:11 -0700 Subject: Minor clean up of variable declarations in xgi_find_pcie_virt. --- linux-core/xgi_pcie.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b449a5fd..d9da30e8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -947,30 +947,25 @@ void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) */ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) { - struct list_head *used_list; - xgi_pcie_block_t *block; - unsigned long offset_in_page; - unsigned long loc_in_pagetable; - void *ret; - - used_list = xgi_pcie_heap->used_list.next; - offset_in_page = address & (PAGE_SIZE - 1); + struct list_head *used_list = xgi_pcie_heap->used_list.next; + const unsigned long offset_in_page = address & (PAGE_SIZE - 1); XGI_INFO("begin (used_list = 0x%p, address = 0x%lx, " "PAGE_SIZE - 1 = %lu, offset_in_page = %lu)\n", used_list, address, PAGE_SIZE - 1, offset_in_page); while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block_s, list); + xgi_pcie_block_t *block = + list_entry(used_list, struct xgi_pcie_block_s, list); XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", block, block->hw_addr, block->size); if ((address >= block->hw_addr) && (address < (block->hw_addr + block->size))) { - loc_in_pagetable = + const unsigned long loc_in_pagetable = (address - block->hw_addr) >> PAGE_SHIFT; - ret = + void *const ret = (void *)(block->page_table[loc_in_pagetable]. virt_addr + offset_in_page); -- cgit v1.2.3 From 475c1e67bacabb89c568c7482991451d223c53ae Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 28 Jun 2007 23:40:36 -0700 Subject: Remove unused type 'struct xgi_pcie_list_s' / xgi_pcie_list_t. --- linux-core/xgi_pcie.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.h b/linux-core/xgi_pcie.h index 32c2b584..6e8e45b9 100644 --- a/linux-core/xgi_pcie.h +++ b/linux-core/xgi_pcie.h @@ -58,11 +58,6 @@ typedef struct xgi_pcie_block_s { unsigned long processID; } xgi_pcie_block_t; -typedef struct xgi_pcie_list_s { - xgi_pcie_block_t *head; - xgi_pcie_block_t *tail; -} xgi_pcie_list_t; - typedef struct xgi_pcie_heap_s { struct list_head free_list; struct list_head used_list; -- cgit v1.2.3 From 33b8476dfb0f9b5045103c3a9781ba82bcae4a9d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 09:30:02 -0700 Subject: Fix return type of xgi_find_pcie_block. This function used to return 'void *', which was then cast to 'xgi_pcie_block_t *' at the only caller. I changed the return type to 'struct xgi_pcie_block_s *' and removed the explicit cast. --- linux-core/xgi_drv.c | 5 +---- linux-core/xgi_drv.h | 3 ++- linux-core/xgi_pcie.c | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 75204283..a01b3c22 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -730,10 +730,7 @@ int xgi_kern_mmap(struct file *filp, struct vm_area_struct *vma) (info, XGI_VMA_OFFSET(vma), vma->vm_end - vma->vm_start)) { xgi_down(info->pcie_sem); - block = - (xgi_pcie_block_t *) xgi_find_pcie_block(info, - XGI_VMA_OFFSET - (vma)); + block = xgi_find_pcie_block(info, XGI_VMA_OFFSET(vma)); if (block == NULL) { XGI_ERROR("couldn't find pre-allocated PCIE memory!\n"); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 429719a7..5d76b632 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -353,7 +353,8 @@ extern void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, enum PcieOwner owner, xgi_mem_alloc_t * alloc); extern void xgi_pcie_free(xgi_info_t * info, unsigned long offset); extern void xgi_pcie_heap_check(void); -extern void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address); +extern struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, + unsigned long address); extern void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address); extern void xgi_read_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index d9da30e8..1a4d8e12 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -906,7 +906,8 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) * given a bus address, fid the pcie mem block * uses the bus address as the key. */ -void *xgi_find_pcie_block(xgi_info_t * info, unsigned long address) +struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, + unsigned long address) { struct list_head *used_list; xgi_pcie_block_t *block; -- cgit v1.2.3 From 88328d4ef007c781874aafedfef59aae0d21a37c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 15:27:38 -0700 Subject: Eliminate structure typedefs Documentation/CodingStyle says that 'typedef struct foo foo_t' is evil. I tend to agree. Elminate all uses of such construct. --- linux-core/xgi_cmdlist.c | 26 +++++----- linux-core/xgi_cmdlist.h | 12 ++--- linux-core/xgi_drv.c | 108 +++++++++++++++++++-------------------- linux-core/xgi_drv.h | 130 +++++++++++++++++++++++------------------------ linux-core/xgi_fb.c | 110 +++++++++++++++++++-------------------- linux-core/xgi_fb.h | 31 ++--------- linux-core/xgi_linux.h | 20 +++----- linux-core/xgi_misc.c | 32 ++++++------ linux-core/xgi_misc.h | 26 +++++----- linux-core/xgi_pcie.c | 116 +++++++++++++++++++++--------------------- linux-core/xgi_pcie.h | 18 +++---- linux-core/xgi_regs.h | 98 +++++++++++++++++------------------ 12 files changed, 350 insertions(+), 377 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 99be2145..2cdf714f 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -47,17 +47,17 @@ U32 s_flush2D[AGPCMDLIST_FLUSH_CMD_LEN] = { FLUSH_2D }; -xgi_cmdring_info_t s_cmdring; +struct xgi_cmdring_info s_cmdring; -static void addFlush2D(xgi_info_t * info); -static U32 getCurBatchBeginPort(xgi_cmd_info_t * pCmdInfo); -static void triggerHWCommandList(xgi_info_t * info, U32 triggerCounter); +static void addFlush2D(struct xgi_info * info); +static U32 getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo); +static void triggerHWCommandList(struct xgi_info * info, U32 triggerCounter); static void xgi_cmdlist_reset(void); -int xgi_cmdlist_initialize(xgi_info_t * info, U32 size) +int xgi_cmdlist_initialize(struct xgi_info * info, U32 size) { - //xgi_mem_req_t mem_req; - xgi_mem_alloc_t mem_alloc; + //struct xgi_mem_req mem_req; + struct xgi_mem_alloc mem_alloc; //mem_req.size = size; @@ -76,7 +76,7 @@ int xgi_cmdlist_initialize(xgi_info_t * info, U32 size) return 1; } -void xgi_submit_cmdlist(xgi_info_t * info, xgi_cmd_info_t * pCmdInfo) +void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) { U32 beginPort; /** XGI_INFO("Jong-xgi_submit_cmdlist-Begin \n"); **/ @@ -238,7 +238,7 @@ void xgi_submit_cmdlist(xgi_info_t * info, xgi_cmd_info_t * pCmdInfo) 2 - fb 3 - logout */ -void xgi_state_change(xgi_info_t * info, xgi_state_info_t * pStateInfo) +void xgi_state_change(struct xgi_info * info, struct xgi_state_info * pStateInfo) { #define STATE_CONSOLE 0 #define STATE_GRAPHIC 1 @@ -273,7 +273,7 @@ void xgi_cmdlist_reset(void) s_cmdring._cmdRingOffset = 0; } -void xgi_cmdlist_cleanup(xgi_info_t * info) +void xgi_cmdlist_cleanup(struct xgi_info * info) { if (s_cmdring._cmdRingBuffer != 0) { xgi_pcie_free(info, s_cmdring._cmdRingBusAddr); @@ -283,7 +283,7 @@ void xgi_cmdlist_cleanup(xgi_info_t * info) } } -static void triggerHWCommandList(xgi_info_t * info, U32 triggerCounter) +static void triggerHWCommandList(struct xgi_info * info, U32 triggerCounter) { static U32 s_triggerID = 1; @@ -295,7 +295,7 @@ static void triggerHWCommandList(xgi_info_t * info, U32 triggerCounter) } } -static U32 getCurBatchBeginPort(xgi_cmd_info_t * pCmdInfo) +static U32 getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo) { // Convert the batch type to begin port ID switch (pCmdInfo->_firstBeginType) { @@ -313,7 +313,7 @@ static U32 getCurBatchBeginPort(xgi_cmd_info_t * pCmdInfo) } } -static void addFlush2D(xgi_info_t * info) +static void addFlush2D(struct xgi_info * info) { U32 *flushBatchVirtAddr; U32 flushBatchHWAddr; diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 5fe1de71..b11511ff 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -57,20 +57,20 @@ typedef enum { AGPCMDLIST_DUMY_END_BATCH_LEN = AGPCMDLIST_BEGIN_SIZE } CMD_SIZE; -typedef struct xgi_cmdring_info_s { +struct xgi_cmdring_info { U32 _cmdRingSize; U32 _cmdRingBuffer; U32 _cmdRingBusAddr; U32 _lastBatchStartAddr; U32 _cmdRingOffset; -} xgi_cmdring_info_t; +}; -extern int xgi_cmdlist_initialize(xgi_info_t * info, U32 size); +extern int xgi_cmdlist_initialize(struct xgi_info * info, U32 size); -extern void xgi_submit_cmdlist(xgi_info_t * info, xgi_cmd_info_t * pCmdInfo); +extern void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo); -extern void xgi_state_change(xgi_info_t * info, xgi_state_info_t * pStateInfo); +extern void xgi_state_change(struct xgi_info * info, struct xgi_state_info * pStateInfo); -extern void xgi_cmdlist_cleanup(xgi_info_t * info); +extern void xgi_cmdlist_cleanup(struct xgi_info * info); #endif /* _XGI_CMDLIST_H_ */ diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index a01b3c22..44b003a8 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -53,14 +53,14 @@ int xgi_major = XGI_DEV_MAJOR; /* xgi reserved major device number. */ static int xgi_num_devices = 0; -xgi_info_t xgi_devices[XGI_MAX_DEVICES]; +struct xgi_info xgi_devices[XGI_MAX_DEVICES]; #if defined(XGI_PM_SUPPORT_APM) static struct pm_dev *apm_xgi_dev[XGI_MAX_DEVICES] = { 0 }; #endif /* add one for the control device */ -xgi_info_t xgi_ctl_device; +struct xgi_info xgi_ctl_device; wait_queue_head_t xgi_ctl_waitqueue; #ifdef CONFIG_PROC_FS @@ -74,7 +74,7 @@ devfs_handle_t xgi_devfs_handles[XGI_MAX_DEVICES]; struct list_head xgi_mempid_list; /* xgi_ functions.. do not take a state device parameter */ -static int xgi_post_vbios(xgi_ioctl_post_vbios_t * info); +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); @@ -110,7 +110,7 @@ unsigned int xgi_kern_ctl_poll(struct file *, poll_table *); void xgi_kern_isr_bh(unsigned long); irqreturn_t xgi_kern_isr(int, void *, struct pt_regs *); -static void xgi_lock_init(xgi_info_t * info); +static void xgi_lock_init(struct xgi_info * info); #if defined(XGI_PM_SUPPORT_ACPI) int xgi_kern_acpi_standby(struct pci_dev *, u32); @@ -128,7 +128,7 @@ int xgi_kern_acpi_resume(struct pci_dev *); #define XGI_CHECK_PCI_CONFIG(xgi) \ xgi_check_pci_config(xgi, __LINE__) -static inline void xgi_check_pci_config(xgi_info_t * info, int line) +static inline void xgi_check_pci_config(struct xgi_info * info, int line) { unsigned short cmd, flag = 0; @@ -208,7 +208,7 @@ static struct pci_driver xgi_pci_driver = { */ int xgi_kern_probe(struct pci_dev *dev, const struct pci_device_id *id_table) { - xgi_info_t *info; + struct xgi_info *info; if ((dev->vendor != PCI_VENDOR_ID_XGI) || (dev->class != (PCI_CLASS_DISPLAY_VGA << 8))) { @@ -361,8 +361,8 @@ void xgi_kern_vma_open(struct vm_area_struct *vma) vma->vm_start, vma->vm_end, XGI_VMA_OFFSET(vma)); if (XGI_VMA_PRIVATE(vma)) { - xgi_pcie_block_t *block = - (xgi_pcie_block_t *) XGI_VMA_PRIVATE(vma); + struct xgi_pcie_block *block = + (struct xgi_pcie_block *) XGI_VMA_PRIVATE(vma); XGI_ATOMIC_INC(block->use_count); } } @@ -373,8 +373,8 @@ void xgi_kern_vma_release(struct vm_area_struct *vma) vma->vm_start, vma->vm_end, XGI_VMA_OFFSET(vma)); if (XGI_VMA_PRIVATE(vma)) { - xgi_pcie_block_t *block = - (xgi_pcie_block_t *) XGI_VMA_PRIVATE(vma); + struct xgi_pcie_block *block = + (struct xgi_pcie_block *) XGI_VMA_PRIVATE(vma); XGI_ATOMIC_DEC(block->use_count); /* @@ -393,7 +393,7 @@ void xgi_kern_vma_release(struct vm_area_struct *vma) struct page *xgi_kern_vma_nopage(struct vm_area_struct *vma, unsigned long address, int *type) { - xgi_pcie_block_t *block = (xgi_pcie_block_t *) XGI_VMA_PRIVATE(vma); + 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; @@ -436,7 +436,7 @@ struct page *xgi_kern_vma_nopage(struct vm_area_struct *vma, struct page *xgi_kern_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access) { - xgi_pcie_block_t *block = (xgi_pcie_block_t *) XGI_VMA_PRIVATE(vma); + 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; @@ -496,15 +496,15 @@ static struct file_operations xgi_fops = { .release = xgi_kern_release, }; -static xgi_file_private_t *xgi_alloc_file_private(void) +static struct xgi_file_private *xgi_alloc_file_private(void) { - xgi_file_private_t *fp; + struct xgi_file_private *fp; - XGI_KMALLOC(fp, sizeof(xgi_file_private_t)); + XGI_KMALLOC(fp, sizeof(struct xgi_file_private)); if (!fp) return NULL; - memset(fp, 0, sizeof(xgi_file_private_t)); + memset(fp, 0, sizeof(struct xgi_file_private)); /* initialize this file's event queue */ init_waitqueue_head(&fp->wait_queue); @@ -514,17 +514,17 @@ static xgi_file_private_t *xgi_alloc_file_private(void) return fp; } -static void xgi_free_file_private(xgi_file_private_t * fp) +static void xgi_free_file_private(struct xgi_file_private * fp) { if (fp == NULL) return; - XGI_KFREE(fp, sizeof(xgi_file_private_t)); + XGI_KFREE(fp, sizeof(struct xgi_file_private)); } int xgi_kern_open(struct inode *inode, struct file *filp) { - xgi_info_t *info = NULL; + struct xgi_info *info = NULL; int dev_num; int result = 0, status; @@ -621,7 +621,7 @@ int xgi_kern_open(struct inode *inode, struct file *filp) int xgi_kern_release(struct inode *inode, struct file *filp) { - xgi_info_t *info = XGI_INFO_FROM_FP(filp); + struct xgi_info *info = XGI_INFO_FROM_FP(filp); XGI_CHECK_PCI_CONFIG(info); @@ -674,8 +674,8 @@ int xgi_kern_release(struct inode *inode, struct file *filp) int xgi_kern_mmap(struct file *filp, struct vm_area_struct *vma) { //struct inode *inode = INODE_FROM_FP(filp); - xgi_info_t *info = XGI_INFO_FROM_FP(filp); - xgi_pcie_block_t *block; + struct xgi_info *info = XGI_INFO_FROM_FP(filp); + struct xgi_pcie_block *block; int pages = 0; unsigned long prot; @@ -792,8 +792,8 @@ int xgi_kern_mmap(struct file *filp, struct vm_area_struct *vma) unsigned int xgi_kern_poll(struct file *filp, struct poll_table_struct *wait) { - xgi_file_private_t *fp; - xgi_info_t *info; + struct xgi_file_private *fp; + struct xgi_info *info; unsigned int mask = 0; unsigned long eflags; @@ -828,8 +828,8 @@ unsigned int xgi_kern_poll(struct file *filp, struct poll_table_struct *wait) int xgi_kern_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - xgi_info_t *info; - xgi_mem_alloc_t *alloc = NULL; + struct xgi_info *info; + struct xgi_mem_alloc *alloc = NULL; int status = 0; void *arg_copy; @@ -880,21 +880,21 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, } else XGI_INFO("Jong-copy_from_user-OK! \n"); - alloc = (xgi_mem_alloc_t *) arg_copy; + 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_DEVICE_INFO: XGI_INFO("Jong-xgi_ioctl_get_device_info \n"); - xgi_get_device_info(info, (struct xgi_chip_info_s *)arg_copy); + xgi_get_device_info(info, (struct xgi_chip_info *)arg_copy); break; 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, (struct xgi_mem_req_s *)arg_copy, alloc); + xgi_fb_alloc(info, (struct xgi_mem_req *)arg_copy, alloc); break; case XGI_ESC_FB_FREE: XGI_INFO("Jong-xgi_ioctl_fb_free \n"); @@ -906,8 +906,8 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, break; case XGI_ESC_PCIE_ALLOC: XGI_INFO("Jong-xgi_ioctl_pcie_alloc \n"); - xgi_pcie_alloc(info, ((xgi_mem_req_t *) arg_copy)->size, - ((xgi_mem_req_t *) arg_copy)->owner, alloc); + xgi_pcie_alloc(info, ((struct xgi_mem_req *) arg_copy)->size, + ((struct xgi_mem_req *) arg_copy)->owner, alloc); break; case XGI_ESC_PCIE_FREE: XGI_INFO("Jong-xgi_ioctl_pcie_free: bus_addr = 0x%lx \n", @@ -920,15 +920,15 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, break; case XGI_ESC_GET_SCREEN_INFO: XGI_INFO("Jong-xgi_get_screen_info \n"); - xgi_get_screen_info(info, (struct xgi_screen_info_s *)arg_copy); + xgi_get_screen_info(info, (struct xgi_screen_info *)arg_copy); break; case XGI_ESC_PUT_SCREEN_INFO: XGI_INFO("Jong-xgi_put_screen_info \n"); - xgi_put_screen_info(info, (struct xgi_screen_info_s *)arg_copy); + xgi_put_screen_info(info, (struct xgi_screen_info *)arg_copy); break; case XGI_ESC_MMIO_INFO: XGI_INFO("Jong-xgi_ioctl_get_mmio_info \n"); - xgi_get_mmio_info(info, (struct xgi_mmio_info_s *)arg_copy); + xgi_get_mmio_info(info, (struct xgi_mmio_info *)arg_copy); break; case XGI_ESC_GE_RESET: XGI_INFO("Jong-xgi_ioctl_ge_reset \n"); @@ -936,7 +936,7 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, break; case XGI_ESC_SAREA_INFO: XGI_INFO("Jong-xgi_ioctl_sarea_info \n"); - xgi_sarea_info(info, (struct xgi_sarea_info_s *)arg_copy); + xgi_sarea_info(info, (struct xgi_sarea_info *)arg_copy); break; case XGI_ESC_DUMP_REGISTER: XGI_INFO("Jong-xgi_ioctl_dump_register \n"); @@ -945,12 +945,12 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, case XGI_ESC_DEBUG_INFO: XGI_INFO("Jong-xgi_ioctl_restore_registers \n"); xgi_restore_registers(info); - //xgi_write_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); - //xgi_read_pcie_mem(info, (struct xgi_mem_req_s *) arg_copy); + //xgi_write_pcie_mem(info, (struct xgi_mem_req *) arg_copy); + //xgi_read_pcie_mem(info, (struct xgi_mem_req *) arg_copy); break; case XGI_ESC_SUBMIT_CMDLIST: XGI_INFO("Jong-xgi_ioctl_submit_cmdlist \n"); - xgi_submit_cmdlist(info, (xgi_cmd_info_t *) arg_copy); + xgi_submit_cmdlist(info, (struct xgi_cmd_info *) arg_copy); break; case XGI_ESC_TEST_RWINKERNEL: XGI_INFO("Jong-xgi_test_rwinkernel \n"); @@ -958,11 +958,11 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, break; case XGI_ESC_STATE_CHANGE: XGI_INFO("Jong-xgi_state_change \n"); - xgi_state_change(info, (xgi_state_info_t *) arg_copy); + xgi_state_change(info, (struct xgi_state_info *) arg_copy); break; case XGI_ESC_CPUID: XGI_INFO("Jong-XGI_ESC_CPUID \n"); - xgi_get_cpu_id((struct cpu_info_s *)arg_copy); + xgi_get_cpu_id((struct cpu_info *)arg_copy); break; default: XGI_INFO("Jong-xgi_ioctl_default \n"); @@ -985,7 +985,7 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, */ int xgi_kern_ctl_open(struct inode *inode, struct file *filp) { - xgi_info_t *info = &xgi_ctl_device; + struct xgi_info *info = &xgi_ctl_device; int rc = 0; @@ -1011,7 +1011,7 @@ int xgi_kern_ctl_open(struct inode *inode, struct file *filp) int xgi_kern_ctl_close(struct inode *inode, struct file *filp) { - xgi_info_t *info = XGI_INFO_FROM_FP(filp); + struct xgi_info *info = XGI_INFO_FROM_FP(filp); XGI_INFO("Jong-xgi_kern_ctl_close\n"); @@ -1031,7 +1031,7 @@ int xgi_kern_ctl_close(struct inode *inode, struct file *filp) unsigned int xgi_kern_ctl_poll(struct file *filp, poll_table * wait) { - //xgi_info_t *info = XGI_INFO_FROM_FP(filp);; + //struct xgi_info *info = XGI_INFO_FROM_FP(filp);; unsigned int ret = 0; if (!(filp->f_flags & O_NONBLOCK)) { @@ -1073,7 +1073,7 @@ static u8 xgi_find_pcie_capability(struct pci_dev *dev) return 0; } -static struct pci_dev *xgi_get_pci_device(xgi_info_t * info) +static struct pci_dev *xgi_get_pci_device(struct xgi_info * info) { struct pci_dev *dev; @@ -1095,8 +1095,8 @@ int xgi_kern_read_card_info(char *page, char **start, off_t off, char *type; int len = 0; - xgi_info_t *info; - info = (xgi_info_t *) data; + struct xgi_info *info; + info = (struct xgi_info *) data; dev = xgi_get_pci_device(info); if (!dev) @@ -1143,8 +1143,8 @@ static void xgi_proc_create(void) struct proc_dir_entry *entry; struct proc_dir_entry *proc_xgi_pcie, *proc_xgi_cards; - xgi_info_t *info; - xgi_info_t *xgi_max_devices; + struct xgi_info *info; + struct xgi_info *xgi_max_devices; /* world readable directory */ int flags = S_IFDIR | S_IRUGO | S_IXUGO; @@ -1268,7 +1268,7 @@ static void xgi_proc_remove(void) */ irqreturn_t xgi_kern_isr(int irq, void *dev_id, struct pt_regs *regs) { - xgi_info_t *info = (xgi_info_t *) dev_id; + struct xgi_info *info = (struct xgi_info *) dev_id; u32 need_to_run_bottom_half = 0; //XGI_INFO("xgi_kern_isr \n"); @@ -1286,7 +1286,7 @@ irqreturn_t xgi_kern_isr(int irq, void *dev_id, struct pt_regs *regs) void xgi_kern_isr_bh(unsigned long data) { - xgi_info_t *info = (xgi_info_t *) data; + struct xgi_info *info = (struct xgi_info *) data; XGI_INFO("xgi_kern_isr_bh \n"); @@ -1295,7 +1295,7 @@ void xgi_kern_isr_bh(unsigned long data) XGI_CHECK_PCI_CONFIG(info); } -static void xgi_lock_init(xgi_info_t * info) +static void xgi_lock_init(struct xgi_info * info) { if (info == NULL) return; @@ -1309,7 +1309,7 @@ static void xgi_lock_init(xgi_info_t * info) XGI_ATOMIC_SET(info->use_count, 0); } -static void xgi_dev_init(xgi_info_t * info) +static void xgi_dev_init(struct xgi_info * info) { struct pci_dev *pdev = NULL; struct xgi_dev *dev; @@ -1354,7 +1354,7 @@ static void xgi_dev_init(xgi_info_t * info) static int __init xgi_init_module(void) { - xgi_info_t *info = &xgi_devices[xgi_num_devices]; + struct xgi_info *info = &xgi_devices[xgi_num_devices]; int i, result; XGI_INFO("Jong-xgi kernel driver %s initializing\n", XGI_DRV_VERSION); @@ -1421,7 +1421,7 @@ static int __init xgi_init_module(void) /* init the xgi control device */ { - xgi_info_t *info_ctl = &xgi_ctl_device; + struct xgi_info *info_ctl = &xgi_ctl_device; xgi_lock_init(info_ctl); } diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 5d76b632..32ee5e81 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -93,26 +93,26 @@ /* need a fake device number for control device; just to flag it for msgs */ #define XGI_CONTROL_DEVICE_NUMBER 100 -typedef struct { +struct xgi_aperture { U32 base; // pcie base is different from fb base U32 size; U8 *vbase; -} xgi_aperture_t; +}; -typedef struct xgi_screen_info_s { +struct xgi_screen_info { U32 scrn_start; U32 scrn_xres; U32 scrn_yres; U32 scrn_bpp; U32 scrn_pitch; -} xgi_screen_info_t; +}; -typedef struct xgi_sarea_info_s { +struct xgi_sarea_info { U32 bus_addr; U32 size; -} xgi_sarea_info_t; +}; -typedef struct xgi_info_s { +struct xgi_info { struct pci_dev *dev; int flags; int device_number; @@ -123,11 +123,11 @@ typedef struct xgi_info_s { U8 revision_id; /* physical characteristics */ - xgi_aperture_t mmio; - xgi_aperture_t fb; - xgi_aperture_t pcie; - xgi_screen_info_t scrn_info; - xgi_sarea_info_t sarea_info; + struct xgi_aperture mmio; + struct xgi_aperture fb; + struct xgi_aperture pcie; + struct xgi_screen_info scrn_info; + struct xgi_sarea_info sarea_info; /* look up table parameters */ U32 *lut_base; @@ -150,18 +150,18 @@ typedef struct xgi_info_s { struct semaphore info_sem; struct semaphore fb_sem; struct semaphore pcie_sem; -} xgi_info_t; +}; -typedef struct xgi_ioctl_post_vbios { +struct xgi_ioctl_post_vbios { U32 bus; U32 slot; -} xgi_ioctl_post_vbios_t; +}; -typedef enum xgi_mem_location_s { +enum xgi_mem_location { NON_LOCAL = 0, LOCAL = 1, INVALID = 0x7fffffff -} xgi_mem_location_t; +}; enum PcieOwner { PCIE_2D = 0, @@ -176,23 +176,23 @@ enum PcieOwner { PCIE_INVALID = 0x7fffffff }; -typedef struct xgi_mem_req_s { - xgi_mem_location_t location; +struct xgi_mem_req { + enum xgi_mem_location location; unsigned long size; unsigned long is_front; enum PcieOwner owner; unsigned long pid; -} xgi_mem_req_t; +}; -typedef struct xgi_mem_alloc_s { - xgi_mem_location_t location; +struct xgi_mem_alloc { + enum xgi_mem_location location; unsigned long size; unsigned long bus_addr; unsigned long hw_addr; unsigned long pid; -} xgi_mem_alloc_t; +}; -typedef struct xgi_chip_info_s { +struct xgi_chip_info { U32 device_id; char device_name[32]; U32 vendor_id; @@ -200,17 +200,17 @@ typedef struct xgi_chip_info_s { U32 fb_size; U32 sarea_bus_addr; U32 sarea_size; -} xgi_chip_info_t; +}; -typedef struct xgi_opengl_cmd_s { +struct xgi_opengl_cmd { U32 cmd; -} xgi_opengl_cmd_t; +}; -typedef struct xgi_mmio_info_s { - xgi_opengl_cmd_t cmd_head; +struct xgi_mmio_info { + struct xgi_opengl_cmd cmd_head; void *mmioBase; int size; -} xgi_mmio_info_t; +}; typedef enum { BTYPE_2D = 0, @@ -220,33 +220,33 @@ typedef enum { BTYPE_NONE = 0x7fffffff } BATCH_TYPE; -typedef struct xgi_cmd_info_s { +struct xgi_cmd_info { BATCH_TYPE _firstBeginType; U32 _firstBeginAddr; U32 _firstSize; U32 _curDebugID; U32 _lastBeginAddr; U32 _beginCount; -} xgi_cmd_info_t; +}; -typedef struct xgi_state_info_s { +struct xgi_state_info { U32 _fromState; U32 _toState; -} xgi_state_info_t; +}; -typedef struct cpu_info_s { +struct cpu_info { U32 _eax; U32 _ebx; U32 _ecx; U32 _edx; -} cpu_info_t; +}; -typedef struct xgi_mem_pid_s { +struct xgi_mem_pid { struct list_head list; - xgi_mem_location_t location; + enum xgi_mem_location location; unsigned long bus_addr; unsigned long pid; -} xgi_mem_pid_t; +}; /* * Ioctl definitions @@ -278,32 +278,32 @@ typedef struct xgi_mem_pid_s { #define XGI_ESC_CPUID (XGI_IOCTL_BASE + 20) #define XGI_ESC_MEM_COLLECT (XGI_IOCTL_BASE + 21) -#define XGI_IOCTL_DEVICE_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_DEVICE_INFO, xgi_chip_info_t) +#define XGI_IOCTL_DEVICE_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_DEVICE_INFO, struct xgi_chip_info) #define XGI_IOCTL_POST_VBIOS _IO(XGI_IOCTL_MAGIC, XGI_ESC_POST_VBIOS) #define XGI_IOCTL_FB_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_FB_INIT) -#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, xgi_mem_req_t) +#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, struct xgi_mem_req) #define XGI_IOCTL_FB_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_FB_FREE, unsigned long) #define XGI_IOCTL_PCIE_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_INIT) -#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, xgi_mem_req_t) +#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, struct xgi_mem_req) #define XGI_IOCTL_PCIE_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_FREE, unsigned long) -#define XGI_IOCTL_PUT_SCREEN_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PUT_SCREEN_INFO, xgi_screen_info_t) -#define XGI_IOCTL_GET_SCREEN_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_GET_SCREEN_INFO, xgi_screen_info_t) +#define XGI_IOCTL_PUT_SCREEN_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PUT_SCREEN_INFO, struct xgi_screen_info) +#define XGI_IOCTL_GET_SCREEN_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_GET_SCREEN_INFO, struct xgi_screen_info) #define XGI_IOCTL_GE_RESET _IO(XGI_IOCTL_MAGIC, XGI_ESC_GE_RESET) -#define XGI_IOCTL_SAREA_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_SAREA_INFO, xgi_sarea_info_t) +#define XGI_IOCTL_SAREA_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_SAREA_INFO, struct xgi_sarea_info) #define XGI_IOCTL_DUMP_REGISTER _IO(XGI_IOCTL_MAGIC, XGI_ESC_DUMP_REGISTER) #define XGI_IOCTL_DEBUG_INFO _IO(XGI_IOCTL_MAGIC, XGI_ESC_DEBUG_INFO) -#define XGI_IOCTL_MMIO_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_MMIO_INFO, xgi_mmio_info_t) +#define XGI_IOCTL_MMIO_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_MMIO_INFO, struct xgi_mmio_info) -#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, xgi_cmd_info_t) +#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, struct xgi_cmd_info) #define XGI_IOCTL_TEST_RWINKERNEL _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_TEST_RWINKERNEL, unsigned long) -#define XGI_IOCTL_STATE_CHANGE _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_STATE_CHANGE, xgi_state_info_t) +#define XGI_IOCTL_STATE_CHANGE _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_STATE_CHANGE, struct xgi_state_info) #define XGI_IOCTL_PCIE_CHECK _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_CHECK) -#define XGI_IOCTL_CPUID _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_CPUID, cpu_info_t) +#define XGI_IOCTL_CPUID _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_CPUID, struct cpu_info) #define XGI_IOCTL_MAXNR 30 /* @@ -338,28 +338,28 @@ typedef struct xgi_mem_pid_s { (((offset) >= (info)->pcie.base) \ && (((offset) + (length)) <= (info)->pcie.base + (info)->pcie.size)) -extern int xgi_fb_heap_init(xgi_info_t * info); -extern void xgi_fb_heap_cleanup(xgi_info_t * info); +extern int xgi_fb_heap_init(struct xgi_info * info); +extern void xgi_fb_heap_cleanup(struct xgi_info * info); -extern void xgi_fb_alloc(xgi_info_t * info, xgi_mem_req_t * req, - xgi_mem_alloc_t * alloc); -extern void xgi_fb_free(xgi_info_t * info, unsigned long offset); -extern void xgi_mem_collect(xgi_info_t * info, unsigned int *pcnt); +extern void xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_req * req, + struct xgi_mem_alloc * alloc); +extern void xgi_fb_free(struct xgi_info * info, unsigned long offset); +extern void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt); -extern int xgi_pcie_heap_init(xgi_info_t * info); -extern void xgi_pcie_heap_cleanup(xgi_info_t * info); +extern int xgi_pcie_heap_init(struct xgi_info * info); +extern void xgi_pcie_heap_cleanup(struct xgi_info * info); -extern void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, - enum PcieOwner owner, xgi_mem_alloc_t * alloc); -extern void xgi_pcie_free(xgi_info_t * info, unsigned long offset); +extern void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, + enum PcieOwner owner, struct xgi_mem_alloc * alloc); +extern void xgi_pcie_free(struct xgi_info * info, unsigned long offset); extern void xgi_pcie_heap_check(void); -extern struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, +extern struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, unsigned long address); -extern void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address); +extern void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address); -extern void xgi_read_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req); -extern void xgi_write_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req); +extern void xgi_read_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req); +extern void xgi_write_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req); -extern void xgi_test_rwinkernel(xgi_info_t * info, unsigned long address); +extern void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address); #endif diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index fab99ae2..56cc589b 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -33,19 +33,19 @@ #define XGI_FB_HEAP_START 0x1000000 -static xgi_mem_heap_t *xgi_fb_heap; -static kmem_cache_t *xgi_fb_cache_block = NULL; +static struct xgi_mem_heap *xgi_fb_heap; +static struct kmem_cache *xgi_fb_cache_block = NULL; extern struct list_head xgi_mempid_list; -static xgi_mem_block_t *xgi_mem_new_node(void); -static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t * info, unsigned long size); -static xgi_mem_block_t *xgi_mem_free(xgi_info_t * info, unsigned long offset); +static struct xgi_mem_block *xgi_mem_new_node(void); +static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, unsigned long size); +static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long offset); -void xgi_fb_alloc(xgi_info_t * info, - xgi_mem_req_t * req, xgi_mem_alloc_t * alloc) +void xgi_fb_alloc(struct xgi_info * info, + struct xgi_mem_req * req, struct xgi_mem_alloc * alloc) { - xgi_mem_block_t *block; - xgi_mem_pid_t *mempid_block; + struct xgi_mem_block *block; + struct xgi_mem_pid *mempid_block; if (req->is_front) { alloc->location = LOCAL; @@ -74,7 +74,7 @@ void xgi_fb_alloc(xgi_info_t * info, /* manage mempid */ mempid_block = - kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); mempid_block->location = LOCAL; mempid_block->bus_addr = alloc->bus_addr; mempid_block->pid = alloc->pid; @@ -90,12 +90,12 @@ void xgi_fb_alloc(xgi_info_t * info, } } -void xgi_fb_free(xgi_info_t * info, unsigned long bus_addr) +void xgi_fb_free(struct xgi_info * info, unsigned long bus_addr) { - xgi_mem_block_t *block; + struct xgi_mem_block *block; unsigned long offset = bus_addr - info->fb.base; - xgi_mem_pid_t *mempid_block; - xgi_mem_pid_t *mempid_freeblock = NULL; + struct xgi_mem_pid *mempid_block; + struct xgi_mem_pid *mempid_freeblock = NULL; struct list_head *mempid_list; if (offset < 0) { @@ -114,7 +114,7 @@ void xgi_fb_free(xgi_info_t * info, unsigned long bus_addr) mempid_list = xgi_mempid_list.next; while (mempid_list != &xgi_mempid_list) { mempid_block = - list_entry(mempid_list, struct xgi_mem_pid_s, list); + list_entry(mempid_list, struct xgi_mem_pid, list); if (mempid_block->location == LOCAL && mempid_block->bus_addr == bus_addr) { mempid_freeblock = mempid_block; @@ -132,11 +132,11 @@ void xgi_fb_free(xgi_info_t * info, unsigned long bus_addr) } } -int xgi_fb_heap_init(xgi_info_t * info) +int xgi_fb_heap_init(struct xgi_info * info) { - xgi_mem_block_t *block; + struct xgi_mem_block *block; - xgi_fb_heap = kmalloc(sizeof(xgi_mem_heap_t), GFP_KERNEL); + xgi_fb_heap = kmalloc(sizeof(struct xgi_mem_heap), GFP_KERNEL); if (!xgi_fb_heap) { XGI_ERROR("xgi_fb_heap alloc failed\n"); return 0; @@ -147,7 +147,7 @@ int xgi_fb_heap_init(xgi_info_t * info) INIT_LIST_HEAD(&xgi_fb_heap->sort_list); xgi_fb_cache_block = - kmem_cache_create("xgi_fb_block", sizeof(xgi_mem_block_t), 0, + kmem_cache_create("xgi_fb_block", sizeof(struct xgi_mem_block), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (NULL == xgi_fb_cache_block) { @@ -156,7 +156,7 @@ int xgi_fb_heap_init(xgi_info_t * info) } block = - (xgi_mem_block_t *) kmem_cache_alloc(xgi_fb_cache_block, + (struct xgi_mem_block *) kmem_cache_alloc(xgi_fb_cache_block, GFP_KERNEL); if (!block) { XGI_ERROR("kmem_cache_alloc failed\n"); @@ -190,10 +190,10 @@ int xgi_fb_heap_init(xgi_info_t * info) return 0; } -void xgi_fb_heap_cleanup(xgi_info_t * info) +void xgi_fb_heap_cleanup(struct xgi_info * info) { struct list_head *free_list, *temp; - xgi_mem_block_t *block; + struct xgi_mem_block *block; int i; if (xgi_fb_heap) { @@ -202,7 +202,7 @@ void xgi_fb_heap_cleanup(xgi_info_t * info) temp = free_list->next; while (temp != free_list) { block = - list_entry(temp, struct xgi_mem_block_s, + list_entry(temp, struct xgi_mem_block, list); temp = temp->next; @@ -225,12 +225,12 @@ void xgi_fb_heap_cleanup(xgi_info_t * info) } } -static xgi_mem_block_t *xgi_mem_new_node(void) +static struct xgi_mem_block *xgi_mem_new_node(void) { - xgi_mem_block_t *block; + struct xgi_mem_block *block; block = - (xgi_mem_block_t *) kmem_cache_alloc(xgi_fb_cache_block, + (struct xgi_mem_block *) kmem_cache_alloc(xgi_fb_cache_block, GFP_KERNEL); if (!block) { XGI_ERROR("kmem_cache_alloc failed\n"); @@ -241,23 +241,23 @@ static xgi_mem_block_t *xgi_mem_new_node(void) } #if 0 -static void xgi_mem_insert_node_after(xgi_mem_list_t * list, - xgi_mem_block_t * current, - xgi_mem_block_t * block); -static void xgi_mem_insert_node_before(xgi_mem_list_t * list, - xgi_mem_block_t * current, - xgi_mem_block_t * block); -static void xgi_mem_insert_node_head(xgi_mem_list_t * list, - xgi_mem_block_t * block); -static void xgi_mem_insert_node_tail(xgi_mem_list_t * list, - xgi_mem_block_t * block); -static void xgi_mem_delete_node(xgi_mem_list_t * list, xgi_mem_block_t * block); +static void xgi_mem_insert_node_after(struct xgi_mem_list * list, + struct xgi_mem_block * current, + struct xgi_mem_block * block); +static void xgi_mem_insert_node_before(struct xgi_mem_list * list, + struct xgi_mem_block * current, + struct xgi_mem_block * block); +static void xgi_mem_insert_node_head(struct xgi_mem_list * list, + struct xgi_mem_block * block); +static void xgi_mem_insert_node_tail(struct xgi_mem_list * list, + struct xgi_mem_block * block); +static void xgi_mem_delete_node(struct xgi_mem_list * list, struct xgi_mem_block * block); /* * insert node:block after node:current */ -static void xgi_mem_insert_node_after(xgi_mem_list_t * list, - xgi_mem_block_t * current, - xgi_mem_block_t * block) +static void xgi_mem_insert_node_after(struct xgi_mem_list * list, + struct xgi_mem_block * current, + struct xgi_mem_block * block) { block->prev = current; block->next = current->next; @@ -273,9 +273,9 @@ static void xgi_mem_insert_node_after(xgi_mem_list_t * list, /* * insert node:block before node:current */ -static void xgi_mem_insert_node_before(xgi_mem_list_t * list, - xgi_mem_block_t * current, - xgi_mem_block_t * block) +static void xgi_mem_insert_node_before(struct xgi_mem_list * list, + struct xgi_mem_block * current, + struct xgi_mem_block * block) { block->prev = current->prev; block->next = current; @@ -286,7 +286,7 @@ static void xgi_mem_insert_node_before(xgi_mem_list_t * list, block->prev->next = block; } } -void xgi_mem_insert_node_head(xgi_mem_list_t * list, xgi_mem_block_t * block) +void xgi_mem_insert_node_head(struct xgi_mem_list * list, struct xgi_mem_block * block) { block->next = list->head; block->prev = NULL; @@ -299,8 +299,8 @@ void xgi_mem_insert_node_head(xgi_mem_list_t * list, xgi_mem_block_t * block) list->head = block; } -static void xgi_mem_insert_node_tail(xgi_mem_list_t * list, - xgi_mem_block_t * block) +static void xgi_mem_insert_node_tail(struct xgi_mem_list * list, + struct xgi_mem_block * block) { block->next = NULL; block->prev = list->tail; @@ -312,7 +312,7 @@ static void xgi_mem_insert_node_tail(xgi_mem_list_t * list, list->tail = block; } -static void xgi_mem_delete_node(xgi_mem_list_t * list, xgi_mem_block_t * block) +static void xgi_mem_delete_node(struct xgi_mem_list * list, struct xgi_mem_block * block) { if (block == list->head) { list->head = block->next; @@ -331,11 +331,11 @@ static void xgi_mem_delete_node(xgi_mem_list_t * list, xgi_mem_block_t * block) block->next = block->prev = NULL; } #endif -static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t * info, +static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, unsigned long originalSize) { struct list_head *free_list; - xgi_mem_block_t *block, *free_block, *used_block; + struct xgi_mem_block *block, *free_block, *used_block; unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; @@ -358,7 +358,7 @@ static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t * info, while (free_list != &xgi_fb_heap->free_list) { XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_mem_block_s, list); + block = list_entry(free_list, struct xgi_mem_block, list); if (size <= block->size) { break; } @@ -406,18 +406,18 @@ static xgi_mem_block_t *xgi_mem_alloc(xgi_info_t * info, return (used_block); } -static xgi_mem_block_t *xgi_mem_free(xgi_info_t * info, unsigned long offset) +static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long offset) { struct list_head *free_list, *used_list; - xgi_mem_block_t *used_block = NULL, *block = NULL; - xgi_mem_block_t *prev, *next; + struct xgi_mem_block *used_block = NULL, *block = NULL; + struct xgi_mem_block *prev, *next; unsigned long upper; unsigned long lower; used_list = xgi_fb_heap->used_list.next; while (used_list != &xgi_fb_heap->used_list) { - block = list_entry(used_list, struct xgi_mem_block_s, list); + block = list_entry(used_list, struct xgi_mem_block, list); if (block->offset == offset) { break; } @@ -441,7 +441,7 @@ static xgi_mem_block_t *xgi_mem_free(xgi_info_t * info, unsigned long offset) free_list = xgi_fb_heap->free_list.next; while (free_list != &xgi_fb_heap->free_list) { - block = list_entry(free_list, struct xgi_mem_block_s, list); + block = list_entry(free_list, struct xgi_mem_block, list); if (block->offset == upper) { next = block; diff --git a/linux-core/xgi_fb.h b/linux-core/xgi_fb.h index ae078ae0..363c8bc8 100644 --- a/linux-core/xgi_fb.h +++ b/linux-core/xgi_fb.h @@ -29,42 +29,19 @@ #ifndef _XGI_FB_H_ #define _XGI_FB_H_ -typedef struct xgi_mem_block_s { +struct xgi_mem_block { struct list_head list; unsigned long offset; unsigned long size; atomic_t use_count; -} xgi_mem_block_t; +}; -typedef struct xgi_mem_heap_s { +struct xgi_mem_heap { struct list_head free_list; struct list_head used_list; struct list_head sort_list; unsigned long max_freesize; spinlock_t lock; -} xgi_mem_heap_t; - -#if 0 -typedef struct xgi_mem_block_s { - struct xgi_mem_block_s *next; - struct xgi_mem_block_s *prev; - unsigned long offset; - unsigned long size; - atomic_t use_count; -} xgi_mem_block_t; - -typedef struct xgi_mem_list_s { - xgi_mem_block_t *head; - xgi_mem_block_t *tail; -} xgi_mem_list_t; - -typedef struct xgi_mem_heap_s { - xgi_mem_list_t *free_list; - xgi_mem_list_t *used_list; - xgi_mem_list_t *sort_list; - unsigned long max_freesize; - spinlock_t lock; -} xgi_mem_heap_t; -#endif +}; #endif diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h index 465feb3c..2602b0f5 100644 --- a/linux-core/xgi_linux.h +++ b/linux-core/xgi_linux.h @@ -415,10 +415,10 @@ static inline pgprot_t pgprot_writecombined(pgprot_t old_prot) free_pages(ptr, order); \ } -typedef struct xgi_pte_s { +struct xgi_pte { unsigned long phys_addr; unsigned long virt_addr; -} xgi_pte_t; +}; /* * AMD Athlon processors expose a subtle bug in the Linux @@ -427,12 +427,12 @@ typedef struct xgi_pte_s { * 2.4.20 is the first kernel to address it properly. The * page_attr API provides the means to solve the problem. */ -static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(xgi_pte_t * page_ptr) +static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(struct xgi_pte * page_ptr) { struct page *page = virt_to_page(__va(page_ptr->phys_addr)); change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); } -static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr) +static inline void XGI_SET_PAGE_ATTRIB_CACHED(struct xgi_pte * page_ptr) { struct page *page = virt_to_page(__va(page_ptr->phys_addr)); change_page_attr(page, 1, PAGE_KERNEL); @@ -453,20 +453,16 @@ static inline void XGI_SET_PAGE_ATTRIB_CACHED(xgi_pte_t * page_ptr) #define XGILockPage(page) SetPageLocked(page) #define XGIUnlockPage(page) ClearPageLocked(page) -/* - * hide a pointer to struct xgi_info_t in a file-private info - */ - -typedef struct { - void *info; +struct xgi_file_private { + struct xgi_info *info; U32 num_events; spinlock_t fp_lock; wait_queue_head_t wait_queue; -} xgi_file_private_t; +}; #define FILE_PRIVATE(filp) ((filp)->private_data) -#define XGI_GET_FP(filp) ((xgi_file_private_t *) FILE_PRIVATE(filp)) +#define XGI_GET_FP(filp) ((struct xgi_file_private *) FILE_PRIVATE(filp)) /* for the card devices */ #define XGI_INFO_FROM_FP(filp) (XGI_GET_FP(filp)->info) diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 8d0e81b6..68c5ca20 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -32,7 +32,7 @@ #include "xgi_regs.h" #include "xgi_pcie.h" -void xgi_get_device_info(xgi_info_t * info, xgi_chip_info_t * req) +void xgi_get_device_info(struct xgi_info * info, struct xgi_chip_info * req) { req->device_id = info->device_id; req->device_name[0] = 'x'; @@ -46,13 +46,13 @@ void xgi_get_device_info(xgi_info_t * info, xgi_chip_info_t * req) req->sarea_size = info->sarea_info.size; } -void xgi_get_mmio_info(xgi_info_t * info, xgi_mmio_info_t * req) +void xgi_get_mmio_info(struct xgi_info * info, struct xgi_mmio_info * req) { req->mmioBase = (void *)info->mmio.base; req->size = info->mmio.size; } -void xgi_put_screen_info(xgi_info_t * info, xgi_screen_info_t * req) +void xgi_put_screen_info(struct xgi_info * info, struct xgi_screen_info * req) { info->scrn_info.scrn_start = req->scrn_start; info->scrn_info.scrn_xres = req->scrn_xres; @@ -71,7 +71,7 @@ void xgi_put_screen_info(xgi_info_t * info, xgi_screen_info_t * req) info->scrn_info.scrn_bpp, info->scrn_info.scrn_pitch); } -void xgi_get_screen_info(xgi_info_t * info, xgi_screen_info_t * req) +void xgi_get_screen_info(struct xgi_info * info, struct xgi_screen_info * req) { req->scrn_start = info->scrn_info.scrn_start; req->scrn_xres = info->scrn_info.scrn_xres; @@ -89,13 +89,13 @@ void xgi_get_screen_info(xgi_info_t * info, xgi_screen_info_t * req) req->scrn_yres, req->scrn_bpp, req->scrn_pitch); } -void xgi_ge_reset(xgi_info_t * info) +void xgi_ge_reset(struct xgi_info * info) { xgi_disable_ge(info); xgi_enable_ge(info); } -void xgi_sarea_info(xgi_info_t * info, xgi_sarea_info_t * req) +void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req) { info->sarea_info.bus_addr = req->bus_addr; info->sarea_info.size = req->size; @@ -111,7 +111,7 @@ void xgi_sarea_info(xgi_info_t * info, xgi_sarea_info_t * req) static U32 s_invalid_begin = 0; -BOOL xgi_ge_irq_handler(xgi_info_t * info) +BOOL xgi_ge_irq_handler(struct xgi_info * info) { volatile U8 *mmio_vbase = info->mmio.vbase; volatile U32 *ge_3d_status = (volatile U32 *)(mmio_vbase + 0x2800); @@ -287,7 +287,7 @@ BOOL xgi_ge_irq_handler(xgi_info_t * info) return FALSE; } -BOOL xgi_crt_irq_handler(xgi_info_t * info) +BOOL xgi_crt_irq_handler(struct xgi_info * info) { BOOL ret = FALSE; U8 save_3ce = bReadReg(0x3ce); @@ -311,7 +311,7 @@ BOOL xgi_crt_irq_handler(xgi_info_t * info) return (ret); } -BOOL xgi_dvi_irq_handler(xgi_info_t * info) +BOOL xgi_dvi_irq_handler(struct xgi_info * info) { BOOL ret = FALSE; U8 save_3ce = bReadReg(0x3ce); @@ -344,7 +344,7 @@ BOOL xgi_dvi_irq_handler(xgi_info_t * info) return (ret); } -void xgi_dump_register(xgi_info_t * info) +void xgi_dump_register(struct xgi_info * info) { int i, j; unsigned char temp; @@ -518,13 +518,13 @@ void xgi_dump_register(xgi_info_t * info) } } -void xgi_restore_registers(xgi_info_t * info) +void xgi_restore_registers(struct xgi_info * info) { bOut3x5(0x13, 0); bOut3x5(0x8b, 2); } -void xgi_waitfor_pci_idle(xgi_info_t * info) +void xgi_waitfor_pci_idle(struct xgi_info * info) { #define WHOLD_GE_STATUS 0x2800 #define IDLE_MASK ~0x90200000 @@ -539,7 +539,7 @@ void xgi_waitfor_pci_idle(xgi_info_t * info) } } -int xgi_get_cpu_id(struct cpu_info_s *arg) +int xgi_get_cpu_id(struct cpu_info *arg) { int op = arg->_eax; __asm__("cpuid":"=a"(arg->_eax), @@ -554,9 +554,9 @@ int xgi_get_cpu_id(struct cpu_info_s *arg) /*memory collect function*/ extern struct list_head xgi_mempid_list; -void xgi_mem_collect(xgi_info_t * info, unsigned int *pcnt) +void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt) { - xgi_mem_pid_t *mempid_block; + struct xgi_mem_pid *mempid_block; struct list_head *mempid_list; struct task_struct *p, *find; unsigned int cnt = 0; @@ -565,7 +565,7 @@ void xgi_mem_collect(xgi_info_t * info, unsigned int *pcnt) while (mempid_list != &xgi_mempid_list) { mempid_block = - list_entry(mempid_list, struct xgi_mem_pid_s, list); + list_entry(mempid_list, struct xgi_mem_pid, list); mempid_list = mempid_list->next; find = NULL; diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h index 37120aaa..0ebbe7e8 100644 --- a/linux-core/xgi_misc.h +++ b/linux-core/xgi_misc.h @@ -29,19 +29,19 @@ #ifndef _XGI_MISC_H_ #define _XGI_MISC_H_ -extern void xgi_dump_register(xgi_info_t * info); -extern void xgi_get_device_info(xgi_info_t * info, xgi_chip_info_t * req); -extern void xgi_get_mmio_info(xgi_info_t * info, xgi_mmio_info_t * req); -extern void xgi_get_screen_info(xgi_info_t * info, xgi_screen_info_t * req); -extern void xgi_put_screen_info(xgi_info_t * info, xgi_screen_info_t * req); -extern void xgi_ge_reset(xgi_info_t * info); -extern void xgi_sarea_info(xgi_info_t * info, xgi_sarea_info_t * req); -extern int xgi_get_cpu_id(struct cpu_info_s *arg); +extern void xgi_dump_register(struct xgi_info * info); +extern void xgi_get_device_info(struct xgi_info * info, struct xgi_chip_info * req); +extern void xgi_get_mmio_info(struct xgi_info * info, struct xgi_mmio_info * req); +extern void xgi_get_screen_info(struct xgi_info * info, struct xgi_screen_info * req); +extern void xgi_put_screen_info(struct xgi_info * info, struct xgi_screen_info * req); +extern void xgi_ge_reset(struct xgi_info * info); +extern void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req); +extern int xgi_get_cpu_id(struct cpu_info *arg); -extern void xgi_restore_registers(xgi_info_t * info); -extern BOOL xgi_ge_irq_handler(xgi_info_t * info); -extern BOOL xgi_crt_irq_handler(xgi_info_t * info); -extern BOOL xgi_dvi_irq_handler(xgi_info_t * info); -extern void xgi_waitfor_pci_idle(xgi_info_t * info); +extern void xgi_restore_registers(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 index 1a4d8e12..a81dbe8b 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -33,11 +33,11 @@ #include "xgi_pcie.h" #include "xgi_misc.h" -static xgi_pcie_heap_t *xgi_pcie_heap = NULL; -static kmem_cache_t *xgi_pcie_cache_block = NULL; -static xgi_pcie_block_t *xgi_pcie_vertex_block = NULL; -static xgi_pcie_block_t *xgi_pcie_cmdlist_block = NULL; -static xgi_pcie_block_t *xgi_pcie_scratchpad_block = NULL; +static struct xgi_pcie_heap *xgi_pcie_heap = NULL; +static struct kmem_cache *xgi_pcie_cache_block = NULL; +static struct xgi_pcie_block *xgi_pcie_vertex_block = NULL; +static struct xgi_pcie_block *xgi_pcie_cmdlist_block = NULL; +static struct xgi_pcie_block *xgi_pcie_scratchpad_block = NULL; extern struct list_head xgi_mempid_list; static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) @@ -85,7 +85,7 @@ static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) free_pages(page_addr, page_order); } -static int xgi_pcie_lut_init(xgi_info_t * info) +static int xgi_pcie_lut_init(struct xgi_info * info) { unsigned char *page_addr = NULL; unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; @@ -214,7 +214,7 @@ static int xgi_pcie_lut_init(xgi_info_t * info) return 0; } -static void xgi_pcie_lut_cleanup(xgi_info_t * info) +static void xgi_pcie_lut_cleanup(struct xgi_info * info) { if (info->lut_base) { XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", @@ -225,10 +225,10 @@ static void xgi_pcie_lut_cleanup(xgi_info_t * info) } } -static xgi_pcie_block_t *xgi_pcie_new_node(void) +static struct xgi_pcie_block *xgi_pcie_new_node(void) { - xgi_pcie_block_t *block = - (xgi_pcie_block_t *) kmem_cache_alloc(xgi_pcie_cache_block, + struct xgi_pcie_block *block = + (struct xgi_pcie_block *) kmem_cache_alloc(xgi_pcie_cache_block, GFP_KERNEL); if (block == NULL) { return NULL; @@ -247,11 +247,11 @@ static xgi_pcie_block_t *xgi_pcie_new_node(void) return block; } -static void xgi_pcie_block_stuff_free(xgi_pcie_block_t * block) +static void xgi_pcie_block_stuff_free(struct xgi_pcie_block * block) { struct page *page; - xgi_page_block_t *page_block = block->page_block; - xgi_page_block_t *free_block; + struct xgi_page_block *page_block = block->page_block; + struct xgi_page_block *free_block; unsigned long page_count = 0; int i; @@ -285,9 +285,9 @@ static void xgi_pcie_block_stuff_free(xgi_pcie_block_t * block) } } -int xgi_pcie_heap_init(xgi_info_t * info) +int xgi_pcie_heap_init(struct xgi_info * info) { - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; if (!xgi_pcie_lut_init(info)) { XGI_ERROR("xgi_pcie_lut_init failed\n"); @@ -295,7 +295,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) } xgi_pcie_heap = - (xgi_pcie_heap_t *) kmalloc(sizeof(xgi_pcie_heap_t), GFP_KERNEL); + (struct xgi_pcie_heap *) kmalloc(sizeof(struct xgi_pcie_heap), GFP_KERNEL); if (!xgi_pcie_heap) { XGI_ERROR("xgi_pcie_heap alloc failed\n"); goto fail1; @@ -307,7 +307,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) xgi_pcie_heap->max_freesize = info->pcie.size; xgi_pcie_cache_block = - kmem_cache_create("xgi_pcie_block", sizeof(xgi_pcie_block_t), 0, + kmem_cache_create("xgi_pcie_block", sizeof(struct xgi_pcie_block), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (NULL == xgi_pcie_cache_block) { @@ -315,7 +315,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) goto fail2; } - block = (xgi_pcie_block_t *) xgi_pcie_new_node(); + block = (struct xgi_pcie_block *) xgi_pcie_new_node(); if (!block) { XGI_ERROR("xgi_pcie_new_node failed\n"); goto fail3; @@ -348,7 +348,7 @@ int xgi_pcie_heap_init(xgi_info_t * info) void xgi_pcie_heap_check(void) { struct list_head *useList, *temp; - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; unsigned int ownerIndex; #ifdef XGI_DEBUG char *ownerStr[6] = @@ -360,7 +360,7 @@ void xgi_pcie_heap_check(void) temp = useList->next; XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); while (temp != useList) { - block = list_entry(temp, struct xgi_pcie_block_s, list); + block = list_entry(temp, struct xgi_pcie_block, list); if (block->owner == PCIE_2D) ownerIndex = 0; else if (block->owner > PCIE_3D_TEXTURE @@ -378,10 +378,10 @@ void xgi_pcie_heap_check(void) } } -void xgi_pcie_heap_cleanup(xgi_info_t * info) +void xgi_pcie_heap_cleanup(struct xgi_info * info) { struct list_head *free_list, *temp; - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; int j; xgi_pcie_lut_cleanup(info); @@ -394,7 +394,7 @@ void xgi_pcie_heap_cleanup(xgi_info_t * info) while (temp != free_list) { block = - list_entry(temp, struct xgi_pcie_block_s, + list_entry(temp, struct xgi_pcie_block, list); XGI_INFO ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", @@ -421,13 +421,13 @@ void xgi_pcie_heap_cleanup(xgi_info_t * info) } } -static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, +static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, unsigned long originalSize, enum PcieOwner owner) { struct list_head *free_list; - xgi_pcie_block_t *block, *used_block, *free_block; - xgi_page_block_t *page_block, *prev_page_block; + struct xgi_pcie_block *block, *used_block, *free_block; + struct xgi_page_block *page_block, *prev_page_block; struct page *page; unsigned long page_order = 0, count = 0, index = 0; unsigned long page_addr = 0; @@ -482,7 +482,7 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, free_list = xgi_pcie_heap->free_list.next; while (free_list != &xgi_pcie_heap->free_list) { //XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_pcie_block_s, list); + block = list_entry(free_list, struct xgi_pcie_block, list); if (size <= block->size) { break; } @@ -543,12 +543,12 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, used_block->page_order); used_block->page_block = NULL; - //used_block->page_block = (xgi_pages_block_t *)kmalloc(sizeof(xgi_pages_block_t), GFP_KERNEL); - //if (!used_block->page_block) return NULL; + //used_block->page_block = (struct xgi_pages_block *)kmalloc(sizeof(struct xgi_pages_block), GFP_KERNEL); + //if (!used_block->page_block) return NULL;_t //used_block->page_block->next = NULL; used_block->page_table = - (xgi_pte_t *) kmalloc(sizeof(xgi_pte_t) * used_block->page_count, + (struct xgi_pte *) kmalloc(sizeof(struct xgi_pte) * used_block->page_count, GFP_KERNEL); if (used_block->page_table == NULL) { goto fail; @@ -595,8 +595,8 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, if (page_block == NULL) { page_block = - (xgi_page_block_t *) - kmalloc(sizeof(xgi_page_block_t), GFP_KERNEL); + (struct xgi_page_block *) + kmalloc(sizeof(struct xgi_page_block), GFP_KERNEL); if (!page_block) { XGI_ERROR ("Can't get memory for page_block! \n"); @@ -697,17 +697,17 @@ static xgi_pcie_block_t *xgi_pcie_mem_alloc(xgi_info_t * info, return NULL; } -static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, +static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, unsigned long offset) { struct list_head *free_list, *used_list; - xgi_pcie_block_t *used_block, *block = NULL; - xgi_pcie_block_t *prev, *next; + struct xgi_pcie_block *used_block, *block = NULL; + struct xgi_pcie_block *prev, *next; unsigned long upper, lower; used_list = xgi_pcie_heap->used_list.next; while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block_s, list); + block = list_entry(used_list, struct xgi_pcie_block, list); if (block->offset == offset) { break; } @@ -737,7 +737,7 @@ static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, free_list = xgi_pcie_heap->free_list.next; while (free_list != &xgi_pcie_heap->free_list) { - block = list_entry(free_list, struct xgi_pcie_block_s, list); + block = list_entry(free_list, struct xgi_pcie_block, list); if (block->offset == upper) { next = block; } else if ((block->offset + block->size) == lower) { @@ -787,11 +787,11 @@ static xgi_pcie_block_t *xgi_pcie_mem_free(xgi_info_t * info, return (used_block); } -void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, - enum PcieOwner owner, xgi_mem_alloc_t * alloc) +void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, + enum PcieOwner owner, struct xgi_mem_alloc * alloc) { - xgi_pcie_block_t *block; - xgi_mem_pid_t *mempid_block; + struct xgi_pcie_block *block; + struct xgi_mem_pid *mempid_block; xgi_down(info->pcie_sem); block = xgi_pcie_mem_alloc(info, size, owner); @@ -819,7 +819,7 @@ void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, */ if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) { mempid_block = - kmalloc(sizeof(xgi_mem_pid_t), GFP_KERNEL); + kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); if (!mempid_block) XGI_ERROR("mempid_block alloc failed\n"); mempid_block->location = NON_LOCAL; @@ -837,12 +837,12 @@ void xgi_pcie_alloc(xgi_info_t * info, unsigned long size, } } -void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) +void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) { - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; unsigned long offset = bus_addr - info->pcie.base; - xgi_mem_pid_t *mempid_block; - xgi_mem_pid_t *mempid_freeblock = NULL; + struct xgi_mem_pid *mempid_block; + struct xgi_mem_pid *mempid_freeblock = NULL; struct list_head *mempid_list; char isvertex = 0; int processcnt; @@ -857,7 +857,7 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) mempid_list = xgi_mempid_list.next; while (mempid_list != &xgi_mempid_list) { mempid_block = - list_entry(mempid_list, struct xgi_mem_pid_s, list); + list_entry(mempid_list, struct xgi_mem_pid, list); if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) { ++processcnt; @@ -884,7 +884,7 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) mempid_list = xgi_mempid_list.next; while (mempid_list != &xgi_mempid_list) { mempid_block = - list_entry(mempid_list, struct xgi_mem_pid_s, list); + list_entry(mempid_list, struct xgi_mem_pid, list); if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) { @@ -906,17 +906,17 @@ void xgi_pcie_free(xgi_info_t * info, unsigned long bus_addr) * given a bus address, fid the pcie mem block * uses the bus address as the key. */ -struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, - unsigned long address) +struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, + unsigned long address) { struct list_head *used_list; - xgi_pcie_block_t *block; + struct xgi_pcie_block *block; int i; used_list = xgi_pcie_heap->used_list.next; while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block_s, list); + block = list_entry(used_list, struct xgi_pcie_block, list); if (block->bus_addr == address) { return block; @@ -946,7 +946,7 @@ struct xgi_pcie_block_s *xgi_find_pcie_block(xgi_info_t * info, * Returns CPU virtual address. Assumes the CPU VAddr is continuous in not * the same block */ -void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) +void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) { struct list_head *used_list = xgi_pcie_heap->used_list.next; const unsigned long offset_in_page = address & (PAGE_SIZE - 1); @@ -956,8 +956,8 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) used_list, address, PAGE_SIZE - 1, offset_in_page); while (used_list != &xgi_pcie_heap->used_list) { - xgi_pcie_block_t *block = - list_entry(used_list, struct xgi_pcie_block_s, list); + struct xgi_pcie_block *block = + list_entry(used_list, struct xgi_pcie_block, list); XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", block, block->hw_addr, block->size); @@ -987,19 +987,19 @@ void *xgi_find_pcie_virt(xgi_info_t * info, unsigned long address) return NULL; } -void xgi_read_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +void xgi_read_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) { } -void xgi_write_pcie_mem(xgi_info_t * info, xgi_mem_req_t * req) +void xgi_write_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) { } /* address -- GE hw address */ -void xgi_test_rwinkernel(xgi_info_t * info, unsigned long address) +void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address) { unsigned long *virtaddr = 0; if (address == 0) { diff --git a/linux-core/xgi_pcie.h b/linux-core/xgi_pcie.h index 6e8e45b9..b66d6a28 100644 --- a/linux-core/xgi_pcie.h +++ b/linux-core/xgi_pcie.h @@ -33,15 +33,15 @@ #define XGI_PCIE_ALLOC_MAX_ORDER 1 /* 8K in Kernel 2.4.* */ #endif -typedef struct xgi_page_block_s { - struct xgi_page_block_s *next; +struct xgi_page_block { + struct xgi_page_block *next; unsigned long phys_addr; unsigned long virt_addr; unsigned long page_count; unsigned long page_order; -} xgi_page_block_t; +}; -typedef struct xgi_pcie_block_s { +struct xgi_pcie_block { struct list_head list; unsigned long offset; /* block's offset in pcie memory, begin from 0 */ unsigned long size; /* The block size. */ @@ -50,19 +50,19 @@ typedef struct xgi_pcie_block_s { unsigned long page_count; unsigned long page_order; - xgi_page_block_t *page_block; - xgi_pte_t *page_table; /* list of physical pages allocated */ + struct xgi_page_block *page_block; + struct xgi_pte *page_table; /* list of physical pages allocated */ atomic_t use_count; enum PcieOwner owner; unsigned long processID; -} xgi_pcie_block_t; +}; -typedef struct xgi_pcie_heap_s { +struct xgi_pcie_heap { struct list_head free_list; struct list_head used_list; struct list_head sort_list; unsigned long max_freesize; -} xgi_pcie_heap_t; +}; #endif diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 487a7e15..0e54e7d8 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -50,25 +50,25 @@ #endif /* Hardware access functions */ -static inline void OUT3C5B(xgi_info_t * info, u8 index, u8 data) +static inline void OUT3C5B(struct xgi_info * info, u8 index, u8 data) { OUTB(0x3C4, index); OUTB(0x3C5, data); } -static inline void OUT3X5B(xgi_info_t * info, u8 index, u8 data) +static inline void OUT3X5B(struct xgi_info * info, u8 index, u8 data) { OUTB(0x3D4, index); OUTB(0x3D5, data); } -static inline void OUT3CFB(xgi_info_t * info, u8 index, u8 data) +static inline void OUT3CFB(struct xgi_info * info, u8 index, u8 data) { OUTB(0x3CE, index); OUTB(0x3CF, data); } -static inline u8 IN3C5B(xgi_info_t * info, u8 index) +static inline u8 IN3C5B(struct xgi_info * info, u8 index) { volatile u8 data = 0; OUTB(0x3C4, index); @@ -76,7 +76,7 @@ static inline u8 IN3C5B(xgi_info_t * info, u8 index) return data; } -static inline u8 IN3X5B(xgi_info_t * info, u8 index) +static inline u8 IN3X5B(struct xgi_info * info, u8 index) { volatile u8 data = 0; OUTB(0x3D4, index); @@ -84,7 +84,7 @@ static inline u8 IN3X5B(xgi_info_t * info, u8 index) return data; } -static inline u8 IN3CFB(xgi_info_t * info, u8 index) +static inline u8 IN3CFB(struct xgi_info * info, u8 index) { volatile u8 data = 0; OUTB(0x3CE, index); @@ -92,25 +92,25 @@ static inline u8 IN3CFB(xgi_info_t * info, u8 index) return data; } -static inline void OUT3C5W(xgi_info_t * info, u8 index, u16 data) +static inline void OUT3C5W(struct xgi_info * info, u8 index, u16 data) { OUTB(0x3C4, index); OUTB(0x3C5, data); } -static inline void OUT3X5W(xgi_info_t * info, u8 index, u16 data) +static inline void OUT3X5W(struct xgi_info * info, u8 index, u16 data) { OUTB(0x3D4, index); OUTB(0x3D5, data); } -static inline void OUT3CFW(xgi_info_t * info, u8 index, u8 data) +static inline void OUT3CFW(struct xgi_info * info, u8 index, u8 data) { OUTB(0x3CE, index); OUTB(0x3CF, data); } -static inline u8 IN3C5W(xgi_info_t * info, u8 index) +static inline u8 IN3C5W(struct xgi_info * info, u8 index) { volatile u8 data = 0; OUTB(0x3C4, index); @@ -118,7 +118,7 @@ static inline u8 IN3C5W(xgi_info_t * info, u8 index) return data; } -static inline u8 IN3X5W(xgi_info_t * info, u8 index) +static inline u8 IN3X5W(struct xgi_info * info, u8 index) { volatile u8 data = 0; OUTB(0x3D4, index); @@ -126,7 +126,7 @@ static inline u8 IN3X5W(xgi_info_t * info, u8 index) return data; } -static inline u8 IN3CFW(xgi_info_t * info, u8 index) +static inline u8 IN3CFW(struct xgi_info * info, u8 index) { volatile u8 data = 0; OUTB(0x3CE, index); @@ -134,14 +134,14 @@ static inline u8 IN3CFW(xgi_info_t * info, u8 index) return data; } -static inline u8 readAttr(xgi_info_t * info, u8 index) +static inline u8 readAttr(struct xgi_info * info, u8 index) { INB(0x3DA); /* flip-flop to index */ OUTB(0x3C0, index); return INB(0x3C1); } -static inline void writeAttr(xgi_info_t * info, u8 index, u8 value) +static inline void writeAttr(struct xgi_info * info, u8 index, u8 value) { INB(0x3DA); /* flip-flop to index */ OUTB(0x3C0, index); @@ -151,7 +151,7 @@ static inline void writeAttr(xgi_info_t * info, u8 index, u8 value) /* * Graphic engine register (2d/3d) acessing interface */ -static inline void WriteRegDWord(xgi_info_t * info, u32 addr, u32 data) +static inline void WriteRegDWord(struct xgi_info * info, u32 addr, u32 data) { /* Jong 05/25/2006 */ XGI_INFO("Jong-WriteRegDWord()-Begin \n"); @@ -165,31 +165,31 @@ static inline void WriteRegDWord(xgi_info_t * info, u32 addr, u32 data) XGI_INFO("Jong-WriteRegDWord()-End \n"); } -static inline void WriteRegWord(xgi_info_t * info, u32 addr, u16 data) +static inline void WriteRegWord(struct xgi_info * info, u32 addr, u16 data) { *(volatile u16 *)(info->mmio.vbase + addr) = (data); } -static inline void WriteRegByte(xgi_info_t * info, u32 addr, u8 data) +static inline void WriteRegByte(struct xgi_info * info, u32 addr, u8 data) { *(volatile u8 *)(info->mmio.vbase + addr) = (data); } -static inline u32 ReadRegDWord(xgi_info_t * info, u32 addr) +static inline u32 ReadRegDWord(struct xgi_info * info, u32 addr) { volatile u32 data; data = *(volatile u32 *)(info->mmio.vbase + addr); return data; } -static inline u16 ReadRegWord(xgi_info_t * info, u32 addr) +static inline u16 ReadRegWord(struct xgi_info * info, u32 addr) { volatile u16 data; data = *(volatile u16 *)(info->mmio.vbase + addr); return data; } -static inline u8 ReadRegByte(xgi_info_t * info, u32 addr) +static inline u8 ReadRegByte(struct xgi_info * info, u32 addr) { volatile u8 data; data = *(volatile u8 *)(info->mmio.vbase + addr); @@ -197,25 +197,25 @@ static inline u8 ReadRegByte(xgi_info_t * info, u32 addr) } #if 0 -extern void OUT3C5B(xgi_info_t * info, u8 index, u8 data); -extern void OUT3X5B(xgi_info_t * info, u8 index, u8 data); -extern void OUT3CFB(xgi_info_t * info, u8 index, u8 data); -extern u8 IN3C5B(xgi_info_t * info, u8 index); -extern u8 IN3X5B(xgi_info_t * info, u8 index); -extern u8 IN3CFB(xgi_info_t * info, u8 index); -extern void OUT3C5W(xgi_info_t * info, u8 index, u8 data); -extern void OUT3X5W(xgi_info_t * info, u8 index, u8 data); -extern void OUT3CFW(xgi_info_t * info, u8 index, u8 data); -extern u8 IN3C5W(xgi_info_t * info, u8 index); -extern u8 IN3X5W(xgi_info_t * info, u8 index); -extern u8 IN3CFW(xgi_info_t * info, u8 index); - -extern void WriteRegDWord(xgi_info_t * info, u32 addr, u32 data); -extern void WriteRegWord(xgi_info_t * info, u32 addr, u16 data); -extern void WriteRegByte(xgi_info_t * info, u32 addr, u8 data); -extern u32 ReadRegDWord(xgi_info_t * info, u32 addr); -extern u16 ReadRegWord(xgi_info_t * info, u32 addr); -extern u8 ReadRegByte(xgi_info_t * info, u32 addr); +extern void OUT3C5B(struct xgi_info * info, u8 index, u8 data); +extern void OUT3X5B(struct xgi_info * info, u8 index, u8 data); +extern void OUT3CFB(struct xgi_info * info, u8 index, u8 data); +extern u8 IN3C5B(struct xgi_info * info, u8 index); +extern u8 IN3X5B(struct xgi_info * info, u8 index); +extern u8 IN3CFB(struct xgi_info * info, u8 index); +extern void OUT3C5W(struct xgi_info * info, u8 index, u8 data); +extern void OUT3X5W(struct xgi_info * info, u8 index, u8 data); +extern void OUT3CFW(struct xgi_info * info, u8 index, u8 data); +extern u8 IN3C5W(struct xgi_info * info, u8 index); +extern u8 IN3X5W(struct xgi_info * info, u8 index); +extern u8 IN3CFW(struct xgi_info * info, u8 index); + +extern void WriteRegDWord(struct xgi_info * info, u32 addr, u32 data); +extern void WriteRegWord(struct xgi_info * info, u32 addr, u16 data); +extern void WriteRegByte(struct xgi_info * info, u32 addr, u8 data); +extern u32 ReadRegDWord(struct xgi_info * info, u32 addr); +extern u16 ReadRegWord(struct xgi_info * info, u32 addr); +extern u8 ReadRegByte(struct xgi_info * info, u32 addr); extern void EnableProtect(); extern void DisableProtect(); @@ -262,19 +262,19 @@ extern void DisableProtect(); #define wReadReg(addr) ReadRegWord(info, addr) #define bReadReg(addr) ReadRegByte(info, addr) -static inline void xgi_protect_all(xgi_info_t * info) +static inline void xgi_protect_all(struct xgi_info * info) { OUTB(0x3C4, 0x11); OUTB(0x3C5, 0x92); } -static inline void xgi_unprotect_all(xgi_info_t * info) +static inline void xgi_unprotect_all(struct xgi_info * info) { OUTB(0x3C4, 0x11); OUTB(0x3C5, 0x92); } -static inline void xgi_enable_mmio(xgi_info_t * info) +static inline void xgi_enable_mmio(struct xgi_info * info) { u8 protect = 0; @@ -294,7 +294,7 @@ static inline void xgi_enable_mmio(xgi_info_t * info) OUTB(0x3C5, protect); } -static inline void xgi_disable_mmio(xgi_info_t * info) +static inline void xgi_disable_mmio(struct xgi_info * info) { u8 protect = 0; @@ -312,7 +312,7 @@ static inline void xgi_disable_mmio(xgi_info_t * info) outb(protect, 0x3C5); } -static inline void xgi_enable_ge(xgi_info_t * info) +static inline void xgi_enable_ge(struct xgi_info * info) { unsigned char bOld3cf2a = 0; int wait = 0; @@ -350,7 +350,7 @@ static inline void xgi_enable_ge(xgi_info_t * info) bOut3cf(0x2a, bOld3cf2a); } -static inline void xgi_disable_ge(xgi_info_t * info) +static inline void xgi_disable_ge(struct xgi_info * info) { int wait = 0; @@ -378,25 +378,25 @@ static inline void xgi_disable_ge(xgi_info_t * info) bOut3x5(0x36, 0); } -static inline void xgi_enable_dvi_interrupt(xgi_info_t * info) +static inline void xgi_enable_dvi_interrupt(struct xgi_info * info) { Out3cf(0x39, In3cf(0x39) & ~0x01); //Set 3cf.39 bit 0 to 0 Out3cf(0x39, In3cf(0x39) | 0x01); //Set 3cf.39 bit 0 to 1 Out3cf(0x39, In3cf(0x39) | 0x02); } -static inline void xgi_disable_dvi_interrupt(xgi_info_t * info) +static inline void xgi_disable_dvi_interrupt(struct xgi_info * info) { Out3cf(0x39, In3cf(0x39) & ~0x02); } -static inline void xgi_enable_crt1_interrupt(xgi_info_t * info) +static inline void xgi_enable_crt1_interrupt(struct xgi_info * info) { Out3cf(0x3d, In3cf(0x3d) | 0x04); Out3cf(0x3d, In3cf(0x3d) & ~0x04); Out3cf(0x3d, In3cf(0x3d) | 0x08); } -static inline void xgi_disable_crt1_interrupt(xgi_info_t * info) +static inline void xgi_disable_crt1_interrupt(struct xgi_info * info) { Out3cf(0x3d, In3cf(0x3d) & ~0x08); } -- cgit v1.2.3 From ba3173fa39e236eee9ce9abb60f1151492378811 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 16:35:36 -0700 Subject: Eliminate unused integer and float typedefs. --- linux-core/xgi_types.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_types.h b/linux-core/xgi_types.h index 65ec498b..89804667 100644 --- a/linux-core/xgi_types.h +++ b/linux-core/xgi_types.h @@ -33,27 +33,17 @@ * Typedefs * ***************************************************************************/ -typedef unsigned char V8; /* "void": enumerated or multiple fields */ -typedef unsigned short V16; /* "void": enumerated or multiple fields */ typedef unsigned char U8; /* 0 to 255 */ typedef unsigned short U16; /* 0 to 65535 */ -typedef signed char S8; /* -128 to 127 */ -typedef signed short S16; /* -32768 to 32767 */ -typedef float F32; /* IEEE Single Precision (S1E8M23) */ -typedef double F64; /* IEEE Double Precision (S1E11M52) */ typedef unsigned long BOOL; /* * mainly for 64-bit linux, where long is 64 bits * and win9x, where int is 16 bit. */ #if defined(vxworks) -typedef unsigned int V32; /* "void": enumerated or multiple fields */ typedef unsigned int U32; /* 0 to 4294967295 */ -typedef signed int S32; /* -2147483648 to 2147483647 */ #else -typedef unsigned long V32; /* "void": enumerated or multiple fields */ typedef unsigned long U32; /* 0 to 4294967295 */ -typedef signed long S32; /* -2147483648 to 2147483647 */ #endif #ifndef TRUE -- cgit v1.2.3 From 5da2a3c2d488983efed6f8433a304096e2bb75e8 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 16:37:01 -0700 Subject: Replace BOOL with bool. --- linux-core/xgi_misc.c | 14 +++++++------- linux-core/xgi_misc.h | 6 +++--- linux-core/xgi_types.h | 1 - 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 68c5ca20..280e69f1 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -111,13 +111,13 @@ void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req) static U32 s_invalid_begin = 0; -BOOL xgi_ge_irq_handler(struct xgi_info * info) +bool xgi_ge_irq_handler(struct xgi_info * info) { volatile U8 *mmio_vbase = info->mmio.vbase; volatile U32 *ge_3d_status = (volatile U32 *)(mmio_vbase + 0x2800); U32 int_status = ge_3d_status[4]; // interrupt status U32 auto_reset_count = 0; - BOOL is_support_auto_reset = FALSE; + bool is_support_auto_reset = FALSE; // Check GE on/off if (0 == (0xffffc0f0 & int_status)) { @@ -128,7 +128,7 @@ BOOL xgi_ge_irq_handler(struct xgi_info * info) ge_3d_status[0x04] = int_status | 0x04000000; if (TRUE == is_support_auto_reset) { - BOOL is_wrong_signal = FALSE; + bool is_wrong_signal = FALSE; static U32 last_int_tick_low, last_int_tick_high; static U32 new_int_tick_low; @@ -287,9 +287,9 @@ BOOL xgi_ge_irq_handler(struct xgi_info * info) return FALSE; } -BOOL xgi_crt_irq_handler(struct xgi_info * info) +bool xgi_crt_irq_handler(struct xgi_info * info) { - BOOL ret = FALSE; + bool ret = FALSE; U8 save_3ce = bReadReg(0x3ce); if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened @@ -311,9 +311,9 @@ BOOL xgi_crt_irq_handler(struct xgi_info * info) return (ret); } -BOOL xgi_dvi_irq_handler(struct xgi_info * info) +bool xgi_dvi_irq_handler(struct xgi_info * info) { - BOOL ret = FALSE; + bool ret = FALSE; U8 save_3ce = bReadReg(0x3ce); if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h index 0ebbe7e8..4b944c4c 100644 --- a/linux-core/xgi_misc.h +++ b/linux-core/xgi_misc.h @@ -39,9 +39,9 @@ extern void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req); extern int xgi_get_cpu_id(struct cpu_info *arg); extern void xgi_restore_registers(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 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_types.h b/linux-core/xgi_types.h index 89804667..6d941abe 100644 --- a/linux-core/xgi_types.h +++ b/linux-core/xgi_types.h @@ -35,7 +35,6 @@ typedef unsigned char U8; /* 0 to 255 */ typedef unsigned short U16; /* 0 to 65535 */ -typedef unsigned long BOOL; /* * mainly for 64-bit linux, where long is 64 bits * and win9x, where int is 16 bit. -- cgit v1.2.3 From ec7730e5ba6ac1d60f90af483b3966d863cb5400 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 16:37:39 -0700 Subject: Eliminate unnecessary defines of TRUE and FALSE. --- linux-core/xgi_types.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_types.h b/linux-core/xgi_types.h index 6d941abe..724f5f86 100644 --- a/linux-core/xgi_types.h +++ b/linux-core/xgi_types.h @@ -45,12 +45,4 @@ typedef unsigned int U32; /* 0 to 4294967295 */ typedef unsigned long U32; /* 0 to 4294967295 */ #endif -#ifndef TRUE -#define TRUE 1UL -#endif - -#ifndef FALSE -#define FALSE 0UL -#endif - #endif -- cgit v1.2.3 From 406ded3816300f6b3e945c932c44350b22f43bd9 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 16:41:32 -0700 Subject: Replace U(8|16) with u(8|16). --- linux-core/xgi_drv.h | 4 ++-- linux-core/xgi_misc.c | 38 +++++++++++++++++++------------------- linux-core/xgi_types.h | 2 -- 3 files changed, 21 insertions(+), 23 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 32ee5e81..8431eb16 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -96,7 +96,7 @@ struct xgi_aperture { U32 base; // pcie base is different from fb base U32 size; - U8 *vbase; + u8 *vbase; }; struct xgi_screen_info { @@ -120,7 +120,7 @@ struct xgi_info { int slot; int vendor_id; U32 device_id; - U8 revision_id; + u8 revision_id; /* physical characteristics */ struct xgi_aperture mmio; diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 280e69f1..96ad12ee 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -113,7 +113,7 @@ static U32 s_invalid_begin = 0; bool xgi_ge_irq_handler(struct xgi_info * info) { - volatile U8 *mmio_vbase = info->mmio.vbase; + volatile u8 *mmio_vbase = info->mmio.vbase; volatile U32 *ge_3d_status = (volatile U32 *)(mmio_vbase + 0x2800); U32 int_status = ge_3d_status[4]; // interrupt status U32 auto_reset_count = 0; @@ -135,11 +135,11 @@ bool xgi_ge_irq_handler(struct xgi_info * info) static U32 continoue_int_count = 0; // OE II is busy. while (old_ge_status & 0x001c0000) { - U16 check; + u16 check; // Check Read back status *(mmio_vbase + 0x235c) = 0x80; check = - *((volatile U16 *)(mmio_vbase + + *((volatile u16 *)(mmio_vbase + 0x2360)); if ((check & 0x3f) != ((check & 0x3f00) >> 8)) { @@ -149,7 +149,7 @@ bool xgi_ge_irq_handler(struct xgi_info * info) // Check RO channel *(mmio_vbase + 0x235c) = 0x83; check = - *((volatile U16 *)(mmio_vbase + + *((volatile u16 *)(mmio_vbase + 0x2360)); if ((check & 0x0f) != ((check & 0xf0) >> 4)) { @@ -159,7 +159,7 @@ bool xgi_ge_irq_handler(struct xgi_info * info) // Check RW channel *(mmio_vbase + 0x235c) = 0x88; check = - *((volatile U16 *)(mmio_vbase + + *((volatile u16 *)(mmio_vbase + 0x2360)); if ((check & 0x0f) != ((check & 0xf0) >> 4)) { @@ -169,7 +169,7 @@ bool xgi_ge_irq_handler(struct xgi_info * info) // Check RO channel outstanding *(mmio_vbase + 0x235c) = 0x8f; check = - *((volatile U16 *)(mmio_vbase + + *((volatile u16 *)(mmio_vbase + 0x2360)); if (0 != (check & 0x3ff)) { is_wrong_signal = TRUE; @@ -178,7 +178,7 @@ bool xgi_ge_irq_handler(struct xgi_info * info) // Check RW channel outstanding *(mmio_vbase + 0x235c) = 0x90; check = - *((volatile U16 *)(mmio_vbase + + *((volatile u16 *)(mmio_vbase + 0x2360)); if (0 != (check & 0x3ff)) { is_wrong_signal = TRUE; @@ -216,10 +216,10 @@ bool xgi_ge_irq_handler(struct xgi_info * info) ((--time_out) & 0xfff)) ; if (0 == time_out) { - U8 old_3ce; - U8 old_3cf; - U8 old_index; - U8 old_36; + u8 old_3ce; + u8 old_3cf; + u8 old_index; + u8 old_36; XGI_INFO ("Can not reset back 0x%lx!\n", @@ -290,12 +290,12 @@ bool xgi_ge_irq_handler(struct xgi_info * info) bool xgi_crt_irq_handler(struct xgi_info * info) { bool ret = FALSE; - U8 save_3ce = bReadReg(0x3ce); + u8 save_3ce = bReadReg(0x3ce); if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened { - U8 op3cf_3d; - U8 op3cf_37; + u8 op3cf_3d; + u8 op3cf_37; // What happened? op3cf_37 = bIn3cf(0x37); @@ -314,14 +314,14 @@ bool xgi_crt_irq_handler(struct xgi_info * info) bool xgi_dvi_irq_handler(struct xgi_info * info) { bool ret = FALSE; - U8 save_3ce = bReadReg(0x3ce); + u8 save_3ce = bReadReg(0x3ce); if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened { - U8 op3cf_39; - U8 op3cf_37; - U8 op3x5_5a; - U8 save_3x4 = bReadReg(0x3d4);; + u8 op3cf_39; + u8 op3cf_37; + u8 op3x5_5a; + u8 save_3x4 = bReadReg(0x3d4);; // What happened? op3cf_37 = bIn3cf(0x37); diff --git a/linux-core/xgi_types.h b/linux-core/xgi_types.h index 724f5f86..f9a3360c 100644 --- a/linux-core/xgi_types.h +++ b/linux-core/xgi_types.h @@ -33,8 +33,6 @@ * Typedefs * ***************************************************************************/ -typedef unsigned char U8; /* 0 to 255 */ -typedef unsigned short U16; /* 0 to 65535 */ /* * mainly for 64-bit linux, where long is 64 bits * and win9x, where int is 16 bit. -- cgit v1.2.3 From 37733786582d04f072178949cc9e31225abf5577 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 20:49:21 -0700 Subject: Delete unused arrays s_emptyBegin and s_flush2D. --- linux-core/xgi_cmdlist.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 2cdf714f..b67a40f6 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -33,20 +33,6 @@ #include "xgi_misc.h" #include "xgi_cmdlist.h" -U32 s_emptyBegin[AGPCMDLIST_BEGIN_SIZE] = { - 0x10000000, // 3D Type Begin, Invalid - 0x80000004, // Length = 4; - 0x00000000, - 0x00000000 -}; - -U32 s_flush2D[AGPCMDLIST_FLUSH_CMD_LEN] = { - FLUSH_2D, - FLUSH_2D, - FLUSH_2D, - FLUSH_2D -}; - struct xgi_cmdring_info s_cmdring; static void addFlush2D(struct xgi_info * info); -- cgit v1.2.3 From e206c4c59da0e81ed65796d543c311fc7e30b19a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:00:50 -0700 Subject: Convert some PCI-e GART related variable to generic types. A few of the PCI-e GART related fields in struct xgi_info were hardcoded to u32. None of them need to be. Convert them to either unsigned int or bool. --- linux-core/xgi_drv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 8431eb16..3cb6dc7f 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -131,10 +131,10 @@ struct xgi_info { /* look up table parameters */ U32 *lut_base; - U32 lutPageSize; - U32 lutPageOrder; - U32 isLUTInLFB; - U32 sdfbPageSize; + unsigned int lutPageSize; + unsigned int lutPageOrder; + bool isLUTInLFB; + unsigned int sdfbPageSize; U32 pcie_config; U32 pcie_status; -- cgit v1.2.3 From 4c4780bc8e5bf01b2b920c6b8de4ddbd0256c81f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:05:16 -0700 Subject: Stop-gap fix in xgi_submit_cmdlist Comment in the code explains it. Basically, I put an if-statement around a block of code to prevent a NULL pointer dereference that should never happen in the first place. Eventually, this will need to come out. --- linux-core/xgi_cmdlist.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index b67a40f6..f8aacea2 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -198,17 +198,24 @@ void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) (U32 *) xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); - lastBatchVirtAddr[1] = - BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize; - lastBatchVirtAddr[2] = pCmdInfo->_firstBeginAddr >> 4; - lastBatchVirtAddr[3] = 0; - //barrier(); - lastBatchVirtAddr[0] = - (beginPort << 22) + (BEGIN_VALID_MASK) + - (0xffff & pCmdInfo->_curDebugID); - - /* Jong 06/12/2006; system hang; marked for test */ - triggerHWCommandList(info, pCmdInfo->_beginCount); + /* lastBatchVirtAddr should *never* be NULL. However, there + * are currently some bugs that cause this to happen. The + * if-statement here prevents some fatal (i.e., hard lock + * requiring the reset button) oopses. + */ + if (lastBatchVirtAddr) { + lastBatchVirtAddr[1] = + BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize; + lastBatchVirtAddr[2] = pCmdInfo->_firstBeginAddr >> 4; + lastBatchVirtAddr[3] = 0; + //barrier(); + lastBatchVirtAddr[0] = + (beginPort << 22) + (BEGIN_VALID_MASK) + + (0xffff & pCmdInfo->_curDebugID); + + /* Jong 06/12/2006; system hang; marked for test */ + triggerHWCommandList(info, pCmdInfo->_beginCount); + } XGI_INFO ("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 - End\n"); -- cgit v1.2.3 From 4403540776c8ed3c2e28f26b6dacaab0b9e40e05 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:15:33 -0700 Subject: Clean up xgi_pcie_heap_check The whole purpose of xgi_pcie_heap_check is to log information about entries on the used_list. If XGI_DEBUG is not set, it doesn't print anything. Therefore we can #ifdef the whole function body. Convert open-code list iteration to use list_for_each_entry. --- linux-core/xgi_pcie.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index a81dbe8b..dd758013 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -347,35 +347,31 @@ int xgi_pcie_heap_init(struct xgi_info * info) void xgi_pcie_heap_check(void) { - struct list_head *useList, *temp; +#ifdef XGI_DEBUG struct xgi_pcie_block *block; unsigned int ownerIndex; -#ifdef XGI_DEBUG - char *ownerStr[6] = + static const char *const ownerStr[6] = { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; -#endif - if (xgi_pcie_heap) { - useList = &xgi_pcie_heap->used_list; - temp = useList->next; - XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); - while (temp != useList) { - block = list_entry(temp, struct xgi_pcie_block, list); - if (block->owner == PCIE_2D) - ownerIndex = 0; - else if (block->owner > PCIE_3D_TEXTURE - || block->owner < PCIE_2D - || block->owner < PCIE_3D) - ownerIndex = 5; - else - ownerIndex = block->owner - PCIE_3D + 1; - XGI_INFO - ("Allocated by %s, block->offset: 0x%lx block->size: 0x%lx \n", - ownerStr[ownerIndex], block->offset, block->size); - temp = temp->next; - } + if (!xgi_pcie_heap) { + return; + } + + XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { + if (block->owner == PCIE_2D) + ownerIndex = 0; + else if (block->owner > PCIE_3D_TEXTURE + || block->owner < PCIE_2D + || block->owner < PCIE_3D) + ownerIndex = 5; + else + ownerIndex = block->owner - PCIE_3D + 1; + XGI_INFO("Allocated by %s, block offset: 0x%lx, size: 0x%lx \n", + ownerStr[ownerIndex], block->offset, block->size); } +#endif } void xgi_pcie_heap_cleanup(struct xgi_info * info) -- cgit v1.2.3 From 32584d94e6ef7c0b463794a40541eb8183c7fb02 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:35:27 -0700 Subject: Convert open coded list iterators to either list_for_each_entry or list_for_each_entry_safe --- linux-core/xgi_fb.c | 43 +++++++---------------------- linux-core/xgi_misc.c | 39 ++++++++++++--------------- linux-core/xgi_pcie.c | 75 +++++++++++++-------------------------------------- 3 files changed, 45 insertions(+), 112 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 56cc589b..32fde5ab 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -96,7 +96,6 @@ void xgi_fb_free(struct xgi_info * info, unsigned long bus_addr) unsigned long offset = bus_addr - info->fb.base; struct xgi_mem_pid *mempid_block; struct xgi_mem_pid *mempid_freeblock = NULL; - struct list_head *mempid_list; if (offset < 0) { XGI_INFO("free onscreen frame buffer successfully !\n"); @@ -111,16 +110,12 @@ void xgi_fb_free(struct xgi_info * info, unsigned long bus_addr) } /* manage mempid */ - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) { - mempid_block = - list_entry(mempid_list, struct xgi_mem_pid, list); + list_for_each_entry(mempid_block, &xgi_mempid_list, list) { if (mempid_block->location == LOCAL && mempid_block->bus_addr == bus_addr) { mempid_freeblock = mempid_block; break; } - mempid_list = mempid_list->next; } if (mempid_freeblock) { list_del(&mempid_freeblock->list); @@ -192,20 +187,15 @@ int xgi_fb_heap_init(struct xgi_info * info) void xgi_fb_heap_cleanup(struct xgi_info * info) { - struct list_head *free_list, *temp; + struct list_head *free_list; struct xgi_mem_block *block; + struct xgi_mem_block *next; int i; if (xgi_fb_heap) { free_list = &xgi_fb_heap->free_list; for (i = 0; i < 3; i++, free_list++) { - temp = free_list->next; - while (temp != free_list) { - block = - list_entry(temp, struct xgi_mem_block, - list); - temp = temp->next; - + list_for_each_entry_safe(block, next, free_list, list) { XGI_INFO ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", i, block->offset, block->size); @@ -334,7 +324,6 @@ static void xgi_mem_delete_node(struct xgi_mem_list * list, struct xgi_mem_block static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, unsigned long originalSize) { - struct list_head *free_list; struct xgi_mem_block *block, *free_block, *used_block; unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; @@ -354,18 +343,14 @@ static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, return (NULL); } - free_list = xgi_fb_heap->free_list.next; - - while (free_list != &xgi_fb_heap->free_list) { + list_for_each_entry(block, &xgi_fb_heap->free_list, list) { XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_mem_block, list); if (size <= block->size) { break; } - free_list = free_list->next; } - if (free_list == &xgi_fb_heap->free_list) { + if (&block->list == &xgi_fb_heap->free_list) { XGI_ERROR ("Can't allocate %ldk size from frame buffer memory !\n", size / 1024); @@ -408,23 +393,19 @@ static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long offset) { - struct list_head *free_list, *used_list; - struct xgi_mem_block *used_block = NULL, *block = NULL; + struct xgi_mem_block *used_block = NULL, *block; struct xgi_mem_block *prev, *next; unsigned long upper; unsigned long lower; - used_list = xgi_fb_heap->used_list.next; - while (used_list != &xgi_fb_heap->used_list) { - block = list_entry(used_list, struct xgi_mem_block, list); + list_for_each_entry(block, &xgi_fb_heap->used_list, list) { if (block->offset == offset) { break; } - used_list = used_list->next; } - if (used_list == &xgi_fb_heap->used_list) { + if (&block->list == &xgi_fb_heap->used_list) { XGI_ERROR("can't find block: 0x%lx to free!\n", offset); return (NULL); } @@ -439,16 +420,12 @@ static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long upper = used_block->offset + used_block->size; lower = used_block->offset; - free_list = xgi_fb_heap->free_list.next; - while (free_list != &xgi_fb_heap->free_list) { - block = list_entry(free_list, struct xgi_mem_block, list); - + list_for_each_entry(block, &xgi_fb_heap->free_list, list) { if (block->offset == upper) { next = block; } else if ((block->offset + block->size) == lower) { prev = block; } - free_list = free_list->next; } XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 96ad12ee..eecd717b 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -556,50 +556,45 @@ int xgi_get_cpu_id(struct cpu_info *arg) extern struct list_head xgi_mempid_list; void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt) { - struct xgi_mem_pid *mempid_block; - struct list_head *mempid_list; + struct xgi_mem_pid *block; + struct xgi_mem_pid *next; struct task_struct *p, *find; unsigned int cnt = 0; - mempid_list = xgi_mempid_list.next; - - while (mempid_list != &xgi_mempid_list) { - mempid_block = - list_entry(mempid_list, struct xgi_mem_pid, list); - mempid_list = mempid_list->next; + list_for_each_entry_safe(block, next, &xgi_mempid_list, list) { find = NULL; XGI_SCAN_PROCESS(p) { - if (p->pid == mempid_block->pid) { + if (p->pid == block->pid) { XGI_INFO ("[!]Find active pid:%ld state:%ld location:%d addr:0x%lx! \n", - mempid_block->pid, p->state, - mempid_block->location, - mempid_block->bus_addr); + block->pid, p->state, + block->location, + block->bus_addr); find = p; - if (mempid_block->bus_addr == 0xFFFFFFFF) + if (block->bus_addr == 0xFFFFFFFF) ++cnt; break; } } if (!find) { - if (mempid_block->location == LOCAL) { + if (block->location == LOCAL) { XGI_INFO ("Memory ProcessID free fb and delete one block pid:%ld addr:0x%lx successfully! \n", - mempid_block->pid, mempid_block->bus_addr); - xgi_fb_free(info, mempid_block->bus_addr); - } else if (mempid_block->bus_addr != 0xFFFFFFFF) { + block->pid, block->bus_addr); + xgi_fb_free(info, block->bus_addr); + } else if (block->bus_addr != 0xFFFFFFFF) { XGI_INFO ("Memory ProcessID free pcie and delete one block pid:%ld addr:0x%lx successfully! \n", - mempid_block->pid, mempid_block->bus_addr); - xgi_pcie_free(info, mempid_block->bus_addr); + block->pid, block->bus_addr); + xgi_pcie_free(info, block->bus_addr); } else { /*only delete the memory block */ - list_del(&mempid_block->list); + list_del(&block->list); XGI_INFO ("Memory ProcessID delete one pcie block pid:%ld successfully! \n", - mempid_block->pid); - kfree(mempid_block); + block->pid); + kfree(block); } } } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index dd758013..e451ebd5 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -376,8 +376,9 @@ void xgi_pcie_heap_check(void) void xgi_pcie_heap_cleanup(struct xgi_info * info) { - struct list_head *free_list, *temp; + struct list_head *free_list; struct xgi_pcie_block *block; + struct xgi_pcie_block *next; int j; xgi_pcie_lut_cleanup(info); @@ -386,23 +387,16 @@ void xgi_pcie_heap_cleanup(struct xgi_info * info) if (xgi_pcie_heap) { free_list = &xgi_pcie_heap->free_list; for (j = 0; j < 3; j++, free_list++) { - temp = free_list->next; - - while (temp != free_list) { - block = - list_entry(temp, struct xgi_pcie_block, - list); + list_for_each_entry_safe(block, next, free_list, list) { XGI_INFO - ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", + ("No. %d block offset: 0x%lx size: 0x%lx\n", j, block->offset, block->size); xgi_pcie_block_stuff_free(block); block->bus_addr = 0; block->hw_addr = 0; - temp = temp->next; //XGI_INFO("No. %d free block: 0x%p \n", j, block); kmem_cache_free(xgi_pcie_cache_block, block); - block = NULL; } } @@ -421,7 +415,6 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, unsigned long originalSize, enum PcieOwner owner) { - struct list_head *free_list; struct xgi_pcie_block *block, *used_block, *free_block; struct xgi_page_block *page_block, *prev_page_block; struct page *page; @@ -475,17 +468,13 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, } /* Jong 05/30/2006; find next free list which has enough space */ - free_list = xgi_pcie_heap->free_list.next; - while (free_list != &xgi_pcie_heap->free_list) { - //XGI_INFO("free_list: 0x%px \n", free_list); - block = list_entry(free_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { if (size <= block->size) { break; } - free_list = free_list->next; } - if (free_list == &xgi_pcie_heap->free_list) { + if (&block->list == &xgi_pcie_heap->free_list) { XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", size / 1024); return (NULL); @@ -696,21 +685,17 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, unsigned long offset) { - struct list_head *free_list, *used_list; - struct xgi_pcie_block *used_block, *block = NULL; + struct xgi_pcie_block *used_block, *block; struct xgi_pcie_block *prev, *next; unsigned long upper, lower; - used_list = xgi_pcie_heap->used_list.next; - while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { if (block->offset == offset) { break; } - used_list = used_list->next; } - if (used_list == &xgi_pcie_heap->used_list) { + if (&block->list == &xgi_pcie_heap->used_list) { XGI_ERROR("can't find block: 0x%lx to free!\n", offset); return (NULL); } @@ -730,16 +715,12 @@ static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, upper = used_block->offset + used_block->size; lower = used_block->offset; - free_list = xgi_pcie_heap->free_list.next; - - while (free_list != &xgi_pcie_heap->free_list) { - block = list_entry(free_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { if (block->offset == upper) { next = block; } else if ((block->offset + block->size) == lower) { prev = block; } - free_list = free_list->next; } XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); @@ -839,7 +820,6 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) unsigned long offset = bus_addr - info->pcie.base; struct xgi_mem_pid *mempid_block; struct xgi_mem_pid *mempid_freeblock = NULL; - struct list_head *mempid_list; char isvertex = 0; int processcnt; @@ -850,15 +830,12 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) if (isvertex) { /*check is there any other process using vertex */ processcnt = 0; - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) { - mempid_block = - list_entry(mempid_list, struct xgi_mem_pid, list); + + list_for_each_entry(mempid_block, &xgi_mempid_list, list) { if (mempid_block->location == NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) { ++processcnt; } - mempid_list = mempid_list->next; } if (processcnt > 1) { return; @@ -877,17 +854,13 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) xgi_pcie_vertex_block = NULL; /* manage mempid */ - mempid_list = xgi_mempid_list.next; - while (mempid_list != &xgi_mempid_list) { - mempid_block = - list_entry(mempid_list, struct xgi_mem_pid, list); + list_for_each_entry(mempid_block, &xgi_mempid_list, list) { if (mempid_block->location == NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) { mempid_freeblock = mempid_block; break; } - mempid_list = mempid_list->next; } if (mempid_freeblock) { list_del(&mempid_freeblock->list); @@ -905,15 +878,11 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, unsigned long address) { - struct list_head *used_list; struct xgi_pcie_block *block; int i; - used_list = xgi_pcie_heap->used_list.next; - - while (used_list != &xgi_pcie_heap->used_list) { - block = list_entry(used_list, struct xgi_pcie_block, list); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { if (block->bus_addr == address) { return block; } @@ -927,7 +896,6 @@ struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, } } } - used_list = used_list->next; } XGI_ERROR("could not find map for vm 0x%lx\n", address); @@ -944,17 +912,13 @@ struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, */ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) { - struct list_head *used_list = xgi_pcie_heap->used_list.next; + struct xgi_pcie_block *block; const unsigned long offset_in_page = address & (PAGE_SIZE - 1); - XGI_INFO("begin (used_list = 0x%p, address = 0x%lx, " - "PAGE_SIZE - 1 = %lu, offset_in_page = %lu)\n", - used_list, address, PAGE_SIZE - 1, offset_in_page); - - while (used_list != &xgi_pcie_heap->used_list) { - struct xgi_pcie_block *block = - list_entry(used_list, struct xgi_pcie_block, list); + XGI_INFO("begin (address = 0x%lx, offset_in_page = %lu)\n", + address, offset_in_page); + list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", block, block->hw_addr, block->size); @@ -973,9 +937,6 @@ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) XGI_INFO("return 0x%p\n", ret); return ret; - } else { - XGI_INFO("used_list = used_list->next;\n"); - used_list = used_list->next; } } -- cgit v1.2.3 From 49ccec1b0845ea14ab2cfd2f53704fe26e38fbef Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:38:48 -0700 Subject: Convert xgi_mem_location enum values to less generic names. --- linux-core/xgi_drv.h | 6 +++--- linux-core/xgi_fb.c | 10 +++++----- linux-core/xgi_misc.c | 2 +- linux-core/xgi_pcie.c | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 3cb6dc7f..360e7120 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -158,9 +158,9 @@ struct xgi_ioctl_post_vbios { }; enum xgi_mem_location { - NON_LOCAL = 0, - LOCAL = 1, - INVALID = 0x7fffffff + XGI_MEMLOC_NON_LOCAL = 0, + XGI_MEMLOC_LOCAL = 1, + XGI_MEMLOC_INVALID = 0x7fffffff }; enum PcieOwner { diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 32fde5ab..d7e9285d 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -48,7 +48,7 @@ void xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_pid *mempid_block; if (req->is_front) { - alloc->location = LOCAL; + alloc->location = XGI_MEMLOC_LOCAL; alloc->bus_addr = info->fb.base; alloc->hw_addr = 0; XGI_INFO @@ -59,7 +59,7 @@ void xgi_fb_alloc(struct xgi_info * info, xgi_up(info->fb_sem); if (block == NULL) { - alloc->location = LOCAL; + alloc->location = XGI_MEMLOC_LOCAL; alloc->size = 0; alloc->bus_addr = 0; alloc->hw_addr = 0; @@ -67,7 +67,7 @@ void xgi_fb_alloc(struct xgi_info * info, } else { XGI_INFO("Video RAM allocation succeeded: 0x%p\n", (char *)block->offset); - alloc->location = LOCAL; + alloc->location = XGI_MEMLOC_LOCAL; alloc->size = block->size; alloc->bus_addr = info->fb.base + block->offset; alloc->hw_addr = block->offset; @@ -75,7 +75,7 @@ void xgi_fb_alloc(struct xgi_info * info, /* manage mempid */ mempid_block = kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); - mempid_block->location = LOCAL; + mempid_block->location = XGI_MEMLOC_LOCAL; mempid_block->bus_addr = alloc->bus_addr; mempid_block->pid = alloc->pid; @@ -111,7 +111,7 @@ void xgi_fb_free(struct xgi_info * info, unsigned long bus_addr) /* manage mempid */ list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == LOCAL + if (mempid_block->location == XGI_MEMLOC_LOCAL && mempid_block->bus_addr == bus_addr) { mempid_freeblock = mempid_block; break; diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index eecd717b..b7923228 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -578,7 +578,7 @@ void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt) } } if (!find) { - if (block->location == LOCAL) { + if (block->location == XGI_MEMLOC_LOCAL) { XGI_INFO ("Memory ProcessID free fb and delete one block pid:%ld addr:0x%lx successfully! \n", block->pid, block->bus_addr); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index e451ebd5..82111249 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -775,7 +775,7 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, xgi_up(info->pcie_sem); if (block == NULL) { - alloc->location = INVALID; + alloc->location = XGI_MEMLOC_INVALID; alloc->size = 0; alloc->bus_addr = 0; alloc->hw_addr = 0; @@ -784,7 +784,7 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, XGI_INFO ("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", block->offset, block->bus_addr); - alloc->location = NON_LOCAL; + alloc->location = XGI_MEMLOC_NON_LOCAL; alloc->size = block->size; alloc->bus_addr = block->bus_addr; alloc->hw_addr = block->hw_addr; @@ -799,7 +799,7 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); if (!mempid_block) XGI_ERROR("mempid_block alloc failed\n"); - mempid_block->location = NON_LOCAL; + mempid_block->location = XGI_MEMLOC_NON_LOCAL; if (owner == PCIE_3D) mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ else @@ -832,7 +832,7 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) processcnt = 0; list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == NON_LOCAL + if (mempid_block->location == XGI_MEMLOC_NON_LOCAL && mempid_block->bus_addr == 0xFFFFFFFF) { ++processcnt; } @@ -855,7 +855,7 @@ void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) /* manage mempid */ list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == NON_LOCAL + if (mempid_block->location == XGI_MEMLOC_NON_LOCAL && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) || (!isvertex && mempid_block->bus_addr == bus_addr))) { mempid_freeblock = mempid_block; -- cgit v1.2.3 From fc37781dd30b53815dd71ce576eb2147d23f0914 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 29 Jun 2007 21:48:31 -0700 Subject: Convert a few more U32 variables to more appropriate, generic types. --- linux-core/xgi_cmdlist.c | 14 +++++++------- linux-core/xgi_cmdlist.h | 2 +- linux-core/xgi_linux.h | 2 +- linux-core/xgi_misc.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index f8aacea2..04ee6e82 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -36,11 +36,11 @@ struct xgi_cmdring_info s_cmdring; static void addFlush2D(struct xgi_info * info); -static U32 getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo); +static unsigned int getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo); static void triggerHWCommandList(struct xgi_info * info, U32 triggerCounter); static void xgi_cmdlist_reset(void); -int xgi_cmdlist_initialize(struct xgi_info * info, U32 size) +int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) { //struct xgi_mem_req mem_req; struct xgi_mem_alloc mem_alloc; @@ -64,7 +64,7 @@ int xgi_cmdlist_initialize(struct xgi_info * info, U32 size) void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) { - U32 beginPort; + unsigned int beginPort; /** XGI_INFO("Jong-xgi_submit_cmdlist-Begin \n"); **/ /* Jong 05/25/2006 */ @@ -77,7 +77,7 @@ void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) /* return; */ if (s_cmdring._lastBatchStartAddr == 0) { - U32 portOffset; + unsigned int portOffset; /* Jong 06/13/2006; remove marked for system hang test */ /* xgi_waitfor_pci_idle(info); */ @@ -278,17 +278,17 @@ void xgi_cmdlist_cleanup(struct xgi_info * info) static void triggerHWCommandList(struct xgi_info * info, U32 triggerCounter) { - static U32 s_triggerID = 1; + static unsigned int s_triggerID = 1; //Fix me, currently we just trigger one time while (triggerCounter--) { dwWriteReg(BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, - 0x05000000 + (0xffff & s_triggerID++)); + 0x05000000 + (0x0ffff & s_triggerID++)); // xgi_waitfor_pci_idle(info); } } -static U32 getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo) +static unsigned int getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo) { // Convert the batch type to begin port ID switch (pCmdInfo->_firstBeginType) { diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index b11511ff..c6221511 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -65,7 +65,7 @@ struct xgi_cmdring_info { U32 _cmdRingOffset; }; -extern int xgi_cmdlist_initialize(struct xgi_info * info, U32 size); +extern int xgi_cmdlist_initialize(struct xgi_info * info, size_t size); extern void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo); diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h index 2602b0f5..99bf2d04 100644 --- a/linux-core/xgi_linux.h +++ b/linux-core/xgi_linux.h @@ -455,7 +455,7 @@ static inline void XGI_SET_PAGE_ATTRIB_CACHED(struct xgi_pte * page_ptr) struct xgi_file_private { struct xgi_info *info; - U32 num_events; + unsigned int num_events; spinlock_t fp_lock; wait_queue_head_t wait_queue; }; diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index b7923228..9bf8205b 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -109,7 +109,7 @@ void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req) */ #define STALL_INTERRUPT_RESET_THRESHOLD 0xffff -static U32 s_invalid_begin = 0; +static unsigned int s_invalid_begin = 0; bool xgi_ge_irq_handler(struct xgi_info * info) { -- cgit v1.2.3 From 2695e8e209228dfc2e6a9b10bc118d0794602b37 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 5 Jul 2007 17:18:12 -0700 Subject: Convert weird rtdsc usage to get_cycles. I'm not convinced that get_cycles is the right approach here, but it's better than the weird way that rtdsc was being used. --- linux-core/xgi_misc.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 9bf8205b..a0ed18c2 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -127,12 +127,10 @@ bool xgi_ge_irq_handler(struct xgi_info * info) // We got GE stall interrupt. ge_3d_status[0x04] = int_status | 0x04000000; - if (TRUE == is_support_auto_reset) { + if (is_support_auto_reset) { bool is_wrong_signal = FALSE; - static U32 last_int_tick_low, - last_int_tick_high; - static U32 new_int_tick_low; - static U32 continoue_int_count = 0; + static cycles_t last_tick; + static unsigned continue_int_count = 0; // OE II is busy. while (old_ge_status & 0x001c0000) { u16 check; @@ -190,19 +188,17 @@ bool xgi_ge_irq_handler(struct xgi_info * info) if (is_wrong_signal) { // Nothing but skip. - } else if (0 == continoue_int_count++) { - rdtsc(last_int_tick_low, - last_int_tick_high); + } else if (0 == continue_int_count++) { + last_tick = get_cycles(); } else { - rdtscl(new_int_tick_low); - if ((new_int_tick_low - - last_int_tick_low) > + const cycles_t new_tick = get_cycles(); + if ((new_tick - last_tick) > STALL_INTERRUPT_RESET_THRESHOLD) { - continoue_int_count = 0; - } else if (continoue_int_count >= 3) { + continue_int_count = 0; + } else if (continue_int_count >= 3) { int time_out; - continoue_int_count = 0; + continue_int_count = 0; // GE Hung up, need reset. XGI_INFO("Reset GE!\n"); -- cgit v1.2.3 From 8b18276458e93263d5d554f779227a906592ac74 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 5 Jul 2007 17:45:44 -0700 Subject: Major clean up of xgi_ge_irq_handler Two large blocks of code were moved out of this function into separate functions. This brought some much needed sanity to the indentation. Some dead varaibles were removed. --- linux-core/xgi_misc.c | 260 ++++++++++++++++++++++++-------------------------- 1 file changed, 123 insertions(+), 137 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index a0ed18c2..6cc0f107 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -111,83 +111,136 @@ void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req) 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; + + XGI_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 *mmio_vbase = info->mmio.vbase; - volatile U32 *ge_3d_status = (volatile U32 *)(mmio_vbase + 0x2800); - U32 int_status = ge_3d_status[4]; // interrupt status - U32 auto_reset_count = 0; + volatile u8 *const mmio_vbase = info->mmio.vbase; + 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 + /* Check GE on/off */ if (0 == (0xffffc0f0 & int_status)) { - U32 old_ge_status = ge_3d_status[0x00]; - U32 old_pcie_cmd_fetch_Addr = ge_3d_status[0x0a]; + u32 old_pcie_cmd_fetch_Addr = ge_3d_status[0x0a]; + if (0 != (0x1000 & int_status)) { - // We got GE stall interrupt. + /* We got GE stall interrupt. + */ ge_3d_status[0x04] = int_status | 0x04000000; if (is_support_auto_reset) { - bool is_wrong_signal = FALSE; static cycles_t last_tick; static unsigned continue_int_count = 0; - // OE II is busy. - while (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)) { - is_wrong_signal = TRUE; - break; - } - // Check RO channel - *(mmio_vbase + 0x235c) = 0x83; - check = - *((volatile u16 *)(mmio_vbase + - 0x2360)); - if ((check & 0x0f) != - ((check & 0xf0) >> 4)) { - is_wrong_signal = TRUE; - break; - } - // Check RW channel - *(mmio_vbase + 0x235c) = 0x88; - check = - *((volatile u16 *)(mmio_vbase + - 0x2360)); - if ((check & 0x0f) != - ((check & 0xf0) >> 4)) { - is_wrong_signal = TRUE; - break; - } - // Check RO channel outstanding - *(mmio_vbase + 0x235c) = 0x8f; - check = - *((volatile u16 *)(mmio_vbase + - 0x2360)); - if (0 != (check & 0x3ff)) { - is_wrong_signal = TRUE; - break; - } - // Check RW channel outstanding - *(mmio_vbase + 0x235c) = 0x90; - check = - *((volatile u16 *)(mmio_vbase + - 0x2360)); - if (0 != (check & 0x3ff)) { - is_wrong_signal = TRUE; - break; - } - // No pending PCIE request. GE stall. - break; - } - if (is_wrong_signal) { - // Nothing but skip. + /* OE II is busy. */ + + if (!xgi_validate_signal(mmio_vbase)) { + /* Nothing but skip. */ } else if (0 == continue_int_count++) { last_tick = get_cycles(); } else { @@ -196,90 +249,23 @@ bool xgi_ge_irq_handler(struct xgi_info * info) STALL_INTERRUPT_RESET_THRESHOLD) { continue_int_count = 0; } else if (continue_int_count >= 3) { - int time_out; - continue_int_count = 0; - // GE Hung up, need reset. + /* GE Hung up, need reset. */ XGI_INFO("Reset GE!\n"); - *(mmio_vbase + 0xb057) = 8; - time_out = 0xffff; - while (0 != - (ge_3d_status[0x00] & - 0xf0000000)) { - while (0 != - ((--time_out) & - 0xfff)) ; - if (0 == time_out) { - u8 old_3ce; - u8 old_3cf; - u8 old_index; - u8 old_36; - - XGI_INFO - ("Can not reset back 0x%lx!\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)) ; - *(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; - - // Increase Reset counter - auto_reset_count++; + xgi_ge_hang_reset(mmio_vbase); } } } - return TRUE; } else if (0 != (0x1 & int_status)) { s_invalid_begin++; ge_3d_status[0x04] = (int_status & ~0x01) | 0x04000000; - return TRUE; } + + return TRUE; } + return FALSE; } -- cgit v1.2.3 From 86e75b7f7f64643c6ef2c0fef353b38753df8239 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 5 Jul 2007 17:49:13 -0700 Subject: Remove XGI_IOCTL_CPUID and associated cruft. --- linux-core/xgi_drv.c | 4 ---- linux-core/xgi_drv.h | 15 +++------------ linux-core/xgi_misc.c | 12 ------------ linux-core/xgi_misc.h | 1 - 4 files changed, 3 insertions(+), 29 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 44b003a8..081db19e 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -960,10 +960,6 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, XGI_INFO("Jong-xgi_state_change \n"); xgi_state_change(info, (struct xgi_state_info *) arg_copy); break; - case XGI_ESC_CPUID: - XGI_INFO("Jong-XGI_ESC_CPUID \n"); - xgi_get_cpu_id((struct cpu_info *)arg_copy); - break; default: XGI_INFO("Jong-xgi_ioctl_default \n"); status = -EINVAL; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 360e7120..248377aa 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -234,13 +234,6 @@ struct xgi_state_info { U32 _toState; }; -struct cpu_info { - U32 _eax; - U32 _ebx; - U32 _ecx; - U32 _edx; -}; - struct xgi_mem_pid { struct list_head list; enum xgi_mem_location location; @@ -275,8 +268,7 @@ struct xgi_mem_pid { #define XGI_ESC_STATE_CHANGE (XGI_IOCTL_BASE + 17) #define XGI_ESC_MMIO_INFO (XGI_IOCTL_BASE + 18) #define XGI_ESC_PCIE_CHECK (XGI_IOCTL_BASE + 19) -#define XGI_ESC_CPUID (XGI_IOCTL_BASE + 20) -#define XGI_ESC_MEM_COLLECT (XGI_IOCTL_BASE + 21) +#define XGI_ESC_MEM_COLLECT (XGI_IOCTL_BASE + 20) #define XGI_IOCTL_DEVICE_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_DEVICE_INFO, struct xgi_chip_info) #define XGI_IOCTL_POST_VBIOS _IO(XGI_IOCTL_MAGIC, XGI_ESC_POST_VBIOS) @@ -298,12 +290,11 @@ struct xgi_mem_pid { #define XGI_IOCTL_DEBUG_INFO _IO(XGI_IOCTL_MAGIC, XGI_ESC_DEBUG_INFO) #define XGI_IOCTL_MMIO_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_MMIO_INFO, struct xgi_mmio_info) -#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, struct xgi_cmd_info) -#define XGI_IOCTL_TEST_RWINKERNEL _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_TEST_RWINKERNEL, unsigned long) +#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, struct xgi_cmd_info) +#define XGI_IOCTL_TEST_RWINKERNEL _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_TEST_RWINKERNEL, unsigned long) #define XGI_IOCTL_STATE_CHANGE _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_STATE_CHANGE, struct xgi_state_info) #define XGI_IOCTL_PCIE_CHECK _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_CHECK) -#define XGI_IOCTL_CPUID _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_CPUID, struct cpu_info) #define XGI_IOCTL_MAXNR 30 /* diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 6cc0f107..9712241f 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -521,18 +521,6 @@ void xgi_waitfor_pci_idle(struct xgi_info * info) } } -int xgi_get_cpu_id(struct cpu_info *arg) -{ - int op = arg->_eax; - __asm__("cpuid":"=a"(arg->_eax), - "=b"(arg->_ebx), - "=c"(arg->_ecx), "=d"(arg->_edx) - : "0"(op)); - - XGI_INFO - ("opCode = 0x%x, eax = 0x%x, ebx = 0x%x, ecx = 0x%x, edx = 0x%x \n", - op, arg->_eax, arg->_ebx, arg->_ecx, arg->_edx); -} /*memory collect function*/ extern struct list_head xgi_mempid_list; diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h index 4b944c4c..85cfbf2b 100644 --- a/linux-core/xgi_misc.h +++ b/linux-core/xgi_misc.h @@ -36,7 +36,6 @@ extern void xgi_get_screen_info(struct xgi_info * info, struct xgi_screen_info * extern void xgi_put_screen_info(struct xgi_info * info, struct xgi_screen_info * req); extern void xgi_ge_reset(struct xgi_info * info); extern void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req); -extern int xgi_get_cpu_id(struct cpu_info *arg); extern void xgi_restore_registers(struct xgi_info * info); extern bool xgi_ge_irq_handler(struct xgi_info * info); -- cgit v1.2.3 From 2f2d8b9688743ac6367bf13c3c023310a257ceb7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 15:59:09 -0700 Subject: Merge xgi_mem_req and xgi_mem_alloc into a single type. These two structures were used as the request and reply for certain ioctls. Having a different type for an ioctl's input and output is just wierd. In addition, each structure contained fields (e.g., pid) that had no business being there. This change requires updates to user-space. --- linux-core/xgi_cmdlist.c | 10 +++++----- linux-core/xgi_drv.c | 7 ++----- linux-core/xgi_drv.h | 37 +++++++++++++++++++------------------ linux-core/xgi_fb.c | 10 +++++----- linux-core/xgi_pcie.c | 25 ++++++++----------------- 5 files changed, 39 insertions(+), 50 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 04ee6e82..f7730d89 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -42,12 +42,12 @@ static void xgi_cmdlist_reset(void); int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) { - //struct xgi_mem_req mem_req; - struct xgi_mem_alloc mem_alloc; + struct xgi_mem_alloc mem_alloc = { + .size = size, + .owner = PCIE_2D, + }; - //mem_req.size = size; - - xgi_pcie_alloc(info, size, PCIE_2D, &mem_alloc); + xgi_pcie_alloc(info, &mem_alloc, 0); if ((mem_alloc.size == 0) && (mem_alloc.hw_addr == 0)) { return -1; diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 081db19e..3608c747 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -894,7 +894,7 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, break; case XGI_ESC_FB_ALLOC: XGI_INFO("Jong-xgi_ioctl_fb_alloc \n"); - xgi_fb_alloc(info, (struct xgi_mem_req *)arg_copy, alloc); + xgi_fb_alloc(info, alloc, 0); break; case XGI_ESC_FB_FREE: XGI_INFO("Jong-xgi_ioctl_fb_free \n"); @@ -906,8 +906,7 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, break; case XGI_ESC_PCIE_ALLOC: XGI_INFO("Jong-xgi_ioctl_pcie_alloc \n"); - xgi_pcie_alloc(info, ((struct xgi_mem_req *) arg_copy)->size, - ((struct xgi_mem_req *) arg_copy)->owner, alloc); + xgi_pcie_alloc(info, alloc, 0); break; case XGI_ESC_PCIE_FREE: XGI_INFO("Jong-xgi_ioctl_pcie_free: bus_addr = 0x%lx \n", @@ -945,8 +944,6 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, case XGI_ESC_DEBUG_INFO: XGI_INFO("Jong-xgi_ioctl_restore_registers \n"); xgi_restore_registers(info); - //xgi_write_pcie_mem(info, (struct xgi_mem_req *) arg_copy); - //xgi_read_pcie_mem(info, (struct xgi_mem_req *) arg_copy); break; case XGI_ESC_SUBMIT_CMDLIST: XGI_INFO("Jong-xgi_ioctl_submit_cmdlist \n"); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 248377aa..361a1e96 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -177,19 +177,23 @@ enum PcieOwner { }; struct xgi_mem_req { - enum xgi_mem_location location; - unsigned long size; - unsigned long is_front; - enum PcieOwner owner; - unsigned long pid; }; struct xgi_mem_alloc { - enum xgi_mem_location location; - unsigned long size; + 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; + + /** + * Physical address of the memory from the processor's point of view. + */ unsigned long bus_addr; - unsigned long hw_addr; - unsigned long pid; }; struct xgi_chip_info { @@ -274,11 +278,11 @@ struct xgi_mem_pid { #define XGI_IOCTL_POST_VBIOS _IO(XGI_IOCTL_MAGIC, XGI_ESC_POST_VBIOS) #define XGI_IOCTL_FB_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_FB_INIT) -#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, struct xgi_mem_req) +#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, struct xgi_mem_alloc) #define XGI_IOCTL_FB_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_FB_FREE, unsigned long) #define XGI_IOCTL_PCIE_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_INIT) -#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, struct xgi_mem_req) +#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, struct xgi_mem_alloc) #define XGI_IOCTL_PCIE_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_FREE, unsigned long) #define XGI_IOCTL_PUT_SCREEN_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PUT_SCREEN_INFO, struct xgi_screen_info) @@ -332,25 +336,22 @@ struct xgi_mem_pid { extern int xgi_fb_heap_init(struct xgi_info * info); extern void xgi_fb_heap_cleanup(struct xgi_info * info); -extern void xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_req * req, - struct xgi_mem_alloc * alloc); +extern void xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, + pid_t pid); extern void xgi_fb_free(struct xgi_info * info, unsigned long offset); extern void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt); extern int xgi_pcie_heap_init(struct xgi_info * info); extern void xgi_pcie_heap_cleanup(struct xgi_info * info); -extern void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, - enum PcieOwner owner, struct xgi_mem_alloc * alloc); +extern void xgi_pcie_alloc(struct xgi_info * info, + struct xgi_mem_alloc * alloc, pid_t pid); extern void xgi_pcie_free(struct xgi_info * info, unsigned long offset); extern void xgi_pcie_heap_check(void); extern struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, unsigned long address); extern void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address); -extern void xgi_read_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req); -extern void xgi_write_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req); - extern void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address); #endif diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index d7e9285d..ac73b41a 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -41,13 +41,13 @@ static struct xgi_mem_block *xgi_mem_new_node(void); static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, unsigned long size); static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long offset); -void xgi_fb_alloc(struct xgi_info * info, - struct xgi_mem_req * req, struct xgi_mem_alloc * alloc) +void xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, + pid_t pid) { struct xgi_mem_block *block; struct xgi_mem_pid *mempid_block; - if (req->is_front) { + if (alloc->is_front) { alloc->location = XGI_MEMLOC_LOCAL; alloc->bus_addr = info->fb.base; alloc->hw_addr = 0; @@ -55,7 +55,7 @@ void xgi_fb_alloc(struct xgi_info * info, ("Video RAM allocation on front buffer successfully! \n"); } else { xgi_down(info->fb_sem); - block = xgi_mem_alloc(info, req->size); + block = xgi_mem_alloc(info, alloc->size); xgi_up(info->fb_sem); if (block == NULL) { @@ -77,7 +77,7 @@ void xgi_fb_alloc(struct xgi_info * info, kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); mempid_block->location = XGI_MEMLOC_LOCAL; mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = alloc->pid; + mempid_block->pid = pid; if (!mempid_block) XGI_ERROR("mempid_block alloc failed\n"); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 82111249..0f82e4ec 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -764,14 +764,13 @@ static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, return (used_block); } -void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, - enum PcieOwner owner, struct xgi_mem_alloc * alloc) +void xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, + pid_t pid) { struct xgi_pcie_block *block; - struct xgi_mem_pid *mempid_block; xgi_down(info->pcie_sem); - block = xgi_pcie_mem_alloc(info, size, owner); + block = xgi_pcie_mem_alloc(info, alloc->size, alloc->owner); xgi_up(info->pcie_sem); if (block == NULL) { @@ -794,17 +793,18 @@ void xgi_pcie_alloc(struct xgi_info * info, unsigned long size, PCIE_3D request means a opengl process created. PCIE_3D_TEXTURE request means texture cannot alloc from fb. */ - if (owner == PCIE_3D || owner == PCIE_3D_TEXTURE) { - mempid_block = + if ((alloc->owner == PCIE_3D) + || (alloc->owner == PCIE_3D_TEXTURE)) { + struct xgi_mem_pid *mempid_block = kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); if (!mempid_block) XGI_ERROR("mempid_block alloc failed\n"); mempid_block->location = XGI_MEMLOC_NON_LOCAL; - if (owner == PCIE_3D) + if (alloc->owner == PCIE_3D) mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ else mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = alloc->pid; + mempid_block->pid = pid; XGI_INFO ("Memory ProcessID add one pcie block pid:%ld successfully! \n", @@ -944,15 +944,6 @@ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) return NULL; } -void xgi_read_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) -{ - -} - -void xgi_write_pcie_mem(struct xgi_info * info, struct xgi_mem_req * req) -{ -} - /* address -- GE hw address */ -- cgit v1.2.3 From a3f56dc3d0620633c7719a01e6e578661d65edfc Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 16:07:27 -0700 Subject: Adjust the types of the fields of xgi_aperture. --- linux-core/xgi_drv.c | 10 ++++------ linux-core/xgi_drv.h | 6 +++--- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 3608c747..2f0218e8 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -252,8 +252,7 @@ int xgi_kern_probe(struct pci_dev *dev, const struct pci_device_id *id_table) 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 = (unsigned char *)ioremap_nocache(info->mmio.base, - 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"); @@ -282,8 +281,7 @@ int xgi_kern_probe(struct pci_dev *dev, const struct pci_device_id *id_table) goto error_disable_dev; } - info->fb.vbase = (unsigned char *)ioremap_nocache(info->fb.base, - info->fb.size); + info->fb.vbase = ioremap_nocache(info->fb.base, info->fb.size); if (!info->fb.vbase) { @@ -1484,11 +1482,11 @@ void __exit xgi_exit_module(void) xgi_cmdlist_cleanup(&xgi_devices[i]); if (xgi_devices[i].fb.vbase != NULL) { - iounmap((void *)xgi_devices[i].fb.vbase); + iounmap(xgi_devices[i].fb.vbase); xgi_devices[i].fb.vbase = NULL; } if (xgi_devices[i].mmio.vbase != NULL) { - iounmap((void *)xgi_devices[i].mmio.vbase); + 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); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 361a1e96..6bd04cd9 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -94,9 +94,9 @@ #define XGI_CONTROL_DEVICE_NUMBER 100 struct xgi_aperture { - U32 base; // pcie base is different from fb base - U32 size; - u8 *vbase; + unsigned long base; + unsigned int size; + void *vbase; }; struct xgi_screen_info { -- cgit v1.2.3 From 7268b65d5ce804713c12b8fadc42f9a086cdfe14 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 16:22:48 -0700 Subject: Correct types that are shared with user mode. --- linux-core/xgi_cmdlist.c | 6 +++-- linux-core/xgi_drv.h | 63 +++++++++++++++++++++--------------------------- linux-core/xgi_misc.c | 2 +- 3 files changed, 33 insertions(+), 38 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index f7730d89..ee53d30c 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -37,7 +37,8 @@ struct xgi_cmdring_info s_cmdring; static void addFlush2D(struct xgi_info * info); static unsigned int getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo); -static void triggerHWCommandList(struct xgi_info * info, U32 triggerCounter); +static void triggerHWCommandList(struct xgi_info * info, + unsigned int triggerCounter); static void xgi_cmdlist_reset(void); int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) @@ -276,7 +277,8 @@ void xgi_cmdlist_cleanup(struct xgi_info * info) } } -static void triggerHWCommandList(struct xgi_info * info, U32 triggerCounter) +static void triggerHWCommandList(struct xgi_info * info, + unsigned int triggerCounter) { static unsigned int s_triggerID = 1; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 6bd04cd9..f1cfa44e 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -100,16 +100,16 @@ struct xgi_aperture { }; struct xgi_screen_info { - U32 scrn_start; - U32 scrn_xres; - U32 scrn_yres; - U32 scrn_bpp; - U32 scrn_pitch; + unsigned int scrn_start; + unsigned int scrn_xres; + unsigned int scrn_yres; + unsigned int scrn_bpp; + unsigned int scrn_pitch; }; struct xgi_sarea_info { - U32 bus_addr; - U32 size; + unsigned long bus_addr; + unsigned int size; }; struct xgi_info { @@ -153,8 +153,8 @@ struct xgi_info { }; struct xgi_ioctl_post_vbios { - U32 bus; - U32 slot; + unsigned int bus; + unsigned int slot; }; enum xgi_mem_location { @@ -176,9 +176,6 @@ enum PcieOwner { PCIE_INVALID = 0x7fffffff }; -struct xgi_mem_req { -}; - struct xgi_mem_alloc { unsigned int location; unsigned int size; @@ -197,45 +194,41 @@ struct xgi_mem_alloc { }; struct xgi_chip_info { - U32 device_id; - char device_name[32]; - U32 vendor_id; - U32 curr_display_mode; //Singe, DualView(Contained), MHS - U32 fb_size; - U32 sarea_bus_addr; - U32 sarea_size; -}; + u16 device_id; + u16 vendor_id; -struct xgi_opengl_cmd { - U32 cmd; + char device_name[32]; + unsigned int curr_display_mode; //Singe, DualView(Contained), MHS + unsigned int fb_size; + unsigned long sarea_bus_addr; + unsigned int sarea_size; }; struct xgi_mmio_info { - struct xgi_opengl_cmd cmd_head; - void *mmioBase; - int size; + unsigned long mmio_base; + unsigned int size; }; -typedef enum { +enum xgi_batch_type { BTYPE_2D = 0, BTYPE_3D = 1, BTYPE_FLIP = 2, BTYPE_CTRL = 3, BTYPE_NONE = 0x7fffffff -} BATCH_TYPE; +}; struct xgi_cmd_info { - BATCH_TYPE _firstBeginType; - U32 _firstBeginAddr; - U32 _firstSize; - U32 _curDebugID; - U32 _lastBeginAddr; - U32 _beginCount; + unsigned int _firstBeginType; + u32 _firstBeginAddr; + u32 _firstSize; + u32 _curDebugID; + u32 _lastBeginAddr; + unsigned int _beginCount; }; struct xgi_state_info { - U32 _fromState; - U32 _toState; + unsigned int _fromState; + unsigned int _toState; }; struct xgi_mem_pid { diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 9712241f..9c9fd38f 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -48,7 +48,7 @@ void xgi_get_device_info(struct xgi_info * info, struct xgi_chip_info * req) void xgi_get_mmio_info(struct xgi_info * info, struct xgi_mmio_info * req) { - req->mmioBase = (void *)info->mmio.base; + req->mmio_base = info->mmio.base; req->size = info->mmio.size; } -- cgit v1.2.3 From 1f4e24b429789710f5d69fc78335f20c023569bb Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 16:33:14 -0700 Subject: Move types shared with user mode to xgi_drm.h. --- linux-core/xgi_drm.h | 1 + linux-core/xgi_drv.h | 131 +-------------------------------------------------- 2 files changed, 3 insertions(+), 129 deletions(-) create mode 120000 linux-core/xgi_drm.h (limited to 'linux-core') diff --git a/linux-core/xgi_drm.h b/linux-core/xgi_drm.h new file mode 120000 index 00000000..677586d7 --- /dev/null +++ b/linux-core/xgi_drm.h @@ -0,0 +1 @@ +../shared-core/xgi_drm.h \ No newline at end of file diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index f1cfa44e..803ed9c1 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -29,6 +29,8 @@ #ifndef _XGI_DRV_H_ #define _XGI_DRV_H_ +#include "xgi_drm.h" + #define XGI_MAJOR_VERSION 0 #define XGI_MINOR_VERSION 7 #define XGI_PATCHLEVEL 5 @@ -99,19 +101,6 @@ struct xgi_aperture { void *vbase; }; -struct xgi_screen_info { - unsigned int scrn_start; - unsigned int scrn_xres; - unsigned int scrn_yres; - unsigned int scrn_bpp; - unsigned int scrn_pitch; -}; - -struct xgi_sarea_info { - unsigned long bus_addr; - unsigned int size; -}; - struct xgi_info { struct pci_dev *dev; int flags; @@ -157,12 +146,6 @@ struct xgi_ioctl_post_vbios { unsigned int slot; }; -enum xgi_mem_location { - XGI_MEMLOC_NON_LOCAL = 0, - XGI_MEMLOC_LOCAL = 1, - XGI_MEMLOC_INVALID = 0x7fffffff -}; - enum PcieOwner { PCIE_2D = 0, /* @@ -176,61 +159,6 @@ enum PcieOwner { PCIE_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; - - /** - * Physical address of the memory from the processor's point of view. - */ - unsigned long bus_addr; -}; - -struct xgi_chip_info { - u16 device_id; - u16 vendor_id; - - char device_name[32]; - unsigned int curr_display_mode; //Singe, DualView(Contained), MHS - unsigned int fb_size; - unsigned long sarea_bus_addr; - unsigned int sarea_size; -}; - -struct xgi_mmio_info { - unsigned long mmio_base; - unsigned int size; -}; - -enum xgi_batch_type { - BTYPE_2D = 0, - BTYPE_3D = 1, - BTYPE_FLIP = 2, - BTYPE_CTRL = 3, - BTYPE_NONE = 0x7fffffff -}; - -struct xgi_cmd_info { - unsigned int _firstBeginType; - u32 _firstBeginAddr; - u32 _firstSize; - u32 _curDebugID; - u32 _lastBeginAddr; - unsigned int _beginCount; -}; - -struct xgi_state_info { - unsigned int _fromState; - unsigned int _toState; -}; - struct xgi_mem_pid { struct list_head list; enum xgi_mem_location location; @@ -238,61 +166,6 @@ struct xgi_mem_pid { unsigned long pid; }; -/* - * Ioctl definitions - */ - -#define XGI_IOCTL_MAGIC 'x' /* use 'x' as magic number */ - -#define XGI_IOCTL_BASE 0 -#define XGI_ESC_DEVICE_INFO (XGI_IOCTL_BASE + 0) -#define XGI_ESC_POST_VBIOS (XGI_IOCTL_BASE + 1) - -#define XGI_ESC_FB_INIT (XGI_IOCTL_BASE + 2) -#define XGI_ESC_FB_ALLOC (XGI_IOCTL_BASE + 3) -#define XGI_ESC_FB_FREE (XGI_IOCTL_BASE + 4) -#define XGI_ESC_PCIE_INIT (XGI_IOCTL_BASE + 5) -#define XGI_ESC_PCIE_ALLOC (XGI_IOCTL_BASE + 6) -#define XGI_ESC_PCIE_FREE (XGI_IOCTL_BASE + 7) -#define XGI_ESC_SUBMIT_CMDLIST (XGI_IOCTL_BASE + 8) -#define XGI_ESC_PUT_SCREEN_INFO (XGI_IOCTL_BASE + 9) -#define XGI_ESC_GET_SCREEN_INFO (XGI_IOCTL_BASE + 10) -#define XGI_ESC_GE_RESET (XGI_IOCTL_BASE + 11) -#define XGI_ESC_SAREA_INFO (XGI_IOCTL_BASE + 12) -#define XGI_ESC_DUMP_REGISTER (XGI_IOCTL_BASE + 13) -#define XGI_ESC_DEBUG_INFO (XGI_IOCTL_BASE + 14) -#define XGI_ESC_TEST_RWINKERNEL (XGI_IOCTL_BASE + 16) -#define XGI_ESC_STATE_CHANGE (XGI_IOCTL_BASE + 17) -#define XGI_ESC_MMIO_INFO (XGI_IOCTL_BASE + 18) -#define XGI_ESC_PCIE_CHECK (XGI_IOCTL_BASE + 19) -#define XGI_ESC_MEM_COLLECT (XGI_IOCTL_BASE + 20) - -#define XGI_IOCTL_DEVICE_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_DEVICE_INFO, struct xgi_chip_info) -#define XGI_IOCTL_POST_VBIOS _IO(XGI_IOCTL_MAGIC, XGI_ESC_POST_VBIOS) - -#define XGI_IOCTL_FB_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_FB_INIT) -#define XGI_IOCTL_FB_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_FB_ALLOC, struct xgi_mem_alloc) -#define XGI_IOCTL_FB_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_FB_FREE, unsigned long) - -#define XGI_IOCTL_PCIE_INIT _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_INIT) -#define XGI_IOCTL_PCIE_ALLOC _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_ALLOC, struct xgi_mem_alloc) -#define XGI_IOCTL_PCIE_FREE _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_FREE, unsigned long) - -#define XGI_IOCTL_PUT_SCREEN_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_PUT_SCREEN_INFO, struct xgi_screen_info) -#define XGI_IOCTL_GET_SCREEN_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_GET_SCREEN_INFO, struct xgi_screen_info) - -#define XGI_IOCTL_GE_RESET _IO(XGI_IOCTL_MAGIC, XGI_ESC_GE_RESET) -#define XGI_IOCTL_SAREA_INFO _IOW(XGI_IOCTL_MAGIC, XGI_ESC_SAREA_INFO, struct xgi_sarea_info) -#define XGI_IOCTL_DUMP_REGISTER _IO(XGI_IOCTL_MAGIC, XGI_ESC_DUMP_REGISTER) -#define XGI_IOCTL_DEBUG_INFO _IO(XGI_IOCTL_MAGIC, XGI_ESC_DEBUG_INFO) -#define XGI_IOCTL_MMIO_INFO _IOR(XGI_IOCTL_MAGIC, XGI_ESC_MMIO_INFO, struct xgi_mmio_info) - -#define XGI_IOCTL_SUBMIT_CMDLIST _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_SUBMIT_CMDLIST, struct xgi_cmd_info) -#define XGI_IOCTL_TEST_RWINKERNEL _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_TEST_RWINKERNEL, unsigned long) -#define XGI_IOCTL_STATE_CHANGE _IOWR(XGI_IOCTL_MAGIC, XGI_ESC_STATE_CHANGE, struct xgi_state_info) - -#define XGI_IOCTL_PCIE_CHECK _IO(XGI_IOCTL_MAGIC, XGI_ESC_PCIE_CHECK) -#define XGI_IOCTL_MAXNR 30 /* * flags -- cgit v1.2.3 From 5c481d0a4284ec7311a47fbeab1680d007769668 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 16:43:48 -0700 Subject: Eliminiate fields in xgi_info that are duplicates of fields in pci_dev. --- linux-core/xgi_drv.c | 51 ++++++++++++++------------------------------------- linux-core/xgi_drv.h | 10 ++-------- linux-core/xgi_misc.c | 4 ++-- 3 files changed, 18 insertions(+), 47 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 2f0218e8..c4cc8900 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -233,10 +233,6 @@ int xgi_kern_probe(struct pci_dev *dev, const struct pci_device_id *id_table) info = &xgi_devices[xgi_num_devices]; info->dev = dev; - info->vendor_id = dev->vendor; - info->device_id = dev->device; - info->bus = dev->bus->number; - info->slot = PCI_SLOT((dev)->devfn); xgi_lock_init(info); @@ -294,14 +290,13 @@ int xgi_kern_probe(struct pci_dev *dev, const struct pci_device_id *id_table) info->fb.vbase = NULL; XGI_INFO("info->fb.vbase: 0x%p \n", info->fb.vbase); - info->irq = dev->irq; /* check common error condition */ - if (info->irq == 0) { + 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->irq); + XGI_INFO("info->irq: %lx \n", info->dev->irq); //xgi_enable_dvi_interrupt(info); @@ -568,21 +563,21 @@ int xgi_kern_open(struct inode *inode, struct file *filp) if (!(info->flags & XGI_FLAG_OPEN)) { XGI_INFO("info->flags & XGI_FLAG_OPEN \n"); - if (info->device_id == 0) { + 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->irq, xgi_kern_isr, + status = request_irq(info->dev->irq, xgi_kern_isr, SA_INTERRUPT | SA_SHIRQ, "xgi", (void *)info); if (status != 0) { - if (info->irq && (status == -EBUSY)) { + if (info->dev->irq && (status == -EBUSY)) { XGI_ERROR ("Tried to get irq %d, but another driver", - (unsigned int)info->irq); + (unsigned int)info->dev->irq); XGI_ERROR("has it and is not sharing it.\n"); } XGI_ERROR("isr request failed 0x%x\n", status); @@ -651,7 +646,7 @@ int xgi_kern_release(struct inode *inode, struct file *filp) * Free the IRQ, which may block until all pending interrupt processing * has completed. */ - free_irq(info->irq, (void *)info); + free_irq(info->dev->irq, (void *)info); xgi_cmdlist_cleanup(info); @@ -1064,21 +1059,6 @@ static u8 xgi_find_pcie_capability(struct pci_dev *dev) return 0; } -static struct pci_dev *xgi_get_pci_device(struct xgi_info * info) -{ - struct pci_dev *dev; - - dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, NULL); - while (dev) { - if (XGI_PCI_SLOT_NUMBER(dev) == info->slot - && XGI_PCI_BUS_NUMBER(dev) == info->bus) - return dev; - dev = XGI_PCI_GET_DEVICE(info->vendor_id, info->device_id, dev); - } - - return NULL; -} - int xgi_kern_read_card_info(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -1089,7 +1069,7 @@ int xgi_kern_read_card_info(char *page, char **start, off_t off, struct xgi_info *info; info = (struct xgi_info *) data; - dev = xgi_get_pci_device(info); + dev = info->dev; if (!dev) return 0; @@ -1162,13 +1142,10 @@ static void xgi_proc_create(void) xgi_max_devices = xgi_devices + XGI_MAX_DEVICES; for (info = xgi_devices; info < xgi_max_devices; info++) { - if (info->device_id == 0) - break; - /* world readable file */ flags = S_IFREG | S_IRUGO; - dev = xgi_get_pci_device(info); + dev = info->dev; if (!dev) break; @@ -1314,19 +1291,19 @@ static void xgi_dev_init(struct xgi_info * info) for (dev = xgidev_list; dev->vendor; dev++) { if ((dev->vendor == pdev->vendor) && (dev->device == pdev->device)) { + u8 rev_id; + XGI_INFO("dev->vendor = pdev->vendor= %x \n", dev->vendor); XGI_INFO("dev->device = pdev->device= %x \n", dev->device); - xgi_devices[found].device_id = pdev->device; + xgi_devices[found].dev = pdev; pci_read_config_byte(pdev, PCI_REVISION_ID, - &xgi_devices[found]. - revision_id); + rev_id); - XGI_INFO("PCI_REVISION_ID= %x \n", - xgi_devices[found].revision_id); + XGI_INFO("PCI_REVISION_ID= %x \n", rev_id); pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 803ed9c1..efbbd647 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -105,11 +105,6 @@ struct xgi_info { struct pci_dev *dev; int flags; int device_number; - int bus; /* PCI config info */ - int slot; - int vendor_id; - U32 device_id; - u8 revision_id; /* physical characteristics */ struct xgi_aperture mmio; @@ -125,9 +120,8 @@ struct xgi_info { bool isLUTInLFB; unsigned int sdfbPageSize; - U32 pcie_config; - U32 pcie_status; - U32 irq; + u32 pcie_config; + u32 pcie_status; atomic_t use_count; diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 9c9fd38f..d3385bef 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -34,12 +34,12 @@ void xgi_get_device_info(struct xgi_info * info, struct xgi_chip_info * req) { - req->device_id = info->device_id; + req->device_id = info->dev->device; req->device_name[0] = 'x'; req->device_name[1] = 'g'; req->device_name[2] = '4'; req->device_name[3] = '7'; - req->vendor_id = info->vendor_id; + req->vendor_id = info->dev->vendor; req->curr_display_mode = 0; req->fb_size = info->fb.size; req->sarea_bus_addr = info->sarea_info.bus_addr; -- cgit v1.2.3 From 76ca1e858fb8e1a65ea49c0c62350d7ca91044a2 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 9 Jul 2007 18:54:25 -0700 Subject: Convert occurances of U32 to other types. Most occurances of U32 were converted to u32. These are cases where the data represents something that will be written to the hardware. Other cases were converted to 'unsigned int'. U32 was the last type in xgi_types.h, so that file is removed. --- linux-core/xgi_cmdlist.c | 20 +++++++++----------- linux-core/xgi_cmdlist.h | 10 +++++----- linux-core/xgi_drv.c | 1 - linux-core/xgi_drv.h | 2 +- linux-core/xgi_fb.c | 1 - linux-core/xgi_misc.c | 1 - linux-core/xgi_pcie.c | 3 +-- linux-core/xgi_types.h | 46 ---------------------------------------------- 8 files changed, 16 insertions(+), 68 deletions(-) delete mode 100644 linux-core/xgi_types.h (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index ee53d30c..7be0ac48 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -26,7 +26,6 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_types.h" #include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" @@ -183,7 +182,7 @@ void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) /* Jong 06/13/2006; remove marked for system hang test */ /* xgi_waitfor_pci_idle(info); */ } else { - U32 *lastBatchVirtAddr; + u32 *lastBatchVirtAddr; XGI_INFO ("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 \n"); @@ -195,9 +194,9 @@ void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) addFlush2D(info); } - lastBatchVirtAddr = - (U32 *) xgi_find_pcie_virt(info, - s_cmdring._lastBatchStartAddr); + lastBatchVirtAddr = + xgi_find_pcie_virt(info, + s_cmdring._lastBatchStartAddr); /* lastBatchVirtAddr should *never* be NULL. However, there * are currently some bugs that cause this to happen. The @@ -310,10 +309,9 @@ static unsigned int getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo) static void addFlush2D(struct xgi_info * info) { - U32 *flushBatchVirtAddr; - U32 flushBatchHWAddr; - - U32 *lastBatchVirtAddr; + u32 *flushBatchVirtAddr; + u32 flushBatchHWAddr; + u32 *lastBatchVirtAddr; /* check buf is large enough to contain a new flush batch */ if ((s_cmdring._cmdRingOffset + 0x20) >= s_cmdring._cmdRingSize) { @@ -321,7 +319,7 @@ static void addFlush2D(struct xgi_info * info) } flushBatchHWAddr = s_cmdring._cmdRingBuffer + s_cmdring._cmdRingOffset; - flushBatchVirtAddr = (U32 *) xgi_find_pcie_virt(info, flushBatchHWAddr); + flushBatchVirtAddr = xgi_find_pcie_virt(info, flushBatchHWAddr); /* not using memcpy for I assume the address is discrete */ *(flushBatchVirtAddr + 0) = 0x10000000; @@ -335,7 +333,7 @@ static void addFlush2D(struct xgi_info * info) // ASSERT(s_cmdring._lastBatchStartAddr != NULL); lastBatchVirtAddr = - (U32 *) xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); + xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; lastBatchVirtAddr[2] = flushBatchHWAddr >> 4; diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index c6221511..d2b95c0e 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -58,11 +58,11 @@ typedef enum { } CMD_SIZE; struct xgi_cmdring_info { - U32 _cmdRingSize; - U32 _cmdRingBuffer; - U32 _cmdRingBusAddr; - U32 _lastBatchStartAddr; - U32 _cmdRingOffset; + unsigned int _cmdRingSize; + u32 _cmdRingBuffer; + unsigned long _cmdRingBusAddr; + u32 _lastBatchStartAddr; + u32 _cmdRingOffset; }; extern int xgi_cmdlist_initialize(struct xgi_info * info, size_t size); diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index c4cc8900..b3425c75 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -25,7 +25,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_types.h" #include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index efbbd647..983ed0a9 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -114,7 +114,7 @@ struct xgi_info { struct xgi_sarea_info sarea_info; /* look up table parameters */ - U32 *lut_base; + u32 *lut_base; unsigned int lutPageSize; unsigned int lutPageOrder; bool isLUTInLFB; diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index ac73b41a..7d390d4b 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -26,7 +26,6 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_types.h" #include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_fb.h" diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index d3385bef..2d310a2f 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -26,7 +26,6 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_types.h" #include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 0f82e4ec..70459b2c 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -26,7 +26,6 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_types.h" #include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" @@ -420,7 +419,7 @@ static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, struct page *page; unsigned long page_order = 0, count = 0, index = 0; unsigned long page_addr = 0; - unsigned long *lut_addr = NULL; + u32 *lut_addr = NULL; unsigned long lut_id = 0; unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; int i, j, page_count = 0; diff --git a/linux-core/xgi_types.h b/linux-core/xgi_types.h deleted file mode 100644 index f9a3360c..00000000 --- a/linux-core/xgi_types.h +++ /dev/null @@ -1,46 +0,0 @@ - -/**************************************************************************** - * 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_TYPES_H_ -#define _XGI_TYPES_H_ - -/**************************************************************************** - * Typedefs * - ***************************************************************************/ - -/* - * mainly for 64-bit linux, where long is 64 bits - * and win9x, where int is 16 bit. - */ -#if defined(vxworks) -typedef unsigned int U32; /* 0 to 4294967295 */ -#else -typedef unsigned long U32; /* 0 to 4294967295 */ -#endif - -#endif -- cgit v1.2.3 From 4575d5b8f18fef8cd19e7884bf8dab5e8f71ec9e Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Jul 2007 20:56:11 -0700 Subject: Massive log message clean up in xgi_submit_cmdlist. --- linux-core/xgi_cmdlist.c | 99 +++++++----------------------------------------- 1 file changed, 14 insertions(+), 85 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 7be0ac48..61373469 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -64,131 +64,61 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) { - unsigned int beginPort; - /** XGI_INFO("Jong-xgi_submit_cmdlist-Begin \n"); **/ + const unsigned int beginPort = getCurBatchBeginPort(pCmdInfo); - /* Jong 05/25/2006 */ - /* return; */ - - beginPort = getCurBatchBeginPort(pCmdInfo); - XGI_INFO("Jong-xgi_submit_cmdlist-After getCurBatchBeginPort() \n"); - - /* Jong 05/25/2006 */ - /* return; */ + XGI_INFO("After getCurBatchBeginPort()\n"); if (s_cmdring._lastBatchStartAddr == 0) { - unsigned int portOffset; + const unsigned int portOffset = BASE_3D_ENG + beginPort; /* Jong 06/13/2006; remove marked for system hang test */ /* xgi_waitfor_pci_idle(info); */ - /* Jong 06132006; BASE_3D_ENG=0x2800 */ - /* beginPort: 2D: 0x30 */ - portOffset = BASE_3D_ENG + beginPort; - // Enable PCI Trigger Mode - XGI_INFO("Jong-xgi_submit_cmdlist-Enable PCI Trigger Mode \n"); - - /* Jong 05/25/2006 */ - /* return; */ - - /* Jong 06/13/2006; M2REG_AUTO_LINK_SETTING_ADDRESS=0x10 */ - XGI_INFO("Jong-M2REG_AUTO_LINK_SETTING_ADDRESS=0x%lx \n", - M2REG_AUTO_LINK_SETTING_ADDRESS); - XGI_INFO("Jong-M2REG_CLEAR_COUNTERS_MASK=0x%lx \n", - M2REG_CLEAR_COUNTERS_MASK); - XGI_INFO - ("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)=0x%lx \n", - (M2REG_AUTO_LINK_SETTING_ADDRESS << 22)); - XGI_INFO("Jong-M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n\n", - M2REG_PCI_TRIGGER_MODE_MASK); + XGI_INFO("Enable PCI Trigger Mode \n"); + /* Jong 06/14/2006; 0x400001a */ - XGI_INFO - ("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|M2REG_CLEAR_COUNTERS_MASK|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", - (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | - M2REG_CLEAR_COUNTERS_MASK | 0x08 | - M2REG_PCI_TRIGGER_MODE_MASK); dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | M2REG_CLEAR_COUNTERS_MASK | 0x08 | M2REG_PCI_TRIGGER_MODE_MASK); - /* Jong 05/25/2006 */ - XGI_INFO("Jong-xgi_submit_cmdlist-After dwWriteReg() \n"); - /* return; *//* OK */ - /* Jong 06/14/2006; 0x400000a */ - XGI_INFO - ("Jong-(M2REG_AUTO_LINK_SETTING_ADDRESS << 22)|0x08|M2REG_PCI_TRIGGER_MODE_MASK=0x%lx \n", - (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | 0x08 | - M2REG_PCI_TRIGGER_MODE_MASK); dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | 0x08 | M2REG_PCI_TRIGGER_MODE_MASK); // Send PCI begin command - XGI_INFO("Jong-xgi_submit_cmdlist-Send PCI begin command \n"); - /* return; */ + XGI_INFO("Send PCI begin command \n"); - XGI_INFO("Jong-xgi_submit_cmdlist-portOffset=%d \n", - portOffset); - XGI_INFO("Jong-xgi_submit_cmdlist-beginPort=%d \n", beginPort); + XGI_INFO("portOffset=%d, beginPort=%d\n", + portOffset, beginPort); /* beginPort = 48; */ /* 0xc100000 */ dwWriteReg(portOffset, (beginPort << 22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); - XGI_INFO("Jong-(beginPort<<22)=0x%lx \n", (beginPort << 22)); - XGI_INFO("Jong-(BEGIN_VALID_MASK)=0x%lx \n", BEGIN_VALID_MASK); - XGI_INFO("Jong- pCmdInfo->_curDebugID=0x%lx \n", - pCmdInfo->_curDebugID); - XGI_INFO - ("Jong- (beginPort<<22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID=0x%lx \n", - (beginPort << 22) + (BEGIN_VALID_MASK) + - pCmdInfo->_curDebugID); - XGI_INFO - ("Jong-xgi_submit_cmdlist-Send PCI begin command- After \n"); - /* return; *//* OK */ + + XGI_INFO("Send PCI begin command- After\n"); /* 0x80000024 */ dwWriteReg(portOffset + 4, BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); - XGI_INFO("Jong- BEGIN_LINK_ENABLE_MASK=0x%lx \n", - BEGIN_LINK_ENABLE_MASK); - XGI_INFO("Jong- pCmdInfo->_firstSize=0x%lx \n", - pCmdInfo->_firstSize); - XGI_INFO - ("Jong- BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize=0x%lx \n", - BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); - XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-1 \n"); /* 0x1010000 */ dwWriteReg(portOffset + 8, (pCmdInfo->_firstBeginAddr >> 4)); - XGI_INFO("Jong- pCmdInfo->_firstBeginAddr=0x%lx \n", - pCmdInfo->_firstBeginAddr); - XGI_INFO("Jong- (pCmdInfo->_firstBeginAddr >> 4)=0x%lx \n", - (pCmdInfo->_firstBeginAddr >> 4)); - XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-2 \n"); - - /* Jong 06/13/2006 */ - xgi_dump_register(info); /* Jong 06/12/2006; system hang; marked for test */ dwWriteReg(portOffset + 12, 0); - XGI_INFO("Jong-xgi_submit_cmdlist-dwWriteReg-3 \n"); /* Jong 06/13/2006; remove marked for system hang test */ /* xgi_waitfor_pci_idle(info); */ } else { u32 *lastBatchVirtAddr; - XGI_INFO - ("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 \n"); - - /* Jong 05/25/2006 */ - /* return; */ + XGI_INFO("s_cmdring._lastBatchStartAddr != 0\n"); if (pCmdInfo->_firstBeginType == BTYPE_3D) { addFlush2D(info); @@ -215,14 +145,13 @@ void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) /* Jong 06/12/2006; system hang; marked for test */ triggerHWCommandList(info, pCmdInfo->_beginCount); + } else { + XGI_ERROR("lastBatchVirtAddr is NULL\n"); } - - XGI_INFO - ("Jong-xgi_submit_cmdlist-s_cmdring._lastBatchStartAddr != 0 - End\n"); } s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; - XGI_INFO("Jong-xgi_submit_cmdlist-End \n"); + XGI_INFO("End\n"); } /* -- cgit v1.2.3 From 658ff2daf3d2a080da2d859f522a627aef841637 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Jul 2007 20:58:43 -0700 Subject: Eliminate several useless ioctls and associated cruft. The ioctlss XGI_ESC_DEVICE_INFO, XGI_ESC_MEM_COLLECT, XGI_ESC_PCIE_CHECK, XGI_ESC_GET_SCREEN_INFO, XGI_ESC_PUT_SCREEN_INFO, XGI_ESC_MMIO_INFO, and XGI_ESC_SAREA_INFO, are completely unnecessary. The will be doubly useless when the driver is converted to the DRM infrastructure. --- linux-core/xgi_drv.c | 28 ---------------------- linux-core/xgi_drv.h | 3 --- linux-core/xgi_misc.c | 66 --------------------------------------------------- linux-core/xgi_misc.h | 5 ---- linux-core/xgi_pcie.c | 29 ---------------------- 5 files changed, 131 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index b3425c75..bd39dfdc 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -877,10 +877,6 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, arg_size); switch (_IOC_NR(cmd)) { - case XGI_ESC_DEVICE_INFO: - XGI_INFO("Jong-xgi_ioctl_get_device_info \n"); - xgi_get_device_info(info, (struct xgi_chip_info *)arg_copy); - break; case XGI_ESC_POST_VBIOS: XGI_INFO("Jong-xgi_ioctl_post_vbios \n"); break; @@ -892,10 +888,6 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, XGI_INFO("Jong-xgi_ioctl_fb_free \n"); xgi_fb_free(info, *(unsigned long *)arg_copy); break; - case XGI_ESC_MEM_COLLECT: - XGI_INFO("Jong-xgi_ioctl_mem_collect \n"); - xgi_mem_collect(info, (unsigned int *)arg_copy); - break; case XGI_ESC_PCIE_ALLOC: XGI_INFO("Jong-xgi_ioctl_pcie_alloc \n"); xgi_pcie_alloc(info, alloc, 0); @@ -905,30 +897,10 @@ int xgi_kern_ioctl(struct inode *inode, struct file *filp, *((unsigned long *)arg_copy)); xgi_pcie_free(info, *((unsigned long *)arg_copy)); break; - case XGI_ESC_PCIE_CHECK: - XGI_INFO("Jong-xgi_pcie_heap_check \n"); - xgi_pcie_heap_check(); - break; - case XGI_ESC_GET_SCREEN_INFO: - XGI_INFO("Jong-xgi_get_screen_info \n"); - xgi_get_screen_info(info, (struct xgi_screen_info *)arg_copy); - break; - case XGI_ESC_PUT_SCREEN_INFO: - XGI_INFO("Jong-xgi_put_screen_info \n"); - xgi_put_screen_info(info, (struct xgi_screen_info *)arg_copy); - break; - case XGI_ESC_MMIO_INFO: - XGI_INFO("Jong-xgi_ioctl_get_mmio_info \n"); - xgi_get_mmio_info(info, (struct xgi_mmio_info *)arg_copy); - break; case XGI_ESC_GE_RESET: XGI_INFO("Jong-xgi_ioctl_ge_reset \n"); xgi_ge_reset(info); break; - case XGI_ESC_SAREA_INFO: - XGI_INFO("Jong-xgi_ioctl_sarea_info \n"); - xgi_sarea_info(info, (struct xgi_sarea_info *)arg_copy); - break; case XGI_ESC_DUMP_REGISTER: XGI_INFO("Jong-xgi_ioctl_dump_register \n"); xgi_dump_register(info); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 983ed0a9..382bb7a6 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -110,8 +110,6 @@ struct xgi_info { struct xgi_aperture mmio; struct xgi_aperture fb; struct xgi_aperture pcie; - struct xgi_screen_info scrn_info; - struct xgi_sarea_info sarea_info; /* look up table parameters */ u32 *lut_base; @@ -207,7 +205,6 @@ extern void xgi_pcie_heap_cleanup(struct xgi_info * info); extern void xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, pid_t pid); extern void xgi_pcie_free(struct xgi_info * info, unsigned long offset); -extern void xgi_pcie_heap_check(void); extern struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, unsigned long address); extern void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address); diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 2d310a2f..bb2813ca 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -31,78 +31,12 @@ #include "xgi_regs.h" #include "xgi_pcie.h" -void xgi_get_device_info(struct xgi_info * info, struct xgi_chip_info * req) -{ - req->device_id = info->dev->device; - req->device_name[0] = 'x'; - req->device_name[1] = 'g'; - req->device_name[2] = '4'; - req->device_name[3] = '7'; - req->vendor_id = info->dev->vendor; - req->curr_display_mode = 0; - req->fb_size = info->fb.size; - req->sarea_bus_addr = info->sarea_info.bus_addr; - req->sarea_size = info->sarea_info.size; -} - -void xgi_get_mmio_info(struct xgi_info * info, struct xgi_mmio_info * req) -{ - req->mmio_base = info->mmio.base; - req->size = info->mmio.size; -} - -void xgi_put_screen_info(struct xgi_info * info, struct xgi_screen_info * req) -{ - info->scrn_info.scrn_start = req->scrn_start; - info->scrn_info.scrn_xres = req->scrn_xres; - info->scrn_info.scrn_yres = req->scrn_yres; - info->scrn_info.scrn_bpp = req->scrn_bpp; - info->scrn_info.scrn_pitch = req->scrn_pitch; - - XGI_INFO("info->scrn_info.scrn_start: 0x%lx" - "info->scrn_info.scrn_xres: 0x%lx" - "info->scrn_info.scrn_yres: 0x%lx" - "info->scrn_info.scrn_bpp: 0x%lx" - "info->scrn_info.scrn_pitch: 0x%lx\n", - info->scrn_info.scrn_start, - info->scrn_info.scrn_xres, - info->scrn_info.scrn_yres, - info->scrn_info.scrn_bpp, info->scrn_info.scrn_pitch); -} - -void xgi_get_screen_info(struct xgi_info * info, struct xgi_screen_info * req) -{ - req->scrn_start = info->scrn_info.scrn_start; - req->scrn_xres = info->scrn_info.scrn_xres; - req->scrn_yres = info->scrn_info.scrn_yres; - req->scrn_bpp = info->scrn_info.scrn_bpp; - req->scrn_pitch = info->scrn_info.scrn_pitch; - - XGI_INFO("req->scrn_start: 0x%lx" - "req->scrn_xres: 0x%lx" - "req->scrn_yres: 0x%lx" - "req->scrn_bpp: 0x%lx" - "req->scrn_pitch: 0x%lx\n", - req->scrn_start, - req->scrn_xres, - req->scrn_yres, req->scrn_bpp, req->scrn_pitch); -} - void xgi_ge_reset(struct xgi_info * info) { xgi_disable_ge(info); xgi_enable_ge(info); } -void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req) -{ - info->sarea_info.bus_addr = req->bus_addr; - info->sarea_info.size = req->size; - XGI_INFO("info->sarea_info.bus_addr: 0x%lx" - "info->sarea_info.size: 0x%lx\n", - info->sarea_info.bus_addr, info->sarea_info.size); -} - /* * irq functions */ diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h index 85cfbf2b..9c0591b2 100644 --- a/linux-core/xgi_misc.h +++ b/linux-core/xgi_misc.h @@ -30,12 +30,7 @@ #define _XGI_MISC_H_ extern void xgi_dump_register(struct xgi_info * info); -extern void xgi_get_device_info(struct xgi_info * info, struct xgi_chip_info * req); -extern void xgi_get_mmio_info(struct xgi_info * info, struct xgi_mmio_info * req); -extern void xgi_get_screen_info(struct xgi_info * info, struct xgi_screen_info * req); -extern void xgi_put_screen_info(struct xgi_info * info, struct xgi_screen_info * req); extern void xgi_ge_reset(struct xgi_info * info); -extern void xgi_sarea_info(struct xgi_info * info, struct xgi_sarea_info * req); extern void xgi_restore_registers(struct xgi_info * info); extern bool xgi_ge_irq_handler(struct xgi_info * info); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 70459b2c..0d641ab8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -344,35 +344,6 @@ int xgi_pcie_heap_init(struct xgi_info * info) return 0; } -void xgi_pcie_heap_check(void) -{ -#ifdef XGI_DEBUG - struct xgi_pcie_block *block; - unsigned int ownerIndex; - static const char *const ownerStr[6] = - { "2D", "3D", "3D_CMD", "3D_SCR", "3D_TEX", "ELSE" }; - - if (!xgi_pcie_heap) { - return; - } - - XGI_INFO("pcie freemax = 0x%lx\n", xgi_pcie_heap->max_freesize); - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - if (block->owner == PCIE_2D) - ownerIndex = 0; - else if (block->owner > PCIE_3D_TEXTURE - || block->owner < PCIE_2D - || block->owner < PCIE_3D) - ownerIndex = 5; - else - ownerIndex = block->owner - PCIE_3D + 1; - - XGI_INFO("Allocated by %s, block offset: 0x%lx, size: 0x%lx \n", - ownerStr[ownerIndex], block->offset, block->size); - } -#endif -} - void xgi_pcie_heap_cleanup(struct xgi_info * info) { struct list_head *free_list; -- cgit v1.2.3 From 5b08ab258f3e541334d2b64d38e15e1431080199 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Jul 2007 21:12:30 -0700 Subject: Clean ups (primarilly log messages) in xgi_test_rwinkernel. --- linux-core/xgi_pcie.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 0d641ab8..cfc9febc 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -919,20 +919,21 @@ void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) */ void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address) { - unsigned long *virtaddr = 0; + u32 *virtaddr = 0; + + XGI_INFO("input GE HW addr is 0x%x\n", address); + if (address == 0) { - XGI_INFO("[Jong-kd] input GE HW addr is 0x00000000\n"); return; } - virtaddr = (unsigned long *)xgi_find_pcie_virt(info, address); + virtaddr = (u32 *)xgi_find_pcie_virt(info, address); + + XGI_INFO("convert to CPU virt addr 0x%p\n", virtaddr); - XGI_INFO("[Jong-kd] input GE HW addr is 0x%lx\n", address); - XGI_INFO("[Jong-kd] convert to CPU virt addr 0x%px\n", virtaddr); - XGI_INFO("[Jong-kd] origin [virtaddr] = 0x%lx\n", *virtaddr); if (virtaddr != NULL) { + XGI_INFO("original [virtaddr] = 0x%x\n", *virtaddr); *virtaddr = 0x00f00fff; + XGI_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); } - - XGI_INFO("[Jong-kd] modified [virtaddr] = 0x%lx\n", *virtaddr); } -- cgit v1.2.3 From bcba7ba981a88e27ad4d7e8ebcdbed7097cf1488 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Jul 2007 21:15:58 -0700 Subject: Log message clean up in WriteRegDWord. Remove unused inline functions. --- linux-core/xgi_regs.h | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 0e54e7d8..bc3e2a1e 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -153,16 +153,10 @@ static inline void writeAttr(struct xgi_info * info, u8 index, u8 value) */ static inline void WriteRegDWord(struct xgi_info * info, u32 addr, u32 data) { - /* Jong 05/25/2006 */ - XGI_INFO("Jong-WriteRegDWord()-Begin \n"); - XGI_INFO("Jong-WriteRegDWord()-info->mmio.vbase=0x%lx \n", - info->mmio.vbase); - XGI_INFO("Jong-WriteRegDWord()-addr=0x%lx \n", addr); - XGI_INFO("Jong-WriteRegDWord()-data=0x%lx \n", data); - /* return; */ + XGI_INFO("mmio vbase = 0x%p, addr = 0x%x, data = 0x%x\n", + info->mmio->vbase, addr, data); *(volatile u32 *)(info->mmio.vbase + addr) = (data); - XGI_INFO("Jong-WriteRegDWord()-End \n"); } static inline void WriteRegWord(struct xgi_info * info, u32 addr, u16 data) @@ -262,18 +256,6 @@ extern void DisableProtect(); #define wReadReg(addr) ReadRegWord(info, addr) #define bReadReg(addr) ReadRegByte(info, addr) -static inline void xgi_protect_all(struct xgi_info * info) -{ - OUTB(0x3C4, 0x11); - OUTB(0x3C5, 0x92); -} - -static inline void xgi_unprotect_all(struct xgi_info * info) -{ - OUTB(0x3C4, 0x11); - OUTB(0x3C5, 0x92); -} - static inline void xgi_enable_mmio(struct xgi_info * info) { u8 protect = 0; -- cgit v1.2.3 From 7f98815d0027b1d4bd07b08e540106d5e994bcc5 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 16 Jul 2007 22:15:01 -0700 Subject: Make drm_sg_free callable in-kernel. --- linux-core/drmP.h | 5 +++-- linux-core/drm_scatter.c | 29 +++++++++++++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 2bbc6200..ebb530bc 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -1135,8 +1135,9 @@ extern void drm_sg_cleanup(drm_sg_mem_t * entry); extern int drm_sg_alloc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int drm_sg_alloc(drm_device_t *dev, drm_scatter_gather_t * request); -extern int drm_sg_free(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_sg_free(struct drm_device *dev, unsigned long handle); +extern int drm_sg_free_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /* ATI PCIGART support (ati_pcigart.h) */ extern int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info *gart_info); diff --git a/linux-core/drm_scatter.c b/linux-core/drm_scatter.c index c0d6db24..5581dc0b 100644 --- a/linux-core/drm_scatter.c +++ b/linux-core/drm_scatter.c @@ -203,6 +203,7 @@ int drm_sg_alloc_ioctl(struct inode *inode, struct file *filp, if (copy_to_user(argp, &request, sizeof(request))) { drm_sg_cleanup(priv->head->dev->sg); + priv->head->dev->sg = NULL; return -EFAULT; } @@ -211,26 +212,18 @@ int drm_sg_alloc_ioctl(struct inode *inode, struct file *filp, } -int drm_sg_free(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_sg_free(struct drm_device *dev, unsigned long handle) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev = priv->head->dev; - drm_scatter_gather_t request; drm_sg_mem_t *entry; if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL; - if (copy_from_user(&request, - (drm_scatter_gather_t __user *) arg, - sizeof(request))) - return -EFAULT; entry = dev->sg; dev->sg = NULL; - if (!entry || entry->handle != request.handle) + if (!entry || entry->handle != handle) return -EINVAL; DRM_DEBUG("sg free virtual = %p\n", entry->virtual); @@ -239,3 +232,19 @@ int drm_sg_free(struct inode *inode, struct file *filp, return 0; } + +EXPORT_SYMBOL(drm_sg_free); + +int drm_sg_free_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_scatter_gather __user *argp = (void __user *)arg; + struct drm_scatter_gather request; + + if (copy_from_user(&request, argp, sizeof(request))) + return -EFAULT; + + return drm_sg_free(dev, request.handle); +} -- cgit v1.2.3 From 5ba94c2ab8be350fee495e5cfe94afb8f663956a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 10:29:18 -0700 Subject: Initial pass at converting driver to DRM infrastructure. --- linux-core/Makefile | 3 +- linux-core/xgi_cmdlist.c | 99 ++- linux-core/xgi_cmdlist.h | 7 +- linux-core/xgi_drv.c | 1522 ++++++---------------------------------------- linux-core/xgi_drv.h | 205 +++---- linux-core/xgi_fb.c | 511 +++++++--------- linux-core/xgi_fb.h | 47 -- linux-core/xgi_linux.h | 490 --------------- linux-core/xgi_misc.c | 145 ++--- linux-core/xgi_misc.h | 2 - linux-core/xgi_pcie.c | 941 ++++++---------------------- linux-core/xgi_pcie.h | 68 --- linux-core/xgi_regs.h | 313 +++------- 13 files changed, 845 insertions(+), 3508 deletions(-) delete mode 100644 linux-core/xgi_fb.h delete mode 100644 linux-core/xgi_linux.h delete mode 100644 linux-core/xgi_pcie.h (limited to 'linux-core') diff --git a/linux-core/Makefile b/linux-core/Makefile index 2052459d..55e25253 100644 --- a/linux-core/Makefile +++ b/linux-core/Makefile @@ -91,8 +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_fb.h xgi_linux.h xgi_misc.h \ - xgi_pcie.h xgi_regs.h xgi_types.h +XGIHEADERS = xgi_cmdlist.h xgi_drv.h xgi_misc.h xgi_regs.h $(DRMHEADERS) PROGS = dristat drmstat diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 61373469..d2018057 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -26,7 +26,6 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" #include "xgi_misc.h" @@ -55,18 +54,19 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) s_cmdring._cmdRingSize = mem_alloc.size; s_cmdring._cmdRingBuffer = mem_alloc.hw_addr; - s_cmdring._cmdRingBusAddr = mem_alloc.bus_addr; + s_cmdring._cmdRingAllocOffset = mem_alloc.offset; s_cmdring._lastBatchStartAddr = 0; s_cmdring._cmdRingOffset = 0; return 1; } -void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) +static void xgi_submit_cmdlist(struct xgi_info * info, + struct xgi_cmd_info * pCmdInfo) { const unsigned int beginPort = getCurBatchBeginPort(pCmdInfo); - XGI_INFO("After getCurBatchBeginPort()\n"); + DRM_INFO("After getCurBatchBeginPort()\n"); if (s_cmdring._lastBatchStartAddr == 0) { const unsigned int portOffset = BASE_3D_ENG + beginPort; @@ -75,50 +75,53 @@ void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) /* xgi_waitfor_pci_idle(info); */ // Enable PCI Trigger Mode - XGI_INFO("Enable PCI Trigger Mode \n"); + DRM_INFO("Enable PCI Trigger Mode \n"); /* Jong 06/14/2006; 0x400001a */ - dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, + 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); /* Jong 06/14/2006; 0x400000a */ - dwWriteReg(BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, + 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 - XGI_INFO("Send PCI begin command \n"); + DRM_INFO("Send PCI begin command \n"); - XGI_INFO("portOffset=%d, beginPort=%d\n", + DRM_INFO("portOffset=%d, beginPort=%d\n", portOffset, beginPort); /* beginPort = 48; */ /* 0xc100000 */ - dwWriteReg(portOffset, + dwWriteReg(info->mmio_map, portOffset, (beginPort << 22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); - XGI_INFO("Send PCI begin command- After\n"); + DRM_INFO("Send PCI begin command- After\n"); /* 0x80000024 */ - dwWriteReg(portOffset + 4, + dwWriteReg(info->mmio_map, portOffset + 4, BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); /* 0x1010000 */ - dwWriteReg(portOffset + 8, (pCmdInfo->_firstBeginAddr >> 4)); + dwWriteReg(info->mmio_map, portOffset + 8, + (pCmdInfo->_firstBeginAddr >> 4)); /* Jong 06/12/2006; system hang; marked for test */ - dwWriteReg(portOffset + 12, 0); + dwWriteReg(info->mmio_map, portOffset + 12, 0); /* Jong 06/13/2006; remove marked for system hang test */ /* xgi_waitfor_pci_idle(info); */ } else { u32 *lastBatchVirtAddr; - XGI_INFO("s_cmdring._lastBatchStartAddr != 0\n"); + DRM_INFO("s_cmdring._lastBatchStartAddr != 0\n"); if (pCmdInfo->_firstBeginType == BTYPE_3D) { addFlush2D(info); @@ -146,21 +149,38 @@ void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo) /* Jong 06/12/2006; system hang; marked for test */ triggerHWCommandList(info, pCmdInfo->_beginCount); } else { - XGI_ERROR("lastBatchVirtAddr is NULL\n"); + DRM_ERROR("lastBatchVirtAddr is NULL\n"); } } s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; - XGI_INFO("End\n"); + DRM_INFO("End\n"); } + +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)); + + xgi_submit_cmdlist(info, &cmd_list); + return 0; +} + + /* state: 0 - console 1 - graphic 2 - fb 3 - logout */ -void xgi_state_change(struct xgi_info * info, struct xgi_state_info * pStateInfo) +int xgi_state_change(struct xgi_info * info, unsigned int to, + unsigned int from) { #define STATE_CONSOLE 0 #define STATE_GRAPHIC 1 @@ -169,26 +189,40 @@ void xgi_state_change(struct xgi_info * info, struct xgi_state_info * pStateInfo #define STATE_REBOOT 4 #define STATE_SHUTDOWN 5 - if ((pStateInfo->_fromState == STATE_GRAPHIC) - && (pStateInfo->_toState == STATE_CONSOLE)) { - XGI_INFO("[kd] I see, now is to leaveVT\n"); + if ((from == STATE_GRAPHIC) && (to == STATE_CONSOLE)) { + DRM_INFO("[kd] I see, now is to leaveVT\n"); // stop to received batch - } else if ((pStateInfo->_fromState == STATE_CONSOLE) - && (pStateInfo->_toState == STATE_GRAPHIC)) { - XGI_INFO("[kd] I see, now is to enterVT\n"); + } else if ((from == STATE_CONSOLE) && (to == STATE_GRAPHIC)) { + DRM_INFO("[kd] I see, now is to enterVT\n"); xgi_cmdlist_reset(); - } else if ((pStateInfo->_fromState == STATE_GRAPHIC) - && ((pStateInfo->_toState == STATE_LOGOUT) - || (pStateInfo->_toState == STATE_REBOOT) - || (pStateInfo->_toState == STATE_SHUTDOWN))) { - XGI_INFO("[kd] I see, not is to exit from X\n"); + } else if ((from == STATE_GRAPHIC) + && ((to == STATE_LOGOUT) + || (to == STATE_REBOOT) + || (to == STATE_SHUTDOWN))) { + DRM_INFO("[kd] I see, not is to exit from X\n"); // stop to received batch } else { - XGI_ERROR("[kd] Should not happen\n"); + DRM_ERROR("[kd] Should not happen\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(void) { s_cmdring._lastBatchStartAddr = 0; @@ -198,7 +232,7 @@ void xgi_cmdlist_reset(void) void xgi_cmdlist_cleanup(struct xgi_info * info) { if (s_cmdring._cmdRingBuffer != 0) { - xgi_pcie_free(info, s_cmdring._cmdRingBusAddr); + xgi_pcie_free(info, s_cmdring._cmdRingAllocOffset, NULL); s_cmdring._cmdRingBuffer = 0; s_cmdring._cmdRingOffset = 0; s_cmdring._cmdRingSize = 0; @@ -212,7 +246,8 @@ static void triggerHWCommandList(struct xgi_info * info, //Fix me, currently we just trigger one time while (triggerCounter--) { - dwWriteReg(BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, + dwWriteReg(info->mmio_map, + BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, 0x05000000 + (0x0ffff & s_triggerID++)); // xgi_waitfor_pci_idle(info); } diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index d2b95c0e..4bc56ec1 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -60,16 +60,15 @@ typedef enum { struct xgi_cmdring_info { unsigned int _cmdRingSize; u32 _cmdRingBuffer; - unsigned long _cmdRingBusAddr; + unsigned long _cmdRingAllocOffset; u32 _lastBatchStartAddr; u32 _cmdRingOffset; }; extern int xgi_cmdlist_initialize(struct xgi_info * info, size_t size); -extern void xgi_submit_cmdlist(struct xgi_info * info, struct xgi_cmd_info * pCmdInfo); - -extern void xgi_state_change(struct xgi_info * info, struct xgi_state_info * pStateInfo); +extern int xgi_state_change(struct xgi_info * info, unsigned int to, + unsigned int from); extern void xgi_cmdlist_cleanup(struct xgi_info * info); 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 "); -MODULE_DESCRIPTION("xgi kernel driver for xgi cards"); -MODULE_LICENSE("GPL"); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 382bb7a6..20965876 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -29,115 +29,69 @@ #ifndef _XGI_DRV_H_ #define _XGI_DRV_H_ -#include "xgi_drm.h" - -#define XGI_MAJOR_VERSION 0 -#define XGI_MINOR_VERSION 7 -#define XGI_PATCHLEVEL 5 - -#define XGI_DRV_VERSION "0.7.5" - -#ifndef XGI_DRV_NAME -#define XGI_DRV_NAME "xgi" -#endif - -/* - * xgi reserved major device number, Set this to 0 to - * request dynamic major number allocation. - */ -#ifndef XGI_DEV_MAJOR -#define XGI_DEV_MAJOR 0 -#endif - -#ifndef XGI_MAX_DEVICES -#define XGI_MAX_DEVICES 1 -#endif - -/* Jong 06/06/2006 */ -/* #define XGI_DEBUG */ +#include "drmP.h" +#include "drm.h" -#ifndef PCI_VENDOR_ID_XGI -/* -#define PCI_VENDOR_ID_XGI 0x1023 -*/ -#define PCI_VENDOR_ID_XGI 0x18CA +#define DRIVER_AUTHOR "Andrea Zhang " -#endif - -#ifndef PCI_DEVICE_ID_XP5 -#define PCI_DEVICE_ID_XP5 0x2200 -#endif - -#ifndef PCI_DEVICE_ID_XG47 -#define PCI_DEVICE_ID_XG47 0x0047 -#endif +#define DRIVER_NAME "xgi" +#define DRIVER_DESC "XGI XP5 / XP10 / XG47" +#define DRIVER_DATE "20070710" -/* Macros to make printk easier */ -#define XGI_ERROR(fmt, arg...) \ - printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) +#define DRIVER_MAJOR 0 +#define DRIVER_MINOR 8 +#define DRIVER_PATCHLEVEL 0 -#define XGI_MEM_ERROR(area, fmt, arg...) \ - printk(KERN_ERR "[" XGI_DRV_NAME ":%s] *ERROR* " fmt, __FUNCTION__, ##arg) +#include "xgi_drm.h" -/* #define XGI_DEBUG */ +struct xgi_aperture { + dma_addr_t base; + unsigned int size; +}; -#ifdef XGI_DEBUG -#define XGI_INFO(fmt, arg...) \ - printk(KERN_ALERT "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) -/* printk(KERN_INFO "[" XGI_DRV_NAME ":%s] " fmt, __FUNCTION__, ##arg) */ -#else -#define XGI_INFO(fmt, arg...) do { } while (0) -#endif +struct xgi_mem_block { + struct list_head list; + unsigned long offset; + unsigned long size; + DRMFILE filp; -/* device name length; must be atleast 8 */ -#define XGI_DEVICE_NAME_LENGTH 40 + unsigned int owner; +}; -/* need a fake device number for control device; just to flag it for msgs */ -#define XGI_CONTROL_DEVICE_NUMBER 100 +struct xgi_mem_heap { + struct list_head free_list; + struct list_head used_list; + struct list_head sort_list; + unsigned long max_freesize; -struct xgi_aperture { - unsigned long base; - unsigned int size; - void *vbase; + bool initialized; }; struct xgi_info { - struct pci_dev *dev; - int flags; - int device_number; + 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 */ - u32 *lut_base; + struct drm_dma_handle *lut_handle; unsigned int lutPageSize; - unsigned int lutPageOrder; - bool isLUTInLFB; - unsigned int sdfbPageSize; - - u32 pcie_config; - u32 pcie_status; - - atomic_t use_count; - /* keep track of any pending bottom halfes */ - struct tasklet_struct tasklet; + struct xgi_mem_heap fb_heap; + struct xgi_mem_heap pcie_heap; - spinlock_t info_lock; - - struct semaphore info_sem; struct semaphore fb_sem; struct semaphore pcie_sem; }; -struct xgi_ioctl_post_vbios { - unsigned int bus; - unsigned int slot; -}; - enum PcieOwner { PCIE_2D = 0, /* @@ -151,64 +105,47 @@ enum PcieOwner { PCIE_INVALID = 0x7fffffff }; -struct xgi_mem_pid { - struct list_head list; - enum xgi_mem_location location; - unsigned long bus_addr; - unsigned long pid; -}; - - -/* - * flags - */ -#define XGI_FLAG_OPEN 0x0001 -#define XGI_FLAG_NEEDS_POSTING 0x0002 -#define XGI_FLAG_WAS_POSTED 0x0004 -#define XGI_FLAG_CONTROL 0x0010 -#define XGI_FLAG_MAP_REGS_EARLY 0x0200 - -/* mmap(2) offsets */ - -#define IS_IO_OFFSET(info, offset, length) \ - (((offset) >= (info)->mmio.base) \ - && (((offset) + (length)) <= (info)->mmio.base + (info)->mmio.size)) - -/* Jong 06/14/2006 */ -/* (info)->fb.base is a base address for physical (bus) address space */ -/* what's the definition of offest? on physical (bus) address space or HW address space */ -/* Jong 06/15/2006; use HW address space */ -#define IS_FB_OFFSET(info, offset, length) \ - (((offset) >= 0) \ - && (((offset) + (length)) <= (info)->fb.size)) -#if 0 -#define IS_FB_OFFSET(info, offset, length) \ - (((offset) >= (info)->fb.base) \ - && (((offset) + (length)) <= (info)->fb.base + (info)->fb.size)) -#endif -#define IS_PCIE_OFFSET(info, offset, length) \ - (((offset) >= (info)->pcie.base) \ - && (((offset) + (length)) <= (info)->pcie.base + (info)->pcie.size)) +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 void xgi_fb_heap_cleanup(struct xgi_info * info); -extern void xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - pid_t pid); -extern void xgi_fb_free(struct xgi_info * info, unsigned long offset); -extern void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt); +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_heap_cleanup(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_alloc(struct xgi_info * info, - struct xgi_mem_alloc * alloc, pid_t pid); -extern void xgi_pcie_free(struct xgi_info * info, unsigned long offset); -extern struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, - unsigned long address); -extern void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address); +extern void xgi_pcie_free_all(struct xgi_info *, DRMFILE); +extern void xgi_fb_free_all(struct xgi_info *, DRMFILE); -extern void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address); +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 index 7d390d4b..ce689847 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -26,343 +26,126 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_linux.h" #include "xgi_drv.h" -#include "xgi_fb.h" #define XGI_FB_HEAP_START 0x1000000 -static struct xgi_mem_heap *xgi_fb_heap; -static struct kmem_cache *xgi_fb_cache_block = NULL; -extern struct list_head xgi_mempid_list; +struct kmem_cache *xgi_mem_block_cache = NULL; static struct xgi_mem_block *xgi_mem_new_node(void); -static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, unsigned long size); -static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long offset); -void xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - pid_t pid) -{ - struct xgi_mem_block *block; - struct xgi_mem_pid *mempid_block; - - if (alloc->is_front) { - alloc->location = XGI_MEMLOC_LOCAL; - alloc->bus_addr = info->fb.base; - alloc->hw_addr = 0; - XGI_INFO - ("Video RAM allocation on front buffer successfully! \n"); - } else { - xgi_down(info->fb_sem); - block = xgi_mem_alloc(info, alloc->size); - xgi_up(info->fb_sem); - - if (block == NULL) { - alloc->location = XGI_MEMLOC_LOCAL; - alloc->size = 0; - alloc->bus_addr = 0; - alloc->hw_addr = 0; - XGI_ERROR("Video RAM allocation failed\n"); - } else { - XGI_INFO("Video RAM allocation succeeded: 0x%p\n", - (char *)block->offset); - alloc->location = XGI_MEMLOC_LOCAL; - alloc->size = block->size; - alloc->bus_addr = info->fb.base + block->offset; - alloc->hw_addr = block->offset; - - /* manage mempid */ - mempid_block = - kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); - mempid_block->location = XGI_MEMLOC_LOCAL; - mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = pid; - - if (!mempid_block) - XGI_ERROR("mempid_block alloc failed\n"); - - XGI_INFO - ("Memory ProcessID add one fb block pid:%ld successfully! \n", - mempid_block->pid); - list_add(&mempid_block->list, &xgi_mempid_list); - } - } -} -void xgi_fb_free(struct xgi_info * info, unsigned long bus_addr) +int xgi_mem_heap_init(struct xgi_mem_heap *heap, unsigned int start, + unsigned int end) { struct xgi_mem_block *block; - unsigned long offset = bus_addr - info->fb.base; - struct xgi_mem_pid *mempid_block; - struct xgi_mem_pid *mempid_freeblock = NULL; - - if (offset < 0) { - XGI_INFO("free onscreen frame buffer successfully !\n"); - } else { - xgi_down(info->fb_sem); - block = xgi_mem_free(info, offset); - xgi_up(info->fb_sem); - - if (block == NULL) { - XGI_ERROR("xgi_mem_free() failed at base 0x%lx\n", - offset); - } - - /* manage mempid */ - list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == XGI_MEMLOC_LOCAL - && mempid_block->bus_addr == bus_addr) { - mempid_freeblock = mempid_block; - break; - } - } - if (mempid_freeblock) { - list_del(&mempid_freeblock->list); - XGI_INFO - ("Memory ProcessID delete one fb block pid:%ld successfully! \n", - mempid_freeblock->pid); - kfree(mempid_freeblock); - } - } -} - -int xgi_fb_heap_init(struct xgi_info * info) -{ - struct xgi_mem_block *block; - - xgi_fb_heap = kmalloc(sizeof(struct xgi_mem_heap), GFP_KERNEL); - if (!xgi_fb_heap) { - XGI_ERROR("xgi_fb_heap alloc failed\n"); - return 0; - } - - INIT_LIST_HEAD(&xgi_fb_heap->free_list); - INIT_LIST_HEAD(&xgi_fb_heap->used_list); - INIT_LIST_HEAD(&xgi_fb_heap->sort_list); - xgi_fb_cache_block = - kmem_cache_create("xgi_fb_block", sizeof(struct xgi_mem_block), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + INIT_LIST_HEAD(&heap->free_list); + INIT_LIST_HEAD(&heap->used_list); + INIT_LIST_HEAD(&heap->sort_list); + heap->initialized = TRUE; - if (NULL == xgi_fb_cache_block) { - XGI_ERROR("Fail to creat xgi_fb_block\n"); - goto fail1; - } - - block = - (struct xgi_mem_block *) kmem_cache_alloc(xgi_fb_cache_block, - GFP_KERNEL); + block = kmem_cache_alloc(xgi_mem_block_cache, GFP_KERNEL); if (!block) { - XGI_ERROR("kmem_cache_alloc failed\n"); - goto fail2; + return DRM_ERR(ENOMEM); } - block->offset = XGI_FB_HEAP_START; - block->size = info->fb.size - XGI_FB_HEAP_START; - - list_add(&block->list, &xgi_fb_heap->free_list); + block->offset = start; + block->size = end - start; - xgi_fb_heap->max_freesize = info->fb.size - XGI_FB_HEAP_START; + list_add(&block->list, &heap->free_list); - XGI_INFO("fb start offset: 0x%lx, memory size : 0x%lx\n", block->offset, - block->size); - XGI_INFO("xgi_fb_heap->max_freesize: 0x%lx \n", - xgi_fb_heap->max_freesize); + heap->max_freesize = end - start; - return 1; - - fail2: - if (xgi_fb_cache_block) { - kmem_cache_destroy(xgi_fb_cache_block); - xgi_fb_cache_block = NULL; - } - fail1: - if (xgi_fb_heap) { - kfree(xgi_fb_heap); - xgi_fb_heap = NULL; - } return 0; } -void xgi_fb_heap_cleanup(struct xgi_info * info) + +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; - if (xgi_fb_heap) { - free_list = &xgi_fb_heap->free_list; - for (i = 0; i < 3; i++, free_list++) { - list_for_each_entry_safe(block, next, free_list, list) { - XGI_INFO - ("No. %d block->offset: 0x%lx block->size: 0x%lx \n", - i, block->offset, block->size); - //XGI_INFO("No. %d free block: 0x%p \n", i, block); - kmem_cache_free(xgi_fb_cache_block, block); - block = NULL; - } + 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; } - XGI_INFO("xgi_fb_heap: 0x%p \n", xgi_fb_heap); - kfree(xgi_fb_heap); - xgi_fb_heap = NULL; - } - - if (xgi_fb_cache_block) { - kmem_cache_destroy(xgi_fb_cache_block); - xgi_fb_cache_block = NULL; } + + heap->initialized = 0; } -static struct xgi_mem_block *xgi_mem_new_node(void) + +struct xgi_mem_block *xgi_mem_new_node(void) { - struct xgi_mem_block *block; + struct xgi_mem_block *block = + kmem_cache_alloc(xgi_mem_block_cache, GFP_KERNEL); - block = - (struct xgi_mem_block *) kmem_cache_alloc(xgi_fb_cache_block, - GFP_KERNEL); if (!block) { - XGI_ERROR("kmem_cache_alloc failed\n"); + DRM_ERROR("kmem_cache_alloc failed\n"); return NULL; } - return block; -} - -#if 0 -static void xgi_mem_insert_node_after(struct xgi_mem_list * list, - struct xgi_mem_block * current, - struct xgi_mem_block * block); -static void xgi_mem_insert_node_before(struct xgi_mem_list * list, - struct xgi_mem_block * current, - struct xgi_mem_block * block); -static void xgi_mem_insert_node_head(struct xgi_mem_list * list, - struct xgi_mem_block * block); -static void xgi_mem_insert_node_tail(struct xgi_mem_list * list, - struct xgi_mem_block * block); -static void xgi_mem_delete_node(struct xgi_mem_list * list, struct xgi_mem_block * block); -/* - * insert node:block after node:current - */ -static void xgi_mem_insert_node_after(struct xgi_mem_list * list, - struct xgi_mem_block * current, - struct xgi_mem_block * block) -{ - block->prev = current; - block->next = current->next; - current->next = block; - - if (current == list->tail) { - list->tail = block; - } else { - block->next->prev = block; - } -} + block->offset = 0; + block->size = 0; + block->owner = PCIE_INVALID; + block->filp = (DRMFILE) -1; -/* - * insert node:block before node:current - */ -static void xgi_mem_insert_node_before(struct xgi_mem_list * list, - struct xgi_mem_block * current, - struct xgi_mem_block * block) -{ - block->prev = current->prev; - block->next = current; - current->prev = block; - if (current == list->head) { - list->head = block; - } else { - block->prev->next = block; - } -} -void xgi_mem_insert_node_head(struct xgi_mem_list * list, struct xgi_mem_block * block) -{ - block->next = list->head; - block->prev = NULL; - - if (NULL == list->head) { - list->tail = block; - } else { - list->head->prev = block; - } - list->head = block; -} - -static void xgi_mem_insert_node_tail(struct xgi_mem_list * list, - struct xgi_mem_block * block) -{ - block->next = NULL; - block->prev = list->tail; - if (NULL == list->tail) { - list->head = block; - } else { - list->tail->next = block; - } - list->tail = block; + return block; } -static void xgi_mem_delete_node(struct xgi_mem_list * list, struct xgi_mem_block * block) -{ - if (block == list->head) { - list->head = block->next; - } - if (block == list->tail) { - list->tail = block->prev; - } - - if (block->prev) { - block->prev->next = block->next; - } - if (block->next) { - block->next->prev = block->prev; - } - block->next = block->prev = NULL; -} -#endif -static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, - unsigned long originalSize) +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; - XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", + + DRM_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", originalSize, size); if (size == 0) { - XGI_ERROR("size == 0\n"); + DRM_ERROR("size == 0\n"); return (NULL); } - XGI_INFO("max_freesize: 0x%lx \n", xgi_fb_heap->max_freesize); - if (size > xgi_fb_heap->max_freesize) { - XGI_ERROR + 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, xgi_fb_heap->max_freesize); + size, heap->max_freesize); return (NULL); } - list_for_each_entry(block, &xgi_fb_heap->free_list, list) { - XGI_INFO("free_list: 0x%px \n", free_list); + list_for_each_entry(block, &heap->free_list, list) { + DRM_INFO("block: 0x%px \n", block); if (size <= block->size) { break; } } - if (&block->list == &xgi_fb_heap->free_list) { - XGI_ERROR + 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; - XGI_INFO("alloc size: 0x%lx from offset: 0x%lx size: 0x%lx \n", + 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; - XGI_INFO("size == free_block->size: free_block = 0x%p\n", + DRM_INFO("size == free_block->size: free_block = 0x%p\n", free_block); list_del(&free_block->list); } else { @@ -372,7 +155,7 @@ static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, return (NULL); if (used_block == free_block) { - XGI_ERROR("used_block == free_block = 0x%p\n", + DRM_ERROR("used_block == free_block = 0x%p\n", used_block); } @@ -383,14 +166,16 @@ static struct xgi_mem_block *xgi_mem_alloc(struct xgi_info * info, free_block->size -= size; } - xgi_fb_heap->max_freesize -= size; + heap->max_freesize -= size; - list_add(&used_block->list, &xgi_fb_heap->used_list); + list_add(&used_block->list, &heap->used_list); + used_block->owner = owner; return (used_block); } -static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long offset) +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; @@ -398,28 +183,32 @@ static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long unsigned long upper; unsigned long lower; - list_for_each_entry(block, &xgi_fb_heap->used_list, list) { + list_for_each_entry(block, &heap->used_list, list) { if (block->offset == offset) { break; } } - if (&block->list == &xgi_fb_heap->used_list) { - XGI_ERROR("can't find block: 0x%lx to free!\n", offset); - return (NULL); + 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; - XGI_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx\n", + DRM_INFO("used_block: 0x%p, offset = 0x%lx, size = 0x%lx\n", used_block, used_block->offset, used_block->size); - xgi_fb_heap->max_freesize += 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, &xgi_fb_heap->free_list, list) { + list_for_each_entry(block, &heap->free_list, list) { if (block->offset == upper) { next = block; } else if ((block->offset + block->size) == lower) { @@ -427,41 +216,157 @@ static struct xgi_mem_block *xgi_mem_free(struct xgi_info * info, unsigned long } } - XGI_INFO("next = 0x%p, prev = 0x%p\n", next, prev); + 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); - XGI_INFO("free node 0x%p\n", next); - kmem_cache_free(xgi_fb_cache_block, next); - kmem_cache_free(xgi_fb_cache_block, used_block); - - next = NULL; - used_block = NULL; - return (prev); + 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); } - - if (prev) { + else if (prev) { prev->size += used_block->size; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_fb_cache_block, used_block); - used_block = NULL; - return (prev); + DRM_INFO("free node 0x%p\n", used_block); + kmem_cache_free(xgi_mem_block_cache, used_block); } - - if (next) { + else if (next) { next->size += used_block->size; next->offset = used_block->offset; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_fb_cache_block, used_block); - used_block = NULL; - return (next); + 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); } - list_add(&used_block->list, &xgi_fb_heap->free_list); - XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", - used_block, used_block->offset, used_block->size); + return 0; +} - return (used_block); + +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_fb_free(info, block->offset, filp); + } while(1); + + up(&info->fb_sem); } diff --git a/linux-core/xgi_fb.h b/linux-core/xgi_fb.h deleted file mode 100644 index 363c8bc8..00000000 --- a/linux-core/xgi_fb.h +++ /dev/null @@ -1,47 +0,0 @@ - -/**************************************************************************** - * 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_FB_H_ -#define _XGI_FB_H_ - -struct xgi_mem_block { - struct list_head list; - unsigned long offset; - unsigned long size; - atomic_t use_count; -}; - -struct xgi_mem_heap { - struct list_head free_list; - struct list_head used_list; - struct list_head sort_list; - unsigned long max_freesize; - spinlock_t lock; -}; - -#endif diff --git a/linux-core/xgi_linux.h b/linux-core/xgi_linux.h deleted file mode 100644 index 99bf2d04..00000000 --- a/linux-core/xgi_linux.h +++ /dev/null @@ -1,490 +0,0 @@ - -/**************************************************************************** - * 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_LINUX_H_ -#define _XGI_LINUX_H_ - -#ifndef LINUX_VERSION_CODE -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -# error "This driver does not support pre-2.6 kernels!" -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) -# define XGI_REMAP_PFN_RANGE_PRESENT -#else -# define XGI_REMAP_PAGE_RANGE_5 -#endif - -#if defined (CONFIG_SMP) && !defined (__SMP__) -#define __SMP__ -#endif - -#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) -#define MODVERSIONS -#endif - -#include /* printk */ -#include - -#include /* module_init, module_exit */ -#include /* pic_t, size_t, __u32, etc */ -#include /* error codes */ -#include /* circular linked list */ -#include /* NULL, offsetof */ -#include /* wait queues */ - -#include /* kmalloc, kfree, etc */ -#include /* vmalloc, vfree, etc */ - -#include /* poll_wait */ -#include /* mdelay, udelay */ -#include /* rdtsc rdtscl */ - -#include /* suser(), capable() replacement - for_each_task, for_each_process */ -#ifdef for_each_process -#define XGI_SCAN_PROCESS(p) for_each_process(p) -#else -#define XGI_SCAN_PROCESS(p) for_each_task(p) -#endif - -#include /* module_param() */ -#include /* kernel_locked */ -#include /* flush_tlb(), flush_tlb_all() */ -#include /* page table entry lookup */ - -#include /* pci_find_class, etc */ -#include /* tasklets, interrupt helpers */ -#include - -#include /* cli, sli, save_flags */ -#include /* ioremap, virt_to_phys */ -#include /* access_ok */ -#include /* PAGE_OFFSET */ -#include /* pte bit definitions */ - -#include -#include -#include - -#ifdef CONFIG_PROC_FS -#include -#endif - -#ifdef CONFIG_DEVFS_FS -#include -#endif - -#ifdef CONFIG_KMOD -#include -#endif - -#ifdef CONFIG_PM -#include -#endif - -#ifdef CONFIG_MTRR -#include -#endif - -#ifdef CONFIG_KDB -#include -#include -#endif - -#if defined (CONFIG_AGP) || defined (CONFIG_AGP_MODULE) -#define AGPGART -#include -#include -#endif - -#ifndef MAX_ORDER -#define MAX_ORDER 11 -#endif - -#ifndef module_init -#define module_init(x) int init_module(void) { return x(); } -#define module_exit(x) void cleanup_module(void) { x(); } -#endif - -#ifndef minor -#define minor(x) MINOR(x) -#endif - -#ifndef IRQ_HANDLED -typedef void irqreturn_t; -#define IRQ_NONE -#define IRQ_HANDLED -#define IRQ_RETVAL(x) -#endif - -#if !defined (list_for_each) -#define list_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) -#endif - -extern struct list_head pci_devices; /* list of all devices */ -#define XGI_PCI_FOR_EACH_DEV(dev) \ - for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next)) - -/* - * the following macro causes problems when used in the same module - * as module_param(); undef it so we don't accidentally mix the two - */ -#undef MODULE_PARM - -#ifdef EXPORT_NO_SYMBOLS -EXPORT_NO_SYMBOLS; -#endif - -#define XGI_IS_SUSER() capable(CAP_SYS_ADMIN) -#define XGI_PCI_DEVICE_NAME(dev) ((dev)->pretty_name) -#define XGI_NUM_CPUS() num_online_cpus() -#define XGI_CLI() local_irq_disable() -#define XGI_SAVE_FLAGS(eflags) local_save_flags(eflags) -#define XGI_RESTORE_FLAGS(eflags) local_irq_restore(eflags) -#define XGI_MAY_SLEEP() (!in_interrupt() && !in_atomic()) -#define XGI_MODULE_PARAMETER(x) module_param(x, int, 0) - - -#define XGI_PCI_DISABLE_DEVICE(dev) pci_disable_device(dev) - -/* common defines */ -#define GET_MODULE_SYMBOL(mod,sym) (const void *) inter_module_get(sym) -#define PUT_MODULE_SYMBOL(sym) inter_module_put((char *) sym) - -#define XGI_GET_PAGE_STRUCT(phys_page) virt_to_page(__va(phys_page)) -#define XGI_VMA_OFFSET(vma) (((vma)->vm_pgoff) << PAGE_SHIFT) -#define XGI_VMA_PRIVATE(vma) ((vma)->vm_private_data) - -#define XGI_DEVICE_NUMBER(x) minor((x)->i_rdev) -#define XGI_IS_CONTROL_DEVICE(x) (minor((x)->i_rdev) == 255) - -#define XGI_PCI_RESOURCE_START(dev, bar) ((dev)->resource[bar].start) -#define XGI_PCI_RESOURCE_SIZE(dev, bar) ((dev)->resource[bar].end - (dev)->resource[bar].start + 1) - -#define XGI_PCI_BUS_NUMBER(dev) (dev)->bus->number -#define XGI_PCI_SLOT_NUMBER(dev) PCI_SLOT((dev)->devfn) - -#define XGI_PCI_GET_CLASS_PRESENT -#ifdef XGI_PCI_GET_CLASS_PRESENT -#define XGI_PCI_DEV_PUT(dev) pci_dev_put(dev) -#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_get_device(vendor,device,from) -#else -#define XGI_PCI_DEV_PUT(dev) -#define XGI_PCI_GET_DEVICE(vendor,device,from) pci_find_device(vendor,device,from) -#endif - -/* - * acpi support has been back-ported to the 2.4 kernel, but the 2.4 driver - * model is not sufficient for full acpi support. it may work in some cases, - * but not enough for us to officially support this configuration. - */ -#if defined(CONFIG_ACPI) -#define XGI_PM_SUPPORT_ACPI -#endif - -#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) -#define XGI_PM_SUPPORT_APM -#endif - -#if defined(CONFIG_DEVFS_FS) -typedef void *devfs_handle_t; -#define XGI_DEVFS_REGISTER(_name, _minor) \ - ({ \ - devfs_handle_t __handle = NULL; \ - if (devfs_mk_cdev(MKDEV(XGI_DEV_MAJOR, _minor), \ - S_IFCHR | S_IRUGO | S_IWUGO, _name) == 0) \ - { \ - __handle = (void *) 1; /* XXX Fix me! (boolean) */ \ - } \ - __handle; \ - }) -/* -#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi%d", i) -*/ -#define XGI_DEVFS_REMOVE_CONTROL() devfs_remove("xgi_ctl") -#define XGI_DEVFS_REMOVE_DEVICE(i) devfs_remove("xgi") -#endif /* defined(CONFIG_DEVFS_FS) */ - -#define XGI_REGISTER_CHRDEV(x...) register_chrdev(x) -#define XGI_UNREGISTER_CHRDEV(x...) unregister_chrdev(x) - -#if defined(XGI_REMAP_PFN_RANGE_PRESENT) -#define XGI_REMAP_PAGE_RANGE(from, offset, x...) \ - remap_pfn_range(vma, from, ((offset) >> PAGE_SHIFT), x) -#elif defined(XGI_REMAP_PAGE_RANGE_5) -#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) -#elif defined(XGI_REMAP_PAGE_RANGE_4) -#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(x) -#else -#warning "xgi_configure.sh failed, assuming remap_page_range(5)!" -#define XGI_REMAP_PAGE_RANGE(x...) remap_page_range(vma, x) -#endif - -#if defined(pmd_offset_map) -#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ - { \ - pg_mid_dir = pmd_offset_map(pg_dir, address); \ - } -#define XGI_PMD_UNMAP(pg_mid_dir) \ - { \ - pmd_unmap(pg_mid_dir); \ - } -#else -#define XGI_PMD_OFFSET(addres, pg_dir, pg_mid_dir) \ - { \ - pg_mid_dir = pmd_offset(pg_dir, address); \ - } -#define XGI_PMD_UNMAP(pg_mid_dir) -#endif - -#define XGI_PMD_PRESENT(pg_mid_dir) \ - ({ \ - if ((pg_mid_dir) && (pmd_none(*pg_mid_dir))) \ - { \ - XGI_PMD_UNMAP(pg_mid_dir); \ - pg_mid_dir = NULL; \ - } \ - pg_mid_dir != NULL; \ - }) - -#if defined(pte_offset_atomic) -#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset_atomic(pg_mid_dir, address); \ - XGI_PMD_UNMAP(pg_mid_dir); \ - } -#define XGI_PTE_UNMAP(pte) \ - { \ - pte_kunmap(pte); \ - } -#elif defined(pte_offset) -#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset(pg_mid_dir, address); \ - XGI_PMD_UNMAP(pg_mid_dir); \ - } -#define XGI_PTE_UNMAP(pte) -#else -#define XGI_PTE_OFFSET(addres, pg_mid_dir, pte) \ - { \ - pte = pte_offset_map(pg_mid_dir, address); \ - XGI_PMD_UNMAP(pg_mid_dir); \ - } -#define XGI_PTE_UNMAP(pte) \ - { \ - pte_unmap(pte); \ - } -#endif - -#define XGI_PTE_PRESENT(pte) \ - ({ \ - if (pte) \ - { \ - if (!pte_present(*pte)) \ - { \ - XGI_PTE_UNMAP(pte); pte = NULL; \ - } \ - } \ - pte != NULL; \ - }) - -#define XGI_PTE_VALUE(pte) \ - ({ \ - unsigned long __pte_value = pte_val(*pte); \ - XGI_PTE_UNMAP(pte); \ - __pte_value; \ - }) - -#define XGI_PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) / PAGE_SIZE) -#define XGI_MASK_OFFSET(addr) ((addr) & (PAGE_SIZE - 1)) - -#if !defined (pgprot_noncached) -static inline pgprot_t pgprot_noncached(pgprot_t old_prot) -{ - pgprot_t new_prot = old_prot; - if (boot_cpu_data.x86 > 3) - new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_PCD); - return new_prot; -} -#endif - -#if defined(XGI_BUILD_XGI_PAT_SUPPORT) && !defined (pgprot_writecombined) -/* Added define for write combining page, only valid if pat enabled. */ -#define _PAGE_WRTCOMB _PAGE_PWT -#define __PAGE_KERNEL_WRTCOMB \ - (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_WRTCOMB | _PAGE_ACCESSED) -#define PAGE_KERNEL_WRTCOMB MAKE_GLOBAL(__PAGE_KERNEL_WRTCOMB) - -static inline pgprot_t pgprot_writecombined(pgprot_t old_prot) -{ - pgprot_t new_prot = old_prot; - if (boot_cpu_data.x86 > 3) { - pgprot_val(old_prot) &= ~(_PAGE_PCD | _PAGE_PWT); - new_prot = __pgprot(pgprot_val(old_prot) | _PAGE_WRTCOMB); - } - return new_prot; -} -#endif - -#if !defined(page_to_pfn) -#define page_to_pfn(page) ((page) - mem_map) -#endif - -#define XGI_VMALLOC(ptr, size) \ - { \ - (ptr) = vmalloc_32(size); \ - } - -#define XGI_VFREE(ptr, size) \ - { \ - vfree((void *) (ptr)); \ - } - -#define XGI_IOREMAP(ptr, physaddr, size) \ - { \ - (ptr) = ioremap(physaddr, size); \ - } - -#define XGI_IOREMAP_NOCACHE(ptr, physaddr, size) \ - { \ - (ptr) = ioremap_nocache(physaddr, size); \ - } - -#define XGI_IOUNMAP(ptr, size) \ - { \ - iounmap(ptr); \ - } - -/* - * only use this because GFP_KERNEL may sleep.. - * GFP_ATOMIC is ok, it won't sleep - */ -#define XGI_KMALLOC(ptr, size) \ - { \ - (ptr) = kmalloc(size, GFP_KERNEL); \ - } - -#define XGI_KMALLOC_ATOMIC(ptr, size) \ - { \ - (ptr) = kmalloc(size, GFP_ATOMIC); \ - } - -#define XGI_KFREE(ptr, size) \ - { \ - kfree((void *) (ptr)); \ - } - -#define XGI_GET_FREE_PAGES(ptr, order) \ - { \ - (ptr) = __get_free_pages(GFP_KERNEL, order); \ - } - -#define XGI_FREE_PAGES(ptr, order) \ - { \ - free_pages(ptr, order); \ - } - -struct xgi_pte { - unsigned long phys_addr; - unsigned long virt_addr; -}; - -/* - * AMD Athlon processors expose a subtle bug in the Linux - * kernel, that may lead to AGP memory corruption. Recent - * kernel versions had a workaround for this problem, but - * 2.4.20 is the first kernel to address it properly. The - * page_attr API provides the means to solve the problem. - */ -static inline void XGI_SET_PAGE_ATTRIB_UNCACHED(struct xgi_pte * page_ptr) -{ - struct page *page = virt_to_page(__va(page_ptr->phys_addr)); - change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); -} -static inline void XGI_SET_PAGE_ATTRIB_CACHED(struct xgi_pte * page_ptr) -{ - struct page *page = virt_to_page(__va(page_ptr->phys_addr)); - change_page_attr(page, 1, PAGE_KERNEL); -} - -/* add for SUSE 9, Jill*/ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 4) -#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->count) -#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->count) -#define XGI_PAGE_COUNT(page) atomic_read(&(page)->count) -#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->count, v) -#else -#define XGI_INC_PAGE_COUNT(page) atomic_inc(&(page)->_count) -#define XGI_DEC_PAGE_COUNT(page) atomic_dec(&(page)->_count) -#define XGI_PAGE_COUNT(page) atomic_read(&(page)->_count) -#define XGI_SET_PAGE_COUNT(page,v) atomic_set(&(page)->_count, v) -#endif -#define XGILockPage(page) SetPageLocked(page) -#define XGIUnlockPage(page) ClearPageLocked(page) - -struct xgi_file_private { - struct xgi_info *info; - unsigned int num_events; - spinlock_t fp_lock; - wait_queue_head_t wait_queue; -}; - -#define FILE_PRIVATE(filp) ((filp)->private_data) - -#define XGI_GET_FP(filp) ((struct xgi_file_private *) FILE_PRIVATE(filp)) - -/* for the card devices */ -#define XGI_INFO_FROM_FP(filp) (XGI_GET_FP(filp)->info) - -#define INODE_FROM_FP(filp) ((filp)->f_dentry->d_inode) - -#define XGI_ATOMIC_SET(data,val) atomic_set(&(data), (val)) -#define XGI_ATOMIC_INC(data) atomic_inc(&(data)) -#define XGI_ATOMIC_DEC(data) atomic_dec(&(data)) -#define XGI_ATOMIC_DEC_AND_TEST(data) atomic_dec_and_test(&(data)) -#define XGI_ATOMIC_READ(data) atomic_read(&(data)) - -/* - * lock-related functions that should only be called from this file - */ -#define xgi_init_lock(lock) spin_lock_init(&lock) -#define xgi_lock(lock) spin_lock(&lock) -#define xgi_unlock(lock) spin_unlock(&lock) -#define xgi_down(lock) down(&lock) -#define xgi_up(lock) up(&lock) - -#define xgi_lock_irqsave(lock,flags) spin_lock_irqsave(&lock,flags) -#define xgi_unlock_irqsave(lock,flags) spin_unlock_irqrestore(&lock,flags) - -#endif diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index bb2813ca..7f3d9d6e 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -26,17 +26,21 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" -#include "xgi_pcie.h" -void xgi_ge_reset(struct xgi_info * info) +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 */ @@ -113,7 +117,7 @@ static void xgi_ge_hang_reset(volatile u8 *mmio_vbase) u8 old_index; u8 old_36; - XGI_INFO("Can not reset back 0x%x!\n", + DRM_INFO("Can not reset back 0x%x!\n", ge_3d_status[0x00]); *(mmio_vbase + 0xb057) = 0; @@ -151,7 +155,7 @@ static void xgi_ge_hang_reset(volatile u8 *mmio_vbase) bool xgi_ge_irq_handler(struct xgi_info * info) { - volatile u8 *const mmio_vbase = info->mmio.vbase; + 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]; @@ -185,7 +189,7 @@ bool xgi_ge_irq_handler(struct xgi_info * info) continue_int_count = 0; /* GE Hung up, need reset. */ - XGI_INFO("Reset GE!\n"); + DRM_INFO("Reset GE!\n"); xgi_ge_hang_reset(mmio_vbase); } @@ -205,23 +209,23 @@ bool xgi_ge_irq_handler(struct xgi_info * info) bool xgi_crt_irq_handler(struct xgi_info * info) { bool ret = FALSE; - u8 save_3ce = bReadReg(0x3ce); + u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce); - if (bIn3cf(0x37) & 0x01) // CRT1 interrupt just happened + if (IN3CFB(info->mmio_map, 0x37) & 0x01) // CRT1 interrupt just happened { u8 op3cf_3d; u8 op3cf_37; // What happened? - op3cf_37 = bIn3cf(0x37); + op3cf_37 = IN3CFB(info->mmio_map, 0x37); // Clear CRT interrupt - op3cf_3d = bIn3cf(0x3d); - bOut3cf(0x3d, (op3cf_3d | 0x04)); - bOut3cf(0x3d, (op3cf_3d & ~0x04)); + 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; } - bWriteReg(0x3ce, save_3ce); + DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce); return (ret); } @@ -229,36 +233,36 @@ bool xgi_crt_irq_handler(struct xgi_info * info) bool xgi_dvi_irq_handler(struct xgi_info * info) { bool ret = FALSE; - u8 save_3ce = bReadReg(0x3ce); + const u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce); - if (bIn3cf(0x38) & 0x20) // DVI interrupt just happened - { + 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; - u8 save_3x4 = bReadReg(0x3d4);; // What happened? - op3cf_37 = bIn3cf(0x37); + op3cf_37 = IN3CFB(info->mmio_map, 0x37); //Notify BIOS that DVI plug/unplug happened - op3x5_5a = bIn3x5(0x5a); - bOut3x5(0x5a, op3x5_5a & 0xf7); + op3x5_5a = IN3X5B(info->mmio_map, 0x5a); + OUT3X5B(info->mmio_map, 0x5a, op3x5_5a & 0xf7); - bWriteReg(0x3d4, save_3x4); + DRM_WRITE8(info->mmio_map, 0x3d4, save_3x4); // Clear DVI interrupt - op3cf_39 = bIn3cf(0x39); - bOut3c5(0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0 - bOut3c5(0x39, (op3cf_39 | 0x01)); //Set 3cf.39 bit 0 to 1 + 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; } - bWriteReg(0x3ce, save_3ce); + DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce); return (ret); } + void xgi_dump_register(struct xgi_info * info) { int i, j; @@ -281,7 +285,7 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bIn3c5(i * 0x10 + j); + temp = IN3C5B(info->mmio_map, i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); @@ -303,7 +307,7 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bIn3x5(i * 0x10 + j); + temp = IN3X5B(info->mmio_map, i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); @@ -325,7 +329,7 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bIn3cf(i * 0x10 + j); + temp = IN3CFB(info->mmio_map, i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); @@ -346,7 +350,7 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bReadReg(0xB000 + i * 0x10 + j); + temp = DRM_READ8(info->mmio_map, 0xB000 + i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); @@ -366,7 +370,7 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bReadReg(0x2200 + i * 0x10 + j); + temp = DRM_READ8(info->mmio_map, 0x2200 + i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); @@ -386,7 +390,7 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bReadReg(0x2300 + i * 0x10 + j); + temp = DRM_READ8(info->mmio_map, 0x2300 + i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); @@ -406,7 +410,7 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bReadReg(0x2400 + i * 0x10 + j); + temp = DRM_READ8(info->mmio_map, 0x2400 + i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); @@ -426,17 +430,34 @@ void xgi_dump_register(struct xgi_info * info) printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = bReadReg(0x2800 + i * 0x10 + j); + temp = DRM_READ8(info->mmio_map, 0x2800 + i * 0x10 + j); printk("%3x", temp); } printk("\r\n"); } } -void xgi_restore_registers(struct xgi_info * info) + +int xgi_dump_register_ioctl(DRM_IOCTL_ARGS) { - bOut3x5(0x13, 0); - bOut3x5(0x8b, 2); + 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) @@ -446,60 +467,10 @@ void xgi_waitfor_pci_idle(struct xgi_info * info) int idleCount = 0; while (idleCount < 5) { - if (dwReadReg(WHOLD_GE_STATUS) & IDLE_MASK) { + if (DRM_READ32(info->mmio_map, WHOLD_GE_STATUS) & IDLE_MASK) { idleCount = 0; } else { idleCount++; } } } - - -/*memory collect function*/ -extern struct list_head xgi_mempid_list; -void xgi_mem_collect(struct xgi_info * info, unsigned int *pcnt) -{ - struct xgi_mem_pid *block; - struct xgi_mem_pid *next; - struct task_struct *p, *find; - unsigned int cnt = 0; - - list_for_each_entry_safe(block, next, &xgi_mempid_list, list) { - - find = NULL; - XGI_SCAN_PROCESS(p) { - if (p->pid == block->pid) { - XGI_INFO - ("[!]Find active pid:%ld state:%ld location:%d addr:0x%lx! \n", - block->pid, p->state, - block->location, - block->bus_addr); - find = p; - if (block->bus_addr == 0xFFFFFFFF) - ++cnt; - break; - } - } - if (!find) { - if (block->location == XGI_MEMLOC_LOCAL) { - XGI_INFO - ("Memory ProcessID free fb and delete one block pid:%ld addr:0x%lx successfully! \n", - block->pid, block->bus_addr); - xgi_fb_free(info, block->bus_addr); - } else if (block->bus_addr != 0xFFFFFFFF) { - XGI_INFO - ("Memory ProcessID free pcie and delete one block pid:%ld addr:0x%lx successfully! \n", - block->pid, block->bus_addr); - xgi_pcie_free(info, block->bus_addr); - } else { - /*only delete the memory block */ - list_del(&block->list); - XGI_INFO - ("Memory ProcessID delete one pcie block pid:%ld successfully! \n", - block->pid); - kfree(block); - } - } - } - *pcnt = cnt; -} diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h index 9c0591b2..10638b2d 100644 --- a/linux-core/xgi_misc.h +++ b/linux-core/xgi_misc.h @@ -30,9 +30,7 @@ #define _XGI_MISC_H_ extern void xgi_dump_register(struct xgi_info * info); -extern void xgi_ge_reset(struct xgi_info * info); -extern void xgi_restore_registers(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); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index cfc9febc..49c531fc 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -26,176 +26,81 @@ * DEALINGS IN THE SOFTWARE. ***************************************************************************/ -#include "xgi_linux.h" #include "xgi_drv.h" #include "xgi_regs.h" -#include "xgi_pcie.h" #include "xgi_misc.h" -static struct xgi_pcie_heap *xgi_pcie_heap = NULL; -static struct kmem_cache *xgi_pcie_cache_block = NULL; -static struct xgi_pcie_block *xgi_pcie_vertex_block = NULL; -static struct xgi_pcie_block *xgi_pcie_cmdlist_block = NULL; -static struct xgi_pcie_block *xgi_pcie_scratchpad_block = NULL; -extern struct list_head xgi_mempid_list; - -static unsigned long xgi_pcie_lut_alloc(unsigned long page_order) -{ - struct page *page; - unsigned long page_addr = 0; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - - if (page_addr == 0UL) { - XGI_ERROR("Can't get free pages: 0x%lx from system memory !\n", - page_count); - return 0; - } - - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) { - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - } - - XGI_INFO("page_count: 0x%lx page_order: 0x%lx page_addr: 0x%lx \n", - page_count, page_order, page_addr); - return page_addr; -} - -static void xgi_pcie_lut_free(unsigned long page_addr, unsigned long page_order) -{ - struct page *page; - unsigned long page_count = 0; - int i; - - page_count = (1 << page_order); - page = virt_to_page(page_addr); - - for (i = 0; i < page_count; i++, page++) { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - - free_pages(page_addr, page_order); -} +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_lut_init(struct xgi_info * info) { - unsigned char *page_addr = NULL; - unsigned long pciePageCount, lutEntryNum, lutPageCount, lutPageOrder; - unsigned long count = 0; u8 temp = 0; + int err; + unsigned i; + struct drm_scatter_gather request; + struct drm_sg_mem *sg; + u32 *lut; - /* Jong 06/06/2006 */ - unsigned long pcie_aperture_size; - - info->pcie.size = 128 * 1024 * 1024; /* Get current FB aperture size */ - temp = In3x5(0x27); - XGI_INFO("In3x5(0x27): 0x%x \n", temp); + temp = IN3X5B(info->mmio_map, 0x27); + DRM_INFO("In3x5(0x27): 0x%x \n", temp); if (temp & 0x01) { /* 256MB; Jong 06/05/2006; 0x10000000 */ - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size = 256 * 1024 * 1024; - /* info->pcie.base = 256 * 1024 * 1024; *//* pcie base is different from fb base */ + info->pcie.base = 256 * 1024 * 1024; } else { /* 128MB; Jong 06/05/2006; 0x08000000 */ - - /* Jong 06/06/2006; allocate memory */ - pcie_aperture_size = 128 * 1024 * 1024; - /* info->pcie.base = 128 * 1024 * 1024; */ + info->pcie.base = 128 * 1024 * 1024; } - /* Jong 06/06/2006; allocate memory; it can be used for build-in kernel modules */ - /* info->pcie.base=(unsigned long)alloc_bootmem(pcie_mem_size); */ - /* total 496 MB; need 256 MB (0x10000000); start from 240 MB (0x0F000000) */ - /* info->pcie.base=ioremap(0x0F000000, 0x10000000); *//* Cause system hang */ - info->pcie.base = pcie_aperture_size; /* works */ - /* info->pcie.base=info->fb.base + info->fb.size; *//* System hang */ - /* info->pcie.base=128 * 1024 * 1024; *//* System hang */ - XGI_INFO("Jong06062006-info->pcie.base: 0x%lx \n", info->pcie.base); + DRM_INFO("info->pcie.base: 0x%lx\n", (unsigned long) info->pcie.base); /* Get current lookup table page size */ - temp = bReadReg(0xB00C); + temp = DRM_READ8(info->mmio_map, 0xB00C); if (temp & 0x04) { /* 8KB */ info->lutPageSize = 8 * 1024; } else { /* 4KB */ - info->lutPageSize = 4 * 1024; } - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + DRM_INFO("info->lutPageSize: 0x%x \n", info->lutPageSize); -#if 0 - /* Get current lookup table location */ - temp = bReadReg(0xB00C); - if (temp & 0x02) { /* LFB */ - info->isLUTInLFB = TRUE; - /* Current we only support lookup table in LFB */ - temp &= 0xFD; - bWriteReg(0xB00C, temp); - info->isLUTInLFB = FALSE; - } else { /* SFB */ - info->isLUTInLFB = FALSE; + 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; } - XGI_INFO("info->lutPageSize: 0x%lx \n", info->lutPageSize); + sg = info->dev->sg; - /* Get current SDFB page size */ - temp = bReadReg(0xB00C); - if (temp & 0x08) { /* 8MB */ - info->sdfbPageSize = 8 * 1024 * 1024; - } else { /* 4MB */ - - info->sdfbPageSize = 4 * 1024 * 1024; + 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); } -#endif - pciePageCount = (info->pcie.size + PAGE_SIZE - 1) / PAGE_SIZE; - /* - * Allocate memory for PCIE GART table; - */ - lutEntryNum = pciePageCount; - lutPageCount = (lutEntryNum * 4 + PAGE_SIZE - 1) / PAGE_SIZE; - - /* get page_order base on page_count */ - count = lutPageCount; - for (lutPageOrder = 0; count; count >>= 1, ++lutPageOrder) ; - - if ((lutPageCount << 1) == (1 << lutPageOrder)) { - lutPageOrder -= 1; - } - - XGI_INFO("lutEntryNum: 0x%lx lutPageCount: 0x%lx lutPageOrder 0x%lx\n", - lutEntryNum, lutPageCount, lutPageOrder); - - info->lutPageOrder = lutPageOrder; - page_addr = (unsigned char *)xgi_pcie_lut_alloc(lutPageOrder); + 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])); + } - if (!page_addr) { - XGI_ERROR("cannot allocate PCIE lut page!\n"); - goto fail; + lut[i] = info->dev->sg->busaddr[i]; } - info->lut_base = (unsigned long *)page_addr; - - XGI_INFO("page_addr: 0x%p virt_to_phys(page_virtual): 0x%lx \n", - page_addr, virt_to_phys(page_addr)); - - XGI_INFO - ("info->lut_base: 0x%p __pa(info->lut_base): 0x%lx info->lutPageOrder 0x%lx\n", - info->lut_base, __pa(info->lut_base), info->lutPageOrder); - - /* - * clean all PCIE GART Entry - */ - memset(page_addr, 0, PAGE_SIZE << lutPageOrder); #if defined(__i386__) || defined(__x86_64__) asm volatile ("wbinvd":::"memory"); @@ -204,675 +109,186 @@ static int xgi_pcie_lut_init(struct xgi_info * info) #endif /* Set GART in SFB */ - bWriteReg(0xB00C, bReadReg(0xB00C) & ~0x02); + temp = DRM_READ8(info->mmio_map, 0xB00C); + DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); + /* Set GART base address to HW */ - dwWriteReg(0xB034, __pa(info->lut_base)); + dwWriteReg(info->mmio_map, 0xB034, info->lut_handle->busaddr); - return 1; - fail: return 0; } -static void xgi_pcie_lut_cleanup(struct xgi_info * info) -{ - if (info->lut_base) { - XGI_INFO("info->lut_base: 0x%p info->lutPageOrder: 0x%lx \n", - info->lut_base, info->lutPageOrder); - xgi_pcie_lut_free((unsigned long)info->lut_base, - info->lutPageOrder); - info->lut_base = NULL; - } -} - -static struct xgi_pcie_block *xgi_pcie_new_node(void) +void xgi_pcie_lut_cleanup(struct xgi_info * info) { - struct xgi_pcie_block *block = - (struct xgi_pcie_block *) kmem_cache_alloc(xgi_pcie_cache_block, - GFP_KERNEL); - if (block == NULL) { - return NULL; + if (info->dev->sg) { + drm_sg_free(info->dev, info->dev->sg->handle); } - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = 0; /* The block size. */ - block->bus_addr = 0; /* CPU access address/bus address */ - block->hw_addr = 0; /* GE access address */ - block->page_count = 0; - block->page_order = 0; - block->page_block = NULL; - block->page_table = NULL; - block->owner = PCIE_INVALID; - - return block; -} - -static void xgi_pcie_block_stuff_free(struct xgi_pcie_block * block) -{ - struct page *page; - struct xgi_page_block *page_block = block->page_block; - struct xgi_page_block *free_block; - unsigned long page_count = 0; - int i; - - //XGI_INFO("block->page_block: 0x%p \n", block->page_block); - while (page_block) { - page_count = page_block->page_count; - - page = virt_to_page(page_block->virt_addr); - for (i = 0; i < page_count; i++, page++) { - XGI_DEC_PAGE_COUNT(page); - XGIUnlockPage(page); - } - free_pages(page_block->virt_addr, page_block->page_order); - - page_block->phys_addr = 0; - page_block->virt_addr = 0; - page_block->page_count = 0; - page_block->page_order = 0; - - free_block = page_block; - page_block = page_block->next; - //XGI_INFO("free free_block: 0x%p \n", free_block); - kfree(free_block); - free_block = NULL; - } - - if (block->page_table) { - //XGI_INFO("free block->page_table: 0x%p \n", block->page_table); - kfree(block->page_table); - block->page_table = NULL; + 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) { - struct xgi_pcie_block *block; - - if (!xgi_pcie_lut_init(info)) { - XGI_ERROR("xgi_pcie_lut_init failed\n"); - return 0; - } - - xgi_pcie_heap = - (struct xgi_pcie_heap *) kmalloc(sizeof(struct xgi_pcie_heap), GFP_KERNEL); - if (!xgi_pcie_heap) { - XGI_ERROR("xgi_pcie_heap alloc failed\n"); - goto fail1; - } - INIT_LIST_HEAD(&xgi_pcie_heap->free_list); - INIT_LIST_HEAD(&xgi_pcie_heap->used_list); - INIT_LIST_HEAD(&xgi_pcie_heap->sort_list); - - xgi_pcie_heap->max_freesize = info->pcie.size; - - xgi_pcie_cache_block = - kmem_cache_create("xgi_pcie_block", sizeof(struct xgi_pcie_block), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + int err; - if (NULL == xgi_pcie_cache_block) { - XGI_ERROR("Fail to creat xgi_pcie_block\n"); - goto fail2; + err = xgi_pcie_lut_init(info); + if (err) { + DRM_ERROR("xgi_pcie_lut_init failed\n"); + return err; } - block = (struct xgi_pcie_block *) xgi_pcie_new_node(); - if (!block) { - XGI_ERROR("xgi_pcie_new_node failed\n"); - goto fail3; - } - - block->offset = 0; /* block's offset in pcie memory, begin from 0 */ - block->size = info->pcie.size; - - list_add(&block->list, &xgi_pcie_heap->free_list); - XGI_INFO("PCIE start address: 0x%lx, memory size : 0x%lx\n", - block->offset, block->size); - return 1; - fail3: - if (xgi_pcie_cache_block) { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; + err = xgi_mem_heap_init(&info->pcie_heap, 0, info->pcie.size); + if (err) { + xgi_pcie_lut_cleanup(info); } - fail2: - if (xgi_pcie_heap) { - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } - fail1: - xgi_pcie_lut_cleanup(info); - return 0; + return err; } -void xgi_pcie_heap_cleanup(struct xgi_info * info) -{ - struct list_head *free_list; - struct xgi_pcie_block *block; - struct xgi_pcie_block *next; - int j; - - xgi_pcie_lut_cleanup(info); - XGI_INFO("xgi_pcie_lut_cleanup scceeded\n"); - - if (xgi_pcie_heap) { - free_list = &xgi_pcie_heap->free_list; - for (j = 0; j < 3; j++, free_list++) { - list_for_each_entry_safe(block, next, free_list, list) { - XGI_INFO - ("No. %d block offset: 0x%lx size: 0x%lx\n", - j, block->offset, block->size); - xgi_pcie_block_stuff_free(block); - block->bus_addr = 0; - block->hw_addr = 0; - - //XGI_INFO("No. %d free block: 0x%p \n", j, block); - kmem_cache_free(xgi_pcie_cache_block, block); - } - } - - XGI_INFO("free xgi_pcie_heap: 0x%p \n", xgi_pcie_heap); - kfree(xgi_pcie_heap); - xgi_pcie_heap = NULL; - } - if (xgi_pcie_cache_block) { - kmem_cache_destroy(xgi_pcie_cache_block); - xgi_pcie_cache_block = NULL; - } -} - -static struct xgi_pcie_block *xgi_pcie_mem_alloc(struct xgi_info * info, - unsigned long originalSize, - enum PcieOwner owner) +int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, + DRMFILE filp) { - struct xgi_pcie_block *block, *used_block, *free_block; - struct xgi_page_block *page_block, *prev_page_block; - struct page *page; - unsigned long page_order = 0, count = 0, index = 0; - unsigned long page_addr = 0; - u32 *lut_addr = NULL; - unsigned long lut_id = 0; - unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; - int i, j, page_count = 0; - int temp = 0; - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-Begin\n"); - XGI_INFO("Original 0x%lx bytes requested, really 0x%lx allocated\n", - originalSize, size); - - if (owner == PCIE_3D) { - if (xgi_pcie_vertex_block) { - XGI_INFO - ("PCIE Vertex has been created, return directly.\n"); - return xgi_pcie_vertex_block; - } - } + struct xgi_mem_block *block; - if (owner == PCIE_3D_CMDLIST) { - if (xgi_pcie_cmdlist_block) { - XGI_INFO - ("PCIE Cmdlist has been created, return directly.\n"); - return xgi_pcie_cmdlist_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; } - - if (owner == PCIE_3D_SCRATCHPAD) { - if (xgi_pcie_scratchpad_block) { - XGI_INFO - ("PCIE Scratchpad has been created, return directly.\n"); - return xgi_pcie_scratchpad_block; - } - } - - if (size == 0) { - XGI_ERROR("size == 0 \n"); - return (NULL); + 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; } - - XGI_INFO("max_freesize: 0x%lx \n", xgi_pcie_heap->max_freesize); - if (size > xgi_pcie_heap->max_freesize) { - XGI_ERROR - ("size: 0x%lx bigger than PCIE total free size: 0x%lx.\n", - size, xgi_pcie_heap->max_freesize); - return (NULL); + 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); - /* Jong 05/30/2006; find next free list which has enough space */ - list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { - if (size <= block->size) { - break; + 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->list == &xgi_pcie_heap->free_list) { - XGI_ERROR("Can't allocate %ldk size from PCIE memory !\n", - size / 1024); - return (NULL); - } - - free_block = block; - XGI_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; - XGI_INFO("size==free_block->size: free_block = 0x%p\n", - free_block); - list_del(&free_block->list); + if (block == NULL) { + alloc->location = XGI_MEMLOC_INVALID; + alloc->size = 0; + DRM_ERROR("PCIE RAM allocation failed\n"); + return DRM_ERR(ENOMEM); } else { - used_block = xgi_pcie_new_node(); - if (used_block == NULL) { - return NULL; - } - - if (used_block == free_block) { - XGI_ERROR("used_block == free_block = 0x%p\n", - used_block); - } - - used_block->offset = free_block->offset; - used_block->size = size; + 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; - free_block->offset += size; - free_block->size -= size; + block->filp = filp; + return 0; } +} - xgi_pcie_heap->max_freesize -= size; - used_block->bus_addr = info->pcie.base + used_block->offset; - used_block->hw_addr = info->pcie.base + used_block->offset; - used_block->page_count = page_count = size / PAGE_SIZE; +int xgi_pcie_alloc_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + struct xgi_mem_alloc alloc; + struct xgi_info *info = dev->dev_private; + int err; - /* get page_order base on page_count */ - for (used_block->page_order = 0; page_count; page_count >>= 1) { - ++used_block->page_order; - } + DRM_COPY_FROM_USER_IOCTL(alloc, (struct xgi_mem_alloc __user *) data, + sizeof(alloc)); - if ((used_block->page_count << 1) == (1 << used_block->page_order)) { - used_block->page_order--; - } - XGI_INFO - ("used_block->offset: 0x%lx, used_block->size: 0x%lx, used_block->bus_addr: 0x%lx, used_block->hw_addr: 0x%lx, used_block->page_count: 0x%lx used_block->page_order: 0x%lx\n", - used_block->offset, used_block->size, used_block->bus_addr, - used_block->hw_addr, used_block->page_count, - used_block->page_order); - - used_block->page_block = NULL; - //used_block->page_block = (struct xgi_pages_block *)kmalloc(sizeof(struct xgi_pages_block), GFP_KERNEL); - //if (!used_block->page_block) return NULL;_t - //used_block->page_block->next = NULL; - - used_block->page_table = - (struct xgi_pte *) kmalloc(sizeof(struct xgi_pte) * used_block->page_count, - GFP_KERNEL); - if (used_block->page_table == NULL) { - goto fail; + 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)); - lut_id = (used_block->offset >> PAGE_SHIFT); - lut_addr = info->lut_base; - lut_addr += lut_id; - XGI_INFO("lutAddr: 0x%p lutID: 0x%lx \n", lut_addr, lut_id); - - /* alloc free pages from system */ - page_count = used_block->page_count; - page_block = used_block->page_block; - prev_page_block = used_block->page_block; - for (i = 0; page_count > 0; i++) { - /* if size is bigger than 2M bytes, it should be split */ - if (page_count > (1 << XGI_PCIE_ALLOC_MAX_ORDER)) { - page_order = XGI_PCIE_ALLOC_MAX_ORDER; - } else { - count = page_count; - for (page_order = 0; count; count >>= 1, ++page_order) ; - - if ((page_count << 1) == (1 << page_order)) { - page_order -= 1; - } - } + return 0; +} - count = (1 << page_order); - page_addr = __get_free_pages(GFP_KERNEL, page_order); - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-page_addr=0x%lx \n", - page_addr); - if (!page_addr) { - XGI_ERROR - ("No: %d :Can't get free pages: 0x%lx from system memory !\n", - i, count); - goto fail; - } +/** + * 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; + } - /* Jong 05/30/2006; test */ - memset((unsigned char *)page_addr, 0xFF, - PAGE_SIZE << page_order); - /* memset((unsigned char *)page_addr, 0, PAGE_SIZE << page_order); */ - - if (page_block == NULL) { - page_block = - (struct xgi_page_block *) - kmalloc(sizeof(struct xgi_page_block), GFP_KERNEL); - if (!page_block) { - XGI_ERROR - ("Can't get memory for page_block! \n"); - goto fail; - } - } + down(&info->pcie_sem); - if (prev_page_block == NULL) { - used_block->page_block = page_block; - prev_page_block = page_block; - } else { - prev_page_block->next = page_block; - prev_page_block = page_block; - } + do { + struct xgi_mem_block *block; - page_block->next = NULL; - page_block->phys_addr = __pa(page_addr); - page_block->virt_addr = page_addr; - page_block->page_count = count; - page_block->page_order = page_order; - - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-page_block->phys_addr=0x%lx \n", - page_block->phys_addr); - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-page_block->virt_addr=0x%lx \n", - page_block->virt_addr); - - page = virt_to_page(page_addr); - - //XGI_INFO("No: %d page_order: 0x%lx page_count: 0x%x count: 0x%lx index: 0x%lx lut_addr: 0x%p" - // "page_block->phys_addr: 0x%lx page_block->virt_addr: 0x%lx \n", - // i, page_order, page_count, count, index, lut_addr, page_block->phys_addr, page_block->virt_addr); - - for (j = 0; j < count; j++, page++, lut_addr++) { - used_block->page_table[index + j].phys_addr = - __pa(page_address(page)); - used_block->page_table[index + j].virt_addr = - (unsigned long)page_address(page); - - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].phys_addr=0x%lx \n", - used_block->page_table[index + j].phys_addr); - XGI_INFO - ("Jong05302006-xgi_pcie_mem_alloc-used_block->page_table[index + j].virt_addr=0x%lx \n", - used_block->page_table[index + j].virt_addr); - - *lut_addr = __pa(page_address(page)); - XGI_INC_PAGE_COUNT(page); - XGILockPage(page); - - if (temp) { - XGI_INFO - ("__pa(page_address(page)): 0x%lx lutAddr: 0x%p lutAddr No: 0x%x = 0x%lx \n", - __pa(page_address(page)), lut_addr, j, - *lut_addr); - temp--; + list_for_each_entry(block, &info->pcie_heap.used_list, list) { + if (block->filp == filp) { + break; } } - page_block = page_block->next; - page_count -= count; - index += count; - temp = 0; - } - - used_block->owner = owner; - list_add(&used_block->list, &xgi_pcie_heap->used_list); - -#if defined(__i386__) || defined(__x86_64__) - asm volatile ("wbinvd":::"memory"); -#else - mb(); -#endif - - /* Flush GART Table */ - bWriteReg(0xB03F, 0x40); - bWriteReg(0xB03F, 0x00); - - if (owner == PCIE_3D) { - xgi_pcie_vertex_block = used_block; - } - - if (owner == PCIE_3D_CMDLIST) { - xgi_pcie_cmdlist_block = used_block; - } - - if (owner == PCIE_3D_SCRATCHPAD) { - xgi_pcie_scratchpad_block = used_block; - } - - XGI_INFO("Jong05302006-xgi_pcie_mem_alloc-End \n"); - return (used_block); - - fail: - xgi_pcie_block_stuff_free(used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - return NULL; -} - -static struct xgi_pcie_block *xgi_pcie_mem_free(struct xgi_info * info, - unsigned long offset) -{ - struct xgi_pcie_block *used_block, *block; - struct xgi_pcie_block *prev, *next; - unsigned long upper, lower; - - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - if (block->offset == offset) { + if (&block->list == &info->pcie_heap.used_list) { break; } - } - - if (&block->list == &xgi_pcie_heap->used_list) { - XGI_ERROR("can't find block: 0x%lx to free!\n", offset); - return (NULL); - } - - used_block = block; - XGI_INFO - ("used_block: 0x%p, offset = 0x%lx, size = 0x%lx, bus_addr = 0x%lx, hw_addr = 0x%lx\n", - used_block, used_block->offset, used_block->size, - used_block->bus_addr, used_block->hw_addr); - - xgi_pcie_block_stuff_free(used_block); - /* update xgi_pcie_heap */ - xgi_pcie_heap->max_freesize += used_block->size; + (void) xgi_pcie_free(info, block->offset, filp); + } while(1); - prev = next = NULL; - upper = used_block->offset + used_block->size; - lower = used_block->offset; - - list_for_each_entry(block, &xgi_pcie_heap->free_list, list) { - if (block->offset == upper) { - next = block; - } else if ((block->offset + block->size) == lower) { - prev = block; - } - } - - XGI_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); - XGI_INFO("free node 0x%p\n", next); - kmem_cache_free(xgi_pcie_cache_block, next); - kmem_cache_free(xgi_pcie_cache_block, used_block); - next = NULL; - used_block = NULL; - return (prev); - } - - if (prev) { - prev->size += used_block->size; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (prev); - } - - if (next) { - next->size += used_block->size; - next->offset = used_block->offset; - XGI_INFO("free node 0x%p\n", used_block); - kmem_cache_free(xgi_pcie_cache_block, used_block); - used_block = NULL; - return (next); - } - - used_block->bus_addr = 0; - used_block->hw_addr = 0; - used_block->page_count = 0; - used_block->page_order = 0; - list_add(&used_block->list, &xgi_pcie_heap->free_list); - XGI_INFO("Recycled free node %p, offset = 0x%lx, size = 0x%lx\n", - used_block, used_block->offset, used_block->size); - return (used_block); + up(&info->pcie_sem); } -void xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - pid_t pid) -{ - struct xgi_pcie_block *block; - - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_alloc(info, alloc->size, alloc->owner); - xgi_up(info->pcie_sem); - - if (block == NULL) { - alloc->location = XGI_MEMLOC_INVALID; - alloc->size = 0; - alloc->bus_addr = 0; - alloc->hw_addr = 0; - XGI_ERROR("PCIE RAM allocation failed\n"); - } else { - XGI_INFO - ("PCIE RAM allocation succeeded: offset = 0x%lx, bus_addr = 0x%lx\n", - block->offset, block->bus_addr); - alloc->location = XGI_MEMLOC_NON_LOCAL; - alloc->size = block->size; - alloc->bus_addr = block->bus_addr; - alloc->hw_addr = block->hw_addr; - - /* - manage mempid, handle PCIE_3D, PCIE_3D_TEXTURE. - PCIE_3D request means a opengl process created. - PCIE_3D_TEXTURE request means texture cannot alloc from fb. - */ - if ((alloc->owner == PCIE_3D) - || (alloc->owner == PCIE_3D_TEXTURE)) { - struct xgi_mem_pid *mempid_block = - kmalloc(sizeof(struct xgi_mem_pid), GFP_KERNEL); - if (!mempid_block) - XGI_ERROR("mempid_block alloc failed\n"); - mempid_block->location = XGI_MEMLOC_NON_LOCAL; - if (alloc->owner == PCIE_3D) - mempid_block->bus_addr = 0xFFFFFFFF; /*xgi_pcie_vertex_block has the address */ - else - mempid_block->bus_addr = alloc->bus_addr; - mempid_block->pid = pid; - - XGI_INFO - ("Memory ProcessID add one pcie block pid:%ld successfully! \n", - mempid_block->pid); - list_add(&mempid_block->list, &xgi_mempid_list); - } - } -} -void xgi_pcie_free(struct xgi_info * info, unsigned long bus_addr) +int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) { - struct xgi_pcie_block *block; - unsigned long offset = bus_addr - info->pcie.base; - struct xgi_mem_pid *mempid_block; - struct xgi_mem_pid *mempid_freeblock = NULL; - char isvertex = 0; - int processcnt; - - if (xgi_pcie_vertex_block - && xgi_pcie_vertex_block->bus_addr == bus_addr) - isvertex = 1; - - if (isvertex) { - /*check is there any other process using vertex */ - processcnt = 0; - - list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == XGI_MEMLOC_NON_LOCAL - && mempid_block->bus_addr == 0xFFFFFFFF) { - ++processcnt; - } - } - if (processcnt > 1) { - return; - } - } + const bool isvertex = (xgi_pcie_vertex_block + && (xgi_pcie_vertex_block->offset == offset)); + int err; - xgi_down(info->pcie_sem); - block = xgi_pcie_mem_free(info, offset); - xgi_up(info->pcie_sem); + down(&info->pcie_sem); + err = xgi_mem_free(&info->pcie_heap, offset, filp); + up(&info->pcie_sem); - if (block == NULL) { - XGI_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); + if (err) { + DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); } if (isvertex) xgi_pcie_vertex_block = NULL; - /* manage mempid */ - list_for_each_entry(mempid_block, &xgi_mempid_list, list) { - if (mempid_block->location == XGI_MEMLOC_NON_LOCAL - && ((isvertex && mempid_block->bus_addr == 0xFFFFFFFF) - || (!isvertex && mempid_block->bus_addr == bus_addr))) { - mempid_freeblock = mempid_block; - break; - } - } - if (mempid_freeblock) { - list_del(&mempid_freeblock->list); - XGI_INFO - ("Memory ProcessID delete one pcie block pid:%ld successfully! \n", - mempid_freeblock->pid); - kfree(mempid_freeblock); - } + return err; } -/* - * given a bus address, fid the pcie mem block - * uses the bus address as the key. - */ -struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, - unsigned long address) -{ - struct xgi_pcie_block *block; - int i; - - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - if (block->bus_addr == address) { - return block; - } - - if (block->page_table) { - for (i = 0; i < block->page_count; i++) { - unsigned long offset = block->bus_addr; - if ((address >= offset) - && (address < (offset + PAGE_SIZE))) { - return block; - } - } - } - } +int xgi_pcie_free_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + struct xgi_info *info = dev->dev_private; + u32 offset; - XGI_ERROR("could not find map for vm 0x%lx\n", address); + DRM_COPY_FROM_USER_IOCTL(offset, (unsigned long __user *) data, + sizeof(offset)); - return NULL; + return xgi_pcie_free(info, offset, filp); } + /** * xgi_find_pcie_virt * @address: GE HW address @@ -880,60 +296,43 @@ struct xgi_pcie_block *xgi_find_pcie_block(struct xgi_info * info, * Returns CPU virtual address. Assumes the CPU VAddr is continuous in not * the same block */ -void *xgi_find_pcie_virt(struct xgi_info * info, unsigned long address) +void *xgi_find_pcie_virt(struct xgi_info * info, u32 address) { - struct xgi_pcie_block *block; - const unsigned long offset_in_page = address & (PAGE_SIZE - 1); - - XGI_INFO("begin (address = 0x%lx, offset_in_page = %lu)\n", - address, offset_in_page); - - list_for_each_entry(block, &xgi_pcie_heap->used_list, list) { - XGI_INFO("block = 0x%p (hw_addr = 0x%lx, size=%lu)\n", - block, block->hw_addr, block->size); - - if ((address >= block->hw_addr) - && (address < (block->hw_addr + block->size))) { - const unsigned long loc_in_pagetable = - (address - block->hw_addr) >> PAGE_SHIFT; - void *const ret = - (void *)(block->page_table[loc_in_pagetable]. - virt_addr + offset_in_page); - - XGI_INFO("PAGE_SHIFT = %d\n", PAGE_SHIFT); - XGI_INFO("block->page_table[0x%lx].virt_addr = 0x%lx\n", - loc_in_pagetable, - block->page_table[loc_in_pagetable].virt_addr); - XGI_INFO("return 0x%p\n", ret); - - return ret; - } - } + const unsigned long offset = address - info->pcie.base; - XGI_ERROR("could not find map for vm 0x%lx\n", address); - return NULL; + return ((u8 *) info->dev->sg->virtual) + offset; } /* address -- GE hw address */ -void xgi_test_rwinkernel(struct xgi_info * info, unsigned long address) +int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) { + DRM_DEVICE; + struct xgi_info *info = dev->dev_private; + u32 address; u32 *virtaddr = 0; - XGI_INFO("input GE HW addr is 0x%x\n", address); + 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; + return DRM_ERR(EFAULT); } virtaddr = (u32 *)xgi_find_pcie_virt(info, address); - XGI_INFO("convert to CPU virt addr 0x%p\n", virtaddr); + DRM_INFO("convert to CPU virt addr 0x%p\n", virtaddr); if (virtaddr != NULL) { - XGI_INFO("original [virtaddr] = 0x%x\n", *virtaddr); + DRM_INFO("original [virtaddr] = 0x%x\n", *virtaddr); *virtaddr = 0x00f00fff; - XGI_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); + DRM_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); + } else { + return DRM_ERR(EFAULT); } + + return 0; } diff --git a/linux-core/xgi_pcie.h b/linux-core/xgi_pcie.h deleted file mode 100644 index b66d6a28..00000000 --- a/linux-core/xgi_pcie.h +++ /dev/null @@ -1,68 +0,0 @@ - -/**************************************************************************** - * 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_PCIE_H_ -#define _XGI_PCIE_H_ - -#ifndef XGI_PCIE_ALLOC_MAX_ORDER -#define XGI_PCIE_ALLOC_MAX_ORDER 1 /* 8K in Kernel 2.4.* */ -#endif - -struct xgi_page_block { - struct xgi_page_block *next; - unsigned long phys_addr; - unsigned long virt_addr; - unsigned long page_count; - unsigned long page_order; -}; - -struct xgi_pcie_block { - struct list_head list; - unsigned long offset; /* block's offset in pcie memory, begin from 0 */ - unsigned long size; /* The block size. */ - unsigned long bus_addr; /* CPU access address/bus address */ - unsigned long hw_addr; /* GE access address */ - - unsigned long page_count; - unsigned long page_order; - struct xgi_page_block *page_block; - struct xgi_pte *page_table; /* list of physical pages allocated */ - - atomic_t use_count; - enum PcieOwner owner; - unsigned long processID; -}; - -struct xgi_pcie_heap { - struct list_head free_list; - struct list_head used_list; - struct list_head sort_list; - unsigned long max_freesize; -}; - -#endif diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index bc3e2a1e..b211626a 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -29,269 +29,100 @@ #ifndef _XGI_REGS_H_ #define _XGI_REGS_H_ -#ifndef XGI_MMIO -#define XGI_MMIO 1 -#endif +#include "drmP.h" +#include "drm.h" -#if XGI_MMIO -#define OUTB(port, value) writeb(value, info->mmio.vbase + port) -#define INB(port) readb(info->mmio.vbase + port) -#define OUTW(port, value) writew(value, info->mmio.vbase + port) -#define INW(port) readw(info->mmio.vbase + port) -#define OUTDW(port, value) writel(value, info->mmio.vbase + port) -#define INDW(port) readl(info->mmio.vbase + port) -#else -#define OUTB(port, value) outb(value, port) -#define INB(port) inb(port) -#define OUTW(port, value) outw(value, port) -#define INW(port) inw(port) -#define OUTDW(port, value) outl(value, port) -#define INDW(port) inl(port) -#endif /* Hardware access functions */ -static inline void OUT3C5B(struct xgi_info * info, u8 index, u8 data) -{ - OUTB(0x3C4, index); - OUTB(0x3C5, data); -} - -static inline void OUT3X5B(struct xgi_info * info, u8 index, u8 data) -{ - OUTB(0x3D4, index); - OUTB(0x3D5, data); -} - -static inline void OUT3CFB(struct xgi_info * info, u8 index, u8 data) -{ - OUTB(0x3CE, index); - OUTB(0x3CF, data); -} - -static inline u8 IN3C5B(struct xgi_info * info, u8 index) -{ - volatile u8 data = 0; - OUTB(0x3C4, index); - data = INB(0x3C5); - return data; -} - -static inline u8 IN3X5B(struct xgi_info * info, u8 index) +static inline void OUT3C5B(struct drm_map * map, u8 index, u8 data) { - volatile u8 data = 0; - OUTB(0x3D4, index); - data = INB(0x3D5); - return data; + DRM_WRITE8(map, 0x3C4, index); + DRM_WRITE8(map, 0x3C5, data); } -static inline u8 IN3CFB(struct xgi_info * info, u8 index) +static inline void OUT3X5B(struct drm_map * map, u8 index, u8 data) { - volatile u8 data = 0; - OUTB(0x3CE, index); - data = INB(0x3CF); - return data; + DRM_WRITE8(map, 0x3D4, index); + DRM_WRITE8(map, 0x3D5, data); } -static inline void OUT3C5W(struct xgi_info * info, u8 index, u16 data) +static inline void OUT3CFB(struct drm_map * map, u8 index, u8 data) { - OUTB(0x3C4, index); - OUTB(0x3C5, data); + DRM_WRITE8(map, 0x3CE, index); + DRM_WRITE8(map, 0x3CF, data); } -static inline void OUT3X5W(struct xgi_info * info, u8 index, u16 data) +static inline u8 IN3C5B(struct drm_map * map, u8 index) { - OUTB(0x3D4, index); - OUTB(0x3D5, data); + DRM_WRITE8(map, 0x3C4, index); + return DRM_READ8(map, 0x3C5); } -static inline void OUT3CFW(struct xgi_info * info, u8 index, u8 data) +static inline u8 IN3X5B(struct drm_map * map, u8 index) { - OUTB(0x3CE, index); - OUTB(0x3CF, data); + DRM_WRITE8(map, 0x3D4, index); + return DRM_READ8(map, 0x3D5); } -static inline u8 IN3C5W(struct xgi_info * info, u8 index) +static inline u8 IN3CFB(struct drm_map * map, u8 index) { - volatile u8 data = 0; - OUTB(0x3C4, index); - data = INB(0x3C5); - return data; + DRM_WRITE8(map, 0x3CE, index); + return DRM_READ8(map, 0x3CF); } -static inline u8 IN3X5W(struct xgi_info * info, u8 index) -{ - volatile u8 data = 0; - OUTB(0x3D4, index); - data = INB(0x3D5); - return data; -} - -static inline u8 IN3CFW(struct xgi_info * info, u8 index) -{ - volatile u8 data = 0; - OUTB(0x3CE, index); - data = INB(0x3CF); - return data; -} - -static inline u8 readAttr(struct xgi_info * info, u8 index) -{ - INB(0x3DA); /* flip-flop to index */ - OUTB(0x3C0, index); - return INB(0x3C1); -} - -static inline void writeAttr(struct xgi_info * info, u8 index, u8 value) -{ - INB(0x3DA); /* flip-flop to index */ - OUTB(0x3C0, index); - OUTB(0x3C0, value); -} /* * Graphic engine register (2d/3d) acessing interface */ -static inline void WriteRegDWord(struct xgi_info * info, u32 addr, u32 data) -{ - XGI_INFO("mmio vbase = 0x%p, addr = 0x%x, data = 0x%x\n", - info->mmio->vbase, addr, data); - - *(volatile u32 *)(info->mmio.vbase + addr) = (data); -} - -static inline void WriteRegWord(struct xgi_info * info, u32 addr, u16 data) +static inline void dwWriteReg(struct drm_map * map, u32 addr, u32 data) { - *(volatile u16 *)(info->mmio.vbase + addr) = (data); -} - -static inline void WriteRegByte(struct xgi_info * info, u32 addr, u8 data) -{ - *(volatile u8 *)(info->mmio.vbase + addr) = (data); -} - -static inline u32 ReadRegDWord(struct xgi_info * info, u32 addr) -{ - volatile u32 data; - data = *(volatile u32 *)(info->mmio.vbase + addr); - return data; -} - -static inline u16 ReadRegWord(struct xgi_info * info, u32 addr) -{ - volatile u16 data; - data = *(volatile u16 *)(info->mmio.vbase + addr); - return data; -} + DRM_INFO("mmio_map->handle = 0x%p, addr = 0x%x, data = 0x%x\n", + map->handle, addr, data); -static inline u8 ReadRegByte(struct xgi_info * info, u32 addr) -{ - volatile u8 data; - data = *(volatile u8 *)(info->mmio.vbase + addr); - return data; + DRM_WRITE32(map, addr, data); } -#if 0 -extern void OUT3C5B(struct xgi_info * info, u8 index, u8 data); -extern void OUT3X5B(struct xgi_info * info, u8 index, u8 data); -extern void OUT3CFB(struct xgi_info * info, u8 index, u8 data); -extern u8 IN3C5B(struct xgi_info * info, u8 index); -extern u8 IN3X5B(struct xgi_info * info, u8 index); -extern u8 IN3CFB(struct xgi_info * info, u8 index); -extern void OUT3C5W(struct xgi_info * info, u8 index, u8 data); -extern void OUT3X5W(struct xgi_info * info, u8 index, u8 data); -extern void OUT3CFW(struct xgi_info * info, u8 index, u8 data); -extern u8 IN3C5W(struct xgi_info * info, u8 index); -extern u8 IN3X5W(struct xgi_info * info, u8 index); -extern u8 IN3CFW(struct xgi_info * info, u8 index); - -extern void WriteRegDWord(struct xgi_info * info, u32 addr, u32 data); -extern void WriteRegWord(struct xgi_info * info, u32 addr, u16 data); -extern void WriteRegByte(struct xgi_info * info, u32 addr, u8 data); -extern u32 ReadRegDWord(struct xgi_info * info, u32 addr); -extern u16 ReadRegWord(struct xgi_info * info, u32 addr); -extern u8 ReadRegByte(struct xgi_info * info, u32 addr); - -extern void EnableProtect(); -extern void DisableProtect(); -#endif - -#define Out(port, data) OUTB(port, data) -#define bOut(port, data) OUTB(port, data) -#define wOut(port, data) OUTW(port, data) -#define dwOut(port, data) OUTDW(port, data) - -#define Out3x5(index, data) OUT3X5B(info, index, data) -#define bOut3x5(index, data) OUT3X5B(info, index, data) -#define wOut3x5(index, data) OUT3X5W(info, index, data) - -#define Out3c5(index, data) OUT3C5B(info, index, data) -#define bOut3c5(index, data) OUT3C5B(info, index, data) -#define wOut3c5(index, data) OUT3C5W(info, index, data) - -#define Out3cf(index, data) OUT3CFB(info, index, data) -#define bOut3cf(index, data) OUT3CFB(info, index, data) -#define wOut3cf(index, data) OUT3CFW(info, index, data) - -#define In(port) INB(port) -#define bIn(port) INB(port) -#define wIn(port) INW(port) -#define dwIn(port) INDW(port) - -#define In3x5(index) IN3X5B(info, index) -#define bIn3x5(index) IN3X5B(info, index) -#define wIn3x5(index) IN3X5W(info, index) - -#define In3c5(index) IN3C5B(info, index) -#define bIn3c5(index) IN3C5B(info, index) -#define wIn3c5(index) IN3C5W(info, index) - -#define In3cf(index) IN3CFB(info, index) -#define bIn3cf(index) IN3CFB(info, index) -#define wIn3cf(index) IN3CFW(info, index) - -#define dwWriteReg(addr, data) WriteRegDWord(info, addr, data) -#define wWriteReg(addr, data) WriteRegWord(info, addr, data) -#define bWriteReg(addr, data) WriteRegByte(info, addr, data) -#define dwReadReg(addr) ReadRegDWord(info, addr) -#define wReadReg(addr) ReadRegWord(info, addr) -#define bReadReg(addr) ReadRegByte(info, addr) static inline void xgi_enable_mmio(struct xgi_info * info) { u8 protect = 0; + u8 temp; /* Unprotect registers */ - outb(0x11, 0x3C4); - protect = inb(0x3C5); - outb(0x92, 0x3C5); + DRM_WRITE8(info->mmio_map, 0x3C4, 0x11); + protect = DRM_READ8(info->mmio_map, 0x3C5); + DRM_WRITE8(info->mmio_map, 0x3C5, 0x92); - outb(0x3A, 0x3D4); - outb(inb(0x3D5) | 0x20, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D4, 0x3A); + temp = DRM_READ8(info->mmio_map, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x20); /* Enable MMIO */ - outb(0x39, 0x3D4); - outb(inb(0x3D5) | 0x01, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D4, 0x39); + temp = DRM_READ8(info->mmio_map, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x01); - OUTB(0x3C4, 0x11); - OUTB(0x3C5, protect); + /* 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 */ - OUTB(0x3C4, 0x11); - protect = INB(0x3C5); - OUTB(0x3C5, 0x92); + /* 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 */ - OUTB(0x3D4, 0x39); - OUTB(0x3D5, INB(0x3D5) & 0xFE); + DRM_WRITE8(info->mmio_map, 0x3D4, 0x39); + temp = DRM_READ8(info->mmio_map, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D5, temp & 0xFE); /* Protect registers */ - outb(0x11, 0x3C4); - outb(protect, 0x3C5); + OUT3C5B(info->mmio_map, 0x11, protect); } static inline void xgi_enable_ge(struct xgi_info * info) @@ -300,36 +131,36 @@ static inline void xgi_enable_ge(struct xgi_info * info) int wait = 0; // Enable GE - OUTW(0x3C4, 0x9211); + DRM_WRITE16(info->mmio_map, 0x3C4, 0x9211); // Save and close dynamic gating - bOld3cf2a = bIn3cf(0x2a); - bOut3cf(0x2a, bOld3cf2a & 0xfe); + bOld3cf2a = IN3CFB(info->mmio_map, 0x2a); + OUT3CFB(info->mmio_map, 0x2a, bOld3cf2a & 0xfe); // Reset both 3D and 2D engine - bOut3x5(0x36, 0x84); + OUT3X5B(info->mmio_map, 0x36, 0x84); wait = 10; while (wait--) { - bIn(0x36); + DRM_READ8(info->mmio_map, 0x36); } - bOut3x5(0x36, 0x94); + OUT3X5B(info->mmio_map, 0x36, 0x94); wait = 10; while (wait--) { - bIn(0x36); + DRM_READ8(info->mmio_map, 0x36); } - bOut3x5(0x36, 0x84); + OUT3X5B(info->mmio_map, 0x36, 0x84); wait = 10; while (wait--) { - bIn(0x36); + DRM_READ8(info->mmio_map, 0x36); } // Enable 2D engine only - bOut3x5(0x36, 0x80); + OUT3X5B(info->mmio_map, 0x36, 0x80); // Enable 2D+3D engine - bOut3x5(0x36, 0x84); + OUT3X5B(info->mmio_map, 0x36, 0x84); // Restore dynamic gating - bOut3cf(0x2a, bOld3cf2a); + OUT3CFB(info->mmio_map, 0x2a, bOld3cf2a); } static inline void xgi_disable_ge(struct xgi_info * info) @@ -337,50 +168,50 @@ static inline void xgi_disable_ge(struct xgi_info * info) int wait = 0; // Reset both 3D and 2D engine - bOut3x5(0x36, 0x84); + OUT3X5B(info->mmio_map, 0x36, 0x84); wait = 10; while (wait--) { - bIn(0x36); + DRM_READ8(info->mmio_map, 0x36); } - bOut3x5(0x36, 0x94); + OUT3X5B(info->mmio_map, 0x36, 0x94); wait = 10; while (wait--) { - bIn(0x36); + DRM_READ8(info->mmio_map, 0x36); } - bOut3x5(0x36, 0x84); + OUT3X5B(info->mmio_map, 0x36, 0x84); wait = 10; while (wait--) { - bIn(0x36); + DRM_READ8(info->mmio_map, 0x36); } // Disable 2D engine only - bOut3x5(0x36, 0); + OUT3X5B(info->mmio_map, 0x36, 0); } static inline void xgi_enable_dvi_interrupt(struct xgi_info * info) { - Out3cf(0x39, In3cf(0x39) & ~0x01); //Set 3cf.39 bit 0 to 0 - Out3cf(0x39, In3cf(0x39) | 0x01); //Set 3cf.39 bit 0 to 1 - Out3cf(0x39, In3cf(0x39) | 0x02); + 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) { - Out3cf(0x39, In3cf(0x39) & ~0x02); + OUT3CFB(info->mmio_map, 0x39, IN3CFB(info->mmio_map, 0x39) & ~0x02); } static inline void xgi_enable_crt1_interrupt(struct xgi_info * info) { - Out3cf(0x3d, In3cf(0x3d) | 0x04); - Out3cf(0x3d, In3cf(0x3d) & ~0x04); - Out3cf(0x3d, In3cf(0x3d) | 0x08); + 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) { - Out3cf(0x3d, In3cf(0x3d) & ~0x08); + OUT3CFB(info->mmio_map, 0x3d, IN3CFB(info->mmio_map, 0x3d) & ~0x08); } #endif -- cgit v1.2.3 From 2f53ce4af2f7db911d908ff382738f30be004e8b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 11:05:13 -0700 Subject: Move MMIO drm_addmap (and code that depends on it) to xgi_bootstrap. For reasons that I don't understand, the drm_addmap call would succeed in xgi_driver_load, but writes to the map later would oops. Moving it to xgi_bootstrap fixes this problem. --- linux-core/xgi_drv.c | 62 ++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 3b9f4cb1..13e79169 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -188,7 +188,38 @@ int xgi_bootstrap(DRM_IOCTL_ARGS) return 0; } + err = drm_addmap(dev, info->mmio.base, info->mmio.size, + _DRM_REGISTERS, _DRM_KERNEL, + &info->mmio_map); + if (err) { + DRM_ERROR("Unable to map MMIO region: %d\n", err); + return err; + } + xgi_enable_mmio(info); + //xgi_enable_ge(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("frame buffer 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 */ + err = xgi_fb_heap_init(info); + if (err) { + DRM_ERROR("xgi_fb_heap_init() failed\n"); + return err; + } + + info->pcie.size = bs.gart_size * (1024 * 1024); @@ -280,36 +311,12 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags) } - 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; - } - - xgi_enable_mmio(info); - //xgi_enable_ge(info); - 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); - 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("frame buffer appears to be wrong: 0x%lx 0x%x\n", - (unsigned long) info->fb.base, info->fb.size); - return DRM_ERR(EINVAL); - } - - xgi_mem_block_cache = kmem_cache_create("xgi_mem_block", sizeof(struct xgi_mem_block), @@ -321,13 +328,6 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags) } - /* Init the resource manager */ - err = xgi_fb_heap_init(info); - if (err) { - DRM_ERROR("xgi_fb_heap_init() failed\n"); - return err; - } - return 0; } -- cgit v1.2.3 From 15245b670e5359a7dbf9151aa9f160e929e0b46b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 11:38:56 -0700 Subject: Rework xgi_(pcie|fb)_free_all to prevent deadlock. --- linux-core/xgi_fb.c | 2 +- linux-core/xgi_pcie.c | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index ce689847..a5885198 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -365,7 +365,7 @@ void xgi_fb_free_all(struct xgi_info * info, DRMFILE filp) break; } - (void) xgi_fb_free(info, block->offset, filp); + (void) xgi_mem_free(&info->fb_heap, block->offset, filp); } while(1); up(&info->fb_sem); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 49c531fc..9dee888b 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -34,6 +34,9 @@ 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; @@ -248,30 +251,39 @@ void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp) break; } - (void) xgi_pcie_free(info, block->offset, filp); + (void) xgi_pcie_free_locked(info, block->offset, filp); } while(1); up(&info->pcie_sem); } -int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) +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_mem_free(&info->pcie_heap, offset, filp); + 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); } - if (isvertex) - xgi_pcie_vertex_block = NULL; - return err; } -- cgit v1.2.3 From a33f5487296eacf503f5b27ba829f5fbdae8e63b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 19:05:52 -0700 Subject: Debug message and comment clean up in xgi_submit_cmdlist. --- linux-core/xgi_cmdlist.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index d2018057..2fdfcc91 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -66,58 +66,43 @@ static void xgi_submit_cmdlist(struct xgi_info * info, { const unsigned int beginPort = getCurBatchBeginPort(pCmdInfo); - DRM_INFO("After getCurBatchBeginPort()\n"); if (s_cmdring._lastBatchStartAddr == 0) { const unsigned int portOffset = BASE_3D_ENG + beginPort; - /* Jong 06/13/2006; remove marked for system hang test */ - /* xgi_waitfor_pci_idle(info); */ - // Enable PCI Trigger Mode + /* Enable PCI Trigger Mode + */ DRM_INFO("Enable PCI Trigger Mode \n"); - - /* Jong 06/14/2006; 0x400001a */ 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); - /* Jong 06/14/2006; 0x400000a */ 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 - DRM_INFO("Send PCI begin command \n"); + /* Send PCI begin command + */ DRM_INFO("portOffset=%d, beginPort=%d\n", portOffset, beginPort); - /* beginPort = 48; */ - /* 0xc100000 */ dwWriteReg(info->mmio_map, portOffset, (beginPort << 22) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); - DRM_INFO("Send PCI begin command- After\n"); - - /* 0x80000024 */ dwWriteReg(info->mmio_map, portOffset + 4, BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); - /* 0x1010000 */ dwWriteReg(info->mmio_map, portOffset + 8, (pCmdInfo->_firstBeginAddr >> 4)); - /* Jong 06/12/2006; system hang; marked for test */ dwWriteReg(info->mmio_map, portOffset + 12, 0); - - /* Jong 06/13/2006; remove marked for system hang test */ - /* xgi_waitfor_pci_idle(info); */ } else { u32 *lastBatchVirtAddr; @@ -154,7 +139,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, } s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; - DRM_INFO("End\n"); + DRM_INFO("%s: exit\n", __func__); } -- cgit v1.2.3 From 970674f4867d65bd16cf3585d46930b72a827cce Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 19:08:47 -0700 Subject: Fix error handing related to xgi_cmdlist_initialize. xgi_cmdlist_initialize wasn't correctly checking for errors from xgi_pcie_alloc. Furthermore, xgi_bootstrap, the one caller of xgi_cmdlist_initialize, wasn't check its return value. --- linux-core/xgi_cmdlist.c | 10 +++++----- linux-core/xgi_drv.c | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 2fdfcc91..885b5066 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -45,11 +45,11 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) .size = size, .owner = PCIE_2D, }; + int err; - xgi_pcie_alloc(info, &mem_alloc, 0); - - if ((mem_alloc.size == 0) && (mem_alloc.hw_addr == 0)) { - return -1; + err = xgi_pcie_alloc(info, &mem_alloc, 0); + if (err) { + return err; } s_cmdring._cmdRingSize = mem_alloc.size; @@ -58,7 +58,7 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) s_cmdring._lastBatchStartAddr = 0; s_cmdring._cmdRingOffset = 0; - return 1; + return 0; } static void xgi_submit_cmdlist(struct xgi_info * info, diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 13e79169..c4e7daae 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -231,7 +231,11 @@ int xgi_bootstrap(DRM_IOCTL_ARGS) } /* Alloc 1M bytes for cmdbuffer which is flush2D batch array */ - xgi_cmdlist_initialize(info, 0x100000); + err = xgi_cmdlist_initialize(info, 0x100000); + if (err) { + DRM_ERROR("xgi_cmdlist_initialize() failed\n"); + return err; + } info->bootstrap_done = 1; return 0; -- cgit v1.2.3 From 56665a42f470d5cf8cb4865558cb658dff15a9dd Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 19 Jul 2007 19:09:24 -0700 Subject: Delete unused variable in xgi_driver_load. --- linux-core/xgi_drv.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index c4e7daae..bcb6946d 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -286,11 +286,8 @@ void xgi_kern_isr_bh(struct drm_device *dev) int xgi_driver_load(struct drm_device *dev, unsigned long flags) { - struct xgi_info *info; - int err; - + struct xgi_info *info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER); - info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER); if (!info) return DRM_ERR(ENOMEM); -- cgit v1.2.3 From 6bd848307485f678915913f282e2ea59ae3ca1a8 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 20 Jul 2007 10:57:40 -0700 Subject: Change handling of begin types slightly. Moved the getCurBatchBeginPort before its only caller. Modified function to return the command ID instead of the port offset. Function also now assumes input begin type is value. Added code to ioctl handler to validate begin type. --- linux-core/xgi_cmdlist.c | 54 +++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 24 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 885b5066..6cc4c142 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -34,7 +34,7 @@ struct xgi_cmdring_info s_cmdring; static void addFlush2D(struct xgi_info * info); -static unsigned int getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo); +static unsigned int get_batch_command(enum xgi_batch_type type); static void triggerHWCommandList(struct xgi_info * info, unsigned int triggerCounter); static void xgi_cmdlist_reset(void); @@ -61,14 +61,33 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) 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, - struct xgi_cmd_info * pCmdInfo) + const struct xgi_cmd_info * pCmdInfo) { - const unsigned int beginPort = getCurBatchBeginPort(pCmdInfo); + const unsigned int cmd = get_batch_command(pCmdInfo->_firstBeginType); if (s_cmdring._lastBatchStartAddr == 0) { - const unsigned int portOffset = BASE_3D_ENG + beginPort; + const unsigned int portOffset = BASE_3D_ENG + (cmd << 2); /* Enable PCI Trigger Mode @@ -90,10 +109,10 @@ static void xgi_submit_cmdlist(struct xgi_info * info, /* Send PCI begin command */ DRM_INFO("portOffset=%d, beginPort=%d\n", - portOffset, beginPort); + portOffset, cmd << 2); dwWriteReg(info->mmio_map, portOffset, - (beginPort << 22) + (BEGIN_VALID_MASK) + + (cmd << 24) + (BEGIN_VALID_MASK) + pCmdInfo->_curDebugID); dwWriteReg(info->mmio_map, portOffset + 4, @@ -128,7 +147,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, lastBatchVirtAddr[3] = 0; //barrier(); lastBatchVirtAddr[0] = - (beginPort << 22) + (BEGIN_VALID_MASK) + + (cmd << 24) + (BEGIN_VALID_MASK) + (0xffff & pCmdInfo->_curDebugID); /* Jong 06/12/2006; system hang; marked for test */ @@ -153,6 +172,10 @@ int xgi_submit_cmdlist_ioctl(DRM_IOCTL_ARGS) (struct xgi_cmd_info __user *) data, sizeof(cmd_list)); + if (cmd_list._firstBeginType > BTYPE_CTRL) { + return DRM_ERR(EINVAL); + } + xgi_submit_cmdlist(info, &cmd_list); return 0; } @@ -238,23 +261,6 @@ static void triggerHWCommandList(struct xgi_info * info, } } -static unsigned int getCurBatchBeginPort(struct xgi_cmd_info * pCmdInfo) -{ - // Convert the batch type to begin port ID - switch (pCmdInfo->_firstBeginType) { - case BTYPE_2D: - return 0x30; - case BTYPE_3D: - return 0x40; - case BTYPE_FLIP: - return 0x50; - case BTYPE_CTRL: - return 0x20; - default: - //ASSERT(0); - return 0xff; - } -} static void addFlush2D(struct xgi_info * info) { -- cgit v1.2.3 From 659209cb2d59c7b25df58d130d0649f8f899b693 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 20 Jul 2007 11:29:16 -0700 Subject: Clean up generation of begin commands in xgi_submit_cmdlist Generate the begin command once in a temporary buffer. Then, depending on whether the command is to be written directly to the hardware or to a secondary buffer, copy to command to the correct place. --- linux-core/xgi_cmdlist.c | 49 ++++++++++++++++++------------------------------ linux-core/xgi_cmdlist.h | 1 + 2 files changed, 19 insertions(+), 31 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 6cc4c142..682c4ac1 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -84,8 +84,15 @@ static void xgi_submit_cmdlist(struct xgi_info * info, const struct xgi_cmd_info * pCmdInfo) { const unsigned int cmd = get_batch_command(pCmdInfo->_firstBeginType); + u32 begin[4]; + begin[0] = (cmd << 24) | (BEGIN_VALID_MASK) | + (BEGIN_BEGIN_IDENTIFICATION_MASK & pCmdInfo->_curDebugID); + begin[1] = BEGIN_LINK_ENABLE_MASK | pCmdInfo->_firstSize; + begin[2] = pCmdInfo->_firstBeginAddr >> 4; + begin[3] = 0; + if (s_cmdring._lastBatchStartAddr == 0) { const unsigned int portOffset = BASE_3D_ENG + (cmd << 2); @@ -111,17 +118,10 @@ static void xgi_submit_cmdlist(struct xgi_info * info, DRM_INFO("portOffset=%d, beginPort=%d\n", portOffset, cmd << 2); - dwWriteReg(info->mmio_map, portOffset, - (cmd << 24) + (BEGIN_VALID_MASK) + - pCmdInfo->_curDebugID); - - dwWriteReg(info->mmio_map, portOffset + 4, - BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize); - - dwWriteReg(info->mmio_map, portOffset + 8, - (pCmdInfo->_firstBeginAddr >> 4)); - - dwWriteReg(info->mmio_map, portOffset + 12, 0); + 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 { u32 *lastBatchVirtAddr; @@ -135,26 +135,13 @@ static void xgi_submit_cmdlist(struct xgi_info * info, xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); - /* lastBatchVirtAddr should *never* be NULL. However, there - * are currently some bugs that cause this to happen. The - * if-statement here prevents some fatal (i.e., hard lock - * requiring the reset button) oopses. - */ - if (lastBatchVirtAddr) { - lastBatchVirtAddr[1] = - BEGIN_LINK_ENABLE_MASK + pCmdInfo->_firstSize; - lastBatchVirtAddr[2] = pCmdInfo->_firstBeginAddr >> 4; - lastBatchVirtAddr[3] = 0; - //barrier(); - lastBatchVirtAddr[0] = - (cmd << 24) + (BEGIN_VALID_MASK) + - (0xffff & pCmdInfo->_curDebugID); - - /* Jong 06/12/2006; system hang; marked for test */ - triggerHWCommandList(info, pCmdInfo->_beginCount); - } else { - DRM_ERROR("lastBatchVirtAddr is NULL\n"); - } + lastBatchVirtAddr[1] = begin[1]; + lastBatchVirtAddr[2] = begin[2]; + lastBatchVirtAddr[3] = begin[3]; + wmb(); + lastBatchVirtAddr[0] = begin[0]; + + triggerHWCommandList(info, pCmdInfo->_beginCount); } s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 4bc56ec1..08029386 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -40,6 +40,7 @@ #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 { -- cgit v1.2.3 From ed82d5398a751cf755cf4168cbb79b181facc86f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 20 Jul 2007 11:31:01 -0700 Subject: Clean up flush command generation in addFlush2D. --- linux-core/xgi_cmdlist.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 682c4ac1..b93541f3 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -280,11 +280,9 @@ static void addFlush2D(struct xgi_info * info) lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; lastBatchVirtAddr[2] = flushBatchHWAddr >> 4; lastBatchVirtAddr[3] = 0; - - //barrier(); - - // BTYPE_CTRL & NO debugID - lastBatchVirtAddr[0] = (0x20 << 22) + (BEGIN_VALID_MASK); + wmb(); + lastBatchVirtAddr[0] = (get_batch_command(BTYPE_CTRL) << 24) + | (BEGIN_VALID_MASK); triggerHWCommandList(info, 1); -- cgit v1.2.3 From 5d6fdd9d7924fde8ce62631e6bdce8d5fe33fc3d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Sat, 21 Jul 2007 20:34:56 -0700 Subject: Clean up xgi_cmd_info and associated code. There were numerous unnecessary fields in xgi_cmd_info. The remaining fields had pretty crummy names. Cut out the cruft, and rename the rest. As a result, the unused parameter "triggerCounter" to triggerHWCommandList can be removed. --- linux-core/xgi_cmdlist.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index b93541f3..5c31fa27 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -35,8 +35,7 @@ struct xgi_cmdring_info s_cmdring; 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, - unsigned int triggerCounter); +static void triggerHWCommandList(struct xgi_info * info); static void xgi_cmdlist_reset(void); int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) @@ -83,14 +82,14 @@ unsigned int get_batch_command(enum xgi_batch_type type) static void xgi_submit_cmdlist(struct xgi_info * info, const struct xgi_cmd_info * pCmdInfo) { - const unsigned int cmd = get_batch_command(pCmdInfo->_firstBeginType); + const unsigned int cmd = get_batch_command(pCmdInfo->type); u32 begin[4]; - begin[0] = (cmd << 24) | (BEGIN_VALID_MASK) | - (BEGIN_BEGIN_IDENTIFICATION_MASK & pCmdInfo->_curDebugID); - begin[1] = BEGIN_LINK_ENABLE_MASK | pCmdInfo->_firstSize; - begin[2] = pCmdInfo->_firstBeginAddr >> 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 (s_cmdring._lastBatchStartAddr == 0) { @@ -127,7 +126,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, DRM_INFO("s_cmdring._lastBatchStartAddr != 0\n"); - if (pCmdInfo->_firstBeginType == BTYPE_3D) { + if (pCmdInfo->type == BTYPE_3D) { addFlush2D(info); } @@ -141,10 +140,10 @@ static void xgi_submit_cmdlist(struct xgi_info * info, wmb(); lastBatchVirtAddr[0] = begin[0]; - triggerHWCommandList(info, pCmdInfo->_beginCount); + triggerHWCommandList(info); } - s_cmdring._lastBatchStartAddr = pCmdInfo->_lastBeginAddr; + s_cmdring._lastBatchStartAddr = pCmdInfo->hw_addr; DRM_INFO("%s: exit\n", __func__); } @@ -159,7 +158,7 @@ int xgi_submit_cmdlist_ioctl(DRM_IOCTL_ARGS) (struct xgi_cmd_info __user *) data, sizeof(cmd_list)); - if (cmd_list._firstBeginType > BTYPE_CTRL) { + if (cmd_list.type > BTYPE_CTRL) { return DRM_ERR(EINVAL); } @@ -234,18 +233,13 @@ void xgi_cmdlist_cleanup(struct xgi_info * info) } } -static void triggerHWCommandList(struct xgi_info * info, - unsigned int triggerCounter) +static void triggerHWCommandList(struct xgi_info * info) { static unsigned int s_triggerID = 1; - //Fix me, currently we just trigger one time - while (triggerCounter--) { - dwWriteReg(info->mmio_map, - BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, - 0x05000000 + (0x0ffff & s_triggerID++)); - // xgi_waitfor_pci_idle(info); - } + dwWriteReg(info->mmio_map, + BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, + 0x05000000 + (0x0ffff & s_triggerID++)); } @@ -284,7 +278,7 @@ static void addFlush2D(struct xgi_info * info) lastBatchVirtAddr[0] = (get_batch_command(BTYPE_CTRL) << 24) | (BEGIN_VALID_MASK); - triggerHWCommandList(info, 1); + triggerHWCommandList(info); s_cmdring._cmdRingOffset += 0x20; s_cmdring._lastBatchStartAddr = flushBatchHWAddr; -- cgit v1.2.3 From 3265a61f895a1d35072984e9cdc71aad898647fa Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Sat, 21 Jul 2007 20:39:22 -0700 Subject: Make s_cmdring a field in the xgi_info structure instead of a global. --- linux-core/xgi_cmdlist.c | 54 +++++++++++++++++++++++------------------------- linux-core/xgi_cmdlist.h | 1 + linux-core/xgi_drv.h | 3 +++ 3 files changed, 30 insertions(+), 28 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 5c31fa27..a040fa15 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -31,12 +31,10 @@ #include "xgi_misc.h" #include "xgi_cmdlist.h" -struct xgi_cmdring_info s_cmdring; - 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(void); +static void xgi_cmdlist_reset(struct xgi_info * info); int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) { @@ -51,11 +49,11 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) return err; } - s_cmdring._cmdRingSize = mem_alloc.size; - s_cmdring._cmdRingBuffer = mem_alloc.hw_addr; - s_cmdring._cmdRingAllocOffset = mem_alloc.offset; - s_cmdring._lastBatchStartAddr = 0; - s_cmdring._cmdRingOffset = 0; + info->cmdring._cmdRingSize = mem_alloc.size; + info->cmdring._cmdRingBuffer = mem_alloc.hw_addr; + info->cmdring._cmdRingAllocOffset = mem_alloc.offset; + info->cmdring._lastBatchStartAddr = 0; + info->cmdring._cmdRingOffset = 0; return 0; } @@ -92,7 +90,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, begin[2] = pCmdInfo->hw_addr >> 4; begin[3] = 0; - if (s_cmdring._lastBatchStartAddr == 0) { + if (info->cmdring._lastBatchStartAddr == 0) { const unsigned int portOffset = BASE_3D_ENG + (cmd << 2); @@ -124,7 +122,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, } else { u32 *lastBatchVirtAddr; - DRM_INFO("s_cmdring._lastBatchStartAddr != 0\n"); + DRM_INFO("info->cmdring._lastBatchStartAddr != 0\n"); if (pCmdInfo->type == BTYPE_3D) { addFlush2D(info); @@ -132,7 +130,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, lastBatchVirtAddr = xgi_find_pcie_virt(info, - s_cmdring._lastBatchStartAddr); + info->cmdring._lastBatchStartAddr); lastBatchVirtAddr[1] = begin[1]; lastBatchVirtAddr[2] = begin[2]; @@ -143,7 +141,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, triggerHWCommandList(info); } - s_cmdring._lastBatchStartAddr = pCmdInfo->hw_addr; + info->cmdring._lastBatchStartAddr = pCmdInfo->hw_addr; DRM_INFO("%s: exit\n", __func__); } @@ -188,7 +186,7 @@ int xgi_state_change(struct xgi_info * info, unsigned int to, // stop to received batch } else if ((from == STATE_CONSOLE) && (to == STATE_GRAPHIC)) { DRM_INFO("[kd] I see, now is to enterVT\n"); - xgi_cmdlist_reset(); + xgi_cmdlist_reset(info); } else if ((from == STATE_GRAPHIC) && ((to == STATE_LOGOUT) || (to == STATE_REBOOT) @@ -217,19 +215,19 @@ int xgi_state_change_ioctl(DRM_IOCTL_ARGS) } -void xgi_cmdlist_reset(void) +void xgi_cmdlist_reset(struct xgi_info * info) { - s_cmdring._lastBatchStartAddr = 0; - s_cmdring._cmdRingOffset = 0; + info->cmdring._lastBatchStartAddr = 0; + info->cmdring._cmdRingOffset = 0; } void xgi_cmdlist_cleanup(struct xgi_info * info) { - if (s_cmdring._cmdRingBuffer != 0) { - xgi_pcie_free(info, s_cmdring._cmdRingAllocOffset, NULL); - s_cmdring._cmdRingBuffer = 0; - s_cmdring._cmdRingOffset = 0; - s_cmdring._cmdRingSize = 0; + if (info->cmdring._cmdRingBuffer != 0) { + xgi_pcie_free(info, info->cmdring._cmdRingAllocOffset, NULL); + info->cmdring._cmdRingBuffer = 0; + info->cmdring._cmdRingOffset = 0; + info->cmdring._cmdRingSize = 0; } } @@ -250,11 +248,11 @@ static void addFlush2D(struct xgi_info * info) u32 *lastBatchVirtAddr; /* check buf is large enough to contain a new flush batch */ - if ((s_cmdring._cmdRingOffset + 0x20) >= s_cmdring._cmdRingSize) { - s_cmdring._cmdRingOffset = 0; + if ((info->cmdring._cmdRingOffset + 0x20) >= info->cmdring._cmdRingSize) { + info->cmdring._cmdRingOffset = 0; } - flushBatchHWAddr = s_cmdring._cmdRingBuffer + s_cmdring._cmdRingOffset; + flushBatchHWAddr = info->cmdring._cmdRingBuffer + info->cmdring._cmdRingOffset; flushBatchVirtAddr = xgi_find_pcie_virt(info, flushBatchHWAddr); /* not using memcpy for I assume the address is discrete */ @@ -267,9 +265,9 @@ static void addFlush2D(struct xgi_info * info) *(flushBatchVirtAddr + 6) = FLUSH_2D; *(flushBatchVirtAddr + 7) = FLUSH_2D; - // ASSERT(s_cmdring._lastBatchStartAddr != NULL); + // ASSERT(info->cmdring._lastBatchStartAddr != NULL); lastBatchVirtAddr = - xgi_find_pcie_virt(info, s_cmdring._lastBatchStartAddr); + xgi_find_pcie_virt(info, info->cmdring._lastBatchStartAddr); lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; lastBatchVirtAddr[2] = flushBatchHWAddr >> 4; @@ -280,6 +278,6 @@ static void addFlush2D(struct xgi_info * info) triggerHWCommandList(info); - s_cmdring._cmdRingOffset += 0x20; - s_cmdring._lastBatchStartAddr = flushBatchHWAddr; + info->cmdring._cmdRingOffset += 0x20; + info->cmdring._lastBatchStartAddr = flushBatchHWAddr; } diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 08029386..7f2c54ac 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -66,6 +66,7 @@ struct xgi_cmdring_info { u32 _cmdRingOffset; }; +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, diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 20965876..0aab04d8 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -42,6 +42,7 @@ #define DRIVER_MINOR 8 #define DRIVER_PATCHLEVEL 0 +#include "xgi_cmdlist.h" #include "xgi_drm.h" struct xgi_aperture { @@ -90,6 +91,8 @@ struct xgi_info { struct semaphore fb_sem; struct semaphore pcie_sem; + + struct xgi_cmdring_info cmdring; }; enum PcieOwner { -- cgit v1.2.3 From 1a0775760c0eecbb238f0e928b185c267c1c3783 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Sat, 21 Jul 2007 21:35:06 -0700 Subject: Rename and document fields of xgi_cmdring_info. --- linux-core/xgi_cmdlist.c | 71 +++++++++++++++++++++--------------------------- linux-core/xgi_cmdlist.h | 33 ++++++++++++++++++---- 2 files changed, 59 insertions(+), 45 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index a040fa15..53bada50 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -49,11 +49,12 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) return err; } - info->cmdring._cmdRingSize = mem_alloc.size; - info->cmdring._cmdRingBuffer = mem_alloc.hw_addr; - info->cmdring._cmdRingAllocOffset = mem_alloc.offset; - info->cmdring._lastBatchStartAddr = 0; - info->cmdring._cmdRingOffset = 0; + info->cmdring.ptr = xgi_find_pcie_virt(info, mem_alloc.offset); + 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; } @@ -90,7 +91,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, begin[2] = pCmdInfo->hw_addr >> 4; begin[3] = 0; - if (info->cmdring._lastBatchStartAddr == 0) { + if (info->cmdring.last_ptr == NULL) { const unsigned int portOffset = BASE_3D_ENG + (cmd << 2); @@ -120,28 +121,22 @@ static void xgi_submit_cmdlist(struct xgi_info * info, dwWriteReg(info->mmio_map, portOffset + 8, begin[2]); dwWriteReg(info->mmio_map, portOffset + 12, begin[3]); } else { - u32 *lastBatchVirtAddr; - - DRM_INFO("info->cmdring._lastBatchStartAddr != 0\n"); + DRM_INFO("info->cmdring.last_ptr != NULL\n"); if (pCmdInfo->type == BTYPE_3D) { addFlush2D(info); } - lastBatchVirtAddr = - xgi_find_pcie_virt(info, - info->cmdring._lastBatchStartAddr); - - lastBatchVirtAddr[1] = begin[1]; - lastBatchVirtAddr[2] = begin[2]; - lastBatchVirtAddr[3] = begin[3]; + info->cmdring.last_ptr[1] = begin[1]; + info->cmdring.last_ptr[2] = begin[2]; + info->cmdring.last_ptr[3] = begin[3]; wmb(); - lastBatchVirtAddr[0] = begin[0]; + info->cmdring.last_ptr[0] = begin[0]; triggerHWCommandList(info); } - info->cmdring._lastBatchStartAddr = pCmdInfo->hw_addr; + info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr); DRM_INFO("%s: exit\n", __func__); } @@ -217,17 +212,17 @@ int xgi_state_change_ioctl(DRM_IOCTL_ARGS) void xgi_cmdlist_reset(struct xgi_info * info) { - info->cmdring._lastBatchStartAddr = 0; - info->cmdring._cmdRingOffset = 0; + info->cmdring.last_ptr = NULL; + info->cmdring.ring_offset = 0; } void xgi_cmdlist_cleanup(struct xgi_info * info) { - if (info->cmdring._cmdRingBuffer != 0) { - xgi_pcie_free(info, info->cmdring._cmdRingAllocOffset, NULL); - info->cmdring._cmdRingBuffer = 0; - info->cmdring._cmdRingOffset = 0; - info->cmdring._cmdRingSize = 0; + 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; } } @@ -245,15 +240,15 @@ static void addFlush2D(struct xgi_info * info) { u32 *flushBatchVirtAddr; u32 flushBatchHWAddr; - u32 *lastBatchVirtAddr; /* check buf is large enough to contain a new flush batch */ - if ((info->cmdring._cmdRingOffset + 0x20) >= info->cmdring._cmdRingSize) { - info->cmdring._cmdRingOffset = 0; + if ((info->cmdring.ring_offset + 0x20) >= info->cmdring.size) { + info->cmdring.ring_offset = 0; } - flushBatchHWAddr = info->cmdring._cmdRingBuffer + info->cmdring._cmdRingOffset; - flushBatchVirtAddr = xgi_find_pcie_virt(info, flushBatchHWAddr); + 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; @@ -265,19 +260,15 @@ static void addFlush2D(struct xgi_info * info) *(flushBatchVirtAddr + 6) = FLUSH_2D; *(flushBatchVirtAddr + 7) = FLUSH_2D; - // ASSERT(info->cmdring._lastBatchStartAddr != NULL); - lastBatchVirtAddr = - xgi_find_pcie_virt(info, info->cmdring._lastBatchStartAddr); - - lastBatchVirtAddr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; - lastBatchVirtAddr[2] = flushBatchHWAddr >> 4; - lastBatchVirtAddr[3] = 0; + info->cmdring.last_ptr[1] = BEGIN_LINK_ENABLE_MASK + 0x08; + info->cmdring.last_ptr[2] = flushBatchHWAddr >> 4; + info->cmdring.last_ptr[3] = 0; wmb(); - lastBatchVirtAddr[0] = (get_batch_command(BTYPE_CTRL) << 24) + info->cmdring.last_ptr[0] = (get_batch_command(BTYPE_CTRL) << 24) | (BEGIN_VALID_MASK); triggerHWCommandList(info); - info->cmdring._cmdRingOffset += 0x20; - info->cmdring._lastBatchStartAddr = flushBatchHWAddr; + info->cmdring.ring_offset += 0x20; + info->cmdring.last_ptr = flushBatchVirtAddr; } diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 7f2c54ac..5b444cf3 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -59,11 +59,34 @@ typedef enum { } CMD_SIZE; struct xgi_cmdring_info { - unsigned int _cmdRingSize; - u32 _cmdRingBuffer; - unsigned long _cmdRingAllocOffset; - u32 _lastBatchStartAddr; - u32 _cmdRingOffset; + /** + * 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; -- cgit v1.2.3 From 699207cf2fa0c5255365dd28eeb3dd760f362818 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Sat, 21 Jul 2007 21:37:45 -0700 Subject: Remove some extraneous debug messages. --- linux-core/xgi_cmdlist.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 53bada50..98d80ef0 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -97,8 +97,6 @@ static void xgi_submit_cmdlist(struct xgi_info * info, /* Enable PCI Trigger Mode */ - DRM_INFO("Enable PCI Trigger Mode \n"); - dwWriteReg(info->mmio_map, BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | @@ -113,9 +111,6 @@ static void xgi_submit_cmdlist(struct xgi_info * info, /* Send PCI begin command */ - DRM_INFO("portOffset=%d, beginPort=%d\n", - portOffset, cmd << 2); - dwWriteReg(info->mmio_map, portOffset, begin[0]); dwWriteReg(info->mmio_map, portOffset + 4, begin[1]); dwWriteReg(info->mmio_map, portOffset + 8, begin[2]); -- cgit v1.2.3 From 94203840fe53edaf1556d1a0a8a27773c24a7fc5 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Sat, 21 Jul 2007 23:00:01 -0700 Subject: Bump version. --- linux-core/xgi_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 0aab04d8..16102950 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -36,10 +36,10 @@ #define DRIVER_NAME "xgi" #define DRIVER_DESC "XGI XP5 / XP10 / XG47" -#define DRIVER_DATE "20070710" +#define DRIVER_DATE "20070721" #define DRIVER_MAJOR 0 -#define DRIVER_MINOR 8 +#define DRIVER_MINOR 9 #define DRIVER_PATCHLEVEL 0 #include "xgi_cmdlist.h" -- cgit v1.2.3 From 2097d743f287d994bd001baedd39e3bc808999c6 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 23 Jul 2007 13:26:28 -0700 Subject: Eliminate XGI_CHECK_PCI_CONFIG. Based on review comments from airlied, XGI_CHECK_PCI_CONFIG is removed. He believes (and I tend to agree) that this is a largely unnecessary workaround for a bug elsewhere. --- linux-core/xgi_drv.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index bcb6946d..19a9a10d 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -139,40 +139,6 @@ MODULE_LICENSE("GPL and additional rights"); void xgi_kern_isr_bh(struct drm_device *dev); -/* - * verify access to pci config space wasn't disabled behind our back - * unfortunately, XFree86 enables/disables memory access in pci config space at - * various times (such as restoring initial pci config space settings during vt - * switches or when doing mulicard). As a result, all of our register accesses - * are garbage at this point. add a check to see if access was disabled and - * reenable any such access. - */ -#define XGI_CHECK_PCI_CONFIG(xgi) \ - xgi_check_pci_config(xgi, __LINE__) - -static inline void xgi_check_pci_config(struct xgi_info * info, int line) -{ - u16 cmd; - bool flag = 0; - - pci_read_config_word(info->dev->pdev, PCI_COMMAND, &cmd); - if (!(cmd & PCI_COMMAND_MASTER)) { - DRM_INFO("restoring bus mastering! (%d)\n", line); - cmd |= PCI_COMMAND_MASTER; - flag = 1; - } - - if (!(cmd & PCI_COMMAND_MEMORY)) { - DRM_INFO("restoring MEM access! (%d)\n", line); - cmd |= PCI_COMMAND_MEMORY; - flag = 1; - } - - if (flag) - pci_write_config_word(info->dev->pdev, PCI_COMMAND, cmd); -} - - int xgi_bootstrap(DRM_IOCTL_ARGS) { DRM_DEVICE; @@ -262,8 +228,6 @@ irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS) //DRM_INFO("xgi_kern_isr \n"); - //XGI_CHECK_PCI_CONFIG(info); - //xgi_dvi_irq_handler(info); if (need_to_run_bottom_half) { @@ -280,8 +244,6 @@ void xgi_kern_isr_bh(struct drm_device *dev) DRM_INFO("xgi_kern_isr_bh \n"); //xgi_dvi_irq_handler(info); - - XGI_CHECK_PCI_CONFIG(info); } int xgi_driver_load(struct drm_device *dev, unsigned long flags) -- cgit v1.2.3 From 388a2c54eea7575a5b046da3df09f7a1c63551d6 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 23 Jul 2007 18:50:07 -0700 Subject: Minor log message clean up. --- linux-core/xgi_cmdlist.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 98d80ef0..f5fc1b94 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -116,7 +116,7 @@ static void xgi_submit_cmdlist(struct xgi_info * info, dwWriteReg(info->mmio_map, portOffset + 8, begin[2]); dwWriteReg(info->mmio_map, portOffset + 12, begin[3]); } else { - DRM_INFO("info->cmdring.last_ptr != NULL\n"); + DRM_DEBUG("info->cmdring.last_ptr != NULL\n"); if (pCmdInfo->type == BTYPE_3D) { addFlush2D(info); @@ -132,7 +132,6 @@ static void xgi_submit_cmdlist(struct xgi_info * info, } info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr); - DRM_INFO("%s: exit\n", __func__); } @@ -172,19 +171,17 @@ int xgi_state_change(struct xgi_info * info, unsigned int to, #define STATE_SHUTDOWN 5 if ((from == STATE_GRAPHIC) && (to == STATE_CONSOLE)) { - DRM_INFO("[kd] I see, now is to leaveVT\n"); - // stop to received batch + DRM_INFO("Leaving graphical mode (probably VT switch)\n"); } else if ((from == STATE_CONSOLE) && (to == STATE_GRAPHIC)) { - DRM_INFO("[kd] I see, now is to enterVT\n"); + 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("[kd] I see, not is to exit from X\n"); - // stop to received batch + DRM_INFO("Leaving graphical mode (probably X shutting down)\n"); } else { - DRM_ERROR("[kd] Should not happen\n"); + DRM_ERROR("Invalid state change.\n"); return DRM_ERR(EINVAL); } -- cgit v1.2.3 From 46214fc3979ed60b32289ade1b8efbba1c8bf732 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 23 Jul 2007 18:50:52 -0700 Subject: Minor log message clean up. --- linux-core/xgi_regs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index b211626a..f5311c1e 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -76,9 +76,10 @@ static inline u8 IN3CFB(struct drm_map * map, u8 index) */ 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); } -- cgit v1.2.3 From 887cb31ee9ec04e45829500f095aa4a3bc1095ea Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 24 Jul 2007 13:27:44 -0700 Subject: Fix bug preventing X server from restarting. The core DRM lastclose routine automatically destroys all mappings and releases SG memory. XP10 DRM and DDX assumed this data stayed around until module unload. xgi_bootstrap was reworked to recreate all these mappings. In addition, the drm_addmap for the GART backing store was moved into the kernel. This causes a change to the ioctl protocol and a version bump. --- linux-core/xgi_drv.c | 126 ++++++++++++++++++++++++++++++++++----------------- linux-core/xgi_drv.h | 4 +- 2 files changed, 87 insertions(+), 43 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 19a9a10d..11d6e950 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -64,6 +64,7 @@ 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); @@ -75,6 +76,7 @@ static struct drm_driver driver = { .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, @@ -144,26 +146,25 @@ 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->bootstrap_done) { - return 0; - } + if (info->mmio_map == NULL) { + err = drm_addmap(dev, info->mmio.base, info->mmio.size, + _DRM_REGISTERS, _DRM_KERNEL, + &info->mmio_map); + if (err) { + DRM_ERROR("Unable to map MMIO region: %d\n", err); + return err; + } - err = drm_addmap(dev, info->mmio.base, info->mmio.size, - _DRM_REGISTERS, _DRM_KERNEL, - &info->mmio_map); - if (err) { - DRM_ERROR("Unable to map MMIO region: %d\n", err); - return err; + xgi_enable_mmio(info); } - xgi_enable_mmio(info); - //xgi_enable_ge(info); info->fb.size = IN3CFB(info->mmio_map, 0x54) * 8 * 1024 * 1024; @@ -172,38 +173,64 @@ int xgi_bootstrap(DRM_IOCTL_ARGS) if ((info->fb.base == 0) || (info->fb.size == 0)) { - DRM_ERROR("frame buffer appears to be wrong: 0x%lx 0x%x\n", + 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 */ - err = xgi_fb_heap_init(info); - if (err) { - DRM_ERROR("xgi_fb_heap_init() failed\n"); - return err; + 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 * (1024 * 1024); + info->pcie.size = bs.gart.size; /* Init the resource manager */ - err = xgi_pcie_heap_init(info); - if (err) { - DRM_ERROR("xgi_pcie_heap_init() failed\n"); - return err; + 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; + } } - /* 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; + } } - info->bootstrap_done = 1; + + 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; } @@ -217,6 +244,33 @@ void xgi_driver_preclose(struct drm_device * dev, DRMFILE 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. */ @@ -298,23 +352,13 @@ int xgi_driver_unload(struct drm_device *dev) { struct xgi_info * info = dev->dev_private; - xgi_cmdlist_cleanup(info); - if (info->fb_map != NULL) { - drm_rmmap(info->dev, info->fb_map); - } - - if (info->mmio_map != NULL) { - drm_rmmap(info->dev, info->mmio_map); - } - - xgi_mem_heap_cleanup(&info->fb_heap); - xgi_mem_heap_cleanup(&info->pcie_heap); - xgi_pcie_lut_cleanup(info); - 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 index 16102950..ae5fe07e 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -36,10 +36,10 @@ #define DRIVER_NAME "xgi" #define DRIVER_DESC "XGI XP5 / XP10 / XG47" -#define DRIVER_DATE "20070721" +#define DRIVER_DATE "20070723" #define DRIVER_MAJOR 0 -#define DRIVER_MINOR 9 +#define DRIVER_MINOR 10 #define DRIVER_PATCHLEVEL 0 #include "xgi_cmdlist.h" -- cgit v1.2.3 From 2ef2997ee38ff359c331b6a3febf194bd46e4962 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 24 Jul 2007 13:29:29 -0700 Subject: Fix flags for serveral ioctls. --- linux-core/xgi_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 11d6e950..3b520850 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -42,7 +42,7 @@ static struct pci_device_id pciidlist[] = { 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_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}, @@ -55,7 +55,7 @@ static drm_ioctl_desc_t xgi_ioctls[] = { [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_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); -- cgit v1.2.3 From 8e64d2ae862d5fa02e23c68db6b55393e1f86005 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 24 Jul 2007 13:36:02 -0700 Subject: Fix license formatting. --- linux-core/xgi_cmdlist.c | 46 ++++++++++++++++++++++------------------------ linux-core/xgi_cmdlist.h | 46 ++++++++++++++++++++++------------------------ linux-core/xgi_drv.c | 46 ++++++++++++++++++++++------------------------ linux-core/xgi_drv.h | 46 ++++++++++++++++++++++------------------------ linux-core/xgi_fb.c | 46 ++++++++++++++++++++++------------------------ linux-core/xgi_misc.c | 46 ++++++++++++++++++++++------------------------ linux-core/xgi_misc.h | 44 +++++++++++++++++++++----------------------- linux-core/xgi_pcie.c | 46 ++++++++++++++++++++++------------------------ linux-core/xgi_regs.h | 44 +++++++++++++++++++++----------------------- 9 files changed, 196 insertions(+), 214 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index f5fc1b94..e4f9dbcd 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * 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" diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 5b444cf3..604c9aac 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * 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_ diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 3b520850..2c3384b0 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * 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" diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index ae5fe07e..2061189a 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * 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_ diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index a5885198..3d3b2ae0 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * 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" diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 7f3d9d6e..5e8c3da8 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * 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" diff --git a/linux-core/xgi_misc.h b/linux-core/xgi_misc.h index 10638b2d..af19a11a 100644 --- a/linux-core/xgi_misc.h +++ b/linux-core/xgi_misc.h @@ -1,29 +1,27 @@ - /**************************************************************************** * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * + * 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. + * 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_ diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 9dee888b..537e82f5 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * 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" diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index f5311c1e..34268a56 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -1,29 +1,27 @@ - /**************************************************************************** - * Copyright (C) 2003-2006 by XGI Technology, Taiwan. - * * - * All Rights Reserved. * - * * + * 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. + * "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_ -- cgit v1.2.3 From 75a68635a8f7b0d4fb31031832cc282a39a4a1e7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 24 Jul 2007 15:53:50 -0700 Subject: Pass correct offset to xgi_find_pcie_virt. The wrong offset was being passed to xgi_find_pcie_virt. This would cause an oops in addFlush2D. --- linux-core/xgi_cmdlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index e4f9dbcd..8ba8dc75 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -47,7 +47,7 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) return err; } - info->cmdring.ptr = xgi_find_pcie_virt(info, mem_alloc.offset); + info->cmdring.ptr = xgi_find_pcie_virt(info, mem_alloc.hw_offset); info->cmdring.size = mem_alloc.size; info->cmdring.ring_hw_base = mem_alloc.hw_addr; info->cmdring.ring_gart_base = mem_alloc.offset; -- cgit v1.2.3 From 2bafeb673f14b1e3799bf00817138c0b8211635e Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 24 Jul 2007 16:17:30 -0700 Subject: Fix typo on previous commit. Sigh... --- linux-core/xgi_cmdlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 8ba8dc75..490e9f39 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -47,7 +47,7 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) return err; } - info->cmdring.ptr = xgi_find_pcie_virt(info, mem_alloc.hw_offset); + 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; -- cgit v1.2.3 From b89cc0346500d9875d4acebc611db8f9ee3463f7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 26 Jul 2007 16:58:59 -0700 Subject: Eliminate unnecessary (and now wrong) call gto drm_sg_free. --- linux-core/xgi_pcie.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 537e82f5..dc5a50b8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -121,10 +121,6 @@ static int xgi_pcie_lut_init(struct xgi_info * info) 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; -- cgit v1.2.3 From c37ed9eca57a42b98cc67ca98dbf5135f5ab7aba Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 26 Jul 2007 17:01:16 -0700 Subject: Eliminate use of DRM_ERR. --- linux-core/xgi_cmdlist.c | 4 ++-- linux-core/xgi_drv.c | 10 +++++----- linux-core/xgi_fb.c | 8 ++++---- linux-core/xgi_pcie.c | 10 +++++----- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 490e9f39..10ee9764 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -144,7 +144,7 @@ int xgi_submit_cmdlist_ioctl(DRM_IOCTL_ARGS) sizeof(cmd_list)); if (cmd_list.type > BTYPE_CTRL) { - return DRM_ERR(EINVAL); + return -EINVAL; } xgi_submit_cmdlist(info, &cmd_list); @@ -180,7 +180,7 @@ int xgi_state_change(struct xgi_info * info, unsigned int to, DRM_INFO("Leaving graphical mode (probably X shutting down)\n"); } else { DRM_ERROR("Invalid state change.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 2c3384b0..ec87df0a 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -173,7 +173,7 @@ int xgi_bootstrap(DRM_IOCTL_ARGS) 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); + return -EINVAL; } @@ -221,7 +221,7 @@ int xgi_bootstrap(DRM_IOCTL_ARGS) 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); + return -EINVAL; } bs.gart = *info->pcie_map; @@ -303,7 +303,7 @@ 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); + return -ENOMEM; (void) memset(info, 0, sizeof(*info)); dev->dev_private = info; @@ -322,7 +322,7 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags) 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); + return -EINVAL; } @@ -339,7 +339,7 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags) SLAB_HWCACHE_ALIGN, NULL, NULL); if (xgi_mem_block_cache == NULL) { - return DRM_ERR(ENOMEM); + return -ENOMEM; } diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 3d3b2ae0..10343c13 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -45,7 +45,7 @@ int xgi_mem_heap_init(struct xgi_mem_heap *heap, unsigned int start, block = kmem_cache_alloc(xgi_mem_block_cache, GFP_KERNEL); if (!block) { - return DRM_ERR(ENOMEM); + return -ENOMEM; } block->offset = start; @@ -189,11 +189,11 @@ int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, if (&block->list == &heap->used_list) { DRM_ERROR("can't find block: 0x%lx to free!\n", offset); - return DRM_ERR(ENOENT); + return -ENOENT; } if (block->filp != filp) { - return DRM_ERR(EPERM); + return -EPERM; } used_block = block; @@ -265,7 +265,7 @@ int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, alloc->location = XGI_MEMLOC_LOCAL; alloc->size = 0; DRM_ERROR("Video RAM allocation failed\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } else { DRM_INFO("Video RAM allocation succeeded: 0x%p\n", (char *)block->offset); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index dc5a50b8..4c369a2a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -85,7 +85,7 @@ static int xgi_pcie_lut_init(struct xgi_info * info) DMA_31BIT_MASK); if (info->lut_handle == NULL) { DRM_ERROR("cannot allocate PCIE lut page!\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } lut = info->lut_handle->vaddr; @@ -97,7 +97,7 @@ static int xgi_pcie_lut_init(struct xgi_info * info) 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])); + return info->dev->sg->busaddr[i]; } lut[i] = info->dev->sg->busaddr[i]; @@ -184,7 +184,7 @@ int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, alloc->location = XGI_MEMLOC_INVALID; alloc->size = 0; DRM_ERROR("PCIE RAM allocation failed\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } else { DRM_INFO("PCIE RAM allocation succeeded: offset = 0x%lx\n", block->offset); @@ -325,7 +325,7 @@ int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) DRM_INFO("input GE HW addr is 0x%x\n", address); if (address == 0) { - return DRM_ERR(EFAULT); + return -EFAULT; } virtaddr = (u32 *)xgi_find_pcie_virt(info, address); @@ -337,7 +337,7 @@ int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) *virtaddr = 0x00f00fff; DRM_INFO("modified [virtaddr] = 0x%x\n", *virtaddr); } else { - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; -- cgit v1.2.3 From cd51f131389297f923798daef6c734ba93f4422b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 27 Jul 2007 15:45:59 -0700 Subject: Convert to new ioctl interface between core DRM and device-specific module. --- linux-core/xgi_cmdlist.c | 36 +++++++++----------------------- linux-core/xgi_drv.c | 53 ++++++++++++++++++++++-------------------------- linux-core/xgi_drv.h | 48 ++++++++++++++++++++++++++----------------- linux-core/xgi_fb.c | 42 +++++++++++++------------------------- linux-core/xgi_misc.c | 14 ++++++------- linux-core/xgi_pcie.c | 52 ++++++++++++++++------------------------------- 6 files changed, 101 insertions(+), 144 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 10ee9764..1d0ee754 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -76,9 +76,12 @@ unsigned int get_batch_command(enum xgi_batch_type type) } -static void xgi_submit_cmdlist(struct xgi_info * info, - const struct xgi_cmd_info * pCmdInfo) +int xgi_submit_cmdlist(struct drm_device * dev, void * data, + struct drm_file * filp) { + struct xgi_info *const info = dev->dev_private; + const struct xgi_cmd_info *const pCmdInfo = + (struct xgi_cmd_info *) data; const unsigned int cmd = get_batch_command(pCmdInfo->type); u32 begin[4]; @@ -130,24 +133,6 @@ static void xgi_submit_cmdlist(struct xgi_info * 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 -EINVAL; - } - - xgi_submit_cmdlist(info, &cmd_list); return 0; } @@ -187,16 +172,15 @@ int xgi_state_change(struct xgi_info * info, unsigned int to, } -int xgi_state_change_ioctl(DRM_IOCTL_ARGS) +int xgi_state_change_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; - struct xgi_state_info state; + struct xgi_state_info *const state = + (struct xgi_state_info *) data; 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); + return xgi_state_change(info, state->_toState, state->_fromState); } diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index ec87df0a..0b094a31 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -37,23 +37,23 @@ static struct pci_device_id pciidlist[] = { xgi_PCI_IDS }; -static int xgi_bootstrap(DRM_IOCTL_ARGS); +static int xgi_bootstrap(struct drm_device *, void *, struct drm_file *); -static drm_ioctl_desc_t xgi_ioctls[] = { - [DRM_IOCTL_NR(DRM_XGI_BOOTSTRAP)] = {xgi_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, +static struct drm_ioctl_desc xgi_ioctls[] = { + DRM_IOCTL_DEF(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_DEF(DRM_XGI_FB_ALLOC, xgi_fb_alloc_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(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_DEF(DRM_XGI_PCIE_ALLOC, xgi_pcie_alloc_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(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}, + DRM_IOCTL_DEF(DRM_XGI_GE_RESET, xgi_ge_reset_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_XGI_DUMP_REGISTER, xgi_dump_register_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_XGI_DEBUG_INFO, xgi_restore_registers_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_XGI_SUBMIT_CMDLIST, xgi_submit_cmdlist, DRM_AUTH), + DRM_IOCTL_DEF(DRM_XGI_TEST_RWINKERNEL, xgi_test_rwinkernel_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_XGI_STATE_CHANGE, xgi_state_change_ioctl, DRM_AUTH|DRM_MASTER), }; static const int xgi_max_ioctl = DRM_ARRAY_SIZE(xgi_ioctls); @@ -61,8 +61,9 @@ 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 void xgi_driver_preclose(struct drm_device * dev, + struct drm_file * filp); +static void xgi_driver_lastclose(struct drm_device * dev); static irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS); @@ -139,18 +140,15 @@ MODULE_LICENSE("GPL and additional rights"); void xgi_kern_isr_bh(struct drm_device *dev); -int xgi_bootstrap(DRM_IOCTL_ARGS) +int xgi_bootstrap(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; struct xgi_info *info = dev->dev_private; - struct xgi_bootstrap bs; + struct xgi_bootstrap * bs = (struct xgi_bootstrap *) data; 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, @@ -187,7 +185,7 @@ int xgi_bootstrap(DRM_IOCTL_ARGS) } - info->pcie.size = bs.gart.size; + info->pcie.size = bs->gart.size; /* Init the resource manager */ if (!info->pcie_heap.initialized) { @@ -224,16 +222,13 @@ int xgi_bootstrap(DRM_IOCTL_ARGS) return -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)); - + bs->gart = *info->pcie_map; + bs->gart.handle = (void *)(unsigned long) maplist->user_token; return 0; } -void xgi_driver_preclose(struct drm_device * dev, DRMFILE filp) +void xgi_driver_preclose(struct drm_device * dev, struct drm_file * filp) { struct xgi_info * info = dev->dev_private; @@ -242,7 +237,7 @@ void xgi_driver_preclose(struct drm_device * dev, DRMFILE filp) } -void xgi_driver_lastclose(drm_device_t * dev) +void xgi_driver_lastclose(struct drm_device * dev) { struct xgi_info * info = dev->dev_private; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 2061189a..8dec1fa1 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -52,7 +52,7 @@ struct xgi_mem_block { struct list_head list; unsigned long offset; unsigned long size; - DRMFILE filp; + struct drm_file * filp; unsigned int owner; }; @@ -111,7 +111,7 @@ 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); + struct drm_file * 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); @@ -119,34 +119,44 @@ 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); + struct drm_file * filp); extern int xgi_fb_free(struct xgi_info * info, unsigned long offset, - DRMFILE filp); + struct drm_file * 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); + struct xgi_mem_alloc * alloc, struct drm_file * filp); extern int xgi_pcie_free(struct xgi_info * info, unsigned long offset, - DRMFILE filp); + struct drm_file * 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); +extern void xgi_pcie_free_all(struct xgi_info *, struct drm_file *); +extern void xgi_fb_free_all(struct xgi_info *, struct drm_file *); + +extern int xgi_fb_alloc_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_fb_free_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_ge_reset_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_dump_register_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_restore_registers_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_submit_cmdlist(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_test_rwinkernel_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); +extern int xgi_state_change_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp); #endif diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 10343c13..9c60a874 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -94,7 +94,7 @@ struct xgi_mem_block *xgi_mem_new_node(void) block->offset = 0; block->size = 0; block->owner = PCIE_INVALID; - block->filp = (DRMFILE) -1; + block->filp = (struct drm_file *) -1; return block; } @@ -173,7 +173,7 @@ struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, } int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, - DRMFILE filp) + struct drm_file * filp) { struct xgi_mem_block *used_block = NULL, *block; struct xgi_mem_block *prev, *next; @@ -246,7 +246,7 @@ int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - DRMFILE filp) + struct drm_file * filp) { struct xgi_mem_block *block; @@ -282,29 +282,19 @@ int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, } -int xgi_fb_alloc_ioctl(DRM_IOCTL_ARGS) +int xgi_fb_alloc_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; - struct xgi_mem_alloc alloc; + struct xgi_mem_alloc *alloc = + (struct xgi_mem_alloc *) data; 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; + return xgi_fb_alloc(info, alloc, filp); } -int xgi_fb_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) +int xgi_fb_free(struct xgi_info * info, unsigned long offset, + struct drm_file * filp) { int err = 0; @@ -320,16 +310,12 @@ int xgi_fb_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) } -int xgi_fb_free_ioctl(DRM_IOCTL_ARGS) +int xgi_fb_free_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - 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); + return xgi_fb_free(info, *(u32 *) data, filp); } @@ -342,7 +328,7 @@ int xgi_fb_heap_init(struct xgi_info * info) /** * Free all blocks associated with a particular file handle. */ -void xgi_fb_free_all(struct xgi_info * info, DRMFILE filp) +void xgi_fb_free_all(struct xgi_info * info, struct drm_file * filp) { if (!info->fb_heap.initialized) { return; diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 5e8c3da8..6c029782 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -27,9 +27,9 @@ #include "xgi_drv.h" #include "xgi_regs.h" -int xgi_ge_reset_ioctl(DRM_IOCTL_ARGS) +int xgi_ge_reset_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; struct xgi_info *info = dev->dev_private; xgi_disable_ge(info); @@ -436,25 +436,23 @@ void xgi_dump_register(struct xgi_info * info) } -int xgi_dump_register_ioctl(DRM_IOCTL_ARGS) +int xgi_dump_register_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; struct xgi_info *info = dev->dev_private; xgi_dump_register(info); - return 0; } -int xgi_restore_registers_ioctl(DRM_IOCTL_ARGS) +int xgi_restore_registers_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; struct xgi_info *info = dev->dev_private; OUT3X5B(info->mmio_map, 0x13, 0); OUT3X5B(info->mmio_map, 0x8b, 2); - return 0; } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 4c369a2a..b91471b8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -33,7 +33,7 @@ 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); + unsigned long offset, struct drm_file * filp); static int xgi_pcie_lut_init(struct xgi_info * info) { @@ -148,7 +148,7 @@ int xgi_pcie_heap_init(struct xgi_info * info) int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - DRMFILE filp) + struct drm_file * filp) { struct xgi_mem_block *block; @@ -199,32 +199,21 @@ int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, } -int xgi_pcie_alloc_ioctl(DRM_IOCTL_ARGS) +int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; - struct xgi_mem_alloc alloc; + struct xgi_mem_alloc *const alloc = + (struct xgi_mem_alloc *) data; 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; + return xgi_pcie_alloc(info, alloc, filp); } /** * Free all blocks associated with a particular file handle. */ -void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp) +void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) { if (!info->pcie_heap.initialized) { return; @@ -252,8 +241,8 @@ void xgi_pcie_free_all(struct xgi_info * info, DRMFILE filp) } -int xgi_pcie_free_locked(struct xgi_info * info, - unsigned long offset, DRMFILE filp) +int xgi_pcie_free_locked(struct xgi_info * info, unsigned long offset, + struct drm_file * filp) { const bool isvertex = (xgi_pcie_vertex_block && (xgi_pcie_vertex_block->offset == offset)); @@ -266,7 +255,8 @@ int xgi_pcie_free_locked(struct xgi_info * info, } -int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) +int xgi_pcie_free(struct xgi_info * info, unsigned long offset, + struct drm_file * filp) { int err; @@ -282,16 +272,12 @@ int xgi_pcie_free(struct xgi_info * info, unsigned long offset, DRMFILE filp) } -int xgi_pcie_free_ioctl(DRM_IOCTL_ARGS) +int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - 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); + return xgi_pcie_free(info, *(u32 *) data, filp); } @@ -312,15 +298,13 @@ void *xgi_find_pcie_virt(struct xgi_info * info, u32 address) /* address -- GE hw address */ -int xgi_test_rwinkernel_ioctl(DRM_IOCTL_ARGS) +int xgi_test_rwinkernel_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - DRM_DEVICE; struct xgi_info *info = dev->dev_private; - u32 address; + u32 address = *(u32 *) data; 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); -- cgit v1.2.3 From 2ac80e79e424aa6577e556b2df01caea9e480852 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 30 Jul 2007 09:59:19 -0700 Subject: Use OUT3C5B macro instead of assuming little-endian byte order. --- linux-core/xgi_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 34268a56..b3a47f8e 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -130,7 +130,7 @@ static inline void xgi_enable_ge(struct xgi_info * info) int wait = 0; // Enable GE - DRM_WRITE16(info->mmio_map, 0x3C4, 0x9211); + OUT3C5B(info->mmio_map, 0x11, 0x92); // Save and close dynamic gating bOld3cf2a = IN3CFB(info->mmio_map, 0x2a); -- cgit v1.2.3 From 01628a430d476f5875270d7137fc083ba85cef90 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 30 Jul 2007 10:02:46 -0700 Subject: Use DRM_READ/DRM_WRITE macros instead of directly accessing MMIO space. --- linux-core/xgi_misc.c | 119 ++++++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 51 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 6c029782..c75a5841 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -27,6 +27,8 @@ #include "xgi_drv.h" #include "xgi_regs.h" +#include + int xgi_ge_reset_ioctl(struct drm_device * dev, void * data, struct drm_file * filp) { @@ -46,47 +48,43 @@ int xgi_ge_reset_ioctl(struct drm_device * dev, void * data, static unsigned int s_invalid_begin = 0; -static bool xgi_validate_signal(volatile u8 *mmio_vbase) +static bool xgi_validate_signal(struct drm_map * map) { - 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) { + if (DRM_READ32(map, 0x2800) & 0x001c0000) { u16 check; /* Check Read back status */ - *(mmio_vbase + 0x235c) = 0x80; - check = *((volatile u16 *)(mmio_vbase + 0x2360)); + DRM_WRITE8(map, 0x235c, 0x80); + check = DRM_READ16(map, 0x2360); if ((check & 0x3f) != ((check & 0x3f00) >> 8)) { return FALSE; } /* Check RO channel */ - *(mmio_vbase + 0x235c) = 0x83; - check = *((volatile u16 *)(mmio_vbase + 0x2360)); + DRM_WRITE8(map, 0x235c, 0x83); + check = DRM_READ16(map, 0x2360); if ((check & 0x0f) != ((check & 0xf0) >> 4)) { return FALSE; } /* Check RW channel */ - *(mmio_vbase + 0x235c) = 0x88; - check = *((volatile u16 *)(mmio_vbase + 0x2360)); + DRM_WRITE8(map, 0x235c, 0x88); + check = DRM_READ16(map, 0x2360); if ((check & 0x0f) != ((check & 0xf0) >> 4)) { return FALSE; } /* Check RO channel outstanding */ - *(mmio_vbase + 0x235c) = 0x8f; - check = *((volatile u16 *)(mmio_vbase + 0x2360)); + DRM_WRITE8(map, 0x235c, 0x8f); + check = DRM_READ16(map, 0x2360); if (0 != (check & 0x3ff)) { return FALSE; } /* Check RW channel outstanding */ - *(mmio_vbase + 0x235c) = 0x90; - check = *((volatile u16 *)(mmio_vbase + 0x2360)); + DRM_WRITE8(map, 0x235c, 0x90); + check = DRM_READ16(map, 0x2360); if (0 != (check & 0x3ff)) { return FALSE; } @@ -98,14 +96,12 @@ static bool xgi_validate_signal(volatile u8 *mmio_vbase) } -static void xgi_ge_hang_reset(volatile u8 *mmio_vbase) +static void xgi_ge_hang_reset(struct drm_map * map) { - 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)) { + DRM_WRITE8(map, 0xb057, 8); + while (0 != (DRM_READ32(map, 0x2800) & 0xf0000000)) { while (0 != ((--time_out) & 0xfff)) /* empty */ ; @@ -116,57 +112,53 @@ static void xgi_ge_hang_reset(volatile u8 *mmio_vbase) u8 old_36; DRM_INFO("Can not reset back 0x%x!\n", - ge_3d_status[0x00]); + DRM_READ32(map, 0x2800)); - *(mmio_vbase + 0xb057) = 0; + DRM_WRITE8(map, 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; + old_3ce = DRM_READ8(map, 0x3ce); + DRM_WRITE8(map, 0x3ce, 0x2a); + old_3cf = DRM_READ8(map, 0x3cf); + DRM_WRITE8(map, 0x3cf, old_3cf & 0xfe); /* Reset GE */ - old_index = *(mmio_vbase + 0x3d4); - *(mmio_vbase + 0x3d4) = 0x36; - old_36 = *(mmio_vbase + 0x3d5); - *(mmio_vbase + 0x3d5) = old_36 | 0x10; - + old_index = DRM_READ8(map, 0x3d4); + DRM_WRITE8(map, 0x3d4, 0x36); + old_36 = DRM_READ8(map, 0x3d5); + DRM_WRITE8(map, 0x3d5, old_36 | 0x10); + while (0 != ((--time_out) & 0xfff)) /* empty */ ; - *(mmio_vbase + 0x3d5) = old_36; - *(mmio_vbase + 0x3d4) = old_index; + DRM_WRITE8(map, 0x3d5, old_36); + DRM_WRITE8(map, 0x3d4, old_index); /* Restore dynamic gating */ - *(mmio_vbase + 0x3cf) = old_3cf; - *(mmio_vbase + 0x3ce) = old_3ce; + DRM_WRITE8(map, 0x3cf, old_3cf); + DRM_WRITE8(map, 0x3ce, old_3ce); break; } } - *(mmio_vbase + 0xb057) = 0; + DRM_WRITE8(map, 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]; + const u32 int_status = DRM_READ32(info->mmio_map, 0x2810); 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; + DRM_WRITE32(info->mmio_map, 0x2810, + int_status | 0x04000000); if (is_support_auto_reset) { static cycles_t last_tick; @@ -174,7 +166,7 @@ bool xgi_ge_irq_handler(struct xgi_info * info) /* OE II is busy. */ - if (!xgi_validate_signal(mmio_vbase)) { + if (!xgi_validate_signal(info->mmio_map)) { /* Nothing but skip. */ } else if (0 == continue_int_count++) { last_tick = get_cycles(); @@ -189,13 +181,14 @@ bool xgi_ge_irq_handler(struct xgi_info * info) /* GE Hung up, need reset. */ DRM_INFO("Reset GE!\n"); - xgi_ge_hang_reset(mmio_vbase); + xgi_ge_hang_reset(info->mmio_map); } } } } else if (0 != (0x1 & int_status)) { s_invalid_begin++; - ge_3d_status[0x04] = (int_status & ~0x01) | 0x04000000; + DRM_WRITE32(info->mmio_map, 0x2810, + (int_status & ~0x01) | 0x04000000); } return TRUE; @@ -456,14 +449,38 @@ int xgi_restore_registers_ioctl(struct drm_device * dev, void * data, return 0; } + +#define WHOLD_GE_STATUS 0x2800 + +/* Test everything except the "whole GE busy" bit, the "master engine busy" + * bit, and the reserved bits [26:21]. + */ +#define IDLE_MASK ~((1U<<31) | (1U<<28) | (0x3f<<21)) + void xgi_waitfor_pci_idle(struct xgi_info * info) { -#define WHOLD_GE_STATUS 0x2800 -#define IDLE_MASK ~0x90200000 + unsigned int idleCount = 0; + u32 old_status = 0; + unsigned int same_count = 0; - int idleCount = 0; while (idleCount < 5) { - if (DRM_READ32(info->mmio_map, WHOLD_GE_STATUS) & IDLE_MASK) { + const u32 status = DRM_READ32(info->mmio_map, WHOLD_GE_STATUS) + & IDLE_MASK; + + if (status == old_status) { + same_count++; + + if ((same_count % 100) == 0) { + DRM_ERROR("GE status stuck at 0x%08x for %u iterations!\n", + old_status, same_count); + } + } else { + old_status = status; + same_count = 0; + } + + if (status != 0) { + msleep(1); idleCount = 0; } else { idleCount++; -- cgit v1.2.3 From 2fc697a7d270d57463eb5a16a0c65bd8e14c9893 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 30 Jul 2007 10:20:15 -0700 Subject: Fix GE shut-down sequence. When the GE is shut down, an empty command packet without a begin-link must be sent. After this command is sent, wait for the hardware to go idle. Finally, turn off the GE and disable MMIO. --- linux-core/xgi_cmdlist.c | 64 +++++++++++++++++++++++++++++++----------------- linux-core/xgi_drv.c | 8 ++++-- 2 files changed, 48 insertions(+), 24 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 1d0ee754..4bb147c4 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -29,7 +29,7 @@ #include "xgi_misc.h" #include "xgi_cmdlist.h" -static void addFlush2D(struct xgi_info * info); +static void xgi_emit_flush(struct xgi_info * info, bool link); 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); @@ -120,7 +120,7 @@ int xgi_submit_cmdlist(struct drm_device * dev, void * data, DRM_DEBUG("info->cmdring.last_ptr != NULL\n"); if (pCmdInfo->type == BTYPE_3D) { - addFlush2D(info); + xgi_emit_flush(info, TRUE); } info->cmdring.last_ptr[1] = begin[1]; @@ -190,9 +190,18 @@ void xgi_cmdlist_reset(struct xgi_info * info) info->cmdring.ring_offset = 0; } + void xgi_cmdlist_cleanup(struct xgi_info * info) { if (info->cmdring.ring_hw_base != 0) { + /* If command lists have been issued, terminate the command + * list chain with a flush command. + */ + if (info->cmdring.last_ptr != NULL) { + xgi_emit_flush(info, FALSE); + xgi_waitfor_pci_idle(info); + } + xgi_pcie_free(info, info->cmdring.ring_gart_base, NULL); info->cmdring.ring_hw_base = 0; info->cmdring.ring_offset = 0; @@ -210,32 +219,43 @@ static void triggerHWCommandList(struct xgi_info * info) } -static void addFlush2D(struct xgi_info * info) +/** + * Emit a flush to the CRTL command stream. + * @info XGI info structure + * @link Emit (or don't emit) link information at start of flush command. + * + * This function assumes info->cmdring.ptr is non-NULL. + */ +static void xgi_emit_flush(struct xgi_info * info, bool link) { - u32 *flushBatchVirtAddr; - u32 flushBatchHWAddr; + static const u32 flush_command[8] = { + (0x10 << 24), + BEGIN_LINK_ENABLE_MASK | (0x00004), + 0x00000000, 0x00000000, + + /* Flush everything with the default 32 clock delay. + */ + 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff + }; + const unsigned int base = (link) ? 0 : 4; + const unsigned int flush_size = (8 - base) * sizeof(u32); + u32 *batch_addr; + u32 hw_addr; /* check buf is large enough to contain a new flush batch */ - if ((info->cmdring.ring_offset + 0x20) >= info->cmdring.size) { + if ((info->cmdring.ring_offset + flush_size) >= info->cmdring.size) { info->cmdring.ring_offset = 0; } - flushBatchHWAddr = info->cmdring.ring_hw_base + info->cmdring.ring_offset; - flushBatchVirtAddr = info->cmdring.ptr + hw_addr = info->cmdring.ring_hw_base + + info->cmdring.ring_offset; + batch_addr = 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; + (void) memcpy(batch_addr, & flush_command[base], flush_size); + + info->cmdring.last_ptr[1] = BEGIN_LINK_ENABLE_MASK | (flush_size / 4); + info->cmdring.last_ptr[2] = hw_addr >> 4; info->cmdring.last_ptr[3] = 0; wmb(); info->cmdring.last_ptr[0] = (get_batch_command(BTYPE_CTRL) << 24) @@ -243,6 +263,6 @@ static void addFlush2D(struct xgi_info * info) triggerHWCommandList(info); - info->cmdring.ring_offset += 0x20; - info->cmdring.last_ptr = flushBatchVirtAddr; + info->cmdring.ring_offset += flush_size; + info->cmdring.last_ptr = (link) ? batch_addr : NULL; } diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 0b094a31..201062ee 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -242,6 +242,12 @@ void xgi_driver_lastclose(struct drm_device * dev) struct xgi_info * info = dev->dev_private; if (info != NULL) { + if (info->mmio_map != NULL) { + xgi_cmdlist_cleanup(info); + xgi_disable_ge(info); + xgi_disable_mmio(info); + } + /* The core DRM lastclose routine will destroy all of our * mappings for us. NULL out the pointers here so that * xgi_bootstrap can do the right thing. @@ -250,8 +256,6 @@ void xgi_driver_lastclose(struct drm_device * dev) info->mmio_map = NULL; info->fb_map = NULL; - xgi_cmdlist_cleanup(info); - if (info->fb_heap.initialized) { xgi_mem_heap_cleanup(&info->fb_heap); } -- cgit v1.2.3 From 08919d8a70558dc61c430be5ed6e4a2bed7429b2 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 30 Jul 2007 12:01:52 -0700 Subject: Move additional GE initialization into the kernel. This code comes directly from the X server. --- linux-core/xgi_drv.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 201062ee..33b3a51d 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -138,6 +138,57 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); +void xgi_engine_init(struct xgi_info * info) +{ + u8 temp; + + + OUT3C5B(info->mmio_map, 0x11, 0x92); + + /* -------> copy from OT2D + * PCI Retry Control Register. + * disable PCI read retry & enable write retry in mem. (10xx xxxx)b + */ + temp = IN3X5B(info->mmio_map, 0x55); + OUT3X5B(info->mmio_map, 0x55, (temp & 0xbf) | 0x80); + + xgi_enable_ge(info); + + /* Enable linear addressing of the card. */ + temp = IN3X5B(info->mmio_map, 0x21); + OUT3X5B(info->mmio_map, 0x21, temp | 0x20); + + /* Enable 32-bit internal data path */ + temp = IN3X5B(info->mmio_map, 0x2A); + OUT3X5B(info->mmio_map, 0x2A, temp | 0x40); + + /* Enable PCI burst write ,disable burst read and enable MMIO. */ + /* + * 0x3D4.39 Enable PCI burst write, disable burst read and enable MMIO. + * 7 ---- Pixel Data Format 1: big endian 0: little endian + * 6 5 4 3---- Memory Data with Big Endian Format, BE[3:0]# with Big Endian Format + * 2 ---- PCI Burst Write Enable + * 1 ---- PCI Burst Read Enable + * 0 ---- MMIO Control + */ + temp = IN3X5B(info->mmio_map, 0x39); + OUT3X5B(info->mmio_map, 0x39, (temp | 0x05) & 0xfd); + + /* enable GEIO decode */ + /* temp = IN3X5B(info->mmio_map, 0x29); + * OUT3X5B(info->mmio_map, 0x29, temp | 0x08); + */ + + /* Enable graphic engine I/O PCI retry function*/ + /* temp = IN3X5B(info->mmio_map, 0x62); + * OUT3X5B(info->mmio_map, 0x62, temp | 0x50); + */ + + /* protect all register except which protected by 3c5.0e.7 */ + /* OUT3C5B(info->mmio_map, 0x11, 0x87); */ +} + + void xgi_kern_isr_bh(struct drm_device *dev); int xgi_bootstrap(struct drm_device * dev, void * data, @@ -159,6 +210,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data, } xgi_enable_mmio(info); + xgi_engine_init(info); } -- cgit v1.2.3 From f83000c8b388f18f677238b9342fd6a7e262394b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 31 Jul 2007 17:27:00 -0700 Subject: Refactor register dumping code. --- linux-core/xgi_misc.c | 183 ++++++++++---------------------------------------- 1 file changed, 35 insertions(+), 148 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index c75a5841..84d1d4f2 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -254,178 +254,65 @@ bool xgi_dvi_irq_handler(struct xgi_info * info) } -void xgi_dump_register(struct xgi_info * info) +static void dump_reg_header(unsigned regbase) { - 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"); + printk("\n=====xgi_dump_register========0x%x===============\n", + regbase); + printk(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); +} - 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"); +static void dump_indexed_reg(struct xgi_info * info, unsigned regbase) +{ + unsigned i, j; + u8 temp; - 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); + dump_reg_header(regbase); 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); + DRM_WRITE8(info->mmio_map, regbase - 1, + (i * 0x10) + j); + temp = DRM_READ8(info->mmio_map, regbase); 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("\n"); } - 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"); - } +static void dump_reg(struct xgi_info * info, unsigned regbase, unsigned range) +{ + unsigned i, j; - 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++) { + dump_reg_header(regbase); + for (i = 0; i < range; i++) { printk("%1x ", i); for (j = 0; j < 0x10; j++) { - temp = DRM_READ8(info->mmio_map, 0x2400 + i * 0x10 + j); + u8 temp = DRM_READ8(info->mmio_map, + regbase + (i * 0x10) + j); printk("%3x", temp); } - printk("\r\n"); + printk("\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"); - } +void xgi_dump_register(struct xgi_info * info) +{ + dump_indexed_reg(info, 0x3c5); + dump_indexed_reg(info, 0x3d5); + dump_indexed_reg(info, 0x3cf); + + dump_reg(info, 0xB000, 0x05); + dump_reg(info, 0x2200, 0x0B); + dump_reg(info, 0x2300, 0x07); + dump_reg(info, 0x2400, 0x10); + dump_reg(info, 0x2800, 0x10); } -- cgit v1.2.3 From 997a9a738ec26cf0ef2c7dee5e30bb53bd11bf6c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 15:31:34 -0700 Subject: Eliminate allocation "owner" usage. --- linux-core/xgi_cmdlist.c | 1 - linux-core/xgi_drv.h | 22 +++------------------- linux-core/xgi_fb.c | 7 ++----- linux-core/xgi_pcie.c | 26 +------------------------- 4 files changed, 6 insertions(+), 50 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 4bb147c4..e0ca31f1 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -38,7 +38,6 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) { struct xgi_mem_alloc mem_alloc = { .size = size, - .owner = PCIE_2D, }; int err; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 8dec1fa1..f771517d 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -34,11 +34,11 @@ #define DRIVER_NAME "xgi" #define DRIVER_DESC "XGI XP5 / XP10 / XG47" -#define DRIVER_DATE "20070723" +#define DRIVER_DATE "20070806" #define DRIVER_MAJOR 0 #define DRIVER_MINOR 10 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_PATCHLEVEL 1 #include "xgi_cmdlist.h" #include "xgi_drm.h" @@ -53,8 +53,6 @@ struct xgi_mem_block { unsigned long offset; unsigned long size; struct drm_file * filp; - - unsigned int owner; }; struct xgi_mem_heap { @@ -93,23 +91,9 @@ struct xgi_info { 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); + unsigned long size); extern int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, struct drm_file * filp); extern int xgi_mem_heap_init(struct xgi_mem_heap * heap, unsigned int start, diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 9c60a874..bbdebb57 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -93,7 +93,6 @@ struct xgi_mem_block *xgi_mem_new_node(void) block->offset = 0; block->size = 0; - block->owner = PCIE_INVALID; block->filp = (struct drm_file *) -1; return block; @@ -101,8 +100,7 @@ struct xgi_mem_block *xgi_mem_new_node(void) struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, - unsigned long originalSize, - enum PcieOwner owner) + unsigned long originalSize) { struct xgi_mem_block *block, *free_block, *used_block; unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; @@ -167,7 +165,6 @@ struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, heap->max_freesize -= size; list_add(&used_block->list, &heap->used_list); - used_block->owner = owner; return (used_block); } @@ -258,7 +255,7 @@ int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, ("Video RAM allocation on front buffer successfully! \n"); } else { down(&info->fb_sem); - block = xgi_mem_alloc(&info->fb_heap, alloc->size, PCIE_2D); + block = xgi_mem_alloc(&info->fb_heap, alloc->size); up(&info->fb_sem); if (block == NULL) { diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b91471b8..f66ffee9 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -153,31 +153,7 @@ int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, 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; - } - } + block = xgi_mem_alloc(&info->pcie_heap, alloc->size); up(&info->pcie_sem); if (block == NULL) { -- cgit v1.2.3 From 78e9c1a93d00097895bc77d9ac90da1945021804 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 15:37:56 -0700 Subject: Eliminate special-case handling of framebuffer (fake) allocation. --- linux-core/xgi_drv.h | 2 +- linux-core/xgi_fb.c | 51 +++++++++++++++++++-------------------------------- 2 files changed, 20 insertions(+), 33 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index f771517d..8a144fda 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -38,7 +38,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 10 -#define DRIVER_PATCHLEVEL 1 +#define DRIVER_PATCHLEVEL 2 #include "xgi_cmdlist.h" #include "xgi_drm.h" diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index bbdebb57..b27b6b20 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -247,32 +247,23 @@ int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, { 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"); + down(&info->fb_sem); + block = xgi_mem_alloc(&info->fb_heap, alloc->size); + up(&info->fb_sem); + + if (block == NULL) { + alloc->size = 0; + DRM_ERROR("Video RAM allocation failed\n"); + return -ENOMEM; } else { - down(&info->fb_sem); - block = xgi_mem_alloc(&info->fb_heap, alloc->size); - up(&info->fb_sem); - - if (block == NULL) { - alloc->location = XGI_MEMLOC_LOCAL; - alloc->size = 0; - DRM_ERROR("Video RAM allocation failed\n"); - return -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; - } + 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; @@ -295,13 +286,9 @@ int xgi_fb_free(struct xgi_info * info, unsigned long offset, { 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); - } + down(&info->fb_sem); + err = xgi_mem_free(&info->fb_heap, offset, filp); + up(&info->fb_sem); return err; } -- cgit v1.2.3 From a6fb93a150f90ada9af6760b52d34716497f744f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 15:43:51 -0700 Subject: Finish removing allocation "owner" infrastructure. --- linux-core/xgi_pcie.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index f66ffee9..be6915e8 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -28,10 +28,6 @@ #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, struct drm_file * filp); @@ -220,14 +216,7 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) int xgi_pcie_free_locked(struct xgi_info * info, unsigned long offset, struct drm_file * 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; + return xgi_mem_free(&info->pcie_heap, offset, filp); } -- cgit v1.2.3 From 5362cc723e6605c31d152eb22ee3dc40c9e3f56b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 15:52:06 -0700 Subject: Eliminate unnecessary function xgi_pcie_free_locked. --- linux-core/xgi_pcie.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index be6915e8..df49615a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -28,9 +28,6 @@ #include "xgi_regs.h" #include "xgi_misc.h" -static int xgi_pcie_free_locked(struct xgi_info * info, - unsigned long offset, struct drm_file * filp); - static int xgi_pcie_lut_init(struct xgi_info * info) { u8 temp = 0; @@ -206,27 +203,20 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) break; } - (void) xgi_pcie_free_locked(info, block->offset, filp); + (void) xgi_mem_free(&info->pcie_heap, block->offset, filp); } while(1); up(&info->pcie_sem); } -int xgi_pcie_free_locked(struct xgi_info * info, unsigned long offset, - struct drm_file * filp) -{ - return xgi_mem_free(&info->pcie_heap, offset, filp); -} - - int xgi_pcie_free(struct xgi_info * info, unsigned long offset, struct drm_file * filp) { int err; down(&info->pcie_sem); - err = xgi_pcie_free_locked(info, offset, filp); + err = xgi_mem_free(&info->pcie_heap, offset, filp); up(&info->pcie_sem); if (err) { -- cgit v1.2.3 From f96bff9e213a950ab910832908d30e732435e628 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 16:09:05 -0700 Subject: Unify infrastructure for allocating (not yet freeing) on-card / GART memory. --- linux-core/xgi_cmdlist.c | 3 ++- linux-core/xgi_drv.h | 9 ++------- linux-core/xgi_fb.c | 18 ++++++++++++------ linux-core/xgi_pcie.c | 31 ++----------------------------- 4 files changed, 18 insertions(+), 43 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index e0ca31f1..33155827 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -37,11 +37,12 @@ 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 = { + .location = XGI_MEMLOC_NON_LOCAL, .size = size, }; int err; - err = xgi_pcie_alloc(info, &mem_alloc, 0); + err = xgi_alloc(info, &mem_alloc, 0); if (err) { return err; } diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 8a144fda..48c4b42c 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -38,7 +38,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 10 -#define DRIVER_PATCHLEVEL 2 +#define DRIVER_PATCHLEVEL 3 #include "xgi_cmdlist.h" #include "xgi_drm.h" @@ -92,8 +92,6 @@ struct xgi_info { }; extern struct kmem_cache *xgi_mem_block_cache; -extern struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, - unsigned long size); extern int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, struct drm_file * filp); extern int xgi_mem_heap_init(struct xgi_mem_heap * heap, unsigned int start, @@ -102,7 +100,7 @@ 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, +extern int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, struct drm_file * filp); extern int xgi_fb_free(struct xgi_info * info, unsigned long offset, @@ -111,9 +109,6 @@ extern int xgi_fb_free(struct xgi_info * info, unsigned long offset, 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, struct drm_file * filp); - extern int xgi_pcie_free(struct xgi_info * info, unsigned long offset, struct drm_file * filp); diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index b27b6b20..1d5dc22b 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -99,8 +99,8 @@ struct xgi_mem_block *xgi_mem_new_node(void) } -struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, - unsigned long originalSize) +static struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, + unsigned long originalSize) { struct xgi_mem_block *block, *free_block, *used_block; unsigned long size = (originalSize + PAGE_SIZE - 1) & PAGE_MASK; @@ -242,13 +242,15 @@ int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, } -int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, +int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, struct drm_file * filp) { struct xgi_mem_block *block; down(&info->fb_sem); - block = xgi_mem_alloc(&info->fb_heap, alloc->size); + block = xgi_mem_alloc((alloc->location == XGI_MEMLOC_LOCAL) + ? &info->fb_heap : &info->pcie_heap, + alloc->size); up(&info->fb_sem); if (block == NULL) { @@ -258,11 +260,14 @@ int xgi_fb_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, } 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; + if (alloc->location == XGI_MEMLOC_NON_LOCAL) { + alloc->hw_addr += info->pcie.base; + } + block->filp = filp; } @@ -277,7 +282,8 @@ int xgi_fb_alloc_ioctl(struct drm_device * dev, void * data, (struct xgi_mem_alloc *) data; struct xgi_info *info = dev->dev_private; - return xgi_fb_alloc(info, alloc, filp); + alloc->location = XGI_MEMLOC_LOCAL; + return xgi_alloc(info, alloc, filp); } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index df49615a..c0d424f5 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -140,34 +140,6 @@ int xgi_pcie_heap_init(struct xgi_info * info) } -int xgi_pcie_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - struct drm_file * filp) -{ - struct xgi_mem_block *block; - - down(&info->pcie_sem); - block = xgi_mem_alloc(&info->pcie_heap, alloc->size); - up(&info->pcie_sem); - - if (block == NULL) { - alloc->location = XGI_MEMLOC_INVALID; - alloc->size = 0; - DRM_ERROR("PCIE RAM allocation failed\n"); - return -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(struct drm_device * dev, void * data, struct drm_file * filp) { @@ -175,7 +147,8 @@ int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, (struct xgi_mem_alloc *) data; struct xgi_info *info = dev->dev_private; - return xgi_pcie_alloc(info, alloc, filp); + alloc->location = XGI_MEMLOC_NON_LOCAL; + return xgi_alloc(info, alloc, filp); } -- cgit v1.2.3 From 90907c59152f628d6f0efea4927a06e547f4a3c7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 16:17:23 -0700 Subject: Replace per-heap semaphores with drm_device::struct_mutex. --- linux-core/xgi_drv.c | 3 --- linux-core/xgi_drv.h | 3 --- linux-core/xgi_fb.c | 12 ++++++------ linux-core/xgi_pcie.c | 8 ++++---- 4 files changed, 10 insertions(+), 16 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 33b3a51d..e98fd608 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -360,9 +360,6 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags) 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); diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 48c4b42c..384381c7 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -85,9 +85,6 @@ struct xgi_info { 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; }; diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 1d5dc22b..373c45dd 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -247,11 +247,11 @@ int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, { struct xgi_mem_block *block; - down(&info->fb_sem); + mutex_lock(&info->dev->struct_mutex); block = xgi_mem_alloc((alloc->location == XGI_MEMLOC_LOCAL) ? &info->fb_heap : &info->pcie_heap, alloc->size); - up(&info->fb_sem); + mutex_unlock(&info->dev->struct_mutex); if (block == NULL) { alloc->size = 0; @@ -292,9 +292,9 @@ int xgi_fb_free(struct xgi_info * info, unsigned long offset, { int err = 0; - down(&info->fb_sem); + mutex_lock(&info->dev->struct_mutex); err = xgi_mem_free(&info->fb_heap, offset, filp); - up(&info->fb_sem); + mutex_unlock(&info->dev->struct_mutex); return err; } @@ -324,7 +324,7 @@ void xgi_fb_free_all(struct xgi_info * info, struct drm_file * filp) return; } - down(&info->fb_sem); + mutex_lock(&info->dev->struct_mutex); do { struct xgi_mem_block *block; @@ -342,5 +342,5 @@ void xgi_fb_free_all(struct xgi_info * info, struct drm_file * filp) (void) xgi_mem_free(&info->fb_heap, block->offset, filp); } while(1); - up(&info->fb_sem); + mutex_unlock(&info->dev->struct_mutex); } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index c0d424f5..883fbe7e 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -161,7 +161,7 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) return; } - down(&info->pcie_sem); + mutex_lock(&info->dev->struct_mutex); do { struct xgi_mem_block *block; @@ -179,7 +179,7 @@ void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) (void) xgi_mem_free(&info->pcie_heap, block->offset, filp); } while(1); - up(&info->pcie_sem); + mutex_unlock(&info->dev->struct_mutex); } @@ -188,9 +188,9 @@ int xgi_pcie_free(struct xgi_info * info, unsigned long offset, { int err; - down(&info->pcie_sem); + mutex_lock(&info->dev->struct_mutex); err = xgi_mem_free(&info->pcie_heap, offset, filp); - up(&info->pcie_sem); + mutex_unlock(&info->dev->struct_mutex); if (err) { DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); -- cgit v1.2.3 From f3072becda3a2d5fe587f20e155d4d4f9ace60a2 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 16:35:07 -0700 Subject: Refactor xgi_(fb|pcie)_free_all into xgi_free_all. --- linux-core/xgi_drv.c | 6 ++++-- linux-core/xgi_drv.h | 6 +++--- linux-core/xgi_fb.c | 14 ++++++-------- linux-core/xgi_pcie.c | 31 ------------------------------- 4 files changed, 13 insertions(+), 44 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index e98fd608..f6e7b550 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -284,8 +284,10 @@ void xgi_driver_preclose(struct drm_device * dev, struct drm_file * filp) { struct xgi_info * info = dev->dev_private; - xgi_pcie_free_all(info, filp); - xgi_fb_free_all(info, filp); + mutex_lock(&info->dev->struct_mutex); + xgi_free_all(info, &info->pcie_heap, filp); + xgi_free_all(info, &info->fb_heap, filp); + mutex_unlock(&info->dev->struct_mutex); } diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 384381c7..79276b70 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -38,7 +38,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 10 -#define DRIVER_PATCHLEVEL 3 +#define DRIVER_PATCHLEVEL 4 #include "xgi_cmdlist.h" #include "xgi_drm.h" @@ -111,8 +111,8 @@ extern int xgi_pcie_free(struct xgi_info * info, unsigned long offset, extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address); -extern void xgi_pcie_free_all(struct xgi_info *, struct drm_file *); -extern void xgi_fb_free_all(struct xgi_info *, struct drm_file *); +extern void xgi_free_all(struct xgi_info *, struct xgi_mem_heap *, + struct drm_file *); extern int xgi_fb_alloc_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 373c45dd..f8341a67 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -318,29 +318,27 @@ int xgi_fb_heap_init(struct xgi_info * info) /** * Free all blocks associated with a particular file handle. */ -void xgi_fb_free_all(struct xgi_info * info, struct drm_file * filp) +void xgi_free_all(struct xgi_info * info, struct xgi_mem_heap * heap, + struct drm_file * filp) { - if (!info->fb_heap.initialized) { + if (!heap->initialized) { return; } - mutex_lock(&info->dev->struct_mutex); do { struct xgi_mem_block *block; - list_for_each_entry(block, &info->fb_heap.used_list, list) { + list_for_each_entry(block, &heap->used_list, list) { if (block->filp == filp) { break; } } - if (&block->list == &info->fb_heap.used_list) { + if (&block->list == &heap->used_list) { break; } - (void) xgi_mem_free(&info->fb_heap, block->offset, filp); + (void) xgi_mem_free(heap, block->offset, filp); } while(1); - - mutex_unlock(&info->dev->struct_mutex); } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 883fbe7e..b2edf3b1 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -152,37 +152,6 @@ int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, } -/** - * Free all blocks associated with a particular file handle. - */ -void xgi_pcie_free_all(struct xgi_info * info, struct drm_file * filp) -{ - if (!info->pcie_heap.initialized) { - return; - } - - mutex_lock(&info->dev->struct_mutex); - - 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_mem_free(&info->pcie_heap, block->offset, filp); - } while(1); - - mutex_unlock(&info->dev->struct_mutex); -} - - int xgi_pcie_free(struct xgi_info * info, unsigned long offset, struct drm_file * filp) { -- cgit v1.2.3 From 6718198897ef9e275506d3fcb497641e1b09d3b1 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 16:56:20 -0700 Subject: Release client memory in reclaim_buffers_idlelocked instead of preclose. --- linux-core/xgi_drv.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index f6e7b550..b6fea437 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -61,9 +61,9 @@ 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, - struct drm_file * filp); static void xgi_driver_lastclose(struct drm_device * dev); +static void xgi_reclaim_buffers_locked(struct drm_device * dev, + struct drm_file * filp); static irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS); @@ -74,7 +74,6 @@ static struct drm_driver driver = { .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, @@ -82,6 +81,7 @@ static struct drm_driver driver = { .irq_uninstall = NULL, .irq_handler = xgi_kern_isr, .reclaim_buffers = drm_core_reclaim_buffers, + .reclaim_buffers_idlelocked = xgi_reclaim_buffers_locked, .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, .ioctls = xgi_ioctls, @@ -280,17 +280,6 @@ int xgi_bootstrap(struct drm_device * dev, void * data, } -void xgi_driver_preclose(struct drm_device * dev, struct drm_file * filp) -{ - struct xgi_info * info = dev->dev_private; - - mutex_lock(&info->dev->struct_mutex); - xgi_free_all(info, &info->pcie_heap, filp); - xgi_free_all(info, &info->fb_heap, filp); - mutex_unlock(&info->dev->struct_mutex); -} - - void xgi_driver_lastclose(struct drm_device * dev) { struct xgi_info * info = dev->dev_private; @@ -322,6 +311,23 @@ void xgi_driver_lastclose(struct drm_device * dev) } +void xgi_reclaim_buffers_locked(struct drm_device * dev, + struct drm_file * filp) +{ + struct xgi_info * info = dev->dev_private; + + mutex_lock(&info->dev->struct_mutex); + if (dev->driver->dma_quiescent) { + dev->driver->dma_quiescent(dev); + } + + xgi_free_all(info, &info->pcie_heap, filp); + xgi_free_all(info, &info->fb_heap, filp); + mutex_unlock(&info->dev->struct_mutex); + return; +} + + /* * driver receives an interrupt if someone waiting, then hand it off. */ -- cgit v1.2.3 From f7ba02b7458823627097a2320bf9befa84fc9c76 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 6 Aug 2007 17:27:15 -0700 Subject: Unify infrastructure for freeing on-card / GART memory. --- linux-core/xgi_cmdlist.c | 4 +++- linux-core/xgi_drv.h | 9 ++------- linux-core/xgi_fb.c | 15 +++++++++------ linux-core/xgi_pcie.c | 19 +------------------ 4 files changed, 15 insertions(+), 32 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 33155827..e1653021 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -202,7 +202,9 @@ void xgi_cmdlist_cleanup(struct xgi_info * info) xgi_waitfor_pci_idle(info); } - xgi_pcie_free(info, info->cmdring.ring_gart_base, NULL); + xgi_free(info, (XGI_MEMLOC_NON_LOCAL + | info->cmdring.ring_gart_base), + NULL); info->cmdring.ring_hw_base = 0; info->cmdring.ring_offset = 0; info->cmdring.size = 0; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 79276b70..a7740ceb 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -38,7 +38,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 10 -#define DRIVER_PATCHLEVEL 4 +#define DRIVER_PATCHLEVEL 5 #include "xgi_cmdlist.h" #include "xgi_drm.h" @@ -89,8 +89,6 @@ struct xgi_info { }; extern struct kmem_cache *xgi_mem_block_cache; -extern int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, - struct drm_file * 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); @@ -100,15 +98,12 @@ extern int xgi_fb_heap_init(struct xgi_info * info); extern int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, struct drm_file * filp); -extern int xgi_fb_free(struct xgi_info * info, unsigned long offset, +extern int xgi_free(struct xgi_info * info, unsigned long index, struct drm_file * filp); extern int xgi_pcie_heap_init(struct xgi_info * info); extern void xgi_pcie_lut_cleanup(struct xgi_info * info); -extern int xgi_pcie_free(struct xgi_info * info, unsigned long offset, - struct drm_file * filp); - extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address); extern void xgi_free_all(struct xgi_info *, struct xgi_mem_heap *, diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index f8341a67..26e6fc4e 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -169,8 +169,8 @@ static struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, return (used_block); } -int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, - struct drm_file * filp) +static int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, + struct drm_file * filp) { struct xgi_mem_block *used_block = NULL, *block; struct xgi_mem_block *prev, *next; @@ -287,13 +287,16 @@ int xgi_fb_alloc_ioctl(struct drm_device * dev, void * data, } -int xgi_fb_free(struct xgi_info * info, unsigned long offset, - struct drm_file * filp) +int xgi_free(struct xgi_info * info, unsigned long index, + struct drm_file * filp) { int err = 0; + const unsigned heap = index & 0x03; mutex_lock(&info->dev->struct_mutex); - err = xgi_mem_free(&info->fb_heap, offset, filp); + err = xgi_mem_free((heap == XGI_MEMLOC_NON_LOCAL) + ? &info->pcie_heap : &info->fb_heap, + (index & ~0x03), filp); mutex_unlock(&info->dev->struct_mutex); return err; @@ -305,7 +308,7 @@ int xgi_fb_free_ioctl(struct drm_device * dev, void * data, { struct xgi_info *info = dev->dev_private; - return xgi_fb_free(info, *(u32 *) data, filp); + return xgi_free(info, XGI_MEMLOC_LOCAL | *(u32 *) data, filp); } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b2edf3b1..281223b3 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -152,29 +152,12 @@ int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, } -int xgi_pcie_free(struct xgi_info * info, unsigned long offset, - struct drm_file * filp) -{ - int err; - - mutex_lock(&info->dev->struct_mutex); - err = xgi_mem_free(&info->pcie_heap, offset, filp); - mutex_unlock(&info->dev->struct_mutex); - - if (err) { - DRM_ERROR("xgi_pcie_free() failed at base 0x%lx\n", offset); - } - - return err; -} - - int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, struct drm_file * filp) { struct xgi_info *info = dev->dev_private; - return xgi_pcie_free(info, *(u32 *) data, filp); + return xgi_free(info, XGI_MEMLOC_NON_LOCAL | *(u32 *) data, filp); } -- cgit v1.2.3 From 25cb876f8513d02d4d189371eaa8b7b9a88e860d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 15:23:13 -0700 Subject: Associate master file pointer with command list buffer. Pass the master's file pointer, as supplied to xgi_bootstrap, to xgi_cmdlist_initialize. Associate that pointer with the memory allocated for the command list buffer. By doing this the memory will be automatically cleaned up when the master closes the device. This allows the removal of some clean up code. --- linux-core/xgi_cmdlist.c | 13 ++++--------- linux-core/xgi_cmdlist.h | 9 ++------- linux-core/xgi_drv.c | 2 +- linux-core/xgi_drv.h | 4 ++-- 4 files changed, 9 insertions(+), 19 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index e1653021..a1ec5720 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -34,7 +34,8 @@ 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) +int xgi_cmdlist_initialize(struct xgi_info * info, size_t size, + struct drm_file * filp) { struct xgi_mem_alloc mem_alloc = { .location = XGI_MEMLOC_NON_LOCAL, @@ -42,7 +43,7 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) }; int err; - err = xgi_alloc(info, &mem_alloc, 0); + err = xgi_alloc(info, &mem_alloc, filp); if (err) { return err; } @@ -50,7 +51,6 @@ int xgi_cmdlist_initialize(struct xgi_info * info, size_t size) 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; @@ -202,12 +202,7 @@ void xgi_cmdlist_cleanup(struct xgi_info * info) xgi_waitfor_pci_idle(info); } - xgi_free(info, (XGI_MEMLOC_NON_LOCAL - | info->cmdring.ring_gart_base), - NULL); - info->cmdring.ring_hw_base = 0; - info->cmdring.ring_offset = 0; - info->cmdring.size = 0; + (void) memset(&info->cmdring, 0, sizeof(info->cmdring)); } } diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 604c9aac..07a2eb98 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -72,12 +72,6 @@ struct xgi_cmdring_info { */ 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; /** @@ -88,7 +82,8 @@ struct xgi_cmdring_info { }; struct xgi_info; -extern int xgi_cmdlist_initialize(struct xgi_info * info, size_t size); +extern int xgi_cmdlist_initialize(struct xgi_info * info, size_t size, + struct drm_file * filp); extern int xgi_state_change(struct xgi_info * info, unsigned int to, unsigned int from); diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index b6fea437..9aaeb467 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -248,7 +248,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data, } /* Alloc 1M bytes for cmdbuffer which is flush2D batch array */ - err = xgi_cmdlist_initialize(info, 0x100000); + err = xgi_cmdlist_initialize(info, 0x100000, filp); if (err) { DRM_ERROR("xgi_cmdlist_initialize() failed\n"); return err; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index a7740ceb..9c0f5a28 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -34,11 +34,11 @@ #define DRIVER_NAME "xgi" #define DRIVER_DESC "XGI XP5 / XP10 / XG47" -#define DRIVER_DATE "20070806" +#define DRIVER_DATE "20070809" #define DRIVER_MAJOR 0 #define DRIVER_MINOR 10 -#define DRIVER_PATCHLEVEL 5 +#define DRIVER_PATCHLEVEL 6 #include "xgi_cmdlist.h" #include "xgi_drm.h" -- cgit v1.2.3 From aea6b4dea9708f66f5fc2068fe84407682570aca Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 15:30:36 -0700 Subject: Unify alloc and free ioctls. The DRM_XGI_PCIE_ALLOC and DRM_XGI_FB_ALLOC ioctls (and the matching free ioctls) are unified to DRM_XGI_ALLOC. The desired memory region is selected by xgi_mem_alloc::location. The region is magically encoded in xgi_mem_alloc::index, which is used to release the memory. Bump to version 0.11.0. This update requires a new DDX. --- linux-core/xgi_drv.c | 7 ++---- linux-core/xgi_drv.h | 14 +++++------ linux-core/xgi_fb.c | 65 ++++++++++++++++++++++++++++++++------------------- linux-core/xgi_pcie.c | 21 ----------------- 4 files changed, 49 insertions(+), 58 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 9aaeb467..997051fb 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -42,11 +42,8 @@ static int xgi_bootstrap(struct drm_device *, void *, struct drm_file *); static struct drm_ioctl_desc xgi_ioctls[] = { DRM_IOCTL_DEF(DRM_XGI_BOOTSTRAP, xgi_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_XGI_FB_ALLOC, xgi_fb_alloc_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_XGI_FB_FREE, xgi_fb_free_ioctl, DRM_AUTH), - - DRM_IOCTL_DEF(DRM_XGI_PCIE_ALLOC, xgi_pcie_alloc_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_XGI_PCIE_FREE, xgi_pcie_free_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_XGI_ALLOC, xgi_alloc_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_XGI_FREE, xgi_free_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_XGI_GE_RESET, xgi_ge_reset_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_XGI_DUMP_REGISTER, xgi_dump_register_ioctl, DRM_AUTH), diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 9c0f5a28..e56d00bb 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -37,8 +37,8 @@ #define DRIVER_DATE "20070809" #define DRIVER_MAJOR 0 -#define DRIVER_MINOR 10 -#define DRIVER_PATCHLEVEL 6 +#define DRIVER_MINOR 11 +#define DRIVER_PATCHLEVEL 0 #include "xgi_cmdlist.h" #include "xgi_drm.h" @@ -89,6 +89,8 @@ struct xgi_info { }; extern struct kmem_cache *xgi_mem_block_cache; +extern int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, + struct drm_file * 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); @@ -109,13 +111,9 @@ extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address); extern void xgi_free_all(struct xgi_info *, struct xgi_mem_heap *, struct drm_file *); -extern int xgi_fb_alloc_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp); -extern int xgi_fb_free_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp); -extern int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, +extern int xgi_alloc_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); -extern int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, +extern int xgi_free_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); extern int xgi_ge_reset_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index 26e6fc4e..d0182831 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -169,8 +169,8 @@ static struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, return (used_block); } -static int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, - struct drm_file * filp) +int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, + struct drm_file * filp) { struct xgi_mem_block *used_block = NULL, *block; struct xgi_mem_block *prev, *next; @@ -243,26 +243,45 @@ static int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, - struct drm_file * filp) + struct drm_file * filp) { struct xgi_mem_block *block; + struct xgi_mem_heap *heap; + const char *const mem_name = (alloc->location == XGI_MEMLOC_LOCAL) + ? "on-card" : "GART"; + + + if ((alloc->location != XGI_MEMLOC_LOCAL) + && (alloc->location != XGI_MEMLOC_NON_LOCAL)) { + DRM_ERROR("Invalid memory pool (0x%08x) specified.\n", + alloc->location); + return -EINVAL; + } + + heap = (alloc->location == XGI_MEMLOC_LOCAL) + ? &info->fb_heap : &info->pcie_heap; + + if (!heap->initialized) { + DRM_ERROR("Attempt to allocate from uninitialized memory " + "pool (0x%08x).\n", alloc->location); + return -EINVAL; + } mutex_lock(&info->dev->struct_mutex); - block = xgi_mem_alloc((alloc->location == XGI_MEMLOC_LOCAL) - ? &info->fb_heap : &info->pcie_heap, - alloc->size); + block = xgi_mem_alloc(heap, alloc->size); mutex_unlock(&info->dev->struct_mutex); if (block == NULL) { alloc->size = 0; - DRM_ERROR("Video RAM allocation failed\n"); + DRM_ERROR("%s memory allocation failed\n", mem_name); return -ENOMEM; } else { - DRM_INFO("Video RAM allocation succeeded: 0x%p\n", - (char *)block->offset); + DRM_DEBUG("%s memory allocation succeeded: 0x%p\n", + mem_name, (char *)block->offset); alloc->size = block->size; alloc->offset = block->offset; alloc->hw_addr = block->offset; + alloc->index = alloc->offset | alloc->location; if (alloc->location == XGI_MEMLOC_NON_LOCAL) { alloc->hw_addr += info->pcie.base; @@ -275,47 +294,45 @@ int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, } -int xgi_fb_alloc_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) +int xgi_alloc_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { - struct xgi_mem_alloc *alloc = - (struct xgi_mem_alloc *) data; struct xgi_info *info = dev->dev_private; - alloc->location = XGI_MEMLOC_LOCAL; - return xgi_alloc(info, alloc, filp); + return xgi_alloc(info, (struct xgi_mem_alloc *) data, filp); } int xgi_free(struct xgi_info * info, unsigned long index, struct drm_file * filp) { - int err = 0; - const unsigned heap = index & 0x03; + int err; + struct xgi_mem_heap *const heap = + ((index & 0x03) == XGI_MEMLOC_NON_LOCAL) + ? &info->pcie_heap : &info->fb_heap; + const u32 offset = (index & ~0x03); mutex_lock(&info->dev->struct_mutex); - err = xgi_mem_free((heap == XGI_MEMLOC_NON_LOCAL) - ? &info->pcie_heap : &info->fb_heap, - (index & ~0x03), filp); + err = xgi_mem_free(heap, offset, filp); mutex_unlock(&info->dev->struct_mutex); return err; } -int xgi_fb_free_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) +int xgi_free_ioctl(struct drm_device * dev, void * data, + struct drm_file * filp) { struct xgi_info *info = dev->dev_private; - return xgi_free(info, XGI_MEMLOC_LOCAL | *(u32 *) data, filp); + return xgi_free(info, *(unsigned long *) data, 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); + info->fb.size - XGI_FB_HEAP_START); } /** diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 281223b3..4ec9b6ff 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -140,27 +140,6 @@ int xgi_pcie_heap_init(struct xgi_info * info) } -int xgi_pcie_alloc_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_mem_alloc *const alloc = - (struct xgi_mem_alloc *) data; - struct xgi_info *info = dev->dev_private; - - alloc->location = XGI_MEMLOC_NON_LOCAL; - return xgi_alloc(info, alloc, filp); -} - - -int xgi_pcie_free_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_info *info = dev->dev_private; - - return xgi_free(info, XGI_MEMLOC_NON_LOCAL | *(u32 *) data, filp); -} - - /** * xgi_find_pcie_virt * @address: GE HW address -- cgit v1.2.3 From dbd4d0597ff32458bbe4347bdea0e4b9e55a14da Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 16:01:14 -0700 Subject: Use sman memory manager instead of internal version. --- linux-core/xgi_drv.c | 46 +++++---- linux-core/xgi_drv.h | 34 +----- linux-core/xgi_fb.c | 281 ++++---------------------------------------------- linux-core/xgi_pcie.c | 6 +- 4 files changed, 54 insertions(+), 313 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 997051fb..b0f84c81 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -225,7 +225,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data, /* Init the resource manager */ - if (!info->fb_heap.initialized) { + if (!info->fb_heap_initialized) { err = xgi_fb_heap_init(info); if (err) { DRM_ERROR("Unable to initialize FB heap.\n"); @@ -237,7 +237,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data, info->pcie.size = bs->gart.size; /* Init the resource manager */ - if (!info->pcie_heap.initialized) { + if (!info->pcie_heap_initialized) { err = xgi_pcie_heap_init(info); if (err) { DRM_ERROR("Unable to initialize GART heap.\n"); @@ -296,13 +296,13 @@ void xgi_driver_lastclose(struct drm_device * dev) info->mmio_map = NULL; info->fb_map = NULL; - if (info->fb_heap.initialized) { - xgi_mem_heap_cleanup(&info->fb_heap); + if (info->pcie_heap_initialized) { + xgi_pcie_lut_cleanup(info); } - if (info->pcie_heap.initialized) { - xgi_mem_heap_cleanup(&info->pcie_heap); - xgi_pcie_lut_cleanup(info); + if (info->fb_heap_initialized + || info->pcie_heap_initialized) { + drm_sman_cleanup(&info->sman); } } } @@ -314,12 +314,16 @@ void xgi_reclaim_buffers_locked(struct drm_device * dev, struct xgi_info * info = dev->dev_private; mutex_lock(&info->dev->struct_mutex); + if (drm_sman_owner_clean(&info->sman, (unsigned long) filp)) { + mutex_unlock(&info->dev->struct_mutex); + return; + } + if (dev->driver->dma_quiescent) { dev->driver->dma_quiescent(dev); } - xgi_free_all(info, &info->pcie_heap, filp); - xgi_free_all(info, &info->fb_heap, filp); + drm_sman_owner_cleanup(&info->sman, (unsigned long) filp); mutex_unlock(&info->dev->struct_mutex); return; } @@ -357,6 +361,7 @@ void xgi_kern_isr_bh(struct drm_device *dev) int xgi_driver_load(struct drm_device *dev, unsigned long flags) { struct xgi_info *info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER); + int err; if (!info) return -ENOMEM; @@ -375,7 +380,8 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags) 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 -EINVAL; + err = -EINVAL; + goto fail; } @@ -386,28 +392,24 @@ int xgi_driver_load(struct drm_device *dev, unsigned long flags) (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 -ENOMEM; + err = drm_sman_init(&info->sman, 2, 12, 8); + if (err) { + goto fail; } return 0; + +fail: + drm_free(info, sizeof(*info), DRM_MEM_DRIVER); + return err; } int xgi_driver_unload(struct drm_device *dev) { struct xgi_info * info = dev->dev_private; - if (xgi_mem_block_cache) { - kmem_cache_destroy(xgi_mem_block_cache); - xgi_mem_block_cache = NULL; - } - + drm_sman_takedown(&info->sman); drm_free(info, sizeof(*info), DRM_MEM_DRIVER); dev->dev_private = NULL; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index e56d00bb..6b209aa4 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -29,6 +29,7 @@ #include "drmP.h" #include "drm.h" +#include "drm_sman.h" #define DRIVER_AUTHOR "Andrea Zhang " @@ -38,7 +39,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 11 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_PATCHLEVEL 1 #include "xgi_cmdlist.h" #include "xgi_drm.h" @@ -48,22 +49,6 @@ struct xgi_aperture { unsigned int size; }; -struct xgi_mem_block { - struct list_head list; - unsigned long offset; - unsigned long size; - struct drm_file * filp; -}; - -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; @@ -82,19 +67,13 @@ struct xgi_info { struct drm_dma_handle *lut_handle; unsigned int lutPageSize; - struct xgi_mem_heap fb_heap; - struct xgi_mem_heap pcie_heap; + struct drm_sman sman; + bool fb_heap_initialized; + bool pcie_heap_initialized; struct xgi_cmdring_info cmdring; }; -extern struct kmem_cache *xgi_mem_block_cache; -extern int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, - struct drm_file * 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_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, @@ -108,9 +87,6 @@ extern void xgi_pcie_lut_cleanup(struct xgi_info * info); extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address); -extern void xgi_free_all(struct xgi_info *, struct xgi_mem_heap *, - struct drm_file *); - extern int xgi_alloc_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); extern int xgi_free_ioctl(struct drm_device * dev, void * data, diff --git a/linux-core/xgi_fb.c b/linux-core/xgi_fb.c index d0182831..40f39fbc 100644 --- a/linux-core/xgi_fb.c +++ b/linux-core/xgi_fb.c @@ -28,225 +28,10 @@ #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 -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->filp = (struct drm_file *) -1; - - return block; -} - - -static struct xgi_mem_block *xgi_mem_alloc(struct xgi_mem_heap * heap, - unsigned long originalSize) -{ - 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); - - return (used_block); -} - -int xgi_mem_free(struct xgi_mem_heap * heap, unsigned long offset, - struct drm_file * 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 -ENOENT; - } - - if (block->filp != filp) { - return -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_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, struct drm_file * filp) { - struct xgi_mem_block *block; - struct xgi_mem_heap *heap; + struct drm_memblock_item *block; const char *const mem_name = (alloc->location == XGI_MEMLOC_LOCAL) ? "on-card" : "GART"; @@ -258,17 +43,16 @@ int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, return -EINVAL; } - heap = (alloc->location == XGI_MEMLOC_LOCAL) - ? &info->fb_heap : &info->pcie_heap; - - if (!heap->initialized) { + if ((alloc->location == XGI_MEMLOC_LOCAL) + ? !info->fb_heap_initialized : !info->pcie_heap_initialized) { DRM_ERROR("Attempt to allocate from uninitialized memory " "pool (0x%08x).\n", alloc->location); return -EINVAL; } mutex_lock(&info->dev->struct_mutex); - block = xgi_mem_alloc(heap, alloc->size); + block = drm_sman_alloc(&info->sman, alloc->location, alloc->size, + 0, (unsigned long) filp); mutex_unlock(&info->dev->struct_mutex); if (block == NULL) { @@ -276,18 +60,17 @@ int xgi_alloc(struct xgi_info * info, struct xgi_mem_alloc * alloc, DRM_ERROR("%s memory allocation failed\n", mem_name); return -ENOMEM; } else { - DRM_DEBUG("%s memory allocation succeeded: 0x%p\n", - mem_name, (char *)block->offset); - alloc->size = block->size; - alloc->offset = block->offset; - alloc->hw_addr = block->offset; - alloc->index = alloc->offset | alloc->location; + alloc->offset = (*block->mm->offset)(block->mm, + block->mm_info); + alloc->hw_addr = alloc->offset; + alloc->index = block->user_hash.key; if (alloc->location == XGI_MEMLOC_NON_LOCAL) { alloc->hw_addr += info->pcie.base; } - block->filp = filp; + DRM_DEBUG("%s memory allocation succeeded: 0x%x\n", + mem_name, alloc->offset); } return 0; @@ -307,13 +90,9 @@ int xgi_free(struct xgi_info * info, unsigned long index, struct drm_file * filp) { int err; - struct xgi_mem_heap *const heap = - ((index & 0x03) == XGI_MEMLOC_NON_LOCAL) - ? &info->pcie_heap : &info->fb_heap; - const u32 offset = (index & ~0x03); mutex_lock(&info->dev->struct_mutex); - err = xgi_mem_free(heap, offset, filp); + err = drm_sman_free_key(&info->sman, index); mutex_unlock(&info->dev->struct_mutex); return err; @@ -331,34 +110,14 @@ int xgi_free_ioctl(struct drm_device * dev, void * data, int xgi_fb_heap_init(struct xgi_info * info) { - return xgi_mem_heap_init(&info->fb_heap, XGI_FB_HEAP_START, + int err; + + mutex_lock(&info->dev->struct_mutex); + err = drm_sman_set_range(&info->sman, XGI_MEMLOC_LOCAL, + XGI_FB_HEAP_START, info->fb.size - XGI_FB_HEAP_START); -} - -/** - * Free all blocks associated with a particular file handle. - */ -void xgi_free_all(struct xgi_info * info, struct xgi_mem_heap * heap, - struct drm_file * filp) -{ - if (!heap->initialized) { - return; - } - - - do { - struct xgi_mem_block *block; - - list_for_each_entry(block, &heap->used_list, list) { - if (block->filp == filp) { - break; - } - } - - if (&block->list == &heap->used_list) { - break; - } + mutex_unlock(&info->dev->struct_mutex); - (void) xgi_mem_free(heap, block->offset, filp); - } while(1); + info->fb_heap_initialized = (err == 0); + return err; } diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 4ec9b6ff..932615a4 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -131,11 +131,15 @@ int xgi_pcie_heap_init(struct xgi_info * info) } - err = xgi_mem_heap_init(&info->pcie_heap, 0, info->pcie.size); + mutex_lock(&info->dev->struct_mutex); + err = drm_sman_set_range(&info->sman, XGI_MEMLOC_NON_LOCAL, + 0, info->pcie.size); + mutex_unlock(&info->dev->struct_mutex); if (err) { xgi_pcie_lut_cleanup(info); } + info->pcie_heap_initialized = (err == 0); return err; } -- cgit v1.2.3 From 6dd97099ea5c6dc7931c6b482eb5935f7dd9ed2d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 16:20:44 -0700 Subject: Minor clean up of IRQ code. Much, much more to come. --- linux-core/xgi_drv.c | 27 ++++++++------------------- linux-core/xgi_drv.h | 2 +- 2 files changed, 9 insertions(+), 20 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index b0f84c81..d0878184 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -186,8 +186,6 @@ void xgi_engine_init(struct xgi_info * info) } -void xgi_kern_isr_bh(struct drm_device *dev); - int xgi_bootstrap(struct drm_device * dev, void * data, struct drm_file * filp) { @@ -335,28 +333,19 @@ void xgi_reclaim_buffers_locked(struct drm_device * dev, 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"); + struct xgi_info *info = dev->dev_private; + const u32 irq_bits = DRM_READ32(info->mmio_map, 0x2810); - //xgi_dvi_irq_handler(info); - if (need_to_run_bottom_half) { - drm_locked_tasklet(dev, xgi_kern_isr_bh); + if ((irq_bits & 0x00000000) != 0) { + DRM_WRITE32(info->mmio_map, 0x2810, + 0x04000000 | irq_bits); + return IRQ_HANDLED; + } else { + return IRQ_NONE; } - - 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) { diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 6b209aa4..6afc4c6c 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -39,7 +39,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 11 -#define DRIVER_PATCHLEVEL 1 +#define DRIVER_PATCHLEVEL 2 #include "xgi_cmdlist.h" #include "xgi_drm.h" -- cgit v1.2.3 From 371f0a4d410f02d8db050b51fd2e714f888a71e0 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 18:15:42 -0700 Subject: Mask off correct bits in M2REG_AUTO_LINK_STATUS for interrupt handling. --- linux-core/xgi_cmdlist.h | 29 --------------------------- linux-core/xgi_drv.c | 19 ++++++++++++------ linux-core/xgi_regs.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 35 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index 07a2eb98..dc3fbe5a 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -27,35 +27,6 @@ #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. diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index d0878184..f20df585 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -334,12 +334,19 @@ irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; struct xgi_info *info = dev->dev_private; - const u32 irq_bits = DRM_READ32(info->mmio_map, 0x2810); - - - if ((irq_bits & 0x00000000) != 0) { - DRM_WRITE32(info->mmio_map, 0x2810, - 0x04000000 | irq_bits); + const u32 irq_bits = DRM_READ32(info->mmio_map, + (0x2800 + + M2REG_AUTO_LINK_STATUS_ADDRESS)) + & (M2REG_ACTIVE_TIMER_INTERRUPT_MASK + | M2REG_ACTIVE_INTERRUPT_0_MASK + | M2REG_ACTIVE_INTERRUPT_2_MASK + | M2REG_ACTIVE_INTERRUPT_3_MASK); + + + if (irq_bits != 0) { + DRM_WRITE32(info->mmio_map, + 0x2800 + M2REG_AUTO_LINK_SETTING_ADDRESS, + M2REG_AUTO_LINK_SETTING_COMMAND | irq_bits); return IRQ_HANDLED; } else { return IRQ_NONE; diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index b3a47f8e..57e93405 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -30,6 +30,57 @@ #include "drmP.h" #include "drm.h" +#define BASE_3D_ENG 0x2800 + +#define MAKE_MASK(bits) ((1U << (bits)) - 1) + +#define ONE_BIT_MASK MAKE_MASK(1) +#define TWENTY_BIT_MASK MAKE_MASK(20) +#define TWENTYONE_BIT_MASK MAKE_MASK(21) +#define TWENTYTWO_BIT_MASK MAKE_MASK(22) + +#define M2REG_FLUSH_ENGINE_ADDRESS 0x000 +#define M2REG_FLUSH_ENGINE_COMMAND 0x00 +#define M2REG_FLUSH_FLIP_ENGINE_MASK (ONE_BIT_MASK<<21) +#define M2REG_FLUSH_2D_ENGINE_MASK (ONE_BIT_MASK<<20) +#define M2REG_FLUSH_3D_ENGINE_MASK TWENTY_BIT_MASK + +/* Write register */ +#define M2REG_AUTO_LINK_SETTING_ADDRESS 0x010 +#define M2REG_AUTO_LINK_SETTING_COMMAND 0x04 +#define M2REG_CLEAR_TIMER_INTERRUPT_MASK (ONE_BIT_MASK<<11) +#define M2REG_CLEAR_INTERRUPT_3_MASK (ONE_BIT_MASK<<10) +#define M2REG_CLEAR_INTERRUPT_2_MASK (ONE_BIT_MASK<<9) +#define M2REG_CLEAR_INTERRUPT_0_MASK (ONE_BIT_MASK<<8) +#define M2REG_CLEAR_COUNTERS_MASK (ONE_BIT_MASK<<4) +#define M2REG_PCI_TRIGGER_MODE_MASK (ONE_BIT_MASK<<1) +#define M2REG_INVALID_LIST_AUTO_INTERRUPT_MASK (ONE_BIT_MASK<<0) + +/* Read register */ +#define M2REG_AUTO_LINK_STATUS_ADDRESS 0x010 +#define M2REG_AUTO_LINK_STATUS_COMMAND 0x04 +#define M2REG_ACTIVE_TIMER_INTERRUPT_MASK (ONE_BIT_MASK<<11) +#define M2REG_ACTIVE_INTERRUPT_3_MASK (ONE_BIT_MASK<<10) +#define M2REG_ACTIVE_INTERRUPT_2_MASK (ONE_BIT_MASK<<9) +#define M2REG_ACTIVE_INTERRUPT_0_MASK (ONE_BIT_MASK<<8) +#define M2REG_INVALID_LIST_AUTO_INTERRUPTED_MODE_MASK (ONE_BIT_MASK<<0) + +#define M2REG_PCI_TRIGGER_REGISTER_ADDRESS 0x014 +#define M2REG_PCI_TRIGGER_REGISTER_COMMAND 0x05 + + +/** + * Begin instruction, double-word 0 + */ +#define BEGIN_VALID_MASK (ONE_BIT_MASK<<20) +#define BEGIN_BEGIN_IDENTIFICATION_MASK TWENTY_BIT_MASK + +/** + * Begin instruction, double-word 1 + */ +#define BEGIN_LINK_ENABLE_MASK (ONE_BIT_MASK<<31) +#define BEGIN_COMMAND_LIST_LENGTH_MASK TWENTYTWO_BIT_MASK + /* Hardware access functions */ static inline void OUT3C5B(struct drm_map * map, u8 index, u8 data) -- cgit v1.2.3 From 06e09842dfbdaa9502d3b3e6b657de4e3630644c Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 18:28:16 -0700 Subject: Use DRM_MEMORYBARRIER() macro instead of mb(). --- linux-core/xgi_pcie.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index 932615a4..d15ea32a 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -96,11 +96,7 @@ static int xgi_pcie_lut_init(struct xgi_info * info) lut[i] = info->dev->sg->busaddr[i]; } -#if defined(__i386__) || defined(__x86_64__) - asm volatile ("wbinvd":::"memory"); -#else - mb(); -#endif + DRM_MEMORYBARRIER(); /* Set GART in SFB */ temp = DRM_READ8(info->mmio_map, 0xB00C); -- cgit v1.2.3 From 20a0e5e4298761ae6005399e45d66b93109d2121 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 9 Aug 2007 18:57:15 -0700 Subject: After calling drm_sman_cleanup, mark both heaps as uninitialized. Since the heaps weren't marked as uninitialized, SG memory was never re-allocated. This prevented the X-server from being able to restart without re-loading the kernel module. --- linux-core/xgi_drv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index f20df585..fa418c0d 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -301,6 +301,9 @@ void xgi_driver_lastclose(struct drm_device * dev) if (info->fb_heap_initialized || info->pcie_heap_initialized) { drm_sman_cleanup(&info->sman); + + info->fb_heap_initialized = FALSE; + info->pcie_heap_initialized = FALSE; } } } -- cgit v1.2.3 From 15f841bd529b50901272ca35a4c57de42a51901a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 13 Aug 2007 16:21:20 -0700 Subject: Strobe magic 0xB03F register to flush PCI-e GART table. The original XGI kernel driver strobed 0xB03F each time a page was allocated to back a GART page. When the driver was converted to use the DRM SG interface, this code was lost. Returning it fixes a long standing issue where the X-server would work fine the first time, but acceleration commands would be ignored on the second X-server invocation. --- linux-core/xgi_pcie.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index d15ea32a..a0f52740 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -103,7 +103,11 @@ static int xgi_pcie_lut_init(struct xgi_info * info) DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); /* Set GART base address to HW */ - dwWriteReg(info->mmio_map, 0xB034, info->lut_handle->busaddr); + DRM_WRITE32(info->mmio_map, 0xB034, info->lut_handle->busaddr); + + /* Flush GART table. */ + DRM_WRITE8(info->mmio_map, 0xB03F, 0x40); + DRM_WRITE8(info->mmio_map, 0xB03F, 0x00); return 0; } -- cgit v1.2.3 From 891714d8d732480af97fbc45562145a560b7999b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 14 Aug 2007 13:18:44 -0700 Subject: Clean up xgi_(en|dis)able_(mmio|ge) and move to xgi_misc.c. --- linux-core/xgi_drv.h | 5 ++ linux-core/xgi_misc.c | 126 ++++++++++++++++++++++++++++++++++++++++++ linux-core/xgi_regs.h | 150 ++++++++++++++------------------------------------ 3 files changed, 171 insertions(+), 110 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 6afc4c6c..9f746de2 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -87,6 +87,11 @@ extern void xgi_pcie_lut_cleanup(struct xgi_info * info); extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address); +extern void xgi_enable_mmio(struct xgi_info * info); +extern void xgi_disable_mmio(struct xgi_info * info); +extern void xgi_enable_ge(struct xgi_info * info); +extern void xgi_disable_ge(struct xgi_info * info); + extern int xgi_alloc_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); extern int xgi_free_ioctl(struct drm_device * dev, void * data, diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 84d1d4f2..be75e970 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -374,3 +374,129 @@ void xgi_waitfor_pci_idle(struct xgi_info * info) } } } + + +void xgi_enable_mmio(struct xgi_info * info) +{ + u8 protect = 0; + u8 temp; + + /* Unprotect registers */ + DRM_WRITE8(info->mmio_map, 0x3C4, 0x11); + protect = DRM_READ8(info->mmio_map, 0x3C5); + DRM_WRITE8(info->mmio_map, 0x3C5, 0x92); + + DRM_WRITE8(info->mmio_map, 0x3D4, 0x3A); + temp = DRM_READ8(info->mmio_map, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x20); + + /* Enable MMIO */ + DRM_WRITE8(info->mmio_map, 0x3D4, 0x39); + temp = DRM_READ8(info->mmio_map, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D5, temp | 0x01); + + /* Protect registers */ + OUT3C5B(info->mmio_map, 0x11, protect); +} + + +void xgi_disable_mmio(struct xgi_info * info) +{ + u8 protect = 0; + u8 temp; + + /* Unprotect registers */ + DRM_WRITE8(info->mmio_map, 0x3C4, 0x11); + protect = DRM_READ8(info->mmio_map, 0x3C5); + DRM_WRITE8(info->mmio_map, 0x3C5, 0x92); + + /* Disable MMIO access */ + DRM_WRITE8(info->mmio_map, 0x3D4, 0x39); + temp = DRM_READ8(info->mmio_map, 0x3D5); + DRM_WRITE8(info->mmio_map, 0x3D5, temp & 0xFE); + + /* Protect registers */ + OUT3C5B(info->mmio_map, 0x11, protect); +} + + +void xgi_enable_ge(struct xgi_info * info) +{ + u8 bOld3cf2a; + int wait = 0; + + OUT3C5B(info->mmio_map, 0x11, 0x92); + + /* Save and close dynamic gating + */ + bOld3cf2a = IN3CFB(info->mmio_map, XGI_MISC_CTRL); + OUT3CFB(info->mmio_map, XGI_MISC_CTRL, bOld3cf2a & ~EN_GEPWM); + + /* Enable 2D and 3D GE + */ + OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D)); + wait = 10; + while (wait--) { + DRM_READ8(info->mmio_map, 0x36); + } + + /* Reset both 3D and 2D engine + */ + OUT3X5B(info->mmio_map, XGI_GE_CNTL, + (GE_ENABLE | GE_RESET | GE_ENABLE_3D)); + wait = 10; + while (wait--) { + DRM_READ8(info->mmio_map, 0x36); + } + + OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D)); + wait = 10; + while (wait--) { + DRM_READ8(info->mmio_map, 0x36); + } + + /* Enable 2D engine only + */ + OUT3X5B(info->mmio_map, XGI_GE_CNTL, GE_ENABLE); + + /* Enable 2D+3D engine + */ + OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D)); + + /* Restore dynamic gating + */ + OUT3CFB(info->mmio_map, XGI_MISC_CTRL, bOld3cf2a); +} + + +void xgi_disable_ge(struct xgi_info * info) +{ + int wait = 0; + + OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D)); + + wait = 10; + while (wait--) { + DRM_READ8(info->mmio_map, 0x36); + } + + /* Reset both 3D and 2D engine + */ + OUT3X5B(info->mmio_map, XGI_GE_CNTL, + (GE_ENABLE | GE_RESET | GE_ENABLE_3D)); + + wait = 10; + while (wait--) { + DRM_READ8(info->mmio_map, 0x36); + } + OUT3X5B(info->mmio_map, XGI_GE_CNTL, (GE_ENABLE | GE_ENABLE_3D)); + + wait = 10; + while (wait--) { + DRM_READ8(info->mmio_map, 0x36); + } + + /* Disable 2D engine and 3D engine. + */ + OUT3X5B(info->mmio_map, XGI_GE_CNTL, 0); +} diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 57e93405..7f643f92 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -30,8 +30,6 @@ #include "drmP.h" #include "drm.h" -#define BASE_3D_ENG 0x2800 - #define MAKE_MASK(bits) ((1U << (bits)) - 1) #define ONE_BIT_MASK MAKE_MASK(1) @@ -39,6 +37,46 @@ #define TWENTYONE_BIT_MASK MAKE_MASK(21) #define TWENTYTWO_BIT_MASK MAKE_MASK(22) + +/* Port 0x3d4/0x3d5, index 0x2a */ +#define XGI_INTERFACE_SEL 0x2a +#define DUAL_64BIT (1U<<7) +#define INTERNAL_32BIT (1U<<6) +#define EN_SEP_WR (1U<<5) +#define POWER_DOWN_SEL (1U<<4) +/*#define RESERVED_3 (1U<<3) */ +#define SUBS_MCLK_PCICLK (1U<<2) +#define MEM_SIZE_MASK (3<<0) +#define MEM_SIZE_32MB (0<<0) +#define MEM_SIZE_64MB (1<<0) +#define MEM_SIZE_128MB (2<<0) +#define MEM_SIZE_256MB (3<<0) + +/* Port 0x3d4/0x3d5, index 0x36 */ +#define XGI_GE_CNTL 0x36 +#define GE_ENABLE (1U<<7) +/*#define RESERVED_6 (1U<<6) */ +/*#define RESERVED_5 (1U<<5) */ +#define GE_RESET (1U<<4) +/*#define RESERVED_3 (1U<<3) */ +#define GE_ENABLE_3D (1U<<2) +/*#define RESERVED_1 (1U<<1) */ +/*#define RESERVED_0 (1U<<0) */ + +/* Port 0x3ce/0x3cf, index 0x2a */ +#define XGI_MISC_CTRL 0x2a +#define MOTION_VID_SUSPEND (1U<<7) +#define DVI_CRTC_TIMING_SEL (1U<<6) +#define LCD_SEL_CTL_NEW (1U<<5) +#define LCD_SEL_EXT_DELYCTRL (1U<<4) +#define REG_LCDDPARST (1U<<3) +#define LCD2DPAOFF (1U<<2) +/*#define RESERVED_1 (1U<<1) */ +#define EN_GEPWM (1U<<0) /* Enable GE power management */ + + +#define BASE_3D_ENG 0x2800 + #define M2REG_FLUSH_ENGINE_ADDRESS 0x000 #define M2REG_FLUSH_ENGINE_COMMAND 0x00 #define M2REG_FLUSH_FLIP_ENGINE_MASK (ONE_BIT_MASK<<21) @@ -133,114 +171,6 @@ static inline void dwWriteReg(struct drm_map * map, u32 addr, u32 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 - OUT3C5B(info->mmio_map, 0x11, 0x92); - - // 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 -- cgit v1.2.3 From be76f0eea9b455fde77e15ff35f4f00c70661e51 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 14 Aug 2007 13:19:48 -0700 Subject: Remove unused interrupt related functions. --- linux-core/xgi_regs.h | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 7f643f92..098d824d 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -170,28 +170,4 @@ static inline void dwWriteReg(struct drm_map * map, u32 addr, u32 data) DRM_WRITE32(map, addr, data); } - -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 -- cgit v1.2.3 From d3c8e98dd9ccc366513c117d032fbf80be4eb06a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 14 Aug 2007 13:20:37 -0700 Subject: Move dwWriteReg to xgi_cmdlist.c, the only file where it is used. --- linux-core/xgi_cmdlist.c | 14 ++++++++++++++ linux-core/xgi_regs.h | 13 ------------- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index a1ec5720..a728c0ef 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -34,6 +34,20 @@ static unsigned int get_batch_command(enum xgi_batch_type type); static void triggerHWCommandList(struct xgi_info * info); static void xgi_cmdlist_reset(struct xgi_info * info); + +/** + * Graphic engine register (2d/3d) acessing interface + */ +static inline void dwWriteReg(struct drm_map * map, u32 addr, u32 data) +{ +#ifdef XGI_MMIO_DEBUG + DRM_INFO("mmio_map->handle = 0x%p, addr = 0x%x, data = 0x%x\n", + map->handle, addr, data); +#endif + DRM_WRITE32(map, addr, data); +} + + int xgi_cmdlist_initialize(struct xgi_info * info, size_t size, struct drm_file * filp) { diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 098d824d..2f9fbe64 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -157,17 +157,4 @@ static inline u8 IN3CFB(struct drm_map * map, u8 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); -} - #endif -- cgit v1.2.3 From 7b12174aacd09a991be3e74a3db47534961a6887 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 14 Aug 2007 13:24:02 -0700 Subject: Clean up remaining C++ style comments. --- linux-core/xgi_misc.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index be75e970..8232de9a 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -202,15 +202,18 @@ 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 - { + /* CRT1 interrupt just happened + */ + if (IN3CFB(info->mmio_map, 0x37) & 0x01) { u8 op3cf_3d; u8 op3cf_37; - // What happened? + /* What happened? + */ op3cf_37 = IN3CFB(info->mmio_map, 0x37); - // Clear CRT interrupt + /* 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)); @@ -226,25 +229,30 @@ 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 + /* DVI interrupt just happened + */ + if (IN3CFB(info->mmio_map, 0x38) & 0x20) { const u8 save_3x4 = DRM_READ8(info->mmio_map, 0x3d4); u8 op3cf_39; u8 op3cf_37; u8 op3x5_5a; - // What happened? + /* What happened? + */ op3cf_37 = IN3CFB(info->mmio_map, 0x37); - //Notify BIOS that DVI plug/unplug happened + /* 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 + /* 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 + OUT3C5B(info->mmio_map, 0x39, (op3cf_39 & ~0x01)); + OUT3C5B(info->mmio_map, 0x39, (op3cf_39 | 0x01)); ret = TRUE; } -- cgit v1.2.3 From f563a50d145848ed296b63c63422caff80232ddf Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 14 Aug 2007 13:44:51 -0700 Subject: Eliminate unused / useless ioctls. --- linux-core/xgi_drv.c | 6 ------ linux-core/xgi_drv.h | 14 +++----------- linux-core/xgi_misc.c | 33 --------------------------------- linux-core/xgi_pcie.c | 32 -------------------------------- 4 files changed, 3 insertions(+), 82 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index fa418c0d..0e77d4cd 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -41,15 +41,9 @@ static int xgi_bootstrap(struct drm_device *, void *, struct drm_file *); static struct drm_ioctl_desc xgi_ioctls[] = { DRM_IOCTL_DEF(DRM_XGI_BOOTSTRAP, xgi_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_XGI_ALLOC, xgi_alloc_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_XGI_FREE, xgi_free_ioctl, DRM_AUTH), - - DRM_IOCTL_DEF(DRM_XGI_GE_RESET, xgi_ge_reset_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_XGI_DUMP_REGISTER, xgi_dump_register_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_XGI_DEBUG_INFO, xgi_restore_registers_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_XGI_SUBMIT_CMDLIST, xgi_submit_cmdlist, DRM_AUTH), - DRM_IOCTL_DEF(DRM_XGI_TEST_RWINKERNEL, xgi_test_rwinkernel_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_XGI_STATE_CHANGE, xgi_state_change_ioctl, DRM_AUTH|DRM_MASTER), }; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 9f746de2..194313cd 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -35,11 +35,11 @@ #define DRIVER_NAME "xgi" #define DRIVER_DESC "XGI XP5 / XP10 / XG47" -#define DRIVER_DATE "20070809" +#define DRIVER_DATE "20070814" #define DRIVER_MAJOR 0 -#define DRIVER_MINOR 11 -#define DRIVER_PATCHLEVEL 2 +#define DRIVER_MINOR 12 +#define DRIVER_PATCHLEVEL 0 #include "xgi_cmdlist.h" #include "xgi_drm.h" @@ -96,16 +96,8 @@ extern int xgi_alloc_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); extern int xgi_free_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); -extern int xgi_ge_reset_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp); -extern int xgi_dump_register_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp); -extern int xgi_restore_registers_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp); extern int xgi_submit_cmdlist(struct drm_device * dev, void * data, struct drm_file * filp); -extern int xgi_test_rwinkernel_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp); extern int xgi_state_change_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); diff --git a/linux-core/xgi_misc.c b/linux-core/xgi_misc.c index 8232de9a..50a721c0 100644 --- a/linux-core/xgi_misc.c +++ b/linux-core/xgi_misc.c @@ -29,18 +29,6 @@ #include -int xgi_ge_reset_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_info *info = dev->dev_private; - - xgi_disable_ge(info); - xgi_enable_ge(info); - - return 0; -} - - /* * irq functions */ @@ -324,27 +312,6 @@ void xgi_dump_register(struct xgi_info * info) } -int xgi_dump_register_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_info *info = dev->dev_private; - - xgi_dump_register(info); - return 0; -} - - -int xgi_restore_registers_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_info *info = dev->dev_private; - - OUT3X5B(info->mmio_map, 0x13, 0); - OUT3X5B(info->mmio_map, 0x8b, 2); - return 0; -} - - #define WHOLD_GE_STATUS 0x2800 /* Test everything except the "whole GE busy" bit, the "master engine busy" diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index a0f52740..b4d204c1 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -157,35 +157,3 @@ void *xgi_find_pcie_virt(struct xgi_info * info, u32 address) return ((u8 *) info->dev->sg->virtual) + offset; } - -/* - address -- GE hw address -*/ -int xgi_test_rwinkernel_ioctl(struct drm_device * dev, void * data, - struct drm_file * filp) -{ - struct xgi_info *info = dev->dev_private; - u32 address = *(u32 *) data; - u32 *virtaddr = 0; - - - DRM_INFO("input GE HW addr is 0x%x\n", address); - - if (address == 0) { - return -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 -EFAULT; - } - - return 0; -} -- cgit v1.2.3 From d8a800b63de09f41d482d2b3367e4da67ed0f92b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 15 Aug 2007 21:05:26 -0700 Subject: Implement fence support. --- linux-core/Makefile.kernel | 3 +- linux-core/xgi_cmdlist.c | 76 ++++++++++++++++++++++++++++++++++++---------- linux-core/xgi_cmdlist.h | 2 ++ linux-core/xgi_drv.c | 18 +++++++++++ linux-core/xgi_drv.h | 13 +++++++- linux-core/xgi_regs.h | 9 ++++++ 6 files changed, 103 insertions(+), 18 deletions(-) (limited to 'linux-core') diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index c898206d..c651b0b2 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -38,7 +38,8 @@ via-objs := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o \ via_video.o via_dmablit.o via_fence.o via_buffer.o mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o nv-objs := nv_drv.o -xgi-objs := xgi_cmdlist.o xgi_drv.o xgi_fb.o xgi_misc.o xgi_pcie.o +xgi-objs := xgi_cmdlist.o xgi_drv.o xgi_fb.o xgi_misc.o xgi_pcie.o \ + xgi_fence.o ifeq ($(CONFIG_COMPAT),y) drm-objs += drm_ioc32.o diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index a728c0ef..5409892a 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -28,8 +28,10 @@ #include "xgi_regs.h" #include "xgi_misc.h" #include "xgi_cmdlist.h" +#include -static void xgi_emit_flush(struct xgi_info * info, bool link); +static void xgi_emit_flush(struct xgi_info * info, bool stop); +static void xgi_emit_nop(struct xgi_info * info); static unsigned int get_batch_command(enum xgi_batch_type type); static void triggerHWCommandList(struct xgi_info * info); static void xgi_cmdlist_reset(struct xgi_info * info); @@ -101,7 +103,7 @@ int xgi_submit_cmdlist(struct drm_device * dev, void * data, begin[0] = (cmd << 24) | BEGIN_VALID_MASK - | (BEGIN_BEGIN_IDENTIFICATION_MASK & pCmdInfo->id); + | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence); begin[1] = BEGIN_LINK_ENABLE_MASK | pCmdInfo->size; begin[2] = pCmdInfo->hw_addr >> 4; begin[3] = 0; @@ -134,19 +136,20 @@ int xgi_submit_cmdlist(struct drm_device * dev, void * data, DRM_DEBUG("info->cmdring.last_ptr != NULL\n"); if (pCmdInfo->type == BTYPE_3D) { - xgi_emit_flush(info, TRUE); + xgi_emit_flush(info, FALSE); } info->cmdring.last_ptr[1] = begin[1]; info->cmdring.last_ptr[2] = begin[2]; info->cmdring.last_ptr[3] = begin[3]; - wmb(); + DRM_WRITEMEMORYBARRIER(); info->cmdring.last_ptr[0] = begin[0]; triggerHWCommandList(info); } info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr); + drm_fence_flush_old(info->dev, 0, info->next_sequence); return 0; } @@ -213,9 +216,11 @@ void xgi_cmdlist_cleanup(struct xgi_info * info) */ if (info->cmdring.last_ptr != NULL) { xgi_emit_flush(info, FALSE); - xgi_waitfor_pci_idle(info); + xgi_emit_nop(info); } + xgi_waitfor_pci_idle(info); + (void) memset(&info->cmdring, 0, sizeof(info->cmdring)); } } @@ -233,23 +238,25 @@ static void triggerHWCommandList(struct xgi_info * info) /** * Emit a flush to the CRTL command stream. * @info XGI info structure - * @link Emit (or don't emit) link information at start of flush command. * * This function assumes info->cmdring.ptr is non-NULL. */ -static void xgi_emit_flush(struct xgi_info * info, bool link) +void xgi_emit_flush(struct xgi_info * info, bool stop) { - static const u32 flush_command[8] = { - (0x10 << 24), + const u32 flush_command[8] = { + ((0x10 << 24) + | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence)), BEGIN_LINK_ENABLE_MASK | (0x00004), 0x00000000, 0x00000000, - /* Flush everything with the default 32 clock delay. + /* Flush the 2D engine with the default 32 clock delay. */ - 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff + M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, + M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, + M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, + M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, }; - const unsigned int base = (link) ? 0 : 4; - const unsigned int flush_size = (8 - base) * sizeof(u32); + const unsigned int flush_size = sizeof(flush_command); u32 *batch_addr; u32 hw_addr; @@ -263,17 +270,54 @@ static void xgi_emit_flush(struct xgi_info * info, bool link) batch_addr = info->cmdring.ptr + (info->cmdring.ring_offset / 4); - (void) memcpy(batch_addr, & flush_command[base], flush_size); + (void) memcpy(batch_addr, flush_command, flush_size); + + if (stop) { + *batch_addr |= BEGIN_STOP_STORE_CURRENT_POINTER_MASK; + } info->cmdring.last_ptr[1] = BEGIN_LINK_ENABLE_MASK | (flush_size / 4); info->cmdring.last_ptr[2] = hw_addr >> 4; info->cmdring.last_ptr[3] = 0; - wmb(); + DRM_WRITEMEMORYBARRIER(); info->cmdring.last_ptr[0] = (get_batch_command(BTYPE_CTRL) << 24) | (BEGIN_VALID_MASK); triggerHWCommandList(info); info->cmdring.ring_offset += flush_size; - info->cmdring.last_ptr = (link) ? batch_addr : NULL; + info->cmdring.last_ptr = batch_addr; +} + + +/** + * Emit an empty command to the CRTL command stream. + * @info XGI info structure + * + * This function assumes info->cmdring.ptr is non-NULL. In addition, since + * this function emits a command that does not have linkage information, + * it sets info->cmdring.ptr to NULL. + */ +void xgi_emit_nop(struct xgi_info * info) +{ + info->cmdring.last_ptr[1] = BEGIN_LINK_ENABLE_MASK + | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence); + info->cmdring.last_ptr[2] = 0; + info->cmdring.last_ptr[3] = 0; + DRM_WRITEMEMORYBARRIER(); + info->cmdring.last_ptr[0] = (get_batch_command(BTYPE_CTRL) << 24) + | (BEGIN_VALID_MASK); + + triggerHWCommandList(info); + + info->cmdring.last_ptr = NULL; +} + + +void xgi_emit_irq(struct xgi_info * info) +{ + if (info->cmdring.last_ptr == NULL) + return; + + xgi_emit_flush(info, TRUE); } diff --git a/linux-core/xgi_cmdlist.h b/linux-core/xgi_cmdlist.h index dc3fbe5a..f6f1c1ef 100644 --- a/linux-core/xgi_cmdlist.h +++ b/linux-core/xgi_cmdlist.h @@ -61,4 +61,6 @@ extern int xgi_state_change(struct xgi_info * info, unsigned int to, extern void xgi_cmdlist_cleanup(struct xgi_info * info); +extern void xgi_emit_irq(struct xgi_info * info); + #endif /* _XGI_CMDLIST_H_ */ diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 0e77d4cd..241cd39f 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -37,6 +37,17 @@ static struct pci_device_id pciidlist[] = { xgi_PCI_IDS }; +static struct drm_fence_driver xgi_fence_driver = { + .num_classes = 1, + .wrap_diff = BEGIN_BEGIN_IDENTIFICATION_MASK, + .flush_diff = BEGIN_BEGIN_IDENTIFICATION_MASK - 1, + .sequence_mask = BEGIN_BEGIN_IDENTIFICATION_MASK, + .lazy_capable = 1, + .emit = xgi_fence_emit_sequence, + .poke_flush = xgi_poke_flush, + .has_irq = xgi_fence_has_irq +}; + static int xgi_bootstrap(struct drm_device *, void *, struct drm_file *); static struct drm_ioctl_desc xgi_ioctls[] = { @@ -95,6 +106,8 @@ static struct drm_driver driver = { .remove = __devexit_p(drm_cleanup_pci), }, + .fence_driver = &xgi_fence_driver, + .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE, @@ -189,6 +202,10 @@ int xgi_bootstrap(struct drm_device * dev, void * data, int err; + spin_lock_init(&info->fence_lock); + info->next_sequence = 0; + info->complete_sequence = 0; + if (info->mmio_map == NULL) { err = drm_addmap(dev, info->mmio.base, info->mmio.size, _DRM_REGISTERS, _DRM_KERNEL, @@ -344,6 +361,7 @@ irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS) DRM_WRITE32(info->mmio_map, 0x2800 + M2REG_AUTO_LINK_SETTING_ADDRESS, M2REG_AUTO_LINK_SETTING_COMMAND | irq_bits); + xgi_fence_handler(dev); return IRQ_HANDLED; } else { return IRQ_NONE; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index 194313cd..c815f63e 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -38,7 +38,7 @@ #define DRIVER_DATE "20070814" #define DRIVER_MAJOR 0 -#define DRIVER_MINOR 12 +#define DRIVER_MINOR 13 #define DRIVER_PATCHLEVEL 0 #include "xgi_cmdlist.h" @@ -72,6 +72,10 @@ struct xgi_info { bool pcie_heap_initialized; struct xgi_cmdring_info cmdring; + + spinlock_t fence_lock; + unsigned complete_sequence; + unsigned next_sequence; }; extern int xgi_fb_heap_init(struct xgi_info * info); @@ -92,6 +96,13 @@ extern void xgi_disable_mmio(struct xgi_info * info); extern void xgi_enable_ge(struct xgi_info * info); extern void xgi_disable_ge(struct xgi_info * info); +extern void xgi_poke_flush(struct drm_device * dev, uint32_t class); +extern int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class, + uint32_t flags, uint32_t * sequence, uint32_t * native_type); +extern void xgi_fence_handler(struct drm_device * dev); +extern int xgi_fence_has_irq(struct drm_device *dev, uint32_t class, + uint32_t flags); + extern int xgi_alloc_ioctl(struct drm_device * dev, void * data, struct drm_file * filp); extern int xgi_free_ioctl(struct drm_device * dev, void * data, diff --git a/linux-core/xgi_regs.h b/linux-core/xgi_regs.h index 2f9fbe64..5c0100a0 100644 --- a/linux-core/xgi_regs.h +++ b/linux-core/xgi_regs.h @@ -83,6 +83,14 @@ #define M2REG_FLUSH_2D_ENGINE_MASK (ONE_BIT_MASK<<20) #define M2REG_FLUSH_3D_ENGINE_MASK TWENTY_BIT_MASK +#define M2REG_RESET_ADDRESS 0x004 +#define M2REG_RESET_COMMAND 0x01 +#define M2REG_RESET_STATUS2_MASK (ONE_BIT_MASK<<10) +#define M2REG_RESET_STATUS1_MASK (ONE_BIT_MASK<<9) +#define M2REG_RESET_STATUS0_MASK (ONE_BIT_MASK<<8) +#define M2REG_RESET_3DENG_MASK (ONE_BIT_MASK<<4) +#define M2REG_RESET_2DENG_MASK (ONE_BIT_MASK<<2) + /* Write register */ #define M2REG_AUTO_LINK_SETTING_ADDRESS 0x010 #define M2REG_AUTO_LINK_SETTING_COMMAND 0x04 @@ -110,6 +118,7 @@ /** * Begin instruction, double-word 0 */ +#define BEGIN_STOP_STORE_CURRENT_POINTER_MASK (ONE_BIT_MASK<<22) #define BEGIN_VALID_MASK (ONE_BIT_MASK<<20) #define BEGIN_BEGIN_IDENTIFICATION_MASK TWENTY_BIT_MASK -- cgit v1.2.3 From 0d3c741df19c35307723422c1f2f28a23995823d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 16 Aug 2007 13:43:04 -0700 Subject: Forgot to add this file on the last commit. --- linux-core/xgi_fence.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 linux-core/xgi_fence.c (limited to 'linux-core') diff --git a/linux-core/xgi_fence.c b/linux-core/xgi_fence.c new file mode 100644 index 00000000..e5b545de --- /dev/null +++ b/linux-core/xgi_fence.c @@ -0,0 +1,125 @@ +/* + * (C) Copyright IBM Corporation 2007 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Ian Romanick + */ + +#include "xgi_drv.h" +#include "xgi_regs.h" +#include "xgi_misc.h" +#include "xgi_cmdlist.h" + +static uint32_t xgi_do_flush(struct drm_device * dev, uint32_t class) +{ + struct xgi_info * info = dev->dev_private; + struct drm_fence_class_manager * fc = &dev->fm.class[class]; + uint32_t pending_flush_types = 0; + uint32_t signaled_flush_types = 0; + + + if ((info == NULL) || (class != 0)) + return 0; + + spin_lock(&info->fence_lock); + + pending_flush_types = fc->pending_flush | + ((fc->pending_exe_flush) ? DRM_FENCE_TYPE_EXE : 0); + + if (pending_flush_types) { + if (pending_flush_types & DRM_FENCE_TYPE_EXE) { + const u32 begin_id = DRM_READ32(info->mmio_map, + 0x2820) + & BEGIN_BEGIN_IDENTIFICATION_MASK; + + if (begin_id != info->complete_sequence) { + info->complete_sequence = begin_id; + signaled_flush_types |= DRM_FENCE_TYPE_EXE; + } + } + + if (signaled_flush_types) { + drm_fence_handler(dev, 0, info->complete_sequence, + signaled_flush_types); + } + } + + spin_unlock(&info->fence_lock); + + return fc->pending_flush | + ((fc->pending_exe_flush) ? DRM_FENCE_TYPE_EXE : 0); +} + + +int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class, + uint32_t flags, uint32_t * sequence, + uint32_t * native_type) +{ + struct xgi_info * info = dev->dev_private; + + if ((info == NULL) || (class != 0)) + return -EINVAL; + + + spin_lock(&info->fence_lock); + info->next_sequence++; + if (info->next_sequence > BEGIN_BEGIN_IDENTIFICATION_MASK) { + info->next_sequence = 1; + } + spin_unlock(&info->fence_lock); + + + *sequence = (uint32_t) info->next_sequence; + *native_type = DRM_FENCE_TYPE_EXE; + + return 0; +} + + +void xgi_poke_flush(struct drm_device * dev, uint32_t class) +{ + struct drm_fence_manager * fm = &dev->fm; + unsigned long flags; + + + write_lock_irqsave(&fm->lock, flags); + xgi_do_flush(dev, class); + write_unlock_irqrestore(&fm->lock, flags); +} + + +void xgi_fence_handler(struct drm_device * dev) +{ + struct drm_fence_manager * fm = &dev->fm; + + + write_lock(&fm->lock); + xgi_do_flush(dev, 0); + write_unlock(&fm->lock); +} + + +int xgi_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags) +{ + return ((class == 0) && (flags == DRM_FENCE_TYPE_EXE)) ? 1 : 0; +} -- cgit v1.2.3 From 3383e8bd6bcd2323c81252e617c8522593baf818 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 17 Aug 2007 10:53:18 -0700 Subject: Remove unnecessary include. --- linux-core/xgi_cmdlist.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_cmdlist.c b/linux-core/xgi_cmdlist.c index 5409892a..261f4e13 100644 --- a/linux-core/xgi_cmdlist.c +++ b/linux-core/xgi_cmdlist.c @@ -28,7 +28,6 @@ #include "xgi_regs.h" #include "xgi_misc.h" #include "xgi_cmdlist.h" -#include static void xgi_emit_flush(struct xgi_info * info, bool stop); static void xgi_emit_nop(struct xgi_info * info); -- cgit v1.2.3 From 2bcd5b5e330843e1e1a5f0a19105ecd33e76b00b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 29 Aug 2007 00:04:18 -0700 Subject: Use DRM_SPINLOCK / DRM_UNSPINLOCK macros. --- linux-core/xgi_drv.c | 2 +- linux-core/xgi_drv.h | 2 +- linux-core/xgi_fence.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 241cd39f..6b576558 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -202,7 +202,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data, int err; - spin_lock_init(&info->fence_lock); + DRM_SPINLOCK_INIT(&info->fence_lock); info->next_sequence = 0; info->complete_sequence = 0; diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index c815f63e..d43a6b4e 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -73,7 +73,7 @@ struct xgi_info { struct xgi_cmdring_info cmdring; - spinlock_t fence_lock; + DRM_SPINTYPE fence_lock; unsigned complete_sequence; unsigned next_sequence; }; diff --git a/linux-core/xgi_fence.c b/linux-core/xgi_fence.c index e5b545de..42ed814d 100644 --- a/linux-core/xgi_fence.c +++ b/linux-core/xgi_fence.c @@ -41,7 +41,7 @@ static uint32_t xgi_do_flush(struct drm_device * dev, uint32_t class) if ((info == NULL) || (class != 0)) return 0; - spin_lock(&info->fence_lock); + DRM_SPINLOCK(&info->fence_lock); pending_flush_types = fc->pending_flush | ((fc->pending_exe_flush) ? DRM_FENCE_TYPE_EXE : 0); @@ -64,7 +64,7 @@ static uint32_t xgi_do_flush(struct drm_device * dev, uint32_t class) } } - spin_unlock(&info->fence_lock); + DRM_SPINUNLOCK(&info->fence_lock); return fc->pending_flush | ((fc->pending_exe_flush) ? DRM_FENCE_TYPE_EXE : 0); @@ -81,12 +81,12 @@ int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class, return -EINVAL; - spin_lock(&info->fence_lock); + DRM_SPINLOCK(&info->fence_lock); info->next_sequence++; if (info->next_sequence > BEGIN_BEGIN_IDENTIFICATION_MASK) { info->next_sequence = 1; } - spin_unlock(&info->fence_lock); + DRM_SPINUNLOCK(&info->fence_lock); *sequence = (uint32_t) info->next_sequence; -- cgit v1.2.3 From c46ffd6b2943332a88589fb525305ffd09d35b8d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 29 Aug 2007 00:23:30 -0700 Subject: Fix late night dumb-dumb mistake. --- linux-core/xgi_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 6b576558..4b90579e 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -202,7 +202,7 @@ int xgi_bootstrap(struct drm_device * dev, void * data, int err; - DRM_SPINLOCK_INIT(&info->fence_lock); + DRM_SPININIT(&info->fence_lock, "fence lock"); info->next_sequence = 0; info->complete_sequence = 0; -- cgit v1.2.3 From 9c5b9d458bc618fb9d7d8590c866655e92f9cb0b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 29 Aug 2007 14:41:49 -0700 Subject: Use ati_pcigart for PCI-e GART table handling. --- linux-core/xgi_drv.c | 2 +- linux-core/xgi_drv.h | 3 +- linux-core/xgi_pcie.c | 89 ++++++++++++++++----------------------------------- 3 files changed, 30 insertions(+), 64 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.c b/linux-core/xgi_drv.c index 4b90579e..84547f62 100644 --- a/linux-core/xgi_drv.c +++ b/linux-core/xgi_drv.c @@ -306,7 +306,7 @@ void xgi_driver_lastclose(struct drm_device * dev) info->fb_map = NULL; if (info->pcie_heap_initialized) { - xgi_pcie_lut_cleanup(info); + drm_ati_pcigart_cleanup(dev, &info->gart_info); } if (info->fb_heap_initialized diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index d43a6b4e..f2768d1b 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -64,7 +64,7 @@ struct xgi_info { struct drm_map *fb_map; /* look up table parameters */ - struct drm_dma_handle *lut_handle; + struct ati_pcigart_info gart_info; unsigned int lutPageSize; struct drm_sman sman; @@ -87,7 +87,6 @@ extern int xgi_free(struct xgi_info * info, unsigned long index, struct drm_file * filp); extern int xgi_pcie_heap_init(struct xgi_info * info); -extern void xgi_pcie_lut_cleanup(struct xgi_info * info); extern void *xgi_find_pcie_virt(struct xgi_info * info, u32 address); diff --git a/linux-core/xgi_pcie.c b/linux-core/xgi_pcie.c index b4d204c1..a7d3ea24 100644 --- a/linux-core/xgi_pcie.c +++ b/linux-core/xgi_pcie.c @@ -28,15 +28,31 @@ #include "xgi_regs.h" #include "xgi_misc.h" -static int xgi_pcie_lut_init(struct xgi_info * info) +void xgi_gart_flush(struct drm_device *dev) +{ + struct xgi_info *const info = dev->dev_private; + u8 temp; + + DRM_MEMORYBARRIER(); + + /* Set GART in SFB */ + temp = DRM_READ8(info->mmio_map, 0xB00C); + DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); + + /* Set GART base address to HW */ + DRM_WRITE32(info->mmio_map, 0xB034, info->gart_info.bus_addr); + + /* Flush GART table. */ + DRM_WRITE8(info->mmio_map, 0xB03F, 0x40); + DRM_WRITE8(info->mmio_map, 0xB03F, 0x00); +} + + +int xgi_pcie_heap_init(struct xgi_info * info) { u8 temp = 0; int err; - 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); @@ -70,73 +86,24 @@ static int xgi_pcie_lut_init(struct xgi_info * info) return err; } - sg = info->dev->sg; + info->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + info->gart_info.gart_reg_if = DRM_ATI_GART_PCI; + info->gart_info.table_size = info->dev->sg->pages * sizeof(u32); - 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"); + if (!drm_ati_pcigart_init(info->dev, &info->gart_info)) { + DRM_ERROR("failed to init PCI GART!\n"); return -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 info->dev->sg->busaddr[i]; - } - - lut[i] = info->dev->sg->busaddr[i]; - } - - DRM_MEMORYBARRIER(); - - /* Set GART in SFB */ - temp = DRM_READ8(info->mmio_map, 0xB00C); - DRM_WRITE8(info->mmio_map, 0xB00C, temp & ~0x02); - - /* Set GART base address to HW */ - DRM_WRITE32(info->mmio_map, 0xB034, info->lut_handle->busaddr); - - /* Flush GART table. */ - DRM_WRITE8(info->mmio_map, 0xB03F, 0x40); - DRM_WRITE8(info->mmio_map, 0xB03F, 0x00); - - return 0; -} - -void xgi_pcie_lut_cleanup(struct xgi_info * info) -{ - 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; - } + xgi_gart_flush(info->dev); mutex_lock(&info->dev->struct_mutex); err = drm_sman_set_range(&info->sman, XGI_MEMLOC_NON_LOCAL, 0, info->pcie.size); mutex_unlock(&info->dev->struct_mutex); if (err) { - xgi_pcie_lut_cleanup(info); + drm_ati_pcigart_cleanup(info->dev, &info->gart_info); } info->pcie_heap_initialized = (err == 0); -- cgit v1.2.3 From bb3da88601749cd647632eed86fb57dfd7cb81ee Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 31 Aug 2007 10:48:13 -0700 Subject: Acutally emit the IRQ (duh) when setting the fence post. --- linux-core/xgi_fence.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/xgi_fence.c b/linux-core/xgi_fence.c index 42ed814d..adedf300 100644 --- a/linux-core/xgi_fence.c +++ b/linux-core/xgi_fence.c @@ -87,7 +87,9 @@ int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class, info->next_sequence = 1; } DRM_SPINUNLOCK(&info->fence_lock); - + + + xgi_emit_irq(info); *sequence = (uint32_t) info->next_sequence; *native_type = DRM_FENCE_TYPE_EXE; -- cgit v1.2.3 From c597bd57eee3ea05a3b8c851615c7351d0b32fce Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 6 Sep 2007 15:20:52 -0700 Subject: Bump version to 1.0.0. --- linux-core/xgi_drv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core') diff --git a/linux-core/xgi_drv.h b/linux-core/xgi_drv.h index f2768d1b..88ade64d 100644 --- a/linux-core/xgi_drv.h +++ b/linux-core/xgi_drv.h @@ -35,10 +35,10 @@ #define DRIVER_NAME "xgi" #define DRIVER_DESC "XGI XP5 / XP10 / XG47" -#define DRIVER_DATE "20070814" +#define DRIVER_DATE "20070906" -#define DRIVER_MAJOR 0 -#define DRIVER_MINOR 13 +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 #include "xgi_cmdlist.h" -- cgit v1.2.3