summaryrefslogtreecommitdiffstats
path: root/sys/dev/ed
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-09-07 03:30:58 +0000
committerimp <imp@FreeBSD.org>2005-09-07 03:30:58 +0000
commit1c4b0b9c5f599f3fe4e9d2ff620d41826faa8b67 (patch)
treea671127b5d08c142b8b43fdf5710ad9a5cf5da4d /sys/dev/ed
parentaa9d523c4119c5a4b3d56e6f062a81e051d4c087 (diff)
downloadFreeBSD-src-1c4b0b9c5f599f3fe4e9d2ff620d41826faa8b67.zip
FreeBSD-src-1c4b0b9c5f599f3fe4e9d2ff620d41826faa8b67.tar.gz
Minor reorg of pccard attach code to fix ax88x90 case broken after fixing
dl100xx case. o We no longer acquire and release resources during attach many times. We now do it once at the beginning. o Move setting the resource offsets to just after acquiring the ports in attach. o Move ax88x90 code to the end of the file, just after the dl100xx specific code. o Rename ed_pccard_Linksys to ed_pccard_dl100xx to reflect the underlying chipset. o Pass the ed_product structure into ed_pccard_{dl100xx,ax88x90} and have those routines test the flags to see if this card should be probed in that way. o transition from ed_probe_Novell to ed_probe_Novell_generic since we already have the resources setup. o Move use of ed_probe_Novell_generic into ed_pccard_dl100xx to be more consistant with ax88x90 case. o simplify the code where we probe for the chipsets
Diffstat (limited to 'sys/dev/ed')
-rw-r--r--sys/dev/ed/if_ed_pccard.c318
1 files changed, 158 insertions, 160 deletions
diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c
index 378e9a0..78275bc 100644
--- a/sys/dev/ed/if_ed_pccard.c
+++ b/sys/dev/ed/if_ed_pccard.c
@@ -79,25 +79,6 @@ MODULE_DEPEND(ed, ether, 1, 1, 1);
*/
#define ED_DEFAULT_MAC_OFFSET 0xff0
-/*
- * PC Card (PCMCIA) specific code.
- */
-static int ed_pccard_probe(device_t);
-static int ed_pccard_attach(device_t);
-
-static int ed_pccard_ax88x90(device_t dev);
-
-static void ax88x90_geteprom(struct ed_softc *);
-static int ed_pccard_memread(device_t dev, off_t offset, u_char *byte);
-static int ed_pccard_memwrite(device_t dev, off_t offset, u_char byte);
-#ifndef ED_NO_MIIBUS
-static void ed_pccard_dlink_mii_reset(struct ed_softc *sc);
-static u_int ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits);
-static void ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val,
- int nbits);
-#endif
-static int ed_pccard_Linksys(device_t dev);
-
static const struct ed_product {
struct pccard_product prod;
int flags;
@@ -194,6 +175,25 @@ static const struct ed_product {
{ { NULL } }
};
+/*
+ * PC Card (PCMCIA) specific code.
+ */
+static int ed_pccard_probe(device_t);
+static int ed_pccard_attach(device_t);
+
+static int ed_pccard_memread(device_t dev, off_t offset, u_char *byte);
+static int ed_pccard_memwrite(device_t dev, off_t offset, u_char byte);
+
+static int ed_pccard_dl100xx(device_t dev, const struct ed_product *);
+#ifndef ED_NO_MIIBUS
+static void ed_pccard_dlink_mii_reset(struct ed_softc *sc);
+static u_int ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits);
+static void ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val,
+ int nbits);
+#endif
+
+static int ed_pccard_ax88x90(device_t dev, const struct ed_product *);
+
static int
ed_pccard_probe(device_t dev)
{
@@ -289,36 +289,35 @@ ed_pccard_attach(device_t dev)
} else {
sc->port_rid = 0;
}
- if (pp->flags & NE2000DVF_DL100XX) {
- error = ed_probe_Novell(dev, sc->port_rid, 0);
- if (error == 0)
- error = ed_pccard_Linksys(dev);
- if (error == 0)
- goto end2;
- }
- if (pp->flags & NE2000DVF_AX88X90) {
- error = ed_pccard_ax88x90(dev);
- if (error == 0)
- goto end2;
- }
- error = ed_probe_Novell(dev, sc->port_rid, 0);
-end2:
- if (error) {
- ed_release_resources(dev);
+ /* Allocate the port resource during setup. */
+ error = ed_alloc_port(dev, sc->port_rid, ED_NOVELL_IO_PORTS);
+ if (error)
return (error);
- }
error = ed_alloc_irq(dev, 0, 0);
- if (error) {
- ed_release_resources(dev);
- return (error);
- }
+ if (error)
+ goto bad;
+
+ /*
+ * Determine which chipset we are. All the PC Card chipsets have the
+ * ASIC and NIC offsets in the same place.
+ */
+ sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_offset = ED_NOVELL_NIC_OFFSET;
+ error = ENXIO;
+ if (error != 0)
+ error = ed_pccard_dl100xx(dev, pp);
+ if (error != 0 && pp->flags & NE2000DVF_AX88X90)
+ error = ed_pccard_ax88x90(dev, pp);
+ if (error != 0)
+ error = ed_probe_Novell_generic(dev, device_get_flags(dev));
+ if (error)
+ goto bad;
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
edintr, sc, &sc->irq_handle);
if (error) {
device_printf(dev, "setup intr failed %d \n", error);
- ed_release_resources(dev);
- return (error);
+ goto bad;
}
/*
@@ -372,10 +371,8 @@ end2:
}
error = ed_attach(dev);
- if (error) {
- ed_release_resources(dev);
- return (error);
- }
+ if (error)
+ goto bad;
#ifndef ED_NO_MIIBUS
if (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
sc->chip_type == ED_CHIP_TYPE_DL10022) {
@@ -390,72 +387,9 @@ end2:
if (sc->modem_rid != -1)
ed_pccard_add_modem(dev);
return (0);
-}
-
-static void
-ax88x90_geteprom(struct ed_softc *sc)
-{
- int prom[16],i;
- u_char tmp;
- struct {
- unsigned char offset, value;
- } pg_seq[] = {
- /* Select Page0 */
- {ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0},
- {ED_P0_DCR, 0x01},
- {ED_P0_RBCR0, 0x00}, /* Clear the count regs. */
- {ED_P0_RBCR1, 0x00},
- {ED_P0_IMR, 0x00}, /* Mask completion irq. */
- {ED_P0_ISR, 0xff},
- {ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT}, /* Set To Monitor */
- {ED_P0_TCR, ED_TCR_LB0}, /* loopback mode. */
- {ED_P0_RBCR0, 32},
- {ED_P0_RBCR1, 0x00},
- {ED_P0_RSAR0, 0x00},
- {ED_P0_RSAR1, 0x04},
- {ED_P0_CR, ED_CR_RD0 | ED_CR_STA | ED_CR_PAGE_0},
- };
-
- /* XXX The Linux axnet_cs driver does the following differently */
- /* Reset Card */
- tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
- ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
- DELAY(5000);
- ed_asic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0);
- DELAY(5000);
-
- /* Card Settings */
- for (i = 0; i < sizeof(pg_seq) / sizeof(pg_seq[0]); i++)
- ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value);
-
- /* Get Data */
- for (i = 0; i < 16; i++)
- prom[i] = ed_asic_inw(sc, 0);
-
- /*
- * Work around a bug I've seen on Linksys EC2T cards. On
- * these cards, the node address is contained in the low order
- * bytes of the prom, with the upper byte being 0. On other
- * cards, the bytes are packed two per word. I'm unsure why
- * this is the case, and why no other open source OS has a
- * similar workaround. The Linksys EC2T card is still extremely
- * popular on E-Bay, fetching way more than any other 10Mbps
- * only card. I might be able to test to see if prom[7] and
- * prom[15] == 0x5757, since that appears to be a reliable
- * test. On the EC2T cards, I get 0x0057 in prom[14,15] instead.
- */
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- if (prom[i] & 0xff00)
- break;
- if (i == ETHER_ADDR_LEN) {
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- sc->enaddr[i] = prom[i] & 0xff;
- } else {
- for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
- sc->enaddr[i] = prom[i / 2] & 0xff;
- sc->enaddr[i + 1] = (prom[i / 2] >> 8) & 0xff;
- }
- }
+bad:
+ ed_release_resources(dev);
+ return (error);
}
static int
@@ -513,12 +447,18 @@ ed_pccard_memread(device_t dev, off_t offset, u_char *byte)
* conditionally.
*/
static int
-ed_pccard_Linksys(device_t dev)
+ed_pccard_dl100xx(device_t dev, const struct ed_product *pp)
{
struct ed_softc *sc = device_get_softc(dev);
u_char sum;
uint8_t id;
- int i;
+ int i, error;
+
+ if (!pp->flags & NE2000DVF_DL100XX)
+ return (ENXIO);
+ error = ed_probe_Novell_generic(dev, device_get_flags(dev));
+ if (error != 0)
+ return (error);
/*
* Linksys registers(offset from ASIC base)
@@ -544,52 +484,6 @@ ed_pccard_Linksys(device_t dev)
return (0);
}
-/*
- * Special setup for AX88[17]90
- */
-static int
-ed_pccard_ax88x90(device_t dev)
-{
- int error;
- int flags = device_get_flags(dev);
- int iobase;
- char *ts;
- struct ed_softc *sc = device_get_softc(dev);
-
- /* Allocate the port resource during setup. */
- error = ed_alloc_port(dev, sc->port_rid, ED_NOVELL_IO_PORTS);
- if (error)
- return (error);
-
- sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
- sc->nic_offset = ED_NOVELL_NIC_OFFSET;
- sc->chip_type = ED_CHIP_TYPE_AX88190;
-
- /* XXX
- * Set Attribute Memory IOBASE Register. Is this a deficiency in
- * the PC Card layer, or an ax88190 specific issue? The card
- * definitely doesn't work without it.
- */
- iobase = rman_get_start(sc->port_res);
- ed_pccard_memwrite(dev, ED_AX88190_IOBASE0, iobase & 0xff);
- ed_pccard_memwrite(dev, ED_AX88190_IOBASE1, (iobase >> 8) & 0xff);
- ts = "AX88190";
- if (ed_asic_inb(sc, ED_ASIX_TEST) != 0) {
- ed_pccard_memwrite(dev, ED_AX88790_CSR, ED_AX88790_CSR_PWRDWN);
- ts = "AX88790";
- }
- ax88x90_geteprom(sc);
- ed_release_resources(dev);
- error = ed_probe_Novell(dev, sc->port_rid, flags);
- if (error == 0) {
- sc->vendor = ED_VENDOR_NOVELL;
- sc->type = ED_TYPE_NE2000;
- sc->chip_type = ED_CHIP_TYPE_AX88190;
- sc->type_str = ts;
- }
- return (error);
-}
-
#ifndef ED_NO_MIIBUS
/* MII bit-twiddling routines for cards using Dlink chipset */
#define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
@@ -663,6 +557,110 @@ ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits)
}
#endif
+static void
+ed_pccard_ax88x90_geteprom(struct ed_softc *sc)
+{
+ int prom[16],i;
+ u_char tmp;
+ struct {
+ unsigned char offset, value;
+ } pg_seq[] = {
+ /* Select Page0 */
+ {ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0},
+ {ED_P0_DCR, 0x01},
+ {ED_P0_RBCR0, 0x00}, /* Clear the count regs. */
+ {ED_P0_RBCR1, 0x00},
+ {ED_P0_IMR, 0x00}, /* Mask completion irq. */
+ {ED_P0_ISR, 0xff},
+ {ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT}, /* Set To Monitor */
+ {ED_P0_TCR, ED_TCR_LB0}, /* loopback mode. */
+ {ED_P0_RBCR0, 32},
+ {ED_P0_RBCR1, 0x00},
+ {ED_P0_RSAR0, 0x00},
+ {ED_P0_RSAR1, 0x04},
+ {ED_P0_CR, ED_CR_RD0 | ED_CR_STA | ED_CR_PAGE_0},
+ };
+
+ /* Reset Card */
+ tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
+ ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
+ DELAY(5000);
+ ed_asic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0);
+ DELAY(5000);
+
+ /* Card Settings */
+ for (i = 0; i < sizeof(pg_seq) / sizeof(pg_seq[0]); i++)
+ ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value);
+
+ /* Get Data */
+ for (i = 0; i < 16; i++)
+ prom[i] = ed_asic_inw(sc, 0);
+
+ /*
+ * Work around a bug I've seen on Linksys EC2T cards. On
+ * these cards, the node address is contained in the low order
+ * bytes of the prom, with the upper byte being 0. On other
+ * cards, the bytes are packed two per word. I'm unsure why
+ * this is the case, and why no other open source OS has a
+ * similar workaround. The Linksys EC2T card is still extremely
+ * popular on E-Bay, fetching way more than any other 10Mbps
+ * only card. I might be able to test to see if prom[7] and
+ * prom[15] == 0x5757, since that appears to be a reliable
+ * test. On the EC2T cards, I get 0x0057 in prom[14,15] instead.
+ */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ if (prom[i] & 0xff00)
+ break;
+ if (i == ETHER_ADDR_LEN) {
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->enaddr[i] = prom[i] & 0xff;
+ } else {
+ for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
+ sc->enaddr[i] = prom[i / 2] & 0xff;
+ sc->enaddr[i + 1] = (prom[i / 2] >> 8) & 0xff;
+ }
+ }
+}
+
+/*
+ * Special setup for AX88[17]90
+ */
+static int
+ed_pccard_ax88x90(device_t dev, const struct ed_product *pp)
+{
+ int error;
+ int iobase;
+ char *ts;
+ struct ed_softc *sc = device_get_softc(dev);
+
+ if (!pp->flags & NE2000DVF_AX88X90)
+ return (ENXIO);
+
+ /* XXX
+ * Set Attribute Memory IOBASE Register. Is this a deficiency in
+ * the PC Card layer, or an ax88190 specific issue? The card
+ * definitely doesn't work without it.
+ */
+ iobase = rman_get_start(sc->port_res);
+ ed_pccard_memwrite(dev, ED_AX88190_IOBASE0, iobase & 0xff);
+ ed_pccard_memwrite(dev, ED_AX88190_IOBASE1, (iobase >> 8) & 0xff);
+ ts = "AX88190";
+ if (ed_asic_inb(sc, ED_ASIX_TEST) != 0) {
+ ed_pccard_memwrite(dev, ED_AX88790_CSR, ED_AX88790_CSR_PWRDWN);
+ ts = "AX88790";
+ }
+ sc->chip_type = ED_CHIP_TYPE_AX88190;
+ ed_pccard_ax88x90_geteprom(sc);
+ error = ed_probe_Novell_generic(dev, device_get_flags(dev));
+ if (error == 0) {
+ sc->vendor = ED_VENDOR_NOVELL;
+ sc->type = ED_TYPE_NE2000;
+ sc->chip_type = ED_CHIP_TYPE_AX88190;
+ sc->type_str = ts;
+ }
+ return (error);
+}
+
static device_method_t ed_pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ed_pccard_probe),
OpenPOWER on IntegriCloud