X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fdevices%2Fpci_device.c;h=f54e2620bf78c6e6564cf14523bb4a54d587881b;hb=35e912cef3aac245202694736281aa8475e977f1;hp=4a9fa1466e7713ce1696842827b909a938fda950;hpb=7eac4450b32f6961d5abd8dae32c5eefc1a07c11;p=coreboot.git diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c index 4a9fa1466..f54e2620b 100644 --- a/src/devices/pci_device.c +++ b/src/devices/pci_device.c @@ -48,14 +48,20 @@ #if CONFIG_CARDBUS_PLUGIN_SUPPORT == 1 #include #endif -#define CONFIG_PC80_SYSTEM 1 #if CONFIG_PC80_SYSTEM == 1 #include #endif +#if CONFIG_HAVE_ACPI_RESUME && !CONFIG_S3_VGA_ROM_RUN +#include +#endif +#if CONFIG_CHROMEOS +#include +#endif u8 pci_moving_config8(struct device *dev, unsigned int reg) { u8 value, ones, zeroes; + value = pci_read_config8(dev, reg); pci_write_config8(dev, reg, 0xff); @@ -69,9 +75,10 @@ u8 pci_moving_config8(struct device *dev, unsigned int reg) return ones ^ zeroes; } -u16 pci_moving_config16(struct device * dev, unsigned int reg) +u16 pci_moving_config16(struct device *dev, unsigned int reg) { u16 value, ones, zeroes; + value = pci_read_config16(dev, reg); pci_write_config16(dev, reg, 0xffff); @@ -85,9 +92,10 @@ u16 pci_moving_config16(struct device * dev, unsigned int reg) return ones ^ zeroes; } -u32 pci_moving_config32(struct device * dev, unsigned int reg) +u32 pci_moving_config32(struct device *dev, unsigned int reg) { u32 value, ones, zeroes; + value = pci_read_config32(dev, reg); pci_write_config32(dev, reg, 0xffffffff); @@ -106,20 +114,21 @@ u32 pci_moving_config32(struct device * dev, unsigned int reg) * matching capability. Always start at the head of the list. * * @param dev Pointer to the device structure. - * @param cap_type PCI_CAP_LIST_ID of the PCI capability we're looking for. + * @param cap PCI_CAP_LIST_ID of the PCI capability we're looking for. * @param last Location of the PCI capability register to start from. + * @return The next matching capability. */ unsigned pci_find_next_capability(struct device *dev, unsigned cap, unsigned last) { unsigned pos = 0; - unsigned status; + u16 status; unsigned reps = 48; status = pci_read_config16(dev, PCI_STATUS); - if (!(status & PCI_STATUS_CAP_LIST)) { + if (!(status & PCI_STATUS_CAP_LIST)) return 0; - } + switch (dev->hdr_type & 0x7f) { case PCI_HEADER_TYPE_NORMAL: case PCI_HEADER_TYPE_BRIDGE: @@ -131,22 +140,24 @@ unsigned pci_find_next_capability(struct device *dev, unsigned cap, default: return 0; } + pos = pci_read_config8(dev, pos); - while (reps-- && (pos >= 0x40)) { /* Loop through the linked list. */ + while (reps-- && (pos >= 0x40)) { /* Loop through the linked list. */ int this_cap; + pos &= ~3; this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID); - printk(BIOS_SPEW, "Capability: type 0x%02x @ 0x%02x\n", this_cap, - pos); - if (this_cap == 0xff) { + printk(BIOS_SPEW, "Capability: type 0x%02x @ 0x%02x\n", + this_cap, pos); + if (this_cap == 0xff) break; - } - if (!last && (this_cap == cap)) { + + if (!last && (this_cap == cap)) return pos; - } - if (last == pos) { + + if (last == pos) last = 0; - } + pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT); } return 0; @@ -157,7 +168,8 @@ unsigned pci_find_next_capability(struct device *dev, unsigned cap, * capability. Always start at the head of the list. * * @param dev Pointer to the device structure. - * @param cap_type PCI_CAP_LIST_ID of the PCI capability we're looking for. + * @param cap PCI_CAP_LIST_ID of the PCI capability we're looking for. + * @return The next matching capability. */ unsigned pci_find_capability(device_t dev, unsigned cap) { @@ -169,6 +181,7 @@ unsigned pci_find_capability(device_t dev, unsigned cap) * * @param dev Pointer to the device structure. * @param index Address of the PCI configuration register. + * @return TODO */ struct resource *pci_get_resource(struct device *dev, unsigned long index) { @@ -196,6 +209,7 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index) moving |= ((resource_t) pci_moving_config32(dev, index + 4)) << 32; } + /* Find the resource constraints. * Start by finding the bits that move. From there: * - Size is the least significant bit of the bits that move. @@ -214,20 +228,25 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index) resource->limit = limit = moving | (resource->size - 1); } - /* Some broken hardware has read-only registers that do not + /* + * Some broken hardware has read-only registers that do not * really size correctly. - * Example: the Acer M7229 has BARs 1-4 normally read-only. + * + * Example: the Acer M7229 has BARs 1-4 normally read-only, * so BAR1 at offset 0x10 reads 0x1f1. If you size that register - * by writing 0xffffffff to it, it will read back as 0x1f1 -- a - * violation of the spec. - * We catch this case and ignore it by observing which bits move, - * This also catches the common case unimplemented registers + * by writing 0xffffffff to it, it will read back as 0x1f1 -- which + * is a violation of the spec. + * + * We catch this case and ignore it by observing which bits move. + * + * This also catches the common case of unimplemented registers * that always read back as 0. */ if (moving == 0) { if (value != 0) { - printk(BIOS_DEBUG, "%s register %02lx(%08lx), read-only ignoring it\n", - dev_path(dev), index, value); + printk(BIOS_DEBUG, "%s register %02lx(%08lx), " + "read-only ignoring it\n", + dev_path(dev), index, value); } resource->flags = 0; } else if (attr & PCI_BASE_ADDRESS_SPACE_IO) { @@ -240,9 +259,8 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index) /* A Memory mapped base address. */ attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK; resource->flags |= IORESOURCE_MEM; - if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH) { + if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH) resource->flags |= IORESOURCE_PREFETCH; - } attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK; if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) { /* 32bit limit. */ @@ -262,10 +280,10 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index) resource->flags = 0; } } + /* Don't let the limit exceed which bits can move. */ - if (resource->limit > limit) { + if (resource->limit > limit) resource->limit = limit; - } return resource; } @@ -312,8 +330,9 @@ static void pci_get_rom_resource(struct device *dev, unsigned long index) resource->flags |= IORESOURCE_MEM | IORESOURCE_READONLY; } else { if (value != 0) { - printk(BIOS_DEBUG, "%s register %02lx(%08lx), read-only ignoring it\n", - dev_path(dev), index, value); + printk(BIOS_DEBUG, "%s register %02lx(%08lx), " + "read-only ignoring it\n", + dev_path(dev), index, value); } resource->flags = 0; } @@ -343,27 +362,29 @@ static void pci_read_bases(struct device *dev, unsigned int howmany) static void pci_record_bridge_resource(struct device *dev, resource_t moving, unsigned index, unsigned long type) { - /* Initialize the constraints on the current bus. */ struct resource *resource; + unsigned long gran; + resource_t step; + resource = NULL; - if (moving) { - unsigned long gran; - resource_t step; - resource = new_resource(dev, index); - resource->size = 0; - gran = 0; - step = 1; - while ((moving & step) == 0) { - gran += 1; - step <<= 1; - } - resource->gran = gran; - resource->align = gran; - resource->limit = moving | (step - 1); - resource->flags = type | IORESOURCE_PCI_BRIDGE | - IORESOURCE_BRIDGE; + + if (!moving) + return; + + /* Initialize the constraints on the current bus. */ + resource = new_resource(dev, index); + resource->size = 0; + gran = 0; + step = 1; + while ((moving & step) == 0) { + gran += 1; + step <<= 1; } - return; + resource->gran = gran; + resource->align = gran; + resource->limit = moving | (step - 1); + resource->flags = type | IORESOURCE_PCI_BRIDGE | + IORESOURCE_BRIDGE; } static void pci_bridge_read_bases(struct device *dev) @@ -373,11 +394,11 @@ static void pci_bridge_read_bases(struct device *dev) /* See if the bridge I/O resources are implemented. */ moving_base = ((u32) pci_moving_config8(dev, PCI_IO_BASE)) << 8; moving_base |= - ((u32) pci_moving_config16(dev, PCI_IO_BASE_UPPER16)) << 16; + ((u32) pci_moving_config16(dev, PCI_IO_BASE_UPPER16)) << 16; moving_limit = ((u32) pci_moving_config8(dev, PCI_IO_LIMIT)) << 8; moving_limit |= - ((u32) pci_moving_config16(dev, PCI_IO_LIMIT_UPPER16)) << 16; + ((u32) pci_moving_config16(dev, PCI_IO_LIMIT_UPPER16)) << 16; moving = moving_base & moving_limit; @@ -386,17 +407,14 @@ static void pci_bridge_read_bases(struct device *dev) /* See if the bridge prefmem resources are implemented. */ moving_base = - ((resource_t) pci_moving_config16(dev, PCI_PREF_MEMORY_BASE)) << 16; + ((resource_t) pci_moving_config16(dev, PCI_PREF_MEMORY_BASE)) << 16; moving_base |= - ((resource_t) pci_moving_config32(dev, PCI_PREF_BASE_UPPER32)) << - 32; + ((resource_t) pci_moving_config32(dev, PCI_PREF_BASE_UPPER32)) << 32; moving_limit = - ((resource_t) pci_moving_config16(dev, PCI_PREF_MEMORY_LIMIT)) << - 16; + ((resource_t) pci_moving_config16(dev, PCI_PREF_MEMORY_LIMIT)) << 16; moving_limit |= - ((resource_t) pci_moving_config32(dev, PCI_PREF_LIMIT_UPPER32)) << - 32; + ((resource_t) pci_moving_config32(dev, PCI_PREF_LIMIT_UPPER32)) << 32; moving = moving_base & moving_limit; /* Initialize the prefetchable memory constraints on the current bus. */ @@ -452,26 +470,23 @@ static void pci_set_resource(struct device *dev, struct resource *resource) /* Make certain the resource has actually been assigned a value. */ if (!(resource->flags & IORESOURCE_ASSIGNED)) { - printk(BIOS_ERR, "ERROR: %s %02lx %s size: 0x%010llx not assigned\n", - dev_path(dev), resource->index, - resource_type(resource), resource->size); + printk(BIOS_ERR, "ERROR: %s %02lx %s size: 0x%010llx not " + "assigned\n", dev_path(dev), resource->index, + resource_type(resource), resource->size); return; } /* If this resource is fixed don't worry about it. */ - if (resource->flags & IORESOURCE_FIXED) { + if (resource->flags & IORESOURCE_FIXED) return; - } /* If I have already stored this resource don't worry about it. */ - if (resource->flags & IORESOURCE_STORED) { + if (resource->flags & IORESOURCE_STORED) return; - } /* If the resource is subtractive don't worry about it. */ - if (resource->flags & IORESOURCE_SUBTRACTIVE) { + if (resource->flags & IORESOURCE_SUBTRACTIVE) return; - } /* Only handle PCI memory and I/O resources for now. */ if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO))) @@ -479,16 +494,14 @@ static void pci_set_resource(struct device *dev, struct resource *resource) /* Enable the resources in the command register. */ if (resource->size) { - if (resource->flags & IORESOURCE_MEM) { + if (resource->flags & IORESOURCE_MEM) dev->command |= PCI_COMMAND_MEMORY; - } - if (resource->flags & IORESOURCE_IO) { + if (resource->flags & IORESOURCE_IO) dev->command |= PCI_COMMAND_IO; - } - if (resource->flags & IORESOURCE_PCI_BRIDGE) { + if (resource->flags & IORESOURCE_PCI_BRIDGE) dev->command |= PCI_COMMAND_MASTER; - } } + /* Get the base address. */ base = resource->base; @@ -498,8 +511,9 @@ static void pci_set_resource(struct device *dev, struct resource *resource) /* Now store the resource. */ resource->flags |= IORESOURCE_STORED; - /* PCI Bridges have no enable bit. They are disabled if the base of - * the range is greater than the limit. If the size is zero, disable + /* + * PCI bridges have no enable bit. They are disabled if the base of + * the range is greater than the limit. If the size is zero, disable * by setting the base = limit and end = limit - 2^gran. */ if (resource->size == 0 && (resource->flags & IORESOURCE_PCI_BRIDGE)) { @@ -510,18 +524,18 @@ static void pci_set_resource(struct device *dev, struct resource *resource) if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) { unsigned long base_lo, base_hi; - /* Some chipsets allow us to set/clear the I/O bit - * (e.g. VIA 82c686a). So set it to be safe. + + /* + * Some chipsets allow us to set/clear the I/O bit + * (e.g. VIA 82C686A). So set it to be safe. */ base_lo = base & 0xffffffff; base_hi = (base >> 32) & 0xffffffff; - if (resource->flags & IORESOURCE_IO) { + if (resource->flags & IORESOURCE_IO) base_lo |= PCI_BASE_ADDRESS_SPACE_IO; - } pci_write_config32(dev, resource->index, base_lo); - if (resource->flags & IORESOURCE_PCI64) { + if (resource->flags & IORESOURCE_PCI64) pci_write_config32(dev, resource->index + 4, base_hi); - } } else if (resource->index == PCI_IO_BASE) { /* Set the I/O ranges. */ pci_write_config8(dev, PCI_IO_BASE, base >> 8); @@ -542,10 +556,10 @@ static void pci_set_resource(struct device *dev, struct resource *resource) /* Don't let me think I stored the resource. */ resource->flags &= ~IORESOURCE_STORED; printk(BIOS_ERR, "ERROR: invalid resource->index %lx\n", - resource->index); + resource->index); } + report_resource_stored(dev, resource, ""); - return; } void pci_dev_set_resources(struct device *dev) @@ -554,28 +568,26 @@ void pci_dev_set_resources(struct device *dev) struct bus *bus; u8 line; - for (res = dev->resource_list; res; res = res->next) { + for (res = dev->resource_list; res; res = res->next) pci_set_resource(dev, res); - } + for (bus = dev->link_list; bus; bus = bus->next) { - if (bus->children) { + if (bus->children) assign_resources(bus); - } } /* Set a default latency timer. */ pci_write_config8(dev, PCI_LATENCY_TIMER, 0x40); /* Set a default secondary latency timer. */ - if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) { + if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) pci_write_config8(dev, PCI_SEC_LATENCY_TIMER, 0x40); - } /* Zero the IRQ settings. */ line = pci_read_config8(dev, PCI_INTERRUPT_PIN); - if (line) { + if (line) pci_write_config8(dev, PCI_INTERRUPT_LINE, 0); - } + /* Set the cache line size, so far 64 bytes is good for everyone. */ pci_write_config8(dev, PCI_CACHE_LINE_SIZE, 64 >> 2); } @@ -585,22 +597,22 @@ void pci_dev_enable_resources(struct device *dev) const struct pci_operations *ops; u16 command; - /* Set the subsystem vendor and device id for mainboard devices. */ + /* Set the subsystem vendor and device ID for mainboard devices. */ ops = ops_pci(dev); if (dev->on_mainboard && ops && ops->set_subsystem) { - printk(BIOS_DEBUG, "%s subsystem <- %02x/%02x\n", - dev_path(dev), - CONFIG_MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID, - CONFIG_MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID); - ops->set_subsystem(dev, - CONFIG_MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID, - CONFIG_MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID); + printk(BIOS_DEBUG, "%s subsystem <- %04x/%04x\n", + dev_path(dev), dev->subsystem_vendor, + dev->subsystem_device); + ops->set_subsystem(dev, dev->subsystem_vendor, + dev->subsystem_device); } command = pci_read_config16(dev, PCI_COMMAND); command |= dev->command; + /* v3 has * command |= (PCI_COMMAND_PARITY + PCI_COMMAND_SERR); // Error check. */ + printk(BIOS_DEBUG, "%s cmd <- %02x\n", dev_path(dev), command); pci_write_config16(dev, PCI_COMMAND, command); } @@ -609,14 +621,15 @@ void pci_bus_enable_resources(struct device *dev) { u16 ctrl; - /* Enable I/O in command register if there is VGA card + /* + * Enable I/O in command register if there is VGA card * connected with (even it does not claim I/O resource). */ if (dev->link_list->bridge_ctrl & PCI_BRIDGE_CTL_VGA) dev->command |= PCI_COMMAND_IO; ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL); ctrl |= dev->link_list->bridge_ctrl; - ctrl |= (PCI_BRIDGE_CTL_PARITY + PCI_BRIDGE_CTL_SERR); /* Error check. */ + ctrl |= (PCI_BRIDGE_CTL_PARITY + PCI_BRIDGE_CTL_SERR); /* Error check. */ printk(BIOS_DEBUG, "%s bridge ctrl <- %04x\n", dev_path(dev), ctrl); pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl); @@ -625,11 +638,13 @@ void pci_bus_enable_resources(struct device *dev) void pci_bus_reset(struct bus *bus) { - unsigned ctl; + u16 ctl; + ctl = pci_read_config16(bus->dev, PCI_BRIDGE_CONTROL); ctl |= PCI_BRIDGE_CTL_BUS_RESET; pci_write_config16(bus->dev, PCI_BRIDGE_CONTROL, ctl); mdelay(10); + ctl &= ~PCI_BRIDGE_CTL_BUS_RESET; pci_write_config16(bus->dev, PCI_BRIDGE_CONTROL, ctl); delay(1); @@ -641,7 +656,7 @@ void pci_dev_set_subsystem(struct device *dev, unsigned vendor, unsigned device) ((device & 0xffff) << 16) | (vendor & 0xffff)); } -/** default handler: only runs the relevant pci bios. */ +/** Default handler: only runs the relevant PCI BIOS. */ void pci_dev_init(struct device *dev) { #if CONFIG_PCI_ROM_RUN == 1 || CONFIG_VGA_ROM_RUN == 1 @@ -655,6 +670,15 @@ void pci_dev_init(struct device *dev) ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)) return; +#if CONFIG_CHROMEOS + /* In ChromeOS we want to boot blazingly fast. Therefore + * we don't run (VGA) option ROMs, unless we have to print + * something on the screen before the kernel is loaded. + */ + if (!developer_mode_enabled() && !recovery_mode_enabled()) + return; +#endif + rom = pci_rom_probe(dev); if (rom == NULL) return; @@ -663,12 +687,15 @@ void pci_dev_init(struct device *dev) if (ram == NULL) return; +#if CONFIG_HAVE_ACPI_RESUME && !CONFIG_S3_VGA_ROM_RUN + /* If S3_VGA_ROM_RUN is disabled, skip running VGA option + * ROMs when coming out of an S3 resume. + */ + if ((acpi_slp_type == 3) && + ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)) + return; +#endif run_bios(dev, (unsigned long)ram); - -#if CONFIG_CONSOLE_VGA == 1 - if ((dev->class>>8) == PCI_CLASS_DISPLAY_VGA) - vga_console_init(); -#endif /* CONFIG_CONSOLE_VGA */ #endif /* CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN */ } @@ -678,13 +705,13 @@ static struct pci_operations pci_dev_ops_pci = { }; struct device_operations default_pci_ops_dev = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, - .init = pci_dev_init, - .scan_bus = 0, - .enable = 0, - .ops_pci = &pci_dev_ops_pci, + .init = pci_dev_init, + .scan_bus = 0, + .enable = 0, + .ops_pci = &pci_dev_ops_pci, }; /** Default device operations for PCI bridges */ @@ -693,33 +720,33 @@ static struct pci_operations pci_bus_ops_pci = { }; struct device_operations default_pci_ops_bus = { - .read_resources = pci_bus_read_resources, - .set_resources = pci_dev_set_resources, + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, .enable_resources = pci_bus_enable_resources, - .init = 0, - .scan_bus = pci_scan_bridge, - .enable = 0, - .reset_bus = pci_bus_reset, - .ops_pci = &pci_bus_ops_pci, + .init = 0, + .scan_bus = pci_scan_bridge, + .enable = 0, + .reset_bus = pci_bus_reset, + .ops_pci = &pci_bus_ops_pci, }; /** - * @brief Detect the type of downstream bridge + * Detect the type of downstream bridge. * * This function is a heuristic to detect which type of bus is downstream * of a PCI-to-PCI bridge. This functions by looking for various capability * blocks to figure out the type of downstream bridge. PCI-X, PCI-E, and * Hypertransport all seem to have appropriate capabilities. * - * When only a PCI-Express capability is found the type - * is examined to see which type of bridge we have. + * When only a PCI-Express capability is found the type is examined to see + * which type of bridge we have. * * @param dev Pointer to the device structure of the bridge. * @return Appropriate bridge operations. */ static struct device_operations *get_pci_bridge_ops(device_t dev) { - unsigned pos; + unsigned int pos; #if CONFIG_PCIX_PLUGIN_SUPPORT == 1 pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); @@ -729,17 +756,17 @@ static struct device_operations *get_pci_bridge_ops(device_t dev) } #endif #if CONFIG_AGP_PLUGIN_SUPPORT == 1 - /* How do I detect an PCI to AGP bridge? */ + /* How do I detect a PCI to AGP bridge? */ #endif #if CONFIG_HYPERTRANSPORT_PLUGIN_SUPPORT == 1 pos = 0; while ((pos = pci_find_next_capability(dev, PCI_CAP_ID_HT, pos))) { - unsigned flags; + u16 flags; flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS); if ((flags >> 13) == 1) { /* Host or Secondary Interface */ - printk(BIOS_DEBUG, "%s subordinate bus Hypertransport\n", - dev_path(dev)); + printk(BIOS_DEBUG, "%s subordinate bus HT\n", + dev_path(dev)); return &default_ht_ops_bus; } } @@ -747,17 +774,18 @@ static struct device_operations *get_pci_bridge_ops(device_t dev) #if CONFIG_PCIEXP_PLUGIN_SUPPORT == 1 pos = pci_find_capability(dev, PCI_CAP_ID_PCIE); if (pos) { - unsigned flags; + u16 flags; flags = pci_read_config16(dev, pos + PCI_EXP_FLAGS); switch ((flags & PCI_EXP_FLAGS_TYPE) >> 4) { case PCI_EXP_TYPE_ROOT_PORT: case PCI_EXP_TYPE_UPSTREAM: case PCI_EXP_TYPE_DOWNSTREAM: printk(BIOS_DEBUG, "%s subordinate bus PCI Express\n", - dev_path(dev)); + dev_path(dev)); return &default_pciexp_ops_bus; case PCI_EXP_TYPE_PCI_BRIDGE: - printk(BIOS_DEBUG, "%s subordinate PCI\n", dev_path(dev)); + printk(BIOS_DEBUG, "%s subordinate PCI\n", + dev_path(dev)); return &default_pci_ops_bus; default: break; @@ -768,8 +796,10 @@ static struct device_operations *get_pci_bridge_ops(device_t dev) } /** - * Set up PCI device operation. Check if it already has a driver. If not, use - * find_device_operations, or set to a default based on type. + * Set up PCI device operation. + * + * Check if it already has a driver. If not, use find_device_operations(), + * or set to a default based on type. * * @param dev Pointer to the device whose pci_ops you want to set. * @see pci_drivers @@ -777,11 +807,12 @@ static struct device_operations *get_pci_bridge_ops(device_t dev) static void set_pci_ops(struct device *dev) { struct pci_driver *driver; - if (dev->ops) { + + if (dev->ops) return; - } - /* Look through the list of setup drivers and find one for + /* + * Look through the list of setup drivers and find one for * this PCI device. */ for (driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) { @@ -789,16 +820,15 @@ static void set_pci_ops(struct device *dev) (driver->device == dev->device)) { dev->ops = (struct device_operations *)driver->ops; printk(BIOS_SPEW, "%s [%04x/%04x] %sops\n", - dev_path(dev), - driver->vendor, driver->device, - (driver->ops->scan_bus ? "bus " : "")); + dev_path(dev), driver->vendor, driver->device, + (driver->ops->scan_bus ? "bus " : "")); return; } } - /* If I don't have a specific driver use the default operations */ - switch (dev->hdr_type & 0x7f) { /* header type */ - case PCI_HEADER_TYPE_NORMAL: /* standard header */ + /* If I don't have a specific driver use the default operations. */ + switch (dev->hdr_type & 0x7f) { /* Header type */ + case PCI_HEADER_TYPE_NORMAL: if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) goto bad; dev->ops = &default_pci_ops_dev; @@ -813,21 +843,19 @@ static void set_pci_ops(struct device *dev) dev->ops = &default_cardbus_ops_bus; break; #endif - default: - bad: +default: +bad: if (dev->enabled) { - printk(BIOS_ERR, "%s [%04x/%04x/%06x] has unknown header " - "type %02x, ignoring.\n", - dev_path(dev), - dev->vendor, dev->device, - dev->class >> 8, dev->hdr_type); + printk(BIOS_ERR, "%s [%04x/%04x/%06x] has unknown " + "header type %02x, ignoring.\n", dev_path(dev), + dev->vendor, dev->device, + dev->class >> 8, dev->hdr_type); } } - return; } /** - * @brief See if we have already allocated a device structure for a given devfn. + * See if we have already allocated a device structure for a given devfn. * * Given a linked list of PCI device structures and a devfn number, find the * device structure correspond to the devfn, if present. This function also @@ -835,18 +863,18 @@ static void set_pci_ops(struct device *dev) * * @param list The device structure list. * @param devfn A device/function number. - * * @return Pointer to the device structure found or NULL if we have not * allocated a device for this devfn yet. */ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) { struct device *dev; + dev = 0; for (; *list; list = &(*list)->sibling) { if ((*list)->path.type != DEVICE_PATH_PCI) { - printk(BIOS_ERR, "child %s not a pci device\n", - dev_path(*list)); + printk(BIOS_ERR, "child %s not a PCI device\n", + dev_path(*list)); continue; } if ((*list)->path.pci.devfn == devfn) { @@ -858,41 +886,41 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) } } - /* Just like alloc_dev() add the device to the list of devices on the + /* + * Just like alloc_dev() add the device to the list of devices on the * bus. When the list of devices was formed we removed all of the * parents children, and now we are interleaving static and dynamic * devices in order on the bus. */ if (dev) { struct device *child; + /* Find the last child of our parent. */ - for (child = dev->bus->children; child && child->sibling;) { + for (child = dev->bus->children; child && child->sibling;) child = child->sibling; - } + /* Place the device on the list of children of its parent. */ - if (child) { + if (child) child->sibling = dev; - } else { + else dev->bus->children = dev; - } } return dev; } /** - * @brief Scan a PCI bus. + * Scan a PCI bus. * * Determine the existence of a given PCI device. Allocate a new struct device * if dev==NULL was passed in and the device exists in hardware. * - * @param bus pointer to the bus structure - * @param devfn to look at - * - * @return The device structure for hte device (if found) - * or the NULL if no device is found. + * @param dev Pointer to the dev structure. + * @param bus Pointer to the bus structure. + * @param devfn A device/function number to look at. + * @return The device structure for the device (if found), NULL otherwise. */ -device_t pci_probe_dev(device_t dev, struct bus * bus, unsigned devfn) +device_t pci_probe_dev(device_t dev, struct bus *bus, unsigned devfn) { u32 id, class; u8 hdr_type; @@ -900,25 +928,29 @@ device_t pci_probe_dev(device_t dev, struct bus * bus, unsigned devfn) /* Detect if a device is present. */ if (!dev) { struct device dummy; + dummy.bus = bus; dummy.path.type = DEVICE_PATH_PCI; dummy.path.pci.devfn = devfn; + id = pci_read_config32(&dummy, PCI_VENDOR_ID); - /* Have we found something? - * Some broken boards return 0 if a slot is empty, but - * the expected answer is 0xffffffff + /* + * Have we found something? Some broken boards return 0 if a + * slot is empty, but the expected answer is 0xffffffff. */ - if (id == 0xffffffff) { + if (id == 0xffffffff) return NULL; - } + if ((id == 0x00000000) || (id == 0x0000ffff) || (id == 0xffff0000)) { - printk(BIOS_SPEW, "%s, bad id 0x%x\n", dev_path(&dummy), id); + printk(BIOS_SPEW, "%s, bad id 0x%x\n", + dev_path(&dummy), id); return NULL; } dev = alloc_dev(bus, &dummy.path); } else { - /* Enable/disable the device. Once we have found the device- + /* + * Enable/disable the device. Once we have found the device- * specific operations this operations we will disable the * device with those as well. * @@ -929,13 +961,14 @@ device_t pci_probe_dev(device_t dev, struct bus * bus, unsigned devfn) * it may be absent and enable_dev() must cope. */ /* Run the magic enable sequence for the device. */ - if (dev->chip_ops && dev->chip_ops->enable_dev) { + if (dev->chip_ops && dev->chip_ops->enable_dev) dev->chip_ops->enable_dev(dev); - } + /* Now read the vendor and device ID. */ id = pci_read_config32(dev, PCI_VENDOR_ID); - /* If the device does not have a PCI ID disable it. Possibly + /* + * If the device does not have a PCI ID disable it. Possibly * this is because we have already disabled the device. But * this also handles optional devices that may not always * show up. @@ -944,13 +977,14 @@ device_t pci_probe_dev(device_t dev, struct bus * bus, unsigned devfn) if ((id == 0xffffffff) || (id == 0x00000000) || (id == 0x0000ffff) || (id == 0xffff0000)) { if (dev->enabled) { - printk(BIOS_INFO, "PCI: Static device %s not found, disabling it.\n", - dev_path(dev)); + printk(BIOS_INFO, "PCI: Static device %s not " + "found, disabling it.\n", dev_path(dev)); dev->enabled = 0; } return dev; } } + /* Read the rest of the PCI configuration information. */ hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); class = pci_read_config32(dev, PCI_CLASS_REVISION); @@ -964,32 +998,30 @@ device_t pci_probe_dev(device_t dev, struct bus * bus, unsigned devfn) dev->class = class >> 8; /* Architectural/System devices always need to be bus masters. */ - if ((dev->class >> 16) == PCI_BASE_CLASS_SYSTEM) { + if ((dev->class >> 16) == PCI_BASE_CLASS_SYSTEM) dev->command |= PCI_COMMAND_MASTER; - } - /* Look at the vendor and device ID, or at least the header type and + + /* + * Look at the vendor and device ID, or at least the header type and * class and figure out which set of configuration methods to use. * Unless we already have some PCI ops. */ set_pci_ops(dev); /* Now run the magic enable/disable sequence for the device. */ - if (dev->ops && dev->ops->enable) { + if (dev->ops && dev->ops->enable) dev->ops->enable(dev); - } /* Display the device. */ - printk(BIOS_DEBUG, "%s [%04x/%04x] %s%s\n", - dev_path(dev), - dev->vendor, dev->device, - dev->enabled ? "enabled" : "disabled", - dev->ops ? "" : " No operations"); + printk(BIOS_DEBUG, "%s [%04x/%04x] %s%s\n", dev_path(dev), + dev->vendor, dev->device, dev->enabled ? "enabled" : "disabled", + dev->ops ? "" : " No operations"); return dev; } /** - * @brief Scan a PCI bus. + * Scan a PCI bus. * * Determine the existence of devices and bridges on a PCI bus. If there are * bridges on the bus, recursively scan the buses behind the bridges. @@ -997,16 +1029,14 @@ device_t pci_probe_dev(device_t dev, struct bus * bus, unsigned devfn) * This function is the default scan_bus() method for the root device * 'dev_root'. * - * @param bus pointer to the bus structure - * @param min_devfn minimum devfn to look at in the scan usually 0x00 - * @param max_devfn maximum devfn to look at in the scan usually 0xff - * @param max current bus number - * - * @return The maximum bus number found, after scanning all subordinate busses + * @param bus Pointer to the bus structure. + * @param min_devfn Minimum devfn to look at in the scan, usually 0x00. + * @param max_devfn Maximum devfn to look at in the scan, usually 0xff. + * @param max Current bus number. + * @return The maximum bus number found, after scanning all subordinate busses. */ -unsigned int pci_scan_bus(struct bus *bus, - unsigned min_devfn, unsigned max_devfn, - unsigned int max) +unsigned int pci_scan_bus(struct bus *bus, unsigned min_devfn, + unsigned max_devfn, unsigned int max) { unsigned int devfn; struct device *old_devices; @@ -1014,59 +1044,77 @@ unsigned int pci_scan_bus(struct bus *bus, #if CONFIG_PCI_BUS_SEGN_BITS printk(BIOS_DEBUG, "PCI: pci_scan_bus for bus %04x:%02x\n", - bus->secondary >> 8, bus->secondary & 0xff); + bus->secondary >> 8, bus->secondary & 0xff); #else printk(BIOS_DEBUG, "PCI: pci_scan_bus for bus %02x\n", bus->secondary); #endif + /* Maximum sane devfn is 0xFF. */ + if (max_devfn > 0xff) { + printk(BIOS_ERR, "PCI: pci_scan_bus limits devfn %x - " + "devfn %x\n", min_devfn, max_devfn); + printk(BIOS_ERR, "PCI: pci_scan_bus upper limit too big. " + "Using 0xff.\n"); + max_devfn=0x08; + } + old_devices = bus->children; bus->children = NULL; post_code(0x24); - /* Probe all devices/functions on this bus with some optimization for + + /* + * Probe all devices/functions on this bus with some optimization for * non-existence and single function devices. */ for (devfn = min_devfn; devfn <= max_devfn; devfn++) { struct device *dev; - /* First thing setup the device structure */ + /* First thing setup the device structure. */ + printk(BIOS_INFO, "%s: before pci_scan_get_dev! devfn: %d\n", __func__, devfn); dev = pci_scan_get_dev(&old_devices, devfn); + printk(BIOS_INFO, "%s: after pci_scan_get_dev!\n", __func__); /* See if a device is present and setup the device structure. */ + printk(BIOS_INFO, "%s: before pci_probe_dev!\n", __func__); dev = pci_probe_dev(dev, bus, devfn); + printk(BIOS_INFO, "%s: after pci_probe_dev!\n", __func__); - /* If this is not a multi function device, or the device is + /* + * If this is not a multi function device, or the device is * not present don't waste time probing another function. * Skip to next device. */ - if ((PCI_FUNC(devfn) == 0x00) && - (!dev + if ((PCI_FUNC(devfn) == 0x00) && (!dev || (dev->enabled && ((dev->hdr_type & 0x80) != 0x80)))) { devfn += 0x07; } } + post_code(0x25); - /* Warn if any leftover static devices are are found. - * There's probably a problem in the Config.lb. + /* + * Warn if any leftover static devices are are found. + * There's probably a problem in devicetree.cb. */ if (old_devices) { device_t left; printk(BIOS_WARNING, "PCI: Left over static devices:\n"); - for (left = old_devices; left; left = left->sibling) { + for (left = old_devices; left; left = left->sibling) printk(BIOS_WARNING, "%s\n", dev_path(left)); - } - printk(BIOS_WARNING, "PCI: Check your mainboard Config.lb.\n"); + + printk(BIOS_WARNING, "PCI: Check your devicetree.cb.\n"); } - /* For all children that implement scan_bus() (i.e. bridges) + /* + * For all children that implement scan_bus() (i.e. bridges) * scan the bus behind that child. */ - for (child = bus->children; child; child = child->sibling) { + for (child = bus->children; child; child = child->sibling) max = scan_bus(child, max); - } - /* We've scanned the bus and so we know all about what's on the other + /* + * We've scanned the bus and so we know all about what's on the other * side of any bridges that may be on this bus plus any devices. * Return how far we've got finding sub-buses. */ @@ -1076,7 +1124,7 @@ unsigned int pci_scan_bus(struct bus *bus, } /** - * @brief Scan a PCI bridge and the buses behind the bridge. + * Scan a PCI bridge and the buses behind the bridge. * * Determine the existence of buses behind the bridge. Set up the bridge * according to the result of the scan. @@ -1085,6 +1133,7 @@ unsigned int pci_scan_bus(struct bus *bus, * * @param dev Pointer to the bridge device. * @param max The highest bus number assigned up to now. + * @param do_scan_bus TODO * @return The maximum bus number found, after scanning all subordinate buses. */ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, @@ -1111,7 +1160,8 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, bus = dev->link_list; - /* Set up the primary, secondary and subordinate bus numbers. We have + /* + * Set up the primary, secondary and subordinate bus numbers. We have * no idea how many buses are behind this bridge yet, so we set the * subordinate bus number to 0xff for the moment. */ @@ -1123,12 +1173,14 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, pci_write_config16(dev, PCI_COMMAND, 0x0000); pci_write_config16(dev, PCI_STATUS, 0xffff); - /* Read the existing primary/secondary/subordinate bus + /* + * Read the existing primary/secondary/subordinate bus * number configuration. */ buses = pci_read_config32(dev, PCI_PRIMARY_BUS); - /* Configure the bus numbers for this bridge: the configuration + /* + * Configure the bus numbers for this bridge: the configuration * transactions will not be propagated by the bridge if it is not * correctly configured. */ @@ -1138,12 +1190,11 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, ((unsigned int)(bus->subordinate) << 16)); pci_write_config32(dev, PCI_PRIMARY_BUS, buses); - /* Now we can scan all subordinate buses - * i.e. the bus behind the bridge. - */ + /* Now we can scan all subordinate buses (those behind the bridge). */ max = do_scan_bus(bus, 0x00, 0xff, max); - /* We know the number of buses behind this bridge. Set the subordinate + /* + * We know the number of buses behind this bridge. Set the subordinate * bus number to its real value. */ bus->subordinate = max; @@ -1156,7 +1207,7 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, } /** - * @brief Scan a PCI bridge and the buses behind the bridge. + * Scan a PCI bridge and the buses behind the bridge. * * Determine the existence of buses behind the bridge. Set up the bridge * according to the result of the scan. @@ -1173,14 +1224,13 @@ unsigned int pci_scan_bridge(struct device *dev, unsigned int max) } /** - * @brief Scan a PCI domain. + * Scan a PCI domain. * * This function is the default scan_bus() method for PCI domains. * - * @param dev pointer to the domain - * @param max the highest bus number assgined up to now - * - * @return The maximum bus number found, after scanning all subordinate busses + * @param dev Pointer to the domain. + * @param max The highest bus number assigned up to now. + * @return The maximum bus number found, after scanning all subordinate busses. */ unsigned int pci_domain_scan_bus(device_t dev, unsigned int max) { @@ -1190,31 +1240,28 @@ unsigned int pci_domain_scan_bus(device_t dev, unsigned int max) #if CONFIG_PC80_SYSTEM == 1 /** - * - * @brief Assign IRQ numbers + * Assign IRQ numbers. * * This function assigns IRQs for all functions contained within the indicated - * device address. If the device does not exist or does not require interrupts + * device address. If the device does not exist or does not require interrupts * then this function has no effect. * * This function should be called for each PCI slot in your system. * - * @param bus - * @param slot - * @param pIntAtoD is an array of IRQ #s that are assigned to PINTA through - * PINTD of this slot. The particular irq #s that are passed in - * depend on the routing inside your southbridge and on your - * motherboard. + * @param bus Pointer to the bus structure. + * @param slot TODO + * @param pIntAtoD An array of IRQ #s that are assigned to PINTA through PINTD + * of this slot. The particular IRQ #s that are passed in depend on the + * routing inside your southbridge and on your board. */ void pci_assign_irqs(unsigned bus, unsigned slot, - const unsigned char pIntAtoD[4]) + const unsigned char pIntAtoD[4]) { unsigned int funct; device_t pdev; - u8 line; - u8 irq; + u8 line, irq; - /* Each slot may contain up to eight functions */ + /* Each slot may contain up to eight functions. */ for (funct = 0; funct < 8; funct++) { pdev = dev_find_slot(bus, (slot << 3) + funct); @@ -1223,26 +1270,28 @@ void pci_assign_irqs(unsigned bus, unsigned slot, line = pci_read_config8(pdev, PCI_INTERRUPT_PIN); - // PCI spec says all values except 1..4 are reserved. + /* PCI spec says all values except 1..4 are reserved. */ if ((line < 1) || (line > 4)) continue; irq = pIntAtoD[line - 1]; printk(BIOS_DEBUG, "Assigning IRQ %d to %d:%x.%d\n", - irq, bus, slot, funct); + irq, bus, slot, funct); pci_write_config8(pdev, PCI_INTERRUPT_LINE, - pIntAtoD[line - 1]); + pIntAtoD[line - 1]); #ifdef PARANOID_IRQ_ASSIGNMENTS irq = pci_read_config8(pdev, PCI_INTERRUPT_LINE); printk(BIOS_DEBUG, " Readback = %d\n", irq); #endif - // Change to level triggered - i8259_configure_irq_trigger(pIntAtoD[line - 1], IRQ_LEVEL_TRIGGERED); +#if CONFIG_PC80_SYSTEM == 1 + /* Change to level triggered. */ + i8259_configure_irq_trigger(pIntAtoD[line - 1], + IRQ_LEVEL_TRIGGERED); +#endif } } #endif -