summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2005-08-09 00:56:02 +0000
committerhpa <hpa>2005-08-09 00:56:02 +0000
commit65d8125e084eda0d29b6ea4a1f20a5a91c51a5e5 (patch)
treeff4c7f0911b3b8f3b24e988cb03d27490805a288
parentaa6dd9789db77992917534a074f89089c91ae1f0 (diff)
downloadsyslinux-65d8125e084eda0d29b6ea4a1f20a5a91c51a5e5.tar.gz
Out-of-line __intcall and __farcall; better detection mechanism for CM#2
-rw-r--r--com32/include/com32.h17
-rw-r--r--com32/include/sys/pci.h3
-rw-r--r--com32/lib/Makefile1
-rw-r--r--com32/lib/pci/cfgtype.c47
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);
}
+