summaryrefslogtreecommitdiff
path: root/linux-core
AgeCommit message (Expand)Author
2000-12-12- Fix nasty depth span bug. Drawable offset was not being added to pixelGareth Hughes
2000-12-02Merged ati-4-1-1-branch into trunk.Gareth Hughes
2000-11-15Sync with Linux 2.4.0-test11-pre5 Provide backward compatibility testedRik Faith
2000-11-08merge with 4.0.1dDavid Dawes
2000-09-29More changes for sync with Linux 2.4.0-test9-pre7Rik Faith
2000-09-29Audit calls to schedule() Remove tags from files shared with Linux kernelRik Faith
2000-09-28Fixed two things Rik pointed out in the last commitJeff Hartmann
2000-09-27Merged the mga-lock-debug-0-2-0-branch with the trunk. This includesJeff Hartmann
2000-09-24commit xfree86 4.0.1d-pre updateAlan Hourihane
2000-09-10Sync with 2.4.0-test8 kernel.Gareth Hughes
2000-09-07Merged tdfx-2-1-branchAlan Hourihane
2000-09-06Sync with 2.4.0-test8-pre5 kernel.Gareth Hughes
2000-08-31Bump version number after kernel interface change.Keith Whitwell
2000-08-28Add compatibility header file to make Linux 2.4.0 kernel patches cleaner.Rik Faith
2000-08-26Sync with Linux 2.4.0-test7 Add signal blocking support to all driversRik Faith
2000-08-25Remove misleading authorship information from sis driver (author has beenRik Faith
2000-08-18Fix ABA problem in drm_freelist_{put,try}Rik Faith
2000-08-18Sync with Linux 2.4.0-test7/pre4Rik Faith
2000-08-17Bug #112197 Made sis driver compile under 2.4.0-test7/pre4Rik Faith
2000-08-16Initial revisionDavid Dawes
2000-08-08Sync with Linux 2.4.0-test6-pre8Rik Faith
2000-08-07Fix for multiple sarea bug + agp built into kernel segfaultJeff Hartmann
2000-08-04Sync with Linux 2.4.0-test6-pre2Rik Faith
2000-07-22Fix typoRik Faith
2000-07-22Move to new, denser, easier-to-read Linux kernel Makefile formatRik Faith
2000-07-21Revert some changes and try alternative way to clean up AGP handling.Rik Faith
2000-07-21Revert some changes and try alternative way to clean up AGP handling.Rik Faith
2000-07-21Fixes for building in the kernel treeRik Faith
2000-07-21Changes to make AGP optional for in-kernel buildsRik Faith
2000-07-20More fixups for kernel build: EXPORT_SYMTAB warning removalRik Faith
2000-07-20Fixes for building in the kernel treeRik Faith
2000-07-20Fixed for monolithic kernel buildRik Faith
2000-07-20Fix signature for *_options functionRik Faith
2000-07-20Added support for building as modules or as part of monolithic kernelRik Faith
2000-07-19Bump driver dates and add descriptionsRik Faith
2000-07-19Sync with Linux 2.4.0-test4 kernelRik Faith
2000-07-13applied Jeff's xf86cvs-I810copy.patchBrian Paul
2000-07-11Merge XFree86 4.0.1Alan Hourihane
2000-07-10Import of XFree86 4.0.1Alan Hourihane
2000-07-01Fix for agpgart module detection. If the kernel module has been configuredGareth Hughes
2000-06-13Unify code with kernel: Change some spacing in comments Add #includeRik Faith
2000-06-13Update email addresses and copyright notices to reflect VA Linux SystemsRik Faith
2000-06-12Merging the ati-4-1-0 branch onto the trunk.Gareth Hughes
2000-06-08Merged glxmisc-3-0-0Brian Paul
2000-06-06define VM_DONTCOPY to zero if undefinedBrian Paul
2000-05-25Merged mga-0-0-3-branchKeith Whitwell
2000-05-18Merged ati-4-0-1Kevin E Martin
2000-04-05Fixed reclaim OopsJeff Hartmann
2000-04-04Merged mga branch with trunkJeff Hartmann
2000-03-16Merge with 4.0Jeff Hartmann
NY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ***************************************************************************/ #include "xgi_drv.h" #include "xgi_regs.h" #include "xgi_misc.h" #include "xgi_cmdlist.h" static void xgi_emit_flush(struct xgi_info * info, bool stop); static void xgi_emit_nop(struct xgi_info * info); static unsigned int get_batch_command(enum xgi_batch_type type); static void triggerHWCommandList(struct xgi_info * info); static void xgi_cmdlist_reset(struct xgi_info * info); /** * Graphic engine register (2d/3d) acessing interface */ static inline void dwWriteReg(struct drm_map * map, u32 addr, u32 data) { #ifdef XGI_MMIO_DEBUG DRM_INFO("mmio_map->handle = 0x%p, addr = 0x%x, data = 0x%x\n", map->handle, addr, data); #endif DRM_WRITE32(map, addr, data); } int xgi_cmdlist_initialize(struct xgi_info * info, size_t size, struct drm_file * filp) { struct xgi_mem_alloc mem_alloc = { .location = XGI_MEMLOC_NON_LOCAL, .size = size, }; int err; err = xgi_alloc(info, &mem_alloc, filp); if (err) { return err; } info->cmdring.ptr = xgi_find_pcie_virt(info, mem_alloc.hw_addr); info->cmdring.size = mem_alloc.size; info->cmdring.ring_hw_base = mem_alloc.hw_addr; info->cmdring.last_ptr = NULL; info->cmdring.ring_offset = 0; return 0; } /** * get_batch_command - Get the command ID for the current begin type. * @type: Type of the current batch * * See section 3.2.2 "Begin" (page 15) of the 3D SPG. * * This function assumes that @type is on the range [0,3]. */ unsigned int get_batch_command(enum xgi_batch_type type) { static const unsigned int ports[4] = { 0x30 >> 2, 0x40 >> 2, 0x50 >> 2, 0x20 >> 2 }; return ports[type]; } int xgi_submit_cmdlist(struct drm_device * dev, void * data, struct drm_file * filp) { struct xgi_info *const info = dev->dev_private; const struct xgi_cmd_info *const pCmdInfo = (struct xgi_cmd_info *) data; const unsigned int cmd = get_batch_command(pCmdInfo->type); u32 begin[4]; begin[0] = (cmd << 24) | BEGIN_VALID_MASK | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence); begin[1] = BEGIN_LINK_ENABLE_MASK | pCmdInfo->size; begin[2] = pCmdInfo->hw_addr >> 4; begin[3] = 0; if (info->cmdring.last_ptr == NULL) { const unsigned int portOffset = BASE_3D_ENG + (cmd << 2); /* Enable PCI Trigger Mode */ dwWriteReg(info->mmio_map, BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | M2REG_CLEAR_COUNTERS_MASK | 0x08 | M2REG_PCI_TRIGGER_MODE_MASK); dwWriteReg(info->mmio_map, BASE_3D_ENG + M2REG_AUTO_LINK_SETTING_ADDRESS, (M2REG_AUTO_LINK_SETTING_ADDRESS << 22) | 0x08 | M2REG_PCI_TRIGGER_MODE_MASK); /* Send PCI begin command */ dwWriteReg(info->mmio_map, portOffset, begin[0]); dwWriteReg(info->mmio_map, portOffset + 4, begin[1]); dwWriteReg(info->mmio_map, portOffset + 8, begin[2]); dwWriteReg(info->mmio_map, portOffset + 12, begin[3]); } else { DRM_DEBUG("info->cmdring.last_ptr != NULL\n"); if (pCmdInfo->type == BTYPE_3D) { xgi_emit_flush(info, FALSE); } info->cmdring.last_ptr[1] = cpu_to_le32(begin[1]); info->cmdring.last_ptr[2] = cpu_to_le32(begin[2]); info->cmdring.last_ptr[3] = cpu_to_le32(begin[3]); DRM_WRITEMEMORYBARRIER(); info->cmdring.last_ptr[0] = cpu_to_le32(begin[0]); triggerHWCommandList(info); } info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr); #ifdef XGI_HAVE_FENCE drm_fence_flush_old(info->dev, 0, info->next_sequence); #endif /* XGI_HAVE_FENCE */ return 0; } /* state: 0 - console 1 - graphic 2 - fb 3 - logout */ int xgi_state_change(struct xgi_info * info, unsigned int to, unsigned int from) { #define STATE_CONSOLE 0 #define STATE_GRAPHIC 1 #define STATE_FBTERM 2 #define STATE_LOGOUT 3 #define STATE_REBOOT 4 #define STATE_SHUTDOWN 5 if ((from == STATE_GRAPHIC) && (to == STATE_CONSOLE)) { DRM_INFO("Leaving graphical mode (probably VT switch)\n"); } else if ((from == STATE_CONSOLE) && (to == STATE_GRAPHIC)) { DRM_INFO("Entering graphical mode (probably VT switch)\n"); xgi_cmdlist_reset(info); } else if ((from == STATE_GRAPHIC) && ((to == STATE_LOGOUT) || (to == STATE_REBOOT) || (to == STATE_SHUTDOWN))) { DRM_INFO("Leaving graphical mode (probably X shutting down)\n"); } else { DRM_ERROR("Invalid state change.\n"); return -EINVAL; } return 0; } int xgi_state_change_ioctl(struct drm_device * dev, void * data, struct drm_file * filp) { struct xgi_state_info *const state = (struct xgi_state_info *) data; struct xgi_info *info = dev->dev_private; return xgi_state_change(info, state->_toState, state->_fromState); } void xgi_cmdlist_reset(struct xgi_info * info) { info->cmdring.last_ptr = NULL; info->cmdring.ring_offset = 0; } void xgi_cmdlist_cleanup(struct xgi_info * info) { if (info->cmdring.ring_hw_base != 0) { /* If command lists have been issued, terminate the command * list chain with a flush command. */ if (info->cmdring.last_ptr != NULL) { xgi_emit_flush(info, FALSE); xgi_emit_nop(info); } xgi_waitfor_pci_idle(info); (void) memset(&info->cmdring, 0, sizeof(info->cmdring)); } } static void triggerHWCommandList(struct xgi_info * info) { static unsigned int s_triggerID = 1; dwWriteReg(info->mmio_map, BASE_3D_ENG + M2REG_PCI_TRIGGER_REGISTER_ADDRESS, 0x05000000 + (0x0ffff & s_triggerID++)); } /** * Emit a flush to the CRTL command stream. * @info XGI info structure * * This function assumes info->cmdring.ptr is non-NULL. */ void xgi_emit_flush(struct xgi_info * info, bool stop) { const u32 flush_command[8] = { ((0x10 << 24) | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence)), BEGIN_LINK_ENABLE_MASK | (0x00004), 0x00000000, 0x00000000, /* Flush the 2D engine with the default 32 clock delay. */ M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, M2REG_FLUSH_ENGINE_COMMAND | M2REG_FLUSH_2D_ENGINE_MASK, }; const unsigned int flush_size = sizeof(flush_command); u32 *batch_addr; u32 hw_addr; unsigned int i; /* check buf is large enough to contain a new flush batch */ if ((info->cmdring.ring_offset + flush_size) >= info->cmdring.size) { info->cmdring.ring_offset = 0; } hw_addr = info->cmdring.ring_hw_base + info->cmdring.ring_offset; batch_addr = info->cmdring.ptr + (info->cmdring.ring_offset / 4); for (i = 0; i < (flush_size / 4); i++) { batch_addr[i] = cpu_to_le32(flush_command[i]); } if (stop) { *batch_addr |= cpu_to_le32(BEGIN_STOP_STORE_CURRENT_POINTER_MASK); } info->cmdring.last_ptr[1] = cpu_to_le32(BEGIN_LINK_ENABLE_MASK | (flush_size / 4)); info->cmdring.last_ptr[2] = cpu_to_le32(hw_addr >> 4); info->cmdring.last_ptr[3] = 0; DRM_WRITEMEMORYBARRIER(); info->cmdring.last_ptr[0] = cpu_to_le32((get_batch_command(BTYPE_CTRL) << 24) | (BEGIN_VALID_MASK)); triggerHWCommandList(info); info->cmdring.ring_offset += flush_size; info->cmdring.last_ptr = batch_addr; } /** * Emit an empty command to the CRTL command stream. * @info XGI info structure * * This function assumes info->cmdring.ptr is non-NULL. In addition, since * this function emits a command that does not have linkage information, * it sets info->cmdring.ptr to NULL. */ void xgi_emit_nop(struct xgi_info * info) { info->cmdring.last_ptr[1] = cpu_to_le32(BEGIN_LINK_ENABLE_MASK | (BEGIN_BEGIN_IDENTIFICATION_MASK & info->next_sequence)); info->cmdring.last_ptr[2] = 0; info->cmdring.last_ptr[3] = 0; DRM_WRITEMEMORYBARRIER(); info->cmdring.last_ptr[0] = cpu_to_le32((get_batch_command(BTYPE_CTRL) << 24) | (BEGIN_VALID_MASK)); triggerHWCommandList(info); info->cmdring.last_ptr = NULL; } void xgi_emit_irq(struct xgi_info * info) { if (info->cmdring.last_ptr == NULL) return; xgi_emit_flush(info, TRUE); }