diff options
-rw-r--r-- | src/devices/device.c | 76 | ||||
-rw-r--r-- | src/devices/pci_device.c | 19 | ||||
-rw-r--r-- | src/devices/root_device.c | 81 | ||||
-rw-r--r-- | src/include/device/device.h | 6 | ||||
-rw-r--r-- | src/include/device/pci.h | 1 |
5 files changed, 109 insertions, 74 deletions
diff --git a/src/devices/device.c b/src/devices/device.c index 033f41d2ca..87e627d52c 100644 --- a/src/devices/device.c +++ b/src/devices/device.c @@ -376,13 +376,14 @@ static void allocate_vga_resource(void) struct bus *bus; bus = 0; vga = 0; - for(dev = all_devices; dev; dev = dev->next) { + for (dev = all_devices; dev; dev = dev->next) { if (((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && - ((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER)) - { + ((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER)) { if (!vga) { printk_debug("Allocating VGA resource %s\n", - dev_path(dev)); + dev_path(dev)); + printk_debug("parent of the vga device %s\n", + dev_path(dev->bus->dev)); vga = dev; } if (vga == dev) { @@ -398,19 +399,28 @@ static void allocate_vga_resource(void) bus = vga->bus; } /* Now walk up the bridges setting the VGA enable */ - while(bus) { + while (bus) { + printk_info("Enabling VGA forward on bus connect to %s\n", + dev_path(bus->dev)); bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA; bus = (bus == bus->dev->bus)? 0 : bus->dev->bus; } } -/** Assign the computed resources to the bridges and devices on the bus. - * Recurse to any bridges found on this bus first. Then do the devices - * on this bus. - * +/** + * @brief Assign the computed resources to the devices on the bus. + * * @param bus Pointer to the structure for this bus - */ + * + * Use the device specific set_resources method to store the computed + * resources to hardware. For bridge devices, the set_resources() method + * has to recurse into every down stream buses. + * + * Mutual recursion: + * assign_resources() -> device_operation::set_resources() + * device_operation::set_resources() -> assign_resources() + */ void assign_resources(struct bus *bus) { struct device *curdev; @@ -418,7 +428,7 @@ void assign_resources(struct bus *bus) printk_spew("%s assign_resources, bus %d link: %d\n", dev_path(bus->dev), bus->secondary, bus->link); - for(curdev = bus->children; curdev; curdev = curdev->sibling) { + for (curdev = bus->children; curdev; curdev = curdev->sibling) { if (!curdev->enabled || !curdev->resources) { continue; } @@ -443,10 +453,13 @@ void assign_resources(struct bus *bus) * * The parent's resources should be enabled first to avoid having enabling * order problem. This is done by calling the parent's enable_resources() - * method and let that method to call it's children's enable_resoruces() via - * enable_childrens_resources(). + * method and let that method to call it's children's enable_resoruces() + * method via the (global) enable_childrens_resources(). * * Indirect mutual recursion: + * enable_resources() -> device_operations::enable_resource() + * device_operations::enable_resource() -> enable_children_resources() + * enable_children_resources() -> enable_resources() */ void enable_resources(struct device *dev) { @@ -461,16 +474,25 @@ void enable_resources(struct device *dev) } /** - * @brief Determine the existence of dynamic devices and construct dynamic + * @brief Determine the existence of devices and extend the device tree. + * + * Most of the devices in the system are listed in the mainboard Config.lb + * file. The device structures for these devices are generated at compile + * time by the config tool and are organized into the device tree. This + * function determines if the devices created at compile time actually exist + * in the physical system. + * + * For devices in the physical system but not listed in the Config.lb file, + * the device structures have to be created at run time and attached to the * device tree. * - * Start from the root device 'dev_root', scan the buses in the system - * recursively, build the dynamic device tree according to the result - * of the probe. + * This function starts from the root device 'dev_root', scan the buses in + * the system recursively, modify the device tree according to the result of + * the probe. * * This function has no idea how to scan and probe buses and devices at all. * It depends on the bus/device specific scan_bus() method to do it. The - * scan_bus() function also has to create the device structure and attach + * scan_bus() method also has to create the device structure and attach * it to the device tree. */ void dev_enumerate(void) @@ -490,12 +512,13 @@ void dev_enumerate(void) printk_info("done\n"); } - /** * @brief Configure devices on the devices tree. * - * Starting at the root of the dynamic device tree, travel recursively, - * and compute resources needed by each device and allocate them. + * Starting at the root of the device tree, travel it recursively in two + * passes. In the first pass, we compute and allocate resources (ranges) + * requried by each device. In the second pass, the resources ranges are + * relocated to their final position and stored to the hardware. * * I/O resources start at DEVICE_IO_START and grow upward. MEM resources start * at DEVICE_MEM_START and grow downward. @@ -519,7 +542,10 @@ void dev_configure(void) printk_err("dev_root missing set_resources\n"); return; } + + printk_info("Reading resources...\n"); root->ops->read_resources(root); + printk_info("Done\n"); /* Get the resources */ io = &root->resource[0]; @@ -539,8 +565,9 @@ void dev_configure(void) allocate_vga_resource(); /* Store the computed resource allocations into device registers ... */ + printk_info("Setting resources...\n"); root->ops->set_resources(root); - + printk_info("Done\n"); #if 0 mem->flags |= IORESOURCE_STORED; report_resource_stored(root, mem, ""); @@ -569,14 +596,15 @@ void dev_enable(void) * @brief Initialize all devices in the global device list. * * Starting at the first device on the global device link list, - * walk the list and call a driver to do device specific setup. + * walk the list and call the device's init() method to do deivce + * specific setup. */ void dev_initialize(void) { struct device *dev; printk_info("Initializing devices...\n"); - for(dev = all_devices; dev; dev = dev->next) { + for (dev = all_devices; dev; dev = dev->next) { if (dev->enabled && !dev->initialized && dev->ops && dev->ops->init) { diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c index bd5e2775fe..a32c3a675f 100644 --- a/src/devices/pci_device.c +++ b/src/devices/pci_device.c @@ -569,9 +569,9 @@ static void set_pci_ops(struct device *dev) /* Look through the list of setup drivers and find one for * this pci device */ - for(driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) { + for (driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) { if ((driver->vendor == dev->vendor) && - (driver->device == dev->device)) + (driver->device == dev->device)) { dev->ops = driver->ops; printk_debug("%s [%04x/%04x] %sops\n", @@ -665,9 +665,6 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) * 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. * - * 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 @@ -709,8 +706,8 @@ unsigned int pci_scan_bus(struct bus *bus, dummy.path.u.pci.devfn = devfn; id = pci_read_config32(&dummy, PCI_VENDOR_ID); /* some broken boards return 0 if a slot is empty: */ - if ( (id == 0xffffffff) || (id == 0x00000000) || - (id == 0x0000ffff) || (id == 0xffff0000)) + if ((id == 0xffffffff) || (id == 0x00000000) || + (id == 0x0000ffff) || (id == 0xffff0000)) { printk_spew("PCI: devfn 0x%x, bad id 0x%x\n", devfn, id); if (PCI_FUNC(devfn) == 0x00) { @@ -753,7 +750,7 @@ unsigned int pci_scan_bus(struct bus *bus, * that may not always show up. */ if (id == 0xffffffff || id == 0x00000000 || - id == 0x0000ffff || id == 0xffff0000) + id == 0x0000ffff || id == 0xffff0000) { if (dev->enabled) { printk_info("Disabling static device: %s\n", @@ -816,10 +813,10 @@ unsigned int pci_scan_bus(struct bus *bus, /* 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) { if (!child->enabled || - !child->ops || - !child->ops->scan_bus) + !child->ops || + !child->ops->scan_bus) { continue; } diff --git a/src/devices/root_device.c b/src/devices/root_device.c index 897a5a3bbf..a02fe7a060 100644 --- a/src/devices/root_device.c +++ b/src/devices/root_device.c @@ -35,7 +35,8 @@ void root_dev_read_resources(device_t root) } /** - * Write the resources for the root device, + * @brief Write the resources for the root device + * * and every device under it which are all of the devices. * @param root Pointer to the device structure for the system root device */ @@ -44,10 +45,10 @@ void root_dev_set_resources(device_t root) struct bus *bus; bus = &root->link[0]; - compute_allocate_resource(bus, - &root->resource[0], IORESOURCE_IO, IORESOURCE_IO); - compute_allocate_resource(bus, - &root->resource[1], IORESOURCE_MEM, IORESOURCE_MEM); + compute_allocate_resource(bus, &root->resource[0], + IORESOURCE_IO, IORESOURCE_IO); + compute_allocate_resource(bus, &root->resource[1], + IORESOURCE_MEM, IORESOURCE_MEM); assign_resources(bus); } @@ -56,26 +57,32 @@ void root_dev_set_resources(device_t root) * * The enumeration of certain buses is purely static. The existence of * devices on those buses can be completely determined at compile time - * by the config file. Typical expamles are the 'PNP' devices on a legacy - * ISA/LPC bus. There is no need of probing of any kind, the only thing - * we have to do is to walk through the bus and enable or disable devices - * as indicated in the config file. + * and is specified in the config file. Typical exapmles are the 'PNP' + * devices on a legacy ISA/LPC bus. There is no need of probing of any + * kind, the only thing we have to do is to walk through the bus and + * enable or disable devices as indicated in the config file. * - * This function is the default scan_bus() method for LPC bridges. + * On the other hand, some devices are virtual and their existence is + * artificial. They can not be probed at run time. One example is the + * debug device. Those virtual devices have to be listed in the config + * file under some static bus in order to be enumerated at run time. * - * @param root Pointer to the device structure for the system root device - * @param max Maximum bus number allowed in the system. - * @return Largest bus number used. + * This function is the default scan_bus() method for the root device and + * LPC bridges. + * + * @param root Pointer to the root device which the static buses are attached + * @param max Maximum bus number currently used before scanning. + * @return Largest bus number used after scanning. */ -unsigned int scan_static_bus(device_t bus, unsigned int max) +unsigned int scan_static_bus(device_t root, unsigned int max) { device_t child; unsigned link; - - printk_spew("%s for %s\n", __func__, dev_path(bus)); - for(link = 0; link < bus->links; link++) { - for(child = bus->link[link].children; child; child = child->sibling) { + printk_spew("%s for %s\n", __func__, dev_path(root)); + + for (link = 0; link < root->links; link++) { + for (child = root->link[link].children; child; child = child->sibling) { if (child->chip_ops && child->chip_ops->enable_dev) { child->chip_ops->enable_dev(child); } @@ -87,8 +94,8 @@ unsigned int scan_static_bus(device_t bus, unsigned int max) child->enabled?"enabled": "disabled"); } } - for(link = 0; link < bus->links; link++) { - for(child = bus->link[link].children; child; child = child->sibling) { + for (link = 0; link < root->links; link++) { + for (child = root->link[link].children; child; child = child->sibling) { if (!child->ops || !child->ops->scan_bus) continue; printk_spew("%s scanning...\n", dev_path(child)); @@ -96,7 +103,7 @@ unsigned int scan_static_bus(device_t bus, unsigned int max) } } - printk_spew("%s done\n", __func__); + printk_spew("%s for %s done\n", __func__, dev_path(root)); return max; } @@ -106,17 +113,20 @@ unsigned int scan_static_bus(device_t bus, unsigned int max) * * @param dev the device whos children's resources are to be enabled * - * This function is call by the enable_resource() indirectly via the - * enable_resources() method of devices. + * This function is call by the global enable_resources() indirectly via the + * device_operation::enable_resources() method of devices. * * Indirect mutual recursion: + * enable_childrens_resources() -> enable_resources() + * enable_resources() -> device_operation::enable_resources() + * device_operation::enable_resources() -> enable_children_resources() */ void enable_childrens_resources(device_t dev) { unsigned link; - for(link = 0; link < dev->links; link++) { + for (link = 0; link < dev->links; link++) { device_t child; - for(child = dev->link[link].children; child; child = child->sibling) { + for (child = dev->link[link].children; child; child = child->sibling) { enable_resources(child); } } @@ -131,12 +141,9 @@ void root_dev_enable_resources(device_t dev) * @brief Scan root bus for generic systems * * @param root The root device structure - * @param max The current bus number scanned so fat, usually 0x00 + * @param max The current bus number scanned so far, usually 0x00 * - * This function is the default scan_bus() method of the dynamic root device. - * The bus heirachy is rooted at the host/northbridge. The northbridge of a - * generic PCI bus system is at Bus 0, Dev 0, Fun 0 so we scan the whole PCI - * buses from there. + * This function is the default scan_bus() method of the root device. */ unsigned int root_dev_scan_bus(device_t root, unsigned int max) { @@ -150,11 +157,9 @@ void root_dev_init(device_t root) /** * @brief Default device operation for root device * - * This is the default device operation for root devices in PCI based systems. - * These operations should be fully usable as is. However the - * chip_operations::dev_enable of a motherboard can override this if you - * want non-default behavior. Currently src/mainboard/arima/hdama/mainbaord.c - * does this for debugging purposes. + * This is the default device operation for root devices. These operations + * should be fully usable as is. However the chip_operations::enable_dev() + * of a motherboard can override this if you want non-default behavior. */ struct device_operations default_dev_ops_root = { .read_resources = root_dev_read_resources, @@ -165,9 +170,9 @@ struct device_operations default_dev_ops_root = { }; /** - * @brief The root of dynamic device tree. + * @brief The root of device tree. * - * This is the root of the dynamic device tree. A PCI tree always has - * one bus, bus 0. Bus 0 contains devices and bridges. + * This is the root of the device tree. The device tree is defined in the + * static.c file and is generated by config tool during compile time. */ extern struct device dev_root; diff --git a/src/include/device/device.h b/src/include/device/device.h index db91fcc1ef..167a518f2a 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -57,7 +57,8 @@ struct bus { */ struct device { - struct bus * bus; /* bus this device is on */ + struct bus * bus; /* bus this device is on, for bridge + * devices, it is the up stream bus */ device_t sibling; /* next device on this bus */ device_t next; /* chain of all devices */ @@ -79,7 +80,10 @@ struct device { struct resource resource[MAX_RESOURCES]; unsigned int resources; + /* link are (down sream) buses attached to the device, usually a leaf + * device with no child have 0 bus attached and a bridge has 1 bus */ struct bus link[MAX_LINKS]; + /* number of buses attached to the device */ unsigned int links; unsigned long rom_address; diff --git a/src/include/device/pci.h b/src/include/device/pci.h index 2c9797fa6c..0ee31f1cb9 100644 --- a/src/include/device/pci.h +++ b/src/include/device/pci.h @@ -23,6 +23,7 @@ /* Common pci operations without a standard interface */ struct pci_operations { + /* set the Subsystem IDs for the PCI device */ void (*set_subsystem)(device_t dev, unsigned vendor, unsigned device); }; |