These mostly are cleanups up to pci bus scan amendment changes.
The pci bus scan is reworked, now we start with pci host bridge which will initiate primary bus scan. PCI-to-PCI bridges do the same.
Although bridges are still mostly unusable in qemu due to missing address space remappings one can now put e.g. ide and vga on sun4u behind secondary bus and see it is found correctly and can be configured.
With these applied my debian etch ppc installation still boots to shell, and helenos can get to video screen (with appropriate QEMU,VGA driver.) Another bonus point that on sparc64 recent linux "btext" boot console works (colors are a bit off though.)
---
Igor V. Kovalenko (10): ebus: set addressing to 2 address cells and 1 size cells ide: fix property data size video: framebuffer properties must be 32bit values pci: property encoding helpers pci: debug printk macros pci: bus scan amendment new style arch declarations for ppc/qemu pci: add host memory base to pci_arch_t pci: allow BARs with zero assigned address pci: assign relocatable address ranges
arch/ppc/qemu/init.c | 96 ++++-- arch/sparc64/openbios.c | 3 drivers/ide.c | 22 + drivers/pci.c | 652 +++++++++++++++++++++++++++------------- drivers/pci.h | 4 drivers/pci_database.c | 2 drivers/pci_database.h | 3 drivers/vga_vbe.c | 8 include/drivers/pci.h | 3 include/libopenbios/bindings.h | 8 libopenbios/bindings.c | 6 packages/video.c | 10 - 12 files changed, 549 insertions(+), 268 deletions(-)
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/pci_database.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/pci_database.c b/drivers/pci_database.c index ddff8f0..ac47621 100644 --- a/drivers/pci_database.c +++ b/drivers/pci_database.c @@ -354,7 +354,7 @@ static const pci_dev_t miscbrg_devices[] = { { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL, "ebus", "ebus", "pci108e,1000\0pciclass,068000\0", - 3, 2, 1, + 2, 1, 1, ebus_config_cb, NULL, }, {
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/ide.c | 22 +++++++++++----------- 1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/ide.c b/drivers/ide.c index 9ff420b..7006720 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -1369,7 +1369,7 @@ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, struct ide_channel *chan; int io_ports[IDE_MAX_CHANNELS]; int ctl_ports[IDE_MAX_CHANNELS]; - cell props[6]; + u32 props[6];
io_ports[0] = io_port0; ctl_ports[0] = ctl_port0 + 2; @@ -1428,17 +1428,17 @@ int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0,
dnode = find_dev(nodebuff);
-#ifndef CONFIG_PPC +#if !defined(CONFIG_PPC) && !defined(CONFIG_SPARC64) props[0]=14; props[1]=0; set_property(dnode, "interrupts", - (char *)&props, 2*sizeof(cell)); + (char *)&props, 2*sizeof(props[0])); #endif
props[0] = __cpu_to_be32(chan->io_regs[0]); props[1] = __cpu_to_be32(1); props[2] = __cpu_to_be32(8); props[3] = __cpu_to_be32(chan->io_regs[8]); props[4] = __cpu_to_be32(1); props[5] = __cpu_to_be32(2); - set_property(dnode, "reg", (char *)&props, 6*sizeof(cell)); + set_property(dnode, "reg", (char *)&props, 6*sizeof(props[0]));
IDE_DPRINTF(DEV_NAME": [io ports 0x%x-0x%x,0x%x]\n", current_channel, chan->io_regs[0], @@ -1523,7 +1523,7 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) int i, j; char nodebuff[128]; phandle_t dnode; - cell props[8]; + u32 props[8]; struct ide_channel *chan;
for (i = 0; i < nb_channels; i++, current_channel++) { @@ -1585,7 +1585,7 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) props[6] = 0x00000000; props[7] = 0x00000000; OLDWORLD(set_property(dnode, "AAPL,pio-timing", - (char *)&props, 8*sizeof(cell))); + (char *)&props, 8*sizeof(props[0])));
/* The first interrupt entry is the ide interrupt, the second the dbdma interrupt */ @@ -1610,25 +1610,25 @@ int macio_ide_init(const char *path, uint32_t addr, int nb_channels) props[1] = 0x00000000; /* XXX level triggered on real hw */ props[3] = 0x00000000; set_property(dnode, "interrupts", - (char *)&props, 4*sizeof(cell)); + (char *)&props, 4*sizeof(props[0])); set_int_property(dnode, "#interrupt-cells", 2); OLDWORLD(set_property(dnode, "AAPL,interrupts", - (char *)&props, 2*sizeof(cell))); + (char *)&props, 2*sizeof(props[0])));
props[0] = MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE; props[1] = MACIO_IDE_SIZE; props[2] = 0x00008b00 + i * 0x0200; props[3] = 0x0200; - set_property(dnode, "reg", (char *)&props, 4*sizeof(cell)); + set_property(dnode, "reg", (char *)&props, 4*sizeof(props[0]));
props[0] = addr + MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE; props[1] = addr + 0x00008b00 + i * 0x0200; OLDWORLD(set_property(dnode, "AAPL,address", - (char *)&props, 2*sizeof(cell))); + (char *)&props, 2*sizeof(props[0])));
props[0] = 0; OLDWORLD(set_property(dnode, "AAPL,bus-id", (char*)props, - 1 * sizeof(cell))); + 1 * sizeof(props[0]))); IDE_DPRINTF(DEV_NAME": [io ports 0x%lx]\n", current_channel, chan->mmio);
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/vga_vbe.c | 2 +- packages/video.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/vga_vbe.c b/drivers/vga_vbe.c index 6e26a6e..b1a95df 100644 --- a/drivers/vga_vbe.c +++ b/drivers/vga_vbe.c @@ -161,7 +161,7 @@ void vga_vbe_init(const char *path, unsigned long fb, uint32_t fb_size, set_int_property(ph, "height", height); set_int_property(ph, "depth", depth); set_int_property(ph, "linebytes", linebytes); - set_int_property(ph, "address", fb & ~0x0000000F); + set_int_property(ph, "address", (u32)(fb & ~0x0000000F));
chosen = find_dev("/chosen"); push_str(path); diff --git a/packages/video.c b/packages/video.c index be4d6a6..7c8ceca 100644 --- a/packages/video.c +++ b/packages/video.c @@ -320,11 +320,11 @@ init_video( unsigned long fb, int width, int height, int depth, int rb ) video.fb.depth = depth; video.fb.rb = rb; while( (ph=dt_iterate_type(ph, "display")) ) { - set_property( ph, "width", (char*)&video.fb.w, 4 ); - set_property( ph, "height", (char*)&video.fb.h, 4 ); - set_property( ph, "depth", (char*)&video.fb.depth, 4 ); - set_property( ph, "linebytes", (char*)&video.fb.rb, 4 ); - set_property( ph, "address", (char*)&video.fb.mphys, 4 ); + set_int_property( ph, "width", video.fb.w ); + set_int_property( ph, "height", video.fb.h ); + set_int_property( ph, "depth", video.fb.depth ); + set_int_property( ph, "linebytes", video.fb.rb ); + set_int_property( ph, "address", video.fb.mphys ); } video.has_video = 1; video.pal = malloc( 256 * sizeof(ulong) );
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/pci.c | 127 +++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 92 insertions(+), 35 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 7df418e..c080372 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -52,7 +52,21 @@ enum { MEMORY_SPACE_64 = 3, };
-static inline void pci_encode_phys_addr(u32 *phys, int flags, int space_code, +static int encode_int32_cells(int num_cells, u32 *prop, ucell val) +{ + int i = 0; + + /* hi ... lo */ + for (i=0; i < num_cells; ++i) { + prop[num_cells - i - 1] = val; + val >>= 16; + val >>= 16; + } + + return num_cells; +} + +static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code, pci_addr dev, uint8_t reg, uint64_t addr) {
@@ -67,8 +81,44 @@ static inline void pci_encode_phys_addr(u32 *phys, int flags, int space_code, /* phys.lo */
phys[2] = addr; + + return 3; }
+static inline int pci_encode_size(u32 *prop, uint64_t size) +{ + return encode_int32_cells(2, prop, size); +} + +static int host_address_cells(void) +{ + return get_int_property(find_dev("/"), "#address-cells", NULL); +} + +static int host_encode_phys_addr(u32 *prop, ucell addr) +{ + return encode_int32_cells(host_address_cells(), prop, addr); +} + +static int host_size_cells(void) +{ + return get_int_property(find_dev("/"), "#size-cells", NULL); +} + +/* +static int parent_address_cells(void) +{ + phandle_t parent_ph = ih_to_phandle(my_parent()); + return get_int_property(parent_ph, "#address-cells", NULL); +} + +static int parent_size_cells(void) +{ + phandle_t parent_ph = ih_to_phandle(my_parent()); + return get_int_property(parent_ph, "#size-cells", NULL); +} +*/ + static void ob_pci_open(int *idx) { @@ -318,14 +368,23 @@ static void pci_host_set_interrupt_map(const pci_config_t *config)
static void pci_host_set_reg(const pci_config_t *config) { - phandle_t dev = get_cur_dev(); - u32 props[2]; + phandle_t dev = get_cur_dev(); + /* at most 2 integers for address and size */ + u32 props[4]; + int ncells = 0; + + ncells += encode_int32_cells(host_address_cells(), props + ncells, + arch->cfg_base); + + ncells += encode_int32_cells(host_size_cells(), props + ncells, + arch->cfg_len);
- props[0] = arch->cfg_base; - props[1] = arch->cfg_len; - set_property(dev, "reg", (char *)props, 2 * sizeof(props[0])); + set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); }
+/* child-phys : parent-phys : size */ +/* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */ + static void pci_host_set_ranges(const pci_config_t *config) { phandle_t dev = get_cur_dev(); @@ -333,29 +392,31 @@ static void pci_host_set_ranges(const pci_config_t *config) int ncells;
ncells = 0; + /* first encode PCI configuration space */ + { + ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, + config->dev, 0, 0); + ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr); + ncells += pci_encode_size(props + ncells, arch->cfg_len); + } + if (arch->io_base) { - pci_encode_phys_addr(props + ncells, 0, IO_SPACE, + ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, config->dev, 0, 0); - ncells += 3; - props[ncells++] = arch->io_base; - props[ncells++] = 0x00000000; - props[ncells++] = arch->io_len; + ncells += host_encode_phys_addr(props + ncells, arch->io_base); + ncells += pci_encode_size(props + ncells, arch->io_len); } if (arch->rbase) { - pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, + ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, config->dev, 0, 0); - ncells += 3; - props[ncells++] = arch->rbase; - props[ncells++] = 0x00000000; - props[ncells++] = arch->rlen; + ncells += host_encode_phys_addr(props + ncells, arch->rbase); + ncells += pci_encode_size(props + ncells, arch->rlen); } if (arch->mem_base) { - pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, + ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, config->dev, 0, arch->mem_base); - ncells += 3; - props[ncells++] = arch->mem_base; - props[ncells++] = 0x00000000; - props[ncells++] = arch->mem_len; + ncells += host_encode_phys_addr(props + ncells, arch->mem_base); + ncells += pci_encode_size(props + ncells, arch->mem_len); } set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); } @@ -548,11 +609,10 @@ static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars) pci_decode_pci_addr(config->assigned[i], &flags, &space_code, &mask);
- pci_encode_phys_addr(props + ncells, + ncells += pci_encode_phys_addr(props + ncells, flags, space_code, config->dev, PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), config->assigned[i] & ~mask); - ncells += 3;
props[ncells++] = 0x00000000; props[ncells++] = config->sizes[i]; @@ -571,13 +631,13 @@ static void pci_set_reg(const pci_config_t *config, int num_bars) uint32_t mask; int space_code, flags;
- ncells = 0; - pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, + ncells = 0; + + /* first (addr, size) pair is the beginning of configuration address space */ + ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, config->dev, 0, 0); - ncells += 3;
- props[ncells++] = 0x00000000; - props[ncells++] = 0x00000000; + ncells += pci_encode_size(props + ncells, 0);
for (i = 0; i < num_bars; i++) { if (!config->assigned[i] || !config->sizes[i]) @@ -586,17 +646,15 @@ static void pci_set_reg(const pci_config_t *config, int num_bars) pci_decode_pci_addr(config->regions[i], &flags, &space_code, &mask);
- pci_encode_phys_addr(props + ncells, + ncells += pci_encode_phys_addr(props + ncells, flags, space_code, config->dev, PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), config->regions[i] & ~mask); - ncells += 3;
/* set size */ - - props[ncells++] = 0x00000000; - props[ncells++] = config->sizes[i]; + ncells += pci_encode_size(props + ncells, config->sizes[i]); } + set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); }
@@ -624,10 +682,9 @@ static void pci_set_ranges(const pci_config_t *config)
pci_decode_pci_addr(config->assigned[i], &flags, &space_code, &mask); - pci_encode_phys_addr(props + ncells, flags, space_code, + ncells += pci_encode_phys_addr(props + ncells, flags, space_code, config->dev, 0x10 + i * 4, config->assigned[i] & ~mask); - ncells += 3;
/* size */
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/pci.c | 25 +++++++++++++------------ 1 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index c080372..5676749 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -32,6 +32,12 @@ #include "macio.h" #endif
+#if defined (CONFIG_DEBUG_PCI) +# define PCI_DPRINTF(format, ...) printk(format, ## __VA_ARGS__) +#else +# define PCI_DPRINTF(format, ...) do { } while (0) +#endif + #define set_bool_property(ph, name) set_property(ph, name, NULL, 0);
/* DECLARE data structures for the nodes. */ @@ -824,9 +830,7 @@ static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev, pci_set_assigned_addresses(config, num_bars); OLDWORLD(pci_set_AAPL_address(config));
-#ifdef CONFIG_DEBUG_PCI - printk("\n"); -#endif + PCI_DPRINTF("\n");
if (pci_dev && pci_dev->config_cb) pci_dev->config_cb(config); @@ -1010,10 +1014,9 @@ static void ob_scan_pci_bus(int bus, unsigned long *mem_base, pci_dev = pci_find_device(class, subclass, iface, vid, did);
-#ifdef CONFIG_DEBUG_PCI - printk("%x:%x.%x - %x:%x - ", bus, devnum, fn, + PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn, vid, did); -#endif + htype = pci_config_read8(addr, PCI_HEADER_TYPE); if (fn == 0) is_multi = htype & 0x80; @@ -1024,9 +1027,9 @@ static void ob_scan_pci_bus(int bus, unsigned long *mem_base, else snprintf(config.path, sizeof(config.path), "%s/%s", *path, pci_dev->name); -#ifdef CONFIG_DEBUG_PCI - printk("%s - ", config.path); -#endif + + PCI_DPRINTF("%s - ", config.path); + config.dev = addr & 0x00FFFFFF;
if (class == PCI_BASE_CLASS_BRIDGE && @@ -1069,9 +1072,7 @@ int ob_pci_init(void) unsigned long mem_base, io_base; char *path;
-#ifdef CONFIG_DEBUG_PCI - printk("Initializing PCI devices...\n"); -#endif + PCI_DPRINTF("Initializing PCI devices...\n");
/* brute force bus scan */
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- refactor scan procedure to start with PCI host controller - initiate scan of subordinate PCI bus from PCI host and PCI-to-PCI bridges - find out PCI subordinate bus numbers and write them to bride devices - automated assignment of "reg", "ranges", and "bus-range" properties
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/pci.c | 488 +++++++++++++++++++++++++++------------- drivers/pci.h | 4 drivers/pci_database.h | 3 drivers/vga_vbe.c | 6 include/libopenbios/bindings.h | 8 + libopenbios/bindings.c | 6 6 files changed, 347 insertions(+), 168 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 5676749..f8d0b41 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -125,6 +125,18 @@ static int parent_size_cells(void) } */
+#if defined(CONFIG_DEBUG_PCI) +static void dump_reg_property(const char* description, int nreg, u32 *reg) +{ + int i; + printk("%s reg", description); + for (i=0; i < nreg; ++i) { + printk(" %08X", reg[i]); + } + printk("\n"); +} +#endif + static void ob_pci_open(int *idx) { @@ -153,6 +165,8 @@ ob_pci_decode_unit(int *idx) int bus = 0; /* no information */ char *ptr;
+ PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx); + fn = 0; reg = 0; n = 0; @@ -245,6 +259,10 @@ ob_pci_decode_unit(int *idx) PUSH(lo); PUSH(mid); PUSH(hi); + + PCI_DPRINTF("ob_pci_decode_unit idx=%p addr=" + FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n", + idx, lo, mid, hi); }
/* ( phys.lo phy.mid phys.hi -- str len ) */ @@ -305,6 +323,9 @@ ob_pci_encode_unit(int *idx) break; } push_str(buf); + + PCI_DPRINTF("ob_pci_encode_unit space=%d dev=%d fn=%d buf=%s\n", + ss, dev, fn, buf); }
NODE_METHODS(ob_pci_bus_node) = { @@ -323,11 +344,22 @@ NODE_METHODS(ob_pci_simple_node) = {
static void pci_set_bus_range(const pci_config_t *config) { - phandle_t dev = get_cur_dev(); + phandle_t dev = find_dev(config->path); u32 props[2];
- props[0] = (config->dev >> 16) & 0xFF; - props[1] = 1; + props[0] = config->secondary_bus; + props[1] = config->subordinate_bus; + + PCI_DPRINTF("setting bus range for %s PCI device, " + "package handle " FMT_ucellx " " + "bus primary=%d secondary=%d subordinate=%d\n", + config->path, + dev, + config->primary_bus, + config->secondary_bus, + config->subordinate_bus); + + set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0])); }
@@ -372,9 +404,10 @@ static void pci_host_set_interrupt_map(const pci_config_t *config) #endif }
-static void pci_host_set_reg(const pci_config_t *config) +static void pci_host_set_reg(phandle_t phandle) { - phandle_t dev = get_cur_dev(); + phandle_t dev = phandle; + /* at most 2 integers for address and size */ u32 props[4]; int ncells = 0; @@ -386,6 +419,10 @@ static void pci_host_set_reg(const pci_config_t *config) arch->cfg_len);
set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); + +#if defined(CONFIG_DEBUG_PCI) + dump_reg_property("pci_host_set_reg", 4, props); +#endif }
/* child-phys : parent-phys : size */ @@ -438,68 +475,18 @@ static unsigned long pci_bus_addr_to_host_addr(uint32_t ba)
int host_config_cb(const pci_config_t *config) { - phandle_t aliases; - - aliases = find_dev("/aliases"); - if (aliases) - set_property(aliases, "pci", - config->path, strlen(config->path) + 1); - //XXX this overrides "reg" property - pci_host_set_reg(config); + pci_host_set_reg(get_cur_dev()); pci_host_set_ranges(config); - pci_set_bus_range(config); pci_host_set_interrupt_map(config);
return 0; }
-int sabre_config_cb(const pci_config_t *config) +static int sabre_configure(phandle_t dev) { - phandle_t dev = get_cur_dev(); uint32_t props[28];
- props[0] = 0x00000000; - props[1] = 0x00000003; - set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0])); - props[0] = 0x000001fe; - props[1] = 0x00000000; - props[2] = 0x00000000; - props[3] = 0x00010000; - props[4] = 0x000001fe; - props[5] = 0x01000000; - props[6] = 0x00000000; - props[7] = 0x00000100; - set_property(dev, "reg", (char *)props, 8 * sizeof(props[0])); - props[0] = 0x00000000; - props[1] = 0x00000000; - props[2] = 0x00000000; - props[3] = 0x000001fe; - props[4] = 0x01000000; - props[5] = 0x00000000; - props[6] = 0x01000000; - props[7] = 0x01000000; - props[8] = 0x00000000; - props[9] = 0x00000000; - props[10] = 0x000001fe; - props[11] = 0x02000000; - props[12] = 0x00000000; - props[13] = 0x01000000; - props[14] = 0x02000000; - props[15] = 0x00000000; - props[16] = 0x00000000; - props[17] = 0x000001ff; - props[18] = 0x00000000; - props[19] = 0x00000001; - props[20] = 0x00000000; - props[21] = 0x03000000; - props[22] = 0x00000000; - props[23] = 0x00000000; - props[24] = 0x000001ff; - props[25] = 0x00000000; - props[26] = 0x00000001; - props[27] = 0x00000000; - set_property(dev, "ranges", (char *)props, 28 * sizeof(props[0])); props[0] = 0xc0000000; props[1] = 0x20000000; set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0])); @@ -518,6 +505,13 @@ int sabre_config_cb(const pci_config_t *config) return 0; }
+int sabre_config_cb(const pci_config_t *config) +{ + host_config_cb(config); + + return sabre_configure(get_cur_dev()); +} + int bridge_config_cb(const pci_config_t *config) { phandle_t aliases; @@ -525,8 +519,6 @@ int bridge_config_cb(const pci_config_t *config) aliases = find_dev("/aliases"); set_property(aliases, "bridge", config->path, strlen(config->path) + 1);
- pci_set_bus_range(config); - return 0; }
@@ -599,9 +591,10 @@ static void pci_set_AAPL_address(const pci_config_t *config) ncells * sizeof(cell)); }
-static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars) +static void pci_set_assigned_addresses(phandle_t phandle, + const pci_config_t *config, int num_bars) { - phandle_t dev = get_cur_dev(); + phandle_t dev = phandle; u32 props[32]; int ncells; int i; @@ -628,9 +621,32 @@ static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars) ncells * sizeof(props[0])); }
-static void pci_set_reg(const pci_config_t *config, int num_bars) +/* call after writing "reg" property to update config->path */ +static void ob_pci_reload_device_path(phandle_t phandle, pci_config_t *config) { - phandle_t dev = get_cur_dev(); + /* since "name" and "reg" are now assigned + we need to reload current node name */ + + PUSH(phandle); + fword("get-package-path"); + char *new_path = pop_fstr_copy(); + if (new_path) { + if (0 != strcmp(config->path, new_path)) { + PCI_DPRINTF("\n=== CHANGED === package path old=%s new=%s\n", + config->path, new_path); + strncpy(config->path, new_path, sizeof(config->path)); + config->path[sizeof(config->path)-1] = '\0'; + } + free(new_path); + } else { + PCI_DPRINTF("\n=== package path old=%s new=NULL\n", config->path); + } +} + +static void pci_set_reg(phandle_t phandle, + pci_config_t *config, int num_bars) +{ + phandle_t dev = phandle; u32 props[38]; int ncells; int i; @@ -662,6 +678,11 @@ static void pci_set_reg(const pci_config_t *config, int num_bars) }
set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); + ob_pci_reload_device_path(dev, config); + +#if defined(CONFIG_DEBUG_PCI) + dump_reg_property("pci_set_reg", ncells, props); +#endif }
@@ -746,10 +767,13 @@ int ebus_config_cb(const pci_config_t *config) return 0; }
-static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev, +static void ob_pci_add_properties(phandle_t phandle, + pci_addr addr, const pci_dev_t *pci_dev, const pci_config_t *config, int num_bars) { - phandle_t dev=get_cur_dev(); + /* cannot use get_cur_dev() path resolution since "name" and "reg" + properties are being changed */ + phandle_t dev=phandle; int status,id; uint16_t vendor_id, device_id; uint8_t rev; @@ -760,6 +784,26 @@ static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev, rev = pci_config_read8(addr, PCI_REVISION_ID); class_code = pci_config_read16(addr, PCI_CLASS_DEVICE);
+ if (pci_dev) { + /**/ + if (pci_dev->name) { + push_str(pci_dev->name); + fword("encode-string"); + push_str("name"); + fword("property"); + } else { + char path[256]; + snprintf(path, sizeof(path), + "pci%x,%x", vendor_id, device_id); + push_str(path); + fword("encode-string"); + push_str("name"); + fword("property"); + } + } else { + PCI_DPRINTF("*** missing pci_dev\n"); + } + /* create properties as described in 2.5 */
set_int_property(dev, "vendor-id", vendor_id); @@ -826,14 +870,10 @@ static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev, pci_dev->icells); }
- pci_set_reg(config, num_bars); - pci_set_assigned_addresses(config, num_bars); + pci_set_assigned_addresses(phandle, config, num_bars); OLDWORLD(pci_set_AAPL_address(config));
PCI_DPRINTF("\n"); - - if (pci_dev && pci_dev->config_cb) - pci_dev->config_cb(config); }
#ifdef CONFIG_XBOX @@ -979,113 +1019,235 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar, pci_config_write16(addr, PCI_COMMAND, cmd); }
-static void ob_scan_pci_bus(int bus, unsigned long *mem_base, - unsigned long *io_base, char **path) +static void ob_configure_pci_device(const char* parent_path, + int *bus_num, unsigned long *mem_base, unsigned long *io_base, + int bus, int devnum, int fn, int *p_is_multi); + +static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base, + unsigned long *io_base, const char *path, + int bus) { - int devnum, fn, is_multi, vid, did; - unsigned int htype; - pci_addr addr; - pci_config_t config; - const pci_dev_t *pci_dev; - uint32_t ccode; - uint8_t class, subclass, iface; - int num_bars, rom_bar; + int devnum, fn, is_multi; + + PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path);
- activate_device("/"); for (devnum = 0; devnum < 32; devnum++) { is_multi = 0; for (fn = 0; fn==0 || (is_multi && fn<8); fn++) { -#ifdef CONFIG_XBOX - if (pci_xbox_blacklisted (bus, devnum, fn)) - continue; -#endif - addr = PCI_ADDR(bus, devnum, fn); - vid = pci_config_read16(addr, PCI_VENDOR_ID); - did = pci_config_read16(addr, PCI_DEVICE_ID); - - if (vid==0xffff || vid==0) - continue; - - ccode = pci_config_read16(addr, PCI_CLASS_DEVICE); - class = ccode >> 8; - subclass = ccode; - iface = pci_config_read8(addr, PCI_CLASS_PROG); - - pci_dev = pci_find_device(class, subclass, iface, - vid, did); - - PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn, - vid, did); - - htype = pci_config_read8(addr, PCI_HEADER_TYPE); - if (fn == 0) - is_multi = htype & 0x80; - - if (pci_dev == NULL || pci_dev->name == NULL) - snprintf(config.path, sizeof(config.path), - "%s/pci%x,%x", *path, vid, did); - else - snprintf(config.path, sizeof(config.path), - "%s/%s", *path, pci_dev->name); - - PCI_DPRINTF("%s - ", config.path); - - config.dev = addr & 0x00FFFFFF; - - if (class == PCI_BASE_CLASS_BRIDGE && - (subclass == PCI_SUBCLASS_BRIDGE_HOST || - subclass == PCI_SUBCLASS_BRIDGE_PCI)) - REGISTER_NAMED_NODE(ob_pci_bus_node, config.path); - else - REGISTER_NAMED_NODE(ob_pci_simple_node, config.path); - - activate_device(config.path); - - if (htype & PCI_HEADER_TYPE_BRIDGE) { - num_bars = 2; - rom_bar = PCI_ROM_ADDRESS1; - } else { - num_bars = 6; - rom_bar = PCI_ROM_ADDRESS; - } - - ob_pci_configure(addr, &config, num_bars, rom_bar, - mem_base, io_base); - ob_pci_add_properties(addr, pci_dev, &config, num_bars); - - if (class == PCI_BASE_CLASS_BRIDGE && - (subclass == PCI_SUBCLASS_BRIDGE_HOST || - subclass == PCI_SUBCLASS_BRIDGE_PCI)) { - /* host or bridge */ - free(*path); - *path = strdup(config.path); - } + ob_configure_pci_device(path, bus_num, mem_base, io_base, + bus, devnum, fn, &is_multi);
} } - device_end(); +} + +static void ob_configure_pci_bridge(pci_addr addr, + int *bus_num, unsigned long *mem_base, + unsigned long *io_base, + int primary_bus, pci_config_t *config) +{ + config->primary_bus = primary_bus; + pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus); + + config->secondary_bus = *bus_num; + pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus); + + config->subordinate_bus = 0xff; + pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus); + + PCI_DPRINTF("scanning new pci bus %u under bridge %s\n", + config->secondary_bus, config->path); + + /* make pci bridge parent device, prepare for recursion */ + + ob_scan_pci_bus(bus_num, mem_base, io_base, + config->path, config->secondary_bus); + + /* bus scan updates *bus_num to last revealed pci bus number */ + config->subordinate_bus = *bus_num; + pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus); + + PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n", + config->path, config->primary_bus, config->secondary_bus, + config->subordinate_bus); + + pci_set_bus_range(config); +} + +static void ob_configure_pci_device(const char* parent_path, + int *bus_num, unsigned long *mem_base, unsigned long *io_base, + int bus, int devnum, int fn, int *p_is_multi) +{ + int vid, did; + unsigned int htype; + pci_addr addr; + pci_config_t config = {}; + const pci_dev_t *pci_dev; + uint32_t ccode; + uint8_t class, subclass, iface; + int num_bars, rom_bar; + + phandle_t phandle = 0; + int is_host_bridge = 0; + +#ifdef CONFIG_XBOX + if (pci_xbox_blacklisted (bus, devnum, fn)) + return; +#endif + addr = PCI_ADDR(bus, devnum, fn); + vid = pci_config_read16(addr, PCI_VENDOR_ID); + did = pci_config_read16(addr, PCI_DEVICE_ID); + + if (vid==0xffff || vid==0) + return; + + ccode = pci_config_read16(addr, PCI_CLASS_DEVICE); + class = ccode >> 8; + subclass = ccode; + + iface = pci_config_read8(addr, PCI_CLASS_PROG); + + pci_dev = pci_find_device(class, subclass, iface, + vid, did); + + PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn, + vid, did); + + htype = pci_config_read8(addr, PCI_HEADER_TYPE); + + if (fn == 0) { + if (p_is_multi) { + *p_is_multi = htype & 0x80; + } + } + + /* stop adding host bridge accessible from it's primary bus + PCI host bridge is to be added by host code + */ + if (class == PCI_BASE_CLASS_BRIDGE && + subclass == PCI_SUBCLASS_BRIDGE_HOST) { + is_host_bridge = 1; + } + + if (is_host_bridge) { + /* reuse device tree node */ + PCI_DPRINTF("host bridge found - "); + snprintf(config.path, sizeof(config.path), + "%s", parent_path); + } else if (pci_dev == NULL || pci_dev->name == NULL) { + snprintf(config.path, sizeof(config.path), + "%s/pci%x,%x", parent_path, vid, did); + } + else { + snprintf(config.path, sizeof(config.path), + "%s/%s", parent_path, pci_dev->name); + } + + PCI_DPRINTF("%s - ", config.path); + + config.dev = addr & 0x00FFFFFF; + + switch (class) { + case PCI_BASE_CLASS_BRIDGE: + if (subclass != PCI_SUBCLASS_BRIDGE_HOST) { + REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle); + } + break; + default: + REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle); + break; + } + + if (is_host_bridge) { + phandle = find_dev(config.path); + + if (get_property(phandle, "vendor-id", NULL)) { + PCI_DPRINTF("host bridge already configured\n"); + return; + } + } + + activate_dev(phandle); + + if (htype & PCI_HEADER_TYPE_BRIDGE) { + num_bars = 2; + rom_bar = PCI_ROM_ADDRESS1; + } else { + num_bars = 6; + rom_bar = PCI_ROM_ADDRESS; + } + + ob_pci_configure(addr, &config, num_bars, rom_bar, + mem_base, io_base); + + ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars); + + if (!is_host_bridge) { + pci_set_reg(phandle, &config, num_bars); + } + + /* call device-specific configuration callback */ + if (pci_dev && pci_dev->config_cb) { + //activate_device(config.path); + pci_dev->config_cb(&config); + } + + /* device is configured so we may move it out of scope */ + device_end(); + + /* scan bus behind bridge device */ + //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) { + if ( class == PCI_BASE_CLASS_BRIDGE && + ( subclass == PCI_SUBCLASS_BRIDGE_PCI || + subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) { + + if (subclass == PCI_SUBCLASS_BRIDGE_PCI) { + /* reserve next pci bus number for this PCI bridge */ + ++(*bus_num); + } + + ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config); + } }
int ob_pci_init(void) { - int bus; - unsigned long mem_base, io_base; - char *path; + int bus; + unsigned long mem_base, io_base;
- PCI_DPRINTF("Initializing PCI devices...\n"); + pci_config_t config = {}; /* host bridge */ + phandle_t phandle_host;
- /* brute force bus scan */ + PCI_DPRINTF("Initializing PCI host bridge...\n");
- /* Find all PCI bridges */ + activate_device("/");
- mem_base = arch->mem_base; - /* I/O ports under 0x400 are used by devices mapped at fixed - location. */ - io_base = arch->io_base + 0x400; - path = strdup(""); - for (bus = 0; bus<0x100; bus++) { - ob_scan_pci_bus(bus, &mem_base, &io_base, &path); - } - free(path); - return 0; + /* Find all PCI bridges */ + + mem_base = arch->mem_base; + /* I/O ports under 0x400 are used by devices mapped at fixed + location. */ + io_base = arch->io_base + 0x400; + + bus = 0; + + /* create root node for host PCI bridge */ + + /* configure */ + snprintf(config.path, sizeof(config.path), "/pci"); + + REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host); + + pci_host_set_reg(phandle_host); + + /* update device path after changing "reg" property */ + ob_pci_reload_device_path(phandle_host, &config); + + /* we expect host PCI bridge at pci0:0:0 but this may be machine-specific */ + + ob_configure_pci_device(config.path, &bus, &mem_base, &io_base, 0, 0, 0, 0); + + device_end(); + + return 0; } diff --git a/drivers/pci.h b/drivers/pci.h index 3ca71f3..0f6ae1f 100644 --- a/drivers/pci.h +++ b/drivers/pci.h @@ -34,7 +34,9 @@ #define PCI_HEADER_TYPE_NORMAL 0x00 #define PCI_HEADER_TYPE_BRIDGE 0x01 #define PCI_HEADER_TYPE_CARDBUS 0x02 -#define PCI_SECONDARY_BUS 0x19 +#define PCI_PRIMARY_BUS 0x18 +#define PCI_SECONDARY_BUS 0x19 +#define PCI_SUBORDINATE_BUS 0x1A #define PCI_BASE_ADDR_0 0x10 #define PCI_BASE_ADDR_1 0x14 #define PCI_BASE_ADDR_2 0x18 diff --git a/drivers/pci_database.h b/drivers/pci_database.h index cdb0045..5ddbb20 100644 --- a/drivers/pci_database.h +++ b/drivers/pci_database.h @@ -8,6 +8,9 @@ struct pci_config_t { uint32_t sizes[7]; int irq_pin; int irq_line; + u32 primary_bus; + u32 secondary_bus; + u32 subordinate_bus; };
typedef struct pci_dev_t pci_dev_t; diff --git a/drivers/vga_vbe.c b/drivers/vga_vbe.c index b1a95df..2c229b4 100644 --- a/drivers/vga_vbe.c +++ b/drivers/vga_vbe.c @@ -155,7 +155,11 @@ void vga_vbe_init(const char *path, unsigned long fb, uint32_t fb_size,
vga_vbe_set_mode(width, height, depth);
- ph = find_dev(path); +#if 0 + ph = find_dev(path); +#else + ph = get_cur_dev(); +#endif
set_int_property(ph, "width", width); set_int_property(ph, "height", height); diff --git a/include/libopenbios/bindings.h b/include/libopenbios/bindings.h index 4c58159..de9c775 100644 --- a/include/libopenbios/bindings.h +++ b/include/libopenbios/bindings.h @@ -112,6 +112,12 @@ typedef struct { path, name##_m, sizeof(name##_m)/sizeof(method_t)); \ } while(0)
+#define REGISTER_NAMED_NODE_PHANDLE( name, path, phandle ) do { \ + phandle = \ + bind_new_node( name##_flags_, name##_size_, \ + path, name##_m, sizeof(name##_m)/sizeof(method_t)); \ + } while(0) + #define REGISTER_NODE_METHODS( name, path ) do { \ const char *paths[1]; \ \ @@ -140,7 +146,7 @@ static const method_t name##_m[] extern void bind_node( int flags, int size, const char * const *paths, int npaths, const method_t *methods, int nmethods );
-extern void bind_new_node( int flags, int size, const char *name, +extern phandle_t bind_new_node( int flags, int size, const char *name, const method_t *methods, int nmethods );
#define INSTALL_OPEN 1 /* install trivial open and close methods */ diff --git a/libopenbios/bindings.c b/libopenbios/bindings.c index 5067455..f6bc8de 100644 --- a/libopenbios/bindings.c +++ b/libopenbios/bindings.c @@ -507,16 +507,18 @@ bind_node( int flags, int size, const char * const *paths, int npaths, activate_dev( save_ph ); }
-void +phandle_t bind_new_node( int flags, int size, const char *name, const method_t *methods, int nmet ) { phandle_t save_ph = get_cur_dev(); - + phandle_t new_ph; /* create node */ push_str( name ); fword("create-node"); add_methods( flags, size, methods, nmet ); + new_ph = get_cur_dev();
activate_dev( save_ph ); + return new_ph; }
On Tue, May 25, 2010 at 12:38 PM, Igor V. Kovalenko igor.v.kovalenko@gmail.com wrote:
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- refactor scan procedure to start with PCI host controller
- initiate scan of subordinate PCI bus from PCI host and PCI-to-PCI bridges
- find out PCI subordinate bus numbers and write them to bride devices
- automated assignment of "reg", "ranges", and "bus-range" properties
Unfortunately this breaks the PPC Mac99 machine.
To test, simply run 'qemu-system-ppc -M mac99', the screen remains black. 5/10 still works.
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com
drivers/pci.c | 488 +++++++++++++++++++++++++++------------- drivers/pci.h | 4 drivers/pci_database.h | 3 drivers/vga_vbe.c | 6 include/libopenbios/bindings.h | 8 + libopenbios/bindings.c | 6 6 files changed, 347 insertions(+), 168 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 5676749..f8d0b41 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -125,6 +125,18 @@ static int parent_size_cells(void) } */
+#if defined(CONFIG_DEBUG_PCI) +static void dump_reg_property(const char* description, int nreg, u32 *reg) +{
- int i;
- printk("%s reg", description);
- for (i=0; i < nreg; ++i) {
- printk(" %08X", reg[i]);
- }
- printk("\n");
+} +#endif
static void ob_pci_open(int *idx) { @@ -153,6 +165,8 @@ ob_pci_decode_unit(int *idx) int bus = 0; /* no information */ char *ptr;
- PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx);
fn = 0; reg = 0; n = 0; @@ -245,6 +259,10 @@ ob_pci_decode_unit(int *idx) PUSH(lo); PUSH(mid); PUSH(hi);
- PCI_DPRINTF("ob_pci_decode_unit idx=%p addr="
- FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n",
- idx, lo, mid, hi);
}
/* ( phys.lo phy.mid phys.hi -- str len ) */ @@ -305,6 +323,9 @@ ob_pci_encode_unit(int *idx) break; } push_str(buf);
- PCI_DPRINTF("ob_pci_encode_unit space=%d dev=%d fn=%d buf=%s\n",
- ss, dev, fn, buf);
}
NODE_METHODS(ob_pci_bus_node) = { @@ -323,11 +344,22 @@ NODE_METHODS(ob_pci_simple_node) = {
static void pci_set_bus_range(const pci_config_t *config) {
- phandle_t dev = get_cur_dev();
- phandle_t dev = find_dev(config->path);
u32 props[2];
- props[0] = (config->dev >> 16) & 0xFF;
- props[1] = 1;
- props[0] = config->secondary_bus;
- props[1] = config->subordinate_bus;
- PCI_DPRINTF("setting bus range for %s PCI device, "
- "package handle " FMT_ucellx " "
- "bus primary=%d secondary=%d subordinate=%d\n",
- config->path,
- dev,
- config->primary_bus,
- config->secondary_bus,
- config->subordinate_bus);
set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0])); }
@@ -372,9 +404,10 @@ static void pci_host_set_interrupt_map(const pci_config_t *config) #endif }
-static void pci_host_set_reg(const pci_config_t *config) +static void pci_host_set_reg(phandle_t phandle) {
- phandle_t dev = get_cur_dev();
- phandle_t dev = phandle;
/* at most 2 integers for address and size */ u32 props[4]; int ncells = 0; @@ -386,6 +419,10 @@ static void pci_host_set_reg(const pci_config_t *config) arch->cfg_len);
set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
+#if defined(CONFIG_DEBUG_PCI)
- dump_reg_property("pci_host_set_reg", 4, props);
+#endif }
/* child-phys : parent-phys : size */ @@ -438,68 +475,18 @@ static unsigned long pci_bus_addr_to_host_addr(uint32_t ba)
int host_config_cb(const pci_config_t *config) {
- phandle_t aliases;
- aliases = find_dev("/aliases");
- if (aliases)
- set_property(aliases, "pci",
- config->path, strlen(config->path) + 1);
//XXX this overrides "reg" property
- pci_host_set_reg(config);
- pci_host_set_reg(get_cur_dev());
pci_host_set_ranges(config);
- pci_set_bus_range(config);
pci_host_set_interrupt_map(config);
return 0; }
-int sabre_config_cb(const pci_config_t *config) +static int sabre_configure(phandle_t dev) {
- phandle_t dev = get_cur_dev();
uint32_t props[28];
- props[0] = 0x00000000;
- props[1] = 0x00000003;
- set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0]));
- props[0] = 0x000001fe;
- props[1] = 0x00000000;
- props[2] = 0x00000000;
- props[3] = 0x00010000;
- props[4] = 0x000001fe;
- props[5] = 0x01000000;
- props[6] = 0x00000000;
- props[7] = 0x00000100;
- set_property(dev, "reg", (char *)props, 8 * sizeof(props[0]));
- props[0] = 0x00000000;
- props[1] = 0x00000000;
- props[2] = 0x00000000;
- props[3] = 0x000001fe;
- props[4] = 0x01000000;
- props[5] = 0x00000000;
- props[6] = 0x01000000;
- props[7] = 0x01000000;
- props[8] = 0x00000000;
- props[9] = 0x00000000;
- props[10] = 0x000001fe;
- props[11] = 0x02000000;
- props[12] = 0x00000000;
- props[13] = 0x01000000;
- props[14] = 0x02000000;
- props[15] = 0x00000000;
- props[16] = 0x00000000;
- props[17] = 0x000001ff;
- props[18] = 0x00000000;
- props[19] = 0x00000001;
- props[20] = 0x00000000;
- props[21] = 0x03000000;
- props[22] = 0x00000000;
- props[23] = 0x00000000;
- props[24] = 0x000001ff;
- props[25] = 0x00000000;
- props[26] = 0x00000001;
- props[27] = 0x00000000;
- set_property(dev, "ranges", (char *)props, 28 * sizeof(props[0]));
props[0] = 0xc0000000; props[1] = 0x20000000; set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0])); @@ -518,6 +505,13 @@ int sabre_config_cb(const pci_config_t *config) return 0; }
+int sabre_config_cb(const pci_config_t *config) +{
- host_config_cb(config);
- return sabre_configure(get_cur_dev());
+}
int bridge_config_cb(const pci_config_t *config) { phandle_t aliases; @@ -525,8 +519,6 @@ int bridge_config_cb(const pci_config_t *config) aliases = find_dev("/aliases"); set_property(aliases, "bridge", config->path, strlen(config->path) + 1);
- pci_set_bus_range(config);
return 0; }
@@ -599,9 +591,10 @@ static void pci_set_AAPL_address(const pci_config_t *config) ncells * sizeof(cell)); }
-static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars) +static void pci_set_assigned_addresses(phandle_t phandle,
- const pci_config_t *config, int num_bars)
{
- phandle_t dev = get_cur_dev();
- phandle_t dev = phandle;
u32 props[32]; int ncells; int i; @@ -628,9 +621,32 @@ static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars) ncells * sizeof(props[0])); }
-static void pci_set_reg(const pci_config_t *config, int num_bars) +/* call after writing "reg" property to update config->path */ +static void ob_pci_reload_device_path(phandle_t phandle, pci_config_t *config) {
- phandle_t dev = get_cur_dev();
- /* since "name" and "reg" are now assigned
- we need to reload current node name */
- PUSH(phandle);
- fword("get-package-path");
- char *new_path = pop_fstr_copy();
- if (new_path) {
- if (0 != strcmp(config->path, new_path)) {
- PCI_DPRINTF("\n=== CHANGED === package path old=%s new=%s\n",
- config->path, new_path);
- strncpy(config->path, new_path, sizeof(config->path));
- config->path[sizeof(config->path)-1] = '\0';
- }
- free(new_path);
- } else {
- PCI_DPRINTF("\n=== package path old=%s new=NULL\n", config->path);
- }
+}
+static void pci_set_reg(phandle_t phandle,
- pci_config_t *config, int num_bars)
+{
- phandle_t dev = phandle;
u32 props[38]; int ncells; int i; @@ -662,6 +678,11 @@ static void pci_set_reg(const pci_config_t *config, int num_bars) }
set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
- ob_pci_reload_device_path(dev, config);
+#if defined(CONFIG_DEBUG_PCI)
- dump_reg_property("pci_set_reg", ncells, props);
+#endif }
@@ -746,10 +767,13 @@ int ebus_config_cb(const pci_config_t *config) return 0; }
-static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev, +static void ob_pci_add_properties(phandle_t phandle,
- pci_addr addr, const pci_dev_t *pci_dev,
const pci_config_t *config, int num_bars) {
- phandle_t dev=get_cur_dev();
- /* cannot use get_cur_dev() path resolution since "name" and "reg"
- properties are being changed */
- phandle_t dev=phandle;
int status,id; uint16_t vendor_id, device_id; uint8_t rev; @@ -760,6 +784,26 @@ static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev, rev = pci_config_read8(addr, PCI_REVISION_ID); class_code = pci_config_read16(addr, PCI_CLASS_DEVICE);
- if (pci_dev) {
- /**/
- if (pci_dev->name) {
- push_str(pci_dev->name);
- fword("encode-string");
- push_str("name");
- fword("property");
- } else {
- char path[256];
- snprintf(path, sizeof(path),
- "pci%x,%x", vendor_id, device_id);
- push_str(path);
- fword("encode-string");
- push_str("name");
- fword("property");
- }
- } else {
- PCI_DPRINTF("*** missing pci_dev\n");
- }
/* create properties as described in 2.5 */
set_int_property(dev, "vendor-id", vendor_id); @@ -826,14 +870,10 @@ static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev, pci_dev->icells); }
- pci_set_reg(config, num_bars);
- pci_set_assigned_addresses(config, num_bars);
- pci_set_assigned_addresses(phandle, config, num_bars);
OLDWORLD(pci_set_AAPL_address(config));
PCI_DPRINTF("\n");
- if (pci_dev && pci_dev->config_cb)
- pci_dev->config_cb(config);
}
#ifdef CONFIG_XBOX @@ -979,113 +1019,235 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar, pci_config_write16(addr, PCI_COMMAND, cmd); }
-static void ob_scan_pci_bus(int bus, unsigned long *mem_base,
- unsigned long *io_base, char **path)
+static void ob_configure_pci_device(const char* parent_path,
- int *bus_num, unsigned long *mem_base, unsigned long *io_base,
- int bus, int devnum, int fn, int *p_is_multi);
+static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base,
- unsigned long *io_base, const char *path,
- int bus)
{
- int devnum, fn, is_multi, vid, did;
- unsigned int htype;
- pci_addr addr;
- pci_config_t config;
- const pci_dev_t *pci_dev;
- uint32_t ccode;
- uint8_t class, subclass, iface;
- int num_bars, rom_bar;
- int devnum, fn, is_multi;
- PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path);
- activate_device("/");
for (devnum = 0; devnum < 32; devnum++) { is_multi = 0; for (fn = 0; fn==0 || (is_multi && fn<8); fn++) { -#ifdef CONFIG_XBOX
- if (pci_xbox_blacklisted (bus, devnum, fn))
- continue;
-#endif
- addr = PCI_ADDR(bus, devnum, fn);
- vid = pci_config_read16(addr, PCI_VENDOR_ID);
- did = pci_config_read16(addr, PCI_DEVICE_ID);
- if (vid==0xffff || vid==0)
- continue;
- ccode = pci_config_read16(addr, PCI_CLASS_DEVICE);
- class = ccode >> 8;
- subclass = ccode;
- iface = pci_config_read8(addr, PCI_CLASS_PROG);
- pci_dev = pci_find_device(class, subclass, iface,
- vid, did);
- PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn,
- vid, did);
- htype = pci_config_read8(addr, PCI_HEADER_TYPE);
- if (fn == 0)
- is_multi = htype & 0x80;
- if (pci_dev == NULL || pci_dev->name == NULL)
- snprintf(config.path, sizeof(config.path),
- "%s/pci%x,%x", *path, vid, did);
- else
- snprintf(config.path, sizeof(config.path),
- "%s/%s", *path, pci_dev->name);
- PCI_DPRINTF("%s - ", config.path);
- config.dev = addr & 0x00FFFFFF;
- if (class == PCI_BASE_CLASS_BRIDGE &&
- (subclass == PCI_SUBCLASS_BRIDGE_HOST ||
- subclass == PCI_SUBCLASS_BRIDGE_PCI))
- REGISTER_NAMED_NODE(ob_pci_bus_node, config.path);
- else
- REGISTER_NAMED_NODE(ob_pci_simple_node, config.path);
- activate_device(config.path);
- if (htype & PCI_HEADER_TYPE_BRIDGE) {
- num_bars = 2;
- rom_bar = PCI_ROM_ADDRESS1;
- } else {
- num_bars = 6;
- rom_bar = PCI_ROM_ADDRESS;
- }
- ob_pci_configure(addr, &config, num_bars, rom_bar,
- mem_base, io_base);
- ob_pci_add_properties(addr, pci_dev, &config, num_bars);
- if (class == PCI_BASE_CLASS_BRIDGE &&
- (subclass == PCI_SUBCLASS_BRIDGE_HOST ||
- subclass == PCI_SUBCLASS_BRIDGE_PCI)) {
- /* host or bridge */
- free(*path);
- *path = strdup(config.path);
- }
- ob_configure_pci_device(path, bus_num, mem_base, io_base,
- bus, devnum, fn, &is_multi);
} }
- device_end();
+}
+static void ob_configure_pci_bridge(pci_addr addr,
- int *bus_num, unsigned long *mem_base,
- unsigned long *io_base,
- int primary_bus, pci_config_t *config)
+{
- config->primary_bus = primary_bus;
- pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus);
- config->secondary_bus = *bus_num;
- pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus);
- config->subordinate_bus = 0xff;
- pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
- PCI_DPRINTF("scanning new pci bus %u under bridge %s\n",
- config->secondary_bus, config->path);
- /* make pci bridge parent device, prepare for recursion */
- ob_scan_pci_bus(bus_num, mem_base, io_base,
- config->path, config->secondary_bus);
- /* bus scan updates *bus_num to last revealed pci bus number */
- config->subordinate_bus = *bus_num;
- pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
- PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n",
- config->path, config->primary_bus, config->secondary_bus,
- config->subordinate_bus);
- pci_set_bus_range(config);
+}
+static void ob_configure_pci_device(const char* parent_path,
- int *bus_num, unsigned long *mem_base, unsigned long *io_base,
- int bus, int devnum, int fn, int *p_is_multi)
+{
- int vid, did;
- unsigned int htype;
- pci_addr addr;
- pci_config_t config = {};
- const pci_dev_t *pci_dev;
- uint32_t ccode;
- uint8_t class, subclass, iface;
- int num_bars, rom_bar;
- phandle_t phandle = 0;
- int is_host_bridge = 0;
+#ifdef CONFIG_XBOX
- if (pci_xbox_blacklisted (bus, devnum, fn))
- return;
+#endif
- addr = PCI_ADDR(bus, devnum, fn);
- vid = pci_config_read16(addr, PCI_VENDOR_ID);
- did = pci_config_read16(addr, PCI_DEVICE_ID);
- if (vid==0xffff || vid==0)
- return;
- ccode = pci_config_read16(addr, PCI_CLASS_DEVICE);
- class = ccode >> 8;
- subclass = ccode;
- iface = pci_config_read8(addr, PCI_CLASS_PROG);
- pci_dev = pci_find_device(class, subclass, iface,
- vid, did);
- PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn,
- vid, did);
- htype = pci_config_read8(addr, PCI_HEADER_TYPE);
- if (fn == 0) {
- if (p_is_multi) {
- *p_is_multi = htype & 0x80;
- }
- }
- /* stop adding host bridge accessible from it's primary bus
- PCI host bridge is to be added by host code
- */
- if (class == PCI_BASE_CLASS_BRIDGE &&
- subclass == PCI_SUBCLASS_BRIDGE_HOST) {
- is_host_bridge = 1;
- }
- if (is_host_bridge) {
- /* reuse device tree node */
- PCI_DPRINTF("host bridge found - ");
- snprintf(config.path, sizeof(config.path),
- "%s", parent_path);
- } else if (pci_dev == NULL || pci_dev->name == NULL) {
- snprintf(config.path, sizeof(config.path),
- "%s/pci%x,%x", parent_path, vid, did);
- }
- else {
- snprintf(config.path, sizeof(config.path),
- "%s/%s", parent_path, pci_dev->name);
- }
- PCI_DPRINTF("%s - ", config.path);
- config.dev = addr & 0x00FFFFFF;
- switch (class) {
- case PCI_BASE_CLASS_BRIDGE:
- if (subclass != PCI_SUBCLASS_BRIDGE_HOST) {
- REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle);
- }
- break;
- default:
- REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle);
- break;
- }
- if (is_host_bridge) {
- phandle = find_dev(config.path);
- if (get_property(phandle, "vendor-id", NULL)) {
- PCI_DPRINTF("host bridge already configured\n");
- return;
- }
- }
- activate_dev(phandle);
- if (htype & PCI_HEADER_TYPE_BRIDGE) {
- num_bars = 2;
- rom_bar = PCI_ROM_ADDRESS1;
- } else {
- num_bars = 6;
- rom_bar = PCI_ROM_ADDRESS;
- }
- ob_pci_configure(addr, &config, num_bars, rom_bar,
- mem_base, io_base);
- ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars);
- if (!is_host_bridge) {
- pci_set_reg(phandle, &config, num_bars);
- }
- /* call device-specific configuration callback */
- if (pci_dev && pci_dev->config_cb) {
- //activate_device(config.path);
- pci_dev->config_cb(&config);
- }
- /* device is configured so we may move it out of scope */
- device_end();
- /* scan bus behind bridge device */
- //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) {
- if ( class == PCI_BASE_CLASS_BRIDGE &&
- ( subclass == PCI_SUBCLASS_BRIDGE_PCI ||
- subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) {
- if (subclass == PCI_SUBCLASS_BRIDGE_PCI) {
- /* reserve next pci bus number for this PCI bridge */
- ++(*bus_num);
- }
- ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config);
- }
}
int ob_pci_init(void) {
- int bus;
- unsigned long mem_base, io_base;
- char *path;
- int bus;
- unsigned long mem_base, io_base;
- PCI_DPRINTF("Initializing PCI devices...\n");
- pci_config_t config = {}; /* host bridge */
- phandle_t phandle_host;
- /* brute force bus scan */
- PCI_DPRINTF("Initializing PCI host bridge...\n");
- /* Find all PCI bridges */
- activate_device("/");
- mem_base = arch->mem_base;
- /* I/O ports under 0x400 are used by devices mapped at fixed
- location. */
- io_base = arch->io_base + 0x400;
- path = strdup("");
- for (bus = 0; bus<0x100; bus++) {
- ob_scan_pci_bus(bus, &mem_base, &io_base, &path);
- }
- free(path);
- return 0;
- /* Find all PCI bridges */
- mem_base = arch->mem_base;
- /* I/O ports under 0x400 are used by devices mapped at fixed
- location. */
- io_base = arch->io_base + 0x400;
- bus = 0;
- /* create root node for host PCI bridge */
- /* configure */
- snprintf(config.path, sizeof(config.path), "/pci");
- REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host);
- pci_host_set_reg(phandle_host);
- /* update device path after changing "reg" property */
- ob_pci_reload_device_path(phandle_host, &config);
- /* we expect host PCI bridge at pci0:0:0 but this may be machine-specific */
- ob_configure_pci_device(config.path, &bus, &mem_base, &io_base, 0, 0, 0, 0);
- device_end();
- return 0;
} diff --git a/drivers/pci.h b/drivers/pci.h index 3ca71f3..0f6ae1f 100644 --- a/drivers/pci.h +++ b/drivers/pci.h @@ -34,7 +34,9 @@ #define PCI_HEADER_TYPE_NORMAL 0x00 #define PCI_HEADER_TYPE_BRIDGE 0x01 #define PCI_HEADER_TYPE_CARDBUS 0x02 -#define PCI_SECONDARY_BUS 0x19 +#define PCI_PRIMARY_BUS 0x18 +#define PCI_SECONDARY_BUS 0x19 +#define PCI_SUBORDINATE_BUS 0x1A #define PCI_BASE_ADDR_0 0x10 #define PCI_BASE_ADDR_1 0x14 #define PCI_BASE_ADDR_2 0x18 diff --git a/drivers/pci_database.h b/drivers/pci_database.h index cdb0045..5ddbb20 100644 --- a/drivers/pci_database.h +++ b/drivers/pci_database.h @@ -8,6 +8,9 @@ struct pci_config_t { uint32_t sizes[7]; int irq_pin; int irq_line;
- u32 primary_bus;
- u32 secondary_bus;
- u32 subordinate_bus;
};
typedef struct pci_dev_t pci_dev_t; diff --git a/drivers/vga_vbe.c b/drivers/vga_vbe.c index b1a95df..2c229b4 100644 --- a/drivers/vga_vbe.c +++ b/drivers/vga_vbe.c @@ -155,7 +155,11 @@ void vga_vbe_init(const char *path, unsigned long fb, uint32_t fb_size,
vga_vbe_set_mode(width, height, depth);
- ph = find_dev(path);
+#if 0
- ph = find_dev(path);
+#else
- ph = get_cur_dev();
+#endif
set_int_property(ph, "width", width); set_int_property(ph, "height", height); diff --git a/include/libopenbios/bindings.h b/include/libopenbios/bindings.h index 4c58159..de9c775 100644 --- a/include/libopenbios/bindings.h +++ b/include/libopenbios/bindings.h @@ -112,6 +112,12 @@ typedef struct { path, name##_m, sizeof(name##_m)/sizeof(method_t)); \ } while(0)
+#define REGISTER_NAMED_NODE_PHANDLE( name, path, phandle ) do { \
- phandle = \
- bind_new_node( name##_flags_, name##_size_, \
- path, name##_m, sizeof(name##_m)/sizeof(method_t)); \
- } while(0)
#define REGISTER_NODE_METHODS( name, path ) do { \ const char *paths[1]; \ \ @@ -140,7 +146,7 @@ static const method_t name##_m[] extern void bind_node( int flags, int size, const char * const *paths, int npaths, const method_t *methods, int nmethods );
-extern void bind_new_node( int flags, int size, const char *name, +extern phandle_t bind_new_node( int flags, int size, const char *name, const method_t *methods, int nmethods );
#define INSTALL_OPEN 1 /* install trivial open and close methods */ diff --git a/libopenbios/bindings.c b/libopenbios/bindings.c index 5067455..f6bc8de 100644 --- a/libopenbios/bindings.c +++ b/libopenbios/bindings.c @@ -507,16 +507,18 @@ bind_node( int flags, int size, const char * const *paths, int npaths, activate_dev( save_ph ); }
-void +phandle_t bind_new_node( int flags, int size, const char *name, const method_t *methods, int nmet ) { phandle_t save_ph = get_cur_dev();
- phandle_t new_ph;
/* create node */ push_str( name ); fword("create-node"); add_methods( flags, size, methods, nmet );
- new_ph = get_cur_dev();
activate_dev( save_ph );
- return new_ph;
}
-- OpenBIOS http://openbios.org/ Mailinglist: http://lists.openbios.org/mailman/listinfo Free your System - May the Forth be with you
On Wed, May 26, 2010 at 11:02 PM, Blue Swirl blauwirbel@gmail.com wrote:
On Tue, May 25, 2010 at 12:38 PM, Igor V. Kovalenko igor.v.kovalenko@gmail.com wrote:
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- refactor scan procedure to start with PCI host controller
- initiate scan of subordinate PCI bus from PCI host and PCI-to-PCI bridges
- find out PCI subordinate bus numbers and write them to bride devices
- automated assignment of "reg", "ranges", and "bus-range" properties
Unfortunately this breaks the PPC Mac99 machine.
To test, simply run 'qemu-system-ppc -M mac99', the screen remains black. 5/10 still works.
The expectation to have host PCI bridge at pci0:0:0 is invalid, mac99 has it at device 0xb The following change attached hereto fixes that by adding a scan for host bridge.
It would be great if you could include it into the set after currently failing one, thanks!
On Thu, May 27, 2010 at 12:24 AM, Igor Kovalenko igor.v.kovalenko@gmail.com wrote:
On Wed, May 26, 2010 at 11:02 PM, Blue Swirl blauwirbel@gmail.com wrote:
On Tue, May 25, 2010 at 12:38 PM, Igor V. Kovalenko igor.v.kovalenko@gmail.com wrote:
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- refactor scan procedure to start with PCI host controller
- initiate scan of subordinate PCI bus from PCI host and PCI-to-PCI bridges
- find out PCI subordinate bus numbers and write them to bride devices
- automated assignment of "reg", "ranges", and "bus-range" properties
Unfortunately this breaks the PPC Mac99 machine.
To test, simply run 'qemu-system-ppc -M mac99', the screen remains black. 5/10 still works.
The expectation to have host PCI bridge at pci0:0:0 is invalid, mac99 has it at device 0xb The following change attached hereto fixes that by adding a scan for host bridge.
It would be great if you could include it into the set after currently failing one, thanks!
Unfortunately there is a typo in ob_pci_read_identification, it must check pointers before assignment, not data pointed to. It does not produce errors in my -M mac99 test but breaks sparc64 test.
Please check the updated version attached. I now tested qemu-system-sparc64 and qemu-system-ppc -M mac99 with updated version.
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- reformat to new style, no functional changes
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- arch/ppc/qemu/init.c | 92 +++++++++++++++++++++++++++++++++++--------------- 1 files changed, 64 insertions(+), 28 deletions(-)
diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index 07ac09d..13887e0 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -84,34 +84,70 @@ int is_newworld(void) }
static const pci_arch_t known_arch[] = { - [ARCH_PREP] = { "PREP", PCI_VENDOR_ID_MOTOROLA, - PCI_DEVICE_ID_MOTOROLA_RAVEN, - 0x80800000, 0x800c0000, - 0x80000000, 0x00100000, 0xf0000000, 0x10000000, - 0x80000000, 0x00010000, 0x00000000, 0x00400000, - { 9, 11, 9, 11 } - }, - [ARCH_MAC99] = { "MAC99", PCI_VENDOR_ID_APPLE, - PCI_DEVICE_ID_APPLE_UNI_N_PCI, - 0xf2800000, 0xf2c00000, - 0xf2000000, 0x02000000, 0x80000000, 0x10000000, - 0xf2000000, 0x00800000, 0x00000000, 0x01000000, - { 0x1b, 0x1c, 0x1d, 0x1e } - }, - [ARCH_MAC99_U3] = { "MAC99_U3", PCI_VENDOR_ID_APPLE, - PCI_DEVICE_ID_APPLE_U3_AGP, - 0xf0800000, 0xf0c00000, - 0xf0000000, 0x02000000, 0x80000000, 0x10000000, - 0xf2000000, 0x00800000, 0x00000000, 0x01000000, - { 0x1b, 0x1c, 0x1d, 0x1e } - }, - [ARCH_HEATHROW] = { "HEATHROW", PCI_VENDOR_ID_MOTOROLA, - PCI_DEVICE_ID_MOTOROLA_MPC106, - 0xfec00000, 0xfee00000, - 0x80000000, 0x7f000000, 0x80000000, 0x01000000, - 0xfe000000, 0x00800000, 0xfd000000, 0x01000000, - { 21, 22, 23, 24 } - }, + [ARCH_PREP] = { + .name = "PREP", + .vendor_id = PCI_VENDOR_ID_MOTOROLA, + .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN, + .cfg_addr = 0x80800000, + .cfg_data = 0x800c0000, + .cfg_base = 0x80000000, + .cfg_len = 0x00100000, + .mem_base = 0xf0000000, + .mem_len = 0x10000000, + .io_base = 0x80000000, + .io_len = 0x00010000, + .rbase = 0x00000000, + .rlen = 0x00400000, + .irqs = { 9, 11, 9, 11 } + }, + [ARCH_MAC99] = { + .name = "MAC99", + .vendor_id = PCI_VENDOR_ID_APPLE, + .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI, + .cfg_addr = 0xf2800000, + .cfg_data = 0xf2c00000, + .cfg_base = 0xf2000000, + .cfg_len = 0x02000000, + .mem_base = 0x80000000, + .mem_len = 0x10000000, + .io_base = 0xf2000000, + .io_len = 0x00800000, + .rbase = 0x00000000, + .rlen = 0x01000000, + .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } + }, + [ARCH_MAC99_U3] = { + .name = "MAC99_U3", + .vendor_id = PCI_VENDOR_ID_APPLE, + .device_id = PCI_DEVICE_ID_APPLE_U3_AGP, + .cfg_addr = 0xf0800000, + .cfg_data = 0xf0c00000, + .cfg_base = 0xf0000000, + .cfg_len = 0x02000000, + .mem_base = 0x80000000, + .mem_len = 0x10000000, + .io_base = 0xf2000000, + .io_len = 0x00800000, + .rbase = 0x00000000, + .rlen = 0x01000000, + .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } + }, + [ARCH_HEATHROW] = { + .name = "HEATHROW", + .vendor_id = PCI_VENDOR_ID_MOTOROLA, + .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106, + .cfg_addr = 0xfec00000, + .cfg_data = 0xfee00000, + .cfg_base = 0x80000000, + .cfg_len = 0x7f000000, + .mem_base = 0x80000000, + .mem_len = 0x01000000, + .io_base = 0xfe000000, + .io_len = 0x00800000, + .rbase = 0xfd000000, + .rlen = 0x01000000, + .irqs = { 21, 22, 23, 24 } + }, }; uint32_t isa_io_base;
Am 25.05.2010 um 14:38 schrieb Igor V. Kovalenko:
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- reformat to new style, no functional changes
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com
arch/ppc/qemu/init.c | 92 ++++++++++++++++++++++++++++++++++ +--------------- 1 files changed, 64 insertions(+), 28 deletions(-)
Looks okay, thanks.
Andreas
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- sparc64 has PCI memory space at offset, therefore "ranges" property of host bridge must have different PCI and host memory addresses
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- arch/ppc/qemu/init.c | 12 ++++++++---- arch/sparc64/openbios.c | 3 ++- drivers/pci.c | 8 ++++---- include/drivers/pci.h | 3 ++- 4 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index 13887e0..a459baa 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -92,7 +92,8 @@ static const pci_arch_t known_arch[] = { .cfg_data = 0x800c0000, .cfg_base = 0x80000000, .cfg_len = 0x00100000, - .mem_base = 0xf0000000, + .host_mem_base = 0xf0000000, + .pci_mem_base = 0xf0000000, .mem_len = 0x10000000, .io_base = 0x80000000, .io_len = 0x00010000, @@ -108,7 +109,8 @@ static const pci_arch_t known_arch[] = { .cfg_data = 0xf2c00000, .cfg_base = 0xf2000000, .cfg_len = 0x02000000, - .mem_base = 0x80000000, + .host_mem_base = 0x80000000, + .pci_mem_base = 0x80000000, .mem_len = 0x10000000, .io_base = 0xf2000000, .io_len = 0x00800000, @@ -124,7 +126,8 @@ static const pci_arch_t known_arch[] = { .cfg_data = 0xf0c00000, .cfg_base = 0xf0000000, .cfg_len = 0x02000000, - .mem_base = 0x80000000, + .host_mem_base = 0x80000000, + .pci_mem_base = 0x80000000, .mem_len = 0x10000000, .io_base = 0xf2000000, .io_len = 0x00800000, @@ -140,7 +143,8 @@ static const pci_arch_t known_arch[] = { .cfg_data = 0xfee00000, .cfg_base = 0x80000000, .cfg_len = 0x7f000000, - .mem_base = 0x80000000, + .host_mem_base = 0x80000000, + .pci_mem_base = 0x80000000, .mem_len = 0x01000000, .io_base = 0xfe000000, .io_len = 0x00800000, diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index 3f583f2..23faa29 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -64,7 +64,8 @@ static const struct hwdef hwdefs[] = { .cfg_data = APB_MEM_BASE, // PCI bus memory space .cfg_base = APB_SPECIAL_BASE, .cfg_len = 0x2000000, - .mem_base = APB_MEM_BASE, + .host_mem_base = APB_MEM_BASE, + .pci_mem_base = 0, .mem_len = 0x10000000, .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space .io_len = 0x10000, diff --git a/drivers/pci.c b/drivers/pci.c index f8d0b41..5a2be02 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -455,10 +455,10 @@ static void pci_host_set_ranges(const pci_config_t *config) ncells += host_encode_phys_addr(props + ncells, arch->rbase); ncells += pci_encode_size(props + ncells, arch->rlen); } - if (arch->mem_base) { + if (arch->host_mem_base) { ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, - config->dev, 0, arch->mem_base); - ncells += host_encode_phys_addr(props + ncells, arch->mem_base); + config->dev, 0, arch->pci_mem_base); + ncells += host_encode_phys_addr(props + ncells, arch->host_mem_base); ncells += pci_encode_size(props + ncells, arch->mem_len); } set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); @@ -1224,7 +1224,7 @@ int ob_pci_init(void)
/* Find all PCI bridges */
- mem_base = arch->mem_base; + mem_base = arch->pci_mem_base; /* I/O ports under 0x400 are used by devices mapped at fixed location. */ io_base = arch->io_base + 0x400; diff --git a/include/drivers/pci.h b/include/drivers/pci.h index 8814b7a..562a43e 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -13,7 +13,8 @@ struct pci_arch_t { unsigned long cfg_data; unsigned long cfg_base; unsigned long cfg_len; - unsigned long mem_base; + unsigned long host_mem_base; /* in host memory space */ + unsigned long pci_mem_base; /* in PCI memory space */ unsigned long mem_len; unsigned long io_base; unsigned long io_len;
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
- consider only PCI BARs with non-zero region size when pupulating "reg" and "assigned-addresses" properties
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/pci.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 5a2be02..d22ac58 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -603,7 +603,8 @@ static void pci_set_assigned_addresses(phandle_t phandle,
ncells = 0; for (i = 0; i < num_bars; i++) { - if (!config->assigned[i] || !config->sizes[i]) + /* consider only bars with non-zero region size */ + if (!config->sizes[i]) continue; pci_decode_pci_addr(config->assigned[i], &flags, &space_code, &mask); @@ -662,7 +663,8 @@ static void pci_set_reg(phandle_t phandle, ncells += pci_encode_size(props + ncells, 0);
for (i = 0; i < num_bars; i++) { - if (!config->assigned[i] || !config->sizes[i]) + /* consider only bars with non-zero region size */ + if (!config->sizes[i]) continue;
pci_decode_pci_addr(config->regions[i],
From: Igor V. Kovalenko igor.v.kovalenko@gmail.com
Signed-off-by: Igor V. Kovalenko igor.v.kovalenko@gmail.com --- drivers/pci.c | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index d22ac58..bd5abe0 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -546,24 +546,24 @@ int eth_config_cb (const pci_config_t *config) static inline void pci_decode_pci_addr(pci_addr addr, int *flags, int *space_code, uint32_t *mask) { - if (addr & 0x01) { + *flags = 0;
+ if (addr & 0x01) { *space_code = IO_SPACE; - *flags = 0; *mask = 0x00000001; - - } else if (addr & 0x04) { - - *flags = IS_NOT_RELOCATABLE; - *space_code = MEMORY_SPACE_64; - *mask = 0x0000000F; - } else { + if (addr & 0x04) { + *space_code = MEMORY_SPACE_64; + *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */ + } else { + *space_code = MEMORY_SPACE_32; + }
- *space_code = MEMORY_SPACE_32; - *flags = IS_NOT_RELOCATABLE; - *mask = 0x0000000F; + if (addr & 0x08) { + *flags |= IS_PREFETCHABLE; + }
+ *mask = 0x0000000F; } }
Igor V. Kovalenko wrote:
These mostly are cleanups up to pci bus scan amendment changes.
The pci bus scan is reworked, now we start with pci host bridge which will initiate primary bus scan. PCI-to-PCI bridges do the same.
Although bridges are still mostly unusable in qemu due to missing address space remappings one can now put e.g. ide and vga on sun4u behind secondary bus and see it is found correctly and can be configured.
With these applied my debian etch ppc installation still boots to shell, and helenos can get to video screen (with appropriate QEMU,VGA driver.) Another bonus point that on sparc64 recent linux "btext" boot console works (colors are a bit off though.)
Igor V. Kovalenko (10): ebus: set addressing to 2 address cells and 1 size cells ide: fix property data size video: framebuffer properties must be 32bit values pci: property encoding helpers pci: debug printk macros pci: bus scan amendment new style arch declarations for ppc/qemu pci: add host memory base to pci_arch_t pci: allow BARs with zero assigned address pci: assign relocatable address ranges
Thanks for the patchset - this is great progress! Overall the patch looks reasonably sensible to me, but will defer to Blue for technical feedback and commit.
ATB,
Mark.
On Tue, May 25, 2010 at 3:22 PM, Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk wrote:
Igor V. Kovalenko wrote:
These mostly are cleanups up to pci bus scan amendment changes.
The pci bus scan is reworked, now we start with pci host bridge which will initiate primary bus scan. PCI-to-PCI bridges do the same.
Although bridges are still mostly unusable in qemu due to missing address space remappings one can now put e.g. ide and vga on sun4u behind secondary bus and see it is found correctly and can be configured.
With these applied my debian etch ppc installation still boots to shell, and helenos can get to video screen (with appropriate QEMU,VGA driver.) Another bonus point that on sparc64 recent linux "btext" boot console works (colors are a bit off though.)
Igor V. Kovalenko (10): ebus: set addressing to 2 address cells and 1 size cells ide: fix property data size video: framebuffer properties must be 32bit values pci: property encoding helpers pci: debug printk macros pci: bus scan amendment new style arch declarations for ppc/qemu pci: add host memory base to pci_arch_t pci: allow BARs with zero assigned address pci: assign relocatable address ranges
Thanks for the patchset - this is great progress! Overall the patch looks reasonably sensible to me, but will defer to Blue for technical feedback and commit.
I also think they are very nice, I'll have to run a few tests though.
Hey,
I'm still a bit puzzled about the cell vs. int concept here... Some of the patches seem to account for cell being 64-bit on sparc64. On ppc(64) however ucell is 32-bit, so wouldn't we need to modify at least our new ofmem_arch_get_translation_entry_size and ofmem_arch_create_translation_entry as well to account for 64-bit physical and virtual addresses?
Andreas
On Wed, May 26, 2010 at 12:47 AM, Andreas Färber andreas.faerber@web.de wrote:
Hey,
I'm still a bit puzzled about the cell vs. int concept here... Some of the patches seem to account for cell being 64-bit on sparc64. On ppc(64) however ucell is 32-bit, so wouldn't we need to modify at least our new ofmem_arch_get_translation_entry_size and ofmem_arch_create_translation_entry as well to account for 64-bit physical and virtual addresses?
Yes, those must be changed as well. Current implementation is OK at the moment though since hardcoded encode method yields the same result as address-cells-aware one. F.e. on sparc64 we will encode 6 u32 values instead of 3 u64 we do now. In my wish list: - ofmem_common: switch to 32bit properties - pci_set_AAPL_address: same
On Tue, May 25, 2010 at 12:37 PM, Igor V. Kovalenko igor.v.kovalenko@gmail.com wrote:
These mostly are cleanups up to pci bus scan amendment changes.
The pci bus scan is reworked, now we start with pci host bridge which will initiate primary bus scan. PCI-to-PCI bridges do the same.
Although bridges are still mostly unusable in qemu due to missing address space remappings one can now put e.g. ide and vga on sun4u behind secondary bus and see it is found correctly and can be configured.
With these applied my debian etch ppc installation still boots to shell, and helenos can get to video screen (with appropriate QEMU,VGA driver.) Another bonus point that on sparc64 recent linux "btext" boot console works (colors are a bit off though.)
Thanks, applied all with the fix merged to 6/10.
Igor V. Kovalenko (10): ebus: set addressing to 2 address cells and 1 size cells ide: fix property data size video: framebuffer properties must be 32bit values pci: property encoding helpers pci: debug printk macros pci: bus scan amendment new style arch declarations for ppc/qemu pci: add host memory base to pci_arch_t pci: allow BARs with zero assigned address pci: assign relocatable address ranges
arch/ppc/qemu/init.c | 96 ++++-- arch/sparc64/openbios.c | 3 drivers/ide.c | 22 + drivers/pci.c | 652 +++++++++++++++++++++++++++------------- drivers/pci.h | 4 drivers/pci_database.c | 2 drivers/pci_database.h | 3 drivers/vga_vbe.c | 8 include/drivers/pci.h | 3 include/libopenbios/bindings.h | 8 libopenbios/bindings.c | 6 packages/video.c | 10 - 12 files changed, 549 insertions(+), 268 deletions(-)
--
-- OpenBIOS http://openbios.org/ Mailinglist: http://lists.openbios.org/mailman/listinfo Free your System - May the Forth be with you