diff options
author | hpa <hpa> | 2005-08-09 00:56:02 +0000 |
---|---|---|
committer | hpa <hpa> | 2005-08-09 00:56:02 +0000 |
commit | 65d8125e084eda0d29b6ea4a1f20a5a91c51a5e5 (patch) | |
tree | ff4c7f0911b3b8f3b24e988cb03d27490805a288 | |
parent | aa6dd9789db77992917534a074f89089c91ae1f0 (diff) | |
download | syslinux-65d8125e084eda0d29b6ea4a1f20a5a91c51a5e5.tar.gz |
Out-of-line __intcall and __farcall; better detection mechanism for CM#2
-rw-r--r-- | com32/include/com32.h | 17 | ||||
-rw-r--r-- | com32/include/sys/pci.h | 3 | ||||
-rw-r--r-- | com32/lib/Makefile | 1 | ||||
-rw-r--r-- | com32/lib/pci/cfgtype.c | 47 |
4 files changed, 44 insertions, 24 deletions
diff --git a/com32/include/com32.h b/com32/include/com32.h index 91799f6b..29656e47 100644 --- a/com32/include/com32.h +++ b/com32/include/com32.h @@ -77,20 +77,11 @@ extern struct com32_sys_args { } __com32; /* - * System call macros + * System call wrapper functions */ -static inline void -__intcall(uint8_t __i, const com32sys_t *__sr, com32sys_t *__dr) -{ - __com32.cs_intcall(__i, __sr, __dr); -} - -static inline void -__farcall(uint16_t __es, uint16_t __eo, - const com32sys_t *__sr, com32sys_t *__dr) -{ - __com32.cs_farcall((__es << 16) + __eo, __sr, __dr); -} +void __intcall(uint8_t __i, const com32sys_t *__sr, com32sys_t *__dr); +void __farcall(uint16_t __es, uint16_t __eo, + const com32sys_t *__sr, com32sys_t *__dr); /* * These functions convert between linear pointers in the range diff --git a/com32/include/sys/pci.h b/com32/include/sys/pci.h index 5f530608..f1c1eb55 100644 --- a/com32/include/sys/pci.h +++ b/com32/include/sys/pci.h @@ -14,13 +14,14 @@ static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev, } enum pci_config_type { + PCI_CFG_NONE = -1, /* badness */ PCI_CFG_AUTO = 0, /* autodetect */ PCI_CFG_TYPE1 = 1, PCI_CFG_TYPE2 = 2, PCI_CFG_BIOS = 3, }; -void pci_set_config_type(enum pci_config_type); +enum pci_config_type pci_set_config_type(enum pci_config_type); uint8_t pci_readb(pciaddr_t); uint16_t pci_readw(pciaddr_t); diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 82faa553..af64950b 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -23,6 +23,7 @@ LIBOBJS = \ libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ libgcc/__divdi3.o libgcc/__moddi3.o \ \ + sys/intcall.o sys/farcall.o \ sys/entry.o sys/exit.o sys/argv.o sys/times.o sys/idle.o \ sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \ sys/close.o sys/open.o sys/fileread.o sys/fileclose.o \ diff --git a/com32/lib/pci/cfgtype.c b/com32/lib/pci/cfgtype.c index e2ed6400..0fdc81e7 100644 --- a/com32/lib/pci/cfgtype.c +++ b/com32/lib/pci/cfgtype.c @@ -4,9 +4,8 @@ enum pci_config_type __pci_cfg_type; -void pci_set_config_type(enum pci_config_type type) +int pci_set_config_type(enum pci_config_type type) { - uint32_t oldcf8; static const com32sys_t ireg = { .eax.l = 0xb101, .edi.l = 0, @@ -15,26 +14,54 @@ void pci_set_config_type(enum pci_config_type type) 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 ) { - /* Use CM#1 if it is present, otherwise BIOS calls. CM#2 is evil. */ - type = (oreg.eax.b[0] & 1) ? PCI_CFG_TYPE1 : PCI_CFG_BIOS; + /* PCI BIOS present. Use direct access if we know how to do it. */ + if ( oreg.eax.b[0] & 1 ) + type = PCI_CFG_TYPE1; + else if ( oreg.eax.b[0] & 2 ) + type = PCI_CFG_TYPE2; + else + type = PCI_CFG_BIOS; } else { /* Try to detect CM #1 */ + uint32_t oldcf8, newcf8; + cli(); + outb(1, 0xcfb); /* Linux does this for some reason? */ oldcf8 = inl(0xcf8); - outl(~0, 0xcf8); - if ( inl(0xcf8) == pci_mkaddr(255,31,7,252) ) - type = PCI_CFG_TYPE1; - else - type = PCI_CFG_TYPE2; /* ... it better be ... */ + 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(); + } } } - __pci_cfg_type = type; + return (__pci_cfg_type = type); } + |