aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core/ati_pcigart.c')
-rw-r--r--linux-core/ati_pcigart.c199
1 files changed, 17 insertions, 182 deletions
diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c
index 6b0d8947..40f8f8dd 100644
--- a/linux-core/ati_pcigart.c
+++ b/linux-core/ati_pcigart.c
@@ -39,7 +39,7 @@
39#define ATI_PCIE_WRITE 0x4 39#define ATI_PCIE_WRITE 0x4
40#define ATI_PCIE_READ 0x8 40#define ATI_PCIE_READ 0x8
41 41
42static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info *gart_info, dma_addr_t addr, volatile u32 *pci_gart) 42static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info *gart_info, dma_addr_t addr, u32 *pci_gart)
43{ 43{
44 u32 page_base; 44 u32 page_base;
45 45
@@ -61,28 +61,8 @@ static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info *
61 *pci_gart = cpu_to_le32(page_base); 61 *pci_gart = cpu_to_le32(page_base);
62} 62}
63 63
64static __inline__ dma_addr_t gart_get_page_from_table(struct drm_ati_pcigart_info *gart_info, volatile u32 *pci_gart) 64static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
65{ 65 struct drm_ati_pcigart_info *gart_info)
66 dma_addr_t retval;
67 switch(gart_info->gart_reg_if) {
68 case DRM_ATI_GART_IGP:
69 retval = (*pci_gart & ATI_PCIGART_PAGE_MASK);
70 retval += (((*pci_gart & 0xf0) >> 4) << 16) << 16;
71 break;
72 case DRM_ATI_GART_PCIE:
73 retval = (*pci_gart & ~0xc);
74 retval <<= 8;
75 break;
76 case DRM_ATI_GART_PCI:
77 retval = *pci_gart;
78 break;
79 }
80
81 return retval;
82}
83
84int drm_ati_alloc_pcigart_table(struct drm_device *dev,
85 struct drm_ati_pcigart_info *gart_info)
86{ 66{
87 gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size, 67 gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
88 PAGE_SIZE, 68 PAGE_SIZE,
@@ -90,25 +70,12 @@ int drm_ati_alloc_pcigart_table(struct drm_device *dev,
90 if (gart_info->table_handle == NULL) 70 if (gart_info->table_handle == NULL)
91 return -ENOMEM; 71 return -ENOMEM;
92 72
93#ifdef CONFIG_X86
94 /* IGPs only exist on x86 in any case */
95 if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
96 set_memory_uc((unsigned long)gart_info->table_handle->vaddr, gart_info->table_size >> PAGE_SHIFT);
97#endif
98
99 memset(gart_info->table_handle->vaddr, 0, gart_info->table_size);
100 return 0; 73 return 0;
101} 74}
102EXPORT_SYMBOL(drm_ati_alloc_pcigart_table);
103 75
104static void drm_ati_free_pcigart_table(struct drm_device *dev, 76static void drm_ati_free_pcigart_table(struct drm_device *dev,
105 struct drm_ati_pcigart_info *gart_info) 77 struct drm_ati_pcigart_info *gart_info)
106{ 78{
107#ifdef CONFIG_X86
108 /* IGPs only exist on x86 in any case */
109 if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
110 set_memory_wb((unsigned long)gart_info->table_handle->vaddr, gart_info->table_size >> PAGE_SHIFT);
111#endif
112 drm_pci_free(dev, gart_info->table_handle); 79 drm_pci_free(dev, gart_info->table_handle);
113 gart_info->table_handle = NULL; 80 gart_info->table_handle = NULL;
114} 81}
@@ -122,6 +89,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
122 89
123 /* we need to support large memory configurations */ 90 /* we need to support large memory configurations */
124 if (!entry) { 91 if (!entry) {
92 DRM_ERROR("no scatter/gather memory!\n");
125 return 0; 93 return 0;
126 } 94 }
127 95
@@ -164,8 +132,12 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
164 int max_pages; 132 int max_pages;
165 dma_addr_t entry_addr; 133 dma_addr_t entry_addr;
166 134
135 if (!entry) {
136 DRM_ERROR("no scatter/gather memory!\n");
137 goto done;
138 }
167 139
168 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && gart_info->table_handle == NULL) { 140 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
169 DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); 141 DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
170 142
171 ret = drm_ati_alloc_pcigart_table(dev, gart_info); 143 ret = drm_ati_alloc_pcigart_table(dev, gart_info);
@@ -173,19 +145,14 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
173 DRM_ERROR("cannot allocate PCI GART page!\n"); 145 DRM_ERROR("cannot allocate PCI GART page!\n");
174 goto done; 146 goto done;
175 } 147 }
176 }
177 148
178 if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
179 address = gart_info->table_handle->vaddr; 149 address = gart_info->table_handle->vaddr;
180 bus_address = gart_info->table_handle->busaddr; 150 bus_address = gart_info->table_handle->busaddr;
181 } else { 151 } else {
182 address = gart_info->addr; 152 address = gart_info->addr;
183 bus_address = gart_info->bus_addr; 153 bus_address = gart_info->bus_addr;
184 } 154 DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
185 155 bus_address, (unsigned long)address);
186 if (!entry) {
187 DRM_ERROR("no scatter/gather memory!\n");
188 goto done;
189 } 156 }
190 157
191 pci_gart = (u32 *) address; 158 pci_gart = (u32 *) address;
@@ -194,6 +161,8 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
194 pages = (entry->pages <= max_pages) 161 pages = (entry->pages <= max_pages)
195 ? entry->pages : max_pages; 162 ? entry->pages : max_pages;
196 163
164 memset(pci_gart, 0, max_pages * sizeof(u32));
165
197 for (i = 0; i < pages; i++) { 166 for (i = 0; i < pages; i++) {
198 /* we need to support large memory configurations */ 167 /* we need to support large memory configurations */
199 entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], 168 entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i],
@@ -216,7 +185,11 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
216 185
217 ret = 1; 186 ret = 1;
218 187
188#if defined(__i386__) || defined(__x86_64__)
189 wbinvd();
190#else
219 mb(); 191 mb();
192#endif
220 193
221 done: 194 done:
222 gart_info->addr = address; 195 gart_info->addr = address;
@@ -224,141 +197,3 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
224 return ret; 197 return ret;
225} 198}
226EXPORT_SYMBOL(drm_ati_pcigart_init); 199EXPORT_SYMBOL(drm_ati_pcigart_init);
227
228static int ati_pcigart_needs_unbind_cache_adjust(struct drm_ttm_backend *backend)
229{
230 return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
231}
232
233static int ati_pcigart_populate(struct drm_ttm_backend *backend,
234 unsigned long num_pages,
235 struct page **pages,
236 struct page *dummy_read_page)
237{
238 struct ati_pcigart_ttm_backend *atipci_be =
239 container_of(backend, struct ati_pcigart_ttm_backend, backend);
240
241 atipci_be->pages = pages;
242 atipci_be->num_pages = num_pages;
243 atipci_be->populated = 1;
244 return 0;
245}
246
247static int ati_pcigart_bind_ttm(struct drm_ttm_backend *backend,
248 struct drm_bo_mem_reg *bo_mem)
249{
250 struct ati_pcigart_ttm_backend *atipci_be =
251 container_of(backend, struct ati_pcigart_ttm_backend, backend);
252 off_t j;
253 int i;
254 struct drm_ati_pcigart_info *info = atipci_be->gart_info;
255 u32 *pci_gart;
256 dma_addr_t offset = bo_mem->mm_node->start;
257 dma_addr_t page_base;
258
259 pci_gart = info->addr;
260
261 j = offset;
262 while (j < (offset + atipci_be->num_pages)) {
263 if (gart_get_page_from_table(info, pci_gart + j))
264 return -EBUSY;
265 j++;
266 }
267
268 for (i = 0, j = offset; i < atipci_be->num_pages; i++, j++) {
269 struct page *cur_page = atipci_be->pages[i];
270 /* write value */
271 page_base = page_to_phys(cur_page);
272 gart_insert_page_into_table(info, page_base, pci_gart + j);
273 }
274
275 mb();
276
277 atipci_be->gart_flush_fn(atipci_be->dev);
278
279 atipci_be->bound = 1;
280 atipci_be->offset = offset;
281 /* need to traverse table and add entries */
282 DRM_DEBUG("\n");
283 return 0;
284}
285
286static int ati_pcigart_unbind_ttm(struct drm_ttm_backend *backend)
287{
288 struct ati_pcigart_ttm_backend *atipci_be =
289 container_of(backend, struct ati_pcigart_ttm_backend, backend);
290 struct drm_ati_pcigart_info *info = atipci_be->gart_info;
291 unsigned long offset = atipci_be->offset;
292 int i;
293 off_t j;
294 u32 *pci_gart = info->addr;
295
296 if (atipci_be->bound != 1)
297 return -EINVAL;
298
299 for (i = 0, j = offset; i < atipci_be->num_pages; i++, j++) {
300 *(pci_gart + j) = 0;
301 }
302 atipci_be->gart_flush_fn(atipci_be->dev);
303 atipci_be->bound = 0;
304 atipci_be->offset = 0;
305 return 0;
306}
307
308static void ati_pcigart_clear_ttm(struct drm_ttm_backend *backend)
309{
310 struct ati_pcigart_ttm_backend *atipci_be =
311 container_of(backend, struct ati_pcigart_ttm_backend, backend);
312
313 DRM_DEBUG("\n");
314 if (atipci_be->pages) {
315 backend->func->unbind(backend);
316 atipci_be->pages = NULL;
317
318 }
319 atipci_be->num_pages = 0;
320}
321
322static void ati_pcigart_destroy_ttm(struct drm_ttm_backend *backend)
323{
324 struct ati_pcigart_ttm_backend *atipci_be;
325 if (backend) {
326 DRM_DEBUG("\n");
327 atipci_be = container_of(backend, struct ati_pcigart_ttm_backend, backend);
328 if (atipci_be) {
329 if (atipci_be->pages) {
330 backend->func->clear(backend);
331 }
332 drm_ctl_free(atipci_be, sizeof(*atipci_be), DRM_MEM_TTM);
333 }
334 }
335}
336
337static struct drm_ttm_backend_func ati_pcigart_ttm_backend =
338{
339 .needs_ub_cache_adjust = ati_pcigart_needs_unbind_cache_adjust,
340 .populate = ati_pcigart_populate,
341 .clear = ati_pcigart_clear_ttm,
342 .bind = ati_pcigart_bind_ttm,
343 .unbind = ati_pcigart_unbind_ttm,
344 .destroy = ati_pcigart_destroy_ttm,
345};
346
347struct drm_ttm_backend *ati_pcigart_init_ttm(struct drm_device *dev, struct drm_ati_pcigart_info *info, void (*gart_flush_fn)(struct drm_device *dev))
348{
349 struct ati_pcigart_ttm_backend *atipci_be;
350
351 atipci_be = drm_ctl_calloc(1, sizeof (*atipci_be), DRM_MEM_TTM);
352 if (!atipci_be)
353 return NULL;
354
355 atipci_be->populated = 0;
356 atipci_be->backend.func = &ati_pcigart_ttm_backend;
357// atipci_be->backend.mem_type = DRM_BO_MEM_TT;
358 atipci_be->gart_info = info;
359 atipci_be->gart_flush_fn = gart_flush_fn;
360 atipci_be->dev = dev;
361
362 return &atipci_be->backend;
363}
364EXPORT_SYMBOL(ati_pcigart_init_ttm);