Adding upstream version 3.61.
[syslinux-debian/hramrach.git] / com32 / lib / pci / cfgtype.c
blob97215d4247e64cd85ed635d8dc1dd9cfdcce7988
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);