4 * This driver is compliant to the
5 * PCI bus binding to IEEE 1275-1994 Rev 2.1
7 * (C) 2004 Stefan Reinauer <stepan@openbios.org>
8 * (C) 2005 Ed Schouten <ed@fxq.nl>
10 * Some parts from OpenHackWare-0.4, Copyright (c) 2004-2005 Jocelyn Mayer
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
19 #include "libopenbios/bindings.h"
20 #include "libopenbios/ofmem.h"
21 #include "kernel/kernel.h"
22 #include "drivers/pci.h"
23 #include "libc/byteorder.h"
24 #include "libc/vsprintf.h"
26 #include "drivers/drivers.h"
27 #include "drivers/vga.h"
28 #include "packages/video.h"
29 #include "libopenbios/video.h"
32 #include "pci_database.h"
33 #ifdef CONFIG_DRIVER_MACIO
37 #ifdef CONFIG_DRIVER_USB
38 #include "drivers/usb.h"
41 #if defined (CONFIG_DEBUG_PCI)
42 # define PCI_DPRINTF(format, ...) printk(format, ## __VA_ARGS__)
44 # define PCI_DPRINTF(format, ...) do { } while (0)
47 #define set_bool_property(ph, name) set_property(ph, name, NULL, 0);
49 /* DECLARE data structures for the nodes. */
51 DECLARE_UNNAMED_NODE( ob_pci_bus_node, INSTALL_OPEN, 2*sizeof(int) );
52 DECLARE_UNNAMED_NODE( ob_pci_simple_node, INSTALL_OPEN, 2*sizeof(int) );
53 DECLARE_UNNAMED_NODE( ob_pci_empty_node, 0, 2*sizeof(int) );
55 const pci_arch_t *arch;
57 #define IS_NOT_RELOCATABLE 0x80000000
58 #define IS_PREFETCHABLE 0x40000000
59 #define IS_ALIASED 0x20000000
62 CONFIGURATION_SPACE = 0,
68 static int encode_int32_cells(int num_cells, u32 *prop, ucell val)
73 for (i=0; i < num_cells; ++i) {
74 prop[num_cells - i - 1] = val;
82 static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code,
83 pci_addr dev, uint8_t reg, uint64_t addr)
88 phys[0] = flags | (space_code << 24) | dev | reg;
101 static inline int pci_encode_size(u32 *prop, uint64_t size)
103 return encode_int32_cells(2, prop, size);
106 static int host_address_cells(void)
108 return get_int_property(find_dev("/"), "#address-cells", NULL);
111 static int host_encode_phys_addr(u32 *prop, ucell addr)
113 return encode_int32_cells(host_address_cells(), prop, addr);
116 static int host_size_cells(void)
118 return get_int_property(find_dev("/"), "#size-cells", NULL);
122 static int parent_address_cells(void)
124 phandle_t parent_ph = ih_to_phandle(my_parent());
125 return get_int_property(parent_ph, "#address-cells", NULL);
128 static int parent_size_cells(void)
130 phandle_t parent_ph = ih_to_phandle(my_parent());
131 return get_int_property(parent_ph, "#size-cells", NULL);
135 #if defined(CONFIG_DEBUG_PCI)
136 static void dump_reg_property(const char* description, int nreg, u32 *reg)
139 printk("%s reg", description);
140 for (i=0; i < nreg; ++i) {
141 printk(" %08X", reg[i]);
147 static unsigned long pci_bus_addr_to_host_addr(uint32_t ba)
149 return arch->host_pci_base + (unsigned long)ba;
153 ob_pci_open(int *idx)
160 ob_pci_close(int *idx)
165 ob_pci_initialize(int *idx)
169 /* ( str len -- phys.lo phys.mid phys.hi ) */
172 ob_pci_decode_unit(int *idx)
175 const char *arg = pop_fstr_copy();
176 int dev, fn, reg, ss, n, p, t;
177 int bus = 0; /* no information */
180 PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx);
190 n = IS_NOT_RELOCATABLE;
201 /* DD,F,RR,NNNNNNNN */
203 dev = strtol(ptr, &ptr, 16);
205 fn = strtol(ptr, &ptr, 16);
207 reg = strtol(ptr, &ptr, 16);
209 lo = strtol(ptr, &ptr, 16);
212 } else if (*ptr == 'm') {
213 ss = MEMORY_SPACE_32;
224 /* DD,F,RR,NNNNNNNN */
226 dev = strtol(ptr, &ptr, 16);
228 fn = strtol(ptr, &ptr, 16);
230 reg = strtol(ptr, &ptr, 16);
232 lo = strtol(ptr, &ptr, 16);
235 } else if (*ptr == 'x') {
236 unsigned long long addr64;
237 ss = MEMORY_SPACE_64;
244 /* DD,F,RR,NNNNNNNNNNNNNNNN */
246 dev = strtol(ptr, &ptr, 16);
248 fn = strtol(ptr, &ptr, 16);
250 reg = strtol(ptr, &ptr, 16);
252 addr64 = strtoll(ptr, &ptr, 16);
257 ss = CONFIGURATION_SPACE;
258 /* "DD" or "DD,FF" */
259 dev = strtol(ptr, &ptr, 16);
262 fn = strtol(ptr, NULL, 16);
269 hi = n | p | t | (ss << 24) | (bus << 16) | (dev << 11) | (fn << 8) | reg;
275 PCI_DPRINTF("ob_pci_decode_unit idx=%p addr="
276 FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n",
280 /* ( phys.lo phy.mid phys.hi -- str len ) */
283 ob_pci_encode_unit(int *idx)
289 int n, p, t, ss, dev, fn, reg;
291 n = hi & IS_NOT_RELOCATABLE;
292 p = hi & IS_PREFETCHABLE;
294 ss = (hi >> 24) & 0x03;
296 dev = (hi >> 11) & 0x1F;
297 fn = (hi >> 8) & 0x07;
301 case CONFIGURATION_SPACE:
303 if (fn == 0) /* DD */
304 snprintf(buf, sizeof(buf), "%x", dev);
306 snprintf(buf, sizeof(buf), "%x,%x", dev, fn);
311 /* [n]i[t]DD,F,RR,NNNNNNNN */
312 snprintf(buf, sizeof(buf), "%si%s%x,%x,%x," FMT_ucellx,
313 n ? "n" : "", /* relocatable */
314 t ? "t" : "", /* aliased */
315 dev, fn, reg, t ? lo & 0x03FF : lo);
318 case MEMORY_SPACE_32:
320 /* [n]m[t][p]DD,F,RR,NNNNNNNN */
321 snprintf(buf, sizeof(buf), "%sm%s%s%x,%x,%x," FMT_ucellx,
322 n ? "n" : "", /* relocatable */
323 t ? "t" : "", /* aliased */
324 p ? "p" : "", /* prefetchable */
328 case MEMORY_SPACE_64:
330 /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN */
331 snprintf(buf, sizeof(buf), "%sx%s%x,%x,%x,%llx",
332 n ? "n" : "", /* relocatable */
333 p ? "p" : "", /* prefetchable */
334 dev, fn, reg, ((long long)mid << 32) | (long long)lo);
339 PCI_DPRINTF("ob_pci_encode_unit space=%d dev=%d fn=%d buf=%s\n",
343 /* ( pci-addr.lo pci-addr.hi size -- virt ) */
346 ob_pci_map_in(int *idx)
352 PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx);
358 phys = pci_bus_addr_to_host_addr(ba);
360 #if defined(CONFIG_OFMEM)
361 ofmem_claim_phys(phys, size, 0);
363 #if defined(CONFIG_PPC)
364 /* For some reason PPC gets upset when virt != phys for map-in... */
365 virt = ofmem_claim_virt(phys, size, 0);
367 virt = ofmem_claim_virt(-1, size, size);
370 ofmem_map(phys, virt, size, ofmem_arch_io_translation_mode(phys));
373 virt = size; /* Keep compiler quiet */
380 NODE_METHODS(ob_pci_bus_node) = {
381 { NULL, ob_pci_initialize },
382 { "open", ob_pci_open },
383 { "close", ob_pci_close },
384 { "decode-unit", ob_pci_decode_unit },
385 { "encode-unit", ob_pci_encode_unit },
386 { "pci-map-in", ob_pci_map_in },
389 NODE_METHODS(ob_pci_simple_node) = {
390 { NULL, ob_pci_initialize },
391 { "open", ob_pci_open },
392 { "close", ob_pci_close },
395 NODE_METHODS(ob_pci_empty_node) = {
396 { NULL, ob_pci_initialize }
399 static void pci_set_bus_range(const pci_config_t *config)
401 phandle_t dev = find_dev(config->path);
404 props[0] = config->secondary_bus;
405 props[1] = config->subordinate_bus;
407 PCI_DPRINTF("setting bus range for %s PCI device, "
408 "package handle " FMT_ucellx " "
409 "bus primary=%d secondary=%d subordinate=%d\n",
413 config->secondary_bus,
414 config->subordinate_bus);
417 set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0]));
420 static void pci_host_set_reg(phandle_t phandle)
422 phandle_t dev = phandle;
424 /* at most 2 integers for address and size */
428 ncells += encode_int32_cells(host_address_cells(), props + ncells,
431 ncells += encode_int32_cells(host_size_cells(), props + ncells,
434 set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
436 #if defined(CONFIG_DEBUG_PCI)
437 dump_reg_property("pci_host_set_reg", 4, props);
441 /* child-phys : parent-phys : size */
442 /* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */
444 static void pci_host_set_ranges(const pci_config_t *config)
446 phandle_t dev = get_cur_dev();
451 /* first encode PCI configuration space */
453 ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
455 ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr);
456 ncells += pci_encode_size(props + ncells, arch->cfg_len);
460 ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE,
462 ncells += host_encode_phys_addr(props + ncells, arch->io_base);
463 ncells += pci_encode_size(props + ncells, arch->io_len);
466 ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
468 ncells += host_encode_phys_addr(props + ncells, arch->rbase);
469 ncells += pci_encode_size(props + ncells, arch->rlen);
471 if (arch->pci_mem_base) {
472 ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
473 config->dev, 0, arch->pci_mem_base);
474 ncells += host_encode_phys_addr(props + ncells, arch->host_pci_base +
476 ncells += pci_encode_size(props + ncells, arch->mem_len);
478 set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
481 int host_config_cb(const pci_config_t *config)
483 //XXX this overrides "reg" property
484 pci_host_set_reg(get_cur_dev());
485 pci_host_set_ranges(config);
490 static int sabre_configure(phandle_t dev)
494 props[0] = 0xc0000000;
495 props[1] = 0x20000000;
496 set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0]));
498 set_property(dev, "#virtual-dma-size-cells", (char *)props,
500 set_property(dev, "#virtual-dma-addr-cells", (char *)props,
503 set_property(dev, "no-streaming-cache", (char *)props, 0);
505 props[0] = 0x000007f0;
506 props[1] = 0x000007ee;
507 props[2] = 0x000007ef;
508 props[3] = 0x000007e5;
509 set_property(dev, "interrupts", (char *)props, 4 * sizeof(props[0]));
510 props[0] = 0x0000001f;
511 set_property(dev, "upa-portid", (char *)props, 1 * sizeof(props[0]));
515 int sabre_config_cb(const pci_config_t *config)
517 host_config_cb(config);
519 return sabre_configure(get_cur_dev());
522 int bridge_config_cb(const pci_config_t *config)
526 aliases = find_dev("/aliases");
527 set_property(aliases, "bridge", config->path, strlen(config->path) + 1);
532 int ide_config_cb2 (const pci_config_t *config)
534 ob_ide_init(config->path,
535 config->assigned[0] & ~0x0000000F,
536 (config->assigned[1] & ~0x0000000F) + 2,
537 config->assigned[2] & ~0x0000000F,
538 (config->assigned[3] & ~0x0000000F) + 2);
542 int eth_config_cb (const pci_config_t *config)
544 phandle_t ph = get_cur_dev();
546 set_property(ph, "network-type", "ethernet", 9);
547 set_property(ph, "removable", "network", 8);
548 set_property(ph, "category", "net", 4);
553 static inline void pci_decode_pci_addr(pci_addr addr, int *flags,
554 int *space_code, uint32_t *mask)
559 *space_code = IO_SPACE;
563 *space_code = MEMORY_SPACE_64;
564 *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */
566 *space_code = MEMORY_SPACE_32;
570 *flags |= IS_PREFETCHABLE;
578 * "Designing PCI Cards and Drivers for Power Macintosh Computers", p. 454
580 * "AAPL,address" provides an array of 32-bit logical addresses
581 * Nth entry corresponding to Nth "assigned-address" base address entry.
584 static void pci_set_AAPL_address(const pci_config_t *config)
586 phandle_t dev = get_cur_dev();
591 for (i = 0; i < 6; i++) {
592 if (!config->assigned[i] || !config->sizes[i])
594 props[ncells++] = config->assigned[i] & ~0x0000000F;
597 set_property(dev, "AAPL,address", (char *)props,
598 ncells * sizeof(cell));
601 static void pci_set_assigned_addresses(phandle_t phandle,
602 const pci_config_t *config, int num_bars)
604 phandle_t dev = phandle;
609 int flags, space_code;
612 for (i = 0; i < num_bars; i++) {
613 /* consider only bars with non-zero region size */
614 if (!config->sizes[i])
616 pci_decode_pci_addr(config->assigned[i],
617 &flags, &space_code, &mask);
619 ncells += pci_encode_phys_addr(props + ncells,
620 flags, space_code, config->dev,
621 PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
622 config->assigned[i] & ~mask);
624 props[ncells++] = 0x00000000;
625 props[ncells++] = config->sizes[i];
628 set_property(dev, "assigned-addresses", (char *)props,
629 ncells * sizeof(props[0]));
632 /* call after writing "reg" property to update config->path */
633 static void ob_pci_reload_device_path(phandle_t phandle, pci_config_t *config)
635 /* since "name" and "reg" are now assigned
636 we need to reload current node name */
639 fword("get-package-path");
640 char *new_path = pop_fstr_copy();
642 if (0 != strcmp(config->path, new_path)) {
643 PCI_DPRINTF("\n=== CHANGED === package path old=%s new=%s\n",
644 config->path, new_path);
645 strncpy(config->path, new_path, sizeof(config->path));
646 config->path[sizeof(config->path)-1] = '\0';
650 PCI_DPRINTF("\n=== package path old=%s new=NULL\n", config->path);
654 static void pci_set_reg(phandle_t phandle,
655 pci_config_t *config, int num_bars)
657 phandle_t dev = phandle;
662 int space_code, flags;
666 /* first (addr, size) pair is the beginning of configuration address space */
667 ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
670 ncells += pci_encode_size(props + ncells, 0);
672 for (i = 0; i < num_bars; i++) {
673 /* consider only bars with non-zero region size */
674 if (!config->sizes[i])
677 pci_decode_pci_addr(config->regions[i],
678 &flags, &space_code, &mask);
680 ncells += pci_encode_phys_addr(props + ncells,
681 flags, space_code, config->dev,
682 PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
683 config->regions[i] & ~mask);
686 ncells += pci_encode_size(props + ncells, config->sizes[i]);
689 set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
690 ob_pci_reload_device_path(dev, config);
692 #if defined(CONFIG_DEBUG_PCI)
693 dump_reg_property("pci_set_reg", ncells, props);
698 static void pci_set_ranges(const pci_config_t *config)
700 phandle_t dev = get_cur_dev();
709 for (i = 0; i < 6; i++) {
710 if (!config->assigned[i] || !config->sizes[i])
715 props[ncells++] = 0x00000000;
719 pci_decode_pci_addr(config->assigned[i],
720 &flags, &space_code, &mask);
721 ncells += pci_encode_phys_addr(props + ncells, flags, space_code,
722 config->dev, 0x10 + i * 4,
723 config->assigned[i] & ~mask);
727 props[ncells++] = config->sizes[i];
729 set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
732 int macio_heathrow_config_cb (const pci_config_t *config)
734 pci_set_ranges(config);
736 #ifdef CONFIG_DRIVER_MACIO
737 ob_macio_heathrow_init(config->path, config->assigned[0] & ~0x0000000F);
742 int macio_keylargo_config_cb (const pci_config_t *config)
744 pci_set_ranges(config);
746 #ifdef CONFIG_DRIVER_MACIO
747 ob_macio_keylargo_init(config->path, config->assigned[0] & ~0x0000000F);
752 int vga_config_cb (const pci_config_t *config)
755 uint32_t rom_size, size;
758 if (config->assigned[0] != 0x00000000) {
761 rom = pci_bus_addr_to_host_addr(config->assigned[1] & ~0x0000000F);
762 rom_size = config->sizes[1];
769 p = (const char *)rom;
770 if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') {
771 size = *(uint32_t*)(p + 4);
772 set_property(ph, "driver,AAPL,MacOS,PowerPC", p + 8, size);
776 /* Currently we don't read FCode from the hardware but execute it directly */
777 feval("['] vga-driver-fcode 2 cells + 1 byte-load");
780 /* Install special words for Mac On Linux */
789 int ebus_config_cb(const pci_config_t *config)
791 #ifdef CONFIG_DRIVER_EBUS
792 phandle_t dev = get_cur_dev();
797 int flags, space_code;
802 props[3] = find_dev("/");
804 set_property(dev, "interrupt-map", (char *)props, 5 * sizeof(props[0]));
806 props[0] = 0x000001ff;
807 props[1] = 0xffffffff;
809 set_property(dev, "interrupt-map-mask", (char *)props, 3 * sizeof(props[0]));
811 /* Build ranges property from the BARs */
813 for (i = 0; i < 6; i++) {
814 /* consider only bars with non-zero region size */
815 if (!config->sizes[i])
818 pci_decode_pci_addr(config->assigned[i],
819 &flags, &space_code, &mask);
821 props[ncells++] = PCI_BASE_ADDR_0 + (i * sizeof(uint32_t));
822 props[ncells++] = 0x0;
824 ncells += pci_encode_phys_addr(props + ncells,
825 flags, space_code, config->dev,
826 PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
829 props[ncells++] = config->sizes[i];
832 set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
834 /* Build eeprom node */
851 fword("device-name");
852 fword("finish-device");
854 #ifdef CONFIG_DRIVER_FLOPPY
855 ob_floppy_init(config->path, "fdthree", 0x3f0ULL, 0);
857 #ifdef CONFIG_DRIVER_PC_SERIAL
858 ob_pc_serial_init(config->path, "su", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x3f8ULL, 0);
860 #ifdef CONFIG_DRIVER_PC_KBD
861 ob_pc_kbd_init(config->path, "kb_ps2", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x60ULL, 0);
867 int i82378_config_cb(const pci_config_t *config)
869 #ifdef CONFIG_DRIVER_PC_SERIAL
870 ob_pc_serial_init(config->path, "serial", arch->io_base, 0x3f8ULL, 0);
872 #ifdef CONFIG_DRIVER_PC_KBD
873 ob_pc_kbd_init(config->path, "8042", arch->io_base, 0x60ULL, 0);
875 #ifdef CONFIG_DRIVER_IDE
876 ob_ide_init(config->path, 0x1f0, 0x3f6, 0x170, 0x376);
882 int usb_ohci_config_cb(const pci_config_t *config)
884 #ifdef CONFIG_DRIVER_USB
885 ob_usb_ohci_init(config->path, 0x80000000 | config->dev);
890 static void ob_pci_add_properties(phandle_t phandle,
891 pci_addr addr, const pci_dev_t *pci_dev,
892 const pci_config_t *config, int num_bars)
894 /* cannot use get_cur_dev() path resolution since "name" and "reg"
895 properties are being changed */
896 phandle_t dev=phandle;
898 uint16_t vendor_id, device_id;
903 vendor_id = pci_config_read16(addr, PCI_VENDOR_ID);
904 device_id = pci_config_read16(addr, PCI_DEVICE_ID);
905 rev = pci_config_read8(addr, PCI_REVISION_ID);
906 class_prog = pci_config_read8(addr, PCI_CLASS_PROG);
907 class_code = pci_config_read16(addr, PCI_CLASS_DEVICE);
912 push_str(pci_dev->name);
913 fword("encode-string");
918 snprintf(path, sizeof(path),
919 "pci%x,%x", vendor_id, device_id);
921 fword("encode-string");
926 PCI_DPRINTF("*** missing pci_dev\n");
929 /* create properties as described in 2.5 */
931 set_int_property(dev, "vendor-id", vendor_id);
932 set_int_property(dev, "device-id", device_id);
933 set_int_property(dev, "revision-id", rev);
934 set_int_property(dev, "class-code", class_code << 8 | class_prog);
936 if (config->irq_pin) {
937 OLDWORLD(set_int_property(dev, "AAPL,interrupts",
939 #if defined(CONFIG_SPARC64)
940 set_int_property(dev, "interrupts", config->irq_pin);
942 NEWWORLD(set_int_property(dev, "interrupts", config->irq_pin));
946 set_int_property(dev, "min-grant", pci_config_read8(addr, PCI_MIN_GNT));
947 set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT));
949 status=pci_config_read16(addr, PCI_STATUS);
951 set_int_property(dev, "devsel-speed",
952 (status&PCI_STATUS_DEVSEL_MASK)>>10);
954 if(status&PCI_STATUS_FAST_BACK)
955 set_bool_property(dev, "fast-back-to-back");
956 if(status&PCI_STATUS_66MHZ)
957 set_bool_property(dev, "66mhz-capable");
958 if(status&PCI_STATUS_UDF)
959 set_bool_property(dev, "udf-supported");
961 id=pci_config_read16(addr, PCI_SUBSYSTEM_VENDOR_ID);
963 set_int_property(dev, "subsystem-vendor-id", id);
964 id=pci_config_read16(addr, PCI_SUBSYSTEM_ID);
966 set_int_property(dev, "subsystem-id", id);
968 set_int_property(dev, "cache-line-size",
969 pci_config_read16(addr, PCI_CACHE_LINE_SIZE));
973 push_str(pci_dev->type);
974 fword("encode-string");
975 push_str("device_type");
978 if (pci_dev->model) {
979 push_str(pci_dev->model);
980 fword("encode-string");
985 set_property(dev, "compatible",
986 pci_dev->compat, pci_compat_len(pci_dev));
989 set_int_property(dev, "#address-cells",
992 set_int_property(dev, "#size-cells",
995 set_int_property(dev, "#interrupt-cells",
999 pci_set_assigned_addresses(phandle, config, num_bars);
1000 OLDWORLD(pci_set_AAPL_address(config));
1006 static char pci_xbox_blacklisted (int bus, int devnum, int fn)
1009 * The Xbox MCPX chipset is a derivative of the nForce 1
1010 * chipset. It almost has the same bus layout; some devices
1011 * cannot be used, because they have been removed.
1015 * Devices 00:00.1 and 00:00.2 used to be memory controllers on
1016 * the nForce chipset, but on the Xbox, using them will lockup
1019 if ((bus == 0) && (devnum == 0) && ((fn == 1) || (fn == 2)))
1023 * Bus 1 only contains a VGA controller at 01:00.0. When you try
1024 * to probe beyond that device, you only get garbage, which
1025 * could cause lockups.
1027 if ((bus == 1) && ((devnum != 0) || (fn != 0)))
1031 * Bus 2 used to contain the AGP controller, but the Xbox MCPX
1032 * doesn't have one. Probing it can cause lockups.
1038 * The device is not blacklisted.
1044 static void ob_pci_configure_bar(pci_addr addr, pci_config_t *config,
1045 int reg, int config_addr,
1047 unsigned long *mem_base,
1048 unsigned long *io_base)
1050 uint32_t smask, amask, size, reloc, min_align;
1053 config->assigned[reg] = 0x00000000;
1054 config->sizes[reg] = 0x00000000;
1056 if ((*p_omask & 0x0000000f) == 0x4) {
1057 /* 64 bits memory mapping */
1058 PCI_DPRINTF("Skipping 64 bit BARs for %s\n", config->path);
1062 config->regions[reg] = pci_config_read32(addr, config_addr);
1064 /* get region size */
1066 pci_config_write32(addr, config_addr, 0xffffffff);
1067 smask = pci_config_read32(addr, config_addr);
1068 if (smask == 0x00000000 || smask == 0xffffffff)
1071 if (smask & 0x00000001 && reg != 6) {
1079 min_align = 1 << 16;
1082 smask |= 1; /* ROM */
1085 *p_omask = smask & amask;
1087 size = (~smask) + 1;
1088 config->sizes[reg] = size;
1090 if (size < min_align)
1092 reloc = (reloc + size -1) & ~(size - 1);
1093 if (*io_base == base) {
1094 PCI_DPRINTF("changing io_base from 0x%lx to 0x%x\n",
1095 *io_base, reloc + size);
1096 *io_base = reloc + size;
1098 PCI_DPRINTF("changing mem_base from 0x%lx to 0x%x\n",
1099 *mem_base, reloc + size);
1100 *mem_base = reloc + size;
1102 PCI_DPRINTF("Configuring BARs for %s: reloc 0x%x omask 0x%x "
1103 "io_base 0x%lx mem_base 0x%lx size 0x%x\n",
1104 config->path, reloc, *p_omask, *io_base, *mem_base, size);
1105 pci_config_write32(addr, config_addr, reloc | *p_omask);
1106 config->assigned[reg] = reloc | *p_omask;
1109 static void ob_pci_configure_irq(pci_addr addr, pci_config_t *config)
1111 uint8_t irq_pin, irq_line;
1113 irq_pin = pci_config_read8(addr, PCI_INTERRUPT_PIN);
1115 config->irq_pin = irq_pin;
1116 irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3;
1117 irq_line = arch->irqs[irq_pin];
1118 pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line);
1119 config->irq_line = irq_line;
1121 config->irq_line = -1;
1125 ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
1126 unsigned long *mem_base, unsigned long *io_base)
1132 pci_addr config_addr;
1134 ob_pci_configure_irq(addr, config);
1137 for (reg = 0; reg < num_regs; ++reg) {
1138 config_addr = PCI_BASE_ADDR_0 + reg * 4;
1140 ob_pci_configure_bar(addr, config, reg, config_addr,
1146 config_addr = rom_bar;
1147 ob_pci_configure_bar(addr, config, reg, config_addr,
1148 &omask, mem_base, io_base);
1150 cmd = pci_config_read16(addr, PCI_COMMAND);
1151 cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
1152 pci_config_write16(addr, PCI_COMMAND, cmd);
1155 static void ob_configure_pci_device(const char* parent_path,
1156 int *bus_num, unsigned long *mem_base, unsigned long *io_base,
1157 int bus, int devnum, int fn, int *p_is_multi);
1159 static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base,
1160 unsigned long *io_base, const char *path,
1163 int devnum, fn, is_multi;
1165 PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path);
1167 for (devnum = 0; devnum < 32; devnum++) {
1169 for (fn = 0; fn==0 || (is_multi && fn<8); fn++) {
1170 ob_configure_pci_device(path, bus_num, mem_base, io_base,
1171 bus, devnum, fn, &is_multi);
1177 static void ob_configure_pci_bridge(pci_addr addr,
1178 int *bus_num, unsigned long *mem_base,
1179 unsigned long *io_base,
1180 int primary_bus, pci_config_t *config)
1182 config->primary_bus = primary_bus;
1183 pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus);
1185 config->secondary_bus = *bus_num;
1186 pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus);
1188 config->subordinate_bus = 0xff;
1189 pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
1191 PCI_DPRINTF("scanning new pci bus %u under bridge %s\n",
1192 config->secondary_bus, config->path);
1194 /* make pci bridge parent device, prepare for recursion */
1196 ob_scan_pci_bus(bus_num, mem_base, io_base,
1197 config->path, config->secondary_bus);
1199 /* bus scan updates *bus_num to last revealed pci bus number */
1200 config->subordinate_bus = *bus_num;
1201 pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
1203 PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n",
1204 config->path, config->primary_bus, config->secondary_bus,
1205 config->subordinate_bus);
1207 pci_set_bus_range(config);
1210 static int ob_pci_read_identification(int bus, int devnum, int fn,
1211 int *p_vid, int *p_did,
1212 uint8_t *p_class, uint8_t *p_subclass)
1219 if (pci_xbox_blacklisted (bus, devnum, fn))
1222 addr = PCI_ADDR(bus, devnum, fn);
1223 vid = pci_config_read16(addr, PCI_VENDOR_ID);
1224 did = pci_config_read16(addr, PCI_DEVICE_ID);
1226 if (vid==0xffff || vid==0) {
1238 ccode = pci_config_read16(addr, PCI_CLASS_DEVICE);
1241 *p_class = ccode >> 8;
1245 *p_subclass = ccode;
1251 static void ob_configure_pci_device(const char* parent_path,
1252 int *bus_num, unsigned long *mem_base, unsigned long *io_base,
1253 int bus, int devnum, int fn, int *p_is_multi)
1258 pci_config_t config = {};
1259 const pci_dev_t *pci_dev;
1260 uint8_t class, subclass, iface;
1261 int num_bars, rom_bar;
1263 phandle_t phandle = 0;
1264 int is_host_bridge = 0;
1266 if (!ob_pci_read_identification(bus, devnum, fn, &vid, &did, &class, &subclass)) {
1270 addr = PCI_ADDR(bus, devnum, fn);
1271 iface = pci_config_read8(addr, PCI_CLASS_PROG);
1273 pci_dev = pci_find_device(class, subclass, iface,
1276 PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn,
1279 htype = pci_config_read8(addr, PCI_HEADER_TYPE);
1283 *p_is_multi = htype & 0x80;
1287 /* stop adding host bridge accessible from it's primary bus
1288 PCI host bridge is to be added by host code
1290 if (class == PCI_BASE_CLASS_BRIDGE &&
1291 subclass == PCI_SUBCLASS_BRIDGE_HOST) {
1295 if (is_host_bridge) {
1296 /* reuse device tree node */
1297 PCI_DPRINTF("host bridge found - ");
1298 snprintf(config.path, sizeof(config.path),
1300 } else if (pci_dev == NULL || pci_dev->name == NULL) {
1301 snprintf(config.path, sizeof(config.path),
1302 "%s/pci%x,%x", parent_path, vid, did);
1305 snprintf(config.path, sizeof(config.path),
1306 "%s/%s", parent_path, pci_dev->name);
1309 PCI_DPRINTF("%s - ", config.path);
1311 config.dev = addr & 0x00FFFFFF;
1314 case PCI_BASE_CLASS_BRIDGE:
1315 if (subclass != PCI_SUBCLASS_BRIDGE_HOST) {
1316 REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle);
1319 case PCI_CLASS_DISPLAY:
1320 REGISTER_NAMED_NODE_PHANDLE(ob_pci_empty_node, config.path, phandle);
1323 REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle);
1327 if (is_host_bridge) {
1328 phandle = find_dev(config.path);
1330 if (get_property(phandle, "vendor-id", NULL)) {
1331 PCI_DPRINTF("host bridge already configured\n");
1336 activate_dev(phandle);
1338 if (htype & PCI_HEADER_TYPE_BRIDGE) {
1340 rom_bar = PCI_ROM_ADDRESS1;
1343 rom_bar = PCI_ROM_ADDRESS;
1346 ob_pci_configure(addr, &config, num_bars, rom_bar,
1349 ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars);
1351 if (!is_host_bridge) {
1352 pci_set_reg(phandle, &config, num_bars);
1355 /* call device-specific configuration callback */
1356 if (pci_dev && pci_dev->config_cb) {
1357 //activate_device(config.path);
1358 pci_dev->config_cb(&config);
1361 /* device is configured so we may move it out of scope */
1364 /* scan bus behind bridge device */
1365 //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) {
1366 if ( class == PCI_BASE_CLASS_BRIDGE &&
1367 ( subclass == PCI_SUBCLASS_BRIDGE_PCI ||
1368 subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) {
1370 if (subclass == PCI_SUBCLASS_BRIDGE_PCI) {
1371 /* reserve next pci bus number for this PCI bridge */
1375 ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config);
1379 static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigned long io_base)
1381 /* Create an available property for both memory and IO space */
1386 ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, 0, 0, mem_base);
1387 ncells += pci_encode_size(props + ncells, arch->mem_len - mem_base);
1388 ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, 0, 0, io_base);
1389 ncells += pci_encode_size(props + ncells, arch->io_len - io_base);
1391 set_property(host, "available", (char *)props, ncells * sizeof(props[0]));
1394 /* Convert device/irq pin to interrupt property */
1395 #define SUN4U_INTERRUPT(dev, irq_pin) \
1396 ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f)
1398 static void ob_pci_host_set_interrupt_map(phandle_t host)
1400 phandle_t dnode = 0;
1404 #if defined(CONFIG_PPC)
1405 phandle_t target_node;
1407 /* Oldworld macs do interrupt maps differently */
1411 dnode = dt_iterate_type(0, "open-pic");
1413 /* patch in openpic interrupt-parent properties */
1414 target_node = find_dev("/pci/mac-io");
1415 set_int_property(target_node, "interrupt-parent", dnode);
1417 target_node = find_dev("/pci/mac-io/escc/ch-a");
1418 set_int_property(target_node, "interrupt-parent", dnode);
1420 target_node = find_dev("/pci/mac-io/escc/ch-b");
1421 set_int_property(target_node, "interrupt-parent", dnode);
1423 /* QEMU only emulates 2 of the 3 ata buses currently */
1424 /* On a new world Mac these are not numbered but named by the
1425 * ATA version they support. Thus we have: ata-3, ata-3, ata-4
1426 * On g3beige they all called just ide.
1427 * We take ata-3 and ata-4 which seems to work for both
1428 * at least for clients we care about */
1429 target_node = find_dev("/pci/mac-io/ata-3");
1430 set_int_property(target_node, "interrupt-parent", dnode);
1432 target_node = find_dev("/pci/mac-io/ata-4");
1433 set_int_property(target_node, "interrupt-parent", dnode);
1435 target_node = find_dev("/pci/mac-io/via-cuda");
1436 set_int_property(target_node, "interrupt-parent", dnode);
1438 target_node = find_dev("/pci");
1439 set_int_property(target_node, "interrupt-parent", dnode);
1441 /* openpic interrupt mapping */
1442 for (i = 0; i < (7*8); i += 7) {
1443 props[i + PCI_INT_MAP_PCI0] = 0;
1444 props[i + PCI_INT_MAP_PCI1] = 0;
1445 props[i + PCI_INT_MAP_PCI2] = 0;
1446 props[i + PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1
1447 props[i + PCI_INT_MAP_PIC_HANDLE] = dnode;
1448 props[i + PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7];
1449 props[i + PCI_INT_MAP_PIC_POL] = 3;
1451 set_property(host, "interrupt-map", (char *)props, 7 * 8 * sizeof(props[0]));
1453 props[PCI_INT_MAP_PCI0] = 0;
1454 props[PCI_INT_MAP_PCI1] = 0;
1455 props[PCI_INT_MAP_PCI2] = 0;
1456 props[PCI_INT_MAP_PCI_INT] = 0x7;
1458 set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
1460 #elif defined(CONFIG_SPARC64)
1465 /* Set interrupt-map for PCI devices with an interrupt pin present */
1472 if (get_int_property(dnode, "interrupts", &len)) {
1473 reg = get_property(dnode, "reg", &len);
1477 for (i = 0; i < (len / sizeof(u32)); i += 5) {
1480 /* Device address is in 1st 32-bit word of encoded PCI address for config space */
1481 if (!(addr & 0x03000000)) {
1482 ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0);
1483 props[ncells++] = 1; /* always interrupt pin 1 for QEMU */
1484 props[ncells++] = host;
1485 props[ncells++] = SUN4U_INTERRUPT(addr, 1);
1495 set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0]));
1497 props[0] = 0x0000f800;
1501 set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
1505 int ob_pci_init(void)
1507 int bus, devnum, fn;
1508 uint8_t class, subclass;
1509 unsigned long mem_base, io_base;
1511 pci_config_t config = {}; /* host bridge */
1512 phandle_t phandle_host = 0;
1514 PCI_DPRINTF("Initializing PCI host bridge...\n");
1516 activate_device("/");
1518 /* Find all PCI bridges */
1520 mem_base = arch->pci_mem_base;
1521 /* I/O ports under 0x400 are used by devices mapped at fixed
1527 for (devnum = 0; devnum < 32; devnum++) {
1528 /* scan only fn 0 */
1531 if (!ob_pci_read_identification(bus, devnum, fn,
1532 0, 0, &class, &subclass)) {
1536 if (class != PCI_BASE_CLASS_BRIDGE || subclass != PCI_SUBCLASS_BRIDGE_HOST) {
1540 /* create root node for host PCI bridge */
1543 snprintf(config.path, sizeof(config.path), "/pci");
1545 REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host);
1547 pci_host_set_reg(phandle_host);
1549 /* update device path after changing "reg" property */
1550 ob_pci_reload_device_path(phandle_host, &config);
1552 ob_configure_pci_device(config.path, &bus, &mem_base, &io_base,
1553 bus, devnum, fn, 0);
1555 /* we expect single host PCI bridge
1556 but this may be machine-specific */
1560 /* create available attributes for the PCI bridge */
1561 ob_pci_set_available(phandle_host, mem_base, io_base);
1563 /* configure the host bridge interrupt map */
1564 ob_pci_host_set_interrupt_map(phandle_host);