Import of openhackware-0.4.1
[openhackware.git] / src / pci.c
blob10e6eb32625a12775d479fd884e0c537f31785ec
1 /* PCI BIOS.
3 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License V2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include "bios.h"
23 //#define DEBUG_PCI 1
25 #if defined (DEBUG_PCI)
26 #define PCI_DPRINTF(fmt, args...) \
27 do { dprintf("PCI %s: " fmt, __func__ , ##args); } while (0)
28 #else
29 #define PCI_DPRINTF(fmt, args...) \
30 do { } while (0)
31 #endif
33 /* On PMAC, there are four kind of PCI bridges:
34 * - uninorth, for all recent machines (all Core99 and more).
35 * - chaos : buggy bandit like
36 * - grackle, for powerbook 1998 & some powermac G3
37 * - bandit : some early PCI powermacs.
38 * For now, only uninorth will be supported, as other ones are deprecated.
41 enum {
42 /* Fake devices */
43 PCI_FAKE_HOST = 0x00000001,
44 PCI_FAKE_BRIDGE = 0x00000002,
45 /* Device found during PCI probe */
46 PCI_HOST_BRIDGE = 0x00000003,
47 PCI_DEV_BRIDGE = 0x00000004,
48 PCI_DEVICE = 0x00000005,
51 enum {
52 BRIDGE_TYPE_UNINORTH = 0x0001,
55 /* PCI devices database */
56 typedef struct pci_class_t pci_class_t;
57 typedef struct pci_subclass_t pci_subclass_t;
58 typedef struct pci_iface_t pci_iface_t;
60 struct pci_iface_t {
61 uint8_t iface;
62 const unsigned char *name;
63 const unsigned char *type;
64 const pci_dev_t *devices;
65 int (*config_cb)(pci_device_t *device);
66 const void *private;
69 struct pci_subclass_t {
70 uint8_t subclass;
71 const unsigned char *name;
72 const unsigned char *type;
73 const pci_dev_t *devices;
74 const pci_iface_t *iface;
75 int (*config_cb)(pci_device_t *device);
76 const void *private;
79 struct pci_class_t {
80 const unsigned char *name;
81 const unsigned char *type;
82 const pci_subclass_t *subc;
85 /* PCI devices tree */
86 struct pci_common_t {
87 int type;
88 const pci_dev_t *device;
89 const pci_u_t *parent;
90 void *OF_private;
93 struct pci_device_t {
94 pci_common_t common;
95 uint8_t bus;
96 uint8_t devfn;
97 uint16_t rev;
98 uint32_t class_code;
99 uint16_t min_grant;
100 uint16_t max_latency;
101 uint8_t irq_line;
102 uint32_t regions[6];
103 uint32_t sizes[6];
104 pci_device_t *next;
107 struct pci_host_t {
108 pci_device_t dev;
109 pci_bridge_t *bridge;
110 pci_host_t *next;
113 struct pci_bridge_t {
114 pci_device_t dev;
115 uint32_t cfg_base;
116 uint32_t cfg_len;
117 uint32_t io_base;
118 uint32_t io_len;
119 uint32_t io_cur;
120 uint32_t mem_base;
121 uint32_t mem_len;
122 uint32_t mem_cur;
123 uint32_t rbase;
124 uint32_t rlen;
125 uint32_t cfg_addr;
126 uint32_t cfg_data;
127 uint32_t flags;
128 const pci_ops_t *ops;
129 pci_device_t *devices;
130 pci_bridge_t *next;
133 union pci_u_t {
134 pci_common_t common;
135 pci_host_t host;
136 pci_device_t device;
137 pci_bridge_t bridge;
140 /* Low level access helpers */
141 struct pci_ops_t {
142 uint8_t (*config_readb)(pci_bridge_t *bridge,
143 uint8_t bus, uint8_t devfn, uint8_t offset);
144 void (*config_writeb)(pci_bridge_t *bridge,
145 uint8_t bus, uint8_t devfn,
146 uint8_t offset, uint8_t val);
147 uint16_t (*config_readw)(pci_bridge_t *bridge,
148 uint8_t bus, uint8_t devfn, uint8_t offset);
149 void (*config_writew)(pci_bridge_t *bridge,
150 uint8_t bus, uint8_t devfn,
151 uint8_t offset, uint16_t val);
152 uint32_t (*config_readl)(pci_bridge_t *bridge,
153 uint8_t bus, uint8_t devfn, uint8_t offset);
154 void (*config_writel)(pci_bridge_t *bridge,
155 uint8_t bus, uint8_t devfn,
156 uint8_t offset, uint32_t val);
159 /* IRQ numbers assigned to PCI IRQs */
160 static uint8_t prep_pci_irqs[4] = { 9, 11, 9, 11 };
161 static uint8_t pmac_pci_irqs[4] = { 8, 9, 10, 11 };
163 /* PREP PCI host */
164 static inline uint32_t PREP_cfg_addr (pci_bridge_t *bridge, unused uint8_t bus,
165 uint8_t devfn, uint8_t offset)
167 #if 0
168 printf("Translate %0x %0x %d %x %x => %0x",
169 bridge->cfg_addr, bridge->cfg_data, bus, devfn, offset,
170 bridge->cfg_addr |
171 (1 << (devfn >> 3)) | ((devfn & 7) << 8) | offset);
172 #endif
173 return bridge->cfg_addr |
174 (1 << (devfn >> 3)) | ((devfn & 7) << 8) | offset;
177 static uint8_t PREP_config_readb (pci_bridge_t *bridge,
178 uint8_t bus, uint8_t devfn,
179 uint8_t offset)
181 uint32_t addr;
183 if (bus != 0 || (devfn >> 3) < 11 || (devfn >> 3) > 21)
184 return 0xFF;
185 addr = PREP_cfg_addr(bridge, bus, devfn, offset);
187 return *((uint8_t *)addr);
190 static void PREP_config_writeb (pci_bridge_t *bridge,
191 uint8_t bus, uint8_t devfn,
192 uint8_t offset, uint8_t val)
194 uint32_t addr;
196 if (bus != 0 || (devfn >> 3) < 11 || (devfn >> 3) > 21)
197 return;
198 addr = PREP_cfg_addr(bridge, bus, devfn, offset);
199 *((uint8_t *)addr) = val;
202 static uint16_t PREP_config_readw (pci_bridge_t *bridge,
203 uint8_t bus, uint8_t devfn,
204 uint8_t offset)
206 uint32_t addr;
208 if (bus != 0 || (devfn >> 3) < 11 || (devfn >> 3) > 21)
209 return 0xFFFF;
210 addr = PREP_cfg_addr(bridge, bus, devfn, offset);
212 return ldswap16((uint16_t *)addr);
215 static void PREP_config_writew (pci_bridge_t *bridge,
216 uint8_t bus, uint8_t devfn,
217 uint8_t offset, uint16_t val)
219 uint32_t addr;
221 if (bus != 0 || (devfn >> 3) < 11 || (devfn >> 3) > 21)
222 return;
223 addr = PREP_cfg_addr(bridge, bus, devfn, offset);
224 stswap16((uint16_t *)addr, val);
227 static uint32_t PREP_config_readl (pci_bridge_t *bridge,
228 uint8_t bus, uint8_t devfn,
229 uint8_t offset)
231 uint32_t addr;
233 if (bus != 0 || (devfn >> 3) < 11 || (devfn >> 3) > 21)
234 return 0xFFFFFFFF;
235 addr = PREP_cfg_addr(bridge, bus, devfn, offset);
237 return ldswap32((uint32_t *)addr);
240 static void PREP_config_writel (pci_bridge_t *bridge,
241 uint8_t bus, uint8_t devfn,
242 uint8_t offset, uint32_t val)
244 uint32_t addr;
246 if (bus != 0 || (devfn >> 3) < 11 || (devfn >> 3) > 21)
247 return;
248 addr = PREP_cfg_addr(bridge, bus, devfn, offset);
249 stswap32((uint32_t *)addr, val);
252 static pci_ops_t PREP_pci_ops = {
253 &PREP_config_readb, &PREP_config_writeb,
254 &PREP_config_readw, &PREP_config_writew,
255 &PREP_config_readl, &PREP_config_writel,
258 /* Uninorth PCI host */
259 static uint32_t macrisc_cfg_address (pci_bridge_t *bridge,
260 uint8_t bus, uint8_t devfn,
261 uint8_t offset)
263 uint32_t addr;
264 int i;
266 /* Kind of magic... */
267 if (bridge->cfg_base == 0xF2000000) {
268 if (bus != 0) {
269 #if 0
270 printf("Skip bus: %d dev: %x offset: %x\n", bus, devfn, offset);
271 #endif
272 return -1;
274 addr = (1 << (devfn >> 3));
275 } else {
276 addr = (bus << 16) | ((devfn & 0xF8) << 8) | 0x01;
278 addr |= ((devfn & 0x07) << 8) | (offset & 0xFC);
279 /* Avoid looping forever */
280 #if 0
281 printf("Translate %0x %0x %d %x %x => %0x",
282 bridge->cfg_addr, bridge->cfg_data, bus, devfn, offset, addr);
283 #endif
284 for (i = 0; i < 100; i++) {
285 stswap32((uint32_t *)bridge->cfg_addr, addr);
286 eieio();
287 if (ldswap32((uint32_t *)bridge->cfg_addr) == addr)
288 break;
290 if (i == 100) {
291 #if 1
292 printf("Translate %0x %0x %d %x %x => %0x",
293 bridge->cfg_addr, bridge->cfg_data, bus, devfn, offset, addr);
294 printf("\nTimeout accessing PCI bridge cfg address\n");
295 #endif
296 return -1;
298 if (bridge->flags & BRIDGE_TYPE_UNINORTH)
299 offset &= 0x07;
300 else
301 offset &= 0x03;
302 #if 0
303 printf(" %0x\n", bridge->cfg_data + offset);
304 #endif
306 return bridge->cfg_data + offset;
309 static uint8_t uninorth_config_readb (pci_bridge_t *bridge,
310 uint8_t bus, uint8_t devfn,
311 uint8_t offset)
313 uint32_t addr;
315 if (bridge->cfg_base == 0xF2000000 && (devfn >> 3) < 11)
316 return 0xFF;
317 addr = macrisc_cfg_address(bridge, bus, devfn, offset);
318 if (addr == (uint32_t)(-1))
319 return 0xFF;
321 return *((uint8_t *)addr);
324 static void uninorth_config_writeb (pci_bridge_t *bridge,
325 uint8_t bus, uint8_t devfn,
326 uint8_t offset, uint8_t val)
328 uint32_t addr;
330 if (bridge->cfg_base == 0xF2000000 && (devfn >> 3) < 11)
331 return;
332 addr = macrisc_cfg_address(bridge, bus, devfn, offset);
333 if (addr != (uint32_t)(-1))
334 *((uint8_t *)addr) = val;
337 static uint16_t uninorth_config_readw (pci_bridge_t *bridge,
338 uint8_t bus, uint8_t devfn,
339 uint8_t offset)
341 uint32_t addr;
343 if (bridge->cfg_base == 0xF2000000 && (devfn >> 3) < 11)
344 return 0xFFFF;
345 addr = macrisc_cfg_address(bridge, bus, devfn, offset);
346 if (addr == (uint32_t)(-1))
347 return 0xFFFF;
349 return ldswap16((uint16_t *)addr);
352 static void uninorth_config_writew (pci_bridge_t *bridge,
353 uint8_t bus, uint8_t devfn,
354 uint8_t offset, uint16_t val)
356 uint32_t addr;
358 if (bridge->cfg_base == 0xF2000000 && (devfn >> 3) < 11)
359 return;
360 addr = macrisc_cfg_address(bridge, bus, devfn, offset);
361 if (addr != (uint32_t)(-1))
362 stswap16((uint16_t *)addr, val);
365 static uint32_t uninorth_config_readl (pci_bridge_t *bridge,
366 uint8_t bus, uint8_t devfn,
367 uint8_t offset)
369 uint32_t addr;
371 if (bridge->cfg_base == 0xF2000000 && (devfn >> 3) < 11)
372 return 0xFFFFFFFF;
373 addr = macrisc_cfg_address(bridge, bus, devfn, offset);
374 if (addr == (uint32_t)(-1)) {
375 // printf("bad address -1\n");
376 return 0xFFFFFFFF;
378 // printf("%s: addr=%0x\n", __func__, addr);
380 return ldswap32((uint32_t *)addr);
383 static void uninorth_config_writel (pci_bridge_t *bridge,
384 uint8_t bus, uint8_t devfn,
385 uint8_t offset, uint32_t val)
387 uint32_t addr;
389 if (bridge->cfg_base == 0xF2000000 && (devfn >> 3) < 11)
390 return;
391 addr = macrisc_cfg_address(bridge, bus, devfn, offset);
392 if (addr != (uint32_t)(-1))
393 stswap32((uint32_t *)addr, val);
396 static pci_ops_t uninorth_pci_ops = {
397 &uninorth_config_readb, &uninorth_config_writeb,
398 &uninorth_config_readw, &uninorth_config_writew,
399 &uninorth_config_readl, &uninorth_config_writel,
402 static inline uint8_t pci_config_readb (pci_bridge_t *bridge,
403 uint8_t bus, uint8_t devfn,
404 uint8_t offset)
406 return (*bridge->ops->config_readb)(bridge, bus, devfn, offset);
409 static inline void pci_config_writeb (pci_bridge_t *bridge,
410 uint8_t bus, uint8_t devfn,
411 uint8_t offset, uint8_t val)
413 (*bridge->ops->config_writeb)(bridge, bus, devfn, offset, val);
416 static inline uint16_t pci_config_readw (pci_bridge_t *bridge,
417 uint8_t bus, uint8_t devfn,
418 uint8_t offset)
420 return (*bridge->ops->config_readw)(bridge, bus, devfn, offset);
423 static inline void pci_config_writew (pci_bridge_t *bridge,
424 uint8_t bus, uint8_t devfn,
425 uint8_t offset, uint16_t val)
427 (*bridge->ops->config_writew)(bridge, bus, devfn, offset, val);
430 static inline uint32_t pci_config_readl (pci_bridge_t *bridge,
431 uint8_t bus, uint8_t devfn,
432 uint8_t offset)
434 return (*bridge->ops->config_readl)(bridge, bus, devfn, offset);
438 static inline void pci_config_writel (pci_bridge_t *bridge,
439 uint8_t bus, uint8_t devfn,
440 uint8_t offset, uint32_t val)
442 (*bridge->ops->config_writel)(bridge, bus, devfn, offset, val);
445 unused static void *get_parent_OF_private (pci_device_t *device)
447 const pci_u_t *u;
449 for (u = (pci_u_t *)device; u != NULL; u = u->common.parent) {
450 if (u->common.OF_private != NULL)
451 return u->common.OF_private;
454 return NULL;
457 /* PCI devices database */
458 static pci_subclass_t undef_subclass[] = {
460 0x00, "misc undefined", NULL, NULL, NULL,
461 NULL, NULL,
464 0xFF, NULL, NULL, NULL, NULL,
465 NULL, NULL,
469 static pci_dev_t ide_devices[] = {
471 0x8086, 0x0100,
472 NULL, "Qemu IDE", "Qemu IDE", "ide",
473 0, 0, 0,
474 NULL, NULL,
477 0xFFFF, 0xFFFF,
478 NULL, NULL, NULL, NULL,
479 -1, -1, -1,
480 NULL, NULL,
484 static int ide_config_cb (pci_device_t *device)
486 printf("Register IDE controller\n");
487 switch (arch) {
488 case ARCH_MAC99:
489 ide_pci_pmac_register(device->regions[0] & ~0x0000000F,
490 device->regions[1] & ~0x0000000F,
491 device->common.OF_private);
492 break;
493 default:
494 ide_pci_pc_register(device->regions[0] & ~0x0000000F,
495 device->regions[1] & ~0x0000000F,
496 device->regions[2] & ~0x0000000F,
497 device->regions[3] & ~0x0000000F,
498 device->common.OF_private);
499 break;
502 return 0;
505 static int ata_config_cb (pci_device_t *device)
507 printf("Register ATA controller\n");
508 switch (arch) {
509 case ARCH_MAC99:
510 ide_pci_pmac_register(device->regions[0] & ~0x0000000F,
511 device->regions[1] & ~0x0000000F,
512 device->common.OF_private);
513 break;
514 default:
515 ide_pci_pc_register(device->regions[0] & ~0x0000000F,
516 device->regions[1] & ~0x0000000F,
517 device->regions[2] & ~0x0000000F,
518 device->regions[3] & ~0x0000000F,
519 device->common.OF_private);
520 break;
523 return 0;
526 static pci_subclass_t mass_subclass[] = {
528 0x00, "SCSI bus controller", NULL, NULL, NULL,
529 NULL, NULL,
532 0x01, "IDE controller", "ide", ide_devices, NULL,
533 &ide_config_cb, NULL,
536 0x02, "Floppy disk controller", NULL, NULL, NULL,
537 NULL, NULL,
540 0x03, "IPI bus controller", NULL, NULL, NULL,
541 NULL, NULL,
544 0x04, "RAID controller", NULL, NULL, NULL,
545 NULL, NULL,
548 0x05, "ATA controller", "ata", NULL, NULL,
549 &ata_config_cb, NULL,
552 0x80, "misc mass-storage controller", NULL, NULL, NULL,
553 NULL, NULL,
556 0xFF, NULL, NULL, NULL, NULL,
557 NULL, NULL,
561 static pci_dev_t eth_devices[] = {
562 { 0x10EC, 0x8029,
563 NULL, "NE2000", "NE2000 PCI", NULL,
564 0, 0, 0,
565 NULL, "ethernet",
568 0xFFFF, 0xFFFF,
569 NULL, NULL, NULL, NULL,
570 -1, -1, -1,
571 NULL, NULL,
575 static pci_subclass_t net_subclass[] = {
577 0x00, "ethernet controller", NULL, eth_devices, NULL,
578 NULL, "ethernet",
581 0x01, "token ring controller", NULL, NULL, NULL,
582 NULL, NULL,
585 0x02, "FDDI controller", NULL, NULL, NULL,
586 NULL, NULL,
589 0x03, "ATM controller", NULL, NULL, NULL,
590 NULL, NULL,
593 0x04, "ISDN controller", NULL, NULL, NULL,
594 NULL, NULL,
597 0x05, "WordFip controller", NULL, NULL, NULL,
598 NULL, NULL,
601 0x06, "PICMG 2.14 controller", NULL, NULL, NULL,
602 NULL, NULL,
605 0x80, "misc network controller", NULL, NULL, NULL,
606 NULL, NULL,
609 0xFF, NULL, NULL, NULL, NULL,
610 NULL, NULL,
614 static pci_dev_t vga_devices[] = {
616 0x1002, 0x5046,
617 NULL, "ATY", "ATY Rage128", "VGA",
618 0, 0, 0,
619 NULL, NULL,
622 0x1234, 0x1111,
623 NULL, "Qemu VGA", "Qemu VGA", "VGA",
624 0, 0, 0,
625 NULL, NULL,
628 0xFFFF, 0xFFFF,
629 NULL, NULL, NULL, NULL,
630 -1, -1, -1,
631 NULL, NULL,
635 /* VGA configuration */
636 /* HACK... */
637 extern int vga_width, vga_height, vga_depth;
638 int vga_console_register (void);
639 static int vga_config_cb (pci_device_t *device)
641 /* Found a VGA device. Let's configure it ! */
642 printf("Set VGA to %0x\n", device->regions[0] & ~0x0000000F);
643 if (device->regions[0] != 0x00000000) {
644 vga_set_mode(vga_width, vga_height, vga_depth);
645 vga_set_address(device->regions[0] & ~0x0000000F);
646 /* VGA 640x480x16 */
647 OF_vga_register(device->common.device->name,
648 device->regions[0] & ~0x0000000F,
649 vga_width, vga_height, vga_depth);
651 vga_console_register();
653 return 0;
656 static struct pci_iface_t vga_iface[] = {
658 0x00, "VGA controller", NULL,
659 vga_devices, &vga_config_cb, NULL,
662 0x01, "8514 compatible controller", NULL,
663 NULL, NULL, NULL,
666 0xFF, NULL, NULL,
667 NULL, NULL, NULL,
671 static pci_subclass_t displ_subclass[] = {
673 0x00, "display controller", NULL, NULL, vga_iface,
674 NULL, NULL,
677 0x01, "XGA display controller", NULL, NULL, NULL,
678 NULL, NULL,
681 0x02, "3D display controller", NULL, NULL, NULL,
682 NULL, NULL,
685 0x80, "misc display controller", NULL, NULL, NULL,
686 NULL, NULL,
689 0xFF, NULL, NULL, NULL, NULL,
690 NULL, NULL,
694 static pci_subclass_t media_subclass[] = {
696 0x00, "video device", NULL, NULL, NULL,
697 NULL, NULL,
700 0x01, "audio device", NULL, NULL, NULL,
701 NULL, NULL,
704 0x02, "computer telephony device", NULL, NULL, NULL,
705 NULL, NULL,
708 0x80, "misc multimedia device", NULL, NULL, NULL,
709 NULL, NULL,
712 0xFF, NULL, NULL, NULL, NULL,
713 NULL, NULL,
717 static pci_subclass_t mem_subclass[] = {
719 0x00, "RAM controller", NULL, NULL, NULL,
720 NULL, NULL,
723 0x01, "flash controller", NULL, NULL, NULL,
724 NULL, NULL,
727 0xFF, NULL, NULL, NULL, NULL,
728 NULL, NULL,
732 static pci_dev_t uninorth_agp_fake_bridge = {
733 0xFFFF, 0xFFFF,
734 "uni-north-agp", "uni-north-agp", NULL, "uni-north-agp",
735 -1, -1, -1,
736 NULL, &uninorth_pci_ops,
739 static pci_dev_t uninorth_fake_bridge = {
740 0xFFFF, 0xFFFF,
741 "uni-north", "uni-north", NULL, "uni-north",
742 -1, -1, -1,
743 NULL, &uninorth_pci_ops,
746 static pci_dev_t PREP_fake_bridge = {
747 0xFFFF, 0xFFFF,
748 "pci", "pci", NULL, "pci",
749 -1, -1, -1,
750 NULL, &PREP_pci_ops,
753 static pci_dev_t hbrg_devices[] = {
755 0x106B, 0x0020, NULL,
756 "pci", "AAPL,UniNorth", "uni-north",
757 3, 2, 1,
758 NULL, &uninorth_agp_fake_bridge,
761 0x106B, 0x001F,
762 NULL, "pci", "AAPL,UniNorth", "uni-north",
763 3, 2, 1,
764 NULL, &uninorth_fake_bridge,
767 0x106B, 0x001E, NULL,
768 "pci", "AAPL,UniNorth", "uni-north",
769 3, 2, 1,
770 NULL, &uninorth_fake_bridge,
773 0x1011, 0x0026, NULL,
774 "pci-bridge", NULL, NULL,
775 3, 2, 1,
776 NULL, &PREP_pci_ops,
779 0x1057, 0x4801, NULL,
780 "pci-bridge", "PREP Host PCI Bridge - Motorola Raven", NULL,
781 3, 2, 1,
782 NULL, &PREP_pci_ops,
785 0xFFFF, 0xFFFF,
786 NULL, NULL, NULL, NULL,
787 -1, -1, -1,
788 NULL, NULL,
792 static pci_dev_t PCIbrg_devices[] = {
794 0x1011, 0x0026, NULL,
795 "pci-bridge", NULL, NULL,
796 3, 2, 1,
797 NULL, &PREP_pci_ops,
800 0xFFFF, 0xFFFF,
801 NULL, NULL, NULL, NULL,
802 -1, -1, -1,
803 NULL, NULL,
807 static pci_subclass_t bridg_subclass[] = {
809 0x00, "PCI host bridge", NULL, hbrg_devices, NULL,
810 NULL, NULL,
813 0x01, "ISA bridge", NULL, NULL, NULL,
814 NULL, NULL,
817 0x02, "EISA bridge", NULL, NULL, NULL,
818 NULL, NULL,
821 0x03, "MCA bridge", NULL, NULL, NULL,
822 NULL, NULL,
825 0x04, "PCI-to-PCI bridge", NULL, PCIbrg_devices, NULL,
826 NULL, NULL,
829 0x05, "PCMCIA bridge", NULL, NULL, NULL,
830 NULL, NULL,
833 0x06, "NUBUS bridge", NULL, NULL, NULL,
834 NULL, NULL,
837 0x07, "cardbus bridge", NULL, NULL, NULL,
838 NULL, NULL,
841 0x08, "raceway bridge", NULL, NULL, NULL,
842 NULL, NULL,
845 0x09, "semi-transparent PCI-to-PCI bridge", NULL, NULL, NULL,
846 NULL, NULL,
849 0x0A, "infiniband-to-PCI bridge", NULL, NULL, NULL,
850 NULL, NULL,
853 0x80, "misc PCI bridge", NULL, NULL, NULL,
854 NULL, NULL,
857 0xFF, NULL, NULL, NULL, NULL,
858 NULL, NULL,
862 static pci_iface_t serial_iface[] = {
864 0x00, "XT serial controller", NULL,
865 NULL, NULL, NULL,
868 0x01, "16450 serial controller", NULL,
869 NULL, NULL, NULL,
872 0x02, "16550 serial controller", NULL,
873 NULL, NULL, NULL,
876 0x03, "16650 serial controller", NULL,
877 NULL, NULL, NULL,
880 0x04, "16750 serial controller", NULL,
881 NULL, NULL, NULL,
884 0x05, "16850 serial controller", NULL,
885 NULL, NULL, NULL,
888 0x06, "16950 serial controller", NULL,
889 NULL, NULL, NULL,
892 0xFF, NULL, NULL,
893 NULL, NULL, NULL,
897 static pci_iface_t par_iface[] = {
899 0x00, "parallel port", NULL,
900 NULL, NULL, NULL,
903 0x01, "bi-directional parallel port", NULL,
904 NULL, NULL, NULL,
907 0x02, "ECP 1.x parallel port", NULL,
908 NULL, NULL, NULL,
911 0x03, "IEEE 1284 controller", NULL,
912 NULL, NULL, NULL,
915 0xFE, "IEEE 1284 device", NULL,
916 NULL, NULL, NULL,
919 0xFF, NULL, NULL,
920 NULL, NULL, NULL,
924 static pci_iface_t modem_iface[] = {
926 0x00, "generic modem", NULL,
927 NULL, NULL, NULL,
930 0x01, "Hayes 16450 modem", NULL,
931 NULL, NULL, NULL,
934 0x02, "Hayes 16550 modem", NULL,
935 NULL, NULL, NULL,
938 0x03, "Hayes 16650 modem", NULL,
939 NULL, NULL, NULL,
942 0x04, "Hayes 16750 modem", NULL,
943 NULL, NULL, NULL,
946 0xFF, NULL, NULL,
947 NULL, NULL, NULL,
951 static pci_subclass_t comm_subclass[] = {
953 0x00, "serial controller", NULL, NULL, serial_iface,
954 NULL, NULL,
957 0x01, "parallel port", NULL, NULL, par_iface,
958 NULL, NULL,
961 0x02, "multiport serial controller", NULL, NULL, NULL,
962 NULL, NULL,
965 0x03, "modem", NULL, NULL, modem_iface,
966 NULL, NULL,
969 0x04, "GPIB controller", NULL, NULL, NULL,
970 NULL, NULL,
973 0x05, "smart card", NULL, NULL, NULL,
974 NULL, NULL,
977 0x80, "misc communication device", NULL, NULL, NULL,
978 NULL, NULL,
981 0xFF, NULL, NULL, NULL, NULL,
982 NULL, NULL,
986 static pci_iface_t pic_iface[] = {
988 0x00, "8259 PIC", NULL,
989 NULL, NULL, NULL,
992 0x01, "ISA PIC", NULL,
993 NULL, NULL, NULL,
996 0x02, "EISA PIC", NULL,
997 NULL, NULL, NULL,
1000 0x10, "I/O APIC", NULL,
1001 NULL, NULL, NULL,
1004 0x20, "I/O APIC", NULL,
1005 NULL, NULL, NULL,
1008 0xFF, NULL, NULL,
1009 NULL, NULL, NULL,
1013 static pci_iface_t dma_iface[] = {
1015 0x00, "8237 DMA controller", NULL,
1016 NULL, NULL, NULL,
1019 0x01, "ISA DMA controller", NULL,
1020 NULL, NULL, NULL,
1023 0x02, "EISA DMA controller", NULL,
1024 NULL, NULL, NULL,
1027 0xFF, NULL, NULL,
1028 NULL, NULL, NULL,
1032 static pci_iface_t tmr_iface[] = {
1034 0x00, "8254 system timer", NULL,
1035 NULL, NULL, NULL,
1038 0x01, "ISA system timer", NULL,
1039 NULL, NULL, NULL,
1042 0x02, "EISA system timer", NULL,
1043 NULL, NULL, NULL,
1046 0xFF, NULL, NULL,
1047 NULL, NULL, NULL,
1051 static pci_iface_t rtc_iface[] = {
1053 0x00, "generic RTC controller", NULL,
1054 NULL, NULL, NULL,
1057 0x01, "ISA RTC controller", NULL,
1058 NULL, NULL, NULL,
1061 0xFF, NULL, NULL,
1062 NULL, NULL, NULL,
1066 static const pci_dev_t sys_devices[] = {
1067 /* IBM MPIC controller */
1069 0x1014, 0x0002,
1070 "open-pic", "MPIC", NULL, "chrp,open-pic",
1071 0, 0, 2,
1072 NULL, NULL,
1074 /* IBM MPIC2 controller */
1076 0x1014, 0xFFFF,
1077 "open-pic", "MPIC2", NULL, "chrp,open-pic",
1078 0, 0, 2,
1079 NULL, NULL,
1082 0xFFFF, 0xFFFF,
1083 NULL, NULL, NULL, NULL,
1084 -1, -1, -1,
1085 NULL, NULL,
1089 static pci_subclass_t sys_subclass[] = {
1091 0x00, "PIC", NULL, NULL, pic_iface,
1092 NULL, NULL,
1095 0x01, "DMA controller", NULL, NULL, dma_iface,
1096 NULL, NULL,
1099 0x02, "system timer", NULL, NULL, tmr_iface,
1100 NULL, NULL,
1103 0x03, "RTC controller", NULL, NULL, rtc_iface,
1104 NULL, NULL,
1107 0x04, "PCI hotplug controller", NULL, NULL, NULL,
1108 NULL, NULL,
1111 0x80, "misc system peripheral", NULL, sys_devices, NULL,
1112 NULL, NULL,
1115 0xFF, NULL, NULL, NULL, NULL,
1116 NULL, NULL,
1120 static pci_subclass_t inp_subclass[] = {
1122 0x00, "keyboard controller", NULL, NULL, NULL,
1123 NULL, NULL,
1126 0x01, "digitizer", NULL, NULL, NULL,
1127 NULL, NULL,
1130 0x02, "mouse controller", NULL, NULL, NULL,
1131 NULL, NULL,
1134 0x03, "scanner controller", NULL, NULL, NULL,
1135 NULL, NULL,
1138 0x04, "gameport controller", NULL, NULL, NULL,
1139 NULL, NULL,
1142 0x80, "misc input device", NULL, NULL, NULL,
1143 NULL, NULL,
1146 0xFF, NULL, NULL, NULL, NULL,
1147 NULL, NULL,
1151 static pci_subclass_t dock_subclass[] = {
1153 0x00, "generic docking station", NULL, NULL, NULL,
1154 NULL, NULL,
1157 0x80, "misc docking station", NULL, NULL, NULL,
1158 NULL, NULL,
1161 0xFF, NULL, NULL, NULL, NULL,
1162 NULL, NULL,
1166 static pci_subclass_t cpu_subclass[] = {
1168 0x00, "i386 processor", NULL, NULL, NULL,
1169 NULL, NULL,
1172 0x01, "i486 processor", NULL, NULL, NULL,
1173 NULL, NULL,
1176 0x02, "pentium processor", NULL, NULL, NULL,
1177 NULL, NULL,
1180 0x10, "alpha processor", NULL, NULL, NULL,
1181 NULL, NULL,
1184 0x20, "PowerPC processor", NULL, NULL, NULL,
1185 NULL, NULL,
1188 0x30, "MIPS processor", NULL, NULL, NULL,
1189 NULL, NULL,
1192 0x40, "co-processor", NULL, NULL, NULL,
1193 NULL, NULL,
1196 0xFF, NULL, NULL, NULL, NULL,
1197 NULL, NULL,
1201 static pci_iface_t usb_iface[] = {
1203 0x00, "UHCI USB controller", NULL,
1204 NULL, NULL, NULL,
1207 0x10, "OHCI USB controller", NULL,
1208 NULL, NULL, NULL,
1211 0x20, "EHCI USB controller", NULL,
1212 NULL, NULL, NULL,
1215 0x80, "misc USB controller", NULL,
1216 NULL, NULL, NULL,
1219 0xFE, "USB device", NULL,
1220 NULL, NULL, NULL,
1223 0xFF, NULL, NULL,
1224 NULL, NULL, NULL,
1228 static pci_iface_t ipmi_iface[] = {
1230 0x00, "IPMI SMIC interface", NULL,
1231 NULL, NULL, NULL,
1234 0x01, "IPMI keyboard interface", NULL,
1235 NULL, NULL, NULL,
1238 0x02, "IPMI block transfer interface", NULL,
1239 NULL, NULL, NULL,
1242 0xFF, NULL, NULL,
1243 NULL, NULL, NULL,
1247 static pci_subclass_t ser_subclass[] = {
1249 0x00, "Firewire bus controller", "ieee1394", NULL, NULL,
1250 NULL, NULL,
1253 0x01, "ACCESS bus controller", NULL, NULL, NULL,
1254 NULL, NULL,
1257 0x02, "SSA controller", NULL, NULL, NULL,
1258 NULL, NULL,
1261 0x03, "USB controller", "usb", NULL, usb_iface,
1262 NULL, NULL,
1265 0x04, "fibre channel controller", NULL, NULL, NULL,
1266 NULL, NULL,
1269 0x05, "SMBus controller", NULL, NULL, NULL,
1270 NULL, NULL,
1273 0x06, "InfiniBand controller", NULL, NULL, NULL,
1274 NULL, NULL,
1277 0x07, "IPMI interface", NULL, NULL, ipmi_iface,
1278 NULL, NULL,
1281 0x08, "SERCOS controller", NULL, NULL, ipmi_iface,
1282 NULL, NULL,
1285 0x09, "CANbus controller", NULL, NULL, ipmi_iface,
1286 NULL, NULL,
1289 0xFF, NULL, NULL, NULL, NULL,
1290 NULL, NULL,
1294 static pci_subclass_t wrl_subclass[] = {
1296 0x00, "IRDA controller", NULL, NULL, NULL,
1297 NULL, NULL,
1300 0x01, "consumer IR controller", NULL, NULL, NULL,
1301 NULL, NULL,
1304 0x10, "RF controller", NULL, NULL, NULL,
1305 NULL, NULL,
1308 0x11, "bluetooth controller", NULL, NULL, NULL,
1309 NULL, NULL,
1312 0x12, "broadband controller", NULL, NULL, NULL,
1313 NULL, NULL,
1316 0x80, "misc wireless controller", NULL, NULL, NULL,
1317 NULL, NULL,
1320 0xFF, NULL, NULL, NULL, NULL,
1321 NULL, NULL,
1325 static pci_subclass_t sat_subclass[] = {
1327 0x01, "satellite TV controller", NULL, NULL, NULL,
1328 NULL, NULL,
1331 0x02, "satellite audio controller", NULL, NULL, NULL,
1332 NULL, NULL,
1335 0x03, "satellite voice controller", NULL, NULL, NULL,
1336 NULL, NULL,
1339 0x04, "satellite data controller", NULL, NULL, NULL,
1340 NULL, NULL,
1343 0xFF, NULL, NULL, NULL, NULL,
1344 NULL, NULL,
1348 static pci_subclass_t crypt_subclass[] = {
1350 0x00, "cryptographic network controller", NULL, NULL, NULL,
1351 NULL, NULL,
1354 0x10, "cryptographic entertainment controller", NULL, NULL, NULL,
1355 NULL, NULL,
1358 0x80, "misc cryptographic controller", NULL, NULL, NULL,
1359 NULL, NULL,
1362 0xFF, NULL, NULL, NULL, NULL,
1363 NULL, NULL,
1367 static pci_subclass_t spc_subclass[] = {
1369 0x00, "DPIO module", NULL, NULL, NULL,
1370 NULL, NULL,
1373 0x01, "performances counters", NULL, NULL, NULL,
1374 NULL, NULL,
1377 0x10, "communication synchronisation", NULL, NULL, NULL,
1378 NULL, NULL,
1381 0x20, "management card", NULL, NULL, NULL,
1382 NULL, NULL,
1385 0x80, "misc signal processing controller", NULL, NULL, NULL,
1386 NULL, NULL,
1389 0xFF, NULL, NULL, NULL, NULL,
1390 NULL, NULL,
1394 static const pci_class_t pci_classes[] = {
1395 /* 0x00 */
1396 { "undefined", NULL, undef_subclass, },
1397 /* 0x01 */
1398 { "mass-storage controller", NULL, mass_subclass, },
1399 /* 0x02 */
1400 { "network controller", "network", net_subclass, },
1401 /* 0x03 */
1402 { "display controller", "display", displ_subclass, },
1403 /* 0x04 */
1404 { "multimedia device", NULL, media_subclass, },
1405 /* 0x05 */
1406 { "memory controller", "memory-controller", mem_subclass, },
1407 /* 0x06 */
1408 { "PCI bridge", "pci", bridg_subclass, },
1409 /* 0x07 */
1410 { "communication device", NULL, comm_subclass,},
1411 /* 0x08 */
1412 { "system peripheral", NULL, sys_subclass, },
1413 /* 0x09 */
1414 { "input device", NULL, inp_subclass, },
1415 /* 0x0A */
1416 { "docking station", NULL, dock_subclass, },
1417 /* 0x0B */
1418 { "processor", NULL, cpu_subclass, },
1419 /* 0x0C */
1420 { "serial bus controller", NULL, ser_subclass, },
1421 /* 0x0D */
1422 { "wireless controller", NULL, wrl_subclass, },
1423 /* 0x0E */
1424 { "intelligent I/O controller", NULL, NULL, },
1425 /* 0x0F */
1426 { "satellite communication controller", NULL, sat_subclass, },
1427 /* 0x10 */
1428 { "cryptographic controller", NULL, crypt_subclass, },
1429 /* 0x11 */
1430 { "signal processing controller", NULL, spc_subclass, },
1433 static int macio_config_cb (pci_device_t *device)
1435 void *private_data;
1437 private_data = cuda_init(device->regions[0] + 0x16000);
1438 OF_finalize_pci_macio(device->common.OF_private,
1439 device->regions[0] & ~0x0000000F, device->sizes[0],
1440 private_data);
1442 return 0;
1445 static const pci_dev_t misc_pci[] = {
1446 /* Apple Mac-io controller */
1448 0x106B, 0x0022,
1449 "mac-io", "mac-io", "AAPL,Keylargo", "Keylargo",
1450 1, 1, 2,
1451 &macio_config_cb, NULL,
1454 0xFFFF, 0xFFFF,
1455 NULL, NULL, NULL, NULL,
1456 -1, -1, -1,
1457 NULL, NULL,
1461 static pci_dev_t *pci_find_device (uint8_t class, uint8_t subclass,
1462 uint8_t iface, uint16_t vendor,
1463 uint16_t product)
1465 int (*config_cb)(pci_device_t *device);
1466 const pci_class_t *pclass;
1467 const pci_subclass_t *psubclass;
1468 const pci_iface_t *piface;
1469 const pci_dev_t *dev;
1470 const void *private;
1471 pci_dev_t *new;
1472 const unsigned char *name, *type;
1474 name = "unknown";
1475 type = "unknown";
1476 config_cb = NULL;
1477 private = NULL;
1478 #if 0
1479 printf("check PCI device : %x %x (%x %x %x)\n",
1480 vendor, product, class, subclass, iface);
1481 #endif
1482 if (class == 0x00 && subclass == 0x01) {
1483 /* Special hack for old style VGA devices */
1484 class = 0x03;
1485 subclass = 0x00;
1486 } else if (class == 0xFF) {
1487 /* Special case for misc devices */
1488 dev = misc_pci;
1489 goto find_device;
1491 if (class > (sizeof(pci_classes) / sizeof(pci_class_t))) {
1492 name = "invalid PCI device";
1493 type = "invalid";
1494 goto bad_device;
1496 pclass = &pci_classes[class];
1497 name = pclass->name;
1498 type = pclass->type;
1499 for (psubclass = pclass->subc; ; psubclass++) {
1500 if (psubclass->subclass == 0xFF)
1501 goto bad_device;
1502 if (psubclass->subclass == subclass) {
1503 if (psubclass->name != NULL)
1504 name = psubclass->name;
1505 if (psubclass->type != NULL)
1506 type = psubclass->type;
1507 if (psubclass->config_cb != NULL) {
1508 config_cb = psubclass->config_cb;
1510 if (psubclass->private != NULL)
1511 private = psubclass->private;
1512 if (psubclass->iface != NULL)
1513 break;
1514 dev = psubclass->devices;
1515 goto find_device;
1518 for (piface = psubclass->iface; ; piface++) {
1519 if (piface->iface == 0xFF) {
1520 dev = psubclass->devices;
1521 break;
1523 if (piface->iface == iface) {
1524 if (piface->name != NULL)
1525 name = piface->name;
1526 if (piface->type != NULL)
1527 type = piface->type;
1528 if (piface->config_cb != NULL) {
1529 config_cb = piface->config_cb;
1531 if (piface->private != NULL)
1532 private = piface->private;
1533 dev = piface->devices;
1534 break;
1537 find_device:
1538 for (;; dev++) {
1539 if (dev->vendor == 0xFFFF && dev->product == 0xFFFF) {
1540 goto bad_device;
1542 if (dev->vendor == vendor && dev->product == product) {
1543 if (dev->name != NULL)
1544 name = dev->name;
1545 if (dev->type != NULL)
1546 type = dev->type;
1547 if (dev->config_cb != NULL) {
1548 config_cb = dev->config_cb;
1550 if (dev->private != NULL)
1551 private = dev->private;
1552 new = malloc(sizeof(pci_dev_t));
1553 if (new == NULL)
1554 return NULL;
1555 new->vendor = vendor;
1556 new->product = product;
1557 new->type = type;
1558 new->name = name;
1559 new->model = dev->model;
1560 new->compat = dev->compat;
1561 new->acells = dev->acells;
1562 new->scells = dev->scells;
1563 new->icells = dev->icells;
1564 new->config_cb = config_cb;
1565 new->private = private;
1567 return new;
1570 bad_device:
1571 printf("Cannot manage '%s' PCI device type '%s':\n %x %x (%x %x %x)\n",
1572 name, type, vendor, product, class, subclass, iface);
1574 return NULL;
1577 /* PCI devices discovery helpers */
1578 static inline void pci_fill_common (pci_common_t *comm, pci_u_t *parent,
1579 int type, pci_dev_t *device)
1581 comm->type = type;
1582 comm->device = device;
1583 comm->parent = parent;
1586 static inline void pci_fill_device (pci_device_t *device, pci_u_t *parent,
1587 int type, uint8_t bus, uint8_t devfn,
1588 pci_dev_t *dev, uint32_t class_code)
1590 pci_fill_common(&device->common, parent, type, dev);
1591 device->bus = bus;
1592 device->devfn = devfn;
1593 device->class_code = class_code;
1594 device->rev = class_code;
1597 static inline void pci_update_device (pci_bridge_t *bridge,
1598 pci_device_t *device,
1599 uint8_t min_grant, uint8_t max_latency,
1600 int irq_line)
1602 uint32_t cmd;
1603 int i;
1605 device->min_grant = min_grant;
1606 device->max_latency = max_latency;
1607 device->irq_line = irq_line;
1608 if (irq_line != -1) {
1609 pci_config_writeb(bridge, device->bus, device->devfn,
1610 0x3c, device->irq_line);
1611 printf("MAP PCI device %d:%d to IRQ %d\n",
1612 device->bus, device->devfn, irq_line);
1614 for (i = 0; i < 6; i++) {
1615 if ((device->regions[i] & ~0xF) != 0x00000000 &&
1616 (device->regions[i] & ~0xF) != 0xFFFFFFF0) {
1617 printf("Map PCI device %d:%d %d to %0x %0x (%s)\n",
1618 device->bus, device->devfn, i,
1619 device->regions[i], device->sizes[i],
1620 device->regions[i] & 0x00000001 ? "I/O" : "memory");
1621 cmd = pci_config_readl(bridge, device->bus, device->devfn, 0x04);
1622 if (device->regions[i] & 0x00000001)
1623 cmd |= 0x00000001;
1624 else
1625 cmd |= 0x00000002;
1626 pci_config_writel(bridge, device->bus, device->devfn, 0x04, cmd);
1627 pci_config_writel(bridge, device->bus, device->devfn,
1628 0x10 + (i * sizeof(uint32_t)),
1629 device->regions[i]);
1634 static pci_host_t *pci_add_host (pci_host_t **hostp, pci_dev_t *device,
1635 uint32_t class_code)
1637 pci_host_t *new, **lnk;
1639 new = malloc(sizeof(pci_host_t));
1640 if (new == NULL)
1641 return NULL;
1642 pci_fill_common(&new->dev.common, NULL, PCI_HOST_BRIDGE, device);
1643 new->dev.class_code = class_code;
1644 new->dev.rev = class_code;
1645 for (lnk = hostp; *lnk != NULL; lnk = &((*lnk)->next))
1646 continue;
1647 *lnk = new;
1649 return new;
1652 static pci_bridge_t *pci_add_bridge (pci_host_t *host,
1653 uint8_t bus, uint8_t devfn,
1654 pci_dev_t *dev, uint32_t class_code,
1655 uint32_t cfg_base, uint32_t cfg_len,
1656 uint32_t cfg_addr, uint32_t cfg_data,
1657 uint32_t mem_base, uint32_t mem_len,
1658 uint32_t io_base, uint32_t io_len,
1659 uint32_t rbase, uint32_t rlen,
1660 uint32_t flags, const pci_ops_t *ops)
1662 pci_u_t *u;
1663 pci_bridge_t *new, **lnk;
1665 new = malloc(sizeof(pci_bridge_t));
1666 if (new == NULL)
1667 return NULL;
1668 u = (pci_u_t *)host;
1669 pci_fill_device(&new->dev, u, PCI_DEV_BRIDGE, bus, devfn, dev, class_code);
1670 new->cfg_base = cfg_base;
1671 new->cfg_len = cfg_len;
1672 new->mem_base = mem_base;
1673 new->mem_len = mem_len;
1674 new->io_base = io_base;
1675 new->io_len = io_len;
1676 new->mem_cur = mem_base;
1677 if (io_base != 0x00000000)
1678 new->io_cur = io_base + 0x1000;
1679 else
1680 new->io_cur = 0x00000000;
1681 new->cfg_addr = cfg_addr;
1682 new->cfg_data = cfg_data;
1683 new->rbase = rbase;
1684 new->rlen = rlen;
1685 new->flags = flags;
1686 new->ops = ops;
1687 for (lnk = &host->bridge; *lnk != NULL; lnk = &((*lnk)->next))
1688 continue;
1689 *lnk = new;
1691 return new;
1694 static pci_device_t *pci_add_device (pci_bridge_t *bridge,
1695 uint8_t bus, uint8_t devfn,
1696 pci_dev_t *dev, uint32_t class_code)
1698 pci_u_t *u;
1699 pci_device_t *new, **lnk;
1701 new = malloc(sizeof(pci_device_t));
1702 if (new == NULL)
1703 return NULL;
1704 u = (pci_u_t *)bridge;
1705 pci_fill_device(new, u, PCI_DEV_BRIDGE, bus, devfn, dev, class_code);
1706 for (lnk = &bridge->devices; *lnk != NULL; lnk = &((*lnk)->next))
1707 continue;
1708 *lnk = new;
1710 return new;
1713 static pci_u_t *pci_check_device (pci_host_t **hostp, pci_host_t **phost,
1714 uint8_t bus, uint8_t devfn,
1715 uint16_t checkv, uint16_t checkp,
1716 uint8_t cclass, uint8_t csubclass,
1717 uint8_t ciface, int check_bridges)
1719 pci_u_t *ret;
1720 pci_host_t *host, *newh;
1721 pci_bridge_t *bridge, *newb;
1722 pci_device_t *newd;
1723 pci_dev_t *dev;
1724 uint32_t *io_base, *mem_base, *base;
1725 uint32_t ccode, addr, omask, amask, size, smask, reloc, min_align;
1726 uint16_t vendor, product;
1727 uint8_t class, subclass, iface, rev, min_grant, max_latency;
1728 int i, max_areas, irq_line, irq_pin;
1730 ret = NULL;
1731 newd = NULL;
1732 host = *hostp;
1733 irq_line = -1;
1734 bridge = host->bridge;
1735 vendor = pci_config_readw(bridge, bus, devfn, 0x00);
1736 product = pci_config_readw(bridge, bus, devfn, 0x02);
1737 if (vendor == 0xFFFF && product == 0xFFFF) {
1738 /* No device: do nothing */
1739 goto out;
1741 ccode = pci_config_readl(bridge, bus, devfn, 0x08);
1742 class = ccode >> 24;
1743 subclass = ccode >> 16;
1744 iface = ccode >> 8;
1745 rev = ccode;
1746 if (checkv != 0xFFFF && vendor != checkv) {
1747 #if 0
1748 printf("Mismatching vendor for dev %x %x: %x %x\n",
1749 bus, devfn, checkv, vendor);
1750 #endif
1751 goto out;
1753 if (checkp != 0xFFFF && product != checkp) {
1754 #if 0
1755 printf("Mismatching product for dev %x %x: %x %x\n",
1756 bus, devfn, checkp, product);
1757 #endif
1758 goto out;
1760 if (cclass != 0xFF && class != cclass) {
1761 #if 0
1762 printf("Mismatching class for dev %x %x: %x %x\n",
1763 bus, devfn, cclass, class);
1764 #endif
1765 goto out;
1767 if (csubclass != 0xFF && subclass != csubclass) {
1768 #if 0
1769 printf("Mismatching subclass for dev %x %x: %x %x\n",
1770 bus, devfn, csubclass, subclass);
1771 #endif
1772 goto out;
1774 if (ciface != 0xFF && iface != ciface) {
1775 #if 0
1776 printf("Mismatching iface for dev %x %x: %x %x\n",
1777 bus, devfn, ciface, iface);
1778 #endif
1779 goto out;
1781 dev = pci_find_device(class, subclass, iface, vendor, product);
1782 if (dev == NULL) {
1783 goto out;
1785 min_grant = pci_config_readb(bridge, bus, devfn, 0x3C);
1786 max_latency = pci_config_readb(bridge, bus, devfn, 0x3D);
1787 /* Special cases for bridges */
1788 if (class == 0x06) {
1789 if (check_bridges < 1)
1790 goto out;
1791 if (subclass == 0x00) {
1792 if (check_bridges < 2)
1793 goto out;
1794 /* host bridge case */
1795 printf("Found new host bridge '%s' '%s' '%s'...\n",
1796 dev->type, dev->model, dev->compat);
1797 newh = pci_add_host(phost, dev, ccode);
1798 if (newh == NULL) {
1799 printf("Can't allocate new host bridge...\n");
1800 goto out;
1802 ret = (pci_u_t *)newh;
1803 #if 0
1804 if ((*hostp)->bridge->dev.common.type != PCI_FAKE_BRIDGE) {
1805 printf("Keep PCI bridge\n");
1806 /* If we already found a PCI bridge, keep it */
1807 newh->bridge = (*phost)->bridge;
1808 goto out;
1810 printf("Add fake PCI bridge\n");
1811 /* Add fake PCI bridge */
1812 newh->bridge = NULL;
1813 dev = dev->private;
1814 newb = pci_add_bridge(host, bus, devfn, dev, ccode,
1815 bridge->cfg_base, bridge->cfg_len,
1816 bridge->cfg_addr, bridge->cfg_data,
1817 bridge->mem_base, bridge->mem_len,
1818 bridge->io_base, bridge->io_len,
1819 bridge->rbase, bridge->rlen,
1820 bridge->flags, dev->private);
1821 if (newb == NULL) {
1822 printf("Can't allocate new PCI bridge\n");
1823 goto out;
1825 newb->dev.common.type = PCI_FAKE_BRIDGE;
1826 newb->devices = bridge->devices;
1827 #else
1828 newh->bridge = (*hostp)->bridge;
1829 newb = newh->bridge;
1830 #endif
1831 newd = &bridge->dev;
1832 host = newh;
1833 host->dev.common.OF_private =
1834 OF_register_pci_host(dev, rev, ccode,
1835 bridge->cfg_base, bridge->cfg_len,
1836 bridge->mem_base, bridge->mem_len,
1837 bridge->io_base, bridge->io_len,
1838 bridge->rbase, bridge->rlen,
1839 min_grant, max_latency);
1840 goto update_device;
1841 } else if (subclass == 0x04) {
1842 /* PCI-to-PCI bridge case */
1843 printf("Found new PCI bridge '%s' '%s' '%s' '%s' %p...\n",
1844 dev->name, dev->type, dev->model, dev->compat,
1845 dev->private);
1846 newb = pci_add_bridge(host, bus + 1, devfn, dev, ccode,
1847 bridge->cfg_base, bridge->cfg_len,
1848 bridge->cfg_addr, bridge->cfg_data,
1849 bridge->mem_base, bridge->mem_len,
1850 bridge->io_base, bridge->io_len,
1851 bridge->rbase, bridge->rlen,
1852 0, dev->private);
1853 if (newb == NULL) {
1854 printf("Can't allocate new PCI bridge...\n");
1855 goto out;
1857 ret = (pci_u_t *)newb;
1858 #if 0
1859 printf("Config addr: 0x%0x data: 0x%0x cfg_base: 0x%08x "
1860 "base: 0x%0x\n",
1861 newb->cfg_addr, newb->cfg_data, newb->cfg_base, newb->base);
1862 printf("newb: %p hb: %p b: %p next: %p\n", newb,
1863 host->bridge, bridge, host->bridge->next);
1864 #endif
1865 if (bridge->dev.common.type == PCI_FAKE_BRIDGE) {
1866 /* Free fake bridge if it's still present
1867 * Note: it should always be first...
1869 printf("Free fake bridge\n");
1870 newb->devices = host->bridge->devices;
1871 host->bridge = bridge->next;
1873 bridge = host->bridge;
1874 newd = &bridge->dev;
1875 #if 0
1876 printf("newb: %p hb: %p b: %p next: %p dev: %p\n", newb,
1877 host->bridge, bridge, host->bridge->next, newd);
1878 #endif
1879 max_areas = 2;
1880 bridge->dev.common.OF_private =
1881 OF_register_pci_bridge(host->dev.common.OF_private,
1882 dev, devfn, rev, ccode,
1883 bridge->cfg_base, bridge->cfg_len,
1884 min_grant, max_latency);
1885 goto configure_device;
1887 printf("Bridges type %x aren't managed for now\n", subclass);
1888 free(dev);
1889 goto out;
1891 /* Main case */
1892 printf("Found PCI device %x:%x %d-%d %d %d\n",
1893 vendor, product, bus, devfn, class, subclass);
1894 printf("=> '%s' '%s' '%s' '%s' (%p)\n",
1895 dev->name, dev->type, dev->model, dev->compat, dev->config_cb);
1896 newd = pci_add_device(bridge, bus, devfn, dev, ccode);
1897 if (newd == NULL) {
1898 printf("Cannot allocate new PCI device: %x %x (%x %x %x) '%s' '%s'\n",
1899 vendor, product, class, subclass, iface, dev->type, dev->name);
1900 goto out;
1902 ret = (pci_u_t *)newd;
1903 max_areas = 6;
1904 /* register PCI device in OF tree */
1905 if (bridge->dev.common.type == PCI_FAKE_BRIDGE) {
1906 newd->common.OF_private =
1907 OF_register_pci_device(host->dev.common.OF_private, dev, devfn,
1908 rev, ccode, min_grant, max_latency);
1909 } else {
1910 newd->common.OF_private =
1911 OF_register_pci_device(bridge->dev.common.OF_private, dev, devfn,
1912 rev, ccode, min_grant, max_latency);
1914 configure_device:
1915 #if 0
1916 printf("Config addr: 0x%08x data: 0x%08x cfg_base: 0x%08x base: 0x%08x\n",
1917 bridge->cfg_addr, bridge->cfg_data, bridge->cfg_base, bridge->base);
1918 printf("ops: %p uni-ops: %p\n", bridge->ops, &uninorth_pci_ops);
1919 #endif
1920 io_base = &bridge->io_cur;
1921 mem_base = &bridge->mem_cur;
1922 omask = 0x00000000;
1923 for (i = 0; i < max_areas; i++) {
1924 newd->regions[i] = 0x00000000;
1925 newd->sizes[i] = 0x00000000;
1926 if ((omask & 0x0000000F) == 0x4) {
1927 /* Handle 64 bits memory mapping */
1928 continue;
1930 addr = 0x10 + (i * sizeof(uint32_t));
1931 /* Get region size
1932 * Note: we assume it's always a power of 2
1934 pci_config_writel(bridge, bus, devfn, addr, 0xFFFFFFFF);
1935 smask = pci_config_readl(bridge, bus, devfn, addr);
1936 if (smask == 0x00000000 || smask == 0xFFFFFFFF)
1937 continue;
1938 if (smask & 0x00000001) {
1939 /* I/O space */
1940 base = io_base;
1941 /* Align to a minimum of 256 bytes (arbitrary) */
1942 min_align = 1 << 8;
1943 amask = 0x00000001;
1944 } else {
1945 /* Memory space */
1946 base = mem_base;
1947 /* Align to a minimum of 64 kB (arbitrary) */
1948 min_align = 1 << 16;
1949 amask = 0x0000000F;
1951 omask = smask & amask;
1952 smask &= ~amask;
1953 size = (~smask) + 1;
1954 reloc = *base;
1955 #if 0
1956 printf("Relocate %s area %d of size %0x to 0x%0x (0x%0x 0x%0x %0x)\n",
1957 omask & 0x00000001 ? "I/O" : "memory", i,
1958 size, reloc, reloc + size, smask);
1959 #endif
1960 if (size < min_align) {
1961 size = min_align;
1963 /* Align reloc to size */
1964 reloc = (reloc + size - 1) & ~(size - 1);
1965 (*base) = reloc + size;
1966 if (omask & 0x00000001) {
1967 /* I/O resources are offsets */
1968 reloc -= bridge->io_base;
1970 /* Set region address */
1971 newd->regions[i] = reloc | omask;
1972 newd->sizes[i] = size;
1974 /* Realign io-base to 4 kB */
1975 bridge->io_base = (bridge->io_base + (1 << 12) - 1) & ~((1 << 12) - 1);
1976 /* Realign mem-base to 1 MB */
1977 bridge->mem_base = (bridge->mem_base + (1 << 20) - 1) & ~((1 << 20) - 1);
1979 irq_pin = pci_config_readb(bridge, bus, devfn, 0x3d);
1980 if (irq_pin > 0) {
1981 /* assign the IRQ */
1982 irq_pin = ((devfn >> 3) + irq_pin - 1) & 3;
1983 if (arch == ARCH_PREP) {
1984 int elcr_port, val;
1985 irq_line = prep_pci_irqs[irq_pin];
1986 /* set the IRQ to level-sensitive */
1987 elcr_port = 0x4d0 + (irq_line >> 8);
1988 val = inb(elcr_port);
1989 val |= 1 << (irq_line & 7);
1990 outb(elcr_port, val);
1991 } else {
1992 irq_line = pmac_pci_irqs[irq_pin];
1995 update_device:
1996 pci_update_device(bridge, newd, min_grant, max_latency, irq_line);
1997 OF_finalize_pci_device(newd->common.OF_private, bus, devfn,
1998 newd->regions, newd->sizes);
1999 /* Call special inits if needed */
2000 if (dev->config_cb != NULL)
2001 (*dev->config_cb)(newd);
2003 out:
2004 return ret;
2007 static int pci_check_host (pci_host_t **hostp,
2008 uint32_t cfg_base, uint32_t cfg_len,
2009 uint32_t mem_base, uint32_t mem_len,
2010 uint32_t io_base, uint32_t io_len,
2011 uint32_t rbase, uint32_t rlen,
2012 uint16_t checkv, uint16_t checkp)
2014 pci_host_t *fake_host, *host, **phost;
2015 pci_bridge_t *fake_bridge;
2016 pci_dev_t *dev;
2017 int bus, devfn;
2018 int ret;
2020 fake_host = NULL;
2021 ret = -1;
2022 switch (arch) {
2023 case ARCH_PREP:
2024 dev = pci_find_device(0x06, 0x00, 0xFF, checkv, checkp);
2025 if (dev == NULL)
2026 return -1;
2027 fake_host = pci_add_host(hostp, dev,
2028 (0x06 << 24) | (0x00 << 16) | (0xFF << 8));
2029 if (fake_host == NULL)
2030 return -1;
2031 fake_host->dev.common.type = PCI_FAKE_HOST;
2032 dev = &PREP_fake_bridge;
2033 if (dev == NULL)
2034 goto free_fake_host;
2035 fake_bridge = pci_add_bridge(fake_host, 0, 11, dev,
2036 (0x06 << 24) | (0x00 << 16) | (0xFF << 8),
2037 cfg_base, cfg_len,
2038 cfg_base + 0x00800000,
2039 cfg_base + 0x00C00000,
2040 mem_base, mem_len,
2041 io_base, io_len,
2042 rbase, rlen,
2044 &PREP_pci_ops);
2045 if (fake_bridge == NULL)
2046 goto free_fake_host;
2047 fake_bridge->dev.common.type = PCI_FAKE_BRIDGE;
2048 break;
2049 case ARCH_CHRP:
2050 /* TODO */
2051 break;
2052 case ARCH_MAC99:
2053 dev = pci_find_device(0x06, 0x00, 0xFF, checkv, checkp);
2054 if (dev == NULL)
2055 return -1;
2056 fake_host = pci_add_host(hostp, dev,
2057 (0x06 << 24) | (0x00 << 16) | (0xFF << 8));
2058 if (fake_host == NULL)
2059 return -1;
2060 fake_host->dev.common.type = PCI_FAKE_HOST;
2061 dev = &uninorth_fake_bridge;
2062 if (dev == NULL)
2063 goto free_fake_host;
2064 fake_bridge = pci_add_bridge(fake_host, 0, 11, dev,
2065 (0x06 << 24) | (0x00 << 16) | (0xFF << 8),
2066 cfg_base, cfg_len,
2067 cfg_base + 0x00800000,
2068 cfg_base + 0x00C00000,
2069 mem_base, mem_len,
2070 io_base, io_len,
2071 rbase, rlen,
2072 BRIDGE_TYPE_UNINORTH,
2073 &uninorth_pci_ops);
2074 if (fake_bridge == NULL)
2075 goto free_fake_host;
2076 fake_bridge->dev.common.type = PCI_FAKE_BRIDGE;
2077 fake_bridge->flags |= BRIDGE_TYPE_UNINORTH;
2078 break;
2079 case ARCH_POP:
2080 /* TODO */
2081 break;
2083 host = NULL;
2084 phost = &host;
2085 for (bus = 0; bus < 256; bus++) {
2086 for (devfn = 0; devfn < 256; devfn++) {
2087 /* Find host bridge */
2088 pci_check_device(hostp, phost, bus, devfn,
2089 checkv, checkp, 0x06, 0x00, 0xFF, 2);
2090 if (host != NULL) {
2091 *hostp = host;
2092 OF_finalize_pci_host(host->dev.common.OF_private, bus, 1);
2093 ret = 0;
2094 goto done;
2098 done:
2099 free(fake_host->bridge);
2100 free_fake_host:
2101 free(fake_host);
2103 return ret;
2106 static int pci_check_devices (pci_host_t *host)
2108 int bus, devfn;
2110 /* Find all PCI bridges */
2111 printf("Check PCI bridges\n");
2112 for (bus = 0; bus < 256; bus++) {
2113 for (devfn = 0; devfn < 256; devfn++) {
2114 pci_check_device(&host, &host, bus, devfn, 0xFFFF, 0xFFFF,
2115 0x06, 0xFF, 0xFF, 1);
2118 /* Now, find all other devices */
2119 /* XXX: should recurse thru all host and bridges ! */
2120 printf("Check PCI devices\n");
2121 for (bus = 0; bus < 256; bus++) {
2122 for (devfn = 0; devfn < 256; devfn++) {
2123 pci_check_device(&host, &host, bus, devfn, 0xFFFF, 0xFFFF,
2124 0xFF, 0xFF, 0xFF, 0);
2128 return 0;
2131 pci_host_t *pci_init (void)
2133 pci_host_t *pci_main = NULL, *curh;
2134 uint32_t rbase, rlen, cfg_base, cfg_len;
2135 uint32_t mem_base, mem_len, io_base, io_len;
2136 uint8_t busnum;
2138 printf("Probing PCI devices\n");
2139 /* We need to discover PCI bridges and devices */
2140 switch (arch) {
2141 case ARCH_PREP:
2142 /* supposed to have 1 host bridge:
2143 * - the Motorola Raven PCI bridge
2145 cfg_base = 0x80000000;
2146 cfg_len = 0x00100000;
2147 mem_base = 0xF0000000;
2148 mem_len = 0x10000000;
2149 io_base = 0x80000000;
2150 io_len = 0x00010000;
2151 #if 0
2152 rbase = 0x80C00000; /* ? */
2153 #else
2154 rbase = 0x00000000;
2155 #endif
2156 rlen = 0x00400000; /* ? */
2157 if (pci_check_host(&pci_main, cfg_base, cfg_len,
2158 mem_base, mem_len, io_base, io_len, rbase, rlen,
2159 0x1057, 0x4801) == 0) {
2160 isa_io_base = io_base;
2161 busnum++;
2163 for (curh = pci_main; curh->next != NULL; curh = curh->next)
2164 continue;
2165 pci_check_devices(curh);
2166 break;
2167 case ARCH_CHRP:
2168 /* TODO */
2169 break;
2170 case ARCH_MAC99:
2171 /* We are supposed to have 3 host bridges:
2172 * - the uninorth AGP bridge at 0xF0000000
2173 * - the uninorth PCI expansion bridge at 0xF2000000
2174 * - the uninorth PCI internal bridge at 0xF4000000
2176 cfg_base = 0xF0000000;
2177 cfg_len = 0x02000000;
2178 mem_base = 0x90000000;
2179 mem_len = 0x10000000;
2180 io_base = 0xF0000000;
2181 io_len = 0x00800000;
2182 rbase = 0xF1000000;
2183 rlen = 0x01000000;
2184 #if 0
2185 if (pci_check_host(&pci_main, cfg_base, cfg_len,
2186 mem_base, mem_len, io_base, io_len, rbase, rlen,
2187 0x106b, 0x0020) == 0) {
2188 busnum++;
2190 for (curh = pci_main; curh->next != NULL; curh = curh->next)
2191 continue;
2192 pci_check_devices(curh);
2193 #endif
2195 cfg_base = 0xF2000000;
2196 cfg_len = 0x02000000;
2197 mem_base = 0x80000000;
2198 mem_len = 0x10000000;
2199 io_base = 0xF2000000;
2200 io_len = 0x00800000;
2201 #if 0 // Hack
2202 rbase = 0xF3000000;
2203 rlen = 0x01000000;
2204 #else
2205 rbase = 0x00000000;
2206 rlen = 0x01000000;
2207 #endif
2208 if (pci_check_host(&pci_main, cfg_base, cfg_len,
2209 mem_base, mem_len, io_base, io_len, rbase, rlen,
2210 0x106b, 0x001F) == 0) {
2211 isa_io_base = io_base;
2212 busnum++;
2214 for (curh = pci_main; curh->next != NULL; curh = curh->next)
2215 continue;
2216 pci_check_devices(curh);
2218 #if 0
2219 cfg_base = 0xF4000000;
2220 cfg_len = 0x02000000;
2221 mem_base = 0xA0000000;
2222 mem_len = 0x10000000;
2223 io_base = 0xF4000000;
2224 io_len = 0x00800000;
2225 rbase = 0xF5000000;
2226 rlen = 0x01000000;
2227 if (pci_check_host(&pci_main, cfg_base, cfg_len,
2228 mem_base, mem_len, io_base, io_len, rbase, rlen,
2229 0x106b, 0x001F) == 0) {
2230 busnum++;
2232 for (curh = pci_main; curh->next != NULL; curh = curh->next)
2233 continue;
2234 pci_check_devices(curh);
2235 #endif
2236 break;
2237 case ARCH_POP:
2238 /* TODO */
2239 break;
2241 printf("PCI probe done (%p)\n", pci_main);
2243 return pci_main;
2246 void pci_get_mem_range (pci_host_t *host, uint32_t *start, uint32_t *len)
2248 *start = host->bridge->mem_base;
2249 *len = host->bridge->mem_len;