1 diff -urN linux-2.4.22.org/drivers/char/agp/agpgart_be.c linux-2.4.22/drivers/char/agp/agpgart_be.c
2 --- linux-2.4.22.org/drivers/char/agp/agpgart_be.c 2003-11-21 18:32:42.000000000 +0100
3 +++ linux-2.4.22/drivers/char/agp/agpgart_be.c 2003-11-21 18:34:41.000000000 +0100
8 +#ifdef CONFIG_AGP_UNINORTH
9 +#include <asm/uninorth.h>
12 #include <linux/agp_backend.h>
17 #if defined(__i386__) || defined(__x86_64__)
18 asm volatile ("wbinvd":::"memory");
19 -#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__)
20 +#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__) || defined(__powerpc__)
21 /* ??? I wonder if we'll really need to flush caches, or if the
22 core logic can manage to keep the system coherent. The ARM
23 speaks only of using `cflush' to get things in memory in
24 @@ -5918,6 +5922,405 @@
26 #endif /* CONFIG_AGP_ATI */
28 +#ifdef CONFIG_AGP_UNINORTH
30 +static int uninorth_fetch_size(void)
34 + aper_size_info_32 *values;
36 + pci_read_config_dword(agp_bridge.dev, UNI_N_CFG_GART_BASE, &temp);
37 + temp &= ~(0xfffff000);
38 + values = A_SIZE_32(agp_bridge.aperture_sizes);
40 + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) {
41 + if (temp == values[i].size_value) {
42 + agp_bridge.previous_size =
43 + agp_bridge.current_size = (void *) (values + i);
44 + agp_bridge.aperture_size_idx = i;
45 + return values[i].size;
49 + agp_bridge.previous_size =
50 + agp_bridge.current_size = (void *) (values + 1);
51 + agp_bridge.aperture_size_idx = 1;
52 + return values[1].size;
57 +static void uninorth_tlbflush(agp_memory * mem)
59 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
60 + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
61 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
62 + UNI_N_CFG_GART_ENABLE);
63 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
64 + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET);
65 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
66 + UNI_N_CFG_GART_ENABLE);
69 +static void uninorth_cleanup(void)
71 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
72 + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
73 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
75 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
76 + UNI_N_CFG_GART_2xRESET);
77 + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL,
81 +static int uninorth_configure(void)
83 + aper_size_info_32 *current_size;
85 + current_size = A_SIZE_32(agp_bridge.current_size);
87 + printk("agp: configuring for size idx: %d\n", current_size->size_value);
89 + /* aperture size and gatt addr */
90 + pci_write_config_dword(agp_bridge.dev,
91 + UNI_N_CFG_GART_BASE,
92 + (agp_bridge.gatt_bus_addr & 0xfffff000)
93 + | current_size->size_value);
96 + * UniNorth seem to be buggy enough not to handle properly when
97 + * the AGP aperture isn't mapped at bus physical address 0
99 + agp_bridge.gart_bus_addr = 0;
100 + pci_write_config_dword(agp_bridge.dev,
101 + UNI_N_CFG_AGP_BASE, agp_bridge.gart_bus_addr);
106 +static unsigned long uninorth_mask_memory(unsigned long addr, int type)
108 + return addr;/* | agp_bridge.masks[0].mask;*/
111 +static int uninorth_insert_memory(agp_memory * mem,
112 + off_t pg_start, int type)
114 + int i, j, num_entries;
117 + temp = agp_bridge.current_size;
118 + num_entries = A_SIZE_32(temp)->num_entries;
120 + if (type != 0 || mem->type != 0) {
121 + /* The generic routines know nothing of memory types */
124 + if ((pg_start + mem->page_count) > num_entries) {
129 + while (j < (pg_start + mem->page_count)) {
130 + if (!PGE_EMPTY(agp_bridge.gatt_table[j])) {
136 + if (mem->is_flushed == FALSE) {
138 + mem->is_flushed = TRUE;
140 + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
141 + agp_bridge.gatt_table[j] = cpu_to_le32((mem->memory[i] & 0xfffff000) | 0x00000001UL);
142 + flush_dcache_range(__va(mem->memory[i]), __va(mem->memory[i])+0x1000);
144 + (void)in_le32((volatile u32*)&agp_bridge.gatt_table[pg_start]);
146 + flush_dcache_range((unsigned long)&agp_bridge.gatt_table[pg_start],
147 + (unsigned long)&agp_bridge.gatt_table[pg_start + mem->page_count]);
149 + agp_bridge.tlb_flush(mem);
153 +static void uninorth_agp_enable(u32 mode)
155 + struct pci_dev *device = NULL;
156 + u32 command, scratch, cap_id;
159 + pci_read_config_dword(agp_bridge.dev,
160 + agp_bridge.capndx + 4,
164 + * PASS1: go throu all devices that claim to be
165 + * AGP devices and collect their data.
168 + while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
169 + device)) != NULL) {
170 + pci_read_config_dword(device, 0x04, &scratch);
172 + if (!(scratch & 0x00100000))
175 + pci_read_config_byte(device, 0x34, &cap_ptr);
177 + if (cap_ptr != 0x00) {
179 + pci_read_config_dword(device,
182 + if ((cap_id & 0xff) != 0x02)
183 + cap_ptr = (cap_id >> 8) & 0xff;
185 + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
187 + if (cap_ptr != 0x00) {
189 + * Ok, here we have a AGP device. Disable impossible
190 + * settings, and adjust the readqueue to the minimum.
193 + pci_read_config_dword(device, cap_ptr + 4, &scratch);
195 + /* adjust RQ depth */
197 + ((command & ~0xff000000) |
198 + min_t(u32, (mode & 0xff000000),
199 + min_t(u32, (command & 0xff000000),
200 + (scratch & 0xff000000))));
202 + /* disable SBA if it's not supported */
203 + if (!((command & 0x00000200) &&
204 + (scratch & 0x00000200) &&
205 + (mode & 0x00000200)))
206 + command &= ~0x00000200;
208 + /* disable FW if it's not supported */
209 + if (!((command & 0x00000010) &&
210 + (scratch & 0x00000010) &&
211 + (mode & 0x00000010)))
212 + command &= ~0x00000010;
214 + if (!((command & 4) &&
217 + command &= ~0x00000004;
219 + if (!((command & 2) &&
222 + command &= ~0x00000002;
224 + if (!((command & 1) &&
227 + command &= ~0x00000001;
231 + * PASS2: Figure out the 4X/2X/1X setting and enable the
232 + * target (our motherboard chipset).
236 + command &= ~3; /* 4X */
239 + command &= ~5; /* 2X */
242 + command &= ~6; /* 1X */
244 + command |= 0x00000100;
246 + uninorth_tlbflush(NULL);
249 + pci_write_config_dword(agp_bridge.dev,
250 + agp_bridge.capndx + 8,
252 + pci_read_config_dword(agp_bridge.dev,
253 + agp_bridge.capndx + 8,
255 + } while((scratch & 0x100) == 0);
258 + * PASS3: Go throu all AGP devices and update the
259 + * command registers.
262 + while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
263 + device)) != NULL) {
264 + pci_read_config_dword(device, 0x04, &scratch);
266 + if (!(scratch & 0x00100000))
269 + pci_read_config_byte(device, 0x34, &cap_ptr);
271 + if (cap_ptr != 0x00) {
273 + pci_read_config_dword(device,
276 + if ((cap_id & 0xff) != 0x02)
277 + cap_ptr = (cap_id >> 8) & 0xff;
279 + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
281 + if (cap_ptr != 0x00)
282 + pci_write_config_dword(device, cap_ptr + 8, command);
285 + uninorth_tlbflush(NULL);
288 +static int uninorth_create_gatt_table(void)
299 + /* The generic routines can't handle 2 level gatt's */
300 + if (agp_bridge.size_type == LVL2_APER_SIZE) {
305 + i = agp_bridge.aperture_size_idx;
306 + temp = agp_bridge.current_size;
307 + size = page_order = num_entries = 0;
310 + size = A_SIZE_32(temp)->size;
311 + page_order = A_SIZE_32(temp)->page_order;
312 + num_entries = A_SIZE_32(temp)->num_entries;
314 + table = (char *) __get_free_pages(GFP_KERNEL, page_order);
316 + if (table == NULL) {
318 + agp_bridge.current_size = A_IDX32();
320 + agp_bridge.aperture_size_idx = i;
322 + } while ((table == NULL) &&
323 + (i < agp_bridge.num_aperture_sizes));
325 + if (table == NULL) {
328 + table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
330 + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
331 + SetPageReserved(page);
333 + agp_bridge.gatt_table_real = (unsigned long *) table;
334 + agp_bridge.gatt_table = (unsigned long *)table;
335 + agp_bridge.gatt_bus_addr = virt_to_phys(table);
337 + for (i = 0; i < num_entries; i++) {
338 + agp_bridge.gatt_table[i] =
339 + (unsigned long) agp_bridge.scratch_page;
342 + flush_dcache_range((unsigned long)table, (unsigned long)table_end);
347 +static int uninorth_free_gatt_table(void)
350 + char *table, *table_end;
354 + temp = agp_bridge.current_size;
355 + page_order = A_SIZE_32(temp)->page_order;
357 + /* Do not worry about freeing memory, because if this is
358 + * called, then all agp memory is deallocated and removed
362 + table = (char *) agp_bridge.gatt_table_real;
363 + table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
365 + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
366 + ClearPageReserved(page);
368 + free_pages((unsigned long) agp_bridge.gatt_table_real, page_order);
373 +/* Setup function */
374 +static gatt_mask uninorth_masks[] =
379 +static aper_size_info_32 uninorth_sizes[7] =
381 +#if 0 /* Not sure uninorth supports that high aperture sizes */
382 + {256, 65536, 6, 64},
383 + {128, 32768, 5, 32},
384 + {64, 16384, 4, 16},
392 +static int __init uninorth_setup (struct pci_dev *pdev)
394 + agp_bridge.masks = uninorth_masks;
395 + agp_bridge.num_of_masks = 1;
396 + agp_bridge.aperture_sizes = (void *)uninorth_sizes;
397 + agp_bridge.size_type = U32_APER_SIZE;
398 + agp_bridge.num_aperture_sizes = 4; //7;
399 + agp_bridge.dev_private_data = NULL;
400 + agp_bridge.needs_scratch_page = FALSE;
401 + agp_bridge.configure = uninorth_configure;
402 + agp_bridge.fetch_size = uninorth_fetch_size;
403 + agp_bridge.cleanup = uninorth_cleanup;
404 + agp_bridge.tlb_flush = uninorth_tlbflush;
405 + agp_bridge.mask_memory = uninorth_mask_memory;
406 + agp_bridge.agp_enable = uninorth_agp_enable;
407 + agp_bridge.cache_flush = global_cache_flush;
408 + agp_bridge.create_gatt_table = uninorth_create_gatt_table;
409 + agp_bridge.free_gatt_table = uninorth_free_gatt_table;
410 + agp_bridge.insert_memory = uninorth_insert_memory;
411 + agp_bridge.remove_memory = agp_generic_remove_memory;
412 + agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
413 + agp_bridge.free_by_type = agp_generic_free_by_type;
414 + agp_bridge.agp_alloc_page = agp_generic_alloc_page;
415 + agp_bridge.agp_destroy_page = agp_generic_destroy_page;
416 + agp_bridge.suspend = agp_generic_suspend;
417 + agp_bridge.resume = agp_generic_resume;
418 + agp_bridge.cant_use_aperture = 1;
422 + (void) pdev; /* unused */
425 +#endif /* CONFIG_AGP_UNINORTH */
427 /* per-chipset initialization data.
428 * note -- all chipsets for a single vendor MUST be grouped together
430 @@ -6462,6 +6865,27 @@
432 #endif /* CONFIG_AGP_ATI */
434 +#ifdef CONFIG_AGP_UNINORTH
435 + { PCI_DEVICE_ID_APPLE_UNI_N_AGP,
436 + PCI_VENDOR_ID_APPLE,
441 + { PCI_DEVICE_ID_APPLE_UNI_N_AGP_P,
442 + PCI_VENDOR_ID_APPLE,
447 + { PCI_DEVICE_ID_APPLE_UNI_N_AGP15,
448 + PCI_VENDOR_ID_APPLE,
453 +#endif /* CONFIG_AGP_UNINORTH */
455 { 0, }, /* dummy final entry, always present */
458 diff -urN linux-2.4.22.org/drivers/char/Config.in linux-2.4.22/drivers/char/Config.in
459 --- linux-2.4.22.org/drivers/char/Config.in 2003-11-21 18:32:29.000000000 +0100
460 +++ linux-2.4.22/drivers/char/Config.in 2003-11-21 18:34:42.000000000 +0100
462 comment ' from the tpqic02-support package. It is available at'
463 comment ' metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
465 + if [ "$CONFIG_ALL_PPC" = "y" ]; then
466 + bool ' Apple UniNorth support' CONFIG_AGP_UNINORTH
470 tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
471 diff -urN linux-2.4.22.org/include/linux/agp_backend.h linux-2.4.22/include/linux/agp_backend.h
472 --- linux-2.4.22.org/include/linux/agp_backend.h 2003-11-21 18:31:25.000000000 +0100
473 +++ linux-2.4.22/include/linux/agp_backend.h 2003-11-21 18:35:20.000000000 +0100