Home | History | Annotate | Download | only in pci
      1 #include "pci/pci.h"
      2 #include <com32.h>
      3 #include <string.h>
      4 
      5 enum pci_config_type __pci_cfg_type;
      6 
      7 static int type1_ok(void)
      8 {
      9     uint32_t oldcf8, newcf8;
     10 
     11     /* Test for Configuration Method #1 */
     12 
     13     /* Note: XFree86 writes ~0 and expects to read back 0x80fffffc.  Linux
     14        does this less severe test; go with Linux. */
     15 
     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();
     23 
     24     return newcf8 == 0x80000000;
     25 }
     26 
     27 static int type2_ok(void)
     28 {
     29     uint8_t oldcf8, oldcfa;
     30     uint8_t cf8, cfa;
     31 
     32     /* Test for Configuration Method #2 */
     33 
     34     /* CM#2 is hard to probe for, but let's do our best... */
     35 
     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);
     42 
     43     cf8 = inb(0xcf8);
     44     cfa = inb(0xcfa);
     45 
     46     outb(oldcf8, 0xcf8);
     47     outb(oldcfa, 0xcfa);
     48     sti();
     49 
     50     return cf8 == 0 && cfa == 0;
     51 }
     52 
     53 int pci_set_config_type(enum pci_config_type type)
     54 {
     55     static const com32sys_t ireg = {
     56 	.eax.l = 0xb101,
     57 	.edi.l = 0,
     58 	.eflags.l = EFLAGS_CF,
     59     };
     60     com32sys_t oreg;
     61 
     62     if (type == PCI_CFG_AUTO) {
     63 	type = PCI_CFG_NONE;
     64 
     65 	/* Try to detect PCI BIOS */
     66 	__intcall(0x1a, &ireg, &oreg);
     67 
     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. */
     71 
     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 */
     78 
     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... */
     85 	}
     86     }
     87 
     88     return (__pci_cfg_type = type);
     89 }
     90