From e52666931a3e34895b3f3b92641de9774ab722ec Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Tue, 23 Mar 2004 21:28:05 +0000 Subject: [PATCH] Doxidization, reformat git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1469 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/arch/i386/lib/cpu_reset.inc | 3 + src/boot/hardwaremain.c | 86 ++++--- src/config/Options.lb | 5 + src/cpu/k8/Config.lb | 3 + src/cpu/k8/cpufixup.c | 2 +- src/cpu/k8/earlymtrr.c | 13 +- src/cpu/k8/earlymtrr.inc | 19 +- src/cpu/p6/mtrr.c | 16 +- src/devices/chip.c | 103 +++++++-- src/devices/device.c | 173 +++++++++----- src/devices/device_util.c | 7 +- src/devices/pci_device.c | 296 ++++++++++++++---------- src/devices/root_device.c | 38 +-- src/include/device/device.h | 1 + src/include/device/pci.h | 2 + src/mainboard/tyan/s2885/Config.lb | 18 +- src/mainboard/via/epia/Config.lb | 3 +- src/mainboard/via/epia/auto.c | 4 +- src/northbridge/amd/amdk8/early_ht.c | 6 +- src/northbridge/amd/amdk8/northbridge.c | 54 ++++- src/northbridge/amd/amdk8/raminit.c | 2 + src/southbridge/amd/amd8111/amd8111.c | 7 +- 22 files changed, 572 insertions(+), 289 deletions(-) diff --git a/src/arch/i386/lib/cpu_reset.inc b/src/arch/i386/lib/cpu_reset.inc index c7c05e219..fcddd6b02 100644 --- a/src/arch/i386/lib/cpu_reset.inc +++ b/src/arch/i386/lib/cpu_reset.inc @@ -1,6 +1,9 @@ +/* -*- asm -*- */ + jmp cpu_reset_out __cpu_reset: + /* set the boot_complete flag */ movl $0xffffffff, %ebp jmp __main diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c index fed530226..e3667cccd 100644 --- a/src/boot/hardwaremain.c +++ b/src/boot/hardwaremain.c @@ -37,9 +37,6 @@ it with the version available from LANL. #include #include #include -#if 0 -#include -#endif #include #include #include @@ -81,6 +78,12 @@ static struct mem_range *get_ramsize(void) /* Number of cpus that are currently running in linuxbios */ static atomic_t active_cpus = ATOMIC_INIT(1); +/** + * @brief Initialize secondary processors. + * + * + * @todo move this into a method of per cpu data structure. + */ void secondary_cpu_init(void) { struct mem_range *mem; @@ -88,12 +91,14 @@ void secondary_cpu_init(void) int index; atomic_inc(&active_cpus); + printk_debug("%s\n", __FUNCTION__); mem = get_ramsize(); id = cpu_initialize(mem); index = processor_index(id); printk_debug("%s %d/%u\n", __FUNCTION__ , index, id); processor_map[index] = CPU_ENABLED; + atomic_dec(&active_cpus); stop_cpu(id); } @@ -105,20 +110,22 @@ static void wait_for_other_cpus(void) old_active_count = 1; active_count = atomic_read(&active_cpus); - while(active_count > 1) { + while (active_count > 1) { if (active_count != old_active_count) { - printk_info("Waiting for %d CPUS to stop\n", active_count); + printk_info("Waiting for %d CPUS to stop\n", + active_count); old_active_count = active_count; } active_count = atomic_read(&active_cpus); } - for(i = 0; i < CONFIG_MAX_CPUS; i++) { + + for (i = 0; i < CONFIG_MAX_CPUS; i++) { if (!(processor_map[i] & CPU_ENABLED)) { printk_err("CPU %d did not initialize!\n", i); processor_map[i] = 0; -#warning "FIXME do I need a mainboard_cpu_fixup function?" } } + printk_debug("All AP CPUs stopped\n"); } @@ -126,20 +133,16 @@ static void wait_for_other_cpus(void) #define wait_for_other_cpus() do {} while(0) #endif /* CONFIG_SMP */ +/** + * @brief Main program of LinuxBIOS + * + * @param boot_complete + */ void hardwaremain(int boot_complete) { /* Processor ID of the BOOT cpu (i.e. the one running this code) */ unsigned long boot_cpu; int boot_index; - - /* the order here is a bit tricky. We don't want to do much of - * anything that uses config registers until after PciAllocateResources - * since that function also figures out what kind of config strategy - * to use (type 1 or type 2). - * so we turn on cache, then worry about PCI setup, then do other - * things, so that the other work can use the PciRead* and PciWrite* - * functions. - */ struct mem_range *mem, *tmem; struct lb_memory *lb_mem; unsigned long totalmem; @@ -153,8 +156,8 @@ void hardwaremain(int boot_complete) post_code(0x39); printk_notice("LinuxBIOS-%s%s %s %s...\n", - linuxbios_version, linuxbios_extra_version, linuxbios_build, - (boot_complete)?"rebooting":"booting"); + linuxbios_version, linuxbios_extra_version, + linuxbios_build, (boot_complete)?"rebooting":"booting"); post_code(0x40); @@ -162,57 +165,68 @@ void hardwaremain(int boot_complete) if (boot_complete) { hard_reset(); } + CONFIGURE(CONF_PASS_PRE_PCI); - /* pick how to scan the bus. This is first so we can get at memory size. */ + /* determine how software can generate PCI configuration transactions + * in this system */ printk_info("Finding PCI configuration type.\n"); pci_set_method(); post_code(0x5f); + + /* convert static device structures into dynamic device structures + * before probing dynamic devices. */ enumerate_static_devices(); + + /* probe the existence of dynamic devices and construct the dynamic + * device tree. */ dev_enumerate(); post_code(0x66); - /* Now do the real bus. - * We round the total ram up a lot for thing like the SISFB, which - * shares high memory with the CPU. - */ + + /* probe and assign the resources required by the dynamic devices */ dev_configure(); post_code(0x88); + /* enable the resources probed and assigned in dev_configure() */ dev_enable(); + /* do the device specific init in additional to simple resources + * allocation performed in dev_enable() */ dev_initialize(); post_code(0x89); CONFIGURE(CONF_PASS_POST_PCI); + /* this is done last because some devices may 'steal' memory from + * the system during device initialization. */ mem = get_ramsize(); post_code(0x70); - totalmem = 0; - for(tmem = mem; tmem->sizek; tmem++) { + for (totalmem = 0, tmem = mem; tmem->sizek; tmem++) { totalmem += tmem->sizek; } - printk_info("totalram: %ldM\n", - (totalmem + 512) >> 10); /* Round to the nearest meg */ + /* Round to the nearest mega */ + printk_info("totalram: %ldM\n", (totalmem + 512) >> 10); - /* Fully initialize the cpu before configuring the bus */ + /* fully initialize the boot processor */ boot_cpu = cpu_initialize(mem); boot_index = processor_index(boot_cpu); printk_spew("BOOT CPU is %d\n", boot_cpu); processor_map[boot_index] = CPU_BOOTPROCESSOR|CPU_ENABLED; - /* Now start the other cpus initializing - * The sooner they start the sooner they stop. - */ + /* start up other processors, it works like a pthread_create() or + * fork(), instead of running the initialization code for all devices + * as the boot processor, they start from secondary_cpu_init(), doing + * cpu initialization only. */ post_code(0x75); startup_other_cpus(processor_map); - post_code(0x77); - /* make certain we are the only cpu running in linuxBIOS */ + /* like pthread_join() or wait(), wait other processors finishing + * their execution of secondary_cpu_init() and make certain we are + * the only cpu running in LinuxBIOS */ wait_for_other_cpus(); - /* Now that we have collected all of our information - * write our configuration tables. - */ + /* Now that we have collected all of our information, write our + * configuration tables. */ lb_mem = write_tables(mem, processor_map); CONFIGURE(CONF_PASS_PRE_BOOT); diff --git a/src/config/Options.lb b/src/config/Options.lb index 694a8aad4..2009106d0 100644 --- a/src/config/Options.lb +++ b/src/config/Options.lb @@ -717,6 +717,11 @@ define HAVE_ACPI_TABLES comment "Define to build ACPI tables" end +define AGP_APERTURE_SIZE + default none + export used + comment "AGP graphics virtual memory aperture size" +end ############################################### # Board specific options diff --git a/src/cpu/k8/Config.lb b/src/cpu/k8/Config.lb index a0a702e04..9081b0771 100644 --- a/src/cpu/k8/Config.lb +++ b/src/cpu/k8/Config.lb @@ -1,3 +1,6 @@ +# How does the config tool pick the correct +# cpufixup.c to generate cupfixup.o ? + uses k8 uses CPU_FIXUP default k8=1 diff --git a/src/cpu/k8/cpufixup.c b/src/cpu/k8/cpufixup.c index 2d347de82..c25a473d2 100644 --- a/src/cpu/k8/cpufixup.c +++ b/src/cpu/k8/cpufixup.c @@ -428,5 +428,5 @@ void k8_enable(struct chip *chip, enum chip_pass pass) struct chip_control cpu_k8_control = { .enable = k8_enable, - .name = "AMD K8", + .name = "AMD K8 CPU", }; diff --git a/src/cpu/k8/earlymtrr.c b/src/cpu/k8/earlymtrr.c index 5fb63d2e7..2138e3fef 100644 --- a/src/cpu/k8/earlymtrr.c +++ b/src/cpu/k8/earlymtrr.c @@ -27,13 +27,24 @@ static void early_mtrr_init(void) msr_t msr; const unsigned long *msr_addr; + /* Enable the access to AMD RdDram and WrDram extension bits */ + msr = rdmsr(SYSCFG_MSR); + msr.lo |= SYSCFG_MSR_MtrrFixDramModEn; + wrmsr(msr); + /* Inialize all of the relevant msrs to 0 */ msr.lo = 0; msr.hi = 0; - for(msr_addr = mtrr_msrs; *msr_addr; msr_addr++) { + + for (msr_addr = mtrr_msrs; *msr_addr; msr_addr++) { wrmsr(*msr_addr, msr); } + /* Disable the access to AMD RdDram and WrDram extension bits */ + msr = rdmsr(SYSCFG_MSR); + msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn; + wrmsr(msr); + /* Enable memory access for 0 - 1MB using top_mem */ msr.hi = 0; msr.lo = ((CONFIG_LB_MEM_TOPK << 10) + TOP_MEM_MASK) & ~TOP_MEM_MASK; diff --git a/src/cpu/k8/earlymtrr.inc b/src/cpu/k8/earlymtrr.inc index acc917be7..6f8537d25 100644 --- a/src/cpu/k8/earlymtrr.inc +++ b/src/cpu/k8/earlymtrr.inc @@ -13,6 +13,13 @@ earlymtrr_start: xorl %edx, %edx # movl $fixed_mtrr_msr, %esi +enable_fixed_mtrr_dram_modify: + /* Enable the access to AMD RdDram and WrDram extension bits */ + movl $SYSCFG_MSR, %ecx + rdmsr + orl $SYSCFG_MSR_MtrrFixDramModEn, %eax + wrmsr + clear_fixed_var_mtrr: lodsl (%esi), %eax testl %eax, %eax @@ -25,7 +32,14 @@ clear_fixed_var_mtrr: jmp clear_fixed_var_mtrr clear_fixed_var_mtrr_out: -/* enable memory access for 0 - 1MB using top_mem */ +disable_fixed_mtrr_dram_modify: + /* Disable the access to AMD RdDram and WrDram extension bits */ + movl $SYSCFG_MSR, %ecx + rdmsr + andl $(~SYSCFG_MSR_MtrrFixDramModEn), %eax + wrmsr + + /* enable memory access for 0 - 1MB using top_mem */ movl $TOP_MEM, %ecx xorl %edx, %edx movl $(((CONFIG_LB_MEM_TOPK << 10) + TOP_MEM_MASK) & ~TOP_MEM_MASK) , %eax @@ -72,9 +86,10 @@ enable_mtrr: movl $0x00000800, %eax wrmsr - /* Enable the MTRRs in SYSCFG */ + /* Enable the MTRRs and IORRs in SYSCFG */ movl $SYSCFG_MSR, %ecx rdmsr + /* Don't enable SYSCFG_MSR_MtrrFixDramEn) untill we have done with VGA BIOS */ orl $(SYSCFG_MSR_MtrrVarDramEn), %eax wrmsr diff --git a/src/cpu/p6/mtrr.c b/src/cpu/p6/mtrr.c index 7e2eb06e9..89465c620 100644 --- a/src/cpu/p6/mtrr.c +++ b/src/cpu/p6/mtrr.c @@ -99,7 +99,7 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l base.hi = basek >> 22; base.lo = basek << 10; - //printk_debug("ADDRESS_MASK_HIGH=%#x\n", ADDRESS_MASK_HIGH); + //printk_debug("ADDRESS_MASK_HIGH=%#x\n", ADDRESS_MASK_HIGH); if (sizek < 4*1024*1024) { mask.hi = ADDRESS_MASK_HIGH; @@ -219,7 +219,7 @@ static void set_fixed_mtrrs(unsigned int first, unsigned int last, unsigned char unsigned int fixed_msr = NUM_FIXED_RANGES >> 3; msr_t msr; msr.lo = msr.hi = 0; /* Shut up gcc */ - for(i = first; i < last; i++) { + for (i = first; i < last; i++) { /* When I switch to a new msr read it in */ if (fixed_msr != i >> 3) { /* But first write out the old msr */ @@ -304,12 +304,12 @@ void setup_mtrrs(struct mem_range *mem) printk_debug("\n"); /* Initialized the fixed_mtrrs to uncached */ printk_debug("Setting fixed MTRRs(%d-%d) type: UC\n", - 0, NUM_FIXED_RANGES); + 0, NUM_FIXED_RANGES); set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHEABLE); /* Now see which of the fixed mtrrs cover ram. */ - for(memp = mem; memp->sizek; memp++) { + for (memp = mem; memp->sizek; memp++) { unsigned int start_mtrr; unsigned int last_mtrr; start_mtrr = fixed_mtrr_index(memp->basek); @@ -317,11 +317,17 @@ void setup_mtrrs(struct mem_range *mem) if (start_mtrr >= NUM_FIXED_RANGES) { break; } + +#if defined(k7) || defined(k8) +#warning "FIXME: dealing with RdMEM/WrMEM for Athlon/Opteron" +#endif + printk_debug("Setting fixed MTRRs(%d-%d) type: WB\n", - start_mtrr, last_mtrr); + start_mtrr, last_mtrr); set_fixed_mtrrs(start_mtrr, last_mtrr, MTRR_TYPE_WRBACK); } printk_debug("DONE fixed MTRRs\n"); + /* Cache as many memory areas as possible */ /* FIXME is there an algorithm for computing the optimal set of mtrrs? * In some cases it is definitely possible to do better. diff --git a/src/devices/chip.c b/src/devices/chip.c index d8a59e306..33f3976eb 100644 --- a/src/devices/chip.c +++ b/src/devices/chip.c @@ -9,8 +9,22 @@ #include #include -void -chip_configure(struct chip *root, enum chip_pass pass) +/** + * @brief Configure static devices + * + * Starting from the static device 'root', walk the tree and configure each + * device by calling the device specific chip_control::enable(). + * + * This function is only an iterator, the exact definition of 'configure' + * depends on the device specific implementation of chip_control::enable(). + * + * @param root root of the static device tree to be configured. + * @param pass pass of the configuration operation to be perfromed. + * + * @see chip_pass + * @see chip_control::enable + */ +void chip_configure(struct chip *root, enum chip_pass pass) { struct chip *c; @@ -25,24 +39,37 @@ chip_configure(struct chip *root, enum chip_pass pass) } } -/** Convert a static struct chip structure to a set of dynamic device structures. - * @param chip Static chip structure to start with. +/** + * @brief Convert static device structures to dynamic structures. + * + * A static device may contain one or more dynamic devices. Dynamic device + * structures of these devices have to be generated before the enumeration + * of dynamic devices. This function converts a static chip structure to a + * set of dynamic device structures. + * + * This function is the generic method called by enumerate_static_device_chain() + * for static devices. Devices extend this default behavior by defining their + * own chip_controll::enumerate(). Generally, device specific + * chip_control::enumerate() method calls this function as its last operation. + * + * @param chip static chip structure to be converted. + * */ - void chip_enumerate(struct chip *chip) { struct chip *child; device_t dev; int link; int i; + dev = 0; link = 0; -#if 1 + if (chip->control && chip->control->name) { printk_debug("Enumerating: %s\n", chip->control->name); } -#endif - for(i = 0; i < MAX_CHIP_PATHS; i++) { + + for (i = 0; i < MAX_CHIP_PATHS; i++) { int identical_paths; identical_paths = (i > 0) && @@ -55,6 +82,7 @@ void chip_enumerate(struct chip *chip) parent = chip->bus; switch(chip->path[i].path.type) { case DEVICE_PATH_NONE: + /* no dynamic device associated */ break; case DEVICE_PATH_PCI: bus = chip->path[i].path.u.pci.bus; @@ -62,7 +90,7 @@ void chip_enumerate(struct chip *chip) device_t dev; int i = 1; dev = chip->dev; - while(dev && (i != bus)) { + while (dev && (i != bus)) { dev = dev->next; i++; } @@ -75,18 +103,21 @@ void chip_enumerate(struct chip *chip) dev = alloc_dev(parent, &chip->path[i].path); break; } - } - else { + } else { link += 1; } + if (dev) { 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("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)); dev->chip = chip; dev->enable = chip->path[i].enable; dev->links = link + 1; - for(child = chip->children; child; child = child->next) { + for (child = chip->children; child; child = child->next) { if (!child->bus && child->link == i) { child->bus = &dev->link[link]; } @@ -102,21 +133,42 @@ void chip_enumerate(struct chip *chip) } } } + if (dev && !chip->dev) { chip->dev = dev; } } - for(child = chip->children; child; child = child->next) { + + for (child = chip->children; child; child = child->next) { if (!child->bus) { child->bus = &chip->dev->link[0]; } } } +/** + * @brief Enumerate a static device tree. + * + * A static device chain is a linked list of static device structures which are + * on the same branch of the static device tree. This function does not only + * enumerate the devices on a single chain, as its name suggest, it also walks + * into the subordinary chains. It calls the device specific + * chip_control::enumerate() of the device if one exists or calls the generic + * chip_enumerate(). + * + * This function is only an iterator, the exact definition of 'enumerate' + * depends on the implementation of the generic chip_enumerate() and/or device + * specific chip_control::enumerate(). + * + * @param root static chip structure to start with. + * + * @see chip_control::enumerate() + */ static void enumerate_static_device_chain(struct chip *root) { struct chip *chip; - for(chip = root; chip; chip = chip->next) { + + for (chip = root; chip; chip = chip->next) { void (*enumerate)(struct chip *chip); enumerate = chip_enumerate; if (chip->control && chip->control->enumerate) { @@ -125,13 +177,30 @@ static void enumerate_static_device_chain(struct chip *root) enumerate(chip); } - for(chip = root; chip; chip = chip->next) { + for (chip = root; chip; chip = chip->next) { if (chip->children) { enumerate_static_device_chain(chip->children); } } } +/** + * @brief Enumerate static devices in the system. + * + * \note The definition of 'enumerate' is not clear in this context. Does it mean + * probe ? + * + * \note How do we determine the existence of the static devices ? Static + * devices are listed in the config file and generated at compile time by config + * tool. This function is called at certain point in the early stage of + * LinuxBIOS. It uses the chip_enumerate() function to convert the static + * structures into dynamic ones. What if the static devices listed in the config + * file does actually not exist in the system ? Is there any side effect of + * these 'phantom' device structures + * + * The static device does not necesarry conform to the dynamic device tree in + * the system. + */ void enumerate_static_devices(void) { enumerate_static_device_chain(&static_root); diff --git a/src/devices/device.c b/src/devices/device.c index b54e77029..0186aa977 100644 --- a/src/devices/device.c +++ b/src/devices/device.c @@ -22,24 +22,41 @@ #include #include -/* Linked list of ALL devices */ +/** Linked list of ALL devices */ struct device *all_devices = &dev_root; -/* pointer to the last device */ +/** Pointer to the last device */ static struct device **last_dev_p = &dev_root.next; -#define DEVICE_MEM_HIGH 0xFEC00000UL /* Reserve 20M for the system */ +/** The upper limit of MEM resource of the devices. + * Reserve 20M for the system */ +#define DEVICE_MEM_HIGH 0xFEC00000UL +/** The lower limit of IO resource of the devices. + * Reserve 4k for ISA/Legacy devices */ #define DEVICE_IO_START 0x1000 -/** Allocate a new device structure +/** + * @brief Allocate a new device structure. + * + * Allocte a new device structure and attached it to the device tree as a child + * of the parent bus. + * + * @param parent parent bus the newly created device attached to. + * @param path path to the device to be created. + * + * @return pointer to the newly created device structure. + * + * @see device_path */ device_t alloc_dev(struct bus *parent, struct device_path *path) { device_t dev, child; int link; + /* Find the last child of our parent */ - for(child = parent->children; child && child->sibling; ) { + for (child = parent->children; child && child->sibling; ) { child = child->sibling; } + dev = malloc(sizeof(*dev)); if (dev == 0) { die("DEV: out of memory.\n"); @@ -47,14 +64,14 @@ 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 chain. - * The chain is used to find devices once everything is set up. + /* 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++) { + for (link = 0; link < MAX_LINKS; link++) { dev->link[link].dev = dev; dev->link[link].link = link; } @@ -66,12 +83,15 @@ 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->enable = 1; + return dev; } -/** round a number to an alignment. +/** + * @brief round a number up to an alignment. * @param val the starting value * @param roundup Alignment as a power of two * @returns rounded up number @@ -104,7 +124,7 @@ static void read_resources(struct bus *bus) struct device *curdev; /* Walk through all of the devices and find which resources they need. */ - for(curdev = bus->children; curdev; curdev = curdev->sibling) { + for (curdev = bus->children; curdev; curdev = curdev->sibling) { unsigned links; int i; if (curdev->resources > 0) { @@ -112,20 +132,22 @@ static void read_resources(struct bus *bus) } if (!curdev->ops || !curdev->ops->read_resources) { printk_err("%s missing read_resources\n", - dev_path(curdev)); + dev_path(curdev)); continue; } if (!curdev->enable) { continue; } + curdev->ops->read_resources(curdev); + /* Read in subtractive resources behind the current device */ links = 0; - for(i = 0; i < curdev->resources; i++) { + for (i = 0; i < curdev->resources; i++) { struct resource *resource; resource = &curdev->resource[i]; if ((resource->flags & IORESOURCE_SUBTRACTIVE) && - (!(links & (1 << resource->index)))) + (!(links & (1 << resource->index)))) { links |= (1 << resource->index); read_resources(&curdev->link[resource->index]); @@ -142,8 +164,8 @@ struct pick_largest_state { int seen_last; }; -static void pick_largest_resource( - struct pick_largest_state *state, struct device *dev, struct resource *resource) +static void pick_largest_resource(struct pick_largest_state *state, + struct device *dev, struct resource *resource) { struct resource *last; last = state->last; @@ -152,32 +174,33 @@ static void pick_largest_resource( state->seen_last = 1; return; } - if (last && ( - (last->align < resource->align) || - ((last->align == resource->align) && - (last->size < resource->size)) || - ((last->align == resource->align) && - (last->size == resource->size) && - (!state->seen_last)))) { + if (last && + ((last->align < resource->align) || + ((last->align == resource->align) && + (last->size < resource->size)) || + ((last->align == resource->align) && + (last->size == resource->size) && + (!state->seen_last)))) { return; } - if (!state->result || - (state->result->align < resource->align) || - ((state->result->align == resource->align) && - (state->result->size < resource->size))) { + if (!state->result || + (state->result->align < resource->align) || + ((state->result->align == resource->align) && + (state->result->size < resource->size))) { state->result_dev = dev; state->result = resource; - } - + } } static void find_largest_resource(struct pick_largest_state *state, - struct bus *bus, unsigned long type_mask, unsigned long type) + struct bus *bus, unsigned long type_mask, + unsigned long type) { struct device *curdev; - for(curdev = bus->children; curdev; curdev = curdev->sibling) { + + for (curdev = bus->children; curdev; curdev = curdev->sibling) { int i; - for(i = 0; i < curdev->resources; i++) { + for (i = 0; i < curdev->resources; i++) { struct resource *resource = &curdev->resource[i]; /* If it isn't the right kind of resource ignore it */ if ((resource->flags & type_mask) != type) { @@ -187,7 +210,8 @@ static void find_largest_resource(struct pick_largest_state *state, if (resource->flags & IORESOURCE_SUBTRACTIVE) { struct bus *subbus; subbus = &curdev->link[resource->index]; - find_largest_resource(state, subbus, type_mask, type); + find_largest_resource(state, subbus, + type_mask, type); continue; } /* See if this is the largest resource */ @@ -196,8 +220,10 @@ static void find_largest_resource(struct pick_largest_state *state, } } -static struct device *largest_resource(struct bus *bus, struct resource **result_res, - unsigned long type_mask, unsigned long type) +static struct device *largest_resource(struct bus *bus, + struct resource **result_res, + unsigned long type_mask, + unsigned long type) { struct pick_largest_state state; @@ -254,12 +280,12 @@ void compute_allocate_resource( min_align = 0; base = bridge->base; - printk_spew("%s compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d\n", - dev_path(bus->dev), - (bridge->flags & IORESOURCE_IO)? "io": - (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", - base, bridge->size, bridge->align, bridge->gran); - + printk_spew("%s compute_allocate_%s: base: %08lx size: %08lx " + "align: %d gran: %d\n", + dev_path(bus->dev), + (bridge->flags & IORESOURCE_IO)? "io": + (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", + base, bridge->size, bridge->align, bridge->gran); /* We want different minimum alignments for different kinds of * resources. These minimums are not device type specific @@ -278,8 +304,9 @@ void compute_allocate_resource( /* Remember I haven't found anything yet. */ resource = 0; - /* Walk through all the devices on the current bus and compute the addresses */ - while((dev = largest_resource(bus, &resource, type_mask, type))) { + /* Walk through all the devices on the current bus and compute the + * addresses */ + while ((dev = largest_resource(bus, &resource, type_mask, type))) { unsigned long 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 @@ -357,6 +384,8 @@ void compute_allocate_resource( static void allocate_vga_resource(void) { #warning "FIXME modify allocate_vga_resource so it is less pci centric!" +#warning "This function knows to much about PCI stuff, it should be just a ietrator/visitor." + /* FIXME handle the VGA pallette snooping */ struct device *dev, *vga; struct bus *bus; @@ -422,7 +451,7 @@ void enable_resources(struct device *dev) */ if (!dev->ops || !dev->ops->enable_resources) { printk_err("%s missing enable_resources\n", - dev_path(dev)); + dev_path(dev)); return; } if (!dev->enable) { @@ -431,58 +460,74 @@ void enable_resources(struct device *dev) dev->ops->enable_resources(dev); } -/** Enumerate the resources on the PCI by calling pci_init +/** + * @brief Determine the existence of dynamic devices and construct dynamic + * device tree. + * + * Start for the root device 'dev_root', scan the buses in the system, build + * the dynamic device tree according to the result of the probe. + * + * This function have no idea how to scan and probe the buses and devices at + * all. It depends on the bus/device specific scan_bus() method to do it. + * The scan_bus() function also have to create the device structure and attach + * it to the device tree. */ void dev_enumerate(void) { struct device *root; unsigned subordinate; - printk_info("Enumerating buses..."); + + printk_info("Enumerating buses...\n"); + root = &dev_root; subordinate = root->ops->scan_bus(root, 0); + printk_info("done\n"); } -/** Starting at the root, compute what resources are needed and allocate them. +/** + * @brief Configure devices on the devices tree. + * + * Starting at the root, compute what resources are needed and allocate them. * I/O starts at PCI_IO_START. Since the assignment is hierarchical we * set the values into the dev_root struct. */ void dev_configure(void) { struct device *root = &dev_root; + printk_info("Allocating resources..."); printk_debug("\n"); - root->ops->read_resources(root); - /* Make certain the io devices are allocated somewhere - * safe. - */ + /* 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; - /* Now reallocate the pci resources memory with the - * highest addresses I can manage. - */ + + /* 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); + 1UL << root->resource[1].align); root->resource[1].flags |= IORESOURCE_ASSIGNED; root->resource[1].flags &= ~IORESOURCE_STORED; - /* Allocate the VGA I/O resource.. - */ + /* Allocate the VGA I/O resource.. */ allocate_vga_resource(); - // now just set things into registers ... we hope ... + /* now just set things into registers ... we hope ... */ root->ops->set_resources(root); printk_info("done.\n"); } -/** Starting at the root, walk the tree and enable all devices/bridges. - * What really happens is computed COMMAND bits get set in register 4 +/** + * @brief Enable devices on the device tree. + * + * Starting at the root, walk the tree and enable all devices/bridges by + * calling the device's enable_resources() method. */ void dev_enable(void) { @@ -490,22 +535,28 @@ void dev_enable(void) /* now enable everything. */ enable_resources(&dev_root); + printk_info("done.\n"); } -/** Starting at the root, walk the tree and call a driver to - * do device specific setup. +/** + * @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. */ void dev_initialize(void) { struct device *dev; printk_info("Initializing devices...\n"); + for (dev = all_devices; dev; dev = dev->next) { if (dev->enable && dev->ops && dev->ops->init) { printk_debug("%s init\n", dev_path(dev)); dev->ops->init(dev); } } + printk_info("Devices initialized\n"); } diff --git a/src/devices/device_util.c b/src/devices/device_util.c index 013501474..29bb539e1 100644 --- a/src/devices/device_util.c +++ b/src/devices/device_util.c @@ -6,15 +6,16 @@ /** - * See if a device structure already exists and if not allocate it + * @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 a device structure for the device on bus at path + * @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; - for(child = parent->children; child; child = child->sibling) { + for (child = parent->children; child; child = child->sibling) { if (path_eq(path, &child->path)) { return child; } diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c index c3f1f6ac8..4bc4e1f9f 100644 --- a/src/devices/pci_device.c +++ b/src/devices/pci_device.c @@ -151,7 +151,7 @@ static void pci_read_bases(struct device *dev, unsigned int howmany) { unsigned long index; - for(index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) { + for (index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) { struct resource *resource; resource = pci_get_resource(dev, index); index += (resource->flags & IORESOURCE_PCI64)?8:4; @@ -159,7 +159,6 @@ static void pci_read_bases(struct device *dev, unsigned int howmany) compact_resources(dev); } - static void pci_bridge_read_bases(struct device *dev) { struct resource *resource; @@ -174,7 +173,7 @@ static void pci_bridge_read_bases(struct device *dev) resource->limit = 0xffffUL; resource->flags |= IORESOURCE_IO | IORESOURCE_PCI_BRIDGE; compute_allocate_resource(&dev->link[0], resource, - IORESOURCE_IO, IORESOURCE_IO); + IORESOURCE_IO, IORESOURCE_IO); /* Initiliaze the prefetchable memory constraints on the current bus */ resource = get_resource(dev, PCI_PREF_MEMORY_BASE); @@ -185,8 +184,8 @@ static void pci_bridge_read_bases(struct device *dev) 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, - IORESOURCE_MEM | IORESOURCE_PREFETCH); + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM | IORESOURCE_PREFETCH); /* Initialize the memory resources on the current bus */ resource = get_resource(dev, PCI_MEMORY_BASE); @@ -196,17 +195,18 @@ static void pci_bridge_read_bases(struct device *dev) resource->limit = 0xffffffffUL; resource->flags = IORESOURCE_MEM | IORESOURCE_PCI_BRIDGE; compute_allocate_resource(&dev->link[0], resource, - IORESOURCE_MEM | IORESOURCE_PREFETCH, - IORESOURCE_MEM); + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM); compact_resources(dev); } - void pci_dev_read_resources(struct device *dev) { uint32_t addr; + pci_read_bases(dev, 6); + addr = pci_read_config32(dev, PCI_ROM_ADDRESS); dev->rom_address = (addr == 0xffffffff)? 0 : addr; } @@ -214,14 +214,29 @@ void pci_dev_read_resources(struct device *dev) void pci_bus_read_resources(struct device *dev) { uint32_t addr; + pci_bridge_read_bases(dev); pci_read_bases(dev, 2); addr = pci_read_config32(dev, PCI_ROM_ADDRESS1); dev->rom_address = (addr == 0xffffffff)? 0 : addr; - } +/** + * @brief round a number up to an alignment. + * @param val the starting value + * @param roundup Alignment as a power of two + * @returns rounded up number + */ +static unsigned long round(unsigned long val, unsigned long roundup) +{ + /* ROUNDUP MUST BE A POWER OF TWO. */ + unsigned long inverse; + inverse = ~(roundup - 1); + val += (roundup - 1); + val &= inverse; + return val; +} static void pci_set_resource(struct device *dev, struct resource *resource) { @@ -230,11 +245,10 @@ static void pci_set_resource(struct device *dev, struct resource *resource) unsigned long gran; /* Make certain the resource has actually been set */ + if (!(resource->flags & IORESOURCE_ASSIGNED)) { -#if 1 printk_err("ERROR: %s %02x not allocated\n", - dev_path(dev), resource->index); -#endif + dev_path(dev), resource->index); return; } @@ -256,8 +270,10 @@ static void pci_set_resource(struct device *dev, struct resource *resource) 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; @@ -268,15 +284,13 @@ static void pci_set_resource(struct device *dev, struct resource *resource) */ /* Get the limit (rounded up) */ - limit = base + ((resource->size + gran - 1UL) & ~(gran - 1UL)) -1UL; + limit = base + round(resource->size, gran) - 1UL; /* Now store the resource */ resource->flags |= IORESOURCE_STORED; if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) { - /* - * some chipsets allow us to set/clear the IO bit. - * (e.g. VIA 82c686a.) So set it to be safe) - */ + /* 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; if (resource->flags & IORESOURCE_IO) { base |= PCI_BASE_ADDRESS_SPACE_IO; @@ -286,58 +300,50 @@ static void pci_set_resource(struct device *dev, struct resource *resource) /* FIXME handle real 64bit base addresses */ pci_write_config32(dev, resource->index + 4, 0); } - } - else if (resource->index == PCI_IO_BASE) { + } else if (resource->index == PCI_IO_BASE) { /* set the IO ranges * WARNING: we don't really do 32-bit addressing for IO yet! */ compute_allocate_resource(&dev->link[0], resource, - IORESOURCE_IO, IORESOURCE_IO); + 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); - } - else if (resource->index == PCI_MEMORY_BASE) { - /* set the memory range - */ + } else if (resource->index == PCI_MEMORY_BASE) { + /* set the memory range */ compute_allocate_resource(&dev->link[0], resource, - IORESOURCE_MEM | IORESOURCE_PREFETCH, - IORESOURCE_MEM); + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM); pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16); pci_write_config16(dev, PCI_MEMORY_LIMIT, limit >> 16); - } - else if (resource->index == PCI_PREF_MEMORY_BASE) { + } 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! - */ + * WARNING: we don't really do 64-bit addressing for + * prefetchable memory yet! */ compute_allocate_resource(&dev->link[0], resource, - IORESOURCE_MEM | IORESOURCE_PREFETCH, - IORESOURCE_MEM | IORESOURCE_PREFETCH); + 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); - } - else { + } else { /* Don't let me think I stored the resource */ resource->flags &= ~IORESOURCE_STORED; printk_err("ERROR: invalid resource->index %x\n", - resource->index); + 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, - resource->base, limit, - buf, - (resource->flags & IORESOURCE_IO)? "io": - (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem"); + printk_debug("%s %02x <- [0x%08lx - 0x%08lx] %s%s\n", + dev_path(dev), resource->index, resource->base, + limit, buf, + (resource->flags & IORESOURCE_IO)? "io": + (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem"); return; } @@ -348,11 +354,11 @@ void pci_dev_set_resources(struct device *dev) uint8_t line; last = &dev->resource[dev->resources]; - - for(resource = &dev->resource[0]; resource < last; resource++) { + for (resource = &dev->resource[0]; resource < last; resource++) { pci_set_resource(dev, resource); } - for(link = 0; link < dev->links; link++) { + + for (link = 0; link < dev->links; link++) { struct bus *bus; bus = &dev->link[link]; if (bus->children) { @@ -401,43 +407,55 @@ void pci_bus_enable_resources(struct device *dev) pci_dev_enable_resources(dev); } +/** Default device operation for PCI devices */ 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, + .init = 0, + .scan_bus = 0, }; + +/** Default device operations for PCI bridges */ 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, + .init = 0, + .scan_bus = pci_scan_bridge, }; + +/** + * @brief Set up PCI device operation + * + * + * @param dev + * + * @see pci_drivers + */ static void set_pci_ops(struct device *dev) { struct pci_driver *driver; + if (dev->ops) { return; } + /* Look through the list of setup drivers and find one for - * this pci device - */ - for(driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) { + * this pci device */ + 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; -#if 1 - printk_debug("%s [%04x/%04x] %sops\n", - dev_path(dev), - driver->vendor, driver->device, - (driver->ops->scan_bus?"bus ":"") - ); -#endif + + printk_debug("%s [%04x/%04x] %sops\n", 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 */ @@ -454,27 +472,35 @@ static void set_pci_ops(struct device *dev) bad: if (dev->enable) { printk_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); + "type %02x, ignoring.\n", + dev_path(dev), + dev->vendor, dev->device, + dev->class >> 8, dev->hdr_type); } } return; } /** - * Given a bus and a devfn number, find the device structure - * @param bus The bus structure + * @brief Find a specific device structure on a list of device structures + * + * Given a linked list of PCI device structures and a devfn number, find the + * device structure correspond to the devfn. + * + * @param list the device structure list * @param devfn a device/function number - * @return pointer to the device structure + * + * @return pointer to the device structure found */ -static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) +static struct device *pci_scan_get_dev(struct device **list, + unsigned int devfn) { struct device *dev = 0; - for(; *list; list = &(*list)->sibling) { + + for (; *list; list = &(*list)->sibling) { if ((*list)->path.type != DEVICE_PATH_PCI) { - printk_err("child %s not a pci device\n", dev_path(*list)); + printk_err("child %s not a pci device\n", + dev_path(*list)); continue; } if ((*list)->path.u.pci.devfn == devfn) { @@ -485,10 +511,13 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) break; } } + + /* FIXME: why are we doing this ? Isn't there some order between the + * structures before ? */ if (dev) { device_t 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 it's parent. */ @@ -502,16 +531,24 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) return dev; } -/** Scan the pci bus devices and bridges. +/** + * @brief 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. + * + * 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 */ -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; device_t dev; @@ -524,42 +561,50 @@ unsigned int pci_scan_bus(struct bus *bus, bus->children = 0; post_code(0x24); - - /* probe all devices on this bus with some optimization for non-existance and - single funcion devices */ + /* probe all devices on this bus with some optimization for + * non-existence and single funcion devices */ for (devfn = min_devfn; devfn <= max_devfn; devfn++) { uint32_t id, class; uint8_t hdr_type; - /* First thing setup the device structure */ + /* 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 */ 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; 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)) - { - printk_spew("PCI: devfn 0x%x, bad id 0x%x\n", devfn, id); + 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) { - /* if this is a function 0 device and it is not present, - skip to next device */ + /* if this is a function 0 device and + * it is not present, skip to next + * device */ devfn += 0x07; } - /* multi function device, skip to next function */ + /* this function in a multi function device is + * not present, skip to next function */ continue; } dev = alloc_dev(bus, &dummy.path); - } - else { - /* Run the magic enable sequence for the device */ - if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) { + } else { + /* Run the magic enable/disable sequence for the + * device */ + /* FIXME: What happen if this PCI device listed as + * static device but does not exist ? This calls + * some arbitray code without any justification */ + if (dev->chip && dev->chip->control && + dev->chip->control->enable_dev) { int enable = dev->enable; dev->enable = 1; dev->chip->control->enable_dev(dev); @@ -580,14 +625,15 @@ unsigned int pci_scan_bus(struct bus *bus, dev->class = class >> 8; /* 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. + * 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); /* Error if we don't have some pci operations for it */ if (!dev->ops) { printk_err("%s No device operations\n", - dev_path(dev)); + dev_path(dev)); continue; } @@ -600,24 +646,28 @@ unsigned int pci_scan_bus(struct bus *bus, } printk_debug("%s [%04x/%04x] %s\n", - dev_path(dev), - dev->vendor, dev->device, - dev->enable?"enabled": "disabled"); + dev_path(dev), + dev->vendor, dev->device, + dev->enable?"enabled": "disabled"); if (PCI_FUNC(devfn) == 0x00 && (hdr_type & 0x80) != 0x80) { - /* if this is not a multi function device, don't waste time probe - another function. Skip to next device. */ + /* if this is not a multi function device, don't + * waste time probe another function. + * Skip to next device. */ devfn += 0x07; } } post_code(0x25); - for(child = bus->children; child; child = child->sibling) { + /* if the child provides scan_bus(), for example a bridge, scan the + * bus behind that child */ + for (child = bus->children; child; child = child->sibling) { if (!child->ops->scan_bus) { continue; } max = child->ops->scan_bus(child, max); } + /* * 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 @@ -630,8 +680,17 @@ unsigned int pci_scan_bus(struct bus *bus, return max; } -/** Scan the bus, first for bridges and next for devices. - * @param pci_bus pointer to the bus structure +/** + * @brief 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. + * + * This function is the default scan_bus() method for PCI bridge devices. + * + * @param dev pointer to the bridge device + * @param max the highest bus number assgined up to now + * * @return The maximum bus number found, after scanning all subordinate busses */ unsigned int pci_scan_bridge(struct device *dev, unsigned int max) @@ -645,47 +704,44 @@ unsigned int pci_scan_bridge(struct device *dev, unsigned int max) /* 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 - */ + * subordinate bus number to 0xff for the moment. */ bus->secondary = ++max; bus->subordinate = 0xff; - + /* Clear all status bits and turn off memory, I/O and master enables. */ cr = pci_read_config16(dev, PCI_COMMAND); pci_write_config16(dev, PCI_COMMAND, 0x0000); pci_write_config16(dev, PCI_STATUS, 0xffff); - /* - * Read the existing primary/secondary/subordinate bus - * number configuration. - */ + /* 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 * transactions will not be propagated by the bridge if it is not - * correctly configured - */ + * correctly configured */ buses &= 0xff000000; buses |= (((unsigned int) (dev->bus->secondary) << 0) | - ((unsigned int) (bus->secondary) << 8) | - ((unsigned int) (bus->subordinate) << 16)); + ((unsigned int) (bus->secondary) << 8) | + ((unsigned int) (bus->subordinate) << 16)); pci_write_config32(dev, PCI_PRIMARY_BUS, buses); - /* Now we can scan all subordinate buses i.e. the bus hehind the bridge */ + /* Now we can scan all subordinate buses i.e. the buses behind the + * bridge */ max = pci_scan_bus(bus, 0x00, 0xff, max); /* We know the number of buses behind this bridge. Set the subordinate - * bus number to its real value - */ + * bus number to its real value */ bus->subordinate = max; buses = (buses & 0xff00ffff) | ((unsigned int) (bus->subordinate) << 16); pci_write_config32(dev, PCI_PRIMARY_BUS, buses); pci_write_config16(dev, PCI_COMMAND, cr); - + printk_spew("%s returns max %d\n", __FUNCTION__, max); return max; } + /* Tell the EISA int controller this int must be level triggered THIS IS A KLUDGE -- sorry, this needs to get cleaned up. diff --git a/src/devices/root_device.c b/src/devices/root_device.c index 4a076a1bb..0bf5ea60a 100644 --- a/src/devices/root_device.c +++ b/src/devices/root_device.c @@ -21,9 +21,9 @@ void root_dev_read_resources(device_t root) root->resource[res].flags = IORESOURCE_IO; root->resource[res].index = 0; printk_spew("%s . link %p, resource %p\n", __FUNCTION__, - &root->link[0], &root->resource[res]); + &root->link[0], &root->resource[res]); compute_allocate_resource(&root->link[0], &root->resource[res], - IORESOURCE_IO, IORESOURCE_IO); + IORESOURCE_IO, IORESOURCE_IO); res++; /* Initialize the system wide memory resources constraints */ @@ -35,9 +35,9 @@ void root_dev_read_resources(device_t root) root->resource[res].flags = IORESOURCE_MEM; root->resource[res].index = 1; printk_spew("%s . link %p, resource %p\n", __FUNCTION__, - &root->link[0], &root->resource[res]); + &root->link[0], &root->resource[res]); compute_allocate_resource(&root->link[0], &root->resource[res], - IORESOURCE_MEM, IORESOURCE_MEM); + IORESOURCE_MEM, IORESOURCE_MEM); res++; root->resources = res; @@ -51,12 +51,12 @@ void root_dev_read_resources(device_t root) */ 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); + struct 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); assign_resources(bus); } @@ -71,18 +71,18 @@ unsigned int walk_static_devices(device_t bus, unsigned int max) { device_t child; unsigned link; - for(link = 0; link < bus->links; link++) { - for(child = bus->link[link].children; child; child = child->sibling) { + + for (link = 0; link < bus->links; link++) { + for (child = bus->link[link].children; child; child = child->sibling) { if (child->ops && child->ops->enable) { child->ops->enable(child); } - printk_debug("%s %s\n", - dev_path(child), - child->enable?"enabled": "disabled"); + printk_debug("%s %s\n", dev_path(child), + child->enable?"enabled": "disabled"); } } - for(link = 0; link < bus->links; link++) { - for(child = bus->link[link].children; child; child = child->sibling) { + for (link = 0; link < bus->links; link++) { + for (child = bus->link[link].children; child; child = child->sibling) { if (!child->ops || !child->ops->scan_bus) continue; printk_debug("%s scanning...\n", dev_path(child)); @@ -95,9 +95,9 @@ unsigned int walk_static_devices(device_t bus, unsigned int max) 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); } } diff --git a/src/include/device/device.h b/src/include/device/device.h index 20d9c2229..38efe53ad 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -46,6 +46,7 @@ struct device { unsigned short device; unsigned int class; /* 3 bytes: (base,sub,prog-if) */ unsigned int hdr_type; /* PCI header type */ + /* @todo rename this to 'enabled' */ unsigned int enable : 1; /* set if we should enable the device */ uint8_t command; diff --git a/src/include/device/pci.h b/src/include/device/pci.h index aa6778c50..ef18cb40e 100644 --- a/src/include/device/pci.h +++ b/src/include/device/pci.h @@ -28,7 +28,9 @@ struct pci_driver { }; #define __pci_driver __attribute__ ((unused,__section__(".rodata.pci_driver"))) +/** start of compile time generated pci driver array */ extern struct pci_driver pci_drivers[]; +/** end of compile time generated pci driver array */ extern struct pci_driver epci_drivers[]; diff --git a/src/mainboard/tyan/s2885/Config.lb b/src/mainboard/tyan/s2885/Config.lb index f30d6aa0c..7ff42d018 100644 --- a/src/mainboard/tyan/s2885/Config.lb +++ b/src/mainboard/tyan/s2885/Config.lb @@ -6,17 +6,19 @@ uses LB_CKS_RANGE_END uses LB_CKS_LOC uses MAINBOARD uses ARCH + # # ### ### Set all of the defaults for an x86 architecture ### + # # ### ### Build the objects we have code for in this directory. ### -##object mainboard.o + config chip.h register "fixup_scsi" = "1" register "fixup_vga" = "1" @@ -38,9 +40,10 @@ driver mainboard.o object reset.o if HAVE_MP_TABLE object mptable.o end if HAVE_PIRQ_TABLE object irq_tables.o end + # arch i386 end -#cpu k8 end + # ### ### Build our 16 bit and 32 bit linuxBIOS entry code @@ -50,6 +53,7 @@ mainboardinit cpu/i386/entry32.inc mainboardinit cpu/i386/bist32.inc ldscript /cpu/i386/entry16.lds ldscript /cpu/i386/entry32.lds + # ### ### Build our reset vector (This is where linuxBIOS is entered) @@ -120,24 +124,30 @@ end makerule ./failover.inc depends "./romcc ./failover.E" - action "./romcc -O -o failover.inc --label-prefix=failover ./failover.E"end + action "./romcc -O -o failover.inc --label-prefix=failover ./failover.E" +end makerule ./auto.E depends "$(MAINBOARD)/auto.c option_table.h" action "$(CPP) -I$(TOP)/src -I. $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/auto.c > ./auto.E" end + makerule ./auto.inc depends "./romcc ./auto.E" action "./romcc -O -mcpu=k8 -o auto.inc --label-prefix=auto ./auto.E" # action "./romcc -mcpu=k8 -O ./auto.E > auto.inc" end + mainboardinit cpu/k8/enable_mmx_sse.inc mainboardinit ./auto.inc mainboardinit cpu/k8/disable_mmx_sse.inc + # ### ### Include the secondary Configuration files ### +dir /pc80 + northbridge amd/amdk8 "mc0" pci 0:18.0 pci 0:18.0 @@ -203,7 +213,7 @@ northbridge amd/amdk8 "mc1" pci 0:19.2 pci 0:19.3 end - + dir /pc80 #dir /bioscall diff --git a/src/mainboard/via/epia/Config.lb b/src/mainboard/via/epia/Config.lb index 8fb365926..0450b2b1b 100644 --- a/src/mainboard/via/epia/Config.lb +++ b/src/mainboard/via/epia/Config.lb @@ -78,7 +78,8 @@ default HEAP_SIZE=0x4000 ## ## Only use the option table in a normal image ## -default USE_OPTION_TABLE = !USE_FALLBACK_IMAGE +#default USE_OPTION_TABLE = !USE_FALLBACK_IMAGE +default USE_OPTION_TABLE = 0 ## ## Compute the location and size of where this firmware image diff --git a/src/mainboard/via/epia/auto.c b/src/mainboard/via/epia/auto.c index 5981d3275..3e40d04e8 100644 --- a/src/mainboard/via/epia/auto.c +++ b/src/mainboard/via/epia/auto.c @@ -1,8 +1,5 @@ #define ASSEMBLY 1 -//#define MAXIMUM_CONSOLE_LOGLEVEL 6 -//#define DEFAULT_CONSOLE_LOGLEVEL 6 - #include #include #include @@ -15,6 +12,7 @@ #include "ram/ramtest.c" #include "northbridge/via/vt8601/raminit.h" #include "cpu/p6/earlymtrr.c" + /* */ void udelay(int usecs) diff --git a/src/northbridge/amd/amdk8/early_ht.c b/src/northbridge/amd/amdk8/early_ht.c index 90f258e1b..be7954553 100644 --- a/src/northbridge/amd/amdk8/early_ht.c +++ b/src/northbridge/amd/amdk8/early_ht.c @@ -16,8 +16,8 @@ static int enumerate_ht_chain(void) id = pci_read_config32(PCI_DEV(0,0,0), PCI_VENDOR_ID); /* If the chain is enumerated quit */ if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || - (((id >> 16) & 0xffff) == 0xffff) || - (((id >> 16) & 0xffff) == 0x0000)) { + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { break; } hdr_type = pci_read_config8(PCI_DEV(0,0,0), PCI_HEADER_TYPE); @@ -25,7 +25,7 @@ static int enumerate_ht_chain(void) hdr_type &= 0x7f; if ((hdr_type == PCI_HEADER_TYPE_NORMAL) || - (hdr_type == PCI_HEADER_TYPE_BRIDGE)) { + (hdr_type == PCI_HEADER_TYPE_BRIDGE)) { pos = pci_read_config8(PCI_DEV(0,0,0), PCI_CAPABILITY_LIST); } while(pos != 0) { diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c index 12d8f73c0..d63f41671 100644 --- a/src/northbridge/amd/amdk8/northbridge.c +++ b/src/northbridge/amd/amdk8/northbridge.c @@ -42,7 +42,7 @@ struct mem_range *sizeram(void) printk_debug("mmio_base: %dKB\n", mmio_basek); #endif - for(idx = i = 0; i < 8; i++) { + for (idx = i = 0; i < 8; i++) { uint32_t base, limit; unsigned basek, limitk, sizek; base = pci_read_config32(dev, 0x40 + (i<<3)); @@ -54,18 +54,18 @@ struct mem_range *sizeram(void) limitk = ((limit + 0x00010000) & 0xffff0000) >> 2; sizek = limitk - basek; if ((idx > 0) && - ((mem[idx -1].basek + mem[idx - 1].sizek) == basek)) { + ((mem[idx - 1].basek + mem[idx - 1].sizek) == basek)) { mem[idx -1].sizek += sizek; - } - else { + } else { mem[idx].basek = basek; mem[idx].sizek = sizek; idx++; } /* see if we need a hole from 0xa0000 to 0xbffff */ - if((mem[idx-1].basek < ((8*64)+(8*16))) && - (mem[idx-1].sizek > ((8*64)+(16*16)))) { + if ((mem[idx-1].basek < ((8*64)+(8*16))) /* 640 */ && + (mem[idx-1].sizek > ((8*64)+(16*16))) /* 768 */ ) { +#warning "FIXME: this left 0xA0000 to 0xBFFFF undefined" mem[idx].basek = (8*64)+(16*16); mem[idx].sizek = mem[idx-1].sizek - ((8*64)+(16*16)); mem[idx-1].sizek = ((8*64)+(8*16)) - mem[idx-1].basek; @@ -74,7 +74,7 @@ struct mem_range *sizeram(void) /* See if I need to split the region to accomodate pci memory space */ if ((mem[idx - 1].basek <= mmio_basek) && - ((mem[idx - 1].basek + mem[idx - 1].sizek) > mmio_basek)) { + ((mem[idx - 1].basek + mem[idx - 1].sizek) > mmio_basek)) { if (mem[idx - 1].basek < mmio_basek) { unsigned pre_sizek; pre_sizek = mmio_basek - mem[idx - 1].basek; @@ -92,10 +92,10 @@ struct mem_range *sizeram(void) } } } -#if 0 - for(i = 0; i < idx; i++) { +#if 1 + for (i = 0; i < idx; i++) { printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n", - i, mem[i].basek, i, mem[i].sizek); + i, mem[i].basek, i, mem[i].sizek); } #endif while(idx < sizeof(mem)/sizeof(mem[0])) { @@ -514,6 +514,40 @@ static void mcf0_control_init(struct device *dev) printk_debug("done.\n"); } + +static void amdk8_enable_resources(struct device *dev) +{ + uint16_t ctrl; + unsigned link; + unsigned int vgalink = -1; + + ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL); + ctrl |= dev->link[0].bridge_ctrl; + printk_debug("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl); + printk_err("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl); + pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl); + +#if 0 + /* let's see what link VGA is on */ + for(link = 0; link < dev->links; link++) { + device_t child; + printk_err("Kid %d of k8: bridge ctrl says: 0x%x\n", + link, dev->link[link].bridge_ctrl); + if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) + vgalink = link; + } + + if (vgalink != 1) { + /* now find the IOPAIR that goes to vgalink and set the vga enable in the base part (0x30) */ + /* now allocate an MMIOPAIR and point it to the CPU0, LINK=vgalink */ + /* now set IORR1 so it has a hole for the 0xa0000-0xcffff region */ + } +#endif + + pci_dev_enable_resources(dev); + //enable_childrens_resources(dev); +} + static struct device_operations northbridge_operations = { .read_resources = amdk8_read_resources, .set_resources = amdk8_set_resources, diff --git a/src/northbridge/amd/amdk8/raminit.c b/src/northbridge/amd/amdk8/raminit.c index e5bcb2d02..fac24d7be 100644 --- a/src/northbridge/amd/amdk8/raminit.c +++ b/src/northbridge/amd/amdk8/raminit.c @@ -5,10 +5,12 @@ #if (CONFIG_LB_MEM_TOPK & (CONFIG_LB_MEM_TOPK -1)) != 0 # error "CONFIG_LB_MEM_TOPK must be a power of 2" #endif + static void setup_resource_map(const unsigned int *register_values, int max) { int i; print_debug("setting up resource map...."); + #if 0 print_debug("\r\n"); #endif diff --git a/src/southbridge/amd/amd8111/amd8111.c b/src/southbridge/amd/amd8111/amd8111.c index d3fdf3b7b..ccf26b623 100644 --- a/src/southbridge/amd/amd8111/amd8111.c +++ b/src/southbridge/amd/amd8111/amd8111.c @@ -15,7 +15,7 @@ void amd8111_enable(device_t dev) /* See if we are on the behind the amd8111 pci bridge */ bus_dev = dev->bus->dev; if ((bus_dev->vendor == PCI_VENDOR_ID_AMD) && - (bus_dev->device == PCI_DEVICE_ID_AMD_8111_PCI)) { + (bus_dev->device == PCI_DEVICE_ID_AMD_8111_PCI)) { unsigned devfn; devfn = bus_dev->path.u.pci.devfn + (1 << 3); lpc_dev = dev_find_slot(bus_dev->bus->secondary, devfn); @@ -26,11 +26,12 @@ void amd8111_enable(device_t dev) lpc_dev = dev_find_slot(dev->bus->secondary, devfn); index = dev->path.u.pci.devfn & 7; } + if ((!lpc_dev) || (index >= 16)) { return; } if ((lpc_dev->vendor != PCI_VENDOR_ID_AMD) || - (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA)) { + (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA)) { uint32_t id; id = pci_read_config32(lpc_dev, PCI_VENDOR_ID); if (id != (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8111_ISA << 16))) { @@ -48,6 +49,6 @@ void amd8111_enable(device_t dev) } struct chip_control southbridge_amd_amd8111_control = { - .name = "AMD 8111", + .name = "AMD 8111 Southbridge", .enable_dev = amd8111_enable, }; -- 2.25.1