diff options
Diffstat (limited to 'contrib/syslinux-4.02/com32/lib/pci/cfgtype.c')
-rw-r--r-- | contrib/syslinux-4.02/com32/lib/pci/cfgtype.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/com32/lib/pci/cfgtype.c b/contrib/syslinux-4.02/com32/lib/pci/cfgtype.c new file mode 100644 index 0000000..896f7e5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/cfgtype.c @@ -0,0 +1,89 @@ +#include "pci/pci.h" +#include <com32.h> +#include <string.h> + +enum pci_config_type __pci_cfg_type; + +static int type1_ok(void) +{ + uint32_t oldcf8, newcf8; + + /* Test for Configuration Method #1 */ + + /* Note: XFree86 writes ~0 and expects to read back 0x80fffffc. Linux + does this less severe test; go with Linux. */ + + cli(); + outb(1, 0xcfb); /* For old Intel chipsets */ + oldcf8 = inl(0xcf8); + outl(0x80000000, 0xcf8); + newcf8 = inl(0xcf8); + outl(oldcf8, 0xcf8); + sti(); + + return newcf8 == 0x80000000; +} + +static int type2_ok(void) +{ + uint8_t oldcf8, oldcfa; + uint8_t cf8, cfa; + + /* Test for Configuration Method #2 */ + + /* CM#2 is hard to probe for, but let's do our best... */ + + cli(); + outb(0, 0xcfb); /* For old Intel chipsets */ + oldcf8 = inb(0xcf8); + outb(0, 0xcf8); + oldcfa = inb(0xcfa); + outb(0, 0xcfa); + + cf8 = inb(0xcf8); + cfa = inb(0xcfa); + + outb(oldcf8, 0xcf8); + outb(oldcfa, 0xcfa); + sti(); + + return cf8 == 0 && cfa == 0; +} + +int pci_set_config_type(enum pci_config_type type) +{ + static const com32sys_t ireg = { + .eax.l = 0xb101, + .edi.l = 0, + .eflags.l = EFLAGS_CF, + }; + com32sys_t oreg; + + if (type == PCI_CFG_AUTO) { + type = PCI_CFG_NONE; + + /* Try to detect PCI BIOS */ + __intcall(0x1a, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && + oreg.eax.b[1] == 0 && oreg.edx.l == 0x20494250) { + /* PCI BIOS present. Use direct access if we know how to do it. */ + + if ((oreg.eax.b[0] & 1) && type1_ok()) + type = PCI_CFG_TYPE1; + else if ((oreg.eax.b[0] & 2) && type2_ok()) + type = PCI_CFG_TYPE2; + else + type = PCI_CFG_BIOS; /* Use BIOS calls as fallback */ + + } else if (type1_ok()) { + type = PCI_CFG_TYPE1; + } else if (type2_ok()) { + type = PCI_CFG_TYPE2; + } else { + type = PCI_CFG_NONE; /* Badness... */ + } + } + + return (__pci_cfg_type = type); +} |