1 | /* |
---|
2 | * pci.c -- Crude pci handling for early boot. |
---|
3 | * |
---|
4 | * Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es |
---|
5 | * |
---|
6 | * Modified to compile in RTEMS development environment |
---|
7 | * by Eric Valette |
---|
8 | * |
---|
9 | * Copyright (C) 1999 Eric Valette. valette@crf.canon.fr |
---|
10 | * |
---|
11 | * The license and distribution terms for this file may be |
---|
12 | * found in found in the file LICENSE in this distribution or at |
---|
13 | * http://www.OARcorp.com/rtems/license.html. |
---|
14 | * |
---|
15 | * $Id$ |
---|
16 | */ |
---|
17 | |
---|
18 | |
---|
19 | #include <sys/types.h> |
---|
20 | #include <libcpu/spr.h> |
---|
21 | #include "bootldr.h" |
---|
22 | #include "pci.h" |
---|
23 | #include <libcpu/io.h> |
---|
24 | #include <bsp/consoleIo.h> |
---|
25 | |
---|
26 | typedef unsigned int u32; |
---|
27 | |
---|
28 | /*#define DEBUG*/ |
---|
29 | /* Used to reorganize PCI space on stupid machines which spread resources |
---|
30 | * across a wide address space. This is bad when P2P bridges are present |
---|
31 | * or when it limits the mappings that a resource hog like a PCI<->VME |
---|
32 | * bridge can use. |
---|
33 | */ |
---|
34 | |
---|
35 | typedef struct _pci_resource { |
---|
36 | struct _pci_resource *next; |
---|
37 | struct pci_dev *dev; |
---|
38 | u_long base; /* will be 64 bits on 64 bits machines */ |
---|
39 | u_long size; |
---|
40 | u_char type; /* 1 is I/O else low order 4 bits of the memory type */ |
---|
41 | u_char reg; /* Register # in conf space header */ |
---|
42 | u_short cmd; /* Original cmd byte */ |
---|
43 | } pci_resource; |
---|
44 | |
---|
45 | typedef struct _pci_area { |
---|
46 | struct _pci_area *next; |
---|
47 | u_long start; |
---|
48 | u_long end; |
---|
49 | struct pci_bus *bus; |
---|
50 | u_int flags; |
---|
51 | } pci_area; |
---|
52 | |
---|
53 | typedef struct _pci_area_head { |
---|
54 | pci_area *head; |
---|
55 | u_long mask; |
---|
56 | int high; /* To allocate from top */ |
---|
57 | } pci_area_head; |
---|
58 | |
---|
59 | #define PCI_AREA_PREFETCHABLE 0 |
---|
60 | #define PCI_AREA_MEMORY 1 |
---|
61 | #define PCI_AREA_IO 2 |
---|
62 | |
---|
63 | struct _pci_private { |
---|
64 | volatile u_int * config_addr; |
---|
65 | volatile u_char * config_data; |
---|
66 | struct pci_dev **last_dev_p; |
---|
67 | struct pci_bus pci_root; |
---|
68 | pci_resource *resources; |
---|
69 | pci_area_head io, mem; |
---|
70 | |
---|
71 | } pci_private = { |
---|
72 | config_addr: NULL, |
---|
73 | config_data: (volatile u_char *) 0x80800000, |
---|
74 | last_dev_p: NULL, |
---|
75 | resources: NULL, |
---|
76 | io: {NULL, 0xfff, 0}, |
---|
77 | mem: {NULL, 0xfffff, 0} |
---|
78 | }; |
---|
79 | |
---|
80 | #define pci ((struct _pci_private *)(bd->pci_private)) |
---|
81 | #define pci_root pci->pci_root |
---|
82 | |
---|
83 | #if !defined(DEBUG) |
---|
84 | #undef PCI_DEBUG |
---|
85 | /* |
---|
86 | #else |
---|
87 | #define PCI_DEBUG |
---|
88 | */ |
---|
89 | #endif |
---|
90 | |
---|
91 | #if defined(PCI_DEBUG) |
---|
92 | static void |
---|
93 | print_pci_resources(const char *s) { |
---|
94 | pci_resource *p; |
---|
95 | printk("%s", s); |
---|
96 | for (p=pci->resources; p; p=p->next) { |
---|
97 | printk(" %p:%p %06x %08lx %08lx %d\n", |
---|
98 | p, p->next, |
---|
99 | (p->dev->devfn<<8)+(p->dev->bus->number<<16) |
---|
100 | +0x10+p->reg*4, |
---|
101 | p->base, |
---|
102 | p->size, |
---|
103 | p->type); |
---|
104 | } |
---|
105 | } |
---|
106 | |
---|
107 | static void |
---|
108 | print_pci_area(pci_area *p) { |
---|
109 | for (; p; p=p->next) { |
---|
110 | printk(" %p:%p %p %08lx %08lx\n", |
---|
111 | p, p->next, p->bus, p->start, p->end); |
---|
112 | } |
---|
113 | } |
---|
114 | |
---|
115 | static void |
---|
116 | print_pci_areas(const char *s) { |
---|
117 | printk("%s PCI I/O areas:\n",s); |
---|
118 | print_pci_area(pci->io.head); |
---|
119 | printk(" PCI memory areas:\n"); |
---|
120 | print_pci_area(pci->mem.head); |
---|
121 | } |
---|
122 | #else |
---|
123 | #define print_pci_areas(x) |
---|
124 | #define print_pci_resources(x) |
---|
125 | #endif |
---|
126 | |
---|
127 | /* Maybe there are some devices who use a size different |
---|
128 | * from the alignment. For now we assume both are the same. |
---|
129 | * The blacklist might be used for other weird things in the future too, |
---|
130 | * since weird non PCI complying devices seem to proliferate these days. |
---|
131 | */ |
---|
132 | |
---|
133 | struct blacklist_entry { |
---|
134 | u_short vendor, device; |
---|
135 | u_char reg; |
---|
136 | u_long actual_size; |
---|
137 | }; |
---|
138 | |
---|
139 | #define BLACKLIST(vid, did, breg, actual_size) \ |
---|
140 | {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##vid##_##did, breg, actual_size} |
---|
141 | |
---|
142 | static struct blacklist_entry blacklist[] = { |
---|
143 | BLACKLIST(S3, TRIO, 0, 0x04000000), |
---|
144 | {0xffff, 0, 0, 0} |
---|
145 | }; |
---|
146 | |
---|
147 | |
---|
148 | /* This function filters resources and then inserts them into a list of |
---|
149 | * configurable pci resources. |
---|
150 | */ |
---|
151 | |
---|
152 | |
---|
153 | #define AREA(r) \ |
---|
154 | (((r->type&PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO) ? PCI_AREA_IO :\ |
---|
155 | ((r->type&PCI_BASE_ADDRESS_MEM_PREFETCH) ? PCI_AREA_PREFETCHABLE :\ |
---|
156 | PCI_AREA_MEMORY)) |
---|
157 | |
---|
158 | static int insert_before(pci_resource *e, pci_resource *t) { |
---|
159 | if (e->dev->bus->number != t->dev->bus->number) |
---|
160 | return e->dev->bus->number > t->dev->bus->number; |
---|
161 | if (AREA(e) != AREA(t)) return AREA(e)<AREA(t); |
---|
162 | return (e->size > t->size); |
---|
163 | } |
---|
164 | |
---|
165 | static void insert_resource(pci_resource *r) { |
---|
166 | struct blacklist_entry *b; |
---|
167 | pci_resource *p; |
---|
168 | if (!r) return; |
---|
169 | |
---|
170 | /* First fixup in case we have a blacklist entry. Note that this |
---|
171 | * may temporarily leave a resource in an inconsistent state: with |
---|
172 | * (base & (size-1)) !=0. This is harmless. |
---|
173 | */ |
---|
174 | for (b=blacklist; b->vendor!=0xffff; b++) { |
---|
175 | if ((r->dev->vendor==b->vendor) && |
---|
176 | (r->dev->device==b->device) && |
---|
177 | (r->reg==b->reg)) { |
---|
178 | r->size=b->actual_size; |
---|
179 | break; |
---|
180 | } |
---|
181 | } |
---|
182 | |
---|
183 | /* Motorola NT firmware does not configure pci devices which are not |
---|
184 | * required for booting, others do. For now: |
---|
185 | * - allocated devices in the ISA range (64kB I/O, 16Mb memory) |
---|
186 | * but non zero base registers are left as is. |
---|
187 | * - all other registers, whether already allocated or not, are |
---|
188 | * reallocated unless they require an inordinate amount of |
---|
189 | * resources (>256 Mb for memory >64kB for I/O). These |
---|
190 | * devices with too large mapping requirements are simply ignored |
---|
191 | * and their bases are set to 0. This should disable the |
---|
192 | * corresponding decoders according to the PCI specification. |
---|
193 | * Many devices are buggy in this respect, however, but the |
---|
194 | * limits have hopefully been set high enough to avoid problems. |
---|
195 | */ |
---|
196 | |
---|
197 | if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) |
---|
198 | ? (r->base && r->base <0x10000) |
---|
199 | : (r->base && r->base <0x1000000)) { |
---|
200 | sfree(r); |
---|
201 | return; |
---|
202 | } |
---|
203 | |
---|
204 | if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) |
---|
205 | ? (r->size >= 0x10000) |
---|
206 | : (r->size >= 0x10000000)) { |
---|
207 | r->size = 0; |
---|
208 | r->base = 0; |
---|
209 | } |
---|
210 | |
---|
211 | /* Now insert into the list sorting by |
---|
212 | * 1) decreasing bus number |
---|
213 | * 2) space: prefetchable memory, non-prefetchable and finally I/O |
---|
214 | * 3) decreasing size |
---|
215 | */ |
---|
216 | if (!pci->resources || insert_before(r, pci->resources)) { |
---|
217 | r->next = pci->resources; |
---|
218 | pci->resources=r; |
---|
219 | } else { |
---|
220 | for (p=pci->resources; p->next; p=p->next) { |
---|
221 | if (insert_before(r, p->next)) break; |
---|
222 | } |
---|
223 | r->next=p->next; |
---|
224 | p->next=r; |
---|
225 | } |
---|
226 | } |
---|
227 | |
---|
228 | /* This version only works for bus 0. I don't have any P2P bridges to test |
---|
229 | * a more sophisticated version which has therefore not been implemented. |
---|
230 | * Prefetchable memory is not yet handled correctly either. |
---|
231 | * And several levels of PCI bridges much less even since there must be |
---|
232 | * allocated together to be able to setup correctly the top bridge. |
---|
233 | */ |
---|
234 | |
---|
235 | static u_long find_range(u_char bus, u_char type, |
---|
236 | pci_resource **first, |
---|
237 | pci_resource **past, u_int *flags) { |
---|
238 | pci_resource *p; |
---|
239 | u_long total=0; |
---|
240 | u_int fl=0; |
---|
241 | |
---|
242 | for (p=pci->resources; p; p=p->next) { |
---|
243 | if ((p->dev->bus->number == bus) && |
---|
244 | AREA(p)==type) break; |
---|
245 | } |
---|
246 | *first = p; |
---|
247 | for (; p; p=p->next) { |
---|
248 | if ((p->dev->bus->number != bus) || |
---|
249 | AREA(p)!=type || p->size == 0) break; |
---|
250 | total = total+p->size; |
---|
251 | fl |= 1<<p->type; |
---|
252 | } |
---|
253 | *past = p; |
---|
254 | /* This will be used later to tell whether there are any 32 bit |
---|
255 | * devices in an area which could be mapped higher than 4Gb |
---|
256 | * on 64 bits architectures |
---|
257 | */ |
---|
258 | *flags = fl; |
---|
259 | return total; |
---|
260 | } |
---|
261 | |
---|
262 | static inline void init_free_area(pci_area_head *h, u_long start, |
---|
263 | u_long end, u_int mask, int high) { |
---|
264 | pci_area *p; |
---|
265 | p = salloc(sizeof(pci_area)); |
---|
266 | if (!p) return; |
---|
267 | h->head = p; |
---|
268 | p->next = NULL; |
---|
269 | p->start = (start+mask)&~mask; |
---|
270 | p->end = (end-mask)|mask; |
---|
271 | p->bus = NULL; |
---|
272 | h->mask = mask; |
---|
273 | h->high = high; |
---|
274 | } |
---|
275 | |
---|
276 | static void insert_area(pci_area_head *h, pci_area *p) { |
---|
277 | pci_area *q = h->head; |
---|
278 | if (!p) return; |
---|
279 | if (q && (q->start< p->start)) { |
---|
280 | for(;q->next && q->next->start<p->start; q = q->next); |
---|
281 | if ((q->end >= p->start) || |
---|
282 | (q->next && p->end>=q->next->start)) { |
---|
283 | sfree(p); |
---|
284 | printk("Overlapping pci areas!\n"); |
---|
285 | return; |
---|
286 | } |
---|
287 | p->next = q->next; |
---|
288 | q->next = p; |
---|
289 | } else { /* Insert at head */ |
---|
290 | if (q && (p->end >= q->start)) { |
---|
291 | sfree(p); |
---|
292 | printk("Overlapping pci areas!\n"); |
---|
293 | return; |
---|
294 | } |
---|
295 | p->next = q; |
---|
296 | h->head = p; |
---|
297 | } |
---|
298 | } |
---|
299 | |
---|
300 | static |
---|
301 | void remove_area(pci_area_head *h, pci_area *p) { |
---|
302 | pci_area *q = h->head; |
---|
303 | |
---|
304 | if (!p || !q) return; |
---|
305 | if (q==p) { |
---|
306 | h->head = q->next; |
---|
307 | return; |
---|
308 | } |
---|
309 | for(;q && q->next!=p; q=q->next); |
---|
310 | if (q) q->next=p->next; |
---|
311 | } |
---|
312 | |
---|
313 | static pci_area * alloc_area(pci_area_head *h, struct pci_bus *bus, |
---|
314 | u_long required, u_long mask, u_int flags) { |
---|
315 | pci_area *p; |
---|
316 | pci_area *from, *split, *new; |
---|
317 | |
---|
318 | required = (required+h->mask) & ~h->mask; |
---|
319 | for (p=h->head, from=NULL; p; p=p->next) { |
---|
320 | u_long l1 = ((p->start+required+mask)&~mask)-1; |
---|
321 | u_long l2 = ((p->start+mask)&~mask)+required-1; |
---|
322 | /* Allocated areas point to the bus to which they pertain */ |
---|
323 | if (p->bus) continue; |
---|
324 | if ((p->end)>=l1 || (p->end)>=l2) from=p; |
---|
325 | if (from && !h->high) break; |
---|
326 | } |
---|
327 | if (!from) return NULL; |
---|
328 | |
---|
329 | split = salloc(sizeof(pci_area)); |
---|
330 | new = salloc(sizeof(pci_area)); |
---|
331 | /* If allocation of new succeeds then allocation of split has |
---|
332 | * also been successful (given the current mm algorithms) ! |
---|
333 | */ |
---|
334 | if (!new) { |
---|
335 | sfree(split); |
---|
336 | return NULL; |
---|
337 | } |
---|
338 | new->bus = bus; |
---|
339 | new->flags = flags; |
---|
340 | /* Now allocate pci_space taking alignment into account ! */ |
---|
341 | if (h->high) { |
---|
342 | u_long l1 = ((from->end+1)&~mask)-required; |
---|
343 | u_long l2 = (from->end+1-required)&~mask; |
---|
344 | new->start = (l1>l2) ? l1 : l2; |
---|
345 | split->end = from->end; |
---|
346 | from->end = new->start-1; |
---|
347 | split->start = new->start+required; |
---|
348 | new->end = new->start+required-1; |
---|
349 | } else { |
---|
350 | u_long l1 = ((from->start+mask)&~mask)+required-1; |
---|
351 | u_long l2 = ((from->start+required+mask)&~mask)-1; |
---|
352 | new->end = (l1<l2) ? l1 : l2; |
---|
353 | split->start = from->start; |
---|
354 | from->start = new->end+1; |
---|
355 | new->start = new->end+1-required; |
---|
356 | split->end = new->start-1; |
---|
357 | } |
---|
358 | |
---|
359 | if (from->end+1 == from->start) remove_area(h, from); |
---|
360 | if (split->end+1 != split->start) { |
---|
361 | split->bus = NULL; |
---|
362 | insert_area(h, split); |
---|
363 | } else { |
---|
364 | sfree(split); |
---|
365 | } |
---|
366 | insert_area(h, new); |
---|
367 | print_pci_areas("alloc_area called:\n"); |
---|
368 | return new; |
---|
369 | } |
---|
370 | |
---|
371 | static inline |
---|
372 | void alloc_space(pci_area *p, pci_resource *r) { |
---|
373 | if (p->start & (r->size-1)) { |
---|
374 | r->base = p->end+1-r->size; |
---|
375 | p->end -= r->size; |
---|
376 | } else { |
---|
377 | r->base = p->start; |
---|
378 | p->start += r->size; |
---|
379 | } |
---|
380 | } |
---|
381 | |
---|
382 | static void reconfigure_bus_space(u_char bus, u_char type, pci_area_head *h) { |
---|
383 | pci_resource *first, *past, *r; |
---|
384 | pci_area *area, tmp; |
---|
385 | u_int flags; |
---|
386 | u_int required = find_range(bus, type, &first, &past, &flags); |
---|
387 | |
---|
388 | if (required==0) return; |
---|
389 | area = alloc_area(h, first->dev->bus, required, first->size-1, flags); |
---|
390 | if (!area) return; |
---|
391 | tmp = *area; |
---|
392 | for (r=first; r!=past; r=r->next) { |
---|
393 | alloc_space(&tmp, r); |
---|
394 | } |
---|
395 | } |
---|
396 | |
---|
397 | static void reconfigure_pci(void) { |
---|
398 | pci_resource *r; |
---|
399 | struct pci_dev *dev; |
---|
400 | /* FIXME: for now memory is relocated from low, it's better |
---|
401 | * to start from higher addresses. |
---|
402 | */ |
---|
403 | init_free_area(&pci->io, 0x10000, 0x7fffff, 0xfff, 0); |
---|
404 | init_free_area(&pci->mem, 0x1000000, 0x3cffffff, 0xfffff, 0); |
---|
405 | |
---|
406 | /* First reconfigure the I/O space, this will be more |
---|
407 | * complex when there is more than 1 bus. And 64 bits |
---|
408 | * devices are another kind of problems. |
---|
409 | */ |
---|
410 | reconfigure_bus_space(0, PCI_AREA_IO, &pci->io); |
---|
411 | reconfigure_bus_space(0, PCI_AREA_MEMORY, &pci->mem); |
---|
412 | reconfigure_bus_space(0, PCI_AREA_PREFETCHABLE, &pci->mem); |
---|
413 | |
---|
414 | /* Now we have to touch the configuration space of all |
---|
415 | * the devices to remap them better than they are right now. |
---|
416 | * This is done in 3 steps: |
---|
417 | * 1) first disable I/O and memory response of all devices |
---|
418 | * 2) modify the base registers |
---|
419 | * 3) restore the original PCI_COMMAND register. |
---|
420 | */ |
---|
421 | for (r=pci->resources; r; r= r->next) { |
---|
422 | if (!r->dev->sysdata) { |
---|
423 | r->dev->sysdata=r; |
---|
424 | pci_read_config_word(r->dev, PCI_COMMAND, &r->cmd); |
---|
425 | pci_write_config_word(r->dev, PCI_COMMAND, |
---|
426 | r->cmd & ~(PCI_COMMAND_IO| |
---|
427 | PCI_COMMAND_MEMORY)); |
---|
428 | } |
---|
429 | } |
---|
430 | |
---|
431 | for (r=pci->resources; r; r= r->next) { |
---|
432 | pci_write_config_dword(r->dev, |
---|
433 | PCI_BASE_ADDRESS_0+(r->reg<<2), |
---|
434 | r->base); |
---|
435 | if ((r->type& |
---|
436 | (PCI_BASE_ADDRESS_SPACE| |
---|
437 | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == |
---|
438 | (PCI_BASE_ADDRESS_SPACE_MEMORY| |
---|
439 | PCI_BASE_ADDRESS_MEM_TYPE_64)) { |
---|
440 | pci_write_config_dword(r->dev, |
---|
441 | PCI_BASE_ADDRESS_1+ |
---|
442 | (r->reg<<2), |
---|
443 | 0); |
---|
444 | } |
---|
445 | } |
---|
446 | for (dev=bd->pci_devices; dev; dev= dev->next) { |
---|
447 | if (dev->sysdata) { |
---|
448 | pci_write_config_word(dev, PCI_COMMAND, |
---|
449 | ((pci_resource *)dev->sysdata) |
---|
450 | ->cmd); |
---|
451 | dev->sysdata=NULL; |
---|
452 | } |
---|
453 | } |
---|
454 | } |
---|
455 | |
---|
456 | static int |
---|
457 | indirect_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
458 | unsigned char offset, unsigned char *val) { |
---|
459 | out_be32(pci->config_addr, |
---|
460 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
461 | *val=in_8(pci->config_data + (offset&3)); |
---|
462 | return PCIBIOS_SUCCESSFUL; |
---|
463 | } |
---|
464 | |
---|
465 | static int |
---|
466 | indirect_pci_read_config_word(unsigned char bus, unsigned char dev_fn, |
---|
467 | unsigned char offset, unsigned short *val) { |
---|
468 | *val = 0xffff; |
---|
469 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
470 | out_be32(pci->config_addr, |
---|
471 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
472 | *val=in_le16((volatile u_short *)(pci->config_data + (offset&3))); |
---|
473 | return PCIBIOS_SUCCESSFUL; |
---|
474 | } |
---|
475 | |
---|
476 | static int |
---|
477 | indirect_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
478 | unsigned char offset, unsigned int *val) { |
---|
479 | *val = 0xffffffff; |
---|
480 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
481 | out_be32(pci->config_addr, |
---|
482 | 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24)); |
---|
483 | *val=in_le32((volatile u_int *)pci->config_data); |
---|
484 | return PCIBIOS_SUCCESSFUL; |
---|
485 | } |
---|
486 | |
---|
487 | static int |
---|
488 | indirect_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
489 | unsigned char offset, unsigned char val) { |
---|
490 | out_be32(pci->config_addr, |
---|
491 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
492 | out_8(pci->config_data + (offset&3), val); |
---|
493 | return PCIBIOS_SUCCESSFUL; |
---|
494 | } |
---|
495 | |
---|
496 | static int |
---|
497 | indirect_pci_write_config_word(unsigned char bus, unsigned char dev_fn, |
---|
498 | unsigned char offset, unsigned short val) { |
---|
499 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
500 | out_be32(pci->config_addr, |
---|
501 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
502 | out_le16((volatile u_short *)(pci->config_data + (offset&3)), val); |
---|
503 | return PCIBIOS_SUCCESSFUL; |
---|
504 | } |
---|
505 | |
---|
506 | static int |
---|
507 | indirect_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
508 | unsigned char offset, unsigned int val) { |
---|
509 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
510 | out_be32(pci->config_addr, |
---|
511 | 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24)); |
---|
512 | out_le32((volatile u_int *)pci->config_data, val); |
---|
513 | return PCIBIOS_SUCCESSFUL; |
---|
514 | } |
---|
515 | |
---|
516 | static const struct pci_config_access_functions indirect_functions = { |
---|
517 | indirect_pci_read_config_byte, |
---|
518 | indirect_pci_read_config_word, |
---|
519 | indirect_pci_read_config_dword, |
---|
520 | indirect_pci_write_config_byte, |
---|
521 | indirect_pci_write_config_word, |
---|
522 | indirect_pci_write_config_dword |
---|
523 | }; |
---|
524 | |
---|
525 | |
---|
526 | static int |
---|
527 | direct_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
528 | unsigned char offset, unsigned char *val) { |
---|
529 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
530 | *val=0xff; |
---|
531 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
532 | } |
---|
533 | *val=in_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
534 | + (PCI_FUNC(dev_fn)<<8) + offset); |
---|
535 | return PCIBIOS_SUCCESSFUL; |
---|
536 | } |
---|
537 | |
---|
538 | static int |
---|
539 | direct_pci_read_config_word(unsigned char bus, unsigned char dev_fn, |
---|
540 | unsigned char offset, unsigned short *val) { |
---|
541 | *val = 0xffff; |
---|
542 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
543 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
544 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
545 | } |
---|
546 | *val=in_le16((volatile u_short *) |
---|
547 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
548 | + (PCI_FUNC(dev_fn)<<8) + offset)); |
---|
549 | return PCIBIOS_SUCCESSFUL; |
---|
550 | } |
---|
551 | |
---|
552 | static int |
---|
553 | direct_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
554 | unsigned char offset, unsigned int *val) { |
---|
555 | *val = 0xffffffff; |
---|
556 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
557 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
558 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
559 | } |
---|
560 | *val=in_le32((volatile u_int *) |
---|
561 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
562 | + (PCI_FUNC(dev_fn)<<8) + offset)); |
---|
563 | return PCIBIOS_SUCCESSFUL; |
---|
564 | } |
---|
565 | |
---|
566 | static int |
---|
567 | direct_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
568 | unsigned char offset, unsigned char val) { |
---|
569 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
570 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
571 | } |
---|
572 | out_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
573 | + (PCI_FUNC(dev_fn)<<8) + offset, |
---|
574 | val); |
---|
575 | return PCIBIOS_SUCCESSFUL; |
---|
576 | } |
---|
577 | |
---|
578 | static int |
---|
579 | direct_pci_write_config_word(unsigned char bus, unsigned char dev_fn, |
---|
580 | unsigned char offset, unsigned short val) { |
---|
581 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
582 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
583 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
584 | } |
---|
585 | out_le16((volatile u_short *) |
---|
586 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
587 | + (PCI_FUNC(dev_fn)<<8) + offset), |
---|
588 | val); |
---|
589 | return PCIBIOS_SUCCESSFUL; |
---|
590 | } |
---|
591 | |
---|
592 | static int |
---|
593 | direct_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
594 | unsigned char offset, unsigned int val) { |
---|
595 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
596 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
597 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
598 | } |
---|
599 | out_le32((volatile u_int *) |
---|
600 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
601 | + (PCI_FUNC(dev_fn)<<8) + offset), |
---|
602 | val); |
---|
603 | return PCIBIOS_SUCCESSFUL; |
---|
604 | } |
---|
605 | |
---|
606 | static const struct pci_config_access_functions direct_functions = { |
---|
607 | direct_pci_read_config_byte, |
---|
608 | direct_pci_read_config_word, |
---|
609 | direct_pci_read_config_dword, |
---|
610 | direct_pci_write_config_byte, |
---|
611 | direct_pci_write_config_word, |
---|
612 | direct_pci_write_config_dword |
---|
613 | }; |
---|
614 | |
---|
615 | |
---|
616 | void pci_read_bases(struct pci_dev *dev, unsigned int howmany) |
---|
617 | { |
---|
618 | unsigned int reg, nextreg; |
---|
619 | #define REG (PCI_BASE_ADDRESS_0 + (reg<<2)) |
---|
620 | u_short cmd; |
---|
621 | u32 l, ml; |
---|
622 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
---|
623 | |
---|
624 | for(reg=0; reg<howmany; reg=nextreg) { |
---|
625 | pci_resource *r; |
---|
626 | nextreg=reg+1; |
---|
627 | pci_read_config_dword(dev, REG, &l); |
---|
628 | #if 0 |
---|
629 | if (l == 0xffffffff /*AJF || !l*/) continue; |
---|
630 | #endif |
---|
631 | /* Note that disabling the memory response of a host bridge |
---|
632 | * would lose data if a DMA transfer were in progress. In a |
---|
633 | * bootloader we don't care however. Also we can't print any |
---|
634 | * message for a while since we might just disable the console. |
---|
635 | */ |
---|
636 | pci_write_config_word(dev, PCI_COMMAND, cmd & |
---|
637 | ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)); |
---|
638 | pci_write_config_dword(dev, REG, ~0); |
---|
639 | pci_read_config_dword(dev, REG, &ml); |
---|
640 | pci_write_config_dword(dev, REG, l); |
---|
641 | |
---|
642 | /* Reenable the device now that we've played with |
---|
643 | * base registers. |
---|
644 | */ |
---|
645 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
---|
646 | |
---|
647 | /* seems to be an unused entry skip it */ |
---|
648 | if ( ml == 0 || ml == 0xffffffff ) continue; |
---|
649 | |
---|
650 | if ((l & |
---|
651 | (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) |
---|
652 | == (PCI_BASE_ADDRESS_MEM_TYPE_64 |
---|
653 | |PCI_BASE_ADDRESS_SPACE_MEMORY)) { |
---|
654 | nextreg=reg+2; |
---|
655 | } |
---|
656 | dev->base_address[reg] = l; |
---|
657 | r = salloc(sizeof(pci_resource)); |
---|
658 | if (!r) { |
---|
659 | printk("Error allocating pci_resource struct.\n"); |
---|
660 | continue; |
---|
661 | } |
---|
662 | r->dev = dev; |
---|
663 | r->reg = reg; |
---|
664 | if ((l&PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { |
---|
665 | r->type = l&~PCI_BASE_ADDRESS_IO_MASK; |
---|
666 | r->base = l&PCI_BASE_ADDRESS_IO_MASK; |
---|
667 | r->size = ~(ml&PCI_BASE_ADDRESS_IO_MASK)+1; |
---|
668 | } else { |
---|
669 | r->type = l&~PCI_BASE_ADDRESS_MEM_MASK; |
---|
670 | r->base = l&PCI_BASE_ADDRESS_MEM_MASK; |
---|
671 | r->size = ~(ml&PCI_BASE_ADDRESS_MEM_MASK)+1; |
---|
672 | } |
---|
673 | /* Check for the blacklisted entries */ |
---|
674 | insert_resource(r); |
---|
675 | } |
---|
676 | } |
---|
677 | |
---|
678 | |
---|
679 | |
---|
680 | |
---|
681 | u_int pci_scan_bus(struct pci_bus *bus) |
---|
682 | { |
---|
683 | unsigned int devfn, l, max, class; |
---|
684 | unsigned char irq, hdr_type, is_multi = 0; |
---|
685 | struct pci_dev *dev, **bus_last; |
---|
686 | struct pci_bus *child; |
---|
687 | |
---|
688 | bus_last = &bus->devices; |
---|
689 | max = bus->secondary; |
---|
690 | for (devfn = 0; devfn < 0xff; ++devfn) { |
---|
691 | if (PCI_FUNC(devfn) && !is_multi) { |
---|
692 | /* not a multi-function device */ |
---|
693 | continue; |
---|
694 | } |
---|
695 | if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type)) |
---|
696 | continue; |
---|
697 | if (!PCI_FUNC(devfn)) |
---|
698 | is_multi = hdr_type & 0x80; |
---|
699 | |
---|
700 | if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) || |
---|
701 | /* some broken boards return 0 if a slot is empty: */ |
---|
702 | l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) { |
---|
703 | is_multi = 0; |
---|
704 | continue; |
---|
705 | } |
---|
706 | |
---|
707 | dev = salloc(sizeof(*dev)); |
---|
708 | dev->bus = bus; |
---|
709 | dev->devfn = devfn; |
---|
710 | dev->vendor = l & 0xffff; |
---|
711 | dev->device = (l >> 16) & 0xffff; |
---|
712 | |
---|
713 | pcibios_read_config_dword(bus->number, devfn, |
---|
714 | PCI_CLASS_REVISION, &class); |
---|
715 | class >>= 8; /* upper 3 bytes */ |
---|
716 | dev->class = class; |
---|
717 | class >>= 8; |
---|
718 | dev->hdr_type = hdr_type; |
---|
719 | |
---|
720 | switch (hdr_type & 0x7f) { /* header type */ |
---|
721 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
---|
722 | if (class == PCI_CLASS_BRIDGE_PCI) |
---|
723 | goto bad; |
---|
724 | /* |
---|
725 | * If the card generates interrupts, read IRQ number |
---|
726 | * (some architectures change it during pcibios_fixup()) |
---|
727 | */ |
---|
728 | pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq); |
---|
729 | if (irq) |
---|
730 | pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); |
---|
731 | dev->irq = irq; |
---|
732 | /* |
---|
733 | * read base address registers, again pcibios_fixup() can |
---|
734 | * tweak these |
---|
735 | */ |
---|
736 | pci_read_bases(dev, 6); |
---|
737 | pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l); |
---|
738 | dev->rom_address = (l == 0xffffffff) ? 0 : l; |
---|
739 | break; |
---|
740 | case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ |
---|
741 | if (class != PCI_CLASS_BRIDGE_PCI) |
---|
742 | goto bad; |
---|
743 | pci_read_bases(dev, 2); |
---|
744 | pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l); |
---|
745 | dev->rom_address = (l == 0xffffffff) ? 0 : l; |
---|
746 | break; |
---|
747 | case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ |
---|
748 | if (class != PCI_CLASS_BRIDGE_CARDBUS) |
---|
749 | goto bad; |
---|
750 | pci_read_bases(dev, 1); |
---|
751 | break; |
---|
752 | default: /* unknown header */ |
---|
753 | bad: |
---|
754 | printk("PCI device with unknown " |
---|
755 | "header type %d ignored.\n", |
---|
756 | hdr_type&0x7f); |
---|
757 | continue; |
---|
758 | } |
---|
759 | |
---|
760 | /* |
---|
761 | * Put it into the global PCI device chain. It's used to |
---|
762 | * find devices once everything is set up. |
---|
763 | */ |
---|
764 | *pci->last_dev_p = dev; |
---|
765 | pci->last_dev_p = &dev->next; |
---|
766 | |
---|
767 | /* |
---|
768 | * Now insert it into the list of devices held |
---|
769 | * by the parent bus. |
---|
770 | */ |
---|
771 | *bus_last = dev; |
---|
772 | bus_last = &dev->sibling; |
---|
773 | |
---|
774 | } |
---|
775 | |
---|
776 | /* |
---|
777 | * After performing arch-dependent fixup of the bus, look behind |
---|
778 | * all PCI-to-PCI bridges on this bus. |
---|
779 | */ |
---|
780 | for(dev=bus->devices; dev; dev=dev->sibling) |
---|
781 | /* |
---|
782 | * If it's a bridge, scan the bus behind it. |
---|
783 | */ |
---|
784 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
---|
785 | unsigned int buses; |
---|
786 | unsigned int devfn = dev->devfn; |
---|
787 | unsigned short cr; |
---|
788 | |
---|
789 | /* |
---|
790 | * Insert it into the tree of buses. |
---|
791 | */ |
---|
792 | child = salloc(sizeof(*child)); |
---|
793 | child->next = bus->children; |
---|
794 | bus->children = child; |
---|
795 | child->self = dev; |
---|
796 | child->parent = bus; |
---|
797 | |
---|
798 | /* |
---|
799 | * Set up the primary, secondary and subordinate |
---|
800 | * bus numbers. |
---|
801 | */ |
---|
802 | child->number = child->secondary = ++max; |
---|
803 | child->primary = bus->secondary; |
---|
804 | child->subordinate = 0xff; |
---|
805 | /* |
---|
806 | * Clear all status bits and turn off memory, |
---|
807 | * I/O and master enables. |
---|
808 | */ |
---|
809 | pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); |
---|
810 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); |
---|
811 | pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); |
---|
812 | /* |
---|
813 | * Read the existing primary/secondary/subordinate bus |
---|
814 | * number configuration to determine if the PCI bridge |
---|
815 | * has already been configured by the system. If so, |
---|
816 | * do not modify the configuration, merely note it. |
---|
817 | */ |
---|
818 | pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); |
---|
819 | if ((buses & 0xFFFFFF) != 0) |
---|
820 | { |
---|
821 | unsigned int cmax; |
---|
822 | |
---|
823 | child->primary = buses & 0xFF; |
---|
824 | child->secondary = (buses >> 8) & 0xFF; |
---|
825 | child->subordinate = (buses >> 16) & 0xFF; |
---|
826 | child->number = child->secondary; |
---|
827 | cmax = pci_scan_bus(child); |
---|
828 | if (cmax > max) max = cmax; |
---|
829 | } |
---|
830 | else |
---|
831 | { |
---|
832 | /* |
---|
833 | * Configure the bus numbers for this bridge: |
---|
834 | */ |
---|
835 | buses &= 0xff000000; |
---|
836 | buses |= |
---|
837 | (((unsigned int)(child->primary) << 0) | |
---|
838 | ((unsigned int)(child->secondary) << 8) | |
---|
839 | ((unsigned int)(child->subordinate) << 16)); |
---|
840 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
---|
841 | /* |
---|
842 | * Now we can scan all subordinate buses: |
---|
843 | */ |
---|
844 | max = pci_scan_bus(child); |
---|
845 | /* |
---|
846 | * Set the subordinate bus number to its real |
---|
847 | * value: |
---|
848 | */ |
---|
849 | child->subordinate = max; |
---|
850 | buses = (buses & 0xff00ffff) |
---|
851 | | ((unsigned int)(child->subordinate) << 16); |
---|
852 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
---|
853 | } |
---|
854 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr); |
---|
855 | } |
---|
856 | |
---|
857 | /* |
---|
858 | * We've scanned the bus and so we know all about what's on |
---|
859 | * the other side of any bridges that may be on this bus plus |
---|
860 | * any devices. |
---|
861 | * |
---|
862 | * Return how far we've got finding sub-buses. |
---|
863 | */ |
---|
864 | return max; |
---|
865 | } |
---|
866 | |
---|
867 | void |
---|
868 | pci_fixup(void) { |
---|
869 | struct pci_dev *p; |
---|
870 | struct pci_bus *bus; |
---|
871 | for (bus = &pci_root; bus; bus=bus->next) { |
---|
872 | |
---|
873 | for (p=bus->devices; p; p=p->sibling) { |
---|
874 | } |
---|
875 | } |
---|
876 | } |
---|
877 | |
---|
878 | void pci_init(void) { |
---|
879 | PPC_DEVICE *hostbridge; |
---|
880 | |
---|
881 | if (pci->last_dev_p) { |
---|
882 | printk("Two or more calls to pci_init!\n"); |
---|
883 | return; |
---|
884 | } |
---|
885 | pci->last_dev_p = &(bd->pci_devices); |
---|
886 | hostbridge=residual_find_device(PROCESSORDEVICE, NULL, |
---|
887 | BridgeController, |
---|
888 | PCIBridge, -1, 0); |
---|
889 | if (hostbridge) { |
---|
890 | if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) { |
---|
891 | bd->pci_functions=&indirect_functions; |
---|
892 | /* Should be extracted from residual data, |
---|
893 | * indeed MPC106 in CHRP mode is different, |
---|
894 | * but we should not use residual data in |
---|
895 | * this case anyway. |
---|
896 | */ |
---|
897 | pci->config_addr = ((volatile u_int *) |
---|
898 | (ptr_mem_map->io_base+0xcf8)); |
---|
899 | pci->config_data = ptr_mem_map->io_base+0xcfc; |
---|
900 | } else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) { |
---|
901 | bd->pci_functions=&direct_functions; |
---|
902 | pci->config_data=(u_char *) 0x80800000; |
---|
903 | } else { |
---|
904 | } |
---|
905 | } else { |
---|
906 | /* Let us try by experimentation at our own risk! */ |
---|
907 | u_int id0; |
---|
908 | bd->pci_functions = &direct_functions; |
---|
909 | /* On all direct bridges I know the host bridge itself |
---|
910 | * appears as device 0 function 0. |
---|
911 | */ |
---|
912 | pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &id0); |
---|
913 | if (id0==~0U) { |
---|
914 | bd->pci_functions = &indirect_functions; |
---|
915 | pci->config_addr = ((volatile u_int *) |
---|
916 | (ptr_mem_map->io_base+0xcf8)); |
---|
917 | pci->config_data = ptr_mem_map->io_base+0xcfc; |
---|
918 | } |
---|
919 | /* Here we should check that the host bridge is actually |
---|
920 | * present, but if it not, we are in such a desperate |
---|
921 | * situation, that we probably can't even tell it. |
---|
922 | */ |
---|
923 | } |
---|
924 | /* Now build a small database of all found PCI devices */ |
---|
925 | printk("\nPCI: Probing PCI hardware\n"); |
---|
926 | pci_root.subordinate=pci_scan_bus(&pci_root); |
---|
927 | print_pci_resources("Configurable PCI resources:\n"); |
---|
928 | reconfigure_pci(); |
---|
929 | print_pci_resources("Allocated PCI resources:\n"); |
---|
930 | } |
---|
931 | |
---|