Rev 16 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | #include <ll/i386/hw-instr.h> |
2 | #include <ll/i386/hw-data.h> |
||
3 | #include <ll/i386/hw-arch.h> |
||
4 | #include <ll/i386/hw-io.h> |
||
5 | #include <ll/i386/cons.h> |
||
6 | #include <ll/i386/mem.h> |
||
7 | #include <ll/stdlib.h> |
||
8 | #include <drivers/llpci.h> |
||
9 | #include <drivers/pci.h> |
||
10 | #include <drivers/linuxpci.h> |
||
16 | pj | 11 | #include <kernel/log.h> |
2 | pj | 12 | |
16 | pj | 13 | //#define DEBUG_PCISCAN |
14 | |||
2 | pj | 15 | static struct pci_dev pci_devs[N_MAX_DEVS]; |
16 | |||
17 | static struct pci_bus pci_root; |
||
18 | static struct pci_dev *pci_devices = NULL; |
||
19 | |||
198 | pj | 20 | #if 0 |
2 | pj | 21 | /* scan the bus to find all the connected devices */ |
22 | DWORD pci_scan_bus(struct pci_bus *bus) |
||
23 | { |
||
24 | int ndev; |
||
25 | DWORD tmp; |
||
198 | pj | 26 | DWORD max, class; |
27 | BYTE hdr; |
||
28 | int ok; |
||
29 | WORD dev; |
||
30 | struct pci_dev **bus_last; |
||
31 | struct pci_dev *device = NULL; |
||
32 | int present; |
||
33 | |||
34 | max = bus->secondary; |
||
35 | bus_last = &bus->devices; |
||
36 | |||
37 | if (pcibios_present() == 0) return -1; |
||
38 | ndev = 0; |
||
39 | |||
40 | for (dev = 0; dev <= 0xFF; dev++) { |
||
41 | present = 0; |
||
42 | if ((dev & 0x07) == 0) { |
||
43 | present = pcibios_read_config_byte(bus->number, dev, 0x0e, &hdr); |
||
44 | } |
||
45 | if (hdr & 0x80) { |
||
46 | present = 1; |
||
47 | } |
||
48 | if (present) { |
||
49 | ok = pcibios_read_config_dword(bus->number, dev, 0, &tmp); |
||
50 | if ( ok && (((tmp & 0xFFFF) != 0xFFFF) && ((tmp >> 16) != 0xFFFF))) { |
||
51 | /* Got a PCI Device!!! */ |
||
52 | device = &(pci_devs[ndev++]); |
||
53 | device->bus = bus; |
||
54 | device->devfn = dev; |
||
55 | device->vendor = tmp & 0xffff; |
||
56 | device->device = (tmp >> 16) & 0xffff; |
||
57 | |||
58 | /* PJ: non-destructively determine if device can be a master: */ |
||
59 | pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &cmd); |
||
60 | pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); |
||
61 | pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &tmp); |
||
62 | dev->master = ((tmp & PCI_COMMAND_MASTER) != 0); |
||
63 | pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd); |
||
64 | |||
65 | /* This is by Luca... We need to set base_addr */ |
||
66 | pcibios_read_config_dword(bus->number, dev, PCI_BASE_ADDRESS_0, &(device->base_address[0])); |
||
67 | |||
68 | |||
69 | |||
70 | pcibios_read_config_byte(bus->number, dev, PCI_INTERRUPT_LINE, &irq1); |
||
71 | device->irq = irq1; |
||
72 | |||
73 | pcibios_read_config_dword(bus->number, dev, PCI_CLASS_REVISION, &class); |
||
74 | class >>= 8; /* upper 3 bytes */ |
||
75 | //printk(KERN_INFO "pci_scan_bus: dev=%d, class=%ld", dev, class); |
||
76 | device->class = class; |
||
77 | class >>= 8; |
||
78 | device->hdr_type = hdr; |
||
79 | |||
80 | |||
81 | |||
82 | |||
83 | #if 0 |
||
84 | switch (hdr & 0x7f) { /* header type */ |
||
85 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
||
86 | if (class == PCI_CLASS_BRIDGE_PCI) |
||
87 | goto bad; |
||
88 | /* |
||
89 | * If the card generates interrupts, read IRQ number |
||
90 | * (some architectures change it during pcibios_fixup()) |
||
91 | */ |
||
92 | pcibios_read_config_byte(bus->number, device->devfn, PCI_INTERRUPT_PIN, &irq1); |
||
93 | if (irq1) |
||
94 | pcibios_read_config_byte(bus->number, device->devfn, PCI_INTERRUPT_LINE, &irq1); |
||
95 | device->irq = irq1; |
||
96 | /* |
||
97 | * read base address registers, again pcibios_fixup() can |
||
98 | * tweak these |
||
99 | */ |
||
100 | pci_read_bases(device, 6); |
||
101 | pcibios_read_config_dword(bus->number, dev, PCI_ROM_ADDRESS, &l); |
||
102 | device->rom_address = (l == 0xffffffff) ? 0 : l; |
||
103 | break; |
||
104 | case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ |
||
105 | if (class != PCI_CLASS_BRIDGE_PCI) |
||
106 | goto bad; |
||
107 | pci_read_bases(device, 2); |
||
108 | pcibios_read_config_dword(bus->number, dev, PCI_ROM_ADDRESS1, &l); |
||
109 | device->rom_address = (l == 0xffffffff) ? 0 : l; |
||
110 | break; |
||
111 | case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ |
||
112 | if (class != PCI_CLASS_BRIDGE_CARDBUS) |
||
113 | goto bad; |
||
114 | pci_read_bases(device, 1); |
||
115 | break; |
||
116 | default: /* unknown header */ |
||
117 | bad: |
||
118 | printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n", |
||
119 | bus->number, device->devfn, device->vendor, device->device, class, hdr); |
||
120 | continue; |
||
121 | } |
||
122 | #endif |
||
123 | |||
124 | |||
125 | |||
126 | |||
127 | //printk(KERN_DEBUG "PCI: %02x:%02x [%04x/%04x]\n", bus->number, device->devfn, device->vendor, device->device); |
||
128 | |||
129 | device->next = pci_devices; |
||
130 | pci_devices = device; |
||
131 | |||
132 | /* |
||
133 | * Now insert it into the list of devices held |
||
134 | * by the parent bus. |
||
135 | */ |
||
136 | *bus_last = device; |
||
137 | bus_last = &device->sibling; |
||
138 | |||
139 | |||
140 | |||
141 | } |
||
142 | } |
||
143 | } |
||
144 | |||
145 | // PJ: PCI bridges not supported??? |
||
146 | #if 0 |
||
147 | for(device = bus->devices; device; device = device->sibling) { |
||
148 | /* |
||
149 | * If it's a bridge, scan the bus behind it. |
||
150 | */ |
||
151 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
||
152 | unsigned int buses; |
||
153 | unsigned int devfn = dev->devfn; |
||
154 | unsigned short cr; |
||
155 | |||
156 | /* |
||
157 | * Insert it into the tree of buses. |
||
158 | */ |
||
159 | child = kmalloc(sizeof(*child), GFP_ATOMIC); |
||
160 | if(child==NULL) { |
||
161 | #ifdef DEBUG_PCISCAN |
||
162 | printk(KERN_ERR "pci: out of memory for bridge.\n"); |
||
163 | #endif |
||
164 | continue; |
||
165 | } |
||
166 | memset(child, 0, sizeof(*child)); |
||
167 | child->next = bus->children; |
||
168 | bus->children = child; |
||
169 | child->self = dev; |
||
170 | child->parent = bus; |
||
171 | |||
172 | /* |
||
173 | * Set up the primary, secondary and subordinate |
||
174 | * bus numbers. |
||
175 | */ |
||
176 | child->number = child->secondary = ++max; |
||
177 | child->primary = bus->secondary; |
||
178 | child->subordinate = 0xff; |
||
179 | /* |
||
180 | * Clear all status bits and turn off memory, |
||
181 | * I/O and master enables. |
||
182 | */ |
||
183 | pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); |
||
184 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); |
||
185 | pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); |
||
186 | /* |
||
187 | * Read the existing primary/secondary/subordinate bus |
||
188 | * number configuration to determine if the PCI bridge |
||
189 | * has already been configured by the system. If so, |
||
190 | * do not modify the configuration, merely note it. |
||
191 | */ |
||
192 | pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); |
||
193 | if ((buses & 0xFFFFFF) != 0) { |
||
194 | unsigned int cmax; |
||
195 | |||
196 | child->primary = buses & 0xFF; |
||
197 | child->secondary = (buses >> 8) & 0xFF; |
||
198 | child->subordinate = (buses >> 16) & 0xFF; |
||
199 | child->number = child->secondary; |
||
200 | cmax = pci_scan_bus(child); |
||
201 | if (cmax > max) max = cmax; |
||
202 | } else { |
||
203 | /* |
||
204 | * Configure the bus numbers for this bridge: |
||
205 | */ |
||
206 | buses &= 0xff000000; |
||
207 | buses |= (((unsigned int)(child->primary) << 0) | |
||
208 | ((unsigned int)(child->secondary) << 8) | |
||
209 | ((unsigned int)(child->subordinate) << 16)); |
||
210 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
||
211 | /* |
||
212 | * Now we can scan all subordinate buses: |
||
213 | */ |
||
214 | max = pci_scan_bus(child); |
||
215 | /* |
||
216 | * Set the subordinate bus number to its real |
||
217 | * value: |
||
218 | */ |
||
219 | child->subordinate = max; |
||
220 | buses = (buses & 0xff00ffff) |
||
221 | | ((unsigned int)(child->subordinate) << 16); |
||
222 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
||
223 | } |
||
224 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr); |
||
225 | } |
||
226 | } |
||
227 | #endif |
||
228 | |||
229 | return max; |
||
230 | } |
||
231 | |||
232 | |||
233 | #endif |
||
234 | |||
235 | |||
236 | |||
237 | |||
238 | |||
239 | |||
240 | |||
241 | |||
242 | |||
243 | |||
244 | |||
245 | |||
246 | |||
247 | |||
248 | |||
249 | |||
250 | |||
251 | |||
252 | |||
253 | |||
254 | |||
255 | |||
256 | |||
257 | |||
258 | |||
259 | |||
260 | |||
261 | |||
262 | |||
263 | |||
264 | |||
265 | |||
266 | |||
267 | |||
268 | |||
269 | |||
270 | |||
271 | |||
272 | |||
273 | /* scan the bus to find all the connected devices */ |
||
274 | DWORD pci_scan_bus(struct pci_bus *bus) |
||
275 | { |
||
276 | int ndev; |
||
277 | DWORD tmp; |
||
278 | DWORD max, class; |
||
2 | pj | 279 | BYTE hdr, irq1; |
280 | int ok; |
||
281 | WORD dev; |
||
282 | struct pci_dev **bus_last; |
||
283 | struct pci_dev *device = NULL; |
||
284 | int present; |
||
285 | |||
286 | max = bus->secondary; |
||
287 | bus_last = &bus->devices; |
||
288 | |||
289 | if (pcibios_present() == 0) return -1; |
||
290 | ndev = 0; |
||
291 | |||
292 | for (dev = 0; dev <= 0xFF; dev++) { |
||
293 | present = 0; |
||
294 | if ((dev & 0x07) == 0) { |
||
295 | present = pcibios_read_config_byte(bus->number, dev, 0x0e, &hdr); |
||
296 | } |
||
297 | if (hdr & 0x80) { |
||
298 | present = 1; |
||
299 | } |
||
300 | if (present) { |
||
301 | ok = pcibios_read_config_dword(bus->number, dev, 0, &tmp); |
||
302 | if ( ok && (((tmp & 0xFFFF) != 0xFFFF) && ((tmp >> 16) != 0xFFFF))) { |
||
303 | /* Got a PCI Device!!! */ |
||
304 | device = &(pci_devs[ndev++]); |
||
305 | device->bus = bus; |
||
306 | device->devfn = dev; |
||
307 | device->vendor = tmp & 0xffff; |
||
308 | device->device = (tmp >> 16) & 0xffff; |
||
309 | |||
310 | |||
311 | /* This is by Luca... We need to set base_addr */ |
||
312 | pcibios_read_config_dword(bus->number, dev, PCI_BASE_ADDRESS_0, &(device->base_address[0])); |
||
313 | |||
314 | |||
315 | /* ...and also the interrupt number!!! */ |
||
316 | pcibios_read_config_byte(bus->number, dev, PCI_INTERRUPT_LINE, &irq1); |
||
317 | device->irq = irq1; |
||
318 | |||
198 | pj | 319 | pcibios_read_config_dword(bus->number, dev, PCI_CLASS_REVISION, &class); |
2 | pj | 320 | class >>= 8; /* upper 3 bytes */ |
198 | pj | 321 | device->class = class; |
2 | pj | 322 | class >>= 8; |
198 | pj | 323 | device->hdr_type = hdr; |
2 | pj | 324 | |
198 | pj | 325 | #if 0 |
2 | pj | 326 | switch (hdr_type & 0x7f) { /* header type */ |
327 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
||
328 | if (class == PCI_CLASS_BRIDGE_PCI) |
||
329 | goto bad; |
||
330 | /* |
||
331 | * If the card generates interrupts, read IRQ number |
||
332 | * (some architectures change it during pcibios_fixup()) |
||
333 | */ |
||
334 | pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq); |
||
335 | if (irq) |
||
336 | pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); |
||
337 | dev->irq = irq; |
||
338 | /* |
||
339 | * read base address registers, again pcibios_fixup() can |
||
340 | * tweak these |
||
341 | */ |
||
342 | pci_read_bases(dev, 6); |
||
343 | pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l); |
||
344 | dev->rom_address = (l == 0xffffffff) ? 0 : l; |
||
345 | break; |
||
346 | case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ |
||
347 | if (class != PCI_CLASS_BRIDGE_PCI) |
||
348 | goto bad; |
||
349 | pci_read_bases(dev, 2); |
||
350 | pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l); |
||
351 | dev->rom_address = (l == 0xffffffff) ? 0 : l; |
||
352 | break; |
||
353 | case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ |
||
354 | if (class != PCI_CLASS_BRIDGE_CARDBUS) |
||
355 | goto bad; |
||
356 | pci_read_bases(dev, 1); |
||
357 | break; |
||
358 | default: /* unknown header */ |
||
359 | bad: |
||
360 | printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n", |
||
361 | bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type); |
||
362 | continue; |
||
363 | } |
||
364 | |||
365 | DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device); |
||
366 | #endif |
||
367 | |||
368 | device->next = pci_devices; |
||
369 | pci_devices = device; |
||
370 | |||
371 | /* |
||
372 | * Now insert it into the list of devices held |
||
373 | * by the parent bus. |
||
374 | */ |
||
375 | *bus_last = device; |
||
376 | bus_last = &device->sibling; |
||
377 | |||
378 | |||
379 | |||
380 | } |
||
381 | } |
||
382 | } |
||
383 | |||
384 | |||
385 | for(device = bus->devices; device; device = device->sibling) { |
||
386 | #if 0 |
||
387 | /* |
||
388 | * If it's a bridge, scan the bus behind it. |
||
389 | */ |
||
390 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
||
391 | unsigned int buses; |
||
392 | unsigned int devfn = dev->devfn; |
||
393 | unsigned short cr; |
||
394 | |||
395 | /* |
||
396 | * Insert it into the tree of buses. |
||
397 | */ |
||
398 | child = kmalloc(sizeof(*child), GFP_ATOMIC); |
||
399 | if(child==NULL) { |
||
16 | pj | 400 | #ifdef DEBUG_PCISCAN |
401 | printk(KERN_ERR "pci: out of memory for bridge.\n"); |
||
402 | #endif |
||
2 | pj | 403 | continue; |
404 | } |
||
405 | memset(child, 0, sizeof(*child)); |
||
406 | child->next = bus->children; |
||
407 | bus->children = child; |
||
408 | child->self = dev; |
||
409 | child->parent = bus; |
||
410 | |||
411 | /* |
||
412 | * Set up the primary, secondary and subordinate |
||
413 | * bus numbers. |
||
414 | */ |
||
415 | child->number = child->secondary = ++max; |
||
416 | child->primary = bus->secondary; |
||
417 | child->subordinate = 0xff; |
||
418 | /* |
||
419 | * Clear all status bits and turn off memory, |
||
420 | * I/O and master enables. |
||
421 | */ |
||
422 | pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); |
||
423 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); |
||
424 | pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); |
||
425 | /* |
||
426 | * Read the existing primary/secondary/subordinate bus |
||
427 | * number configuration to determine if the PCI bridge |
||
428 | * has already been configured by the system. If so, |
||
429 | * do not modify the configuration, merely note it. |
||
430 | */ |
||
431 | pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); |
||
432 | if ((buses & 0xFFFFFF) != 0) { |
||
433 | unsigned int cmax; |
||
434 | |||
435 | child->primary = buses & 0xFF; |
||
436 | child->secondary = (buses >> 8) & 0xFF; |
||
437 | child->subordinate = (buses >> 16) & 0xFF; |
||
438 | child->number = child->secondary; |
||
439 | cmax = pci_scan_bus(child); |
||
440 | if (cmax > max) max = cmax; |
||
441 | } else { |
||
442 | /* |
||
443 | * Configure the bus numbers for this bridge: |
||
444 | */ |
||
445 | buses &= 0xff000000; |
||
446 | buses |= (((unsigned int)(child->primary) << 0) | |
||
447 | ((unsigned int)(child->secondary) << 8) | |
||
448 | ((unsigned int)(child->subordinate) << 16)); |
||
449 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
||
450 | /* |
||
451 | * Now we can scan all subordinate buses: |
||
452 | */ |
||
453 | max = pci_scan_bus(child); |
||
454 | /* |
||
455 | * Set the subordinate bus number to its real |
||
456 | * value: |
||
457 | */ |
||
458 | child->subordinate = max; |
||
459 | buses = (buses & 0xff00ffff) |
||
460 | | ((unsigned int)(child->subordinate) << 16); |
||
461 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
||
462 | } |
||
463 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr); |
||
464 | } |
||
465 | #endif |
||
466 | } |
||
467 | |||
468 | return max; |
||
469 | } |
||
470 | |||
471 | |||
472 | void linuxpci_init(void) |
||
473 | { |
||
474 | pcibios_init(); |
||
475 | |||
476 | if (!pci_present()) { |
||
16 | pj | 477 | #ifdef DEBUG_PCISCAN |
478 | printk("PCI: No PCI bus detected\n"); |
||
479 | #endif |
||
2 | pj | 480 | return; |
481 | } |
||
482 | |||
16 | pj | 483 | #ifdef DEBUG_PCISCAN |
484 | printk("PCI: Probing PCI hardware\n"); |
||
485 | #endif |
||
2 | pj | 486 | memset(&pci_root, 0, sizeof(pci_root)); |
487 | pci_root.subordinate = pci_scan_bus(&pci_root); |
||
488 | } |
||
489 | |||
490 | struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from) |
||
491 | { |
||
492 | if (!from) |
||
493 | from = pci_devices; |
||
494 | else |
||
495 | from = from->next; |
||
496 | while (from && (from->vendor != vendor || from->device != device)) |
||
497 | from = from->next; |
||
498 | return from; |
||
499 | } |
||
500 | |||
501 | struct pci_dev *pci_find_class(unsigned int class, struct pci_dev *from) |
||
502 | { |
||
503 | if (!from) |
||
504 | from = pci_devices; |
||
505 | else |
||
506 | from = from->next; |
||
507 | while (from && from->class != class) |
||
508 | from = from->next; |
||
509 | |||
510 | cprintf("PCI_FIND_CLASS: found %p at bus %d\n", from, from->bus->number); |
||
511 | return from; |
||
512 | } |
||
513 | |||
514 | struct pci_dev * |
||
515 | pci_find_slot(unsigned int bus, unsigned int devfn) |
||
516 | { |
||
517 | struct pci_dev *dev; |
||
518 | |||
519 | for(dev=pci_devices; dev; dev=dev->next) |
||
520 | if (dev->bus->number == bus && dev->devfn == devfn) { |
||
521 | cprintf("FOUND!!!!!!!!!!\n"); |
||
522 | break; |
||
523 | } else { |
||
524 | cprintf("NOT FOUND! %d!=%d %d!=%d\n", dev->bus->number, bus, dev->devfn, devfn); |
||
525 | } |
||
526 | cprintf("PCI_FIND_SLOT: found %p at bus %d\n", dev, dev->bus->number); |
||
527 | return dev; |
||
528 | } |
||
198 | pj | 529 | |
530 | |||
531 | void |
||
532 | pci_set_master(struct pci_dev *dev) |
||
533 | { |
||
534 | unsigned short cmd; // was: u16 |
||
535 | unsigned char lat; // was: u8 |
||
536 | |||
537 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
||
538 | if (! (cmd & PCI_COMMAND_MASTER)) { |
||
539 | printk("PCI: Enabling bus mastering for device %02x:%02x\n", |
||
540 | dev->bus->number, dev->devfn); |
||
541 | cmd |= PCI_COMMAND_MASTER; |
||
542 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
||
543 | } |
||
544 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); |
||
545 | if (lat < 16) { |
||
546 | printk("PCI: Increasing latency timer of device %02x:%02x to 64\n", |
||
547 | dev->bus->number, dev->devfn); |
||
548 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); |
||
549 | } |
||
550 | } |