redo the PCI configuration mode detection - should make some less
standard compliant PCI chipsets work (Compaq, Connectix emulated Triton) fix the bug reported in PR port-i386/5727 (soda@sra.co.jp)
This commit is contained in:
parent
b5a268eddf
commit
d1da31d671
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pci_machdep.c,v 1.31 1998/06/03 06:35:49 thorpej Exp $ */
|
||||
/* $NetBSD: pci_machdep.c,v 1.32 1998/07/09 20:19:52 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
|
||||
@ -109,6 +109,28 @@ int pci_mode = -1;
|
||||
#define PCI_MODE2_ENABLE_REG 0x0cf8
|
||||
#define PCI_MODE2_FORWARD_REG 0x0cfa
|
||||
|
||||
#define _m1tag(b, d, f) \
|
||||
(PCI_MODE1_ENABLE | ((b) << 16) | ((d) << 11) | ((f) << 8))
|
||||
#define _id(v, p) \
|
||||
(((v) << PCI_VENDOR_SHIFT) | ((p) << PCI_PRODUCT_SHIFT))
|
||||
#define _qe(bus, dev, fcn, vend, prod) \
|
||||
{_m1tag(bus, dev, fcn), _id(vend, prod)}
|
||||
struct {
|
||||
u_int32_t tag;
|
||||
pcireg_t id;
|
||||
} pcim1_quirk_tbl[] = {
|
||||
_qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX1),
|
||||
/* XXX Triflex2 not tested */
|
||||
_qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX2),
|
||||
_qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX4),
|
||||
/* Triton needed for Connectix Virtual PC */
|
||||
_qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437FX),
|
||||
{0, 0xffffffff} /* patchable */
|
||||
};
|
||||
#undef _m1tag
|
||||
#undef _id
|
||||
#undef _qe
|
||||
|
||||
/*
|
||||
* PCI doesn't have any special needs; just use the generic versions
|
||||
* of these functions.
|
||||
@ -313,6 +335,7 @@ mode1:
|
||||
outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
|
||||
outl(PCI_MODE1_DATA_REG, data);
|
||||
outl(PCI_MODE1_ADDRESS_REG, 0);
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
|
||||
@ -337,35 +360,79 @@ pci_mode_detect()
|
||||
#error Invalid PCI configuration mode.
|
||||
#endif
|
||||
#else
|
||||
u_int32_t sav, val;
|
||||
int i;
|
||||
pcireg_t idreg;
|
||||
|
||||
if (pci_mode != -1)
|
||||
return pci_mode;
|
||||
|
||||
/*
|
||||
* We try to divine which configuration mode the host bridge wants. We
|
||||
* try mode 2 first, because our probe for mode 1 is likely to succeed
|
||||
* for mode 2 also.
|
||||
*
|
||||
* XXX
|
||||
* This should really be done using the PCI BIOS.
|
||||
* We try to divine which configuration mode the host bridge wants.
|
||||
*/
|
||||
|
||||
sav = inl(PCI_MODE1_ADDRESS_REG);
|
||||
|
||||
pci_mode = 1; /* assume this for now */
|
||||
/*
|
||||
* catch some known buggy implementations of mode 1
|
||||
*/
|
||||
for (i = 0; i < sizeof(pcim1_quirk_tbl) / sizeof(pcim1_quirk_tbl[0]);
|
||||
i++) {
|
||||
pcitag_t t;
|
||||
|
||||
if (!pcim1_quirk_tbl[i].tag)
|
||||
break;
|
||||
t.mode1 = pcim1_quirk_tbl[i].tag;
|
||||
idreg = pci_conf_read(0, t, PCI_ID_REG); /* needs "pci_mode" */
|
||||
if (idreg == pcim1_quirk_tbl[i].id) {
|
||||
#ifdef DEBUG
|
||||
printf("known mode 1 PCI chipset (%08x)\n",
|
||||
idreg);
|
||||
#endif
|
||||
return (pci_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Strong check for standard compliant mode 1:
|
||||
* 1. bit 31 ("enable") can be set
|
||||
* 2. byte/word access does not affect register
|
||||
*/
|
||||
outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE);
|
||||
outb(PCI_MODE1_ADDRESS_REG + 3, 0);
|
||||
outw(PCI_MODE1_ADDRESS_REG + 2, 0);
|
||||
val = inl(PCI_MODE1_ADDRESS_REG);
|
||||
if ((val & 0x80fffffc) != PCI_MODE1_ENABLE) {
|
||||
#ifdef DEBUG
|
||||
printf("pci_mode_detect: mode 1 enable failed (%x)\n",
|
||||
val);
|
||||
#endif
|
||||
goto not1;
|
||||
}
|
||||
outl(PCI_MODE1_ADDRESS_REG, 0);
|
||||
val = inl(PCI_MODE1_ADDRESS_REG);
|
||||
if ((val & 0x80fffffc) != 0)
|
||||
goto not1;
|
||||
return (pci_mode);
|
||||
not1:
|
||||
outl(PCI_MODE1_ADDRESS_REG, sav);
|
||||
|
||||
/*
|
||||
* This mode 2 check is quite weak (and known to give false
|
||||
* positives on some Compaq machines).
|
||||
* However, this doesn't matter, because this is the
|
||||
* last test, and simply no PCI devices will be found if
|
||||
* this happens.
|
||||
*/
|
||||
outb(PCI_MODE2_ENABLE_REG, 0);
|
||||
outb(PCI_MODE2_FORWARD_REG, 0);
|
||||
if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
|
||||
inb(PCI_MODE2_FORWARD_REG) != 0)
|
||||
goto not2;
|
||||
return (pci_mode = 2);
|
||||
|
||||
not2:
|
||||
outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE);
|
||||
if (inl(PCI_MODE1_ADDRESS_REG) != PCI_MODE1_ENABLE)
|
||||
goto not1;
|
||||
outl(PCI_MODE1_ADDRESS_REG, 0);
|
||||
if (inl(PCI_MODE1_ADDRESS_REG) != 0)
|
||||
goto not1;
|
||||
return (pci_mode = 1);
|
||||
|
||||
not1:
|
||||
return (pci_mode = 0);
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user