Adjust the code to probe for the PCI config mechanism to use.
- On amd64, just assume type #1 is always used. PCI 2.0 mandated deprecated type #2 and required type #1 for all future bridges which was well before amd64 existed. - For i386, ignore whatever value was in 0xcf8 before testing for type #1 and instead rely on the other tests to determine if type #1 works. Some newer machines leave garbage in 0xcf8 during boot and as a result the kernel doesn't find PCI at all (which greatly confuses ACPI which expects PCI to exist when PCI busses are in the namespace). MFC after: 3 days Discussed with: scottl
This commit is contained in:
parent
b468fe2bce
commit
98bbce55fa
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=174050
@ -37,11 +37,6 @@
|
||||
#define CONF1_ENABLE_MSK1 0x80000001ul
|
||||
#define CONF1_ENABLE_RES1 0x80000000ul
|
||||
|
||||
#define CONF2_ENABLE_PORT 0x0cf8
|
||||
#define CONF2_FORWARD_PORT 0x0cfa
|
||||
#define CONF2_ENABLE_CHK 0x0e
|
||||
#define CONF2_ENABLE_RES 0x0e
|
||||
|
||||
int pci_cfgregopen(void);
|
||||
u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes);
|
||||
void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes);
|
||||
|
@ -38,12 +38,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <machine/pci_cfgreg.h>
|
||||
|
||||
static int cfgmech;
|
||||
static int devmax;
|
||||
|
||||
static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
|
||||
static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
|
||||
static int pcireg_cfgopen(void);
|
||||
|
||||
static struct mtx pcicfg_mtx;
|
||||
|
||||
@ -57,8 +53,6 @@ pci_cfgregopen(void)
|
||||
|
||||
if (opened)
|
||||
return (1);
|
||||
if (pcireg_cfgopen() == 0)
|
||||
return (0);
|
||||
mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
|
||||
opened = 1;
|
||||
return (1);
|
||||
@ -109,26 +103,12 @@ pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
|
||||
{
|
||||
int dataport = 0;
|
||||
|
||||
if (bus <= PCI_BUSMAX
|
||||
&& slot < devmax
|
||||
&& func <= PCI_FUNCMAX
|
||||
&& reg <= PCI_REGMAX
|
||||
&& bytes != 3
|
||||
&& (unsigned) bytes <= 4
|
||||
&& (reg & (bytes - 1)) == 0) {
|
||||
switch (cfgmech) {
|
||||
case 1:
|
||||
outl(CONF1_ADDR_PORT, (1 << 31)
|
||||
| (bus << 16) | (slot << 11)
|
||||
| (func << 8) | (reg & ~0x03));
|
||||
dataport = CONF1_DATA_PORT + (reg & 0x03);
|
||||
break;
|
||||
case 2:
|
||||
outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
|
||||
outb(CONF2_FORWARD_PORT, bus);
|
||||
dataport = 0xc000 | (slot << 8) | reg;
|
||||
break;
|
||||
}
|
||||
if (bus <= PCI_BUSMAX && slot < 32 && func <= PCI_FUNCMAX &&
|
||||
reg <= PCI_REGMAX && bytes != 3 && (unsigned) bytes <= 4 &&
|
||||
(reg & (bytes - 1)) == 0) {
|
||||
outl(CONF1_ADDR_PORT, (1 << 31) | (bus << 16) | (slot << 11)
|
||||
| (func << 8) | (reg & ~0x03));
|
||||
dataport = CONF1_DATA_PORT + (reg & 0x03);
|
||||
}
|
||||
return (dataport);
|
||||
}
|
||||
@ -137,19 +117,11 @@ pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
|
||||
static void
|
||||
pci_cfgdisable(void)
|
||||
{
|
||||
switch (cfgmech) {
|
||||
case 1:
|
||||
/*
|
||||
* Do nothing for the config mechanism 1 case.
|
||||
* Writing a 0 to the address port can apparently
|
||||
* confuse some bridges and cause spurious
|
||||
* access failures.
|
||||
*/
|
||||
break;
|
||||
case 2:
|
||||
outb(CONF2_ENABLE_PORT, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do nothing. Writing a 0 to the address port can apparently
|
||||
* confuse some bridges and cause spurious access failures.
|
||||
*/
|
||||
}
|
||||
|
||||
static int
|
||||
@ -201,131 +173,3 @@ pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
|
||||
}
|
||||
mtx_unlock_spin(&pcicfg_mtx);
|
||||
}
|
||||
|
||||
/* check whether the configuration mechanism has been correctly identified */
|
||||
static int
|
||||
pci_cfgcheck(int maxdev)
|
||||
{
|
||||
uint32_t id, class;
|
||||
uint8_t header;
|
||||
uint8_t device;
|
||||
int port;
|
||||
|
||||
if (bootverbose)
|
||||
printf("pci_cfgcheck:\tdevice ");
|
||||
|
||||
for (device = 0; device < maxdev; device++) {
|
||||
if (bootverbose)
|
||||
printf("%d ", device);
|
||||
|
||||
port = pci_cfgenable(0, device, 0, 0, 4);
|
||||
id = inl(port);
|
||||
if (id == 0 || id == 0xffffffff)
|
||||
continue;
|
||||
|
||||
port = pci_cfgenable(0, device, 0, 8, 4);
|
||||
class = inl(port) >> 8;
|
||||
if (bootverbose)
|
||||
printf("[class=%06x] ", class);
|
||||
if (class == 0 || (class & 0xf870ff) != 0)
|
||||
continue;
|
||||
|
||||
port = pci_cfgenable(0, device, 0, 14, 1);
|
||||
header = inb(port);
|
||||
if (bootverbose)
|
||||
printf("[hdr=%02x] ", header);
|
||||
if ((header & 0x7e) != 0)
|
||||
continue;
|
||||
|
||||
if (bootverbose)
|
||||
printf("is there (id=%08x)\n", id);
|
||||
|
||||
pci_cfgdisable();
|
||||
return (1);
|
||||
}
|
||||
if (bootverbose)
|
||||
printf("-- nothing found\n");
|
||||
|
||||
pci_cfgdisable();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcireg_cfgopen(void)
|
||||
{
|
||||
uint32_t mode1res, oldval1;
|
||||
uint8_t mode2res, oldval2;
|
||||
|
||||
oldval1 = inl(CONF1_ADDR_PORT);
|
||||
|
||||
if (bootverbose) {
|
||||
printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08x\n",
|
||||
oldval1);
|
||||
}
|
||||
|
||||
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
|
||||
|
||||
cfgmech = 1;
|
||||
devmax = 32;
|
||||
|
||||
outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
|
||||
DELAY(1);
|
||||
mode1res = inl(CONF1_ADDR_PORT);
|
||||
outl(CONF1_ADDR_PORT, oldval1);
|
||||
|
||||
if (bootverbose)
|
||||
printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n",
|
||||
mode1res, CONF1_ENABLE_CHK);
|
||||
|
||||
if (mode1res) {
|
||||
if (pci_cfgcheck(32))
|
||||
return (cfgmech);
|
||||
}
|
||||
|
||||
outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
|
||||
mode1res = inl(CONF1_ADDR_PORT);
|
||||
outl(CONF1_ADDR_PORT, oldval1);
|
||||
|
||||
if (bootverbose)
|
||||
printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n",
|
||||
mode1res, CONF1_ENABLE_CHK1);
|
||||
|
||||
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
|
||||
if (pci_cfgcheck(32))
|
||||
return (cfgmech);
|
||||
}
|
||||
}
|
||||
|
||||
oldval2 = inb(CONF2_ENABLE_PORT);
|
||||
|
||||
if (bootverbose) {
|
||||
printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
|
||||
oldval2);
|
||||
}
|
||||
|
||||
if ((oldval2 & 0xf0) == 0) {
|
||||
|
||||
cfgmech = 2;
|
||||
devmax = 16;
|
||||
|
||||
outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
|
||||
mode2res = inb(CONF2_ENABLE_PORT);
|
||||
outb(CONF2_ENABLE_PORT, oldval2);
|
||||
|
||||
if (bootverbose)
|
||||
printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n",
|
||||
mode2res, CONF2_ENABLE_CHK);
|
||||
|
||||
if (mode2res == CONF2_ENABLE_RES) {
|
||||
if (bootverbose)
|
||||
printf("pci_open(2a):\tnow trying mechanism 2\n");
|
||||
|
||||
if (pci_cfgcheck(16))
|
||||
return (cfgmech);
|
||||
}
|
||||
}
|
||||
|
||||
cfgmech = 0;
|
||||
devmax = 0;
|
||||
return (cfgmech);
|
||||
}
|
||||
|
@ -403,6 +403,7 @@ pcireg_cfgopen(void)
|
||||
uint32_t mode1res, oldval1;
|
||||
uint8_t mode2res, oldval2;
|
||||
|
||||
/* Check for type #1 first. */
|
||||
oldval1 = inl(CONF1_ADDR_PORT);
|
||||
|
||||
if (bootverbose) {
|
||||
@ -410,39 +411,37 @@ pcireg_cfgopen(void)
|
||||
oldval1);
|
||||
}
|
||||
|
||||
if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
|
||||
cfgmech = CFGMECH_1;
|
||||
devmax = 32;
|
||||
|
||||
cfgmech = CFGMECH_1;
|
||||
devmax = 32;
|
||||
outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
|
||||
DELAY(1);
|
||||
mode1res = inl(CONF1_ADDR_PORT);
|
||||
outl(CONF1_ADDR_PORT, oldval1);
|
||||
|
||||
outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
|
||||
DELAY(1);
|
||||
mode1res = inl(CONF1_ADDR_PORT);
|
||||
outl(CONF1_ADDR_PORT, oldval1);
|
||||
if (bootverbose)
|
||||
printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n", mode1res,
|
||||
CONF1_ENABLE_CHK);
|
||||
|
||||
if (bootverbose)
|
||||
printf("pci_open(1a):\tmode1res=0x%08x (0x%08lx)\n",
|
||||
mode1res, CONF1_ENABLE_CHK);
|
||||
|
||||
if (mode1res) {
|
||||
if (pci_cfgcheck(32))
|
||||
return (cfgmech);
|
||||
}
|
||||
|
||||
outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
|
||||
mode1res = inl(CONF1_ADDR_PORT);
|
||||
outl(CONF1_ADDR_PORT, oldval1);
|
||||
|
||||
if (bootverbose)
|
||||
printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n",
|
||||
mode1res, CONF1_ENABLE_CHK1);
|
||||
|
||||
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
|
||||
if (pci_cfgcheck(32))
|
||||
return (cfgmech);
|
||||
}
|
||||
if (mode1res) {
|
||||
if (pci_cfgcheck(32))
|
||||
return (cfgmech);
|
||||
}
|
||||
|
||||
outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
|
||||
mode1res = inl(CONF1_ADDR_PORT);
|
||||
outl(CONF1_ADDR_PORT, oldval1);
|
||||
|
||||
if (bootverbose)
|
||||
printf("pci_open(1b):\tmode1res=0x%08x (0x%08lx)\n", mode1res,
|
||||
CONF1_ENABLE_CHK1);
|
||||
|
||||
if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
|
||||
if (pci_cfgcheck(32))
|
||||
return (cfgmech);
|
||||
}
|
||||
|
||||
/* Type #1 didn't work, so try type #2. */
|
||||
oldval2 = inb(CONF2_ENABLE_PORT);
|
||||
|
||||
if (bootverbose) {
|
||||
@ -472,6 +471,7 @@ pcireg_cfgopen(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing worked, so punt. */
|
||||
cfgmech = CFGMECH_NONE;
|
||||
devmax = 0;
|
||||
return (cfgmech);
|
||||
|
Loading…
Reference in New Issue
Block a user