diff --git a/clib/clib.c b/clib/clib.c index 8ae20bc..15c879f 100644 --- a/clib/clib.c +++ b/clib/clib.c @@ -30,6 +30,8 @@ #include "clib.h" +uint8_t pci_mechanism = 0, pci_device_count = 0; + #ifdef __WATCOMC__ static union REGPACK rp; /* things break if this is not a global variable... */ #endif @@ -323,16 +325,62 @@ pci_cf8(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg) } +int +pci_init() +{ + multi_t cf8; + cf8.u32 = 0x80000000; + + /* Determine the supported PCI configuration mechanism. */ + cli(); + outb(0xcf8, 0x00); + outb(0xcfa, 0x00); + if ((inb(0xcf8) == 0x00) && (inb(0xcfa) == 0x00)) { + pci_mechanism = 2; + pci_device_count = 32; + } else { + outl(0xcf8, cf8.u32); + cf8.u32 = inl(0xcf8); + if (cf8.u32 == 0x80000000) { + pci_mechanism = 1; + pci_device_count = 16; + } + } + sti(); + if (pci_mechanism == 0) + printf("Failed to probe PCI configuration mechanism (%04X%04X). Is this a PCI system?\n", cf8.u16[1], cf8.u16[0]); + + return pci_mechanism; +} + + uint8_t pci_readb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg) { uint8_t ret; - uint16_t data_port = 0xcfc | (reg & 0x03); - uint32_t cf8 = pci_cf8(bus, dev, func, reg); - cli(); - outl(0xcf8, cf8); - ret = inb(data_port); - sti(); + uint16_t data_port; + uint32_t cf8; + + switch (pci_mechanism) { + case 1: + data_port = 0xcfc | (reg & 0x03); + cf8 = pci_cf8(bus, dev, func, reg); + cli(); + outl(0xcf8, cf8); + ret = inb(data_port); + sti(); + break; + + case 2: + cf8 = pci_readl(bus, dev, func, reg); + ret = cf8 >> ((reg & 0x03) << 3); + break; + + default: + ret = 0xff; + break; + } + return ret; } @@ -340,12 +388,29 @@ pci_readb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg) uint16_t pci_readw(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg) { - uint16_t ret, data_port = 0xcfc | (reg & 0x02); - uint32_t cf8 = pci_cf8(bus, dev, func, reg); - cli(); - outl(0xcf8, cf8); - ret = inw(data_port); - sti(); + uint16_t ret, data_port; + uint32_t cf8; + + switch (pci_mechanism) { + case 1: + data_port = 0xcfc | (reg & 0x02); + cf8 = pci_cf8(bus, dev, func, reg); + cli(); + outl(0xcf8, cf8); + ret = inw(data_port); + sti(); + break; + + case 2: + cf8 = pci_readl(bus, dev, func, reg); + ret = cf8 >> ((reg & 0x02) << 3); + break; + + default: + ret = 0xffff; + break; + } + return ret; } @@ -353,11 +418,33 @@ pci_readw(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg) uint32_t pci_readl(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg) { - uint32_t ret, cf8 = pci_cf8(bus, dev, func, reg); - cli(); - outl(0xcf8, cf8); - ret = inl(0xcfc); - sti(); + uint16_t data_port; + uint32_t ret, cf8; + + switch (pci_mechanism) { + case 1: + cf8 = pci_cf8(bus, dev, func, reg); + cli(); + outl(0xcf8, cf8); + ret = inl(0xcfc); + sti(); + break; + + case 2: + func = 0x80 | (func << 1); + data_port = 0xc000 | (dev << 8) | (reg & 0xfc); + cli(); + outb(0xcf8, func); + outb(0xcfa, bus); + ret = inl(data_port); + sti(); + break; + + default: + ret = 0xffffffff; + break; + } + return ret; } @@ -365,35 +452,84 @@ pci_readl(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg) void pci_writeb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint8_t val) { - uint16_t data_port = 0xcfc | (reg & 0x03); - uint32_t cf8 = pci_cf8(bus, dev, func, reg); - cli(); - outl(0xcf8, cf8); - outb(data_port, val); - sti(); + uint8_t shift; + uint16_t data_port; + uint32_t cf8; + + switch (pci_mechanism) { + case 1: + data_port = 0xcfc | (reg & 0x03); + cf8 = pci_cf8(bus, dev, func, reg); + cli(); + outl(0xcf8, cf8); + outb(data_port, val); + sti(); + break; + + case 2: + cf8 = pci_readl(bus, dev, func, reg); + shift = (reg & 0x03) << 3; + cf8 &= ~(0x000000ff << shift); + cf8 |= val << shift; + pci_writel(bus, dev, func, reg, cf8); + break; + } } void pci_writew(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint16_t val) { - uint16_t data_port = 0xcfc | (reg & 0x02); - uint32_t cf8 = pci_cf8(bus, dev, func, reg); - cli(); - outl(0xcf8, cf8); - outw(data_port, val); - sti(); + uint8_t shift; + uint16_t data_port; + uint32_t cf8; + + switch (pci_mechanism) { + case 1: + data_port = 0xcfc | (reg & 0x02); + cf8 = pci_cf8(bus, dev, func, reg); + cli(); + outl(0xcf8, cf8); + outw(data_port, val); + sti(); + break; + + case 2: + cf8 = pci_readl(bus, dev, func, reg); + shift = (reg & 0x02) << 3; + cf8 &= ~(0x0000ffff << shift); + cf8 |= val << shift; + pci_writel(bus, dev, func, reg, cf8); + break; + } } void pci_writel(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg, uint32_t val) { - uint32_t cf8 = pci_cf8(bus, dev, func, reg); - cli(); - outl(0xcf8, cf8); - outl(0xcfc, val); - sti(); + uint16_t data_port; + uint32_t cf8; + + switch (pci_mechanism) { + case 1: + cf8 = pci_cf8(bus, dev, func, reg); + cli(); + outl(0xcf8, cf8); + outl(0xcfc, val); + sti(); + break; + + case 2: + func = 0x80 | (func << 1); + data_port = 0xc000 | (dev << 8) | (reg & 0xfc); + cli(); + outb(0xcf8, func); + outb(0xcfa, bus); + outl(data_port, val); + sti(); + break; + } } diff --git a/clib/clib.h b/clib/clib.h index 448077c..ee199c8 100644 --- a/clib/clib.h +++ b/clib/clib.h @@ -41,6 +41,10 @@ typedef union { #pragma pack(pop) +/* Global variables. */ +extern uint8_t pci_mechanism, pci_device_count; + + /* String functions. */ extern int parse_hex_u8(char *val, uint8_t *dest); extern int parse_hex_u16(char *val, uint16_t *dest); @@ -113,6 +117,7 @@ extern void outl(uint16_t port, uint32_t data); /* PCI I/O functions. */ extern uint32_t pci_cf8(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg); +extern int pci_init(); extern uint8_t pci_readb(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg); extern uint16_t pci_readw(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg); extern uint32_t pci_readl(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg); diff --git a/pcireg/PCIREG.EFI b/pcireg/PCIREG.EFI index 290ad9f..444ed81 100644 Binary files a/pcireg/PCIREG.EFI and b/pcireg/PCIREG.EFI differ diff --git a/pcireg/PCIREG.EXE b/pcireg/PCIREG.EXE index 6be08c5..cee7758 100644 Binary files a/pcireg/PCIREG.EXE and b/pcireg/PCIREG.EXE differ diff --git a/pcireg/pcireg.c b/pcireg/pcireg.c index 914aa09..10d4a32 100644 --- a/pcireg/pcireg.c +++ b/pcireg/pcireg.c @@ -549,9 +549,9 @@ scan_bus(uint8_t bus, int nesting, char dump, char *buf) /* Iterate through devices. */ count = 0; - for (dev = 0; dev <= 31; dev++) { + for (dev = 0; dev < pci_device_count; dev++) { /* Iterate through functions. */ - for (func = 0; func <= 7; func++) { + for (func = 0; func < 8; func++) { /* Read vendor/device ID. */ #ifdef DEBUG if ((bus < DEBUG) && (dev <= bus) && (func == 0)) { @@ -1381,14 +1381,12 @@ usage: return 1; } -#ifndef DEBUG - /* Test for PCI presence. */ - outl(0xcf8, 0x80000000); - cf8 = inl(0xcf8); - if (cf8 == 0xffffffff) { - printf("Port CF8h is not responding. Does this system even have PCI?\n"); +#ifdef DEBUG + pci_mechanism = 1; +#else + /* Initialize PCI, and exit in case of failure. */ + if (!pci_init()) return 1; - } #endif /* Convert the first parameter to lowercase. */