]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.20-agp_uninorth.patch
- xen update to 3.0.4
[packages/kernel.git] / linux-2.4.20-agp_uninorth.patch
CommitLineData
99eac90e
AM
1diff -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
4@@ -53,6 +53,10 @@
5 #include <asm/msr.h>
6 #endif
3d98ac96 7
8+#ifdef CONFIG_AGP_UNINORTH
9+#include <asm/uninorth.h>
10+#endif
11+
12 #include <linux/agp_backend.h>
13 #include "agp.h"
14
99eac90e 15@@ -81,7 +85,7 @@
3d98ac96 16 {
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
99eac90e
AM
24@@ -5918,6 +5922,405 @@
25 }
26 #endif /* CONFIG_AGP_ATI */
3d98ac96 27
28+#ifdef CONFIG_AGP_UNINORTH
29+
30+static int uninorth_fetch_size(void)
31+{
32+ int i;
33+ u32 temp;
34+ aper_size_info_32 *values;
35+
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);
39+
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;
46+ }
47+ }
48+
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;
53+
54+ return 0;
55+}
56+
57+static void uninorth_tlbflush(agp_memory * mem)
58+{
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);
67+}
68+
69+static void uninorth_cleanup(void)
70+{
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,
74+ 0);
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,
78+ 0);
79+}
80+
81+static int uninorth_configure(void)
82+{
83+ aper_size_info_32 *current_size;
84+
85+ current_size = A_SIZE_32(agp_bridge.current_size);
86+
87+ printk("agp: configuring for size idx: %d\n", current_size->size_value);
88+
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);
94+
95+ /* HACK ALERT
96+ * UniNorth seem to be buggy enough not to handle properly when
97+ * the AGP aperture isn't mapped at bus physical address 0
98+ */
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);
102+
103+ return 0;
104+}
105+
106+static unsigned long uninorth_mask_memory(unsigned long addr, int type)
107+{
108+ return addr;/* | agp_bridge.masks[0].mask;*/
109+}
110+
111+static int uninorth_insert_memory(agp_memory * mem,
112+ off_t pg_start, int type)
113+{
114+ int i, j, num_entries;
115+ void *temp;
116+
117+ temp = agp_bridge.current_size;
118+ num_entries = A_SIZE_32(temp)->num_entries;
119+
120+ if (type != 0 || mem->type != 0) {
121+ /* The generic routines know nothing of memory types */
122+ return -EINVAL;
123+ }
124+ if ((pg_start + mem->page_count) > num_entries) {
125+ return -EINVAL;
126+ }
127+ j = pg_start;
128+
129+ while (j < (pg_start + mem->page_count)) {
130+ if (!PGE_EMPTY(agp_bridge.gatt_table[j])) {
131+ return -EBUSY;
132+ }
133+ j++;
134+ }
135+
136+ if (mem->is_flushed == FALSE) {
137+ CACHE_FLUSH();
138+ mem->is_flushed = TRUE;
139+ }
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);
143+ }
144+ (void)in_le32((volatile u32*)&agp_bridge.gatt_table[pg_start]);
145+ mb();
146+ flush_dcache_range((unsigned long)&agp_bridge.gatt_table[pg_start],
147+ (unsigned long)&agp_bridge.gatt_table[pg_start + mem->page_count]);
148+
149+ agp_bridge.tlb_flush(mem);
150+ return 0;
151+}
152+
153+static void uninorth_agp_enable(u32 mode)
154+{
155+ struct pci_dev *device = NULL;
156+ u32 command, scratch, cap_id;
157+ u8 cap_ptr;
158+
159+ pci_read_config_dword(agp_bridge.dev,
160+ agp_bridge.capndx + 4,
161+ &command);
162+
163+ /*
164+ * PASS1: go throu all devices that claim to be
165+ * AGP devices and collect their data.
166+ */
167+
168+ while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
169+ device)) != NULL) {
170+ pci_read_config_dword(device, 0x04, &scratch);
171+
172+ if (!(scratch & 0x00100000))
173+ continue;
174+
175+ pci_read_config_byte(device, 0x34, &cap_ptr);
176+
177+ if (cap_ptr != 0x00) {
178+ do {
179+ pci_read_config_dword(device,
180+ cap_ptr, &cap_id);
181+
182+ if ((cap_id & 0xff) != 0x02)
183+ cap_ptr = (cap_id >> 8) & 0xff;
184+ }
185+ while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
186+ }
187+ if (cap_ptr != 0x00) {
188+ /*
189+ * Ok, here we have a AGP device. Disable impossible
190+ * settings, and adjust the readqueue to the minimum.
191+ */
192+
193+ pci_read_config_dword(device, cap_ptr + 4, &scratch);
194+
195+ /* adjust RQ depth */
196+ command =
197+ ((command & ~0xff000000) |
198+ min_t(u32, (mode & 0xff000000),
199+ min_t(u32, (command & 0xff000000),
200+ (scratch & 0xff000000))));
201+
202+ /* disable SBA if it's not supported */
203+ if (!((command & 0x00000200) &&
204+ (scratch & 0x00000200) &&
205+ (mode & 0x00000200)))
206+ command &= ~0x00000200;
207+
208+ /* disable FW if it's not supported */
209+ if (!((command & 0x00000010) &&
210+ (scratch & 0x00000010) &&
211+ (mode & 0x00000010)))
212+ command &= ~0x00000010;
213+
214+ if (!((command & 4) &&
215+ (scratch & 4) &&
216+ (mode & 4)))
217+ command &= ~0x00000004;
218+
219+ if (!((command & 2) &&
220+ (scratch & 2) &&
221+ (mode & 2)))
222+ command &= ~0x00000002;
223+
224+ if (!((command & 1) &&
225+ (scratch & 1) &&
226+ (mode & 1)))
227+ command &= ~0x00000001;
228+ }
229+ }
230+ /*
231+ * PASS2: Figure out the 4X/2X/1X setting and enable the
232+ * target (our motherboard chipset).
233+ */
234+
235+ if (command & 4) {
236+ command &= ~3; /* 4X */
237+ }
238+ if (command & 2) {
239+ command &= ~5; /* 2X */
240+ }
241+ if (command & 1) {
242+ command &= ~6; /* 1X */
243+ }
244+ command |= 0x00000100;
245+
246+ uninorth_tlbflush(NULL);
247+
248+ do {
249+ pci_write_config_dword(agp_bridge.dev,
250+ agp_bridge.capndx + 8,
251+ command);
252+ pci_read_config_dword(agp_bridge.dev,
253+ agp_bridge.capndx + 8,
254+ &scratch);
255+ } while((scratch & 0x100) == 0);
256+
257+ /*
258+ * PASS3: Go throu all AGP devices and update the
259+ * command registers.
260+ */
261+
262+ while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
263+ device)) != NULL) {
264+ pci_read_config_dword(device, 0x04, &scratch);
265+
266+ if (!(scratch & 0x00100000))
267+ continue;
268+
269+ pci_read_config_byte(device, 0x34, &cap_ptr);
270+
271+ if (cap_ptr != 0x00) {
272+ do {
273+ pci_read_config_dword(device,
274+ cap_ptr, &cap_id);
275+
276+ if ((cap_id & 0xff) != 0x02)
277+ cap_ptr = (cap_id >> 8) & 0xff;
278+ }
279+ while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
280+ }
281+ if (cap_ptr != 0x00)
282+ pci_write_config_dword(device, cap_ptr + 8, command);
283+ }
284+
285+ uninorth_tlbflush(NULL);
286+}
287+
288+static int uninorth_create_gatt_table(void)
289+{
290+ char *table;
291+ char *table_end;
292+ int size;
293+ int page_order;
294+ int num_entries;
295+ int i;
296+ void *temp;
297+ struct page *page;
298+
299+ /* The generic routines can't handle 2 level gatt's */
300+ if (agp_bridge.size_type == LVL2_APER_SIZE) {
301+ return -EINVAL;
302+ }
303+
304+ table = NULL;
305+ i = agp_bridge.aperture_size_idx;
306+ temp = agp_bridge.current_size;
307+ size = page_order = num_entries = 0;
308+
309+ do {
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;
313+
314+ table = (char *) __get_free_pages(GFP_KERNEL, page_order);
315+
316+ if (table == NULL) {
317+ i++;
318+ agp_bridge.current_size = A_IDX32();
319+ } else {
320+ agp_bridge.aperture_size_idx = i;
321+ }
322+ } while ((table == NULL) &&
323+ (i < agp_bridge.num_aperture_sizes));
324+
325+ if (table == NULL) {
326+ return -ENOMEM;
327+ }
328+ table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
329+
330+ for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
331+ SetPageReserved(page);
332+
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);
336+
337+ for (i = 0; i < num_entries; i++) {
338+ agp_bridge.gatt_table[i] =
339+ (unsigned long) agp_bridge.scratch_page;
340+ }
341+
342+ flush_dcache_range((unsigned long)table, (unsigned long)table_end);
343+
344+ return 0;
345+}
346+
347+static int uninorth_free_gatt_table(void)
348+{
349+ int page_order;
350+ char *table, *table_end;
351+ void *temp;
352+ struct page *page;
353+
354+ temp = agp_bridge.current_size;
355+ page_order = A_SIZE_32(temp)->page_order;
356+
357+ /* Do not worry about freeing memory, because if this is
358+ * called, then all agp memory is deallocated and removed
359+ * from the table.
360+ */
361+
362+ table = (char *) agp_bridge.gatt_table_real;
363+ table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
364+
365+ for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
366+ ClearPageReserved(page);
367+
368+ free_pages((unsigned long) agp_bridge.gatt_table_real, page_order);
369+
370+ return 0;
371+}
372+
373+/* Setup function */
374+static gatt_mask uninorth_masks[] =
375+{
376+ {0x00000000, 0}
377+};
378+
379+static aper_size_info_32 uninorth_sizes[7] =
380+{
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},
385+#endif
386+ {32, 8192, 3, 8},
387+ {16, 4096, 2, 4},
388+ {8, 2048, 1, 2},
389+ {4, 1024, 0, 1}
390+};
391+
392+static int __init uninorth_setup (struct pci_dev *pdev)
393+{
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;
419+
420+ return 0;
421+
422+ (void) pdev; /* unused */
423+}
424+
425+#endif /* CONFIG_AGP_UNINORTH */
426+
427 /* per-chipset initialization data.
428 * note -- all chipsets for a single vendor MUST be grouped together
429 */
99eac90e
AM
430@@ -6462,6 +6865,27 @@
431 ati_generic_setup },
432 #endif /* CONFIG_AGP_ATI */
3d98ac96 433
434+#ifdef CONFIG_AGP_UNINORTH
435+ { PCI_DEVICE_ID_APPLE_UNI_N_AGP,
436+ PCI_VENDOR_ID_APPLE,
437+ APPLE_UNINORTH,
438+ "Apple",
439+ "UniNorth",
440+ uninorth_setup },
441+ { PCI_DEVICE_ID_APPLE_UNI_N_AGP_P,
442+ PCI_VENDOR_ID_APPLE,
443+ APPLE_UNINORTH,
444+ "Apple",
445+ "UniNorth/Pangea",
446+ uninorth_setup },
447+ { PCI_DEVICE_ID_APPLE_UNI_N_AGP15,
448+ PCI_VENDOR_ID_APPLE,
449+ APPLE_UNINORTH,
450+ "Apple",
451+ "UniNorth 1.5",
452+ uninorth_setup },
453+#endif /* CONFIG_AGP_UNINORTH */
454+
455 { 0, }, /* dummy final entry, always present */
456 };
457
99eac90e
AM
458diff -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
461@@ -210,6 +210,9 @@
462 comment ' from the tpqic02-support package. It is available at'
463 comment ' metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
3d98ac96 464 fi
465+ if [ "$CONFIG_ALL_PPC" = "y" ]; then
466+ bool ' Apple UniNorth support' CONFIG_AGP_UNINORTH
467+ fi
468 fi
469
99eac90e
AM
470 tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
471diff -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
474@@ -95,6 +95,7 @@
475 NVIDIA_NFORCE3,
476 NVIDIA_GENERIC,
3d98ac96 477 HP_ZX1,
478+ APPLE_UNINORTH,
99eac90e
AM
479 ATI_RS100,
480 ATI_RS200,
481 ATI_RS250,
This page took 0.260821 seconds and 4 git commands to generate.