]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.20-agp_uninorth.patch
- 2.6.19 ready
[packages/kernel.git] / linux-2.4.20-agp_uninorth.patch
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
4 @@ -53,6 +53,10 @@
5  #include <asm/msr.h>
6  #endif
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  
15 @@ -81,7 +85,7 @@
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
24 @@ -5918,6 +5922,405 @@
25  }
26  #endif /* CONFIG_AGP_ATI */
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   */
430 @@ -6462,6 +6865,27 @@
431           ati_generic_setup },
432  #endif /* CONFIG_AGP_ATI */
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  
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
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/'
464     fi
465 +   if [ "$CONFIG_ALL_PPC" = "y" ]; then
466 +      bool '  Apple UniNorth support' CONFIG_AGP_UNINORTH
467 +   fi
468  fi
469  
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
474 @@ -95,6 +95,7 @@
475         NVIDIA_NFORCE3,
476         NVIDIA_GENERIC,
477         HP_ZX1,
478 +       APPLE_UNINORTH,
479         ATI_RS100,
480         ATI_RS200,
481         ATI_RS250,
This page took 0.22073 seconds and 3 git commands to generate.