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 #pragma ident "%Z%%M% %I% %E% SMI" 38 39 #include "drmP.h" 40 41 #define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */ 42 #define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */ 43 #define ATI_PCIGART_TABLE_SIZE 32768 44 45 int 46 drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 47 { 48 unsigned long pages; 49 drm_sg_mem_t *entry; 50 drm_dma_handle_t *dmah; 51 u32 *pci_gart = NULL, page_base; 52 int i, j, k; 53 int pagenum; 54 size_t bulksize; 55 56 entry = dev->sg; 57 if (entry == NULL) { 58 DRM_ERROR("no scatter/gather memory!\n"); 59 return (0); 60 } 61 62 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { 63 /* GART table in system memory */ 64 entry->dmah_gart = drm_pci_alloc(dev, ATI_PCIGART_TABLE_SIZE, 0, 65 0xfffffffful, 1); 66 if (entry->dmah_gart == NULL) { 67 DRM_ERROR("cannot allocate PCI GART table!\n"); 68 return (0); 69 } 70 gart_info->addr = (void *)entry->dmah_gart->vaddr; 71 gart_info->bus_addr = entry->dmah_gart->paddr; 72 pci_gart = (u32 *)entry->dmah_gart->vaddr; 73 } else { 74 /* GART table in framebuffer memory */ 75 pci_gart = gart_info->addr; 76 } 77 78 pages = DRM_MIN(entry->pages, ATI_MAX_PCIGART_PAGES); 79 bzero(pci_gart, ATI_PCIGART_TABLE_SIZE); 80 ASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE); 81 82 dmah = entry->dmah_sg; 83 pagenum = 0; 84 for (i = 0; i < dmah->cookie_num; i++) { 85 bulksize = dmah->cookie.dmac_size; 86 for (k = 0; k < bulksize / PAGE_SIZE; k++) { 87 entry->busaddr[pagenum] = 88 dmah->cookie.dmac_address + k * PAGE_SIZE; 89 page_base = (u32) entry->busaddr[pagenum]; 90 if (pagenum ++ == pages) 91 goto out; 92 for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); 93 j++) { 94 if (gart_info->is_pcie) 95 *pci_gart = (page_base >> 8) | 0xc; 96 else 97 *pci_gart = page_base; 98 pci_gart++; 99 page_base += ATI_PCIGART_PAGE_SIZE; 100 } 101 } 102 ddi_dma_nextcookie(dmah->dma_hdl, &dmah->cookie); 103 } 104 105 out: 106 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { 107 (void) ddi_dma_sync(entry->dmah_gart->dma_hdl, 0, 108 entry->dmah_gart->real_sz, DDI_DMA_SYNC_FORDEV); 109 } 110 111 return (1); 112 } 113 114 /*ARGSUSED*/ 115 extern int 116 drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) 117 { 118 drm_dma_handle_t *dmah; 119 120 if (dev->sg == NULL) { 121 DRM_ERROR("no scatter/gather memory!\n"); 122 return (0); 123 } 124 dmah = dev->sg->dmah_gart; 125 dev->sg->dmah_gart = NULL; 126 if (dmah) 127 drm_pci_free(dev, dmah); 128 return (1); 129 } 130