diff --git a/arch/x86/Makefile b/arch/x86/Makefile index f6c4e24e51..efe67681d7 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -182,7 +182,7 @@ STAGE2_LIB_SRC = stage2.c clog2.c mem.c tables.c delay.c \ compute_ip_checksum.c string.c STAGE2_ARCH_X86_SRC = archtables.c coreboot_table.c udelay_io.c -STAGE2_ARCH_X86_SRC += pci_ops_auto.c pci_ops_conf1.c pci_ops_conf2.c +STAGE2_ARCH_X86_SRC += pci_ops_auto.c pci_ops_conf1.c STAGE2_ARCH_X86_SRC += keyboard.c i8259.c isa-dma.c ifeq ($(CONFIG_PIRQ_TABLE),y) diff --git a/arch/x86/pci_ops_auto.c b/arch/x86/pci_ops_auto.c index 556b23dbea..1fbc0f4c8c 100644 --- a/arch/x86/pci_ops_auto.c +++ b/arch/x86/pci_ops_auto.c @@ -22,7 +22,6 @@ static int pci_sanity_check(const struct pci_bus_operations *o) u16 class, vendor; unsigned bus; int devfn; - struct bus pbus; /* Dummy device */ #define PCI_CLASS_BRIDGE_HOST 0x0600 #define PCI_CLASS_DISPLAY_VGA 0x0300 #define PCI_VENDOR_ID_COMPAQ 0x0e11 @@ -30,8 +29,8 @@ static int pci_sanity_check(const struct pci_bus_operations *o) #define PCI_VENDOR_ID_MOTOROLA 0x1057 for (bus = 0, devfn = 0; devfn < 0x100; devfn++) { - class = o->read16(&pbus, bus, devfn, PCI_CLASS_DEVICE); - vendor = o->read16(&pbus, bus, devfn, PCI_VENDOR_ID); + class = o->read16(PCI_BDEVFN(bus, devfn), PCI_CLASS_DEVICE); + vendor = o->read16(PCI_BDEVFN(bus, devfn), PCI_VENDOR_ID); if (((class == PCI_CLASS_BRIDGE_HOST) || (class == PCI_CLASS_DISPLAY_VGA)) || ((vendor == PCI_VENDOR_ID_INTEL) || (vendor == PCI_VENDOR_ID_COMPAQ) || (vendor == PCI_VENDOR_ID_MOTOROLA))) { @@ -63,21 +62,6 @@ const struct pci_bus_operations *pci_check_direct(void) outl(tmp, 0xCF8); } - /* - * Check if configuration type 2 works. - */ - { - outb(0x00, 0xCFB); - outb(0x00, 0xCF8); - outb(0x00, 0xCFA); - if ((inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) && - pci_sanity_check(&pci_cf8_conf2)) - { - printk(BIOS_DEBUG, "PCI: Using configuration type 2\n"); - return &pci_cf8_conf2; - } - } - die("pci_check_direct failed\n"); return NULL; } diff --git a/arch/x86/pci_ops_conf1.c b/arch/x86/pci_ops_conf1.c index b0b0f19047..f50413ec0e 100644 --- a/arch/x86/pci_ops_conf1.c +++ b/arch/x86/pci_ops_conf1.c @@ -6,57 +6,151 @@ #include #include #include +/* + * This file is part of the coreboot project. + * It came from libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 coresystems GmbH + * Copyright (C) 2008 Ronald G. Minnich (conversion from libpayload to coreboot) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ /* * Functions for accessing PCI configuration space with type 1 accesses */ -/* this shit really should come with comments ...this is annoying. -#if PCI_IO_CFG_EXT == 0 -#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3)) -#else -#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | (devfn << 8) | ((where & 0xff) & ~3) | ((where & 0xf00)<<16) ) -#endif -*/ -#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3)) +/* The EXT is for extended register sets, i.e. chipsets that have more than 8 bits of registers */ +/* Here is one reason that overkill on types can bite you: Suppose we had insisted on u8 for 'where' for years. + * We would have to rewrite everything to grow 'where' to 12 bits! There is a reason that C uses 'int'. + * It's a good handy type meaning 'value suitable to the native machine register size' + * Also note these take a PCI_BDF -- meaning that the 'where' just needs to be 'or'ed in. + */ -static u8 pci_conf1_read_config8(struct bus *pbus, int bus, int devfn, int where) +#define PCI_IO_CFG_EXT 0 +#if PCI_IO_CFG_EXT +#define CONFIG_CMD(bdf, where) (0x80000000 | (bdf) | (where & ~3)) +#else +#define CONFIG_CMD(bdf, where) (0x80000000 | (bdf) | ((where & 0xff) & ~3) | ((where & 0xf00)<<16) ) +#endif + +static u8 pci_conf1_read_config8(u32 bdf, int where) { - outl(CONFIG_CMD(bus, devfn, where), 0xCF8); + outl(CONFIG_CMD(bdf, where), 0xCF8); return inb(0xCFC + (where & 3)); } -static u16 pci_conf1_read_config16(struct bus *pbus, int bus, int devfn, int where) +static u16 pci_conf1_read_config16(u32 bdf, int where) { - outl(CONFIG_CMD(bus, devfn, where), 0xCF8); + outl(CONFIG_CMD(bdf, where), 0xCF8); return inw(0xCFC + (where & 2)); } -static u32 pci_conf1_read_config32(struct bus *pbus, int bus, int devfn, int where) +static u32 pci_conf1_read_config32(u32 bdf, int where) { - outl(CONFIG_CMD(bus, devfn, where), 0xCF8); + outl(CONFIG_CMD(bdf, where), 0xCF8); return inl(0xCFC); } -static void pci_conf1_write_config8(struct bus *pbus, int bus, int devfn, int where, u8 value) +static void pci_conf1_write_config8(u32 bdf, int where, u8 value) { - outl(CONFIG_CMD(bus, devfn, where), 0xCF8); + outl(CONFIG_CMD(bdf, where), 0xCF8); outb(value, 0xCFC + (where & 3)); } -static void pci_conf1_write_config16(struct bus *pbus, int bus, int devfn, int where, u16 value) +static void pci_conf1_write_config16(u32 bdf, int where, u16 value) { - outl(CONFIG_CMD(bus, devfn, where), 0xCF8); + outl(CONFIG_CMD(bdf, where), 0xCF8); outw(value, 0xCFC + (where & 2)); } -static void pci_conf1_write_config32(struct bus *pbus, int bus, int devfn, int where, u32 value) +static void pci_conf1_write_config32(u32 bdf, int where, u32 value) { - outl(CONFIG_CMD(bus, devfn, where), 0xCF8); + outl(CONFIG_CMD(bdf, where), 0xCF8); outl(value, 0xCFC); } -#undef CONFIG_CMD +/** + * find a device given a vendor id and a device id. + * WARNING: the busdevfn is returned in a form suitable for use with the other functions in this file. + * THIS MEANS THAT THE bus is the top 16 bits, the devfn is the high byte of the low 16 bits. + * One can do this: + * u32 slot; + * find(vendor, device, &slot); + * pci_conf1_write_config32(slot, this, that); + * This is a low-level interface. If you are using the device tree, as in stage 2, you should not be + * calling this interface directly. + * We should consider a breadth-first search. The reason is that in almost all cases, + * the device you want in the coreboot context is on bus 0. + * + * @param vid vendor id + * @param did device ide + * @param busdevfn pointer to a u32 in which the slot is returned. + * @return 1 if found, 0 otherwise + */ + +static int find_on_bus(u16 bus, u16 vid, u16 did, u32 *busdevfn) + +{ + u16 devfn; + u32 val; + u8 hdr; + int bdf = bus << 16; + + /* skip over all the function sin a device -- multifunction devices always have one vendor */ + for (devfn = 0; devfn < 0x100; devfn += 8) { + u32 confaddr = bdf | (devfn << 8); + val = pci_conf1_read_config32(confaddr, PCI_VENDOR_ID); + + if (val == 0xffffffff || val == 0x00000000 || + val == 0x0000ffff || val == 0xffff0000) + continue; + + if (val == ((did << 16) | vid)) { + *busdevfn = confaddr; + return 1; + } + + hdr = pci_conf1_read_config8(confaddr, PCI_HEADER_TYPE); + hdr &= 0x7F; + + if (hdr == PCI_HEADER_TYPE_BRIDGE || hdr == PCI_HEADER_TYPE_CARDBUS) { + unsigned int busses; + busses = pci_conf1_read_config32(confaddr, PCI_PRIMARY_BUS); + if (find_on_bus((busses >> 8) & 0xFF, vid, did, busdevfn)) + return 1; + } + } + + return 0; +} + +static int pci_find_device(u16 vid, u16 did, u32 * dev) +{ + return find_on_bus(0, vid, did, dev); +} const struct pci_bus_operations pci_cf8_conf1 = { .read8 = pci_conf1_read_config8, @@ -65,4 +159,5 @@ const struct pci_bus_operations pci_cf8_conf1 = { .write8 = pci_conf1_write_config8, .write16 = pci_conf1_write_config16, .write32 = pci_conf1_write_config32, + .find = pci_find_device, }; diff --git a/arch/x86/pci_ops_conf2.c b/arch/x86/pci_ops_conf2.c deleted file mode 100644 index 2a7b4ca216..0000000000 --- a/arch/x86/pci_ops_conf2.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Functions for accessing PCI configuration space with type 2 accesses - */ - -#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where) -#define DEVFUNC(devfn) (((devfn & 7) << 1) | 0xf0) -#define SET(bus,devfn) outb(DEVFUNC(devfn), 0xCF8); outb(bus, 0xCFA); - -static u8 pci_conf2_read_config8(struct bus *pbus, int bus, int devfn, int where) -{ - u8 value; - SET(bus, devfn); - value = inb(IOADDR(devfn, where)); - outb(0, 0xCF8); - return value; -} - -static u16 pci_conf2_read_config16(struct bus *pbus, int bus, int devfn, int where) -{ - u16 value; - SET(bus, devfn); - value = inw(IOADDR(devfn, where)); - outb(0, 0xCF8); - return value; -} - -static u32 pci_conf2_read_config32(struct bus *pbus, int bus, int devfn, int where) -{ - u32 value; - SET(bus, devfn); - value = inl(IOADDR(devfn, where)); - outb(0, 0xCF8); - return value; -} - -static void pci_conf2_write_config8(struct bus *pbus, int bus, int devfn, int where, u8 value) -{ - SET(bus, devfn); - outb(value, IOADDR(devfn, where)); - outb(0, 0xCF8); -} - -static void pci_conf2_write_config16(struct bus *pbus, int bus, int devfn, int where, u16 value) -{ - SET(bus, devfn); - outw(value, IOADDR(devfn, where)); - outb(0, 0xCF8); -} - -static void pci_conf2_write_config32(struct bus *pbus, int bus, int devfn, int where, u32 value) -{ - SET(bus, devfn); - outl(value, IOADDR(devfn, where)); - outb(0, 0xCF8); -} - -#undef SET -#undef IOADDR -#undef DEVFUNC - -const struct pci_bus_operations pci_cf8_conf2 = { - .read8 = pci_conf2_read_config8, - .read16 = pci_conf2_read_config16, - .read32 = pci_conf2_read_config32, - .write8 = pci_conf2_write_config8, - .write16 = pci_conf2_write_config16, - .write32 = pci_conf2_write_config32, -}; - diff --git a/device/pci_ops.c b/device/pci_ops.c index b013c40a6f..cb383d013d 100644 --- a/device/pci_ops.c +++ b/device/pci_ops.c @@ -48,42 +48,48 @@ static struct bus *get_pbus(struct device *dev) u8 pci_read_config8(struct device *dev, unsigned int where) { - struct bus *pbus = get_pbus(dev); - return ops_pci_bus(pbus)->read8(pbus, dev->bus->secondary, - dev->path.u.pci.devfn, where); + struct bus *pbus = get_pbus(dev); + return ops_pci_bus(pbus)->read8(PCI_BDEVFN(dev->bus->secondary, + dev->path.u.pci.devfn), + where); } u16 pci_read_config16(struct device *dev, unsigned int where) { struct bus *pbus = get_pbus(dev); - return ops_pci_bus(pbus)->read16(pbus, dev->bus->secondary, - dev->path.u.pci.devfn, where); + return ops_pci_bus(pbus)->read16(PCI_BDEVFN(dev->bus->secondary, + dev->path.u.pci.devfn), + where); } u32 pci_read_config32(struct device *dev, unsigned int where) { struct bus *pbus = get_pbus(dev); - return ops_pci_bus(pbus)->read32(pbus, dev->bus->secondary, - dev->path.u.pci.devfn, where); + return ops_pci_bus(pbus)->read32(PCI_BDEVFN(dev->bus->secondary, + dev->path.u.pci.devfn), + where); } void pci_write_config8(struct device *dev, unsigned int where, u8 val) { struct bus *pbus = get_pbus(dev); - ops_pci_bus(pbus)->write8(pbus, dev->bus->secondary, - dev->path.u.pci.devfn, where, val); + ops_pci_bus(pbus)->write8(PCI_BDEVFN(dev->bus->secondary, + dev->path.u.pci.devfn), + where, val); } void pci_write_config16(struct device *dev, unsigned int where, u16 val) { struct bus *pbus = get_pbus(dev); - ops_pci_bus(pbus)->write16(pbus, dev->bus->secondary, - dev->path.u.pci.devfn, where, val); + ops_pci_bus(pbus)->write16(PCI_BDEVFN(dev->bus->secondary, + dev->path.u.pci.devfn), + where, val); } void pci_write_config32(struct device *dev, unsigned int where, u32 val) { struct bus *pbus = get_pbus(dev); - ops_pci_bus(pbus)->write32(pbus, dev->bus->secondary, - dev->path.u.pci.devfn, where, val); + ops_pci_bus(pbus)->write32(PCI_BDEVFN(dev->bus->secondary, + dev->path.u.pci.devfn), + where, val); } diff --git a/include/arch/x86/pci_ops.h b/include/arch/x86/pci_ops.h index 6121d85300..571a825adc 100644 --- a/include/arch/x86/pci_ops.h +++ b/include/arch/x86/pci_ops.h @@ -20,7 +20,6 @@ #include extern const struct pci_bus_operations pci_cf8_conf1; -extern const struct pci_bus_operations pci_cf8_conf2; #if defined(CONFIG_MMCONF_SUPPORT) && (CONFIG_MMCONF_SUPPORT==1) extern const struct pci_bus_operations pci_ops_mmconf; diff --git a/include/console.h b/include/console.h index 304fbbd7ad..a755667199 100644 --- a/include/console.h +++ b/include/console.h @@ -21,6 +21,7 @@ #include /* We share symbols from stage 0 */ #include +#define BIOS_ALWAYS 0 /* log no matter what; not necessarily an error */ #define BIOS_EMERG 0 /* system is unusable */ #define BIOS_ALERT 1 /* action must be taken immediately */ #define BIOS_CRIT 2 /* critical conditions */ diff --git a/include/device/pci.h b/include/device/pci.h index 07a24527e3..c61f7eaafd 100644 --- a/include/device/pci.h +++ b/include/device/pci.h @@ -49,12 +49,13 @@ struct pci_operations { /* Common pci bus operations */ struct pci_bus_operations { - u8 (*read8)(struct bus *pbus, int bus, int devfn, int where); - u16 (*read16)(struct bus *pbus, int bus, int devfn, int where); - u32 (*read32)(struct bus *pbus, int bus, int devfn, int where); - void (*write8)(struct bus *pbus, int bus, int devfn, int where, u8 val); - void (*write16)(struct bus *pbus, int bus, int devfn, int where, u16 val); - void (*write32)(struct bus *pbus, int bus, int devfn, int where, u32 val); + u8 (*read8)(u32 bdf, int where); + u16 (*read16)(u32 bdf, int where); + u32 (*read32)(u32 bdf, int where); + void (*write8)(u32 bdf, int where, u8 val); + void (*write16)(u32 bdf, int where, u16 val); + void (*write32)(u32 bdf, int where, u32 val); + int (*find)(u16 vendid, u16 devid, u32 *busdevfn); }; struct pci_driver { diff --git a/include/device/pci_def.h b/include/device/pci_def.h index 53467a4f6a..ab41454b91 100644 --- a/include/device/pci_def.h +++ b/include/device/pci_def.h @@ -481,6 +481,8 @@ #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) #define PCI_BDF(bus,dev,func) ((bus) << 16 | (dev) << 11 | (func) << 8) +/* bus,devfn pairs are used many places as well */ +#define PCI_BDEVFN(bus,devfn) ((bus) << 16 | (devfn) << 8) #define PCI_ADDR(bus,dev,func,where) (PCI_BDF((bus),(dev),(func)) << 4 | (where & 0xfff)) #endif /* DEVICE_PCI_DEF_H */ diff --git a/lib/console.c b/lib/console.c index 322532d707..9cad3b7b7f 100644 --- a/lib/console.c +++ b/lib/console.c @@ -8,9 +8,30 @@ int vtxprintf(void (*)(unsigned char, void *arg), void *arg, const char *, va_list); -static int console_loglevel(void) +static unsigned int loglevel = CONFIG_DEFAULT_CONSOLE_LOGLEVEL; + +/** + * set the console log level + * There are no invalid settings, although there are ones that + * do not make much sense. + * + * @param level The new level + */ +void set_loglevel(unsigned int level) { + if (level > BIOS_SPEW) + printk(BIOS_ALWAYS, "Warning: ridiculous log level setting: %d (max %d)\n", + level, BIOS_SPEW); + loglevel = level; +} + +/** + * get the console log level + * + * @return The level + */ +static unsigned int console_loglevel(void) { - return CONFIG_DEFAULT_CONSOLE_LOGLEVEL; + return loglevel; } #ifdef CONFIG_CONSOLE_BUFFER @@ -150,9 +171,9 @@ void console_init(void) COREBOOT_EXTRA_VERSION " " COREBOOT_BUILD - " starting...\n"; + " starting... (console_loglevel=%d)\n"; - printk(BIOS_INFO, console_test); + printk(BIOS_ALWAYS, console_test, console_loglevel()); } /** diff --git a/mainboard/artecgroup/dbe62/initram.c b/mainboard/artecgroup/dbe62/initram.c index ca4610024e..a33687d32d 100644 --- a/mainboard/artecgroup/dbe62/initram.c +++ b/mainboard/artecgroup/dbe62/initram.c @@ -152,7 +152,7 @@ int main(void) sdram_enable(DIMM0, DIMM1); printk(BIOS_DEBUG, "done sdram enable\n"); - dumplxmsrs(); + /*dumplxmsrs();*/ /* Check low memory */ /* The RAM is working now. Leave this test commented out but * here for reference. diff --git a/northbridge/amd/geodelx/raminit.c b/northbridge/amd/geodelx/raminit.c index b13ffde313..988189e6fd 100644 --- a/northbridge/amd/geodelx/raminit.c +++ b/northbridge/amd/geodelx/raminit.c @@ -66,7 +66,10 @@ void dumplxmsrs(void) for (i = 0; i < ARRAY_SIZE(msrs); i++) { struct msr msr; msr = rdmsr(msrs[i]); - printk(BIOS_DEBUG, "%s (%lx): %x.%x\n", msrnames[i], msrs[i], + /* don't change the %p to a %s unless you fix the problem. + * in particular, don't change or submit a patch UNLESS YOU TEST IT + */ + printk(BIOS_DEBUG, "%p (%lx): %x.%x\n", msrnames[i], msrs[i], msr.hi, msr.lo); }