diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/agp/generic.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/agp/generic.c')
-rw-r--r-- | drivers/char/agp/generic.c | 1222 |
1 files changed, 1222 insertions, 0 deletions
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c new file mode 100644 index 000000000000..c321a924e38a --- /dev/null +++ b/drivers/char/agp/generic.c | |||
@@ -0,0 +1,1222 @@ | |||
1 | /* | ||
2 | * AGPGART driver. | ||
3 | * Copyright (C) 2004 Silicon Graphics, Inc. | ||
4 | * Copyright (C) 2002-2005 Dave Jones. | ||
5 | * Copyright (C) 1999 Jeff Hartmann. | ||
6 | * Copyright (C) 1999 Precision Insight, Inc. | ||
7 | * Copyright (C) 1999 Xi Graphics, Inc. | ||
8 | * | ||
9 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
10 | * copy of this software and associated documentation files (the "Software"), | ||
11 | * to deal in the Software without restriction, including without limitation | ||
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
13 | * and/or sell copies of the Software, and to permit persons to whom the | ||
14 | * Software is furnished to do so, subject to the following conditions: | ||
15 | * | ||
16 | * The above copyright notice and this permission notice shall be included | ||
17 | * in all copies or substantial portions of the Software. | ||
18 | * | ||
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
22 | * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, | ||
23 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
24 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | ||
25 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
26 | * | ||
27 | * TODO: | ||
28 | * - Allocate more than order 0 pages to avoid too much linear map splitting. | ||
29 | */ | ||
30 | #include <linux/config.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/pci.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/pagemap.h> | ||
35 | #include <linux/miscdevice.h> | ||
36 | #include <linux/pm.h> | ||
37 | #include <linux/agp_backend.h> | ||
38 | #include <linux/vmalloc.h> | ||
39 | #include <linux/dma-mapping.h> | ||
40 | #include <linux/mm.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/cacheflush.h> | ||
43 | #include <asm/pgtable.h> | ||
44 | #include "agp.h" | ||
45 | |||
46 | __u32 *agp_gatt_table; | ||
47 | int agp_memory_reserved; | ||
48 | |||
49 | /* | ||
50 | * Needed by the Nforce GART driver for the time being. Would be | ||
51 | * nice to do this some other way instead of needing this export. | ||
52 | */ | ||
53 | EXPORT_SYMBOL_GPL(agp_memory_reserved); | ||
54 | |||
55 | #if defined(CONFIG_X86) | ||
56 | int map_page_into_agp(struct page *page) | ||
57 | { | ||
58 | int i; | ||
59 | i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); | ||
60 | global_flush_tlb(); | ||
61 | return i; | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(map_page_into_agp); | ||
64 | |||
65 | int unmap_page_from_agp(struct page *page) | ||
66 | { | ||
67 | int i; | ||
68 | i = change_page_attr(page, 1, PAGE_KERNEL); | ||
69 | global_flush_tlb(); | ||
70 | return i; | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(unmap_page_from_agp); | ||
73 | #endif | ||
74 | |||
75 | /* | ||
76 | * Generic routines for handling agp_memory structures - | ||
77 | * They use the basic page allocation routines to do the brunt of the work. | ||
78 | */ | ||
79 | |||
80 | void agp_free_key(int key) | ||
81 | { | ||
82 | if (key < 0) | ||
83 | return; | ||
84 | |||
85 | if (key < MAXKEY) | ||
86 | clear_bit(key, agp_bridge->key_list); | ||
87 | } | ||
88 | EXPORT_SYMBOL(agp_free_key); | ||
89 | |||
90 | |||
91 | static int agp_get_key(void) | ||
92 | { | ||
93 | int bit; | ||
94 | |||
95 | bit = find_first_zero_bit(agp_bridge->key_list, MAXKEY); | ||
96 | if (bit < MAXKEY) { | ||
97 | set_bit(bit, agp_bridge->key_list); | ||
98 | return bit; | ||
99 | } | ||
100 | return -1; | ||
101 | } | ||
102 | |||
103 | |||
104 | struct agp_memory *agp_create_memory(int scratch_pages) | ||
105 | { | ||
106 | struct agp_memory *new; | ||
107 | |||
108 | new = kmalloc(sizeof(struct agp_memory), GFP_KERNEL); | ||
109 | |||
110 | if (new == NULL) | ||
111 | return NULL; | ||
112 | |||
113 | memset(new, 0, sizeof(struct agp_memory)); | ||
114 | new->key = agp_get_key(); | ||
115 | |||
116 | if (new->key < 0) { | ||
117 | kfree(new); | ||
118 | return NULL; | ||
119 | } | ||
120 | new->memory = vmalloc(PAGE_SIZE * scratch_pages); | ||
121 | |||
122 | if (new->memory == NULL) { | ||
123 | agp_free_key(new->key); | ||
124 | kfree(new); | ||
125 | return NULL; | ||
126 | } | ||
127 | new->num_scratch_pages = scratch_pages; | ||
128 | return new; | ||
129 | } | ||
130 | EXPORT_SYMBOL(agp_create_memory); | ||
131 | |||
132 | /** | ||
133 | * agp_free_memory - free memory associated with an agp_memory pointer. | ||
134 | * | ||
135 | * @curr: agp_memory pointer to be freed. | ||
136 | * | ||
137 | * It is the only function that can be called when the backend is not owned | ||
138 | * by the caller. (So it can free memory on client death.) | ||
139 | */ | ||
140 | void agp_free_memory(struct agp_memory *curr) | ||
141 | { | ||
142 | size_t i; | ||
143 | |||
144 | if (curr == NULL) | ||
145 | return; | ||
146 | |||
147 | if (curr->is_bound == TRUE) | ||
148 | agp_unbind_memory(curr); | ||
149 | |||
150 | if (curr->type != 0) { | ||
151 | curr->bridge->driver->free_by_type(curr); | ||
152 | return; | ||
153 | } | ||
154 | if (curr->page_count != 0) { | ||
155 | for (i = 0; i < curr->page_count; i++) { | ||
156 | curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i])); | ||
157 | } | ||
158 | } | ||
159 | agp_free_key(curr->key); | ||
160 | vfree(curr->memory); | ||
161 | kfree(curr); | ||
162 | } | ||
163 | EXPORT_SYMBOL(agp_free_memory); | ||
164 | |||
165 | #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) | ||
166 | |||
167 | /** | ||
168 | * agp_allocate_memory - allocate a group of pages of a certain type. | ||
169 | * | ||
170 | * @page_count: size_t argument of the number of pages | ||
171 | * @type: u32 argument of the type of memory to be allocated. | ||
172 | * | ||
173 | * Every agp bridge device will allow you to allocate AGP_NORMAL_MEMORY which | ||
174 | * maps to physical ram. Any other type is device dependent. | ||
175 | * | ||
176 | * It returns NULL whenever memory is unavailable. | ||
177 | */ | ||
178 | struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, | ||
179 | size_t page_count, u32 type) | ||
180 | { | ||
181 | int scratch_pages; | ||
182 | struct agp_memory *new; | ||
183 | size_t i; | ||
184 | |||
185 | if (!bridge) | ||
186 | return NULL; | ||
187 | |||
188 | if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp) | ||
189 | return NULL; | ||
190 | |||
191 | if (type != 0) { | ||
192 | new = bridge->driver->alloc_by_type(page_count, type); | ||
193 | if (new) | ||
194 | new->bridge = bridge; | ||
195 | return new; | ||
196 | } | ||
197 | |||
198 | scratch_pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE; | ||
199 | |||
200 | new = agp_create_memory(scratch_pages); | ||
201 | |||
202 | if (new == NULL) | ||
203 | return NULL; | ||
204 | |||
205 | for (i = 0; i < page_count; i++) { | ||
206 | void *addr = bridge->driver->agp_alloc_page(bridge); | ||
207 | |||
208 | if (addr == NULL) { | ||
209 | agp_free_memory(new); | ||
210 | return NULL; | ||
211 | } | ||
212 | new->memory[i] = virt_to_phys(addr); | ||
213 | new->page_count++; | ||
214 | } | ||
215 | new->bridge = bridge; | ||
216 | |||
217 | flush_agp_mappings(); | ||
218 | |||
219 | return new; | ||
220 | } | ||
221 | EXPORT_SYMBOL(agp_allocate_memory); | ||
222 | |||
223 | |||
224 | /* End - Generic routines for handling agp_memory structures */ | ||
225 | |||
226 | |||
227 | static int agp_return_size(void) | ||
228 | { | ||
229 | int current_size; | ||
230 | void *temp; | ||
231 | |||
232 | temp = agp_bridge->current_size; | ||
233 | |||
234 | switch (agp_bridge->driver->size_type) { | ||
235 | case U8_APER_SIZE: | ||
236 | current_size = A_SIZE_8(temp)->size; | ||
237 | break; | ||
238 | case U16_APER_SIZE: | ||
239 | current_size = A_SIZE_16(temp)->size; | ||
240 | break; | ||
241 | case U32_APER_SIZE: | ||
242 | current_size = A_SIZE_32(temp)->size; | ||
243 | break; | ||
244 | case LVL2_APER_SIZE: | ||
245 | current_size = A_SIZE_LVL2(temp)->size; | ||
246 | break; | ||
247 | case FIXED_APER_SIZE: | ||
248 | current_size = A_SIZE_FIX(temp)->size; | ||
249 | break; | ||
250 | default: | ||
251 | current_size = 0; | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | current_size -= (agp_memory_reserved / (1024*1024)); | ||
256 | if (current_size <0) | ||
257 | current_size = 0; | ||
258 | return current_size; | ||
259 | } | ||
260 | |||
261 | |||
262 | int agp_num_entries(void) | ||
263 | { | ||
264 | int num_entries; | ||
265 | void *temp; | ||
266 | |||
267 | temp = agp_bridge->current_size; | ||
268 | |||
269 | switch (agp_bridge->driver->size_type) { | ||
270 | case U8_APER_SIZE: | ||
271 | num_entries = A_SIZE_8(temp)->num_entries; | ||
272 | break; | ||
273 | case U16_APER_SIZE: | ||
274 | num_entries = A_SIZE_16(temp)->num_entries; | ||
275 | break; | ||
276 | case U32_APER_SIZE: | ||
277 | num_entries = A_SIZE_32(temp)->num_entries; | ||
278 | break; | ||
279 | case LVL2_APER_SIZE: | ||
280 | num_entries = A_SIZE_LVL2(temp)->num_entries; | ||
281 | break; | ||
282 | case FIXED_APER_SIZE: | ||
283 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
284 | break; | ||
285 | default: | ||
286 | num_entries = 0; | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | num_entries -= agp_memory_reserved>>PAGE_SHIFT; | ||
291 | if (num_entries<0) | ||
292 | num_entries = 0; | ||
293 | return num_entries; | ||
294 | } | ||
295 | EXPORT_SYMBOL_GPL(agp_num_entries); | ||
296 | |||
297 | |||
298 | static int check_bridge_mode(struct pci_dev *dev) | ||
299 | { | ||
300 | u32 agp3; | ||
301 | u8 cap_ptr; | ||
302 | |||
303 | cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); | ||
304 | pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3); | ||
305 | if (agp3 & AGPSTAT_MODE_3_0) | ||
306 | return 1; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * agp_copy_info - copy bridge state information | ||
313 | * | ||
314 | * @info: agp_kern_info pointer. The caller should insure that this pointer is valid. | ||
315 | * | ||
316 | * This function copies information about the agp bridge device and the state of | ||
317 | * the agp backend into an agp_kern_info pointer. | ||
318 | */ | ||
319 | int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info) | ||
320 | { | ||
321 | memset(info, 0, sizeof(struct agp_kern_info)); | ||
322 | if (!bridge) { | ||
323 | info->chipset = NOT_SUPPORTED; | ||
324 | return -EIO; | ||
325 | } | ||
326 | |||
327 | info->version.major = bridge->version->major; | ||
328 | info->version.minor = bridge->version->minor; | ||
329 | info->chipset = SUPPORTED; | ||
330 | info->device = bridge->dev; | ||
331 | if (check_bridge_mode(bridge->dev)) | ||
332 | info->mode = bridge->mode & ~AGP3_RESERVED_MASK; | ||
333 | else | ||
334 | info->mode = bridge->mode & ~AGP2_RESERVED_MASK; | ||
335 | info->mode = bridge->mode; | ||
336 | info->aper_base = bridge->gart_bus_addr; | ||
337 | info->aper_size = agp_return_size(); | ||
338 | info->max_memory = bridge->max_memory_agp; | ||
339 | info->current_memory = atomic_read(&bridge->current_memory_agp); | ||
340 | info->cant_use_aperture = bridge->driver->cant_use_aperture; | ||
341 | info->vm_ops = bridge->vm_ops; | ||
342 | info->page_mask = ~0UL; | ||
343 | return 0; | ||
344 | } | ||
345 | EXPORT_SYMBOL(agp_copy_info); | ||
346 | |||
347 | /* End - Routine to copy over information structure */ | ||
348 | |||
349 | /* | ||
350 | * Routines for handling swapping of agp_memory into the GATT - | ||
351 | * These routines take agp_memory and insert them into the GATT. | ||
352 | * They call device specific routines to actually write to the GATT. | ||
353 | */ | ||
354 | |||
355 | /** | ||
356 | * agp_bind_memory - Bind an agp_memory structure into the GATT. | ||
357 | * | ||
358 | * @curr: agp_memory pointer | ||
359 | * @pg_start: an offset into the graphics aperture translation table | ||
360 | * | ||
361 | * It returns -EINVAL if the pointer == NULL. | ||
362 | * It returns -EBUSY if the area of the table requested is already in use. | ||
363 | */ | ||
364 | int agp_bind_memory(struct agp_memory *curr, off_t pg_start) | ||
365 | { | ||
366 | int ret_val; | ||
367 | |||
368 | if (curr == NULL) | ||
369 | return -EINVAL; | ||
370 | |||
371 | if (curr->is_bound == TRUE) { | ||
372 | printk (KERN_INFO PFX "memory %p is already bound!\n", curr); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | if (curr->is_flushed == FALSE) { | ||
376 | curr->bridge->driver->cache_flush(); | ||
377 | curr->is_flushed = TRUE; | ||
378 | } | ||
379 | ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type); | ||
380 | |||
381 | if (ret_val != 0) | ||
382 | return ret_val; | ||
383 | |||
384 | curr->is_bound = TRUE; | ||
385 | curr->pg_start = pg_start; | ||
386 | return 0; | ||
387 | } | ||
388 | EXPORT_SYMBOL(agp_bind_memory); | ||
389 | |||
390 | |||
391 | /** | ||
392 | * agp_unbind_memory - Removes an agp_memory structure from the GATT | ||
393 | * | ||
394 | * @curr: agp_memory pointer to be removed from the GATT. | ||
395 | * | ||
396 | * It returns -EINVAL if this piece of agp_memory is not currently bound to | ||
397 | * the graphics aperture translation table or if the agp_memory pointer == NULL | ||
398 | */ | ||
399 | int agp_unbind_memory(struct agp_memory *curr) | ||
400 | { | ||
401 | int ret_val; | ||
402 | |||
403 | if (curr == NULL) | ||
404 | return -EINVAL; | ||
405 | |||
406 | if (curr->is_bound != TRUE) { | ||
407 | printk (KERN_INFO PFX "memory %p was not bound!\n", curr); | ||
408 | return -EINVAL; | ||
409 | } | ||
410 | |||
411 | ret_val = curr->bridge->driver->remove_memory(curr, curr->pg_start, curr->type); | ||
412 | |||
413 | if (ret_val != 0) | ||
414 | return ret_val; | ||
415 | |||
416 | curr->is_bound = FALSE; | ||
417 | curr->pg_start = 0; | ||
418 | return 0; | ||
419 | } | ||
420 | EXPORT_SYMBOL(agp_unbind_memory); | ||
421 | |||
422 | /* End - Routines for handling swapping of agp_memory into the GATT */ | ||
423 | |||
424 | |||
425 | /* Generic Agp routines - Start */ | ||
426 | static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat) | ||
427 | { | ||
428 | u32 tmp; | ||
429 | |||
430 | if (*requested_mode & AGP2_RESERVED_MASK) { | ||
431 | printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); | ||
432 | *requested_mode &= ~AGP2_RESERVED_MASK; | ||
433 | } | ||
434 | |||
435 | /* Check the speed bits make sense. Only one should be set. */ | ||
436 | tmp = *requested_mode & 7; | ||
437 | switch (tmp) { | ||
438 | case 0: | ||
439 | printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm); | ||
440 | *requested_mode |= AGPSTAT2_1X; | ||
441 | break; | ||
442 | case 1: | ||
443 | case 2: | ||
444 | break; | ||
445 | case 3: | ||
446 | *requested_mode &= ~(AGPSTAT2_1X); /* rate=2 */ | ||
447 | break; | ||
448 | case 4: | ||
449 | break; | ||
450 | case 5: | ||
451 | case 6: | ||
452 | case 7: | ||
453 | *requested_mode &= ~(AGPSTAT2_1X|AGPSTAT2_2X); /* rate=4*/ | ||
454 | break; | ||
455 | } | ||
456 | |||
457 | /* disable SBA if it's not supported */ | ||
458 | if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA))) | ||
459 | *bridge_agpstat &= ~AGPSTAT_SBA; | ||
460 | |||
461 | /* Set rate */ | ||
462 | if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X))) | ||
463 | *bridge_agpstat &= ~AGPSTAT2_4X; | ||
464 | |||
465 | if (!((*bridge_agpstat & AGPSTAT2_2X) && (*vga_agpstat & AGPSTAT2_2X) && (*requested_mode & AGPSTAT2_2X))) | ||
466 | *bridge_agpstat &= ~AGPSTAT2_2X; | ||
467 | |||
468 | if (!((*bridge_agpstat & AGPSTAT2_1X) && (*vga_agpstat & AGPSTAT2_1X) && (*requested_mode & AGPSTAT2_1X))) | ||
469 | *bridge_agpstat &= ~AGPSTAT2_1X; | ||
470 | |||
471 | /* Now we know what mode it should be, clear out the unwanted bits. */ | ||
472 | if (*bridge_agpstat & AGPSTAT2_4X) | ||
473 | *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */ | ||
474 | |||
475 | if (*bridge_agpstat & AGPSTAT2_2X) | ||
476 | *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */ | ||
477 | |||
478 | if (*bridge_agpstat & AGPSTAT2_1X) | ||
479 | *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1X */ | ||
480 | |||
481 | /* Apply any errata. */ | ||
482 | if (agp_bridge->flags & AGP_ERRATA_FASTWRITES) | ||
483 | *bridge_agpstat &= ~AGPSTAT_FW; | ||
484 | |||
485 | if (agp_bridge->flags & AGP_ERRATA_SBA) | ||
486 | *bridge_agpstat &= ~AGPSTAT_SBA; | ||
487 | |||
488 | if (agp_bridge->flags & AGP_ERRATA_1X) { | ||
489 | *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); | ||
490 | *bridge_agpstat |= AGPSTAT2_1X; | ||
491 | } | ||
492 | |||
493 | /* If we've dropped down to 1X, disable fast writes. */ | ||
494 | if (*bridge_agpstat & AGPSTAT2_1X) | ||
495 | *bridge_agpstat &= ~AGPSTAT_FW; | ||
496 | } | ||
497 | |||
498 | /* | ||
499 | * requested_mode = Mode requested by (typically) X. | ||
500 | * bridge_agpstat = PCI_AGP_STATUS from agp bridge. | ||
501 | * vga_agpstat = PCI_AGP_STATUS from graphic card. | ||
502 | */ | ||
503 | static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat) | ||
504 | { | ||
505 | u32 origbridge=*bridge_agpstat, origvga=*vga_agpstat; | ||
506 | u32 tmp; | ||
507 | |||
508 | if (*requested_mode & AGP3_RESERVED_MASK) { | ||
509 | printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode); | ||
510 | *requested_mode &= ~AGP3_RESERVED_MASK; | ||
511 | } | ||
512 | |||
513 | /* Check the speed bits make sense. */ | ||
514 | tmp = *requested_mode & 7; | ||
515 | if (tmp == 0) { | ||
516 | printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm); | ||
517 | *requested_mode |= AGPSTAT3_4X; | ||
518 | } | ||
519 | if (tmp >= 3) { | ||
520 | printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4); | ||
521 | *requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X; | ||
522 | } | ||
523 | |||
524 | /* ARQSZ - Set the value to the maximum one. | ||
525 | * Don't allow the mode register to override values. */ | ||
526 | *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) | | ||
527 | max_t(u32,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ))); | ||
528 | |||
529 | /* Calibration cycle. | ||
530 | * Don't allow the mode register to override values. */ | ||
531 | *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_CAL_MASK) | | ||
532 | min_t(u32,(*bridge_agpstat & AGPSTAT_CAL_MASK),(*vga_agpstat & AGPSTAT_CAL_MASK))); | ||
533 | |||
534 | /* SBA *must* be supported for AGP v3 */ | ||
535 | *bridge_agpstat |= AGPSTAT_SBA; | ||
536 | |||
537 | /* | ||
538 | * Set speed. | ||
539 | * Check for invalid speeds. This can happen when applications | ||
540 | * written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware | ||
541 | */ | ||
542 | if (*requested_mode & AGPSTAT_MODE_3_0) { | ||
543 | /* | ||
544 | * Caller hasn't a clue what it is doing. Bridge is in 3.0 mode, | ||
545 | * have been passed a 3.0 mode, but with 2.x speed bits set. | ||
546 | * AGP2.x 4x -> AGP3.0 4x. | ||
547 | */ | ||
548 | if (*requested_mode & AGPSTAT2_4X) { | ||
549 | printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n", | ||
550 | current->comm, *requested_mode); | ||
551 | *requested_mode &= ~AGPSTAT2_4X; | ||
552 | *requested_mode |= AGPSTAT3_4X; | ||
553 | } | ||
554 | } else { | ||
555 | /* | ||
556 | * The caller doesn't know what they are doing. We are in 3.0 mode, | ||
557 | * but have been passed an AGP 2.x mode. | ||
558 | * Convert AGP 1x,2x,4x -> AGP 3.0 4x. | ||
559 | */ | ||
560 | printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n", | ||
561 | current->comm, *requested_mode); | ||
562 | *requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X); | ||
563 | *requested_mode |= AGPSTAT3_4X; | ||
564 | } | ||
565 | |||
566 | if (*requested_mode & AGPSTAT3_8X) { | ||
567 | if (!(*bridge_agpstat & AGPSTAT3_8X)) { | ||
568 | *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); | ||
569 | *bridge_agpstat |= AGPSTAT3_4X; | ||
570 | printk ("%s requested AGPx8 but bridge not capable.\n", current->comm); | ||
571 | return; | ||
572 | } | ||
573 | if (!(*vga_agpstat & AGPSTAT3_8X)) { | ||
574 | *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); | ||
575 | *bridge_agpstat |= AGPSTAT3_4X; | ||
576 | printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm); | ||
577 | return; | ||
578 | } | ||
579 | /* All set, bridge & device can do AGP x8*/ | ||
580 | *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); | ||
581 | goto done; | ||
582 | |||
583 | } else { | ||
584 | |||
585 | /* | ||
586 | * If we didn't specify AGPx8, we can only do x4. | ||
587 | * If the hardware can't do x4, we're up shit creek, and never | ||
588 | * should have got this far. | ||
589 | */ | ||
590 | *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); | ||
591 | if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X)) | ||
592 | *bridge_agpstat |= AGPSTAT3_4X; | ||
593 | else { | ||
594 | printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. " | ||
595 | "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n", | ||
596 | origbridge, origvga, *bridge_agpstat, *vga_agpstat); | ||
597 | if (!(*bridge_agpstat & AGPSTAT3_4X)) | ||
598 | printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n"); | ||
599 | if (!(*vga_agpstat & AGPSTAT3_4X)) | ||
600 | printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n"); | ||
601 | return; | ||
602 | } | ||
603 | } | ||
604 | |||
605 | done: | ||
606 | /* Apply any errata. */ | ||
607 | if (agp_bridge->flags & AGP_ERRATA_FASTWRITES) | ||
608 | *bridge_agpstat &= ~AGPSTAT_FW; | ||
609 | |||
610 | if (agp_bridge->flags & AGP_ERRATA_SBA) | ||
611 | *bridge_agpstat &= ~AGPSTAT_SBA; | ||
612 | |||
613 | if (agp_bridge->flags & AGP_ERRATA_1X) { | ||
614 | *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); | ||
615 | *bridge_agpstat |= AGPSTAT2_1X; | ||
616 | } | ||
617 | } | ||
618 | |||
619 | |||
620 | /** | ||
621 | * agp_collect_device_status - determine correct agp_cmd from various agp_stat's | ||
622 | * @bridge: an agp_bridge_data struct allocated for the AGP host bridge. | ||
623 | * @requested_mode: requested agp_stat from userspace (Typically from X) | ||
624 | * @bridge_agpstat: current agp_stat from AGP bridge. | ||
625 | * | ||
626 | * This function will hunt for an AGP graphics card, and try to match | ||
627 | * the requested mode to the capabilities of both the bridge and the card. | ||
628 | */ | ||
629 | u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode, u32 bridge_agpstat) | ||
630 | { | ||
631 | struct pci_dev *device = NULL; | ||
632 | u32 vga_agpstat; | ||
633 | u8 cap_ptr; | ||
634 | |||
635 | for (;;) { | ||
636 | device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device); | ||
637 | if (!device) { | ||
638 | printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n"); | ||
639 | return 0; | ||
640 | } | ||
641 | cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); | ||
642 | if (cap_ptr) | ||
643 | break; | ||
644 | } | ||
645 | |||
646 | /* | ||
647 | * Ok, here we have a AGP device. Disable impossible | ||
648 | * settings, and adjust the readqueue to the minimum. | ||
649 | */ | ||
650 | pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &vga_agpstat); | ||
651 | |||
652 | /* adjust RQ depth */ | ||
653 | bridge_agpstat = ((bridge_agpstat & ~AGPSTAT_RQ_DEPTH) | | ||
654 | min_t(u32, (requested_mode & AGPSTAT_RQ_DEPTH), | ||
655 | min_t(u32, (bridge_agpstat & AGPSTAT_RQ_DEPTH), (vga_agpstat & AGPSTAT_RQ_DEPTH)))); | ||
656 | |||
657 | /* disable FW if it's not supported */ | ||
658 | if (!((bridge_agpstat & AGPSTAT_FW) && | ||
659 | (vga_agpstat & AGPSTAT_FW) && | ||
660 | (requested_mode & AGPSTAT_FW))) | ||
661 | bridge_agpstat &= ~AGPSTAT_FW; | ||
662 | |||
663 | /* Check to see if we are operating in 3.0 mode */ | ||
664 | if (check_bridge_mode(agp_bridge->dev)) | ||
665 | agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); | ||
666 | else | ||
667 | agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); | ||
668 | |||
669 | pci_dev_put(device); | ||
670 | return bridge_agpstat; | ||
671 | } | ||
672 | EXPORT_SYMBOL(agp_collect_device_status); | ||
673 | |||
674 | |||
675 | void agp_device_command(u32 bridge_agpstat, int agp_v3) | ||
676 | { | ||
677 | struct pci_dev *device = NULL; | ||
678 | int mode; | ||
679 | |||
680 | mode = bridge_agpstat & 0x7; | ||
681 | if (agp_v3) | ||
682 | mode *= 4; | ||
683 | |||
684 | for_each_pci_dev(device) { | ||
685 | u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP); | ||
686 | if (!agp) | ||
687 | continue; | ||
688 | |||
689 | printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n", | ||
690 | agp_v3 ? 3 : 2, pci_name(device), mode); | ||
691 | pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat); | ||
692 | } | ||
693 | } | ||
694 | EXPORT_SYMBOL(agp_device_command); | ||
695 | |||
696 | |||
697 | void get_agp_version(struct agp_bridge_data *bridge) | ||
698 | { | ||
699 | u32 ncapid; | ||
700 | |||
701 | /* Exit early if already set by errata workarounds. */ | ||
702 | if (bridge->major_version != 0) | ||
703 | return; | ||
704 | |||
705 | pci_read_config_dword(bridge->dev, bridge->capndx, &ncapid); | ||
706 | bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; | ||
707 | bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf; | ||
708 | } | ||
709 | EXPORT_SYMBOL(get_agp_version); | ||
710 | |||
711 | |||
712 | void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) | ||
713 | { | ||
714 | u32 bridge_agpstat, temp; | ||
715 | |||
716 | get_agp_version(agp_bridge); | ||
717 | |||
718 | printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", | ||
719 | agp_bridge->major_version, | ||
720 | agp_bridge->minor_version, | ||
721 | pci_name(agp_bridge->dev)); | ||
722 | |||
723 | pci_read_config_dword(agp_bridge->dev, | ||
724 | agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat); | ||
725 | |||
726 | bridge_agpstat = agp_collect_device_status(agp_bridge, requested_mode, bridge_agpstat); | ||
727 | if (bridge_agpstat == 0) | ||
728 | /* Something bad happened. FIXME: Return error code? */ | ||
729 | return; | ||
730 | |||
731 | bridge_agpstat |= AGPSTAT_AGP_ENABLE; | ||
732 | |||
733 | /* Do AGP version specific frobbing. */ | ||
734 | if (bridge->major_version >= 3) { | ||
735 | if (check_bridge_mode(bridge->dev)) { | ||
736 | /* If we have 3.5, we can do the isoch stuff. */ | ||
737 | if (bridge->minor_version >= 5) | ||
738 | agp_3_5_enable(bridge); | ||
739 | agp_device_command(bridge_agpstat, TRUE); | ||
740 | return; | ||
741 | } else { | ||
742 | /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/ | ||
743 | bridge_agpstat &= ~(7<<10) ; | ||
744 | pci_read_config_dword(bridge->dev, | ||
745 | bridge->capndx+AGPCTRL, &temp); | ||
746 | temp |= (1<<9); | ||
747 | pci_write_config_dword(bridge->dev, | ||
748 | bridge->capndx+AGPCTRL, temp); | ||
749 | |||
750 | printk (KERN_INFO PFX "Device is in legacy mode," | ||
751 | " falling back to 2.x\n"); | ||
752 | } | ||
753 | } | ||
754 | |||
755 | /* AGP v<3 */ | ||
756 | agp_device_command(bridge_agpstat, FALSE); | ||
757 | } | ||
758 | EXPORT_SYMBOL(agp_generic_enable); | ||
759 | |||
760 | |||
761 | int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | ||
762 | { | ||
763 | char *table; | ||
764 | char *table_end; | ||
765 | int size; | ||
766 | int page_order; | ||
767 | int num_entries; | ||
768 | int i; | ||
769 | void *temp; | ||
770 | struct page *page; | ||
771 | |||
772 | /* The generic routines can't handle 2 level gatt's */ | ||
773 | if (bridge->driver->size_type == LVL2_APER_SIZE) | ||
774 | return -EINVAL; | ||
775 | |||
776 | table = NULL; | ||
777 | i = bridge->aperture_size_idx; | ||
778 | temp = bridge->current_size; | ||
779 | size = page_order = num_entries = 0; | ||
780 | |||
781 | if (bridge->driver->size_type != FIXED_APER_SIZE) { | ||
782 | do { | ||
783 | switch (bridge->driver->size_type) { | ||
784 | case U8_APER_SIZE: | ||
785 | size = A_SIZE_8(temp)->size; | ||
786 | page_order = | ||
787 | A_SIZE_8(temp)->page_order; | ||
788 | num_entries = | ||
789 | A_SIZE_8(temp)->num_entries; | ||
790 | break; | ||
791 | case U16_APER_SIZE: | ||
792 | size = A_SIZE_16(temp)->size; | ||
793 | page_order = A_SIZE_16(temp)->page_order; | ||
794 | num_entries = A_SIZE_16(temp)->num_entries; | ||
795 | break; | ||
796 | case U32_APER_SIZE: | ||
797 | size = A_SIZE_32(temp)->size; | ||
798 | page_order = A_SIZE_32(temp)->page_order; | ||
799 | num_entries = A_SIZE_32(temp)->num_entries; | ||
800 | break; | ||
801 | /* This case will never really happen. */ | ||
802 | case FIXED_APER_SIZE: | ||
803 | case LVL2_APER_SIZE: | ||
804 | default: | ||
805 | size = page_order = num_entries = 0; | ||
806 | break; | ||
807 | } | ||
808 | |||
809 | table = (char *) __get_free_pages(GFP_KERNEL, | ||
810 | page_order); | ||
811 | |||
812 | if (table == NULL) { | ||
813 | i++; | ||
814 | switch (bridge->driver->size_type) { | ||
815 | case U8_APER_SIZE: | ||
816 | bridge->current_size = A_IDX8(bridge); | ||
817 | break; | ||
818 | case U16_APER_SIZE: | ||
819 | bridge->current_size = A_IDX16(bridge); | ||
820 | break; | ||
821 | case U32_APER_SIZE: | ||
822 | bridge->current_size = A_IDX32(bridge); | ||
823 | break; | ||
824 | /* This case will never really happen. */ | ||
825 | case FIXED_APER_SIZE: | ||
826 | case LVL2_APER_SIZE: | ||
827 | default: | ||
828 | bridge->current_size = | ||
829 | bridge->current_size; | ||
830 | break; | ||
831 | } | ||
832 | temp = bridge->current_size; | ||
833 | } else { | ||
834 | bridge->aperture_size_idx = i; | ||
835 | } | ||
836 | } while (!table && (i < bridge->driver->num_aperture_sizes)); | ||
837 | } else { | ||
838 | size = ((struct aper_size_info_fixed *) temp)->size; | ||
839 | page_order = ((struct aper_size_info_fixed *) temp)->page_order; | ||
840 | num_entries = ((struct aper_size_info_fixed *) temp)->num_entries; | ||
841 | table = (char *) __get_free_pages(GFP_KERNEL, page_order); | ||
842 | } | ||
843 | |||
844 | if (table == NULL) | ||
845 | return -ENOMEM; | ||
846 | |||
847 | table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); | ||
848 | |||
849 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) | ||
850 | SetPageReserved(page); | ||
851 | |||
852 | bridge->gatt_table_real = (u32 *) table; | ||
853 | agp_gatt_table = (void *)table; | ||
854 | |||
855 | bridge->driver->cache_flush(); | ||
856 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), | ||
857 | (PAGE_SIZE * (1 << page_order))); | ||
858 | bridge->driver->cache_flush(); | ||
859 | |||
860 | if (bridge->gatt_table == NULL) { | ||
861 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) | ||
862 | ClearPageReserved(page); | ||
863 | |||
864 | free_pages((unsigned long) table, page_order); | ||
865 | |||
866 | return -ENOMEM; | ||
867 | } | ||
868 | bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real); | ||
869 | |||
870 | /* AK: bogus, should encode addresses > 4GB */ | ||
871 | for (i = 0; i < num_entries; i++) { | ||
872 | writel(bridge->scratch_page, bridge->gatt_table+i); | ||
873 | readl(bridge->gatt_table+i); /* PCI Posting. */ | ||
874 | } | ||
875 | |||
876 | return 0; | ||
877 | } | ||
878 | EXPORT_SYMBOL(agp_generic_create_gatt_table); | ||
879 | |||
880 | int agp_generic_free_gatt_table(struct agp_bridge_data *bridge) | ||
881 | { | ||
882 | int page_order; | ||
883 | char *table, *table_end; | ||
884 | void *temp; | ||
885 | struct page *page; | ||
886 | |||
887 | temp = bridge->current_size; | ||
888 | |||
889 | switch (bridge->driver->size_type) { | ||
890 | case U8_APER_SIZE: | ||
891 | page_order = A_SIZE_8(temp)->page_order; | ||
892 | break; | ||
893 | case U16_APER_SIZE: | ||
894 | page_order = A_SIZE_16(temp)->page_order; | ||
895 | break; | ||
896 | case U32_APER_SIZE: | ||
897 | page_order = A_SIZE_32(temp)->page_order; | ||
898 | break; | ||
899 | case FIXED_APER_SIZE: | ||
900 | page_order = A_SIZE_FIX(temp)->page_order; | ||
901 | break; | ||
902 | case LVL2_APER_SIZE: | ||
903 | /* The generic routines can't deal with 2 level gatt's */ | ||
904 | return -EINVAL; | ||
905 | break; | ||
906 | default: | ||
907 | page_order = 0; | ||
908 | break; | ||
909 | } | ||
910 | |||
911 | /* Do not worry about freeing memory, because if this is | ||
912 | * called, then all agp memory is deallocated and removed | ||
913 | * from the table. */ | ||
914 | |||
915 | iounmap(bridge->gatt_table); | ||
916 | table = (char *) bridge->gatt_table_real; | ||
917 | table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); | ||
918 | |||
919 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) | ||
920 | ClearPageReserved(page); | ||
921 | |||
922 | free_pages((unsigned long) bridge->gatt_table_real, page_order); | ||
923 | |||
924 | agp_gatt_table = NULL; | ||
925 | bridge->gatt_table = NULL; | ||
926 | bridge->gatt_table_real = NULL; | ||
927 | bridge->gatt_bus_addr = 0; | ||
928 | |||
929 | return 0; | ||
930 | } | ||
931 | EXPORT_SYMBOL(agp_generic_free_gatt_table); | ||
932 | |||
933 | |||
934 | int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) | ||
935 | { | ||
936 | int num_entries; | ||
937 | size_t i; | ||
938 | off_t j; | ||
939 | void *temp; | ||
940 | struct agp_bridge_data *bridge; | ||
941 | |||
942 | bridge = mem->bridge; | ||
943 | if (!bridge) | ||
944 | return -EINVAL; | ||
945 | |||
946 | temp = bridge->current_size; | ||
947 | |||
948 | switch (bridge->driver->size_type) { | ||
949 | case U8_APER_SIZE: | ||
950 | num_entries = A_SIZE_8(temp)->num_entries; | ||
951 | break; | ||
952 | case U16_APER_SIZE: | ||
953 | num_entries = A_SIZE_16(temp)->num_entries; | ||
954 | break; | ||
955 | case U32_APER_SIZE: | ||
956 | num_entries = A_SIZE_32(temp)->num_entries; | ||
957 | break; | ||
958 | case FIXED_APER_SIZE: | ||
959 | num_entries = A_SIZE_FIX(temp)->num_entries; | ||
960 | break; | ||
961 | case LVL2_APER_SIZE: | ||
962 | /* The generic routines can't deal with 2 level gatt's */ | ||
963 | return -EINVAL; | ||
964 | break; | ||
965 | default: | ||
966 | num_entries = 0; | ||
967 | break; | ||
968 | } | ||
969 | |||
970 | num_entries -= agp_memory_reserved/PAGE_SIZE; | ||
971 | if (num_entries < 0) num_entries = 0; | ||
972 | |||
973 | if (type != 0 || mem->type != 0) { | ||
974 | /* The generic routines know nothing of memory types */ | ||
975 | return -EINVAL; | ||
976 | } | ||
977 | |||
978 | /* AK: could wrap */ | ||
979 | if ((pg_start + mem->page_count) > num_entries) | ||
980 | return -EINVAL; | ||
981 | |||
982 | j = pg_start; | ||
983 | |||
984 | while (j < (pg_start + mem->page_count)) { | ||
985 | if (!PGE_EMPTY(bridge, readl(bridge->gatt_table+j))) | ||
986 | return -EBUSY; | ||
987 | j++; | ||
988 | } | ||
989 | |||
990 | if (mem->is_flushed == FALSE) { | ||
991 | bridge->driver->cache_flush(); | ||
992 | mem->is_flushed = TRUE; | ||
993 | } | ||
994 | |||
995 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | ||
996 | writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); | ||
997 | readl(bridge->gatt_table+j); /* PCI Posting. */ | ||
998 | } | ||
999 | |||
1000 | bridge->driver->tlb_flush(mem); | ||
1001 | return 0; | ||
1002 | } | ||
1003 | EXPORT_SYMBOL(agp_generic_insert_memory); | ||
1004 | |||
1005 | |||
1006 | int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | ||
1007 | { | ||
1008 | size_t i; | ||
1009 | struct agp_bridge_data *bridge; | ||
1010 | |||
1011 | bridge = mem->bridge; | ||
1012 | if (!bridge) | ||
1013 | return -EINVAL; | ||
1014 | |||
1015 | if (type != 0 || mem->type != 0) { | ||
1016 | /* The generic routines know nothing of memory types */ | ||
1017 | return -EINVAL; | ||
1018 | } | ||
1019 | |||
1020 | /* AK: bogus, should encode addresses > 4GB */ | ||
1021 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | ||
1022 | writel(bridge->scratch_page, bridge->gatt_table+i); | ||
1023 | readl(bridge->gatt_table+i); /* PCI Posting. */ | ||
1024 | } | ||
1025 | |||
1026 | global_cache_flush(); | ||
1027 | bridge->driver->tlb_flush(mem); | ||
1028 | return 0; | ||
1029 | } | ||
1030 | EXPORT_SYMBOL(agp_generic_remove_memory); | ||
1031 | |||
1032 | |||
1033 | struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type) | ||
1034 | { | ||
1035 | return NULL; | ||
1036 | } | ||
1037 | EXPORT_SYMBOL(agp_generic_alloc_by_type); | ||
1038 | |||
1039 | |||
1040 | void agp_generic_free_by_type(struct agp_memory *curr) | ||
1041 | { | ||
1042 | vfree(curr->memory); | ||
1043 | agp_free_key(curr->key); | ||
1044 | kfree(curr); | ||
1045 | } | ||
1046 | EXPORT_SYMBOL(agp_generic_free_by_type); | ||
1047 | |||
1048 | |||
1049 | /* | ||
1050 | * Basic Page Allocation Routines - | ||
1051 | * These routines handle page allocation and by default they reserve the allocated | ||
1052 | * memory. They also handle incrementing the current_memory_agp value, Which is checked | ||
1053 | * against a maximum value. | ||
1054 | */ | ||
1055 | |||
1056 | void *agp_generic_alloc_page(struct agp_bridge_data *bridge) | ||
1057 | { | ||
1058 | struct page * page; | ||
1059 | |||
1060 | page = alloc_page(GFP_KERNEL); | ||
1061 | if (page == NULL) | ||
1062 | return NULL; | ||
1063 | |||
1064 | map_page_into_agp(page); | ||
1065 | |||
1066 | get_page(page); | ||
1067 | SetPageLocked(page); | ||
1068 | atomic_inc(&agp_bridge->current_memory_agp); | ||
1069 | return page_address(page); | ||
1070 | } | ||
1071 | EXPORT_SYMBOL(agp_generic_alloc_page); | ||
1072 | |||
1073 | |||
1074 | void agp_generic_destroy_page(void *addr) | ||
1075 | { | ||
1076 | struct page *page; | ||
1077 | |||
1078 | if (addr == NULL) | ||
1079 | return; | ||
1080 | |||
1081 | page = virt_to_page(addr); | ||
1082 | unmap_page_from_agp(page); | ||
1083 | put_page(page); | ||
1084 | unlock_page(page); | ||
1085 | free_page((unsigned long)addr); | ||
1086 | atomic_dec(&agp_bridge->current_memory_agp); | ||
1087 | } | ||
1088 | EXPORT_SYMBOL(agp_generic_destroy_page); | ||
1089 | |||
1090 | /* End Basic Page Allocation Routines */ | ||
1091 | |||
1092 | |||
1093 | /** | ||
1094 | * agp_enable - initialise the agp point-to-point connection. | ||
1095 | * | ||
1096 | * @mode: agp mode register value to configure with. | ||
1097 | */ | ||
1098 | void agp_enable(struct agp_bridge_data *bridge, u32 mode) | ||
1099 | { | ||
1100 | if (!bridge) | ||
1101 | return; | ||
1102 | bridge->driver->agp_enable(bridge, mode); | ||
1103 | } | ||
1104 | EXPORT_SYMBOL(agp_enable); | ||
1105 | |||
1106 | /* When we remove the global variable agp_bridge from all drivers | ||
1107 | * then agp_alloc_bridge and agp_generic_find_bridge need to be updated | ||
1108 | */ | ||
1109 | |||
1110 | struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev) | ||
1111 | { | ||
1112 | if (list_empty(&agp_bridges)) | ||
1113 | return NULL; | ||
1114 | |||
1115 | return agp_bridge; | ||
1116 | } | ||
1117 | |||
1118 | static void ipi_handler(void *null) | ||
1119 | { | ||
1120 | flush_agp_cache(); | ||
1121 | } | ||
1122 | |||
1123 | void global_cache_flush(void) | ||
1124 | { | ||
1125 | if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0) | ||
1126 | panic(PFX "timed out waiting for the other CPUs!\n"); | ||
1127 | } | ||
1128 | EXPORT_SYMBOL(global_cache_flush); | ||
1129 | |||
1130 | unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge, | ||
1131 | unsigned long addr, int type) | ||
1132 | { | ||
1133 | /* memory type is ignored in the generic routine */ | ||
1134 | if (bridge->driver->masks) | ||
1135 | return addr | bridge->driver->masks[0].mask; | ||
1136 | else | ||
1137 | return addr; | ||
1138 | } | ||
1139 | EXPORT_SYMBOL(agp_generic_mask_memory); | ||
1140 | |||
1141 | /* | ||
1142 | * These functions are implemented according to the AGPv3 spec, | ||
1143 | * which covers implementation details that had previously been | ||
1144 | * left open. | ||
1145 | */ | ||
1146 | |||
1147 | int agp3_generic_fetch_size(void) | ||
1148 | { | ||
1149 | u16 temp_size; | ||
1150 | int i; | ||
1151 | struct aper_size_info_16 *values; | ||
1152 | |||
1153 | pci_read_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, &temp_size); | ||
1154 | values = A_SIZE_16(agp_bridge->driver->aperture_sizes); | ||
1155 | |||
1156 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { | ||
1157 | if (temp_size == values[i].size_value) { | ||
1158 | agp_bridge->previous_size = | ||
1159 | agp_bridge->current_size = (void *) (values + i); | ||
1160 | |||
1161 | agp_bridge->aperture_size_idx = i; | ||
1162 | return values[i].size; | ||
1163 | } | ||
1164 | } | ||
1165 | return 0; | ||
1166 | } | ||
1167 | EXPORT_SYMBOL(agp3_generic_fetch_size); | ||
1168 | |||
1169 | void agp3_generic_tlbflush(struct agp_memory *mem) | ||
1170 | { | ||
1171 | u32 ctrl; | ||
1172 | pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &ctrl); | ||
1173 | pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl & ~AGPCTRL_GTLBEN); | ||
1174 | pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl); | ||
1175 | } | ||
1176 | EXPORT_SYMBOL(agp3_generic_tlbflush); | ||
1177 | |||
1178 | int agp3_generic_configure(void) | ||
1179 | { | ||
1180 | u32 temp; | ||
1181 | struct aper_size_info_16 *current_size; | ||
1182 | |||
1183 | current_size = A_SIZE_16(agp_bridge->current_size); | ||
1184 | |||
1185 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
1186 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
1187 | |||
1188 | /* set aperture size */ | ||
1189 | pci_write_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, current_size->size_value); | ||
1190 | /* set gart pointer */ | ||
1191 | pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPGARTLO, agp_bridge->gatt_bus_addr); | ||
1192 | /* enable aperture and GTLB */ | ||
1193 | pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp); | ||
1194 | pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp | AGPCTRL_APERENB | AGPCTRL_GTLBEN); | ||
1195 | return 0; | ||
1196 | } | ||
1197 | EXPORT_SYMBOL(agp3_generic_configure); | ||
1198 | |||
1199 | void agp3_generic_cleanup(void) | ||
1200 | { | ||
1201 | u32 ctrl; | ||
1202 | pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &ctrl); | ||
1203 | pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl & ~AGPCTRL_APERENB); | ||
1204 | } | ||
1205 | EXPORT_SYMBOL(agp3_generic_cleanup); | ||
1206 | |||
1207 | struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] = | ||
1208 | { | ||
1209 | {4096, 1048576, 10,0x000}, | ||
1210 | {2048, 524288, 9, 0x800}, | ||
1211 | {1024, 262144, 8, 0xc00}, | ||
1212 | { 512, 131072, 7, 0xe00}, | ||
1213 | { 256, 65536, 6, 0xf00}, | ||
1214 | { 128, 32768, 5, 0xf20}, | ||
1215 | { 64, 16384, 4, 0xf30}, | ||
1216 | { 32, 8192, 3, 0xf38}, | ||
1217 | { 16, 4096, 2, 0xf3c}, | ||
1218 | { 8, 2048, 1, 0xf3e}, | ||
1219 | { 4, 1024, 0, 0xf3f} | ||
1220 | }; | ||
1221 | EXPORT_SYMBOL(agp3_generic_sizes); | ||
1222 | |||