Adding upstream version 4.00~pre54+dfsg.
[syslinux-debian/hramrach.git] / com32 / lib / pci / cfgtype.c
blob896f7e5e5fd4a74bb75c7f7a343133d84aa06d87
1 #include "pci/pci.h"
2 #include <com32.h>
3 #include <string.h>
5 enum pci_config_type __pci_cfg_type;
7 static int type1_ok(void)
9 uint32_t oldcf8, newcf8;
11 /* Test for Configuration Method #1 */
13 /* Note: XFree86 writes ~0 and expects to read back 0x80fffffc. Linux
14 does this less severe test; go with Linux. */
16 cli();
17 outb(1, 0xcfb); /* For old Intel chipsets */
18 oldcf8 = inl(0xcf8);
19 outl(0x80000000, 0xcf8);
20 newcf8 = inl(0xcf8);
21 outl(oldcf8, 0xcf8);
22 sti();
24 return newcf8 == 0x80000000;
27 static int type2_ok(void)
29 uint8_t oldcf8, oldcfa;
30 uint8_t cf8, cfa;
32 /* Test for Configuration Method #2 */
34 /* CM#2 is hard to probe for, but let's do our best... */
36 cli();
37 outb(0, 0xcfb); /* For old Intel chipsets */
38 oldcf8 = inb(0xcf8);
39 outb(0, 0xcf8);
40 oldcfa = inb(0xcfa);
41 outb(0, 0xcfa);
43 cf8 = inb(0xcf8);
44 cfa = inb(0xcfa);
46 outb(oldcf8, 0xcf8);
47 outb(oldcfa, 0xcfa);
48 sti();
50 return cf8 == 0 && cfa == 0;
53 int pci_set_config_type(enum pci_config_type type)
55 static const com32sys_t ireg = {
56 .eax.l = 0xb101,
57 .edi.l = 0,
58 .eflags.l = EFLAGS_CF,
60 com32sys_t oreg;
62 if (type == PCI_CFG_AUTO) {
63 type = PCI_CFG_NONE;
65 /* Try to detect PCI BIOS */
66 __intcall(0x1a, &ireg, &oreg);
68 if (!(oreg.eflags.l & EFLAGS_CF) &&
69 oreg.eax.b[1] == 0 && oreg.edx.l == 0x20494250) {
70 /* PCI BIOS present. Use direct access if we know how to do it. */
72 if ((oreg.eax.b[0] & 1) && type1_ok())
73 type = PCI_CFG_TYPE1;
74 else if ((oreg.eax.b[0] & 2) && type2_ok())
75 type = PCI_CFG_TYPE2;
76 else
77 type = PCI_CFG_BIOS; /* Use BIOS calls as fallback */
79 } else if (type1_ok()) {
80 type = PCI_CFG_TYPE1;
81 } else if (type2_ok()) {
82 type = PCI_CFG_TYPE2;
83 } else {
84 type = PCI_CFG_NONE; /* Badness... */
88 return (__pci_cfg_type = type);