diff options
author | Eric Biederman <ebiederm@xmission.com> | 2004-10-14 20:54:17 +0000 |
---|---|---|
committer | Eric Biederman <ebiederm@xmission.com> | 2004-10-14 20:54:17 +0000 |
commit | b78c1972feed4c57eebba8f94de86a91e32c3fa7 (patch) | |
tree | 2ba60cfe9866f4d1e2de1d9727d0e548139afb35 | |
parent | cadfd4c462673bcb44cdb1f193e52c95a888762a (diff) |
- First pass through with with device tree enhancement merge. Most of the mechanisms should
be in place but don't expect anything to quite work yet.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1662 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
52 files changed, 1714 insertions, 1769 deletions
diff --git a/src/arch/i386/boot/linuxbios_table.c b/src/arch/i386/boot/linuxbios_table.c index 3b14488de8..5b7431479b 100644 --- a/src/arch/i386/boot/linuxbios_table.c +++ b/src/arch/i386/boot/linuxbios_table.c @@ -5,6 +5,8 @@ #include "linuxbios_table.h" #include <string.h> #include <version.h> +#include <device/device.h> +#include <stdlib.h> struct lb_header *lb_table_init(unsigned long addr) @@ -217,18 +219,75 @@ struct lb_memory *get_lb_mem(void) return mem_ranges; } +struct mem_range *sizeram(void) +{ + struct mem_range *mem, *rmem; + struct device *dev; + unsigned int count; + count = 0; + for(dev = all_devices; dev; dev = dev->next) { + struct resource *res, *last; + last = &dev->resource[dev->resources]; + for(res = &dev->resource[0]; res < last; res++) { + if ((res->flags & IORESOURCE_MEM) && + (res->flags & IORESOURCE_CACHEABLE)) + { + count++; + } + } + } + rmem = mem = malloc(sizeof(*mem) * (count + 1)); + for(dev = all_devices; dev; dev = dev->next) { + struct resource *res, *last; + last = &dev->resource[dev->resources]; + for(res = &dev->resource[0]; res < last; res++) { + if ((res->flags & IORESOURCE_MEM) && + (res->flags & IORESOURCE_CACHEABLE)) + { + mem->basek = res->base >> 10; + mem->sizek = res->size >> 10; + mem++; + } + } + } + mem->basek = 0; + mem->sizek = 0; +#if 0 + for(mem = rmem; mem->sizek; mem++) { + printk_debug("basek: %lu sizek: %lu\n", + mem->basek, mem->sizek); + } +#endif + return rmem; +} + +static struct mem_range *get_ramsize(void) +{ + struct mem_range *mem = 0; + if (!mem) { + mem = sizeram(); + } + if (!mem) { + printk_emerg("No memory size information!\n"); + for(;;) { + /* Ensure this loop is not optimized away */ + asm volatile("":/* outputs */:/*inputs */ :"memory"); + } + } + return mem; +} + unsigned long write_linuxbios_table( - unsigned long *processor_map, - struct mem_range *ram, unsigned long low_table_start, unsigned long low_table_end, unsigned long rom_table_startk, unsigned long rom_table_endk) { unsigned long table_size; - struct mem_range *ramp; + struct mem_range *ram, *ramp; struct lb_header *head; struct lb_memory *mem; struct lb_record *rec_dest, *rec_src; + ram = get_ramsize(); head = lb_table_init(low_table_end); low_table_end = (unsigned long)head; #if HAVE_OPTION_TABLE == 1 diff --git a/src/arch/i386/boot/linuxbios_table.h b/src/arch/i386/boot/linuxbios_table.h index 42c0a07dac..d15e1c722a 100644 --- a/src/arch/i386/boot/linuxbios_table.h +++ b/src/arch/i386/boot/linuxbios_table.h @@ -3,12 +3,8 @@ #include <boot/linuxbios_tables.h> -struct mem_range; - /* This file holds function prototypes for building the linuxbios table. */ unsigned long write_linuxbios_table( - unsigned long *processor_map, - struct mem_range *ram, unsigned long low_table_start, unsigned long low_table_end, unsigned long rom_table_start, unsigned long rom_table_end); diff --git a/src/arch/i386/boot/tables.c b/src/arch/i386/boot/tables.c index 18e271db8c..b148abd1c2 100644 --- a/src/arch/i386/boot/tables.c +++ b/src/arch/i386/boot/tables.c @@ -1,39 +1,13 @@ #include <console/console.h> -#include <mem.h> #include <cpu/cpu.h> #include <boot/tables.h> #include <boot/linuxbios_tables.h> #include <arch/pirq_routing.h> #include <arch/smp/mpspec.h> #include <arch/acpi.h> -#include <pc80/mc146818rtc.h> #include "linuxbios_table.h" -#if CONFIG_SMP && CONFIG_MAX_PHYSICAL_CPUS && (CONFIG_MAX_PHYSICAL_CPUS < CONFIG_MAX_CPUS) -static void remove_logical_cpus(unsigned long *processor_map) -{ - /* To turn off hyperthreading just remove the logical - * cpus from the processor map. - */ - int disable_logical_cpus = !CONFIG_LOGICAL_CPUS; - if (get_option(&disable_logical_cpus,"hyper_threading")) { - disable_logical_cpus = !CONFIG_LOGICAL_CPUS; - } - if (disable_logical_cpus) { - /* disable logical cpus */ - int cnt; - for(cnt=CONFIG_MAX_PHYSICAL_CPUS;cnt<CONFIG_MAX_CPUS;cnt++) - processor_map[cnt]=0; - printk_debug("logical cpus disabled\n"); - } -} -#else - -#define remove_logical_cpus(processor_map) do {} while(0) - -#endif /* CONFIG_SMP && CONFIG_MAX_PHYSICAL_CPUS */ - -struct lb_memory *write_tables(struct mem_range *mem, unsigned long *processor_map) +struct lb_memory *write_tables(void) { unsigned long low_table_start, low_table_end; unsigned long rom_table_start, rom_table_end; @@ -56,8 +30,7 @@ struct lb_memory *write_tables(struct mem_range *mem, unsigned long *processor_m post_code(0x96); /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ - remove_logical_cpus(processor_map); - low_table_end = write_smp_table(low_table_end, processor_map); + low_table_end = write_smp_table(low_table_end); /* Write ACPI tables */ /* write them in the rom area because DSDT can be large (8K on epia-m) which @@ -73,7 +46,7 @@ struct lb_memory *write_tables(struct mem_range *mem, unsigned long *processor_m } /* The linuxbios table must be in 0-4K or 960K-1M */ - write_linuxbios_table(processor_map, mem, + write_linuxbios_table( low_table_start, low_table_end, rom_table_start >> 10, rom_table_end >> 10); diff --git a/src/arch/i386/include/arch/hlt.h b/src/arch/i386/include/arch/hlt.h index 86ed7c8f41..7d3a563734 100644 --- a/src/arch/i386/include/arch/hlt.h +++ b/src/arch/i386/include/arch/hlt.h @@ -9,7 +9,7 @@ static void hlt(void) #endif -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(__ROMCC__) static inline void hlt(void) { asm("hlt"); diff --git a/src/arch/i386/include/arch/romcc_io.h b/src/arch/i386/include/arch/romcc_io.h index 0d5f071428..80037bd7ad 100644 --- a/src/arch/i386/include/arch/romcc_io.h +++ b/src/arch/i386/include/arch/romcc_io.h @@ -191,6 +191,11 @@ static inline void pnp_set_iobase(device_t dev, unsigned index, unsigned iobase) pnp_write_config(dev, index + 1, iobase & 0xff); } +static inline uint16_t pnp_read_iobase(device_t dev, unsigned index) +{ + return (uint16_t)((pnp_read_config(dev, index) << 8) | pnp_read_config(dev, index + 1)); +} + static inline void pnp_set_irq(device_t dev, unsigned index, unsigned irq) { pnp_write_config(dev, index, irq); diff --git a/src/arch/i386/include/arch/smp/lapic.h b/src/arch/i386/include/arch/smp/lapic.h deleted file mode 100644 index 0ac87aa2d3..0000000000 --- a/src/arch/i386/include/arch/smp/lapic.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef ARCH_SMP_LAPIC_H -#define ARCH_SMP_LAPIC_H - -#include <cpu/p6/msr.h> -#include <cpu/p6/apic.h> -#include <arch/hlt.h> - -static void enable_lapic(void) -{ - - msr_t msr; - msr = rdmsr(0x1b); - msr.hi &= 0xffffff00; - msr.lo &= 0x000007ff; - msr.lo |= APIC_DEFAULT_BASE | (1 << 11); - wrmsr(0x1b, msr); -} - -static void disable_lapic(void) -{ - msr_t msr; - msr = rdmsr(0x1b); - msr.lo &= ~ (1 << 11); - wrmsr(0x1b, msr); -} - -static inline unsigned long lapicid(void) -{ - return apic_read(APIC_ID) >> 24; -} - -static void stop_this_cpu(void) -{ - unsigned apicid; - apicid = lapicid(); - - /* Send an APIC INIT to myself */ - apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT); - /* Wait for the ipi send to finish */ - apic_wait_icr_idle(); - - /* Deassert the APIC INIT */ - apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); - /* Wait for the ipi send to finish */ - apic_wait_icr_idle(); - - /* If I haven't halted spin forever */ - for(;;) { - hlt(); - } -} - -#endif /* ARCH_SMP_LAPIC_H */ diff --git a/src/arch/i386/include/arch/smp/mpspec.h b/src/arch/i386/include/arch/smp/mpspec.h index 66232c921d..9f22b7f4af 100644 --- a/src/arch/i386/include/arch/smp/mpspec.h +++ b/src/arch/i386/include/arch/smp/mpspec.h @@ -238,8 +238,7 @@ void smp_write_processor(struct mp_config_table *mc, unsigned char apicid, unsigned char apicver, unsigned char cpuflag, unsigned int cpufeature, unsigned int featureflag); -void smp_write_processors(struct mp_config_table *mc, - unsigned long *processor_map); +void smp_write_processors(struct mp_config_table *mc); void smp_write_bus(struct mp_config_table *mc, unsigned char id, unsigned char *bustype); void smp_write_ioapic(struct mp_config_table *mc, @@ -265,18 +264,15 @@ void smp_write_compatibility_address_space(struct mp_config_table *mc, unsigned int range_list); unsigned char smp_compute_checksum(void *v, int len); void *smp_write_floating_table(unsigned long addr); -unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map); +unsigned long write_smp_table(unsigned long addr); #else /* HAVE_MP_TABLE */ static inline -unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map) +unsigned long write_smp_table(unsigned long addr); { return addr; } #endif /* HAVE_MP_TABLE */ -/* A table (per mainboard) listing the initial apicid of each cpu. */ -extern unsigned long initial_apicid[CONFIG_MAX_CPUS]; - #endif diff --git a/src/arch/i386/include/arch/smp/spinlock.h b/src/arch/i386/include/arch/smp/spinlock.h index d0cc11c6a7..65ad8d0673 100644 --- a/src/arch/i386/include/arch/smp/spinlock.h +++ b/src/arch/i386/include/arch/smp/spinlock.h @@ -54,4 +54,10 @@ static inline void spin_unlock(spinlock_t *lock) :"=m" (lock->lock) : : "memory"); } +/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ +static inline void cpu_relax(void) +{ + __asm__ __volatile__("rep;nop": : :"memory"); +} + #endif /* ARCH_SMP_SPINLOCK_H */ diff --git a/src/arch/i386/include/stddef.h b/src/arch/i386/include/stddef.h index 4bf6b0a867..e4fc019c87 100644 --- a/src/arch/i386/include/stddef.h +++ b/src/arch/i386/include/stddef.h @@ -8,7 +8,7 @@ typedef long ssize_t; typedef int wchar_t; typedef unsigned int wint_t; -#define NULL 0 +#define NULL ((void *)0) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) diff --git a/src/arch/i386/include/stdint.h b/src/arch/i386/include/stdint.h index 0fc4346317..76bd89a354 100644 --- a/src/arch/i386/include/stdint.h +++ b/src/arch/i386/include/stdint.h @@ -1,7 +1,7 @@ #ifndef I386_STDINT_H #define I386_STDINT_H -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__ROMCC__) #define __HAVE_LONG_LONG__ 1 #else #define __HAVE_LONG_LONG__ 0 diff --git a/src/arch/i386/lib/c_start.S b/src/arch/i386/lib/c_start.S index 47fb64588c..c82da2f76e 100644 --- a/src/arch/i386/lib/c_start.S +++ b/src/arch/i386/lib/c_start.S @@ -1,8 +1,5 @@ #include <arch/asm.h> #include <arch/intel.h> -#if CONFIG_SMP==1 -#include <cpu/p6/apic.h> -#endif .section ".text" .code32 .globl _start @@ -39,27 +36,10 @@ _start: /* set new stack */ movl $_estack, %esp -#if CONFIG_SMP==1 - /* Get the cpu id */ - movl $APIC_DEFAULT_BASE, %edi - movl APIC_ID(%edi), %eax - shrl $24, %eax - - /* Get the cpu index (CONFIG_MAX_CPUS on error) */ - movl $-4, %ebx -1: addl $4, %ebx - cmpl $(CONFIG_MAX_CPUS << 2), %ebx - je 2 - cmpl %eax, initial_apicid(%ebx) - jne 1b -2: shrl $2, %ebx - - /* Now compute the appropriate stack */ - movl %ebx, %eax - movl $STACK_SIZE, %ebx - mull %ebx - subl %eax, %esp -#endif + + /* Push the cpu index and struct cpu */ + pushl $0 + pushl $0 /* push the boot_complete flag */ pushl %ebp @@ -74,7 +54,7 @@ _start: */ intel_chip_post_macro(0xfe) /* post fe */ - /* Resort the stack location */ + /* Restore the stack location */ movl %ebp, %esp /* The boot_complete flag has already been pushed */ diff --git a/src/arch/i386/lib/console.c b/src/arch/i386/lib/console.c index f3594e9786..76f4f16e01 100644 --- a/src/arch/i386/lib/console.c +++ b/src/arch/i386/lib/console.c @@ -118,21 +118,18 @@ static void print_spew_hex16(unsigned short value){ __console_tx_hex16(BIOS_SPEW static void print_spew_hex32(unsigned int value) { __console_tx_hex32(BIOS_SPEW, value); } static void print_spew(const char *str) { __console_tx_string(BIOS_SPEW, str); } -#define __STR(X) #X -#define STR(X) __STR(X) - #ifndef LINUXBIOS_EXTRA_VERSION -#define LINUXBIOS_EXTRA_VERSION +#define LINUXBIOS_EXTRA_VERSION "" #endif static void console_init(void) { static const char console_test[] = "\r\n\r\nLinuxBIOS-" - STR(LINUXBIOS_VERSION) - STR(LINUXBIOS_EXTRA_VERSION) + LINUXBIOS_VERSION + LINUXBIOS_EXTRA_VERSION " " - STR(LINUXBIOS_BUILD) + LINUXBIOS_BUILD " starting...\r\n"; print_info(console_test); } diff --git a/src/arch/i386/lib/console.inc b/src/arch/i386/lib/console.inc index b617b8c1d0..be7df6af16 100644 --- a/src/arch/i386/lib/console.inc +++ b/src/arch/i386/lib/console.inc @@ -2,11 +2,8 @@ jmp console0 -#define __STR(X) #X -#define STR(X) __STR(X) - #ifndef LINUXBIOS_EXTRA_VERSION -#define LINUXBIOS_EXTRA_VERSION +#define LINUXBIOS_EXTRA_VERSION "" #endif #ifndef ASM_CONSOLE_LOGLEVEL @@ -14,13 +11,12 @@ jmp console0 #endif console_test: .ascii "\r\n\r\nLinuxBIOS-" - .ascii STR(LINUXBIOS_VERSION) - .ascii STR(LINUXBIOS_EXTRA_VERSION) + .ascii LINUXBIOS_VERSION + .ascii LINUXBIOS_EXTRA_VERSION .ascii " " - .ascii STR(LINUXBIOS_BUILD) + .ascii LINUXBIOS_BUILD .asciz " starting...\r\n" -#undef STR /* uses: ax, dx */ #if CONFIG_CONSOLE_SERIAL8250 #define __CONSOLE_INLINE_TX_AL TTYS0_TX_AL diff --git a/src/arch/i386/lib/cpu.c b/src/arch/i386/lib/cpu.c index 23c35bc816..74db2e81f8 100644 --- a/src/arch/i386/lib/cpu.c +++ b/src/arch/i386/lib/cpu.c @@ -1,147 +1,252 @@ #include <console/console.h> #include <cpu/cpu.h> -#include <mem.h> #include <arch/io.h> #include <string.h> -#include <cpu/cpufixup.h> -#include <smp/start_stop.h> -#include <cpu/cpufixup.h> -#include <cpu/p6/mtrr.h> -#include <cpu/p6/msr.h> -#include <cpu/p6/apic.h> -#include <cpu/p5/cpuid.h> -#include <arch/smp/lapic.h> -#if 0 -#include <cpu/l2_cache.h> -#endif - -#if CONFIG_SMP || CONFIG_IOAPIC -#define APIC 1 -#endif - - -static void cache_on(struct mem_range *mem) +#include <cpu/x86/mtrr.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/lapic.h> +#include <arch/cpu.h> +#include <device/path.h> +#include <device/device.h> +#include <smp/spinlock.h> + +/* Standard macro to see if a specific flag is changeable */ +static inline int flag_is_changeable_p(uint32_t flag) { - post_code(0x60); - printk_info("Enabling cache..."); - - - /* we need an #ifdef i586 here at some point ... */ - __asm__ __volatile__("mov %cr0, %eax\n\t" - "and $0x9fffffff,%eax\n\t" - "mov %eax, %cr0\n\t"); - /* turns out cache isn't really on until you set MTRR registers on - * 686 and later. - * NOTHING FANCY. Linux does a much better job anyway. - * so absolute minimum needed to get it going. - */ - /* OK, linux it turns out does nothing. We have to do it ... */ -#if i686==1 - // totalram here is in linux sizing, i.e. units of KB. - // set_mtrr is responsible for getting it into the right units! - setup_mtrrs(mem); -#endif - - post_code(0x6A); - printk_info("done.\n"); + uint32_t f1, f2; + + asm( + "pushfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "movl %0,%1\n\t" + "xorl %2,%0\n\t" + "pushl %0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "popfl\n\t" + : "=&r" (f1), "=&r" (f2) + : "ir" (flag)); + return ((f1^f2) & flag) != 0; } -static void interrupts_on() + +/* Probe for the CPUID instruction */ +static int have_cpuid_p(void) { - /* this is so interrupts work. This is very limited scope -- - * linux will do better later, we hope ... - */ - /* this is the first way we learned to do it. It fails on real SMP - * stuff. So we have to do things differently ... - * see the Intel mp1.4 spec, page A-3 - */ + return flag_is_changeable_p(X86_EFLAGS_ID); +} + +/* + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected + * by the fact that they preserve the flags across the division of 5/2. + * PII and PPro exhibit this behavior too, but they have cpuid available. + */ + +/* + * Perform the Cyrix 5/2 test. A Cyrix won't change + * the flags, while other 486 chips will. + */ +static inline int test_cyrix_52div(void) +{ + unsigned int test; + + __asm__ __volatile__( + "sahf\n\t" /* clear flags (%eax = 0x0005) */ + "div %b2\n\t" /* divide 5 by 2 */ + "lahf" /* store flags into %ah */ + : "=a" (test) + : "0" (5), "q" (2) + : "cc"); + + /* AH is 0x02 on Cyrix after the divide.. */ + return (unsigned char) (test >> 8) == 0x02; +} -#if defined(APIC) - /* Only Pentium Pro and later have those MSR stuff */ - msr_t msr; +/* + * Detect a NexGen CPU running without BIOS hypercode new enough + * to have CPUID. (Thanks to Herbert Oppmann) + */ + +static int deep_magic_nexgen_probe(void) +{ + int ret; + + __asm__ __volatile__ ( + " movw $0x5555, %%ax\n" + " xorw %%dx,%%dx\n" + " movw $2, %%cx\n" + " divw %%cx\n" + " movl $0, %%eax\n" + " jnz 1f\n" + " movl $1, %%eax\n" + "1:\n" + : "=a" (ret) : : "cx", "dx" ); + return ret; +} - printk_info("Setting up local apic..."); +/* List of cpu vendor strings along with their normalized + * id values. + */ +static struct { + int vendor; + const char *name; +} x86_vendors[] = { + { X86_VENDOR_INTEL, "GenuineIntel", }, + { X86_VENDOR_CYRIX, "CyrixInstead", }, + { X86_VENDOR_AMD, "AuthenticAMD", }, + { X86_VENDOR_UMC, "UMC UMC UMC ", }, + { X86_VENDOR_NEXGEN, "NexGenDriven", }, + { X86_VENDOR_CENTAUR, "CentaurHauls", }, + { X86_VENDOR_RISE, "RiseRiseRise", }, + { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, + { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, + { X86_VENDOR_NSC, "Geode by NSC", }, + { X86_VENDOR_SIS, "SiS SiS SiS ", }, +}; + +static const char *x86_vendor_name[] = { + [X86_VENDOR_INTEL] = "Intel", + [X86_VENDOR_CYRIX] = "Cyrix", + [X86_VENDOR_AMD] = "AMD", + [X86_VENDOR_UMC] = "UMC", + [X86_VENDOR_NEXGEN] = "NexGen", + [X86_VENDOR_CENTAUR] = "Centaur", + [X86_VENDOR_RISE] = "Rise", + [X86_VENDOR_TRANSMETA] = "Transmeta", + [X86_VENDOR_NSC] = "NSC", + [X86_VENDOR_SIS] = "SiS", +}; + +static const char *cpu_vendor_name(int vendor) +{ + const char *name; + name = "<invalid cpu vendor>"; + if ((vendor < (sizeof(x86_vendor_name)/sizeof(x86_vendor_name[0]))) && + (x86_vendor_name[vendor] != 0)) + { + name = x86_vendor_name[vendor]; + } + return name; +} - /* Enable the local apic */ - msr = rdmsr(APIC_BASE_MSR); - msr.lo |= APIC_BASE_MSR_ENABLE; - msr.lo &= ~APIC_BASE_MSR_ADDR_MASK; - msr.lo |= APIC_DEFAULT_BASE; - wrmsr(APIC_BASE_MSR, msr); +static void identify_cpu(struct device *cpu) +{ + char vendor_name[16]; + int cpuid_level; + int i; + + vendor_name[0] = '\0'; /* Unset */ + cpuid_level = -1; /* Maximum supported CPUID level, -1=no CPUID */ + + /* Find the id and vendor_name */ + if (!have_cpuid_p()) { + /* Its a 486 if we can modify the AC flag */ + if (flag_is_changeable_p(X86_EFLAGS_AC)) { + cpu->device = 0x00000400; /* 486 */ + } else { + cpu->device = 0x00000300; /* 386 */ + } + if ((cpu->device == 0x00000400) && test_cyrix_52div()) { + memcpy(vendor_name, "CyrixInstead", 13); + /* If we ever care we can enable cpuid here */ + } + /* Detect NexGen with old hypercode */ + else if (deep_magic_nexgen_probe()) { + memcpy(vendor_name, "NexGenDriven", 13); + } + } + if (have_cpuid_p()) { + struct cpuid_result result; + result = cpuid(0x00000000); + cpuid_level = result.eax; + vendor_name[ 0] = (result.ebx >> 0) & 0xff; + vendor_name[ 1] = (result.ebx >> 8) & 0xff; + vendor_name[ 2] = (result.ebx >> 16) & 0xff; + vendor_name[ 3] = (result.ebx >> 24) & 0xff; + vendor_name[ 4] = (result.edx >> 0) & 0xff; + vendor_name[ 5] = (result.edx >> 8) & 0xff; + vendor_name[ 6] = (result.edx >> 16) & 0xff; + vendor_name[ 7] = (result.edx >> 24) & 0xff; + vendor_name[ 8] = (result.ecx >> 0) & 0xff; + vendor_name[ 9] = (result.ecx >> 8) & 0xff; + vendor_name[10] = (result.ecx >> 16) & 0xff; + vendor_name[11] = (result.ecx >> 24) & 0xff; + vendor_name[12] = '\0'; + + /* Intel-defined flags: level 0x00000001 */ + if (cpuid_level >= 0x00000001) { + cpu->device = cpuid_eax(0x00000001); + } + else { + /* Have CPUID level 0 only unheard of */ + cpu->device = 0x00000400; + } + } + cpu->vendor = X86_VENDOR_UNKNOWN; + for(i = 0; i < sizeof(x86_vendors)/sizeof(x86_vendors[0]); i++) { + if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) { + cpu->vendor = x86_vendors[i].vendor; + break; + } + } +} - /* - * Set Task Priority to 'accept all'. - */ - apic_write_around(APIC_TASKPRI, - apic_read_around(APIC_TASKPRI) & ~APIC_TPRI_MASK); - - /* Put the local apic in virtual wire mode */ - apic_write_around(APIC_SPIV, - (apic_read_around(APIC_SPIV) & ~(APIC_VECTOR_MASK)) - | APIC_SPIV_ENABLE); - apic_write_around(APIC_LVT0, - (apic_read_around(APIC_LVT0) & - ~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER | - APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY | - APIC_SEND_PENDING |APIC_LVT_RESERVED_1 | - APIC_DELIVERY_MODE_MASK)) - | (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING | - APIC_DELIVERY_MODE_EXTINT) - ); - apic_write_around(APIC_LVT1, - (apic_read_around(APIC_LVT1) & - ~(APIC_LVT_MASKED | APIC_LVT_LEVEL_TRIGGER | - APIC_LVT_REMOTE_IRR | APIC_INPUT_POLARITY | - APIC_SEND_PENDING |APIC_LVT_RESERVED_1 | - APIC_DELIVERY_MODE_MASK)) - | (APIC_LVT_REMOTE_IRR |APIC_SEND_PENDING | - APIC_DELIVERY_MODE_NMI) - ); - - printk_debug(" apic_id: %d ", lapicid()); - -#else /* APIC */ -#if i686==1 - /* Only Pentium Pro and later have those MSR stuff */ - msr_t msr; - - printk_info("Disabling local apic..."); - - msr = rdmsr(APIC_BASE_MSR); - msr.lo &= ~APIC_BASE_MSR_ENABLE; - wrmsr(APIC_BASE_MSR, msr); -#endif /* i686 */ -#endif /* APIC */ - printk_info("done.\n"); - post_code(0x9b); +static void set_cpu_ops(struct device *cpu) +{ + struct cpu_driver *driver; + cpu->ops = 0; + for (driver = cpu_drivers; driver < ecpu_drivers; driver++) { + struct cpu_device_id *id; + for(id = driver->id_table; id->vendor != X86_VENDOR_INVALID; id++) { + if ((cpu->vendor == id->vendor) && + (cpu->device == id->device)) + { + goto found; + } + } + } + die("Unknown cpu"); + return; + found: + cpu->ops = driver->ops; } -unsigned long cpu_initialize(struct mem_range *mem) +void cpu_initialize(void) { /* Because we busy wait at the printk spinlock. * It is important to keep the number of printed messages * from secondary cpus to a minimum, when debugging is * disabled. */ - unsigned long processor_id = this_processors_id(); - printk_notice("Initializing CPU #%d\n", processor_id); - - /* Turn on caching if we haven't already */ - cache_on(mem); -#if i586==1 - display_cpuid(); -#endif -#if i686==1 - mtrr_check(); -#endif - - /* some cpus need a fixup done. This is the hook for doing that. */ - cpufixup(mem); - - interrupts_on(); - - processor_id = this_processors_id(); - printk_info("CPU #%d Initialized\n", processor_id); - return processor_id; + struct device *cpu; + struct cpu_info *info; + info = cpu_info(); + + printk_notice("Initializing CPU #%d\n", info->index); + + cpu = info->cpu; + if (!cpu) { + die("CPU: missing cpu device structure"); + } + + /* Find what type of cpu we are dealing with */ + identify_cpu(cpu); + printk_debug("CPU: vendor %s device %x\n", + cpu_vendor_name(cpu->vendor), cpu->device); + + /* Lookup the cpu's operations */ + set_cpu_ops(cpu); + + /* Initialize the cpu */ + if (cpu->ops && cpu->ops->init) { + cpu->enabled = 1; + cpu->initialized = 1; + cpu->ops->init(cpu); + } + + printk_info("CPU #%d Initialized\n", info->index); + return; } diff --git a/src/arch/i386/lib/id.inc b/src/arch/i386/lib/id.inc index f28e23a2e8..44c452b03a 100644 --- a/src/arch/i386/lib/id.inc +++ b/src/arch/i386/lib/id.inc @@ -1,21 +1,16 @@ - .section ".id", "a", @progbits -#define __STR(X) #X -#define STR(X) __STR(X) + .section ".id", "a", @progbits .globl __id_start __id_start: vendor: - .asciz STR(MAINBOARD_VENDOR) + .asciz MAINBOARD_VENDOR part: - .asciz STR(MAINBOARD_PART_NUMBER) + .asciz MAINBOARD_PART_NUMBER .long __id_end + 0x10 - vendor /* Reverse offset to the vendor id */ .long __id_end + 0x10 - part /* Reverse offset to the part number */ .long PAYLOAD_SIZE + ROM_IMAGE_SIZE /* Size of this romimage */ .globl __id_end -#undef __STR -#undef STR - __id_end: .previous diff --git a/src/arch/i386/smp/Config.lb b/src/arch/i386/smp/Config.lb index d1e365c073..b41f5c295e 100644 --- a/src/arch/i386/smp/Config.lb +++ b/src/arch/i386/smp/Config.lb @@ -1,12 +1,8 @@ uses HAVE_MP_TABLE -uses CONFIG_SMP if HAVE_MP_TABLE object mpspec.o end #object ioapic.o CONFIG_IOAPIC -if CONFIG_SMP - object start_stop.o - object secondary.S -end + diff --git a/src/arch/i386/smp/mpspec.c b/src/arch/i386/smp/mpspec.c index 4a1e233be9..babfcbdca2 100644 --- a/src/arch/i386/smp/mpspec.c +++ b/src/arch/i386/smp/mpspec.c @@ -1,10 +1,9 @@ #include <console/console.h> #include <cpu/cpu.h> -#include <smp/start_stop.h> #include <arch/smp/mpspec.h> #include <string.h> -#include <cpu/p5/cpuid.h> -#include <cpu/p6/apic.h> +#include <arch/cpu.h> +#include <cpu/x86/lapic.h> unsigned char smp_compute_checksum(void *v, int len) { @@ -94,30 +93,33 @@ void smp_write_processor(struct mp_config_table *mc, * Having the proper apicid's in the table so the non-bootstrap * processors can be woken up should be enough. */ -void smp_write_processors(struct mp_config_table *mc, - unsigned long *processor_map) +void smp_write_processors(struct mp_config_table *mc) { - int i; - int processor_id; + int boot_apic_id; unsigned apic_version; unsigned cpu_features; unsigned cpu_feature_flags; - int eax, ebx, ecx, edx; - processor_id = this_processors_id(); - apic_version = apic_read(APIC_LVR) & 0xff; - cpuid(1, &eax, &ebx, &ecx, &edx); - cpu_features = eax; - cpu_feature_flags = edx; - for(i = 0; i < CONFIG_MAX_CPUS; i++) { - unsigned long cpu_apicid = initial_apicid[i]; + struct cpuid_result result; + device_t cpu; + boot_apic_id = lapicid(); + apic_version = lapic_read(LAPIC_LVR) & 0xff; + result = cpuid(1); + cpu_features = result.eax; + cpu_feature_flags = result.edx; + for(cpu = dev_root.link[1].children; cpu; cpu = cpu->sibling) { unsigned long cpu_flag; - if(initial_apicid[i]==-1) + if (cpu->path.type != DEVICE_PATH_APIC) { + continue; + } + if (!cpu->enabled) { continue; + } cpu_flag = MPC_CPU_ENABLED; - if (processor_map[i] & CPU_BOOTPROCESSOR) { - cpu_flag |= MPC_CPU_BOOTPROCESSOR; + if (boot_apic_id == cpu->path.u.apic.apic_id) { + cpu_flag = MPC_CPU_ENABLED; } - smp_write_processor(mc, cpu_apicid, apic_version, + smp_write_processor(mc, + cpu->path.u.apic.apic_id, apic_version, cpu_flag, cpu_features, cpu_feature_flags ); } @@ -136,8 +138,8 @@ void smp_write_bus(struct mp_config_table *mc, } void smp_write_ioapic(struct mp_config_table *mc, - unsigned char id, unsigned char ver, - unsigned long apicaddr) + unsigned char id, unsigned char ver, + unsigned long apicaddr) { struct mpc_config_ioapic *mpc; mpc = smp_next_mpc_entry(mc); diff --git a/src/arch/i386/smp/secondary.S b/src/arch/i386/smp/secondary.S deleted file mode 100644 index c27d6282b0..0000000000 --- a/src/arch/i386/smp/secondary.S +++ /dev/null @@ -1,76 +0,0 @@ -#include <arch/asm.h> -#include <arch/intel.h> -#include <cpu/p6/mtrr.h> -#include <cpu/p6/apic.h> - .text - .globl _secondary_start - .balign 4096 -_secondary_start: - .code16 - cli - xorl %eax, %eax - movl %eax, %cr3 /* Invalidate TLB*/ - - /* On hyper threaded cpus invalidating the cache here is - * very very bad. Don't. - */ - - /* setup the data segment */ - movw %cs, %ax - movw %ax, %ds - - data32 lgdt gdtaddr - _secondary_start - - movl %cr0, %eax - andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ - orl $0x60000001, %eax /* CD, NW, PE = 1 */ - movl %eax, %cr0 - - ljmpl $0x10, $1f -1: - .code32 - movw $0x18, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - movw %ax, %fs - movw %ax, %gs - - /* Enable the local apic, and map it where we expext it */ - movl $APIC_BASE_MSR, %ecx - rdmsr - orl $APIC_BASE_MSR_ENABLE, %eax - andl $(~APIC_BASE_MSR_ADDR_MASK), %eax - orl $APIC_DEFAULT_BASE, %eax - wrmsr - - /* Get the apic_id */ - movl (APIC_ID + APIC_DEFAULT_BASE), %edi - shrl $24, %edi - - /* Get the cpu index (CONFIG_MAX_CPUS on error) */ - movl $-4, %ebx -1: addl $4, %ebx - cmpl $(CONFIG_MAX_CPUS << 2), %ebx - je 2 - cmpl %edi, initial_apicid(%ebx) - jne 1b -2: shrl $2, %ebx - - /* set the stack pointer */ - movl $_estack, %esp - movl %ebx, %eax - movl $STACK_SIZE, %ebx - mull %ebx - subl %eax, %esp - - call secondary_cpu_init -1: hlt - jmp 1b - -gdtaddr: - .word gdt_limit /* the table limit */ - .long gdt /* we know the offset */ - - -.code32 diff --git a/src/arch/i386/smp/start_stop.c b/src/arch/i386/smp/start_stop.c deleted file mode 100644 index bf26437984..0000000000 --- a/src/arch/i386/smp/start_stop.c +++ /dev/null @@ -1,240 +0,0 @@ -#include <smp/start_stop.h> -#include <arch/smp/mpspec.h> -#include <cpu/p6/apic.h> -#include <delay.h> -#include <string.h> -#include <console/console.h> -#include <arch/smp/lapic.h> -#include <arch/hlt.h> - - -unsigned long this_processors_id(void) -{ - return lapicid(); -} - -int processor_index(unsigned long apicid) -{ - int i; - for(i = 0; i < CONFIG_MAX_CPUS; i++) { - if (initial_apicid[i] == apicid) { - return i; - } - } - return -1; -} - -void stop_cpu(unsigned long apicid) -{ - int timeout; - unsigned long send_status; - - /* send an APIC INIT to myself */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT); - - /* wait for the ipi send to finish */ - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("timed out\n"); - } - mdelay(10); - - printk_spew("Deasserting INIT.\n"); - /* Deassert the APIC INIT */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("timed out\n"); - } - - while(1) { - hlt(); - } -} - -/* This is a lot more paranoid now, since Linux can NOT handle - * being told there is a CPU when none exists. So any errors - * will return 0, meaning no CPU. - * - * We actually handling that case by noting which cpus startup - * and not telling anyone about the ones that dont. - */ -int start_cpu(unsigned long apicid) -{ - int timeout; - unsigned long send_status, accept_status, start_eip; - int j, num_starts, maxlvt; - extern char _secondary_start[]; - - /* - * Starting actual IPI sequence... - */ - - printk_spew("Asserting INIT.\n"); - - /* - * Turn INIT on target chip - */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - - /* - * Send IPI - */ - - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT - | APIC_DM_INIT); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("CPU %d: First apic write timed out. Disabling\n", - apicid); - // too bad. - printk_err("ESR is 0x%x\n", apic_read(APIC_ESR)); - if (apic_read(APIC_ESR)) { - printk_err("Try to reset ESR\n"); - apic_write_around(APIC_ESR, 0); - printk_err("ESR is 0x%x\n", apic_read(APIC_ESR)); - } - return 0; - } - mdelay(10); - - printk_spew("Deasserting INIT.\n"); - - /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - - /* Send IPI */ - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("CPU %d: Second apic write timed out. Disabling\n", - apicid); - // too bad. - return 0; - } - - start_eip = (unsigned long)_secondary_start; - printk_spew("start_eip=0x%08lx\n", start_eip); - - num_starts = 2; - - /* - * Run STARTUP IPI loop. - */ - printk_spew("#startup loops: %d.\n", num_starts); - - maxlvt = 4; - - for (j = 1; j <= num_starts; j++) { - printk_spew("Sending STARTUP #%d to %u.\n", j, apicid); - apic_read_around(APIC_SPIV); - apic_write(APIC_ESR, 0); - apic_read(APIC_ESR); - printk_spew("After apic_write.\n"); - - /* - * STARTUP IPI - */ - - /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - - /* Boot on the stack */ - /* Kick the second */ - apic_write_around(APIC_ICR, APIC_DM_STARTUP - | (start_eip >> 12)); - - /* - * Give the other CPU some time to accept the IPI. - */ - udelay(300); - - printk_spew("Startup point 1.\n"); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - - /* - * Give the other CPU some time to accept the IPI. - */ - udelay(200); - /* - * Due to the Pentium erratum 3AP. - */ - if (maxlvt > 3) { - apic_read_around(APIC_SPIV); - apic_write(APIC_ESR, 0); - } - accept_status = (apic_read(APIC_ESR) & 0xEF); - if (send_status || accept_status) - break; - } - printk_spew("After Startup.\n"); - if (send_status) - printk_warning("APIC never delivered???\n"); - if (accept_status) - printk_warning("APIC delivery error (%lx).\n", accept_status); - if (send_status || accept_status) - return 0; - return 1; -} - - -void startup_other_cpus(unsigned long *processor_map) -{ - unsigned long apicid = this_processors_id(); - int i; - - /* Assume the cpus are densly packed by apicid */ - for(i = 0; i < CONFIG_MAX_CPUS; i++) { - unsigned long cpu_apicid = initial_apicid[i]; - if (cpu_apicid == -1) { - printk_err("CPU %d not found\n",i); - processor_map[i] = 0; - continue; - } - if (cpu_apicid == apicid ) { - continue; - } - if (!start_cpu(cpu_apicid)) { - /* Put an error in processor_map[i]? */ - printk_err("CPU %d/%u would not start!\n", - i, cpu_apicid); - processor_map[i] = 0; - } - } -} diff --git a/src/arch/ppc/boot/linuxbios_table.c b/src/arch/ppc/boot/linuxbios_table.c index f199615d5f..2b37e877e5 100644 --- a/src/arch/ppc/boot/linuxbios_table.c +++ b/src/arch/ppc/boot/linuxbios_table.c @@ -218,7 +218,6 @@ struct lb_memory *get_lb_mem(void) } unsigned long write_linuxbios_table( - unsigned long *processor_map, struct mem_range *ram, unsigned long low_table_start, unsigned long low_table_end, unsigned long rom_table_startk, unsigned long rom_table_endk) diff --git a/src/arch/ppc/boot/tables.c b/src/arch/ppc/boot/tables.c index c5f5a5da19..468fbcabe8 100644 --- a/src/arch/ppc/boot/tables.c +++ b/src/arch/ppc/boot/tables.c @@ -6,7 +6,7 @@ #include "linuxbios_table.h" struct lb_memory * -write_tables(struct mem_range *mem, unsigned long *processor_map) +write_tables(struct mem_range *mem) { unsigned long low_table_start, low_table_end; unsigned long rom_table_start, rom_table_end; @@ -19,28 +19,10 @@ write_tables(struct mem_range *mem, unsigned long *processor_map) low_table_start = 0; low_table_end = 16; -#if 0 - post_code(0x9a); - check_pirq_routing_table(); - /* This table must be betweeen 0xf0000 & 0x100000 */ - rom_table_end = copy_pirq_routing_table(rom_table_end); - rom_table_end = (rom_table_end + 1023) & ~1023; - - /* copy the smp block to address 0 */ - post_code(0x96); - /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ - remove_logical_cpus(); - low_table_end = write_smp_table(low_table_end, processor_map); - - /* Don't write anything in the traditional x86 BIOS data segment */ - if (low_table_end < 0x500) { - low_table_end = 0x500; - } -#endif /* The linuxbios table must be in 0-4K or 960K-1M */ - write_linuxbios_table(processor_map, mem, - low_table_start, low_table_end, - rom_table_start >> 10, rom_table_end >> 10); + write_linuxbios_table(mem, + low_table_start, low_table_end, + rom_table_start >> 10, rom_table_end >> 10); return get_lb_mem(); } diff --git a/src/boot/elfboot.c b/src/boot/elfboot.c index 272aee9d73..eeb4e40cd4 100644 --- a/src/boot/elfboot.c +++ b/src/boot/elfboot.c @@ -440,6 +440,12 @@ static int load_elf_segments( end = dest + ptr->s_memsz; middle = dest + ptr->s_filesz; start_offset = ptr->s_offset; +#if 1 + if (ptr->s_filesz == 0) { + start_offset = offset; + } +#endif + printk_spew("[ 0x%016lx, %016lx, 0x%016lx) <- %016lx\n", (unsigned long)dest, diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c index efaf59519d..d292e5dcd4 100644 --- a/src/boot/hardwaremain.c +++ b/src/boot/hardwaremain.c @@ -27,129 +27,28 @@ it with the version available from LANL. #include <console/console.h> -#include <cpu/cpu.h> #include <mem.h> #include <version.h> -#include <smp/start_stop.h> #include <boot/tables.h> -#include <part/sizeram.h> #include <device/device.h> #include <device/pci.h> #include <device/chip.h> #include <delay.h> +#include <stdlib.h> #include <part/hard_reset.h> -#include <smp/atomic.h> #include <boot/elf.h> - -#ifndef CONFIG_MAX_PHYSICAL_CPUS -#define CONFIG_MAX_PHYSICAL_CPUS CONFIG_MAX_CPUS -#endif - -#if CONFIG_FS_STREAM == 1 -extern int filo(struct lb_memory *); -#endif - -/* The processor map. - * Now that SMP is in linuxbios, and Linux counts on us - * giving accurate information about processors, we need a map - * of what processors are out there. This could be a bit mask, - * but we will be optimistic and hope we someday run on - * REALLY BIG SMPs. Also we may need more than one bit of - * info per processor at some point. I hope we don't need - * anything more complex than an int. - */ -static unsigned long processor_map[CONFIG_MAX_CPUS]; - -static struct mem_range *get_ramsize(void) -{ - struct mem_range *mem = 0; - if (!mem) { - mem = sizeram(); - } - if (!mem) { - printk_emerg("No memory size information!\n"); - for(;;) { - /* Ensure this loop is not optimized away */ - asm volatile("":/* outputs */:/*inputs */ :"memory"); - } - } - return mem; -} - - -#if CONFIG_SMP == 1 -/* 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; - unsigned long id; - 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); -} - -static void wait_for_other_cpus(void) -{ - int old_active_count, active_count; - int i; - old_active_count = 1; - - active_count = atomic_read(&active_cpus); - while (active_count > 1) { - if (active_count != old_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++) { - if (!(processor_map[i] & CPU_ENABLED)) { - printk_err("CPU %d did not initialize!\n", i); - processor_map[i] = 0; - } - } - - printk_debug("All AP CPUs stopped\n"); -} - -#else /* CONIFG_SMP */ -#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; - struct mem_range *mem, *tmem; + /* 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 lb_memory *lb_mem; - unsigned long totalmem; post_code(0x80); @@ -160,8 +59,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); @@ -172,66 +71,31 @@ void hardwaremain(int boot_complete) CONFIGURE(CONF_PASS_PRE_PCI); - /* determine how software can generate PCI configuration transactions - * in this system */ + /* pick how to scan the bus. This is first so we can get at memory size. */ 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); - - /* probe and assign the resources required by the dynamic devices */ + /* 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. + */ 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); - for (totalmem = 0, tmem = mem; tmem->sizek; tmem++) { - totalmem += tmem->sizek; - } - /* Round to the nearest mega */ - printk_info("totalram: %ldM\n", (totalmem + 512) >> 10); - - /* 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; - - /* 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); - - /* 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. */ - lb_mem = write_tables(mem, processor_map); + /* Now that we have collected all of our information + * write our configuration tables. + */ + lb_mem = write_tables(); CONFIGURE(CONF_PASS_PRE_BOOT); diff --git a/src/config/Config.lb b/src/config/Config.lb index f6026d4950..70b3dc9630 100644 --- a/src/config/Config.lb +++ b/src/config/Config.lb @@ -2,7 +2,7 @@ uses HAVE_OPTION_TABLE -makedefine CPP:= $(CC) -no-gcc -x assembler-with-cpp -DASSEMBLY -E +makedefine CPP:= $(CC) -x assembler-with-cpp -DASSEMBLY -E makedefine LIBGCC_FILE_NAME := $(shell $(CC) -print-libgcc-file-name) makedefine GCC_INC_DIR := $(shell $(CC) -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp") diff --git a/src/config/Options.lb b/src/config/Options.lb index db00c51b84..bf9fed8dee 100644 --- a/src/config/Options.lb +++ b/src/config/Options.lb @@ -81,6 +81,11 @@ define i686 export used comment "We're a 686" end +define i786 + default none + export used + comment "We're a 786" +end define CPU_FIXUP default none export used @@ -119,52 +124,62 @@ end define LINUXBIOS_VERSION default "1.1.6" export always + format "\"%s\"" comment "LinuxBIOS version" end define LINUXBIOS_EXTRA_VERSION default "" export used + format "\"%s\"" comment "LinuxBIOS extra version" end define LINUXBIOS_BUILD default "$(shell date)" export always + format "\"%s\"" comment "Build date" end define LINUXBIOS_COMPILE_TIME default "$(shell date +%T)" export always + format "\"%s\"" comment "Build time" end define LINUXBIOS_COMPILE_BY default "$(shell whoami)" export always + format "\"%s\"" comment "Who build this image" end define LINUXBIOS_COMPILE_HOST default "$(shell hostname)" export always + format "\"%s\"" comment "Build host" end define LINUXBIOS_COMPILE_DOMAIN default "$(shell dnsdomainname)" export always + format "\"%s\"" comment "Build domain name" end define LINUXBIOS_COMPILER default "$(shell $(CC) $(CFLAGS) -v 2>&1 | tail -n 1)" export always + format "\"%s\"" comment "Build compiler" end define LINUXBIOS_LINKER default "$(shell $(CC) -Wl,-v 2>&1 | grep version | tail -n 1)" export always + format "\"%s\"" comment "Build linker" end define LINUXBIOS_ASSEMBLER default "$(shell touch dummy.s ; $(CC) -c -Wa,-v dummy.s 2>&1; rm -f dummy.s dummy.o )" export always + format "\"%s\"" comment "Build assembler" end define CONFIG_CHIP_CONFIGURE @@ -459,13 +474,26 @@ end define MAINBOARD_PART_NUMBER default "Part_number_not_set" export always + format "\"%s\"" comment "Part number of mainboard" end define MAINBOARD_VENDOR default "Vendor_not_set" export always + format "\"%s\"" comment "Vendor of mainboard" end +define MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID + default 0 + export always + comment "PCI Vendor ID of mainboard manufacturer" +end +define MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID + default 0 + format "0x%x" + export always + comment "PCI susbsystem device id assigned my mainboard manufacturer" +end define MAINBOARD_POWER_ON_AFTER_POWER_FAIL default none export used @@ -500,11 +528,6 @@ define CONFIG_MAX_CPUS export always comment "Maximum CPU count for this machine" end -define CONFIG_MAX_PHYSICAL_CPUS - default {CONFIG_MAX_CPUS} - export always - comment "Physical CPU count for this machine" -end define CONFIG_LOGICAL_CPUS default 0 export always diff --git a/src/config/linuxbios_c.ld b/src/config/linuxbios_c.ld index c05a4c995e..6fa311fc0e 100644 --- a/src/config/linuxbios_c.ld +++ b/src/config/linuxbios_c.ld @@ -48,6 +48,9 @@ SECTIONS pci_drivers = . ; *(.rodata.pci_driver) epci_drivers = . ; + cpu_drivers = . ; + *(.rodata.cpu_driver) + ecpu_drivers = . ; *(.rodata) *(.rodata.*) /* @@ -84,10 +87,11 @@ SECTIONS } _ebss = .; _end = .; + . = ALIGN(STACK_SIZE); _stack = .; .stack . : { - /* Reserve a stack for each possible cpu, +1 extra */ - . = ((CONFIG_MAX_CPUS * STACK_SIZE) + STACK_SIZE) ; + /* Reserve a stack for each possible cpu */ + . = (CONFIG_MAX_CPUS * STACK_SIZE) ; } _estack = .; _heap = .; @@ -105,5 +109,6 @@ SECTIONS /DISCARD/ : { *(.comment) *(.note) + *(.note.*) } } diff --git a/src/cpu/simple_init/Config.lb b/src/cpu/simple_init/Config.lb new file mode 100644 index 0000000000..ba1753c930 --- /dev/null +++ b/src/cpu/simple_init/Config.lb @@ -0,0 +1 @@ +object simple_cpu_init.o
\ No newline at end of file diff --git a/src/cpu/simple_init/simple_cpu_init.c b/src/cpu/simple_init/simple_cpu_init.c new file mode 100644 index 0000000000..39b5832971 --- /dev/null +++ b/src/cpu/simple_init/simple_cpu_init.c @@ -0,0 +1,26 @@ +#include <linux/console.h> +#include <device/device.h> +#include <device/path.h> +#include <device/cpu.h> + +#if CONFIG_SMP +#error "This Configuration does not support SMP" +#endif + +void initialize_cpus(device_t root) +{ + struct device_path cpu_path; + struct cpu_info *info; + + /* Find the info struct for this cpu */ + info = cpu_info(); + + /* Get the device path of the boot cpu */ + cpu_path.type = DEVICE_PATH_BOOT_CPU; + + /* Find the device struct for the boot cpu */ + info->cpu = alloc_find_dev(root->link[1], &cpu_path); + + /* Initialize the bootstrap processor */ + cpu_initialize(); +} diff --git a/src/devices/chip.c b/src/devices/chip.c index 4c74949e46..8315fab674 100644 --- a/src/devices/chip.c +++ b/src/devices/chip.c @@ -69,7 +69,7 @@ void chip_enumerate(struct chip *chip) printk_debug("Enumerating: %s\n", chip->control->name); } - for (i = 0; i < MAX_CHIP_PATHS; i++) { + for(i = 0; i < MAX_CHIP_PATHS; i++) { int identical_paths; identical_paths = (i > 0) && @@ -90,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++; } @@ -103,21 +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("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->bus->dev, dev_path(dev->bus->dev)); dev->chip = chip; dev->enabled = chip->path[i].enabled; 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]; } @@ -138,8 +138,10 @@ void chip_enumerate(struct chip *chip) chip->dev = dev; } } - - for (child = chip->children; child; child = child->next) { + if (chip->children && !chip->dev) { + die("No device but children?"); + } + for(child = chip->children; child; child = child->next) { if (!child->bus) { child->bus = &chip->dev->link[0]; } @@ -167,8 +169,7 @@ void chip_enumerate(struct chip *chip) 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) { @@ -177,7 +178,7 @@ 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); } @@ -208,5 +209,6 @@ static void enumerate_static_device_chain(struct chip *root) void enumerate_static_devices(void) { printk_info("Enumerating static devices...\n"); + static_root.dev = &dev_root; enumerate_static_device_chain(&static_root); } diff --git a/src/devices/device.c b/src/devices/device.c index 01aca4844f..4b7d8728fd 100644 --- a/src/devices/device.c +++ b/src/devices/device.c @@ -54,10 +54,9 @@ device_t alloc_dev(struct bus *parent, struct device_path *path) 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"); @@ -72,19 +71,18 @@ device_t alloc_dev(struct bus *parent, struct device_path *path) 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; } - /* Add the new device as a children of the bus. */ + /* Add the new device to the list of children of the bus. */ dev->bus = parent; if (child) { child->sibling = dev; } else { parent->children = dev; } - /* If we don't have any other information about a device enable it */ dev->enabled = 1; @@ -125,7 +123,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) { @@ -133,22 +131,20 @@ 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->enabled) { 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]); @@ -165,8 +161,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; @@ -175,33 +171,31 @@ static void pick_largest_resource(struct pick_largest_state *state, 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) { @@ -211,8 +205,7 @@ 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 */ @@ -281,12 +274,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 @@ -305,9 +298,10 @@ 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 @@ -355,12 +349,13 @@ void compute_allocate_resource( resource->flags &= ~IORESOURCE_STORED; base += size; - printk_spew("%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_PREFETCH)? "prefmem": "mem"); + printk_spew( + "%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_PREFETCH)? "prefmem": "mem"); } } /* A pci bridge resource does not need to be a power @@ -372,10 +367,10 @@ void compute_allocate_resource( bridge->size = round(base, 1UL << bridge->gran) - bridge->base; printk_spew("%s compute_allocate_%s: base: %08lx size: %08lx align: %d gran: %d done\n", - dev_path(dev), - (bridge->flags & IORESOURCE_IO)? "io": - (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", - base, bridge->size, bridge->align, bridge->gran); + dev_path(dev), + (bridge->flags & IORESOURCE_IO)? "io": + (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", + base, bridge->size, bridge->align, bridge->gran); } @@ -386,14 +381,16 @@ static void allocate_vga_resource(void) #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 = 0; - struct bus *bus = 0; - - for (dev = all_devices; dev; dev = dev->next) { + struct device *dev, *vga; + struct bus *bus; + bus = 0; + 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)) { if (!vga) { - printk_debug("Allocating VGA resource %s\n", dev_path(dev)); + printk_debug("Allocating VGA resource %s\n", + dev_path(dev)); vga = dev; } if (vga == dev) { @@ -408,9 +405,8 @@ static void allocate_vga_resource(void) if (vga) { bus = vga->bus; } - /* Now walk up the bridges setting the VGA enable */ - while (bus) { + while(bus) { bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA; bus = (bus == bus->dev->bus)? 0 : bus->dev->bus; } @@ -432,7 +428,7 @@ void assign_resources(struct bus *bus) for (curdev = bus->children; curdev; curdev = curdev->sibling) { if (!curdev->ops || !curdev->ops->set_resources) { printk_err("%s missing set_resources\n", - dev_path(curdev)); + dev_path(curdev)); continue; } if (!curdev->enabled) { @@ -474,25 +470,26 @@ void enable_resources(struct device *dev) * @brief Determine the existence of dynamic devices and construct dynamic * device tree. * - * Start form the root device 'dev_root', scan the buses in the system + * Start from the root device 'dev_root', scan the buses in the system * recursively, build the dynamic device tree according to the result * of the probe. * * This function has no idea how to scan and probe buses and devices at all. * It depends on the bus/device specific scan_bus() method to do it. The - * scan_bus() function also have to create the device structure and attach + * scan_bus() function also has 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...\n"); - root = &dev_root; + if (!root->ops || !root->ops->scan_bus) { + printk_err("dev_root missing scan_bus operation"); + return; + } subordinate = root->ops->scan_bus(root, 0); - printk_info("done\n"); } @@ -510,29 +507,38 @@ void dev_enumerate(void) */ void dev_configure(void) { - struct device *root = &dev_root; + struct device *root; printk_info("Allocating resources...\n"); + root = &dev_root; + if (!root->ops || !root->ops->read_resources) { + printk_err("dev_root missing read_resources\n"); + return; + } + if (!root->ops || !root->ops->set_resources) { + printk_err("dev_root missing set_resources\n"); + return; + } root->ops->read_resources(root); /* 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_vga_resource(); - /* now just set things into registers ... we hope ... */ + /* Store the computed resource allocations into device registers ... */ root->ops->set_resources(root); printk_info("done.\n"); @@ -565,13 +571,11 @@ 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) { 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 93a8a5cd96..f5f8bb4482 100644 --- a/src/devices/device_util.c +++ b/src/devices/device_util.c @@ -15,7 +15,7 @@ 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; } @@ -184,7 +184,7 @@ struct resource *get_resource(device_t dev, unsigned index) /* See if there is a resource with the appropriate index */ resource = 0; - for (i = 0; i < dev->resources; i++) { + for(i = 0; i < dev->resources; i++) { if (dev->resource[i].index == index) { resource = &dev->resource[i]; break; diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c index f87a590d0e..6f7fabf67b 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; @@ -173,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); @@ -184,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); @@ -195,8 +195,8 @@ 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); } @@ -223,18 +223,18 @@ void pci_bus_read_resources(struct device *dev) } /** - * @brief round a number up to an alignment. + * @brief round a number up to the next multiple of gran * @param val the starting value - * @param roundup Alignment as a power of two - * @returns rounded up number + * @param gran granularity we are aligning the number to. + * @returns aligned value */ -static unsigned long round(unsigned long val, unsigned long roundup) +static unsigned long align(unsigned long val, unsigned long gran) { - /* ROUNDUP MUST BE A POWER OF TWO. */ - unsigned long inverse; - inverse = ~(roundup - 1); - val += (roundup - 1); - val &= inverse; + /* GRAN MUST BE A POWER OF TWO. */ + unsigned long mask; + mask = ~(gran - 1); + val += (gran - 1); + val &= mask; return val; } @@ -245,10 +245,9 @@ 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)) { printk_err("ERROR: %s %02x not allocated\n", - dev_path(dev), resource->index); + dev_path(dev), resource->index); return; } @@ -270,10 +269,8 @@ 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; @@ -284,13 +281,15 @@ static void pci_set_resource(struct device *dev, struct resource *resource) */ /* Get the limit (rounded up) */ - limit = base + round(resource->size, gran) - 1UL; + limit = base + align(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; @@ -300,50 +299,58 @@ 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, + (unsigned long)(resource->base), limit, + buf, + (resource->flags & IORESOURCE_IO)? "io": + (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem"); return; } @@ -354,11 +361,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) { @@ -442,16 +449,17 @@ static void set_pci_ops(struct device *dev) } /* Look through the list of setup drivers and find one for - * this pci device */ - for (driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) { + * 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; - - printk_debug("%s [%04x/%04x] %sops\n", dev_path(dev), - driver->vendor, driver->device, - (driver->ops->scan_bus?"bus ":"")); - + printk_debug("%s [%04x/%04x] %sops\n", + dev_path(dev), + driver->vendor, driver->device, + (driver->ops->scan_bus?"bus ":"")); return; } } @@ -483,10 +491,10 @@ static void set_pci_ops(struct device *dev) bad: if (dev->enabled) { 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; @@ -496,24 +504,25 @@ static void set_pci_ops(struct device *dev) * @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. + * device structure correspond to the devfn, if present. * * @param list the device structure list * @param devfn a device/function number * - * @return pointer to the device structure found + * @return pointer to the device structure found or null of we have not allocated + * a device for this devfn yet. */ -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; + struct device *dev; - printk_debug("%s, looking for devfn: %02x.%01x\n", __FUNCTION__, - devfn >> 3, devfn & 7); - for (; *list; list = &(*list)->sibling) { + 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) { printk_err("child %s not a pci device\n", - dev_path(*list)); + dev_path(*list)); continue; } if ((*list)->path.u.pci.devfn == devfn) { @@ -524,15 +533,16 @@ static struct device *pci_scan_get_dev(struct device **list, break; } } - - printk_debug("%s, found dev %08x\n", __FUNCTION__, dev); - - /* FIXME: why are we doing this ? Isn't there some order between the - * structures before ? */ + /* Just like alloc_dev add the device to the + * list of device on the bus. When the list of devices was formed + * we removed all of the parents children, and now we are interleaving + * static and dynamic devices in order on the bus. + */ + printk_spew("%s, found dev %08x\n", __FUNCTION__, dev); 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. */ @@ -546,8 +556,8 @@ static struct device *pci_scan_get_dev(struct device **list, return dev; } -/** - * @brief Scan a PCI bus +/** + * @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. @@ -562,8 +572,9 @@ static struct device *pci_scan_get_dev(struct device **list, * * @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; @@ -578,7 +589,8 @@ unsigned int pci_scan_bus(struct bus *bus, unsigned min_devfn, post_code(0x24); /* probe all devices/functions on this bus with some optimization for - * non-existence and single funcion devices */ + * non-existence and single funcion devices + */ for (devfn = min_devfn; devfn <= max_devfn; devfn++) { uint32_t id, class; uint8_t hdr_type; @@ -597,31 +609,39 @@ unsigned int pci_scan_bus(struct bus *bus, unsigned min_devfn, 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; } - /* this function in a multi function device is - * not present, skip to next function */ + /* This function in a multi function device is + * not present, skip to the next function. + */ continue; } dev = alloc_dev(bus, &dummy.path); - } 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 - * Also, it calls the enable function regardlessly - * the value of dev->enabled */ - if (dev->chip && dev->chip->control && - dev->chip->control->enable_dev) { + } + 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. + * + * This is geared toward devices that have subfunctions + * that do not show up by default. + * + * If a device is a stuff option on the motherboard + * it may be absent and enable_dev must cope. + * + */ + if ( dev->chip && dev->chip->control && + dev->chip->control->enable_dev) + { int enabled = dev->enabled; dev->enabled = 1; dev->chip->control->enable_dev(dev); @@ -650,15 +670,17 @@ unsigned int pci_scan_bus(struct bus *bus, unsigned min_devfn, /* 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; } /* Now run the magic enable/disable sequence for the device */ if (dev->ops && dev->ops->enable) { dev->ops->enable(dev); - } else if (dev->chip && dev->chip->control && - dev->chip->control->enable_dev) { + } + else if (dev->chip && dev->chip->control && + dev->chip->control->enable_dev) + { dev->chip->control->enable_dev(dev); } @@ -668,22 +690,23 @@ unsigned int pci_scan_bus(struct bus *bus, unsigned min_devfn, dev->enabled?"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 probing another function. + * Skip to next device. + */ devfn += 0x07; } } post_code(0x25); - /* if a child provides scan_bus(), for example a bridge, scan - * buses behind that child */ - for (child = bus->children; child; child = child->sibling) { - // make sure that we have an ops structure - if (!child->ops) { - continue; - } - if (!child->ops->scan_bus) { + /* For all children that implement scan_bus (i.e. bridges) + * scan the bus behind that child. + */ + for(child = bus->children; child; child = child->sibling) { + if (!child->enabled || + !child->ops || + !child->ops->scan_bus) + { continue; } max = child->ops->scan_bus(child, max); @@ -725,7 +748,8 @@ 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; @@ -734,32 +758,37 @@ unsigned int pci_scan_bridge(struct device *dev, unsigned int max) pci_write_config16(dev, PCI_COMMAND, 0x0000); pci_write_config16(dev, PCI_STATUS, 0xffff); - /* Read the existing primary/secondary/subordinate bus - * 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 buses behind the - * bridge */ + + /* Now we can scan all subordinate buses + * i.e. the bus 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); + + printk_spew("%s returns max %d\n", __func__, max); return max; } @@ -771,10 +800,18 @@ 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); @@ -784,11 +821,11 @@ static void pci_level_irq(unsigned char intNum) #if 1 if (inb(0x4d0) != (intBits & 0xf)) { printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n", - __FUNCTION__, intBits &0xf, inb(0x4d0)); + __func__, intBits &0xf, inb(0x4d0)); } if (inb(0x4d1) != ((intBits >> 8) & 0xf)) { printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n", - __FUNCTION__, (intBits>>8) &0xf, inb(0x4d1)); + __func__, (intBits>>8) &0xf, inb(0x4d1)); } #endif } diff --git a/src/devices/pnp_device.c b/src/devices/pnp_device.c index 5f4ede1ec4..4bdb67e4aa 100644 --- a/src/devices/pnp_device.c +++ b/src/devices/pnp_device.c @@ -76,25 +76,30 @@ static void pnp_set_resource(device_t dev, struct resource *resource) /* Now store the resource */ if (resource->flags & IORESOURCE_IO) { pnp_set_iobase(dev, resource->index, resource->base); - } else if (resource->flags & IORESOURCE_DRQ) { + } + else if (resource->flags & IORESOURCE_DRQ) { pnp_set_drq(dev, resource->index, resource->base); - } else if (resource->flags & IORESOURCE_IRQ) { + } + else if (resource->flags & IORESOURCE_IRQ) { pnp_set_irq(dev, resource->index, resource->base); - } else { + } + else { printk_err("ERROR: %s %02x unknown resource type\n", - dev_path(dev), resource->index); + dev_path(dev), resource->index); return; } 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": - "???"); + 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": + "???"); } void pnp_set_resources(device_t dev) @@ -105,7 +110,7 @@ void pnp_set_resources(device_t dev) pnp_set_logical_device(dev); /* Paranoia says I should disable the device here... */ - for (i = 0; i < dev->resources; i++) { + for(i = 0; i < dev->resources; i++) { pnp_set_resource(dev, &dev->resource[i]); } } @@ -133,8 +138,7 @@ struct device_operations pnp_ops = { /* PNP chip opertations */ -static void pnp_get_ioresource(device_t dev, unsigned index, - struct io_info *info) +static void pnp_get_ioresource(device_t dev, unsigned index, struct io_info *info) { struct resource *resource; uint32_t size; @@ -156,14 +160,18 @@ static void get_resources(device_t dev, struct pnp_info *info) { struct resource *resource; -// pnp_set_logical_device(dev); // coment out by LYH - if (info->flags & PNP_IO0) { pnp_get_ioresource(dev, PNP_IDX_IO0, &info->io0); } if (info->flags & PNP_IO1) { pnp_get_ioresource(dev, PNP_IDX_IO1, &info->io1); } + if (info->flags & PNP_IO2) { + pnp_get_ioresource(dev, PNP_IDX_IO2, &info->io2); + } + if (info->flags & PNP_IO3) { + pnp_get_ioresource(dev, PNP_IDX_IO3, &info->io3); + } if (info->flags & PNP_IRQ0) { resource = get_resource(dev, PNP_IDX_IRQ0); resource->size = 1; @@ -187,7 +195,7 @@ static void get_resources(device_t dev, struct pnp_info *info) } void pnp_enumerate(struct chip *chip, unsigned functions, - struct device_operations *ops, struct pnp_info *info) + struct device_operations *ops, struct pnp_info *info) { struct device_path path; device_t dev; @@ -199,14 +207,13 @@ void pnp_enumerate(struct chip *chip, unsigned functions, path.u.pnp.port = chip->dev->path.u.pnp.port; /* Setup the ops and resources on the newly allocated devices */ - for (i = 0; i < functions; i++) { + for(i = 0; i < functions; i++) { path.u.pnp.device = info[i].function; - dev = alloc_find_dev(chip->bus, &path); if (info[i].ops == 0) { dev->ops = ops; - } else { + } else { dev->ops = info[i].ops; } get_resources(dev, &info[i]); diff --git a/src/devices/root_device.c b/src/devices/root_device.c index 10cebbaf38..04c96770fe 100644 --- a/src/devices/root_device.c +++ b/src/devices/root_device.c @@ -11,7 +11,6 @@ void root_dev_read_resources(device_t root) { int res = 0; - printk_spew("%s . Root is %p\n", __FUNCTION__, dev_path(root)); /* Initialize the system wide io space constraints */ root->resource[res].base = 0x400; root->resource[res].size = 0; @@ -20,10 +19,8 @@ void root_dev_read_resources(device_t root) root->resource[res].limit = 0xffffUL; 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]); 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 */ @@ -34,14 +31,12 @@ void root_dev_read_resources(device_t root) root->resource[res].limit = 0xffffffffUL; 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]); compute_allocate_resource(&root->link[0], &root->resource[res], - IORESOURCE_MEM, IORESOURCE_MEM); + IORESOURCE_MEM, IORESOURCE_MEM); res++; root->resources = res; - printk_spew("%s DONE\n", __FUNCTION__); + printk_spew("%s DONE\n", __func__); } /** @@ -51,12 +46,13 @@ void root_dev_read_resources(device_t root) */ void root_dev_set_resources(device_t root) { - struct bus *bus = &root->link[0]; + struct bus *bus; - compute_allocate_resource(bus, &root->resource[0], - IORESOURCE_IO, IORESOURCE_IO); - compute_allocate_resource(bus, &root->resource[1], - IORESOURCE_MEM, IORESOURCE_MEM); + 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); } @@ -80,20 +76,21 @@ unsigned int scan_static_bus(device_t bus, unsigned int max) { device_t child; unsigned link; + + printk_debug("%s for %s\n", __func__, dev_path(bus)); - printk_debug("%s for %s\n", __FUNCTION__, dev_path(bus)); - - 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->enabled?"enabled": "disabled"); + printk_debug("%s %s\n", + dev_path(child), + child->enabled?"enabled": "disabled"); } } - for (link = 0; link < bus->links; link++) { - for (child = bus->link[link].children; child; child = child->sibling) { + for(link = 0; link < 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)); @@ -101,7 +98,7 @@ unsigned int scan_static_bus(device_t bus, unsigned int max) } } - printk_debug("%s done\n", __FUNCTION__); + printk_debug("%s done\n", __func__); return max; } @@ -119,9 +116,9 @@ unsigned int scan_static_bus(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); } } @@ -172,11 +169,11 @@ 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, - }, - }, + .links = 1, + .link = { + [0] = { + .dev = &dev_root, + .link = 0, + }, + }, }; diff --git a/src/drivers/ati/ragexl/xlinit.c b/src/drivers/ati/ragexl/xlinit.c index 38e1aa4198..30e18b2960 100644 --- a/src/drivers/ati/ragexl/xlinit.c +++ b/src/drivers/ati/ragexl/xlinit.c @@ -30,11 +30,11 @@ #include "fbcon.h" struct aty_cmap_regs { - u8 windex; - u8 lut; - u8 mask; - u8 rindex; - u8 cntl; + u8 windex; + u8 lut; + u8 mask; + u8 rindex; + u8 cntl; }; #include <console/btext.h> @@ -427,31 +427,29 @@ int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, #endif struct fb_var_screeninfo default_var = { - /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, - 0, FB_VMODE_NONINTERLACED + /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED }; #endif /*CONFIG_CONSOLE_BTEXT*/ static struct { - u16 pci_id, chip_type; - u8 rev_mask, rev_val; - const char *name; - int pll, mclk, xclk; - u32 features; + u16 pci_id, chip_type; + u8 rev_mask, rev_val; + const char *name; + int pll, mclk, xclk; + u32 features; } aty_chips[] = { - /* 3D RAGE XL PCI-66/BGA */ - { 0x474f, 0x474f, 0x00, 0x00, m64n_xl_66, 230, 83, 63, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL | M64F_MFB_TIMES_4 }, - /* 3D RAGE XL PCI-33/BGA */ - { 0x4752, 0x4752, 0x00, 0x00, m64n_xl_33, 230, 83, 63, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL | M64F_MFB_TIMES_4 }, + /* 3D RAGE XL PCI-66/BGA */ + { 0x474f, 0x474f, 0x00, 0x00, m64n_xl_66, 230, 83, 63, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL | M64F_MFB_TIMES_4 }, + /* 3D RAGE XL PCI-33/BGA */ + { 0x4752, 0x4752, 0x00, 0x00, m64n_xl_33, 230, 83, 63, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL | M64F_MFB_TIMES_4 }, }; #if CONFIG_CONSOLE_BTEXT==1 -static void aty_calc_mem_refresh(struct fb_info_aty *info, - u16 id, - int xclk) +static void aty_calc_mem_refresh(struct fb_info_aty *info, u16 id, int xclk) { int i, size; #if 0 @@ -484,7 +482,8 @@ static void aty_calc_mem_refresh(struct fb_info_aty *info, info->mem_refresh_rate = i; } #endif /*CONFIG_CONSOLE_BTEXT */ -static void ati_ragexl_init(device_t dev) { +static void ati_ragexl_init(device_t dev) +{ u32 chip_id; u32 i; int j; diff --git a/src/include/boot/tables.h b/src/include/boot/tables.h index 618c32ef94..6c309b3c26 100644 --- a/src/include/boot/tables.h +++ b/src/include/boot/tables.h @@ -1,9 +1,8 @@ #ifndef BOOT_TABLES_H #define BOOT_TABLES_H -#include <mem.h> #include <boot/linuxbios_tables.h> -struct lb_memory *write_tables(struct mem_range *mem, unsigned long *processor_map); +struct lb_memory *write_tables(void); #endif /* BOOT_TABLES_H */ diff --git a/src/include/console/console.h b/src/include/console/console.h index aeb5895587..5d31dd1296 100644 --- a/src/include/console/console.h +++ b/src/include/console/console.h @@ -10,7 +10,7 @@ void console_tx_flush(void); unsigned char console_rx_byte(void); int console_tst_byte(void); void post_code(uint8_t value); -void die(char *msg); +void die(const char *msg); struct console_driver { void (*init)(void); @@ -20,7 +20,7 @@ struct console_driver { int (*tst_byte)(void); }; -#define __console __attribute__((unused, __section__ (".rodata.console_drivers"))) +#define __console __attribute__((used, __section__ (".rodata.console_drivers"))) /* Defined by the linker... */ extern struct console_driver console_drivers[]; diff --git a/src/include/device/device.h b/src/include/device/device.h index 439fc606a3..6dade9ed99 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -42,8 +42,8 @@ struct device { device_t next; /* chain of all devices */ struct device_path path; - unsigned short vendor; - unsigned short device; + unsigned vendor; + unsigned device; unsigned int class; /* 3 bytes: (base,sub,prog-if) */ unsigned int hdr_type; /* PCI header type */ unsigned int enabled : 1; /* set if we should enable the device */ diff --git a/src/include/device/path.h b/src/include/device/path.h index 20d76d1bbe..cd6be6ac03 100644 --- a/src/include/device/path.h +++ b/src/include/device/path.h @@ -4,9 +4,11 @@ enum device_path_type { DEVICE_PATH_NONE = 0, DEVICE_PATH_ROOT, + DEVICE_PATH_DEFAULT_CPU, DEVICE_PATH_PCI, DEVICE_PATH_PNP, DEVICE_PATH_I2C, + DEVICE_PATH_APIC, }; struct pci_path @@ -26,12 +28,18 @@ struct i2c_path unsigned device; }; +struct apic_path +{ + unsigned apic_id; +}; + struct device_path { enum device_path_type type; union { - struct pci_path pci; - struct pnp_path pnp; - struct i2c_path i2c; + struct pci_path pci; + struct pnp_path pnp; + struct i2c_path i2c; + struct apic_path apic; } u; }; diff --git a/src/include/device/pci.h b/src/include/device/pci.h index ef18cb40ee..13414a7df6 100644 --- a/src/include/device/pci.h +++ b/src/include/device/pci.h @@ -21,13 +21,18 @@ #include <device/pci_ops.h> +/* Common pci operations without a standard interface */ +struct pci_operations { + void (*set_subsystem)(device_t dev, unsigned vendor, unsigned device); +}; + struct pci_driver { struct device_operations *ops; unsigned short vendor; unsigned short device; }; -#define __pci_driver __attribute__ ((unused,__section__(".rodata.pci_driver"))) +#define __pci_driver __attribute__ ((used,__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 */ @@ -37,7 +42,6 @@ extern struct pci_driver epci_drivers[]; struct device_operations default_pci_ops_dev; struct device_operations default_pci_ops_bus; - void pci_dev_read_resources(device_t dev); void pci_bus_read_resources(device_t dev); void pci_dev_set_resources(device_t dev); @@ -45,8 +49,19 @@ void pci_dev_enable_resources(device_t dev); void pci_bus_enable_resources(device_t dev); unsigned int pci_scan_bridge(device_t bus, unsigned int max); unsigned int pci_scan_bus(struct bus *bus, unsigned min_devfn, unsigned max_devfn, unsigned int max); +struct resource *pci_get_resource(struct device *dev, unsigned long index); #define PCI_IO_BRIDGE_ALIGN 4096 #define PCI_MEM_BRIDGE_ALIGN (1024*1024) +static inline struct pci_operations *ops_pci(device_t dev) +{ + struct pci_operations *pops; + pops = 0; + if (dev && dev->ops) { + pops = dev->ops->ops_pci; + } + return pops; +} + #endif /* PCI_H */ diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h index df27c83d83..d840b3879a 100644 --- a/src/include/device/pci_ids.h +++ b/src/include/device/pci_ids.h @@ -1757,6 +1757,7 @@ #define PCI_DEVICE_ID_INTEL_82801DB_7 0x24c7 #define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb #define PCI_DEVICE_ID_INTEL_82801DB_13 0x24cd +#define PCI_DEVICE_ID_INTEL_82801EB_0 0x24d0 #define PCI_DEVICE_ID_INTEL_80310 0x530d #define PCI_DEVICE_ID_INTEL_82810_MC1 0x7120 #define PCI_DEVICE_ID_INTEL_82810_IG1 0x7121 diff --git a/src/include/device/pnp.h b/src/include/device/pnp.h index 508fac68ed..89c0a730f5 100644 --- a/src/include/device/pnp.h +++ b/src/include/device/pnp.h @@ -36,11 +36,13 @@ struct pnp_info { unsigned flags; #define PNP_IO0 0x01 #define PNP_IO1 0x02 -#define PNP_IRQ0 0x04 -#define PNP_IRQ1 0x08 -#define PNP_DRQ0 0x10 -#define PNP_DRQ1 0x20 - struct io_info io0, io1; +#define PNP_IO2 0x04 +#define PNP_IO3 0x08 +#define PNP_IRQ0 0x10 +#define PNP_IRQ1 0x20 +#define PNP_DRQ0 0x40 +#define PNP_DRQ1 0x80 + struct io_info io0, io1, io2, io3; }; struct resource *pnp_get_resource(device_t dev, unsigned index); void pnp_enumerate(struct chip *chip, unsigned functions, diff --git a/src/include/device/pnp_def.h b/src/include/device/pnp_def.h index b077837d02..b17fde6478 100644 --- a/src/include/device/pnp_def.h +++ b/src/include/device/pnp_def.h @@ -3,6 +3,8 @@ #define PNP_IDX_IO0 0x60 #define PNP_IDX_IO1 0x62 +#define PNP_IDX_IO2 0x64 +#define PNP_IDX_IO3 0x66 #define PNP_IDX_IRQ0 0x70 #define PNP_IDX_IRQ1 0x72 #define PNP_IDX_DRQ0 0x74 diff --git a/src/mainboard/arima/hdama/Config.lb b/src/mainboard/arima/hdama/Config.lb index 87318da6f5..f8091bdbe8 100644 --- a/src/mainboard/arima/hdama/Config.lb +++ b/src/mainboard/arima/hdama/Config.lb @@ -31,6 +31,8 @@ uses LB_CKS_RANGE_END uses LB_CKS_LOC uses MAINBOARD_PART_NUMBER uses MAINBOARD_VENDOR +uses MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID +uses MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID ## ROM_SIZE is the size of boot ROM that this board will use. @@ -95,6 +97,8 @@ default CONFIG_IOAPIC=1 ## default MAINBOARD_PART_NUMBER="HDAMA" default MAINBOARD_VENDOR="ARIMA" +default MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID=0x161f +default MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID=0x3016 ### ### LinuxBIOS layout values @@ -109,9 +113,9 @@ default ROM_IMAGE_SIZE = 65536 default STACK_SIZE=0x2000 ## -## Use a small 16K heap +## Use a small 32K heap ## -default HEAP_SIZE=0x4000 +default HEAP_SIZE=0x8000 ## ## Only use the option table in a normal image @@ -158,7 +162,6 @@ default XIP_ROM_BASE = ( _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE ) ## arch i386 end -#cpu k8 end ## ## Build the objects we have code for in this directory. @@ -193,21 +196,20 @@ end ## ## Build our 16 bit and 32 bit linuxBIOS entry code ## -mainboardinit cpu/i386/entry16.inc -mainboardinit cpu/i386/entry32.inc -mainboardinit cpu/i386/bist32.inc -ldscript /cpu/i386/entry16.lds -ldscript /cpu/i386/entry32.lds +mainboardinit cpu/x86/16bit/entry16.inc +mainboardinit cpu/x86/32bit/entry32.inc +ldscript /cpu/x86/16bit/entry16.lds +ldscript /cpu/x86/32bit/entry32.lds ## ## Build our reset vector (This is where linuxBIOS is entered) ## if USE_FALLBACK_IMAGE - mainboardinit cpu/i386/reset16.inc - ldscript /cpu/i386/reset16.lds + mainboardinit cpu/x86/16bit/reset16.inc + ldscript /cpu/x86/16bit/reset16.lds else - mainboardinit cpu/i386/reset32.inc - ldscript /cpu/i386/reset32.lds + mainboardinit cpu/x86/32bit/reset32.inc + ldscript /cpu/x86/32bit/reset32.lds end ### Should this be in the northbridge code? @@ -219,11 +221,6 @@ mainboardinit arch/i386/lib/cpu_reset.inc mainboardinit arch/i386/lib/id.inc ldscript /arch/i386/lib/id.lds -## -## Setup our mtrrs -## -mainboardinit cpu/k8/earlymtrr.inc - ### ### This is the early phase of linuxBIOS startup ### Things are delicate and we test to see if we should @@ -241,9 +238,12 @@ end ## ## Setup RAM ## -mainboardinit cpu/k8/enable_mmx_sse.inc +mainboardinit cpu/x86/fpu/enable_fpu.inc +mainboardinit cpu/x86/mmx/enable_mmx.inc +mainboardinit cpu/x86/sse/enable_sse.inc mainboardinit ./auto.inc -mainboardinit cpu/k8/disable_mmx_sse.inc +mainboardinit cpu/x86/sse/disable_sse.inc +mainboardinit cpu/x86/mmx/disable_mmx.inc ## ## Include the secondary Configuration files @@ -252,30 +252,25 @@ dir /pc80 config chip.h northbridge amd/amdk8 "mc0" - pci 0:18.0 - pci 0:18.0 - pci 0:18.0 - pci 0:18.1 - pci 0:18.2 - pci 0:18.3 - southbridge amd/amd8131 "amd8131" link 0 + pnp cf8.0 + northbridge amd/amdk8 "mc1" link 0 + pci 0:19.0 + pci 0:19.0 + pci 0:19.0 + pci 0:19.1 + pci 0:19.2 + pci 0:19.3 + end + pci 1:18.0 + southbridge amd/amd8131 "amd8131" link 1 pci 0:0.0 pci 0:0.1 pci 0:1.0 pci 0:1.1 end - southbridge amd/amd8111 "amd8111" link 0 + southbridge amd/amd8111 "amd8111" link 1 pci 0:0.0 pci 0:1.0 on - pci 0:1.1 on - pci 0:1.2 on - pci 0:1.3 on - pci 0:1.5 off - pci 0:1.6 off - pci 1:0.0 on - pci 1:0.1 on - pci 1:0.2 on - pci 1:1.0 off superio NSC/pc87360 link 1 pnp 2e.0 off # Floppy io 0x60 = 0x3f0 @@ -301,29 +296,64 @@ northbridge amd/amdk8 "mc0" pnp 2e.9 off # FSCM pnp 2e.a off # WDT end + pci 0:1.1 on + pci 0:1.2 on + pci 0:1.3 on # ACPI/SMBUS + chip drivers/generic/generic link 4 + #phillips pca9545 smbus mux + i2c 70 + # analog_devices adm1026 + chip drivers/generic/generic link 0 + i2c 2c + end + i2c 70 + i2c 70 + i2c 70 + end + chip drivers/generic/generic link 4 #dimm 0-0-0 + i2c 50 + end + chip drivers/generic/generic link 4 #dimm 0-0-1 + i2c 51 + end + chip drivers/generic/generic link 4 #dimm 0-1-0 + i2c 52 + end + chip drivers/generic/generic link 4 #dimm 0-1-1 + i2c 53 + end + chip drivers/generic/generic link 4 #dimm 1-0-0 + i2c 54 + end + chip drivers/generic/generic link 4 #dimm 1-0-1 + i2c 55 + end + chip drivers/generic/generic link 4 #dimm 1-1-0 + i2c 56 + end + chip drivers/generic/generic link 4 #dimm 1-1-1 + i2c 57 + end + pci 0:1.5 off + pci 0:1.6 off + pci 1:0.0 on + pci 1:0.1 on + pci 1:0.2 on + pci 1:1.0 off end + pci 1:18.0 + pci 1:18.0 + pci 1:18.1 + pci 1:18.2 + pci 1:18.3 end -northbridge amd/amdk8 "mc1" - pci 0:19.0 - pci 0:19.0 - pci 0:19.0 - pci 0:19.1 - pci 0:19.2 - pci 0:19.3 -end -cpu k8 "cpu0" - register "ldt0" = "{ .chip = &amd8131, .ht_width=16, .ht_speed=600 }" +cpu amd/socket_940 "cpu0" link 1 + apic 0 end -cpu k8 "cpu1" +cpu amd/socket_940 "cpu1" link 1 + apic 1 end -## -## Include the old serial code for those few places that still need it. -## -mainboardinit pc80/serial.inc -mainboardinit arch/i386/lib/console.inc -mainboardinit cpu/i386/bist32_fail.inc - diff --git a/src/mainboard/arima/hdama/auto.c b/src/mainboard/arima/hdama/auto.c index 17b39b9c84..7ead2d27d0 100644 --- a/src/mainboard/arima/hdama/auto.c +++ b/src/mainboard/arima/hdama/auto.c @@ -4,7 +4,8 @@ #include <arch/io.h> #include <device/pnp_def.h> #include <arch/romcc_io.h> -#include <arch/smp/lapic.h> +#include <cpu/x86/lapic.h> +#include <arch/cpu.h> #include "option_table.h" #include "pc80/mc146818rtc_early.c" #include "pc80/serial.c" @@ -13,13 +14,15 @@ #include "northbridge/amd/amdk8/incoherent_ht.c" #include "southbridge/amd/amd8111/amd8111_early_smbus.c" #include "northbridge/amd/amdk8/raminit.h" -#include "cpu/k8/apic_timer.c" +#include "cpu/amd/model_fxx/apic_timer.c" #include "lib/delay.c" -#include "cpu/p6/boot_cpu.c" +#include "cpu/x86/lapic/boot_cpu.c" #include "northbridge/amd/amdk8/reset_test.c" #include "northbridge/amd/amdk8/debug.c" #include "northbridge/amd/amdk8/cpu_rev.c" #include "superio/NSC/pc87360/pc87360_early_serial.c" +#include "cpu/amd/mtrr/amd_earlymtrr.c" +#include "cpu/x86/bist.h" #define SERIAL_DEV PNP_DEV(0x2e, PC87360_SP1) @@ -50,7 +53,8 @@ static void memreset_setup(void) outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28); /* Ensure the BIOS has control of the memory lines */ outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29); - } else { + } + else { /* Ensure the CPU has controll of the memory lines */ outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 29); } @@ -128,7 +132,7 @@ static inline int spd_read_byte(unsigned device, unsigned address) #define FIRST_CPU 1 #define SECOND_CPU 1 #define TOTAL_CPUS (FIRST_CPU + SECOND_CPU) -static void main(void) +static void main(unsigned long bist) { static const struct mem_controller cpu[] = { #if FIRST_CPU @@ -156,25 +160,29 @@ static void main(void) }; int needs_reset; - enable_lapic(); - init_timer(); - - if (cpu_init_detected()) { - asm volatile ("jmp __cpu_reset"); - } - - distinguish_cpu_resets(); - if (!boot_cpu()) { - stop_this_cpu(); + if (bist == 0) { + /* Skip this if there was a built in self test failure */ + amd_early_mtrr_init(); + enable_lapic(); + init_timer(); + if (cpu_init_detected()) { + asm volatile ("jmp __cpu_reset"); + } + distinguish_cpu_resets(); + if (!boot_cpu()) { + stop_this_cpu(); + } } - + /* Setup the console */ pc87360_enable_serial(SERIAL_DEV, TTYS0_BASE); uart_init(); console_init(); + /* Halt if there was a built in self test failure */ + report_bist_failure(bist); + setup_default_resource_map(); needs_reset = setup_coherent_ht_domain(); - /* Non-coherent HT is on LDT0 */ needs_reset |= ht_setup_chain(PCI_DEV(0, 0x18, 0), 0x80); if (needs_reset) { print_info("ht reset -\r\n"); @@ -184,9 +192,7 @@ static void main(void) #if 0 print_pci_devices(); #endif - enable_smbus(); - #if 0 dump_spd_registers(&cpu[0]); #endif diff --git a/src/mainboard/arima/hdama/cmos.layout b/src/mainboard/arima/hdama/cmos.layout index 247715e6ac..ea027282c4 100644 --- a/src/mainboard/arima/hdama/cmos.layout +++ b/src/mainboard/arima/hdama/cmos.layout @@ -41,6 +41,7 @@ entries 432 8 h 0 boot_countdown 440 4 e 9 slow_cpu 444 1 e 1 nmi +445 1 e 1 iommu 728 256 h 0 user_data 984 16 h 0 check_sum # Reserve the extended AMD configuration registers diff --git a/src/mainboard/arima/hdama/failover.c b/src/mainboard/arima/hdama/failover.c index 201bcb9203..e351cae83d 100644 --- a/src/mainboard/arima/hdama/failover.c +++ b/src/mainboard/arima/hdama/failover.c @@ -4,22 +4,15 @@ #include <device/pci_ids.h> #include <arch/io.h> #include <arch/romcc_io.h> -#include <arch/smp/lapic.h> +#include <cpu/x86/lapic.h> #include "pc80/mc146818rtc_early.c" #include "southbridge/amd/amd8111/amd8111_enable_rom.c" #include "northbridge/amd/amdk8/early_ht.c" -#include "cpu/p6/boot_cpu.c" +#include "cpu/x86/lapic/boot_cpu.c" #include "northbridge/amd/amdk8/reset_test.c" -#define HAVE_REGPARM_SUPPORT 0 -#if HAVE_REGPARM_SUPPORT static unsigned long main(unsigned long bist) { -#else -static void main(void) -{ - unsigned long bist = 0; -#endif /* Make cerain my local apic is useable */ enable_lapic(); @@ -72,9 +65,5 @@ static void main(void) : /* clobbers */ ); fallback_image: -#if HAVE_REGPARM_SUPPORT return bist; -#else - return; -#endif } diff --git a/src/mainboard/arima/hdama/mainboard.c b/src/mainboard/arima/hdama/mainboard.c index bbc6f53716..52a32b0adf 100644 --- a/src/mainboard/arima/hdama/mainboard.c +++ b/src/mainboard/arima/hdama/mainboard.c @@ -3,145 +3,251 @@ #include <device/pci.h> #include <device/pci_ids.h> #include <device/pci_ops.h> -#include <cpu/p6/msr.h> +#include <cpu/x86/msr.h> +#include <part/hard_reset.h> +#include <device/smbus.h> +#include <delay.h> #include <arch/io.h> #include <device/chip.h> #include "../../../northbridge/amd/amdk8/northbridge.h" +#include "../../../northbridge/amd/amdk8/cpu_rev.c" #include "chip.h" #include "pc80/mc146818rtc.h" - -unsigned long initial_apicid[CONFIG_MAX_CPUS] = +#undef DEBUG +#define DEBUG 0 +#if DEBUG +static void debug_init(device_t dev) { - 0, 1, -}; + unsigned bus; + unsigned devfn; +#if 0 + for(bus = 0; bus < 256; bus++) { + for(devfn = 0; devfn < 256; devfn++) { + int i; + dev = dev_find_slot(bus, devfn); + if (!dev) { + continue; + } + if (!dev->enabled) { + continue; + } + printk_info("%02x:%02x.%0x aka %s\n", + bus, devfn >> 3, devfn & 7, dev_path(dev)); + for(i = 0; i < 256; i++) { + if ((i & 0x0f) == 0) { + printk_info("%02x:", i); + } + printk_info(" %02x", pci_read_config8(dev, i)); + if ((i & 0x0f) == 0xf) { + printk_info("\n"); + } + } + printk_info("\n"); + } + } +#endif +#if 0 + msr_t msr; + unsigned index; + unsigned eax, ebx, ecx, edx; + index = 0x80000007; + printk_debug("calling cpuid 0x%08x\n", index); + asm volatile( + "cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "a" (index) + ); + printk_debug("cpuid[%08x]: %08x %08x %08x %08x\n", + index, eax, ebx, ecx, edx); + if (edx & (3 << 1)) { + index = 0xC0010042; + printk_debug("Reading msr: 0x%08x\n", index); + msr = rdmsr(index); + printk_debug("msr[0x%08x]: 0x%08x%08x\n", + index, msr.hi, msr.hi); + } +#endif +} -#define SMBGSTATUS 0xe0 -#define SMBGCTL 0xe2 -#define SMBHSTADDR 0xe4 -#define SMBHSTDAT 0xe6 -#define SMBHSTCMD 0xe8 -#define SMBHSTFIFO 0xe9 +static void debug_noop(device_t dummy) +{ +} -#define SMBUS_TIMEOUT (100*1000*10) +static struct device_operations debug_operations = { + .read_resources = debug_noop, + .set_resources = debug_noop, + .enable_resources = debug_noop, + .init = debug_init, +}; -static inline void smbus_delay(void) +static unsigned int scan_root_bus(device_t root, unsigned int max) { - outb(0x80, 0x80); + struct device_path path; + device_t debug; + max = root_dev_scan_bus(root, max); + path.type = DEVICE_PATH_PNP; + path.u.pnp.port = 0; + path.u.pnp.device = 0; + debug = alloc_dev(&root->link[1], &path); + debug->ops = &debug_operations; + return max; } +#endif -static int smbus_wait_until_ready(unsigned smbus_io_base) +#if 0 +static void handle_smbus_error(int value, const char *msg) { - unsigned long loops; - loops = SMBUS_TIMEOUT; - do { - unsigned short val; - smbus_delay(); - val = inw(smbus_io_base + SMBGSTATUS); - if ((val & 0x800) == 0) { - break; - } - if(loops == (SMBUS_TIMEOUT / 2)) { - outw(inw(smbus_io_base + SMBGSTATUS), - smbus_io_base + SMBGSTATUS); - } - } while(--loops); - return loops?0:-2; + if (value >= 0) { + return; + } + switch(value) { + case SMBUS_WAIT_UNTIL_READY_TIMEOUT: + printk_emerg("SMBUS wait until ready timed out - resetting..."); + hard_reset(); + break; + case SMBUS_WAIT_UNTIL_DONE_TIMEOUT: + printk_emerg("SMBUS wait until done timed out - resetting..."); + hard_reset(); + break; + default: + die(msg); + break; + } } -static int smbus_wait_until_done(unsigned smbus_io_base) +#define ADM1026_DEVICE 0x2c /* 0x2e or 0x2d */ +#define ADM1026_REG_CONFIG1 0x00 +#define CFG1_MONITOR 0x01 +#define CFG1_INT_ENABLE 0x02 +#define CFG1_INT_CLEAR 0x04 +#define CFG1_AIN8_9 0x08 +#define CFG1_THERM_HOT 0x10 +#define CFT1_DAC_AFC 0x20 +#define CFG1_PWM_AFC 0x40 +#define CFG1_RESET 0x80 +#define ADM1026_REG_CONFIG2 0x01 +#define ADM1026_REG_CONFIG3 0x07 + + + +#define BILLION 1000000000UL + +static void verify_cpu_voltage(const char *name, + device_t dev, unsigned int reg, + unsigned factor, unsigned cpu_volts, unsigned delta) { - unsigned long loops; - loops = SMBUS_TIMEOUT; + unsigned nvolts_lo, nvolts_hi; + unsigned cpuvolts_hi, cpuvolts_lo; + int value; + int loops; + + loops = 1000; do { - unsigned short val; - smbus_delay(); + value = smbus_read_byte(dev, reg); + handle_smbus_error(value, "SMBUS read byte failed"); + } while ((--loops > 0) && value == 0); + /* Convert the byte value to nanoVolts. + * My accuracy is nowhere near that good but I don't + * have to round so the math is simple. + * I can only go up to about 4.2 Volts this way so my range is + * limited. + */ + nvolts_lo = ((unsigned)value * factor); + nvolts_hi = nvolts_lo + factor - 1; + /* Get the range of acceptable cpu voltage values */ + cpuvolts_lo = cpu_volts - delta; + cpuvolts_hi = cpu_volts + delta; + if ((nvolts_lo < cpuvolts_lo) || (nvolts_hi > cpuvolts_hi)) { + printk_emerg("%s at (%u.%09u-%u.%09u)Volts expected %u.%09u+/-%u.%09uVolts\n", + name, + nvolts_lo/BILLION, nvolts_lo%BILLION, + nvolts_hi/BILLION, nvolts_hi%BILLION, + cpu_volts/BILLION, cpu_volts%BILLION, + delta/BILLION, delta%BILLION); + die(""); + } + printk_info("%s at (%u.%09u-%u.%09u)Volts\n", + name, + nvolts_lo/BILLION, nvolts_lo%BILLION, + nvolts_hi/BILLION, nvolts_hi%BILLION); - val = inw(smbus_io_base + SMBGSTATUS); - if (((val & 0x8) == 0) | ((val & 0x437) != 0)) { - break; - } - } while(--loops); - return loops?0:-3; } -static int smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned value) +static void adm1026_enable_monitoring(device_t dev) { - unsigned char global_status_register; + int result; + result = smbus_read_byte(dev, ADM1026_REG_CONFIG1); + handle_smbus_error(result, "ADM1026: cannot read config1"); + + result = (result | CFG1_MONITOR) & ~(CFG1_INT_CLEAR | CFG1_RESET); + result = smbus_write_byte(dev, ADM1026_REG_CONFIG1, result); + handle_smbus_error(result, "ADM1026: cannot write to config1"); + + result = smbus_read_byte(dev, ADM1026_REG_CONFIG1); + handle_smbus_error(result, "ADM1026: cannot reread config1"); + if (!(result & CFG1_MONITOR)) { + die("ADM1026: monitoring would not enable"); + } +} - if (smbus_wait_until_ready(smbus_io_base) < 0) { - return -2; + +static unsigned k8_cpu_volts(void) +{ + unsigned volts = ~0; + if (is_cpu_c0()) { + volts = 1500000000; } - - /* setup transaction */ - /* disable interrupts */ - outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL); - /* set the device I'm talking too */ - outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); - /* set the command/address... */ - outb(0, smbus_io_base + SMBHSTCMD); - /* set up for a send byte */ - outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL); - - /* clear any lingering errors, so the transaction will run */ - /* Do I need to write the bits to a 1 to clear an error? */ - outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); - - /* set the data word...*/ - outw(value, smbus_io_base + SMBHSTDAT); - - /* start the command */ - outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); - - - /* poll for transaction completion */ - if (smbus_wait_until_done(smbus_io_base) < 0) { - return -3; + if (is_cpu_b3()) { + volts = 1550000000; } - global_status_register = inw(smbus_io_base + SMBGSTATUS); + return volts; +} - if (global_status_register != (1 << 4)) { - return -1; +static void verify_cpu_voltages(device_t dev) +{ + unsigned cpu_volts; + unsigned delta; +#if 0 + delta = 50000000; +#else + delta = 75000000; +#endif + cpu_volts = k8_cpu_volts(); + if (cpu_volts == ~0) { + printk_info("Required cpu voltage unknwon not checking\n"); + return; } - return 0; + /* I need to read registers 0x37 == Ain7CPU1 core 0x2d == VcppCPU0 core */ + /* CPU1 core + * The sensor has a range of 0-2.5V and reports in + * 256 distinct steps. + */ + verify_cpu_voltage("CPU1 Vcore", dev, 0x37, 9765625, + cpu_volts, delta); + /* CPU0 core + * The sensor has range of 0-3.0V and reports in + * 256 distinct steps. + */ + verify_cpu_voltage("CPU0 Vcore", dev, 0x2d, 11718750, + cpu_volts, delta); } -static int smbus_recv_byte(unsigned smbus_io_base, unsigned device) -{ - unsigned char global_status_register; - unsigned char byte; +#define SMBUS_MUX 0x70 if (smbus_wait_until_ready(smbus_io_base) < 0) { return -2; } - /* setup transaction */ - /* disable interrupts */ - outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL); - /* set the device I'm talking too */ - outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); - /* set the command/address... */ - outb(0, smbus_io_base + SMBHSTCMD); - /* set up for a send byte */ - outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL); - - /* clear any lingering errors, so the transaction will run */ - /* Do I need to write the bits to a 1 to clear an error? */ - outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); - - /* set the data word...*/ - outw(0, smbus_io_base + SMBHSTDAT); - - /* start the command */ - outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); - - - /* poll for transaction completion */ - if (smbus_wait_until_done(smbus_io_base) < 0) { - return -3; + /* Find the smbus mux */ + mux_path.type = DEVICE_PATH_I2C; + mux_path.u.i2c.device = SMBUS_MUX; + mux = find_dev_path(smbus_dev, &mux_path); + if (!mux) { + die("SMBUS mux not found\n"); } global_status_register = inw(smbus_io_base + SMBGSTATUS); @@ -165,119 +271,54 @@ static int smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned add return -2; } - /* setup transaction */ - /* disable interrupts */ - outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL); - /* set the device I'm talking too */ - outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); - /* set the command/address... */ - outb(address & 0xFF, smbus_io_base + SMBHSTCMD); - /* set up for a byte data read */ - outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x2), smbus_io_base + SMBGCTL); - - /* clear any lingering errors, so the transaction will run */ - /* Do I need to write the bits to a 1 to clear an error? */ - outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); - - /* clear the data word...*/ - outw(0, smbus_io_base + SMBHSTDAT); - - /* start the command */ - outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); - - - /* poll for transaction completion */ - if (smbus_wait_until_done(smbus_io_base) < 0) { - return -3; + /* Set the mux to see the temperature sensors */ + mux_setting = 1; + result = smbus_send_byte(mux, mux_setting); + handle_smbus_error(result, "SMBUS send byte failed\n"); + + result = smbus_recv_byte(mux); + handle_smbus_error(result, "SMBUS recv byte failed\n"); + if (result != mux_setting) { + printk_emerg("SMBUS mux would not set to %d\n", mux_setting); + die(""); } - global_status_register = inw(smbus_io_base + SMBGSTATUS); + adm1026_enable_monitoring(sensor); - /* read results of transaction */ - byte = inw(smbus_io_base + SMBHSTDAT) & 0xff; + /* It takes 11.38ms to read a new voltage sensor value */ + mdelay(12); - if (global_status_register != (1 << 4)) { - return -1; - } - return byte; -} - -static int smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val) -{ - if (smbus_wait_until_ready(smbus_io_base) < 0) { - return -2; - } - - /* setup transaction */ - /* disable interrupts */ - outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), - smbus_io_base + SMBGCTL); - /* set the device I'm talking too */ - outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); - outb(address & 0xFF, smbus_io_base + SMBHSTCMD); - /* set up for a byte data write */ /* FIXME */ - outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL); - /* clear any lingering errors, so the transaction will run */ - /* Do I need to write the bits to a 1 to clear an error? */ - outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS); - - /* clear the data word...*/ - outw(val, smbus_io_base + SMBHSTDAT); - - /* start the command */ - outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL); - - /* poll for transaction completion */ - if (smbus_wait_until_done(smbus_io_base) < 0) { - return -3; - } - return 0; + /* Read the cpu voltages and make certain everything looks sane */ + verify_cpu_voltages(sensor); } +#else +#define do_verify_cpu_voltages() do {} while(0) #endif -#define SMBUS_MUX 0x70 static void mainboard_init(device_t dev) { - /* Set the mux to see the temperature sensors */ - dev = dev_find_device(0x1022, 0x746b, 0); - if (dev) { - unsigned smbus_io_base; - unsigned device; - int result; - int mux_setting; - device = SMBUS_MUX; - mux_setting = 1; - smbus_io_base = pci_read_config32(dev, 0x58) & ~1;; - result = smbus_send_byte(smbus_io_base, device, mux_setting); - if ((result < 0) || - (smbus_recv_byte(smbus_io_base, device) != mux_setting)) { - printk_err("SMBUS mux would not set to %d\n", mux_setting); - } - - } - else { - printk_err("SMBUS_controller not found\n"); - } + root_dev_init(dev); + + do_verify_cpu_voltages(); } static struct device_operations mainboard_operations = { .read_resources = root_dev_read_resources, .set_resources = root_dev_set_resources, - .enable_resources = enable_childrens_resources, + .enable_resources = root_dev_enable_resources, .init = mainboard_init, - .scan_bus = amdk8_scan_root_bus, +#if !DEBUG + .scan_bus = root_dev_scan_bus, +#else + .scan_bus = scan_root_bus, +#endif .enable = 0, }; static void enumerate(struct chip *chip) { - struct chip *child; dev_root.ops = &mainboard_operations; - chip->dev = &dev_root; - chip->bus = 0; - for(child = chip->children; child; child = child->next) { - child->bus = &dev_root.link[0]; - } + chip_enumerate(chip); } struct chip_control mainboard_arima_hdama_control = { .enumerate = enumerate, diff --git a/src/mainboard/arima/hdama/mptable.c b/src/mainboard/arima/hdama/mptable.c index 6c2f7fa718..a9c5cbfea2 100644 --- a/src/mainboard/arima/hdama/mptable.c +++ b/src/mainboard/arima/hdama/mptable.c @@ -4,7 +4,7 @@ #include <string.h> #include <stdint.h> -void *smp_write_config_table(void *v, unsigned long * processor_map) +void *smp_write_config_table(void *v) { static const char sig[4] = "PCMP"; static const char oem[8] = "LNXI "; @@ -33,7 +33,7 @@ void *smp_write_config_table(void *v, unsigned long * processor_map) mc->mpe_checksum = 0; mc->reserved = 0; - smp_write_processors(mc, processor_map); + smp_write_processors(mc); { device_t dev; @@ -44,7 +44,8 @@ void *smp_write_config_table(void *v, unsigned long * processor_map) bus_8111_1 = pci_read_config8(dev, PCI_SECONDARY_BUS); bus_isa = pci_read_config8(dev, PCI_SUBORDINATE_BUS); bus_isa++; - } else { + } + else { printk_debug("ERROR - could not find PCI 1:03.0, using defaults\n"); bus_8111_1 = 4; @@ -54,15 +55,20 @@ void *smp_write_config_table(void *v, unsigned long * processor_map) dev = dev_find_slot(1, PCI_DEVFN(0x01,0)); if (dev) { bus_8131_1 = pci_read_config8(dev, PCI_SECONDARY_BUS); - } else { + + } + else { printk_debug("ERROR - could not find PCI 1:01.0, using defaults\n"); + bus_8131_1 = 2; } /* 8131-2 */ dev = dev_find_slot(1, PCI_DEVFN(0x02,0)); if (dev) { bus_8131_2 = pci_read_config8(dev, PCI_SECONDARY_BUS); - } else { + + } + else { printk_debug("ERROR - could not find PCI 1:02.0, using defaults\n"); bus_8131_2 = 3; @@ -79,20 +85,22 @@ void *smp_write_config_table(void *v, unsigned long * processor_map) smp_write_ioapic(mc, 2, 0x11, 0xfec00000); { device_t dev; - uint32_t base; - /* 8131-1 apic #3 */ + struct resource *res; + /* 8131 apic 3 */ dev = dev_find_slot(1, PCI_DEVFN(0x01,1)); if (dev) { - base = pci_read_config32(dev, PCI_BASE_ADDRESS_0); - base &= PCI_BASE_ADDRESS_MEM_MASK; - smp_write_ioapic(mc, 0x03, 0x11, base); + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + smp_write_ioapic(mc, 0x03, 0x11, res->base); + } } - /* 8131-2 apic #4 */ + /* 8131 apic 4 */ dev = dev_find_slot(1, PCI_DEVFN(0x02,1)); if (dev) { - base = pci_read_config32(dev, PCI_BASE_ADDRESS_0); - base &= PCI_BASE_ADDRESS_MEM_MASK; - smp_write_ioapic(mc, 0x04, 0x11, base); + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + smp_write_ioapic(mc, 0x04, 0x11, res->base); + } } } @@ -193,14 +201,14 @@ void *smp_write_config_table(void *v, unsigned long * processor_map) mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length); mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length); printk_debug("Wrote the mp table end at: %p - %p\n", - mc, smp_next_mpe_entry(mc)); + mc, smp_next_mpe_entry(mc)); return smp_next_mpe_entry(mc); } -unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map) +unsigned long write_smp_table(unsigned long addr) { void *v; v = smp_write_floating_table(addr); - return (unsigned long)smp_write_config_table(v, processor_map); + return (unsigned long)smp_write_config_table(v); } diff --git a/src/northbridge/amd/amdk8/cpu_rev.c b/src/northbridge/amd/amdk8/cpu_rev.c index 0c4c5f8fbd..15b4cf6318 100644 --- a/src/northbridge/amd/amdk8/cpu_rev.c +++ b/src/northbridge/amd/amdk8/cpu_rev.c @@ -1,30 +1,25 @@ -/* this is a shrunken cpuid. */ - -static unsigned int cpuid(unsigned int op) +#include <arch/cpu.h> +static int is_cpu_rev_a0(void) { - unsigned int ret; - unsigned dummy2,dummy3,dummy4; - - asm volatile ( - "cpuid" - : "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4) - : "a" (op) - ); - - return ret; + return (cpuid_eax(1) & 0xffef) == 0x0f00; } -static int is_cpu_rev_a0(void) +static int is_cpu_pre_c0(void) { - return (cpuid(1) & 0xffef) == 0x0f00; + return (cpuid_eax(1) & 0xffef) < 0x0f48; } -static int is_cpu_pre_c0(void) +static int is_cpu_c0(void) { - return (cpuid(1) & 0xffef) < 0x0f48; + return (cpuid_eax(1) & 0xffef) == 0x0f48; } static int is_cpu_pre_b3(void) { - return (cpuid(1) & 0xffef) < 0x0f41; + return (cpuid_eax(1) & 0xffef) < 0x0f41; +} + +static int is_cpu_b3(void) +{ + return (cpuid_eax(1) & 0xffef) == 0x0f41; } diff --git a/src/northbridge/amd/amdk8/misc_control.c b/src/northbridge/amd/amdk8/misc_control.c index 0fe2cc5460..4938c453d7 100644 --- a/src/northbridge/amd/amdk8/misc_control.c +++ b/src/northbridge/amd/amdk8/misc_control.c @@ -15,6 +15,8 @@ #include <device/pci_ids.h> #include <device/pci_ops.h> #include <part/hard_reset.h> +#include <pc80/mc146818rtc.h> +#include <bitops.h> #include "./cpu_rev.c" #include "amdk8.h" @@ -35,7 +37,7 @@ static void mcf3_read_resources(device_t dev) { struct resource *resource; - + unsigned char iommu; /* Read the generic PCI resources */ pci_dev_read_resources(dev); @@ -43,58 +45,60 @@ static void mcf3_read_resources(device_t dev) if (dev->path.u.pci.devfn != PCI_DEVFN(0x18, 0x3)) { return; } - - /* Add a Gart apeture resource */ - if (dev->resources < MAX_RESOURCES) { - resource = &dev->resource[dev->resources]; - dev->resources++; - resource->base = 0; - resource->size = AGP_APERTURE_SIZE; + + iommu = 1; + get_option(&iommu, "iommu"); + + if (iommu) { + /* Add a Gart apeture resource */ + resource = new_resource(dev, 0x94); + resource->size = iommu?AGP_APERTURE_SIZE:1; resource->align = log2(resource->size); resource->gran = log2(resource->size); resource->limit = 0xffffffff; /* 4G */ resource->flags = IORESOURCE_MEM; - resource->index = 0x94; - } else { - printk_err("%s Unexpeted resource shortage\n", dev_path(dev)); } } -static void set_agp_aperture(device_t dev, struct resource *resource) +static void set_agp_aperture(device_t dev) { - device_t pdev; - uint32_t base; - uint32_t size; + struct resource *resource; - size = (0<<6)|(0<<5)|(0<<4)| ((log2(resource->size) - 25) << 1)|(0<<0); - base = ((resource->base) >> 25) & 0x00007fff; - pdev = 0; - - /* A search for MISC Control device is neceressary */ - while (pdev = dev_find_device(PCI_VENDOR_ID_AMD, 0x1103, pdev)) { - pci_write_config32(pdev, 0x90, size); - pci_write_config32(pdev, 0x94, base); - /* Don't set the GART Table base address */ - pci_write_config32(pdev, 0x98, 0); - - printk_debug("%s %02x <- [0x%08lx - 0x%08lx] mem <gart>\n", - dev_path(pdev), resource->index, resource->base, - resource->base + resource->size - 1); + resource = probe_resource(dev, 0x94); + if (resource) { + device_t pdev; + uint32_t gart_base, gart_acr; + /* Remember this resource has been stored */ + resource->flags |= IORESOURCE_STORED; + + /*Find the size of the GART aperture */ + gart_acr = (0<<6)|(0<<5)|(0<<4)| ((log2(resource->size) - 25) << 1)|(0<<0); + + /* Get the base address */ + gart_base = ((resource->base) >> 25) & 0x00007fff; + + /* Update the other northbriges */ + pdev = 0; + while (pdev = dev_find_device(PCI_VENDOR_ID_AMD, 0x1103, pdev)) { + /* Store GART size but don't enable it */ + pci_write_config32(pdev, 0x90, gart_acr); + + /* Store the GART base address */ + pci_write_config32(pdev, 0x94, gart_base); + + /* Don't set the GART Table base address */ + pci_write_config32(pdev, 0x98, 0); + + /* Report the resource has been stored... */ + report_resource_stored(pdev, resource, " <gart>"); + } } - /* Remember this resource has been stored */ - resource->flags |= IORESOURCE_STORED; } static void mcf3_set_resources(device_t dev) { - struct resource *resource, *last; - - last = &dev->resource[dev->resources]; - for (resource = &dev->resource[0]; resource < last; resource++) { - if (resource->index == 0x94) { - set_agp_aperture(dev, resource); - } - } + /* Set the gart apeture */ + set_agp_aperture(dev); /* Set the generic PCI resources */ pci_dev_set_resources(dev); diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c index 89a4092168..4933b161b7 100644 --- a/src/northbridge/amd/amdk8/northbridge.c +++ b/src/northbridge/amd/amdk8/northbridge.c @@ -2,7 +2,6 @@ #include <arch/io.h> #include <stdint.h> #include <mem.h> -#include <part/sizeram.h> #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> @@ -15,121 +14,41 @@ #include "northbridge.h" #include "amdk8.h" -struct mem_range *sizeram(void) -{ - unsigned long mmio_basek; - static struct mem_range mem[10]; - device_t dev; - int i, idx; - -#warning "FIXME handle interleaved nodes" - dev = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - if (!dev) { - printk_err("Cannot find PCI: 0:18.1\n"); - return 0; - } - mmio_basek = (dev_root.resource[1].base >> 10); - /* Round mmio_basek to something the processor can support */ - mmio_basek &= ~((1 << 6) -1); - -#if 1 -#warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole" - /* Round the mmio hold to 256M */ - mmio_basek &= ~((256*1024) - 1); -#endif - -#if 0 - printk_debug("mmio_base: %dKB\n", mmio_basek); -#endif - - for (idx = i = 0; i < 8; i++) { - uint32_t base, limit; - unsigned basek, limitk, sizek; - base = pci_read_config32(dev, 0x40 + (i<<3)); - limit = pci_read_config32(dev, 0x44 + (i<<3)); - if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { - continue; - } - basek = (base & 0xffff0000) >> 2; - limitk = ((limit + 0x00010000) & 0xffff0000) >> 2; - sizek = limitk - basek; - if ((idx > 0) && - ((mem[idx - 1].basek + mem[idx - 1].sizek) == basek)) { - mem[idx -1].sizek += sizek; - } 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))) /* 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; - idx++; - } - - /* 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)) { - if (mem[idx - 1].basek < mmio_basek) { - unsigned pre_sizek; - pre_sizek = mmio_basek - mem[idx - 1].basek; - mem[idx].basek = mmio_basek; - mem[idx].sizek = mem[idx - 1].sizek - pre_sizek; - mem[idx - 1].sizek = pre_sizek; - idx++; - } - if ((mem[idx - 1].basek + mem[idx - 1].sizek) <= 4*1024*1024) { - idx -= 1; - } else { - mem[idx - 1].basek = 4*1024*1024; - mem[idx - 1].sizek -= (4*1024*1024 - mmio_basek); - } - } - } -#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); - } -#endif - while (idx < sizeof(mem)/sizeof(mem[0])) { - mem[idx].basek = 0; - mem[idx].sizek = 0; - idx++; - } - return mem; -} +#define DEVICE_MEM_HIGH 0xFEC00000ULL /* Reserve 20M for the system */ +#define DEVICE_IO_START 0x1000 -#define F1_DEVS 8 -static device_t __f1_dev[F1_DEVS]; +#define FX_DEVS 8 +static device_t __f0_dev[FX_DEVS]; +static device_t __f1_dev[FX_DEVS]; #if 0 -static void debug_f1_devs(void) +static void debug_fx_devs(void) { int i; - for (i = 0; i < F1_DEVS; i++) { + for(i = 0; i < FX_DEVS; i++) { device_t dev; + dev = __f0_dev[i]; + if (dev) { + printk_debug("__f0_dev[%d]: %s bus: %p\n", + i, dev_path(dev), dev->bus); + } dev = __f1_dev[i]; if (dev) { printk_debug("__f1_dev[%d]: %s bus: %p\n", - i, dev_path(dev), dev->bus); + i, dev_path(dev), dev->bus); } } } #endif -static void get_f1_devs(void) +static void get_fx_devs(void) { int i; if (__f1_dev[0]) { return; } - for (i = 0; i < F1_DEVS; i++) { + for(i = 0; i < FX_DEVS; i++) { + __f0_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0)); __f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1)); } if (!__f1_dev[0]) { @@ -139,18 +58,18 @@ static void get_f1_devs(void) static uint32_t f1_read_config32(unsigned reg) { - get_f1_devs(); + get_fx_devs(); return pci_read_config32(__f1_dev[0], reg); } static void f1_write_config32(unsigned reg, uint32_t value) { int i; - get_f1_devs(); - for (i = 0; i < F1_DEVS; i++) { + get_fx_devs(); + for(i = 0; i < FX_DEVS; i++) { device_t dev; dev = __f1_dev[i]; - if (dev) { + if (dev && dev->enabled) { pci_write_config32(dev, reg, value); } } @@ -165,12 +84,12 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) { unsigned nodeid; unsigned link; - nodeid = amdk8_nodeid(dev); - - printk_spew("amdk8_scan_chains max: %d starting...\n", max); - - for (link = 0; link < dev->links; link++) { +#if 0 + printk_debug("%s amdk8_scan_chains max: %d starting...\n", + dev_path(dev), max); +#endif + for(link = 0; link < dev->links; link++) { uint32_t link_type; uint32_t busses, config_busses; unsigned free_reg, config_reg; @@ -187,10 +106,9 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) if (!(link_type & NonCoherent)) { continue; } - /* See if there is an available configuration space mapping register - * in function 1. */ + /* See if there is an available configuration space mapping register in function 1. */ free_reg = 0; - for (config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) { + for(config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) { uint32_t config; config = f1_read_config32(config_reg); if (!free_reg && ((config & 3) == 0)) { @@ -198,23 +116,22 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) continue; } if (((config & 3) == 3) && - (((config >> 4) & 7) == nodeid) && - (((config >> 8) & 3) == link)) { + (((config >> 4) & 7) == nodeid) && + (((config >> 8) & 3) == link)) { break; } } if (free_reg && (config_reg > 0xec)) { config_reg = free_reg; } - /* If we can't find an available configuration space mapping - * register skip this bus */ + /* If we can't find an available configuration space mapping register skip this bus */ if (config_reg > 0xec) { continue; } - /* Set up the primary, secondary and subordinate bus numbers. - * We have no idea how many busses are behind this bridge yet, - * so we set the subordinate bus number to 0xff for the moment. + /* Set up the primary, secondary and subordinate bus numbers. We have + * no idea how many busses are behind this bridge yet, so we set the subordinate + * bus number to 0xff for the moment. */ dev->link[link].secondary = ++max; dev->link[link].subordinate = 0xff; @@ -226,8 +143,8 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) config_busses = f1_read_config32(config_reg); /* Configure the bus numbers for this bridge: the configuration - * transactions will not be propagates by the bridge if it is - * not correctly configured + * transactions will not be propagates by the bridge if it is not + * correctly configured */ busses &= 0xff000000; busses |= (((unsigned int)(dev->bus->secondary) << 0) | @@ -244,145 +161,188 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max) ((dev->link[link].subordinate) << 24); f1_write_config32(config_reg, config_busses); - printk_spew("Hyper transport scan link: %d max: %d\n", - link, max); - - /* Now we can scan all of the subordinate busses i.e. the - * chain on the hypertranport link */ +#if 0 + printk_debug("%s Hyper transport scan link: %d max: %d\n", + dev_path(dev), link, max); +#endif + /* Now we can scan all of the subordinate busses i.e. the chain on the hypertranport link */ max = hypertransport_scan_chain(&dev->link[link], max); - printk_spew("Hyper transport scan link: %d new max: %d\n", - link, max); +#if 0 + printk_debug("%s Hyper transport scan link: %d new max: %d\n", + dev_path(dev), link, max); +#endif - /* We know the number of busses behind this bridge. Set the - * subordinate bus number to it's real value + /* We know the number of busses behind this bridge. Set the subordinate + * bus number to it's real value */ dev->link[link].subordinate = max; busses = (busses & 0xff00ffff) | ((unsigned int) (dev->link[link].subordinate) << 16); pci_write_config32(dev, dev->link[link].cap + 0x14, busses); - config_busses = (config_busses & 0x00ffffff) | - (dev->link[link].subordinate << 24); + config_busses = (config_busses & 0x00ffffff) | (dev->link[link].subordinate << 24); f1_write_config32(config_reg, config_busses); - printk_spew("Hypertransport scan link done\n"); +#if 0 + printk_debug("%s Hypertransport scan link: %d done\n", + dev_path(dev), link); +#endif } - - printk_spew("amdk8_scan_chains max: %d done\n", max); +#if 0 + printk_debug("%s amdk8_scan_chains max: %d done\n", + dev_path(dev), max); +#endif return max; } -static unsigned amdk8_find_iopair(unsigned nodeid, unsigned link) +static int reg_useable(unsigned reg, + device_t goal_dev, unsigned goal_nodeid, unsigned goal_link) { - unsigned free_reg, reg; + struct resource *res; + unsigned nodeid, link; + int result; + res = 0; + for(nodeid = 0; !res && (nodeid < 8); nodeid++) { + device_t dev; + dev = __f0_dev[nodeid]; + for(link = 0; !res && (link < 3); link++) { + res = probe_resource(dev, 0x100 + (reg | link)); + } + } + result = 2; + if (res) { + result = 0; + if ( (goal_link == (link - 1)) && + (goal_nodeid == (nodeid - 1)) && + (res->flags <= 1)) { + result = 1; + } + } +#if 0 + printk_debug("reg: %02x result: %d gnodeid: %u glink: %u nodeid: %u link: %u\n", + reg, result, + goal_nodeid, goal_link, + nodeid, link); +#endif + return result; +} + +static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link) +{ + struct resource *resource; + unsigned free_reg, reg; + resource = 0; free_reg = 0; - for (reg = 0xc0; reg <= 0xd8; reg += 0x8) { - uint32_t base, limit; - base = f1_read_config32(reg); - limit = f1_read_config32(reg + 0x4); - /* Do I have a free register */ - if (!free_reg && ((base & 3) == 0)) { - free_reg = reg; - } - /* Do I have a match for this node and link? */ - if (((base & 3) == 3) && - ((limit & 7) == nodeid) && - (((limit >> 4) & 3) == link)) { + for(reg = 0xc0; reg <= 0xd8; reg += 0x8) { + int result; + result = reg_useable(reg, dev, nodeid, link); + if (result == 1) { + /* I have been allocated this one */ break; } + else if (result > 1) { + /* I have a free register pair */ + free_reg = reg; + } } - /* If I didn't find an exact match return a free register */ if (reg > 0xd8) { reg = free_reg; } - /* Return an available I/O pair or 0 on failure */ - return reg; + if (reg > 0) { + resource = new_resource(dev, 0x100 + (reg | link)); + } + return resource; } -static unsigned amdk8_find_mempair(unsigned nodeid, unsigned link) +static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsigned link) { + struct resource *resource; unsigned free_reg, reg; - + resource = 0; free_reg = 0; - for (reg = 0x80; reg <= 0xb8; reg += 0x8) { - uint32_t base, limit; - base = f1_read_config32(reg); - limit = f1_read_config32(reg + 0x4); - /* Do I have a free register */ - if (!free_reg && ((base & 3) == 0)) { - free_reg = reg; - } - /* Do I have a match for this node and link? */ - if (((base & 3) == 3) && - ((limit & 7) == nodeid) && - (((limit >> 4) & 3) == link)) { + for(reg = 0x80; reg <= 0xb8; reg += 0x8) { + int result; + result = reg_useable(reg, dev, nodeid, link); + if (result == 1) { + /* I have been allocated this one */ break; } + else if (result > 1) { + /* I have a free register pair */ + free_reg = reg; + } } - /* If I didn't find an exact match return a free register */ if (reg > 0xb8) { reg = free_reg; } - /* Return an available I/O pair or 0 on failure */ - return reg; + if (reg > 0) { + resource = new_resource(dev, 0x100 + (reg | link)); + } + return resource; } - static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link) { - unsigned int reg = dev->resources; - unsigned index; + struct resource *resource; /* Initialize the io space constraints on the current bus */ - index = amdk8_find_iopair(nodeid, link); - if (index) { - dev->resource[reg].base = 0; - dev->resource[reg].size = 0; - dev->resource[reg].align = log2(HT_IO_HOST_ALIGN); - dev->resource[reg].gran = log2(HT_IO_HOST_ALIGN); - dev->resource[reg].limit = 0xffffUL; - dev->resource[reg].flags = IORESOURCE_IO; - dev->resource[reg].index = index | (link & 0x3); - compute_allocate_resource(&dev->link[link], &dev->resource[reg], - IORESOURCE_IO, IORESOURCE_IO); - reg++; + resource = amdk8_find_iopair(dev, nodeid, link); + if (resource) { + resource->base = 0; + resource->size = 0; + resource->align = log2(HT_IO_HOST_ALIGN); + resource->gran = log2(HT_IO_HOST_ALIGN); + resource->limit = 0xffffUL; + resource->flags = IORESOURCE_IO; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_IO, IORESOURCE_IO); + } + + /* Initialize the prefetchable memory constraints on the current bus */ + resource = amdk8_find_mempair(dev, nodeid, link); + if (resource) { + resource->base = 0; + resource->size = 0; + resource->align = log2(HT_MEM_HOST_ALIGN); + resource->gran = log2(HT_MEM_HOST_ALIGN); + resource->limit = 0xffffffffffULL; + resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM | IORESOURCE_PREFETCH); } /* Initialize the memory constraints on the current bus */ - index = amdk8_find_mempair(nodeid, link); - if (index) { - dev->resource[reg].base = 0; - dev->resource[reg].size = 0; - dev->resource[reg].align = log2(HT_MEM_HOST_ALIGN); - dev->resource[reg].gran = log2(HT_MEM_HOST_ALIGN); - dev->resource[reg].limit = 0xffffffffUL; - dev->resource[reg].flags = IORESOURCE_MEM; - dev->resource[reg].index = index | (link & 0x3); - compute_allocate_resource(&dev->link[link], &dev->resource[reg], - IORESOURCE_MEM, IORESOURCE_MEM); - reg++; - } - dev->resources = reg; + resource = amdk8_find_mempair(dev, nodeid, link); + if (resource) { + resource->base = 0; + resource->size = 0; + resource->align = log2(HT_MEM_HOST_ALIGN); + resource->gran = log2(HT_MEM_HOST_ALIGN); + resource->limit = 0xffffffffffULL; + resource->flags = IORESOURCE_MEM; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM); + } } static void amdk8_read_resources(device_t dev) { unsigned nodeid, link; nodeid = amdk8_nodeid(dev); - dev->resources = 0; - memset(&dev->resource, 0, sizeof(dev->resource)); - for (link = 0; link < dev->links; link++) { + for(link = 0; link < dev->links; link++) { if (dev->link[link].children) { amdk8_link_read_bases(dev, nodeid, link); } } } -static void amdk8_set_resource(device_t dev, struct resource *resource, - unsigned nodeid) +static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned nodeid) { - unsigned long rbase, rlimit; + resource_t rbase, rend; unsigned reg, link; + char buf[50]; /* Make certain the resource has actually been set */ if (!(resource->flags & IORESOURCE_ASSIGNED)) { @@ -398,28 +358,31 @@ static void amdk8_set_resource(device_t dev, struct resource *resource, if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO))) return; + /* Ensure I am actually looking at a resource of function 1 */ + if (resource->index < 0x100) { + return; + } /* Get the base address */ rbase = resource->base; /* Get the limit (rounded up) */ - rlimit = rbase + ((resource->size + resource->align - 1UL) & - ~(resource->align -1)) - 1UL; + rend = resource_end(resource); /* Get the register and link */ - reg = resource->index & ~3; + reg = resource->index & 0xfc; link = resource->index & 3; if (resource->flags & IORESOURCE_IO) { uint32_t base, limit; compute_allocate_resource(&dev->link[link], resource, - IORESOURCE_IO, IORESOURCE_IO); + IORESOURCE_IO, IORESOURCE_IO); base = f1_read_config32(reg); limit = f1_read_config32(reg + 0x4); base &= 0xfe000fcc; base |= rbase & 0x01fff000; base |= 3; limit &= 0xfe000fc8; - limit |= rlimit & 0x01fff000; + limit |= rend & 0x01fff000; limit |= (link & 3) << 4; limit |= (nodeid & 7); @@ -429,28 +392,31 @@ static void amdk8_set_resource(device_t dev, struct resource *resource, if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) { base |= PCI_IO_BASE_NO_ISA; } + f1_write_config32(reg + 0x4, limit); f1_write_config32(reg, base); - } else if (resource->flags & IORESOURCE_MEM) { + } + else if (resource->flags & IORESOURCE_MEM) { uint32_t base, limit; compute_allocate_resource(&dev->link[link], resource, - IORESOURCE_MEM, IORESOURCE_MEM); + IORESOURCE_MEM | IORESOURCE_PREFETCH, + resource->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)); base = f1_read_config32(reg); limit = f1_read_config32(reg + 0x4); base &= 0x000000f0; - base |= (rbase & 0xffff0000) >> 8; + base |= (rbase >> 8) & 0xffffff00; base |= 3; limit &= 0x00000048; - limit |= (rlimit & 0xffff0000) >> 8; + limit |= (rend >> 8) & 0xffffff00; limit |= (link & 3) << 4; limit |= (nodeid & 7); f1_write_config32(reg + 0x4, limit); f1_write_config32(reg, base); } resource->flags |= IORESOURCE_STORED; - printk_debug("%s %02x <- [0x%08lx - 0x%08lx] node %d link %d %s\n", - dev_path(dev), reg, rbase, rlimit, nodeid, link, - (resource->flags & IORESOURCE_IO)? "io": "mem"); + sprintf(buf, " <node %d link %d>", + nodeid, link); + report_resource_stored(dev, resource, buf); } static void amdk8_set_resources(device_t dev) @@ -462,11 +428,11 @@ static void amdk8_set_resources(device_t dev) nodeid = amdk8_nodeid(dev); /* Set each resource we have found */ - for (i = 0; i < dev->resources; i++) { + for(i = 0; i < dev->resources; i++) { amdk8_set_resource(dev, &dev->resource[i], nodeid); } - - for (link = 0; link < dev->links; link++) { + + for(link = 0; link < dev->links; link++) { struct bus *bus; bus = &dev->link[link]; if (bus->children) { @@ -475,48 +441,15 @@ static void amdk8_set_resources(device_t dev) } } -/** - * @brief Scan root bus for AMD K8 systems - * - * @param root the root device structure - * @max the current bus number scanned so far, usually 0x00 - * - * The root device in a AMD K8 system is not at Bus 0, Device 0, Fun 0 - * as other PCI based systems. The northbridge is at Bus 0, Device 0x18, - * Fun 0. We have to call the pci_scan_bus() with PCI_DEVFN(0x18,0) as - * the starting device instead of PCI_DEVFN(0x00, 0) as in the default - * root_dev_scan_pci_bus(). - * - * This function is set up as the default scan_bus() method for mainboards' - * device_operations for AMD K8 mainboards in mainboard.c - * - * @see device_operation() - * @see root_dev_scan_pci_bus() - */ -unsigned int amdk8_scan_root_bus(device_t root, unsigned int max) -{ - unsigned reg; - - printk_spew("amdk8_scan_root_bus\n"); - - /* Unmap all of the HT chains by clearing the Configuration - * Map registers */ - for (reg = 0xe0; reg <= 0xec; reg += 4) { - f1_write_config32(reg, 0); - } - - max = pci_scan_bus(&root->link[0], PCI_DEVFN(0x18, 0), 0xff, max); - - printk_spew("amdk8_scan_root_bus: done\n"); - return max; -} static void mcf0_control_init(struct device *dev) { uint32_t cmd; -#if 1 - printk_spew("NB: Function 0 Misc Control.. "); +#if 0 + printk_debug("NB: Function 0 Misc Control.. "); +#endif +#if 1 /* improve latency and bandwith on HT */ cmd = pci_read_config32(dev, 0x68); cmd &= 0xffff80ff; @@ -530,82 +463,306 @@ static void mcf0_control_init(struct device *dev) cmd &= 0xfffff0ff; cmd |= 0x00000600; pci_write_config32(dev, 0xdc, cmd ); -#endif - - printk_spew("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); - pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl); - -#if 1 - /* No, don;t do it here, we should create phantom PCI resource - * for leagcy VGA resources in VGA device driver and use the - * generic resource allocation/assignment code to do it - * - * TOO BAD, the generic resource allcation code refuses to do - * abything with VGA and the AMDK8 resource code does want - * more than one discontinous IO/MEM regions */ - - /* 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) { - uint32_t base, limit; - unsigned reg; - /* now allocate an MMPAIR and point it to the CPU0, - * LINK=vgalink */ - /* Set up mem pair - * FIXME: add amdk8_find_free_mempair() */ - //reg = amdk8_find_mempair(0, vgalink); - reg = 0x90; - /* Set base of 0xa0000 */ - base = 0xa03; - limit = 0xd00 | (vgalink << 4); - printk_debug("setting MMIO routing for VGA reg:0x%x, base: 0x%x, limit 0x%x\n", - reg, base, limit); - f1_write_config32(reg, base); - f1_write_config32(reg + 4, limit); - } -#endif - - pci_dev_enable_resources(dev); +#endif + printk_debug("done.\n"); } static struct device_operations northbridge_operations = { .read_resources = amdk8_read_resources, .set_resources = amdk8_set_resources, - .enable_resources = amdk8_enable_resources, + .enable_resources = pci_dev_enable_resources, .init = mcf0_control_init, .scan_bus = amdk8_scan_chains, .enable = 0, + .ops_pci = 0, }; + static struct pci_driver mcf0_driver __pci_driver = { .ops = &northbridge_operations, .vendor = PCI_VENDOR_ID_AMD, .device = 0x1100, }; + +#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH) + +static void bridge_read_resources(device_t dev) +{ + struct resource *resource; + unsigned reg; + + /* Find the already assigned resource pairs */ + get_fx_devs(); + for(reg = 0x80; reg <= 0xd8; reg+= 0x08) { + uint32_t base, limit; + base = f1_read_config32(reg); + limit = f1_read_config32(reg + 0x04); + /* Is this register allocated? */ + if ((base & 3) != 0) { + unsigned nodeid, link; + device_t dev; + nodeid = limit & 7; + link = (limit >> 4) & 3; + dev = __f0_dev[nodeid]; + if (dev) { + /* Reserve the resource */ + struct resource *resource; + resource = new_resource(dev, 0x100 + (reg | link)); + if (resource) { + resource->flags = 1; + } + } + } + } + + /* Initialize the system wide io space constraints */ + resource = new_resource(dev, 0); + resource->base = 0x400; + resource->limit = 0xffffUL; + resource->flags = IORESOURCE_IO; + compute_allocate_resource(&dev->link[0], resource, + IORESOURCE_IO, IORESOURCE_IO); + + /* Initialize the system wide prefetchable memory resources constraints */ + resource = new_resource(dev, 1); + resource->limit = 0xfcffffffffULL; + resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; + compute_allocate_resource(&dev->link[0], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM | IORESOURCE_PREFETCH); + + /* Initialize the system wide memory resources constraints */ + resource = new_resource(dev, 2); + resource->limit = 0xfcffffffffULL; + resource->flags = IORESOURCE_MEM; + compute_allocate_resource(&dev->link[0], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM); +} + +static void ram_resource(device_t dev, unsigned long index, + unsigned long basek, unsigned long sizek) +{ + struct resource *resource; + + if (!sizek) { + return; + } + resource = new_resource(dev, index); + resource->base = ((resource_t)basek) << 10; + resource->size = ((resource_t)sizek) << 10; + resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \ + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; +} + +static void bridge_set_resources(device_t dev) +{ + struct resource *io, *mem1, *mem2; + struct resource *resource, *last; + unsigned long mmio_basek; + uint32_t pci_tolm; + int i, idx; + +#if 0 + /* Place the IO devices somewhere safe */ + io = find_resource(dev, 0); + io->base = DEVICE_IO_START; +#endif +#if 1 + /* Now reallocate the pci resources memory with the + * highest addresses I can manage. + */ + mem1 = find_resource(dev, 1); + mem2 = find_resource(dev, 2); + /* See if both resources have roughly the same limits */ + if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) || + (mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff)) + { + /* If so place the one with the most stringent alignment first + */ + if (mem2->align > mem1->align) { + struct resource *tmp; + tmp = mem1; + mem1 = mem2; + mem2 = mem1; + } + /* Now place the memory as high up as it will go */ + mem2->base = resource_max(mem2); + mem1->limit = mem2->base - 1; + mem1->base = resource_max(mem2); + } + else { + /* Place the resources as high up as they will go */ + mem2->base = resource_max(mem2); + mem1->base = resource_max(mem1); + } + +#if 1 + printk_debug("base1: 0x%08Lx limit1: 0x%08lx size: 0x%08Lx\n", + mem1->base, mem1->limit, mem1->size); + printk_debug("base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx\n", + mem2->base, mem2->limit, mem2->size); +#endif +#endif + pci_tolm = 0xffffffffUL; + last = &dev->resource[dev->resources]; + for(resource = &dev->resource[0]; resource < last; resource++) + { +#if 1 + resource->flags |= IORESOURCE_ASSIGNED; + resource->flags &= ~IORESOURCE_STORED; +#endif + compute_allocate_resource(&dev->link[0], resource, + BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK); + + resource->flags |= IORESOURCE_STORED; + report_resource_stored(dev, resource, ""); + + if ((resource->flags & IORESOURCE_MEM) && + (pci_tolm > resource->base)) + { + pci_tolm = resource->base; + } + } + +#warning "FIXME handle interleaved nodes" + mmio_basek = pci_tolm >> 10; + /* Round mmio_basek to something the processor can support */ + mmio_basek &= ~((1 << 6) -1); + +#if 1 +#warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole" + /* Round the mmio hold to 64M */ + mmio_basek &= ~((64*1024) - 1); +#endif + + idx = 10; + for(i = 0; i < 8; i++) { + uint32_t base, limit; + unsigned basek, limitk, sizek; + base = f1_read_config32(0x40 + (i << 3)); + limit = f1_read_config32(0x44 + (i << 3)); + if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { + continue; + } + basek = (base & 0xffff0000) >> 2; + limitk = ((limit + 0x00010000) & 0xffff0000) >> 2; + sizek = limitk - basek; + + /* see if we need a hole from 0xa0000 to 0xbffff */ + if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) { + ram_resource(dev, idx++, basek, ((8*64)+(8*16)) - basek); + basek = (8*64)+(16*16); + sizek = limitk - ((8*64)+(16*16)); + + } + + + /* See if I need to split the region to accomodate pci memory space */ + if ((basek < mmio_basek) && (limitk > mmio_basek)) { + if (basek < mmio_basek) { + unsigned pre_sizek; + pre_sizek = mmio_basek - basek; + ram_resource(dev, idx++, basek, pre_sizek); + sizek -= pre_sizek; + basek = mmio_basek; + } + if ((basek + sizek) <= 4*1024*1024) { + sizek = 0; + } + else { + basek = 4*1024*1024; + sizek -= (4*1024*1024 - mmio_basek); + } + } + ram_resource(dev, idx++, basek, sizek); + } + + assign_resources(&dev->link[0]); +} + + + +static unsigned int bridge_scan_bus(device_t root, unsigned int max) +{ + struct bus *cpu_bus; + unsigned reg; + int i; + /* Unmap all of the HT chains */ + for(reg = 0xe0; reg <= 0xec; reg += 4) { + f1_write_config32(reg, 0); + } + max = pci_scan_bus(&root->link[0], PCI_DEVFN(0x18, 0), 0xff, max); + + /* Find which cpus are present */ + cpu_bus = &dev_root.link[1]; + for(i = 0; i < 7; i++) { + device_t dev, cpu; + struct device_path cpu_path; + + /* Find the cpu's memory controller */ + dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0)); + + /* Build the cpu device path */ + cpu_path.type = DEVICE_PATH_APIC; + cpu_path.u.apic.apic_id = i; + + /* See if I can find the cpu */ + cpu = find_dev_path(cpu_bus, &cpu_path); + + /* Enable the cpu if I have the processor */ + if (dev && dev->enabled) { + if (!cpu) { + cpu = alloc_dev(cpu_bus, &cpu_path); + } + if (cpu) { + cpu->enabled = 1; + } + } + + /* Disable the cpu if I don't have the processor */ + if (cpu && (!dev || !dev->enabled)) { + cpu->enabled = 0; + } + + /* Report what I have done */ + if (cpu) { + printk_debug("CPU: %s %s\n", + dev_path(cpu), cpu->enabled?"enabled":"disabled"); + } + } + + return max; +} + + +static struct device_operations bridge_ops = { + .read_resources = bridge_read_resources, + .set_resources = bridge_set_resources, + .enable_resources = enable_childrens_resources, + .init = 0, + .scan_bus = bridge_scan_bus, +}; + static void enumerate(struct chip *chip) { + struct device_path path; + device_t bridge; chip_enumerate(chip); - chip->dev->ops = &northbridge_operations; + + /* Get the path for the bridge device */ + path.type = DEVICE_PATH_PNP; + path.u.pnp.port = 0xcf8; + path.u.pnp.device = 0; + + /* Lookup the bridge device */ + bridge = find_dev_path(&dev_root.link[0], &path); + + /* Set the bridge operations */ + if (bridge) { + bridge->ops = &bridge_ops; + } } struct chip_control northbridge_amd_amdk8_control = { |