00001 #include <stddef.h>
00002 #include <console/console.h>
00003 #include <arch/io.h>
00004 #include <arch/pciconf.h>
00005 #include <device/pci.h>
00006 #include <device/pci_ids.h>
00007 #include <device/pci_ops.h>
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 static int pci_sanity_check(const struct pci_bus_operations *o)
00020 {
00021 uint16_t class, vendor;
00022 unsigned bus;
00023 int devfn;
00024 struct bus pbus;
00025 #define PCI_CLASS_BRIDGE_HOST 0x0600
00026 #define PCI_CLASS_DISPLAY_VGA 0x0300
00027 #define PCI_VENDOR_ID_COMPAQ 0x0e11
00028 #define PCI_VENDOR_ID_INTEL 0x8086
00029 #define PCI_VENDOR_ID_MOTOROLA 0x1057
00030
00031 for (bus = 0, devfn = 0; devfn < 0x100; devfn++) {
00032 class = o->read16(&pbus, bus, devfn, PCI_CLASS_DEVICE);
00033 vendor = o->read16(&pbus, bus, devfn, PCI_VENDOR_ID);
00034 if (((class == PCI_CLASS_BRIDGE_HOST) || (class == PCI_CLASS_DISPLAY_VGA)) ||
00035 ((vendor == PCI_VENDOR_ID_INTEL) || (vendor == PCI_VENDOR_ID_COMPAQ) ||
00036 (vendor == PCI_VENDOR_ID_MOTOROLA))) {
00037 return 1;
00038 }
00039 }
00040 printk_err("PCI: Sanity check failed\n");
00041 return 0;
00042 }
00043
00044 const struct pci_bus_operations *pci_check_direct(void)
00045 {
00046 unsigned int tmp;
00047
00048
00049
00050
00051 {
00052 outb(0x01, 0xCFB);
00053 tmp = inl(0xCF8);
00054 outl(0x80000000, 0xCF8);
00055 if ((inl(0xCF8) == 0x80000000) &&
00056 pci_sanity_check(&pci_cf8_conf1))
00057 {
00058 outl(tmp, 0xCF8);
00059 printk_debug("PCI: Using configuration type 1\n");
00060 return &pci_cf8_conf1;
00061 }
00062 outl(tmp, 0xCF8);
00063 }
00064
00065
00066
00067
00068 {
00069 outb(0x00, 0xCFB);
00070 outb(0x00, 0xCF8);
00071 outb(0x00, 0xCFA);
00072 if ((inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) &&
00073 pci_sanity_check(&pci_cf8_conf2))
00074 {
00075 printk_debug("PCI: Using configuration type 2\n");
00076 return &pci_cf8_conf2;
00077 }
00078 }
00079
00080 die("pci_check_direct failed\n");
00081 return NULL;
00082 }
00083
00084
00085
00086 void pci_set_method(device_t dev)
00087 {
00088 printk_info("Finding PCI configuration type.\n");
00089 dev->ops->ops_pci_bus = pci_check_direct();
00090 post_code(0x5f);
00091 }