1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 /* 6 * ati_pcigart.h -- ATI PCI GART support -*- linux-c -*- 7 * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com 8 */ 9 /* 10 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 11 * All Rights Reserved. 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a 14 * copy of this software and associated documentation files (the "Software"), 15 * to deal in the Software without restriction, including without limitation 16 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 * and/or sell copies of the Software, and to permit persons to whom the 18 * Software is furnished to do so, subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice (including the next 21 * paragraph) shall be included in all copies or substantial portions of the 22 * Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 * DEALINGS IN THE SOFTWARE. 31 * 32 * Authors: 33 * Gareth Hughes <gareth@valinux.com> 34 * 35 */ 36 37 #include "drmP.h" 38 39 #define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */ 40 #define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */ 41 #define ATI_PCIGART_TABLE_SIZE 32768 42 43 int 44 drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 45 { 46 unsigned long pages; 47 drm_sg_mem_t *entry; 48 drm_dma_handle_t *dmah; 49 u32 *pci_gart = NULL, page_base; 50 int i, j, k; 51 int pagenum; 52 size_t bulksize; 53 54 entry = dev->sg; 55 if (entry == NULL) { 56 DRM_ERROR("no scatter/gather memory!\n"); 57 return (0); 58 } 59 60 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { 61 /* GART table in system memory */ 62 entry->dmah_gart = drm_pci_alloc(dev, ATI_PCIGART_TABLE_SIZE, 0, 63 0xfffffffful, 1); 64 if (entry->dmah_gart == NULL) { 65 DRM_ERROR("cannot allocate PCI GART table!\n"); 66 return (0); 67 } 68 gart_info->addr = (void *)entry->dmah_gart->vaddr; 69 gart_info->bus_addr = entry->dmah_gart->paddr; 70 pci_gart = (u32 *)entry->dmah_gart->vaddr; 71 } else { 72 /* GART table in framebuffer memory */ 73 pci_gart = gart_info->addr; 74 } 75 76 pages = DRM_MIN(entry->pages, ATI_MAX_PCIGART_PAGES); 77 bzero(pci_gart, ATI_PCIGART_TABLE_SIZE); 78 /*CONSTCOND*/ 79 ASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE); 80 81 dmah = entry->dmah_sg; 82 pagenum = 0; 83 for (i = 0; i < dmah->cookie_num; i++) { 84 bulksize = dmah->cookie.dmac_size; 85 for (k = 0; k < bulksize / PAGE_SIZE; k++) { 86 entry->busaddr[pagenum] = 87 dmah->cookie.dmac_address + k * PAGE_SIZE; 88 page_base = (u32) entry->busaddr[pagenum]; 89 if (pagenum ++ == pages) 90 goto out; 91 for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); 92 j++) { 93 if (gart_info->is_pcie) 94 *pci_gart = (page_base >> 8) | 0xc; 95 else 96 *pci_gart = page_base; 97 pci_gart++; 98 page_base += ATI_PCIGART_PAGE_SIZE; 99 } 100 } 101 ddi_dma_nextcookie(dmah->dma_hdl, &dmah->cookie); 102 } 103 104 out: 105 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { 106 (void) ddi_dma_sync(entry->dmah_gart->dma_hdl, 0, 107 entry->dmah_gart->real_sz, DDI_DMA_SYNC_FORDEV); 108 } 109 110 return (1); 111 } 112 113 /*ARGSUSED*/ 114 extern int 115 drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 116 { 117 drm_dma_handle_t *dmah; 118 119 if (dev->sg == NULL) { 120 DRM_ERROR("no scatter/gather memory!\n"); 121 return (0); 122 } 123 dmah = dev->sg->dmah_gart; 124 dev->sg->dmah_gart = NULL; 125 if (dmah) 126 drm_pci_free(dev, dmah); 127 return (1); 128 } 129