diff options
Diffstat (limited to 'src/devices')
-rw-r--r-- | src/devices/chip.c | 24 | ||||
-rw-r--r-- | src/devices/device.c | 103 | ||||
-rw-r--r-- | src/devices/device_util.c | 187 | ||||
-rw-r--r-- | src/devices/hypertransport.c | 20 | ||||
-rw-r--r-- | src/devices/pci_device.c | 541 | ||||
-rw-r--r-- | src/devices/pnp_device.c | 23 | ||||
-rw-r--r-- | src/devices/root_device.c | 68 |
7 files changed, 637 insertions, 329 deletions
diff --git a/src/devices/chip.c b/src/devices/chip.c index 8315fab674..6882a4b797 100644 --- a/src/devices/chip.c +++ b/src/devices/chip.c @@ -112,8 +112,9 @@ void chip_enumerate(struct chip *chip) struct chip_resource *res, *res_limit; printk_spew("path (%p) %s %s", dev, dev_path(dev), identical_paths?"identical":""); - printk_spew(" parent: (%p) %s\n", - dev->bus->dev, dev_path(dev->bus->dev)); + printk_spew(" parent: (%p):%d %s\n", + dev->bus->dev, dev->bus->link, + dev_path(dev->bus->dev)); dev->chip = chip; dev->enabled = chip->path[i].enabled; dev->links = link + 1; @@ -127,7 +128,7 @@ void chip_enumerate(struct chip *chip) for(; res < res_limit; res++) { if (res->flags) { struct resource *resource; - resource = get_resource(dev, res->index); + resource = new_resource(dev, res->index); resource->flags = res->flags | IORESOURCE_FIXED | IORESOURCE_ASSIGNED; resource->base = res->base; } @@ -208,7 +209,24 @@ static void enumerate_static_device_chain(struct chip *root) */ void enumerate_static_devices(void) { + struct chip *child; + int i; printk_info("Enumerating static devices...\n"); static_root.dev = &dev_root; + dev_root.links = MAX_LINKS; + for(i = 0; i < MAX_LINKS; i++) { + dev_root.link[i].link = i; + dev_root.link[i].dev = &dev_root; + for(child = static_root.children; child; child = child->next) { + if (!child->bus && child->link == i) { + child->bus = &dev_root.link[i]; + } + } + } + for(child = static_root.children; child; child = child->next) { + if (!child->bus) { + child->bus = &dev_root.link[0]; + } + } enumerate_static_device_chain(&static_root); } diff --git a/src/devices/device.c b/src/devices/device.c index 4b7d8728fd..7ef65e2fe4 100644 --- a/src/devices/device.c +++ b/src/devices/device.c @@ -22,6 +22,7 @@ #include <device/pci_ids.h> #include <stdlib.h> #include <string.h> +#include <smp/spinlock.h> /** Linked list of ALL devices */ struct device *all_devices = &dev_root; @@ -30,7 +31,7 @@ static struct device **last_dev_p = &dev_root.next; /** The upper limit of MEM resource of the devices. * Reserve 20M for the system */ -#define DEVICE_MEM_HIGH 0xFEC00000UL +#define DEVICE_MEM_HIGH 0xFEBFFFFFUL /** The lower limit of IO resource of the devices. * Reserve 4k for ISA/Legacy devices */ #define DEVICE_IO_START 0x1000 @@ -53,6 +54,7 @@ device_t alloc_dev(struct bus *parent, struct device_path *path) device_t dev, child; int link; + spin_lock(&dev_lock); /* Find the last child of our parent */ for(child = parent->children; child && child->sibling; ) { child = child->sibling; @@ -64,17 +66,15 @@ device_t alloc_dev(struct bus *parent, struct device_path *path) memset(dev, 0, sizeof(*dev)); memcpy(&dev->path, path, sizeof(*path)); - /* Append a new device to the global device list. - * The list is used to find devices once everything is set up. - */ - *last_dev_p = dev; - last_dev_p = &dev->next; /* Initialize the back pointers in the link fields */ for(link = 0; link < MAX_LINKS; link++) { dev->link[link].dev = dev; dev->link[link].link = link; } + + /* By default devices are enabled */ + dev->enabled = 1; /* Add the new device to the list of children of the bus. */ dev->bus = parent; @@ -83,9 +83,14 @@ device_t alloc_dev(struct bus *parent, struct device_path *path) } else { parent->children = dev; } - /* If we don't have any other information about a device enable it */ - dev->enabled = 1; + /* Append a new device to the global device list. + * The list is used to find devices once everything is set up. + */ + *last_dev_p = dev; + last_dev_p = &dev->next; + + spin_unlock(&dev_lock); return dev; } @@ -269,7 +274,7 @@ void compute_allocate_resource( { struct device *dev; struct resource *resource; - unsigned long base; + resource_t base; unsigned long align, min_align; min_align = 0; base = bridge->base; @@ -302,7 +307,7 @@ void compute_allocate_resource( * compute the addresses. */ while((dev = largest_resource(bus, &resource, type_mask, type))) { - unsigned long size; + resource_t size; /* Do NOT I repeat do not ignore resources which have zero size. * If they need to be ignored dev->read_resources should not even * return them. Some resources must be set even when they have @@ -314,6 +319,15 @@ void compute_allocate_resource( bridge->align = resource->align; } + /* Propogate the resource limit to the bridge register */ + if (bridge->limit > resource->limit) { + bridge->limit = resource->limit; + } + /* Artificially deny limits between DEVICE_MEM_HIGH and 0xffffffff */ + if ((bridge->limit > DEVICE_MEM_HIGH) && (bridge->limit <= 0xffffffff)) { + bridge->limit = DEVICE_MEM_HIGH; + } + /* Make certain we are dealing with a good minimum size */ size = resource->size; align = resource->align; @@ -341,19 +355,20 @@ void compute_allocate_resource( base = 0x3e0; } } - if (((round(base, 1UL << align) + size) -1) <= resource->limit) { + if (((round(base, align) + size) -1) <= resource->limit) { /* base must be aligned to size */ - base = round(base, 1UL << align); + base = round(base, align); resource->base = base; resource->flags |= IORESOURCE_ASSIGNED; resource->flags &= ~IORESOURCE_STORED; base += size; printk_spew( - "%s %02x * [0x%08lx - 0x%08lx] %s\n", + "%s %02x * [0x%08Lx - 0x%08Lx] %s\n", dev_path(dev), resource->index, - resource->base, resource->base + resource->size - 1, + resource->base, + resource->base + resource->size - 1, (resource->flags & IORESOURCE_IO)? "io": (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem"); } @@ -364,10 +379,10 @@ void compute_allocate_resource( * know not to place something else at an address postitively * decoded by the bridge. */ - bridge->size = round(base, 1UL << bridge->gran) - bridge->base; + bridge->size = round(base, bridge->gran) - bridge->base; printk_spew("%s compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d done\n", - dev_path(dev), + dev_path(bus->dev), (bridge->flags & IORESOURCE_IO)? "io": (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", base, bridge->size, bridge->align, bridge->gran); @@ -387,7 +402,8 @@ static void allocate_vga_resource(void) vga = 0; 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)); @@ -423,20 +439,22 @@ void assign_resources(struct bus *bus) { struct device *curdev; - printk_debug("ASSIGN RESOURCES, bus %d\n", bus->secondary); + 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; + } if (!curdev->ops || !curdev->ops->set_resources) { printk_err("%s missing set_resources\n", dev_path(curdev)); continue; } - if (!curdev->enabled) { - continue; - } curdev->ops->set_resources(curdev); } - printk_debug("ASSIGNED RESOURCES, bus %d\n", bus->secondary); + printk_spew("%s assign_resources, bus %d link: %d\n", + dev_path(bus->dev), bus->secondary, bus->link); } /** @@ -456,11 +474,11 @@ void assign_resources(struct bus *bus) */ void enable_resources(struct device *dev) { - if (!dev->ops || !dev->ops->enable_resources) { - printk_err("%s missing enable_resources\n", dev_path(dev)); + if (!dev->enabled) { return; } - if (!dev->enabled) { + if (!dev->ops || !dev->ops->enable_resources) { + printk_err("%s missing enable_resources\n", dev_path(dev)); return; } dev->ops->enable_resources(dev); @@ -493,11 +511,12 @@ 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, - * compute resources needed by each device and allocate them. + * and compute resources needed by each device and allocate them. * * I/O resources start at DEVICE_IO_START and grow upward. MEM resources start * at DEVICE_MEM_START and grow downward. @@ -507,6 +526,7 @@ void dev_enumerate(void) */ void dev_configure(void) { + struct resource *io, *mem; struct device *root; printk_info("Allocating resources...\n"); @@ -522,18 +542,19 @@ void dev_configure(void) } root->ops->read_resources(root); + /* Get the resources */ + io = &root->resource[0]; + mem = &root->resource[1]; /* Make certain the io devices are allocated somewhere safe. */ - root->resource[0].base = DEVICE_IO_START; - root->resource[0].flags |= IORESOURCE_ASSIGNED; - root->resource[0].flags &= ~IORESOURCE_STORED; + io->base = DEVICE_IO_START; + io->flags |= IORESOURCE_ASSIGNED; + io->flags &= ~IORESOURCE_STORED; /* Now reallocate the pci resources memory with the * highest addresses I can manage. */ - root->resource[1].base = - round_down(DEVICE_MEM_HIGH - root->resource[1].size, - 1UL << root->resource[1].align); - root->resource[1].flags |= IORESOURCE_ASSIGNED; - root->resource[1].flags &= ~IORESOURCE_STORED; + mem->base = resource_max(&root->resource[1]); + mem->flags |= IORESOURCE_ASSIGNED; + mem->flags &= ~IORESOURCE_STORED; /* Allocate the VGA I/O resource.. */ allocate_vga_resource(); @@ -541,6 +562,11 @@ void dev_configure(void) /* Store the computed resource allocations into device registers ... */ root->ops->set_resources(root); +#if 0 + mem->flags |= IORESOURCE_STORED; + report_resource_stored(root, mem, ""); +#endif + printk_info("done.\n"); } @@ -571,9 +597,12 @@ void dev_initialize(void) struct device *dev; printk_info("Initializing devices...\n"); - for (dev = all_devices; dev; dev = dev->next) { - if (dev->enabled && dev->ops && dev->ops->init) { + for(dev = all_devices; dev; dev = dev->next) { + if (dev->enabled && !dev->initialized && + dev->ops && dev->ops->init) + { printk_debug("%s init\n", dev_path(dev)); + dev->initialized = 1; dev->ops->init(dev); } } diff --git a/src/devices/device_util.c b/src/devices/device_util.c index f5f8bb4482..7a942b457e 100644 --- a/src/devices/device_util.c +++ b/src/devices/device_util.c @@ -4,23 +4,40 @@ #include <device/pci.h> #include <string.h> - /** - * @brief See if a device structure already exists and if not allocate it + * @brief See if a device structure exists for path * * @param bus The bus to find the device on * @param path The relative path from the bus to the appropriate device * @return pointer to a device structure for the device on bus at path + * or 0/NULL if no device is found */ -device_t alloc_find_dev(struct bus *parent, struct device_path *path) +device_t find_dev_path(struct bus *parent, struct device_path *path) { device_t child; for(child = parent->children; child; child = child->sibling) { if (path_eq(path, &child->path)) { - return child; + break; } } - return alloc_dev(parent, path); + return child; +} + +/** + * @brief See if a device structure already exists and if not allocate it + * + * @param bus The bus to find the device on + * @param path The relative path from the bus to the appropriate device + * @return pointer to a device structure for the device on bus at path + */ +device_t alloc_find_dev(struct bus *parent, struct device_path *path) +{ + device_t child; + child = find_dev_path(parent, path); + if (!child) { + child = alloc_dev(parent, path); + } + return child; } /** @@ -96,6 +113,9 @@ const char *dev_path(device_t dev) case DEVICE_PATH_ROOT: memcpy(buffer, "Root Device", 12); break; + case DEVICE_PATH_DEFAULT_CPU: + memcpy(buffer, "Default CPU", 12); + break; case DEVICE_PATH_PCI: sprintf(buffer, "PCI: %02x:%02x.%01x", dev->bus->secondary, @@ -109,6 +129,10 @@ const char *dev_path(device_t dev) sprintf(buffer, "I2C: %02x", dev->path.u.i2c.device); break; + case DEVICE_PATH_APIC: + sprintf(buffer, "APIC: %02x", + dev->path.u.apic.apic_id); + break; default: printk_err("Unknown device path type: %d\n", dev->path.type); break; @@ -127,6 +151,9 @@ int path_eq(struct device_path *path1, struct device_path *path2) case DEVICE_PATH_ROOT: equal = 1; break; + case DEVICE_PATH_DEFAULT_CPU: + equal = 1; + break; case DEVICE_PATH_PCI: equal = (path1->u.pci.bus == path2->u.pci.bus) && (path1->u.pci.devfn == path2->u.pci.devfn); @@ -138,6 +165,9 @@ int path_eq(struct device_path *path1, struct device_path *path2) case DEVICE_PATH_I2C: equal = (path1->u.i2c.device == path2->u.i2c.device); break; + case DEVICE_PATH_APIC: + equal = (path1->u.apic.apic_id == path2->u.apic.apic_id); + break; default: printk_err("Uknown device type: %d\n", path1->type); break; @@ -168,20 +198,17 @@ void compact_resources(device_t dev) } } + /** - * See if a resource structure already exists for a given index and if - * not allocate one. + * See if a resource structure already exists for a given index * @param dev The device to find the resource on * @param index The index of the resource on the device. + * @return the resource if it already exists */ -struct resource *get_resource(device_t dev, unsigned index) +struct resource *probe_resource(device_t dev, unsigned index) { struct resource *resource; int i; - - /* First move all of the free resources to the end */ - compact_resources(dev); - /* See if there is a resource with the appropriate index */ resource = 0; for(i = 0; i < dev->resources; i++) { @@ -190,6 +217,25 @@ struct resource *get_resource(device_t dev, unsigned index) break; } } + return resource; +} + +/** + * See if a resource structure already exists for a given index and if + * not allocate one. Then initialize the initialize the resource + * to default values. + * @param dev The device to find the resource on + * @param index The index of the resource on the device. + */ +struct resource *new_resource(device_t dev, unsigned index) +{ + struct resource *resource; + + /* First move all of the free resources to the end */ + compact_resources(dev); + + /* See if there is a resource with the appropriate index */ + resource = probe_resource(dev, index); if (!resource) { if (dev->resources == MAX_RESOURCES) { die("MAX_RESOURCES exceeded."); @@ -212,3 +258,120 @@ struct resource *get_resource(device_t dev, unsigned index) return resource; } +/** + * Return an existing resource structure for a given index. + * @param dev The device to find the resource on + * @param index The index of the resource on the device. + */ +struct resource *find_resource(device_t dev, unsigned index) +{ + struct resource *resource; + + /* See if there is a resource with the appropriate index */ + resource = probe_resource(dev, index); + if (!resource) { + printk_emerg("%s missing resource: %02x\n", + dev_path(dev), index); + die(""); + } + return resource; +} + + +/** + * @brief round a number up to the next multiple of gran + * @param val the starting value + * @param gran granularity we are aligning the number to. + * @returns aligned value + */ +static resource_t align_up(resource_t val, unsigned long gran) +{ + resource_t mask; + mask = (1ULL << gran) - 1ULL; + val += mask; + val &= ~mask; + return val; +} + +/** + * @brief round a number up to the previous multiple of gran + * @param val the starting value + * @param gran granularity we are aligning the number to. + * @returns aligned value + */ +static resource_t align_down(resource_t val, unsigned long gran) +{ + resource_t mask; + mask = (1ULL << gran) - 1ULL; + val &= ~mask; + return val; +} + +/** + * @brief Compute the maximum address that is part of a resource + * @param resource the resource whose limit is desired + * @returns the end + */ +resource_t resource_end(struct resource *resource) +{ + resource_t base, end; + /* get the base address */ + base = resource->base; + + /* For a non bridge resource granularity and alignment are the same. + * For a bridge resource align is the largest needed alignment below + * the bridge. While the granularity is simply how many low bits of the + * address cannot be set. + */ + + /* Get the end (rounded up) */ + end = base + align_up(resource->size, resource->gran) - 1; + + return end; +} + +/** + * @brief Compute the maximum legal value for resource->base + * @param resource the resource whose maximum is desired + * @returns the maximum + */ +resource_t resource_max(struct resource *resource) +{ + resource_t max; + + max = align_down(resource->limit - resource->size + 1, resource->align); + + return max; +} + +/** + * @brief print the resource that was just stored. + * @param dev the device the stored resorce lives on + * @param resource the resource that was just stored. + */ +void report_resource_stored(device_t dev, struct resource *resource, const char *comment) +{ + if (resource->flags & IORESOURCE_STORED) { + unsigned char buf[10]; + unsigned long long base, end; + base = resource->base; + end = resource_end(resource); + buf[0] = '\0'; + if (resource->flags & IORESOURCE_PCI_BRIDGE) { + sprintf(buf, "bus %d ", dev->link[0].secondary); + } + printk_debug( + "%s %02x <- [0x%010Lx - 0x%010Lx] %s%s%s%s\n", + dev_path(dev), + resource->index, + base, end, + buf, + (resource->flags & IORESOURCE_PREFETCH) ? "pref" : "", + (resource->flags & IORESOURCE_IO)? "io": + (resource->flags & IORESOURCE_DRQ)? "drq": + (resource->flags & IORESOURCE_IRQ)? "irq": + (resource->flags & IORESOURCE_MEM)? "mem": + "????", + comment); + } +} diff --git a/src/devices/hypertransport.c b/src/devices/hypertransport.c index 2126889e19..344f23fec4 100644 --- a/src/devices/hypertransport.c +++ b/src/devices/hypertransport.c @@ -14,9 +14,9 @@ static device_t ht_scan_get_devs(device_t *old_devices) device_t first, last; first = *old_devices; last = first; - while (last && last->sibling && - (last->sibling->path.type == DEVICE_PATH_PCI) && - (last->sibling->path.u.pci.devfn > last->path.u.pci.devfn)) { + while(last && last->sibling && + (last->sibling->path.type == DEVICE_PATH_PCI) && + (last->sibling->path.u.pci.devfn > last->path.u.pci.devfn)) { last = last->sibling; } if (first) { @@ -264,19 +264,21 @@ unsigned int hypertransport_scan_chain(struct bus *bus, unsigned int max) *chain_last = dev; /* Run the magice enable sequence for the device */ if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) { - int enable = dev->enabled; - dev->enabled = 1; dev->chip->control->enable_dev(dev); - dev->enabled = enable; } /* Now read the vendor and device id */ id = pci_read_config32(dev, PCI_VENDOR_ID); + /* If the chain is fully enumerated quit */ if (id == 0xffffffff || id == 0x00000000 || - id == 0x0000ffff || id == 0xffff0000) { - printk_err("Missing static device: %s\n", - dev_path(dev)); + id == 0x0000ffff || id == 0xffff0000) + { + if (dev->enabled) { + printk_info("Disabling static device: %s\n", + dev_path(dev)); + dev->enabled = 0; + } break; } } diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c index 6f7fabf67b..5d72f03ccd 100644 --- a/src/devices/pci_device.c +++ b/src/devices/pci_device.c @@ -21,125 +21,200 @@ #include <device/chip.h> #include <part/hard_reset.h> #include <part/fallback_boot.h> +#include <delay.h> + +static uint8_t pci_moving_config8(struct device *dev, unsigned reg) +{ + uint8_t value, ones, zeroes; + value = pci_read_config8(dev, reg); + + pci_write_config8(dev, reg, 0xff); + ones = pci_read_config8(dev, reg); + + pci_write_config8(dev, reg, 0x00); + zeroes = pci_read_config8(dev, reg); + + pci_write_config8(dev, reg, value); + + return ones ^ zeroes; +} +static uint16_t pci_moving_config16(struct device *dev, unsigned reg) +{ + uint16_t value, ones, zeroes; + value = pci_read_config16(dev, reg); + + pci_write_config16(dev, reg, 0xffff); + ones = pci_read_config16(dev, reg); + + pci_write_config16(dev, reg, 0x0000); + zeroes = pci_read_config16(dev, reg); + + pci_write_config16(dev, reg, value); + + return ones ^ zeroes; +} +static uint32_t pci_moving_config32(struct device *dev, unsigned reg) +{ + uint32_t value, ones, zeroes; + value = pci_read_config32(dev, reg); + + pci_write_config32(dev, reg, 0xffffffff); + ones = pci_read_config32(dev, reg); + + pci_write_config32(dev, reg, 0x00000000); + zeroes = pci_read_config32(dev, reg); + + pci_write_config32(dev, reg, value); + + return ones ^ zeroes; +} + +unsigned pci_find_capability(device_t dev, unsigned cap) +{ + unsigned pos; + pos = 0; + switch(dev->hdr_type & 0x7f) { + case PCI_HEADER_TYPE_NORMAL: + case PCI_HEADER_TYPE_BRIDGE: + pos = PCI_CAPABILITY_LIST; + break; + } + if (pos > PCI_CAP_LIST_NEXT) { + pos = pci_read_config8(dev, pos); + } + while(pos != 0) { /* loop through the linked list */ + int this_cap; + this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID); + if (this_cap == cap) { + return pos; + } + } + return 0; +} + /** Given a device and register, read the size of the BAR for that register. * @param dev Pointer to the device structure * @param resource Pointer to the resource structure * @param index Address of the pci configuration register */ -static struct resource *pci_get_resource(struct device *dev, unsigned long index) +struct resource *pci_get_resource(struct device *dev, unsigned long index) { struct resource *resource; - uint32_t addr, size, base; - unsigned long type; + unsigned long value, attr; + resource_t moving, limit; /* Initialize the resources to nothing */ - resource = get_resource(dev, index); + resource = new_resource(dev, index); - addr = pci_read_config32(dev, index); + /* Get the initial value */ + value = pci_read_config32(dev, index); - /* FIXME: more consideration for 64-bit PCI devices, - * we currently detect their size but otherwise - * treat them as 32-bit resources + /* See which bits move */ + moving = pci_moving_config32(dev, index); + + /* Initialize attr to the bits that do not move */ + attr = value & ~moving; + + /* If it is a 64bit resource look at the high half as well */ + if (((attr & PCI_BASE_ADDRESS_SPACE_IO) == 0) && + ((attr & PCI_BASE_ADDRESS_MEM_LIMIT_MASK) == PCI_BASE_ADDRESS_MEM_LIMIT_64)) + { + /* Find the high bits that move */ + 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. + * - Limit is all of the bits that move plus all of the lower bits. + * See PCI Spec 6.2.5.1 ... */ - /* get the size */ - pci_write_config32(dev, index, ~0); - size = pci_read_config32(dev, index); - - /* get the minimum value the bar can be set to */ - pci_write_config32(dev, index, 0); - base = pci_read_config32(dev, index); - - /* restore addr */ - pci_write_config32(dev, index, addr); - + limit = 0; + if (moving) { + resource->size = 1; + resource->align = resource->gran = 0; + while(!(moving & resource->size)) { + resource->size <<= 1; + resource->align += 1; + resource->gran += 1; + } + resource->limit = limit = moving | (resource->size - 1); + } /* * some broken hardware has read-only registers that do not - * really size correctly. You can tell this if addr == size + * really size correctly. * 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 settting size and type to 0. - * This incidentally catches the common case where registers - * read back as 0 for both address and size. + * We catch this case and ignore it by observing which bits move, + * This also catches the common case unimplemented registers + * that always read back as 0. */ - if ((addr == size) && (addr == base)) { - if (size != 0) { + if (moving == 0) { + if (value != 0) { printk_debug( "%s register %02x(%08x), read-only ignoring it\n", - dev_path(dev), - index, addr); + dev_path(dev), index, value); } resource->flags = 0; } - /* Now compute the actual size, See PCI Spec 6.2.5.1 ... */ - else if (size & PCI_BASE_ADDRESS_SPACE_IO) { - type = size & (~PCI_BASE_ADDRESS_IO_MASK); - /* BUG! Top 16 bits can be zero (or not) - * So set them to 0xffff so they go away ... - */ - resource->size = (~((size | 0xffff0000) & PCI_BASE_ADDRESS_IO_MASK)) +1; - resource->align = log2(resource->size); - resource->gran = resource->align; + else if (attr & PCI_BASE_ADDRESS_SPACE_IO) { + /* An I/O mapped base address */ + attr &= PCI_BASE_ADDRESS_IO_ATTR_MASK; resource->flags |= IORESOURCE_IO; + /* I don't want to deal with 32bit I/O resources */ resource->limit = 0xffff; } else { /* A Memory mapped base address */ - type = size & (~PCI_BASE_ADDRESS_MEM_MASK); - resource->size = (~(size &PCI_BASE_ADDRESS_MEM_MASK)) +1; - resource->align = log2(resource->size); - resource->gran = resource->align; + attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK; resource->flags |= IORESOURCE_MEM; - if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) { + if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH) { resource->flags |= IORESOURCE_PREFETCH; } - type &= PCI_BASE_ADDRESS_MEM_TYPE_MASK; - if (type == PCI_BASE_ADDRESS_MEM_TYPE_32) { + attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK; + if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) { /* 32bit limit */ resource->limit = 0xffffffffUL; } - else if (type == PCI_BASE_ADDRESS_MEM_TYPE_1M) { + else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) { /* 1MB limit */ resource->limit = 0x000fffffUL; } - else if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) { - unsigned long index_hi; - /* 64bit limit - * For now just treat this as a 32bit limit - */ - index_hi = index + 4; - resource->limit = 0xffffffffUL; + else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) { + /* 64bit limit */ + resource->limit = 0xffffffffffffffffULL; resource->flags |= IORESOURCE_PCI64; - addr = pci_read_config32( dev, index_hi); - /* get the extended size */ - pci_write_config32(dev, index_hi, 0xffffffffUL); - size = pci_read_config32( dev, index_hi); - - /* get the minimum value the bar can be set to */ - pci_write_config32(dev, index_hi, 0); - base = pci_read_config32(dev, index_hi); - - /* restore addr */ - pci_write_config32(dev, index_hi, addr); - - if ((size == 0xffffffff) && (base == 0)) { - /* Clear the top half of the bar */ - pci_write_config32(dev, index_hi, 0); - } - else { - printk_err("%s Unable to handle 64-bit address\n", - dev_path(dev)); - resource->flags = IORESOURCE_PCI64; - } - } + } else { /* Invalid value */ resource->flags = 0; } } - /* dev->size holds the flags... */ + /* Don't let the limit exceed which bits can move */ + if (resource->limit > limit) { + resource->limit = limit; + } +#if 0 + if (resource->flags) { + printk_debug("%s %02x ->", + dev_path(dev), resource->index); + printk_debug(" value: 0x%08Lx zeroes: 0x%08Lx ones: 0x%08Lx attr: %08lx\n", + value, zeroes, ones, attr); + printk_debug( + "%s %02x -> size: 0x%08Lx max: 0x%08Lx %s%s\n ", + dev_path(dev), + resource->index, + resource->size, resource->limit, + (resource->flags == 0) ? "unused": + (resource->flags & IORESOURCE_IO)? "io": + (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem", + (resource->flags & IORESOURCE_PCI64)?"64":""); + } +#endif + return resource; } @@ -159,42 +234,90 @@ static void pci_read_bases(struct device *dev, unsigned int howmany) compact_resources(dev); } -static void pci_bridge_read_bases(struct device *dev) +static void pci_set_resource(struct device *dev, struct resource *resource); + +static void pci_record_bridge_resource( + struct device *dev, resource_t moving, + unsigned index, unsigned long mask, unsigned long type) { + /* Initiliaze the constraints on the current bus */ struct resource *resource; + resource = 0; + 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; + compute_allocate_resource(&dev->link[0], resource, mask, type); + /* If there is nothing behind the resource, + * clear it and forget it. + */ + if (resource->size == 0) { + resource->base = moving; + resource->flags |= IORESOURCE_ASSIGNED; + resource->flags &= ~IORESOURCE_STORED; + pci_set_resource(dev, resource); + resource->flags = 0; + } + } + return; +} - /* FIXME handle bridges without some of the optional resources */ + +static void pci_bridge_read_bases(struct device *dev) +{ + resource_t moving_base, moving_limit, moving; + + + /* See if the bridge I/O resources are implemented */ + moving_base = ((uint32_t)pci_moving_config8(dev, PCI_IO_BASE)) << 8; + moving_base |= ((uint32_t)pci_moving_config16(dev, PCI_IO_BASE_UPPER16)) << 16; + + moving_limit = ((uint32_t)pci_moving_config8(dev, PCI_IO_LIMIT)) << 8; + moving_limit |= ((uint32_t)pci_moving_config16(dev, PCI_IO_LIMIT_UPPER16)) << 16; + + moving = moving_base & moving_limit; /* Initialize the io space constraints on the current bus */ - resource = get_resource(dev, PCI_IO_BASE); - resource->size = 0; - resource->align = log2(PCI_IO_BRIDGE_ALIGN); - resource->gran = log2(PCI_IO_BRIDGE_ALIGN); - resource->limit = 0xffffUL; - resource->flags |= IORESOURCE_IO | IORESOURCE_PCI_BRIDGE; - compute_allocate_resource(&dev->link[0], resource, + pci_record_bridge_resource( + dev, moving, PCI_IO_BASE, IORESOURCE_IO, IORESOURCE_IO); + + /* See if the bridge prefmem resources are implemented */ + moving_base = ((resource_t)pci_moving_config16(dev, PCI_PREF_MEMORY_BASE)) << 16; + moving_base |= ((resource_t)pci_moving_config32(dev, PCI_PREF_BASE_UPPER32)) << 32; + + moving_limit = ((resource_t)pci_moving_config16(dev, PCI_PREF_MEMORY_LIMIT)) << 16; + moving_limit |= ((resource_t)pci_moving_config32(dev, PCI_PREF_LIMIT_UPPER32)) << 32; + + moving = moving_base & moving_limit; /* Initiliaze the prefetchable memory constraints on the current bus */ - resource = get_resource(dev, PCI_PREF_MEMORY_BASE); - resource->size = 0; - resource->align = log2(PCI_MEM_BRIDGE_ALIGN); - resource->gran = log2(PCI_MEM_BRIDGE_ALIGN); - resource->limit = 0xffffffffUL; - resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_PCI_BRIDGE; - resource->index = PCI_PREF_MEMORY_BASE; - compute_allocate_resource(&dev->link[0], resource, - IORESOURCE_MEM | IORESOURCE_PREFETCH, + pci_record_bridge_resource( + dev, moving, PCI_PREF_MEMORY_BASE, + IORESOURCE_MEM | IORESOURCE_PREFETCH, IORESOURCE_MEM | IORESOURCE_PREFETCH); + + + /* See if the bridge mem resources are implemented */ + moving_base = ((uint32_t)pci_moving_config16(dev, PCI_MEMORY_BASE)) << 16; + moving_limit = ((uint32_t)pci_moving_config16(dev, PCI_MEMORY_LIMIT)) << 16; + + moving = moving_base & moving_limit; /* Initialize the memory resources on the current bus */ - resource = get_resource(dev, PCI_MEMORY_BASE); - resource->size = 0; - resource->align = log2(PCI_MEM_BRIDGE_ALIGN); - resource->gran = log2(PCI_MEM_BRIDGE_ALIGN); - resource->limit = 0xffffffffUL; - resource->flags = IORESOURCE_MEM | IORESOURCE_PCI_BRIDGE; - compute_allocate_resource(&dev->link[0], resource, + pci_record_bridge_resource( + dev, moving, PCI_MEMORY_BASE, IORESOURCE_MEM | IORESOURCE_PREFETCH, IORESOURCE_MEM); @@ -222,27 +345,9 @@ void pci_bus_read_resources(struct device *dev) dev->rom_address = (addr == 0xffffffff)? 0 : addr; } -/** - * @brief round a number up to the next multiple of gran - * @param val the starting value - * @param gran granularity we are aligning the number to. - * @returns aligned value - */ -static unsigned long align(unsigned long val, unsigned long gran) -{ - /* GRAN MUST BE A POWER OF TWO. */ - unsigned long mask; - mask = ~(gran - 1); - val += (gran - 1); - val &= mask; - return val; -} - static void pci_set_resource(struct device *dev, struct resource *resource) { - unsigned long base, limit; - unsigned char buf[10]; - unsigned long gran; + resource_t base, end; /* Make certain the resource has actually been set */ if (!(resource->flags & IORESOURCE_ASSIGNED)) { @@ -256,82 +361,77 @@ static void pci_set_resource(struct device *dev, struct resource *resource) return; } + /* If the resources is substractive don't worry about it */ + if (resource->flags & IORESOURCE_SUBTRACTIVE) { + return; + } + /* Only handle PCI memory and IO resources for now */ if (!(resource->flags & (IORESOURCE_MEM |IORESOURCE_IO))) return; - if (resource->flags & IORESOURCE_MEM) { - dev->command |= PCI_COMMAND_MEMORY; - } - if (resource->flags & IORESOURCE_IO) { - dev->command |= PCI_COMMAND_IO; - } - if (resource->flags & IORESOURCE_PCI_BRIDGE) { - dev->command |= PCI_COMMAND_MASTER; + /* Enable the resources in the command register */ + if (resource->size) { + if (resource->flags & IORESOURCE_MEM) { + dev->command |= PCI_COMMAND_MEMORY; + } + if (resource->flags & IORESOURCE_IO) { + dev->command |= PCI_COMMAND_IO; + } + if (resource->flags & IORESOURCE_PCI_BRIDGE) { + dev->command |= PCI_COMMAND_MASTER; + } } /* Get the base address */ base = resource->base; - /* Get the resource granularity */ - gran = 1UL << resource->gran; - /* For a non bridge resource granularity and alignment are the same. - * For a bridge resource align is the largest needed alignment below - * the bridge. While the granularity is simply how many low bits of the - * address cannot be set. - */ - - /* Get the limit (rounded up) */ - limit = base + align(resource->size, gran) - 1UL; + /* Get the end */ + end = resource_end(resource); /* Now store the resource */ resource->flags |= IORESOURCE_STORED; if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) { + unsigned long base_lo, base_hi; /* * some chipsets allow us to set/clear the IO bit. * (e.g. VIA 82c686a.) So set it to be safe) */ - limit = base + resource->size -1; + base_lo = base & 0xffffffff; + base_hi = (base >> 32) & 0xffffffff; if (resource->flags & IORESOURCE_IO) { - base |= PCI_BASE_ADDRESS_SPACE_IO; + base_lo |= PCI_BASE_ADDRESS_SPACE_IO; } - pci_write_config32(dev, resource->index, base & 0xffffffff); + pci_write_config32(dev, resource->index, base_lo); if (resource->flags & IORESOURCE_PCI64) { - /* FIXME handle real 64bit base addresses */ - pci_write_config32(dev, resource->index + 4, 0); + pci_write_config32(dev, resource->index + 4, base_hi); } } else if (resource->index == PCI_IO_BASE) { - /* set the IO ranges - * WARNING: we don't really do 32-bit addressing for IO yet! - */ + /* set the IO ranges */ compute_allocate_resource(&dev->link[0], resource, IORESOURCE_IO, IORESOURCE_IO); - pci_write_config8(dev, PCI_IO_BASE, base >> 8); - pci_write_config8(dev, PCI_IO_LIMIT, limit >> 8); - pci_write_config16(dev, PCI_IO_BASE_UPPER16, 0); - pci_write_config16(dev, PCI_IO_LIMIT_UPPER16, 0); + pci_write_config8(dev, PCI_IO_BASE, base >> 8); + pci_write_config16(dev, PCI_IO_BASE_UPPER16, base >> 16); + pci_write_config8(dev, PCI_IO_LIMIT, end >> 8); + pci_write_config16(dev, PCI_IO_LIMIT_UPPER16, end >> 16); } else if (resource->index == PCI_MEMORY_BASE) { - /* set the memory range - */ + /* set the memory range */ compute_allocate_resource(&dev->link[0], resource, IORESOURCE_MEM | IORESOURCE_PREFETCH, IORESOURCE_MEM); pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16); - pci_write_config16(dev, PCI_MEMORY_LIMIT, limit >> 16); + pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16); } else if (resource->index == PCI_PREF_MEMORY_BASE) { - /* set the prefetchable memory range - * WARNING: we don't really do 64-bit addressing - * for prefetchable memory yet! - */ + /* set the prefetchable memory range */ compute_allocate_resource(&dev->link[0], resource, IORESOURCE_MEM | IORESOURCE_PREFETCH, IORESOURCE_MEM | IORESOURCE_PREFETCH); - pci_write_config16(dev, PCI_PREF_MEMORY_BASE, base >> 16); - pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, limit >> 16); - pci_write_config32(dev, PCI_PREF_BASE_UPPER32, 0); - pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, 0); + pci_write_config16(dev, PCI_PREF_MEMORY_BASE, base >> 16); + pci_write_config32(dev, PCI_PREF_BASE_UPPER32, base >> 32); + pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, end >> 16); + pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, end >> 32); } else { /* Don't let me think I stored the resource */ @@ -339,18 +439,7 @@ static void pci_set_resource(struct device *dev, struct resource *resource) printk_err("ERROR: invalid resource->index %x\n", resource->index); } - buf[0] = '\0'; - if (resource->flags & IORESOURCE_PCI_BRIDGE) { - sprintf(buf, "bus %d ", dev->link[0].secondary); - } - printk_debug( - "%s %02x <- [0x%08lx - 0x%08lx] %s%s\n", - dev_path(dev), - resource->index, - (unsigned long)(resource->base), limit, - buf, - (resource->flags & IORESOURCE_IO)? "io": - (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem"); + report_resource_stored(dev, resource, ""); return; } @@ -392,7 +481,20 @@ void pci_dev_set_resources(struct device *dev) void pci_dev_enable_resources(struct device *dev) { + struct pci_operations *ops; uint16_t command; + + /* Set the subsystem vendor and device id for mainboard devices */ + ops = ops_pci(dev); + if (dev->chip && ops && ops->set_subsystem) { + printk_debug("%s subsystem <- %02x/%02x\n", + dev_path(dev), + MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID, + MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID); + ops->set_subsystem(dev, + MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID, + MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID); + } command = pci_read_config16(dev, PCI_COMMAND); command |= dev->command; command |= (PCI_COMMAND_PARITY + PCI_COMMAND_SERR); /* error check */ @@ -414,22 +516,39 @@ void pci_bus_enable_resources(struct device *dev) pci_dev_enable_resources(dev); } +static void pci_dev_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + /** Default device operation for PCI devices */ +static struct pci_operations pci_ops_pci_dev = { + .set_subsystem = pci_dev_set_subsystem, +}; + struct device_operations default_pci_ops_dev = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, .init = 0, .scan_bus = 0, + .enable = 0, + .ops_pci = &pci_ops_pci_dev, }; /** Default device operations for PCI bridges */ +static struct pci_operations pci_ops_pci_bus = { + .set_subsystem = 0, +}; struct device_operations default_pci_ops_bus = { .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, + .ops_pci = &pci_ops_pci_bus, }; /** @@ -443,7 +562,6 @@ struct device_operations default_pci_ops_bus = { static void set_pci_ops(struct device *dev) { struct pci_driver *driver; - if (dev->ops) { return; } @@ -464,17 +582,6 @@ static void set_pci_ops(struct device *dev) } } -#if 0 - extern struct pci_driver generic_vga_driver; - /* TODO: Install generic VGA driver for VGA devices, base on the - * class ID */ - if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { - printk_debug("setting up generic VGA driver\n"); - dev->ops = generic_vga_driver.ops; - return; - } -#endif - /* 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 */ @@ -501,7 +608,7 @@ static void set_pci_ops(struct device *dev) } /** - * @brief Find a specific device structure on a list of device structures + * @brief 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. @@ -515,9 +622,6 @@ static void set_pci_ops(struct device *dev) static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) { struct device *dev; - - printk_spew("%s, looking for devfn: %02x.%01x\n", __FUNCTION__, - devfn >> 3, devfn & 7); dev = 0; for(; *list; list = &(*list)->sibling) { if ((*list)->path.type != DEVICE_PATH_PCI) { @@ -538,7 +642,6 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) * we removed all of the parents children, and now we are interleaving * static and dynamic devices in order on the bus. */ - printk_spew("%s, found dev %08x\n", __FUNCTION__, dev); if (dev) { device_t child; /* Find the last child of our parent */ @@ -595,14 +698,11 @@ unsigned int pci_scan_bus(struct bus *bus, uint32_t id, class; uint8_t hdr_type; - /* device structures for PCI devices associated with static - * devices are already created during the static device - * enumeration, find out if it is the case for this devfn */ + /* First thing setup the device structure */ dev = pci_scan_get_dev(&old_devices, devfn); - + + /* Detect if a device is present */ if (!dev) { - /* it's not associated with a static device, detect if - * this device is present */ struct device dummy; dummy.bus = bus; dummy.path.type = DEVICE_PATH_PCI; @@ -628,10 +728,11 @@ unsigned int pci_scan_bus(struct bus *bus, dev = alloc_dev(bus, &dummy.path); } else { - /* If at all possible enable the device, if desired - * we will disable the device later, once we have - * found it's device specific operations. - * + /* Enable/disable the device. Once we have + * found the device specific operations this + * operations we will disable the device with + * those as well. + * * This is geared toward devices that have subfunctions * that do not show up by default. * @@ -642,13 +743,25 @@ unsigned int pci_scan_bus(struct bus *bus, if ( dev->chip && dev->chip->control && dev->chip->control->enable_dev) { - int enabled = dev->enabled; - dev->enabled = 1; dev->chip->control->enable_dev(dev); - dev->enabled = enabled; } /* 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 this is because we have already disabled + * the device. But this also handles optional devices + * that may not always show up. + */ + if (id == 0xffffffff || id == 0x00000000 || + id == 0x0000ffff || id == 0xffff0000) + { + if (dev->enabled) { + printk_info("Disabling static device: %s\n", + dev_path(dev)); + dev->enabled = 0; + } + } } /* Read the rest of the pci configuration information */ hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); @@ -661,6 +774,13 @@ unsigned int pci_scan_bus(struct bus *bus, /* class code, the upper 3 bytes of PCI_CLASS_REVISION */ dev->class = class >> 8; + /* Architectural/System devices always need to + * be bus masters. + */ + 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 class and figure out which set of * configuration methods to use. Unless we already @@ -678,16 +798,11 @@ unsigned int pci_scan_bus(struct bus *bus, if (dev->ops && dev->ops->enable) { dev->ops->enable(dev); } - else if (dev->chip && dev->chip->control && - dev->chip->control->enable_dev) - { - dev->chip->control->enable_dev(dev); - } printk_debug("%s [%04x/%04x] %s\n", - dev_path(dev), - dev->vendor, dev->device, - dev->enabled?"enabled": "disabled"); + dev_path(dev), + dev->vendor, dev->device, + dev->enabled?"enabled": "disabled"); if (PCI_FUNC(devfn) == 0x00 && (hdr_type & 0x80) != 0x80) { /* if this is not a multi function device, @@ -800,18 +915,10 @@ static void pci_level_irq(unsigned char intNum) { unsigned short intBits = inb(0x4d0) | (((unsigned) inb(0x4d1)) << 8); -<<<<<<< pci_device.c printk_spew("%s: current ints are 0x%x\n", __func__, intBits); -======= - printk_debug("%s: current ints are 0x%x\n", __FUNCTION__, intBits); ->>>>>>> 1.25 intBits |= (1 << intNum); -<<<<<<< pci_device.c printk_spew("%s: try to set ints 0x%x\n", __func__, intBits); -======= - printk_debug("%s: try to set ints 0x%x\n", __FUNCTION__, intBits); ->>>>>>> 1.25 // Write new values outb((unsigned char) intBits, 0x4d0); diff --git a/src/devices/pnp_device.c b/src/devices/pnp_device.c index 4bdb67e4aa..9ecfe63a52 100644 --- a/src/devices/pnp_device.c +++ b/src/devices/pnp_device.c @@ -69,7 +69,7 @@ static void pnp_set_resource(device_t dev, struct resource *resource) { if (!(resource->flags & IORESOURCE_ASSIGNED)) { printk_err("ERROR: %s %02x not allocated\n", - dev_path(dev), resource->index); + dev_path(dev), resource->index); return; } @@ -90,16 +90,7 @@ static void pnp_set_resource(device_t dev, struct resource *resource) } resource->flags |= IORESOURCE_STORED; - printk_debug( - "%s %02x <- [0x%08lx - 0x%08lx] %s\n", - dev_path(dev), - resource->index, - resource->base, resource->base + resource->size - 1, - (resource->flags & IORESOURCE_IO)? "io": - (resource->flags & IORESOURCE_DRQ)? "drq": - (resource->flags & IORESOURCE_IRQ)? "irq": - (resource->flags & IORESOURCE_MEM)? "mem": - "???"); + report_resource_stored(dev, resource, ""); } void pnp_set_resources(device_t dev) @@ -143,7 +134,7 @@ static void pnp_get_ioresource(device_t dev, unsigned index, struct io_info *inf struct resource *resource; uint32_t size; - resource = get_resource(dev, index); + resource = new_resource(dev, index); /* Initilize the resource */ resource->limit = 0xffff; @@ -173,22 +164,22 @@ static void get_resources(device_t dev, struct pnp_info *info) pnp_get_ioresource(dev, PNP_IDX_IO3, &info->io3); } if (info->flags & PNP_IRQ0) { - resource = get_resource(dev, PNP_IDX_IRQ0); + resource = new_resource(dev, PNP_IDX_IRQ0); resource->size = 1; resource->flags |= IORESOURCE_IRQ; } if (info->flags & PNP_IRQ1) { - resource = get_resource(dev, PNP_IDX_IRQ1); + resource = new_resource(dev, PNP_IDX_IRQ1); resource->size = 1; resource->flags |= IORESOURCE_IRQ; } if (info->flags & PNP_DRQ0) { - resource = get_resource(dev, PNP_IDX_DRQ0); + resource = new_resource(dev, PNP_IDX_DRQ0); resource->size = 1; resource->flags |= IORESOURCE_DRQ; } if (info->flags & PNP_DRQ1) { - resource = get_resource(dev, PNP_IDX_DRQ1); + resource = new_resource(dev, PNP_IDX_DRQ1); resource->size = 1; resource->flags |= IORESOURCE_DRQ; } diff --git a/src/devices/root_device.c b/src/devices/root_device.c index 04c96770fe..1642e8beda 100644 --- a/src/devices/root_device.c +++ b/src/devices/root_device.c @@ -9,34 +9,29 @@ */ void root_dev_read_resources(device_t root) { - int res = 0; + struct resource *resource; /* Initialize the system wide io space constraints */ - root->resource[res].base = 0x400; - root->resource[res].size = 0; - root->resource[res].align = 0; - root->resource[res].gran = 0; - root->resource[res].limit = 0xffffUL; - root->resource[res].flags = IORESOURCE_IO; - root->resource[res].index = 0; - compute_allocate_resource(&root->link[0], &root->resource[res], + resource = new_resource(root, 0); + resource->base = 0x400; + resource->size = 0; + resource->align = 0; + resource->gran = 0; + resource->limit = 0xffffUL; + resource->flags = IORESOURCE_IO; + compute_allocate_resource(&root->link[0], resource, IORESOURCE_IO, IORESOURCE_IO); - res++; /* Initialize the system wide memory resources constraints */ - root->resource[res].base = 0; - root->resource[res].size = 0; - root->resource[res].align = 0; - root->resource[res].gran = 0; - root->resource[res].limit = 0xffffffffUL; - root->resource[res].flags = IORESOURCE_MEM; - root->resource[res].index = 1; - compute_allocate_resource(&root->link[0], &root->resource[res], + resource = new_resource(root, 1); + resource->base = 0; + resource->size = 0; + resource->align = 0; + resource->gran = 0; + resource->limit = 0xffffffffUL; + resource->flags = IORESOURCE_MEM; + compute_allocate_resource(&root->link[0], resource, IORESOURCE_MEM, IORESOURCE_MEM); - res++; - - root->resources = res; - printk_spew("%s DONE\n", __func__); } /** @@ -124,8 +119,13 @@ void enable_childrens_resources(device_t dev) } } +void root_dev_enable_resources(device_t dev) +{ + enable_childrens_resources(dev); +} + /** - * @brief Scan root bus for generic PCI systems + * @brief Scan root bus for generic systems * * @param root The root device structure * @param max The current bus number scanned so fat, usually 0x00 @@ -135,9 +135,14 @@ void enable_childrens_resources(device_t dev) * generic PCI bus system is at Bus 0, Dev 0, Fun 0 so we scan the whole PCI * buses from there. */ -unsigned int root_dev_scan_pci_bus(device_t root, unsigned int max) +unsigned int root_dev_scan_bus(device_t root, unsigned int max) +{ + return scan_static_bus(root, max); +} + +void root_dev_init(device_t root) { - return pci_scan_bus(&root->link[0], 0, 0xff, max); + initialize_cpus(root); } /** @@ -153,9 +158,9 @@ unsigned int root_dev_scan_pci_bus(device_t root, unsigned int max) struct device_operations default_dev_ops_root = { .read_resources = root_dev_read_resources, .set_resources = root_dev_set_resources, - .enable_resources = enable_childrens_resources, - .init = 0, - .scan_bus = root_dev_scan_pci_bus, + .enable_resources = root_dev_enable_resources, + .init = root_dev_init, + .scan_bus = root_dev_scan_bus, }; /** @@ -169,11 +174,4 @@ struct device dev_root = { .bus = &dev_root.link[0], .path = { .type = DEVICE_PATH_ROOT }, .enabled = 1, - .links = 1, - .link = { - [0] = { - .dev = &dev_root, - .link = 0, - }, - }, }; |