summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhpa <hpa>2005-08-09 03:34:04 +0000
committerhpa <hpa>2005-08-09 03:34:04 +0000
commit14aef35cffa86e0a0d54b3b6556b229e61befe33 (patch)
treebc292739e3e8eeee43244b748fa71d9375a72347
parenta0764e212fd2a589f19c317393f67e1c5cdfa08d (diff)
downloadsyslinux-3.10-pre6.tar.gz
Better tests for CM#1 and CM#2syslinux-3.10-pre6
-rw-r--r--com32/lib/pci/cfgtype.c89
1 files changed, 56 insertions, 33 deletions
diff --git a/com32/lib/pci/cfgtype.c b/com32/lib/pci/cfgtype.c
index 0fdc81e7..0f8c623f 100644
--- a/com32/lib/pci/cfgtype.c
+++ b/com32/lib/pci/cfgtype.c
@@ -4,6 +4,52 @@
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 = {
@@ -22,43 +68,20 @@ int pci_set_config_type(enum pci_config_type type)
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 )
+
+ if ( (oreg.eax.b[0] & 1) && type1_ok() )
type = PCI_CFG_TYPE1;
- else if ( oreg.eax.b[0] & 2 )
+ else if ( (oreg.eax.b[0] & 2) && type2_ok() )
type = PCI_CFG_TYPE2;
else
- type = PCI_CFG_BIOS;
+ 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 {
- /* Try to detect CM #1 */
- uint32_t oldcf8, newcf8;
-
- cli();
- outb(1, 0xcfb); /* Linux does this for some reason? */
- oldcf8 = inl(0xcf8);
- outl(0x80000000, 0xcf8);
- newcf8 = inl(0xcf8);
- outl(oldcf8, 0xcf8);
- sti();
-
- if ( newcf8 == 0x80000000 )
- type = PCI_CFG_TYPE1;
- else {
- uint8_t oldcf8, oldcfa;
- /* Try to detect CM#2 */
- cli();
- outb(0, 0xcfb); /* Linux does this for some reason? */
- oldcf8 = inb(0xcf8);
- outb(0, 0xcf8);
- oldcfa = inb(0xcfa);
- outb(0, 0xcfa);
-
- if ( inb(0xcf8) == 0 && inb(0xcfa) == 0 )
- type = PCI_CFG_TYPE2;
-
- outb(oldcf8, 0xcf8);
- outb(oldcfa, 0xcfa);
- sti();
- }
+ type = PCI_CFG_NONE; /* Badness... */
}
}