Subject: Re: PCI mode probe [was Re: INSTALL kernel support ]
To: Manuel BOUYER , Jarkko Torppa <torppa@cute.fi>
From: Matthias Drochner <drochner@zelux6.zel.kfa-juelich.de>
List: port-i386
Date: 12/08/1997 20:53:16
Here is an updated patch to the "Compaq PCI configuration problem".
It's close to what I'd call a final solution. There are only minor
unresolved questions:
-Does it work at all?
-Do we need this hack for "Triflex 2" (device ID 0x2000)? Nobody
  with such a machine spoke up so far.
-Are there more chipsets which need special treatment?
-Can non-PCI machines be messed up by the probes?

For the last 2 items: It should not be worse than before. The same
registers are written to or read from. And the code doesn't do more
than equivalent code in FreeBSD and Linux does.
The second is only a question of esthetics - is this chipset
behaves correctly, the "switch" statement is not reached.

Please try it!

best regards
Matthias


Index: pci_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/pci/pci_machdep.c,v
retrieving revision 1.28
diff -r1.28 pci_machdep.c
100a101
> #include <dev/pci/pcidevs.h>
338a340,341
> 	u_int32_t sav, val;
> 
343,348c346
< 	 * 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.
350a349,392
> 	sav = inl(PCI_MODE1_ADDRESS_REG);
> 	/*
> 	 * Check:
> 	 * 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*/
> 		val = inl(PCI_MODE1_DATA_REG);
> 		if (PCI_VENDOR(val) == PCI_VENDOR_COMPAQ) {
> 			switch (PCI_PRODUCT(val)) {
> 			    case PCI_PRODUCT_COMPAQ_TRIFLEX1:
> 			    case PCI_PRODUCT_COMPAQ_TRIFLEX2:
> 			    case PCI_PRODUCT_COMPAQ_TRIFLEX4:
> 				printf("Compaq bug (%x)\n", val);
> 				break;
> 			    default:
> 				goto not1;
> 			}
> 		} else
> 			goto not1;
> 	}
> 	outl(PCI_MODE1_ADDRESS_REG, 0);
> 	val = inl(PCI_MODE1_ADDRESS_REG);
> 	if ((val & 0x80fffffc) != 0)
> 		goto not1;
> 	return (pci_mode = 1);
> 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.
> 	 */
357d398
< 
359,365d399
< 	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);
367d400
< not1: