switch-coreboot/arch/x86/pci_ops_auto.c
Ronald G. Minnich 6a732582c7 Here we start to see the good design of 3. In v2, there were pci ops in
all stages, blighting everything with the same code, compiled different 
ways. In this change, we see that:
- basic conf ops are compiled into stage0, where they are used. 
- they are called directly from initram
- they are used to initialize the pci_cf8_conf1 structure in stage 2, 
   but the call still goes to stage0!

one copy of the code. 

Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>


git-svn-id: svn://coreboot.org/repository/coreboot-v3@752 f3766cd6-281f-0410-b1cd-43a5c92072e9
2008-08-13 02:41:29 +00:00

88 lines
2.5 KiB
C

#include <console.h>
#include <device/device.h>
#include <pciconf.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <types.h>
#include <io.h>
const struct pci_bus_operations pci_cf8_conf1 = {
.read8 = pci_conf1_read_config8,
.read16 = pci_conf1_read_config16,
.read32 = pci_conf1_read_config32,
.write8 = pci_conf1_write_config8,
.write16 = pci_conf1_write_config16,
.write32 = pci_conf1_write_config32,
.find = pci_conf1_find_device,
};
/*
* Before we decide to use direct hardware access mechanisms, we try to do some
* trivial checks to ensure it at least _seems_ to be working -- we just test
* whether bus 00 contains a host bridge (this is similar to checking
* techniques used in XFree86, but ours should be more reliable since we
* attempt to make use of direct access hints provided by the PCI BIOS).
*
* This should be close to trivial, but it isn't, because there are buggy
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
*/
static int pci_sanity_check(const struct pci_bus_operations *o)
{
u16 class, vendor;
unsigned bus;
int devfn;
#define PCI_CLASS_BRIDGE_HOST 0x0600
#define PCI_CLASS_DISPLAY_VGA 0x0300
#define PCI_VENDOR_ID_COMPAQ 0x0e11
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_VENDOR_ID_MOTOROLA 0x1057
for (bus = 0, devfn = 0; devfn < 0x100; devfn++) {
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))) {
return 1;
}
}
printk(BIOS_ERR, "PCI: Sanity check failed\n");
return 0;
}
const struct pci_bus_operations *pci_check_direct(void)
{
unsigned int tmp;
/*
* Check if configuration type 1 works.
*/
{
outb(0x01, 0xCFB);
tmp = inl(0xCF8);
outl(0x80000000, 0xCF8);
if ((inl(0xCF8) == 0x80000000) &&
pci_sanity_check(&pci_cf8_conf1))
{
outl(tmp, 0xCF8);
printk(BIOS_DEBUG, "PCI: Using configuration type 1\n");
return &pci_cf8_conf1;
}
outl(tmp, 0xCF8);
}
die("pci_check_direct failed\n");
return NULL;
}
/** Set the method to be used for PCI, type I or type II
*/
void pci_set_method(struct device * dev)
{
printk(BIOS_INFO, "Finding PCI configuration type.\n");
dev->ops->ops_pci_bus = pci_check_direct();
post_code(POST_STAGE2_PHASE2_PCI_SET_METHOD);
}