summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authormdodd <mdodd@FreeBSD.org>2004-12-03 18:21:30 +0000
committermdodd <mdodd@FreeBSD.org>2004-12-03 18:21:30 +0000
commitaa6945f506cd58becfa1c81a24af00613f5eb2e9 (patch)
tree9770b8c435462a46b4d4f47a60431dc498f8fe52 /sys/pci
parentb0e48f225888bdc5304000616e8159beb9074fb2 (diff)
downloadFreeBSD-src-aa6945f506cd58becfa1c81a24af00613f5eb2e9.zip
FreeBSD-src-aa6945f506cd58becfa1c81a24af00613f5eb2e9.tar.gz
- Move chip ID code into separate function.
- Initialize sc->pcn_type during ATTACH as softc contents may not surivive from PROBE. - Print out chip-id to assist with ongoing pcn(4) debugging efforts.
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_pcn.c136
1 files changed, 94 insertions, 42 deletions
diff --git a/sys/pci/if_pcn.c b/sys/pci/if_pcn.c
index ead2845..bae6de0 100644
--- a/sys/pci/if_pcn.c
+++ b/sys/pci/if_pcn.c
@@ -104,6 +104,28 @@ static struct pcn_type pcn_devs[] = {
{ 0, 0, NULL }
};
+static struct pcn_chipid {
+ u_int32_t id;
+ char * name;
+} pcn_chipid[] = {
+ { Am79C960, "Am79C960" },
+ { Am79C961, "Am79C961" },
+ { Am79C961A, "Am79C961A" },
+ { Am79C965, "Am79C965" },
+ { Am79C970, "Am79C970" },
+ { Am79C970A, "Am79C970A" },
+ { Am79C971, "Am79C971" },
+ { Am79C972, "Am79C972" },
+ { Am79C973, "Am79C973" },
+ { Am79C978, "Am79C978" },
+ { Am79C975, "Am79C975" },
+ { Am79C976, "Am79C976" },
+ { 0, NULL },
+};
+
+static char * pcn_chipid_name(u_int32_t);
+static u_int32_t pcn_chip_id (device_t);
+
static u_int32_t pcn_csr_read (struct pcn_softc *, int);
static u_int16_t pcn_csr_read16 (struct pcn_softc *, int);
static u_int16_t pcn_bcr_read16 (struct pcn_softc *, int);
@@ -373,6 +395,72 @@ pcn_reset(sc)
return;
}
+static char *
+pcn_chipid_name (u_int32_t id)
+{
+ struct pcn_chipid *p = pcn_chipid;
+
+ while (p->name) {
+ if (id == p->id)
+ return (p->name);
+ p++;
+ }
+ return ("Unknown");
+}
+
+static u_int32_t
+pcn_chip_id (device_t dev)
+{
+ struct pcn_softc *sc;
+ u_int32_t chip_id;
+
+ sc = device_get_softc(dev);
+ /*
+ * 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.
+ * Note II: if the chip happens to already
+ * be in 32-bit mode, we still need to check
+ * the chip ID, but first we have to detect
+ * 32-bit mode using only 16-bit operations.
+ * The safest way to do this is to read the
+ * PCI subsystem ID from BCR23/24 and compare
+ * that with the value read from PCI config
+ * space.
+ */
+ chip_id = pcn_bcr_read16(sc, PCN_BCR_PCISUBSYSID);
+ chip_id <<= 16;
+ chip_id |= pcn_bcr_read16(sc, PCN_BCR_PCISUBVENID);
+ /*
+ * Note III: the test for 0x10001000 is a hack to
+ * pacify VMware, who's pseudo-PCnet interface is
+ * broken. Reading the subsystem register from PCI
+ * config space yields 0x00000000 while reading the
+ * same value from I/O space yields 0x10001000. It's
+ * not supposed to be that way.
+ */
+ if (chip_id == pci_read_config(dev,
+ PCIR_SUBVEND_0, 4) || chip_id == 0x10001000) {
+ /* We're in 16-bit mode. */
+ chip_id = pcn_csr_read16(sc, PCN_CSR_CHIPID1);
+ chip_id <<= 16;
+ chip_id |= pcn_csr_read16(sc, PCN_CSR_CHIPID0);
+ } else {
+ /* We're in 32-bit mode. */
+ chip_id = pcn_csr_read(sc, PCN_CSR_CHIPID1);
+ chip_id <<= 16;
+ chip_id |= pcn_csr_read(sc, PCN_CSR_CHIPID0);
+ }
+
+ return (chip_id);
+}
+
/*
* Probe for an AMD chip. Check the PCI vendor and device
* IDs against our list and return a device name if we find a match.
@@ -410,48 +498,7 @@ pcn_probe(dev)
device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
PCN_LOCK(sc);
- /*
- * 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.
- * Note II: if the chip happens to already
- * be in 32-bit mode, we still need to check
- * the chip ID, but first we have to detect
- * 32-bit mode using only 16-bit operations.
- * The safest way to do this is to read the
- * PCI subsystem ID from BCR23/24 and compare
- * that with the value read from PCI config
- * space.
- */
- chip_id = pcn_bcr_read16(sc, PCN_BCR_PCISUBSYSID);
- chip_id <<= 16;
- chip_id |= pcn_bcr_read16(sc, PCN_BCR_PCISUBVENID);
- /*
- * Note III: the test for 0x10001000 is a hack to
- * pacify VMware, who's pseudo-PCnet interface is
- * broken. Reading the subsystem register from PCI
- * config space yields 0x00000000 while reading the
- * same value from I/O space yields 0x10001000. It's
- * not supposed to be that way.
- */
- if (chip_id == pci_read_config(dev,
- PCIR_SUBVEND_0, 4) || chip_id == 0x10001000) {
- /* We're in 16-bit mode. */
- chip_id = pcn_csr_read16(sc, PCN_CSR_CHIPID1);
- chip_id <<= 16;
- chip_id |= pcn_csr_read16(sc, PCN_CSR_CHIPID0);
- } else {
- /* We're in 32-bit mode. */
- chip_id = pcn_csr_read(sc, PCN_CSR_CHIPID1);
- chip_id <<= 16;
- chip_id |= pcn_csr_read(sc, PCN_CSR_CHIPID0);
- }
+ chip_id = pcn_chip_id(dev);
bus_release_resource(dev, PCN_RES,
PCN_RID, sc->pcn_res);
PCN_UNLOCK(sc);
@@ -502,6 +549,11 @@ pcn_attach(dev)
*/
pci_enable_busmaster(dev);
+ /* Retrieve the chip ID */
+ sc->pcn_type = (pcn_chip_id(dev) >> 12) & PART_MASK;
+ device_printf(dev, "Chip ID %04x (%s)\n",
+ sc->pcn_type, pcn_chipid_name(sc->pcn_type));
+
rid = PCN_RID;
sc->pcn_res = bus_alloc_resource_any(dev, PCN_RES, &rid, RF_ACTIVE);
OpenPOWER on IntegriCloud