diff options
author | wpaul <wpaul@FreeBSD.org> | 2000-11-16 19:56:09 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2000-11-16 19:56:09 +0000 |
commit | 7d8c4474eabedfa44c889c93748c3dbd3de0b9e2 (patch) | |
tree | 40f1e0bdb0ea1b5a3549ca34373604149d3c4edb /sys/pci/if_pcn.c | |
parent | b593b76bee29d3f6951bb3facde86725c3061964 (diff) | |
download | FreeBSD-src-7d8c4474eabedfa44c889c93748c3dbd3de0b9e2.zip FreeBSD-src-7d8c4474eabedfa44c889c93748c3dbd3de0b9e2.tar.gz |
When checking the device code in the probe routine, leave the chip in
16-bit mode. Technically, pcn_probe() is destructive because once the
chip goes into 32-bit mode, the only way to get it out again is a
hardware reset. And once the device is in 32-bit mode, the lnc driver
won't be able to talk to it. So if pcn_probe() is called before the
lnc probe routine, and pcn_probe() rejects the chip as one it doesn't
support, the lnc driver will be SOL.
I don't like this. I think it's a design flaw that you can't switch
the chip out of 32-bit mode once it's selected. The only 'right'
solution is for the pcn driver to support all of the PCI devices
in 32-bit mode, however I don't have samples of all the PCnet series
cards for testing.
Diffstat (limited to 'sys/pci/if_pcn.c')
-rw-r--r-- | sys/pci/if_pcn.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/sys/pci/if_pcn.c b/sys/pci/if_pcn.c index dc04df8..216e17c 100644 --- a/sys/pci/if_pcn.c +++ b/sys/pci/if_pcn.c @@ -110,6 +110,7 @@ static struct pcn_type pcn_devs[] = { }; static u_int32_t pcn_csr_read __P((struct pcn_softc *, int)); +static u_int16_t pcn_csr_read16 __P((struct pcn_softc *, int)); static void pcn_csr_write __P((struct pcn_softc *, int, int)); static u_int32_t pcn_bcr_read __P((struct pcn_softc *, int)); static void pcn_bcr_write __P((struct pcn_softc *, int, int)); @@ -203,6 +204,14 @@ static u_int32_t pcn_csr_read(sc, reg) return(CSR_READ_4(sc, PCN_IO32_RDP)); } +static u_int16_t pcn_csr_read16(sc, reg) + struct pcn_softc *sc; + int reg; +{ + CSR_WRITE_2(sc, PCN_IO16_RAP, reg); + return(CSR_READ_2(sc, PCN_IO16_RDP)); +} + static void pcn_csr_write(sc, reg, val) struct pcn_softc *sc; int reg; @@ -401,10 +410,20 @@ static int pcn_probe(dev) mtx_init(&sc->pcn_mtx, device_get_nameunit(dev), MTX_DEF); PCN_LOCK(sc); - pcn_reset(sc); - chip_id = pcn_csr_read(sc, PCN_CSR_CHIPID1); + /* + * Note: we can *NOT* put the chip into + * 32-bit mode yet. The lnc driver will only + * work in 16-bit mode, and once the chip + * goes into 32-bit mode, the only way to + * get it out again is with a hardware reset. + * So if pcn_probe() is called before the + * lnc driver's probe routine, the chip will + * be locked into 32-bit operation and the lnc + * driver will be unable to attach to it. + */ + chip_id = pcn_csr_read16(sc, PCN_CSR_CHIPID1); chip_id <<= 16; - chip_id |= pcn_csr_read(sc, PCN_CSR_CHIPID0); + chip_id |= pcn_csr_read16(sc, PCN_CSR_CHIPID0); bus_release_resource(dev, PCN_RES, PCN_RID, sc->pcn_res); PCN_UNLOCK(sc); |