summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/com32/lib/pci/cfgtype.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux-4.02/com32/lib/pci/cfgtype.c')
-rw-r--r--contrib/syslinux-4.02/com32/lib/pci/cfgtype.c89
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);
+}