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.
|
* 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_ENABLE_REG 0x0cf8
|
||||||
#define PCI_MODE2_FORWARD_REG 0x0cfa
|
#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
|
* PCI doesn't have any special needs; just use the generic versions
|
||||||
* of these functions.
|
* of these functions.
|
||||||
@ -313,6 +335,7 @@ mode1:
|
|||||||
outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
|
outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
|
||||||
outl(PCI_MODE1_DATA_REG, data);
|
outl(PCI_MODE1_DATA_REG, data);
|
||||||
outl(PCI_MODE1_ADDRESS_REG, 0);
|
outl(PCI_MODE1_ADDRESS_REG, 0);
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
|
#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
|
||||||
@ -337,35 +360,79 @@ pci_mode_detect()
|
|||||||
#error Invalid PCI configuration mode.
|
#error Invalid PCI configuration mode.
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
|
u_int32_t sav, val;
|
||||||
|
int i;
|
||||||
|
pcireg_t idreg;
|
||||||
|
|
||||||
if (pci_mode != -1)
|
if (pci_mode != -1)
|
||||||
return pci_mode;
|
return pci_mode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We try to divine which configuration mode the host bridge wants. We
|
* We try to divine which configuration mode the host bridge wants.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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_ENABLE_REG, 0);
|
||||||
outb(PCI_MODE2_FORWARD_REG, 0);
|
outb(PCI_MODE2_FORWARD_REG, 0);
|
||||||
if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
|
if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
|
||||||
inb(PCI_MODE2_FORWARD_REG) != 0)
|
inb(PCI_MODE2_FORWARD_REG) != 0)
|
||||||
goto not2;
|
goto not2;
|
||||||
return (pci_mode = 2);
|
return (pci_mode = 2);
|
||||||
|
|
||||||
not2:
|
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);
|
return (pci_mode = 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user