0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <linux/export.h>
0035 #include <linux/pci.h>
0036
0037 #include <drm/drm_device.h>
0038 #include <drm/drm_legacy.h>
0039 #include <drm/drm_print.h>
0040
0041 #include "ati_pcigart.h"
0042
0043 # define ATI_PCIGART_PAGE_SIZE 4096
0044
0045 static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
0046 struct drm_ati_pcigart_info *gart_info)
0047 {
0048 drm_dma_handle_t *dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
0049
0050 if (!dmah)
0051 return -ENOMEM;
0052
0053 dmah->size = gart_info->table_size;
0054 dmah->vaddr = dma_alloc_coherent(dev->dev,
0055 dmah->size,
0056 &dmah->busaddr,
0057 GFP_KERNEL);
0058
0059 if (!dmah->vaddr) {
0060 kfree(dmah);
0061 return -ENOMEM;
0062 }
0063
0064 gart_info->table_handle = dmah;
0065 return 0;
0066 }
0067
0068 static void drm_ati_free_pcigart_table(struct drm_device *dev,
0069 struct drm_ati_pcigart_info *gart_info)
0070 {
0071 drm_dma_handle_t *dmah = gart_info->table_handle;
0072
0073 dma_free_coherent(dev->dev, dmah->size, dmah->vaddr, dmah->busaddr);
0074 kfree(dmah);
0075
0076 gart_info->table_handle = NULL;
0077 }
0078
0079 int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
0080 {
0081 struct drm_sg_mem *entry = dev->sg;
0082 struct pci_dev *pdev = to_pci_dev(dev->dev);
0083 unsigned long pages;
0084 int i;
0085 int max_pages;
0086
0087
0088 if (!entry) {
0089 DRM_ERROR("no scatter/gather memory!\n");
0090 return 0;
0091 }
0092
0093 if (gart_info->bus_addr) {
0094
0095 max_pages = (gart_info->table_size / sizeof(u32));
0096 pages = (entry->pages <= max_pages)
0097 ? entry->pages : max_pages;
0098
0099 for (i = 0; i < pages; i++) {
0100 if (!entry->busaddr[i])
0101 break;
0102 dma_unmap_page(&pdev->dev, entry->busaddr[i],
0103 PAGE_SIZE, DMA_BIDIRECTIONAL);
0104 }
0105
0106 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
0107 gart_info->bus_addr = 0;
0108 }
0109
0110 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN &&
0111 gart_info->table_handle) {
0112 drm_ati_free_pcigart_table(dev, gart_info);
0113 }
0114
0115 return 1;
0116 }
0117
0118 int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
0119 {
0120 struct drm_local_map *map = &gart_info->mapping;
0121 struct drm_sg_mem *entry = dev->sg;
0122 struct pci_dev *pdev = to_pci_dev(dev->dev);
0123 void *address = NULL;
0124 unsigned long pages;
0125 u32 *pci_gart = NULL, page_base, gart_idx;
0126 dma_addr_t bus_address = 0;
0127 int i, j, ret = -ENOMEM;
0128 int max_ati_pages, max_real_pages;
0129
0130 if (!entry) {
0131 DRM_ERROR("no scatter/gather memory!\n");
0132 goto done;
0133 }
0134
0135 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
0136 DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
0137
0138 if (dma_set_mask(&pdev->dev, gart_info->table_mask)) {
0139 DRM_ERROR("fail to set dma mask to 0x%Lx\n",
0140 (unsigned long long)gart_info->table_mask);
0141 ret = -EFAULT;
0142 goto done;
0143 }
0144
0145 ret = drm_ati_alloc_pcigart_table(dev, gart_info);
0146 if (ret) {
0147 DRM_ERROR("cannot allocate PCI GART page!\n");
0148 goto done;
0149 }
0150
0151 pci_gart = gart_info->table_handle->vaddr;
0152 address = gart_info->table_handle->vaddr;
0153 bus_address = gart_info->table_handle->busaddr;
0154 } else {
0155 address = gart_info->addr;
0156 bus_address = gart_info->bus_addr;
0157 DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n",
0158 (unsigned long long)bus_address,
0159 (unsigned long)address);
0160 }
0161
0162
0163 max_ati_pages = (gart_info->table_size / sizeof(u32));
0164 max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE);
0165 pages = (entry->pages <= max_real_pages)
0166 ? entry->pages : max_real_pages;
0167
0168 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
0169 memset(pci_gart, 0, max_ati_pages * sizeof(u32));
0170 } else {
0171 memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u32));
0172 }
0173
0174 gart_idx = 0;
0175 for (i = 0; i < pages; i++) {
0176
0177 entry->busaddr[i] = dma_map_page(&pdev->dev, entry->pagelist[i],
0178 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
0179 if (dma_mapping_error(&pdev->dev, entry->busaddr[i])) {
0180 DRM_ERROR("unable to map PCIGART pages!\n");
0181 drm_ati_pcigart_cleanup(dev, gart_info);
0182 address = NULL;
0183 bus_address = 0;
0184 ret = -ENOMEM;
0185 goto done;
0186 }
0187 page_base = (u32) entry->busaddr[i];
0188
0189 for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
0190 u32 offset;
0191 u32 val;
0192
0193 switch(gart_info->gart_reg_if) {
0194 case DRM_ATI_GART_IGP:
0195 val = page_base | 0xc;
0196 break;
0197 case DRM_ATI_GART_PCIE:
0198 val = (page_base >> 8) | 0xc;
0199 break;
0200 default:
0201 case DRM_ATI_GART_PCI:
0202 val = page_base;
0203 break;
0204 }
0205 if (gart_info->gart_table_location ==
0206 DRM_ATI_GART_MAIN) {
0207 pci_gart[gart_idx] = cpu_to_le32(val);
0208 } else {
0209 offset = gart_idx * sizeof(u32);
0210 writel(val, (void __iomem *)map->handle + offset);
0211 }
0212 gart_idx++;
0213 page_base += ATI_PCIGART_PAGE_SIZE;
0214 }
0215 }
0216 ret = 0;
0217
0218 #ifdef CONFIG_X86
0219 wbinvd();
0220 #else
0221 mb();
0222 #endif
0223
0224 done:
0225 gart_info->addr = address;
0226 gart_info->bus_addr = bus_address;
0227 return ret;
0228 }