pcireg: Add support for PCI configuration mechanism 2

This commit is contained in:
RichardG867
2021-10-15 14:44:58 -03:00
parent 810c0f2369
commit f36c1b1388
5 changed files with 182 additions and 43 deletions

View File

@@ -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;
}
}

View File

@@ -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);

Binary file not shown.

Binary file not shown.

View File

@@ -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. */