summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ep/if_ep.c5
-rw-r--r--sys/dev/ep/if_ep_eisa.c2
-rw-r--r--sys/dev/ep/if_ep_pccard.c372
-rw-r--r--sys/dev/ep/if_epvar.h2
4 files changed, 226 insertions, 155 deletions
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index 7202bf9..508dd8a 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -66,6 +66,7 @@
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
+#include <sys/bus.h>
#include <net/ethernet.h>
#include <net/if.h>
@@ -84,6 +85,7 @@ struct ep_softc * ep_softc[NEP];
struct ep_board ep_board[EP_MAX_BOARDS + 1];
int ep_boards;
u_long ep_unit;
+devclass_t ep_devclass;
static char * ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
@@ -517,6 +519,9 @@ ep_intr(arg)
sc = (struct ep_softc *)arg;
+ if (sc->gone)
+ return;
+
ifp = &sc->arpcom.ac_if;
outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */
diff --git a/sys/dev/ep/if_ep_eisa.c b/sys/dev/ep/if_ep_eisa.c
index f9a58f0..42ae2b6 100644
--- a/sys/dev/ep/if_ep_eisa.c
+++ b/sys/dev/ep/if_ep_eisa.c
@@ -304,7 +304,7 @@ static driver_t ep_eisa_driver = {
1, /* unused */
};
-static devclass_t ep_devclass;
+extern devclass_t ep_devclass;
DRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0);
diff --git a/sys/dev/ep/if_ep_pccard.c b/sys/dev/ep/if_ep_pccard.c
index 6fad878..7b373e1 100644
--- a/sys/dev/ep/if_ep_pccard.c
+++ b/sys/dev/ep/if_ep_pccard.c
@@ -43,6 +43,10 @@
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
#include <net/ethernet.h>
#include <net/if.h>
@@ -51,195 +55,255 @@
#include <machine/clock.h>
+#include <dev/ep/if_epreg.h>
+#include <dev/ep/if_epvar.h>
+
+/* XXX should die XXX */
#include <sys/select.h>
#include <sys/module.h>
#include <pccard/cardinfo.h>
#include <pccard/slot.h>
-#include <dev/ep/if_epreg.h>
-#include <dev/ep/if_epvar.h>
-
-/*
- * PC-Card (PCMCIA) specific code.
- */
-static int ep_pccard_init (struct pccard_devinfo *);
-static int ep_pccard_attach (struct pccard_devinfo *);
-static void ep_pccard_unload (struct pccard_devinfo *);
-static int ep_pccard_intr (struct pccard_devinfo *);
-static int ep_pccard_identify (struct ep_board *epb, int unit);
-
-PCCARD_MODULE(ep, ep_pccard_init, ep_pccard_unload, ep_pccard_intr, 0, net_imask);
+static const char *ep_pccard_identify(u_short id);
/*
* Initialize the device - called from Slot manager.
*/
static int
-ep_pccard_init(devi)
- struct pccard_devinfo *devi;
+ep_pccard_probe(device_t dev)
{
- struct isa_device *is = &devi->isahd;
- struct ep_softc *sc = ep_softc[is->id_unit];
- struct ep_board *epb;
- int i;
+ struct ep_board ep;
+ struct ep_board *epb;
+ u_long port_start, port_count;
+ struct ep_softc fake_softc;
+ struct ep_softc *sc = &fake_softc;
+ const char *desc;
+ int error;
+ const char *name;
+
+ name = pccard_get_name(dev);
+ printf("ep_pccard_probe: Does %s match?\n", name);
+ if (strcmp(name, "ep"))
+ return ENXIO;
+
+ epb = &ep;
+ error = bus_get_resource(dev, SYS_RES_IOPORT, 0, &port_start,
+ &port_count);
+ if (error != 0)
+ return error;
+ /* get_e() requires these. */
+ bzero(sc, sizeof(*sc));
+ sc->ep_io_addr = port_start;
+ sc->unit = device_get_unit(dev);
+ sc->epb = epb;
- epb = &ep_board[is->id_unit];
+ /*
+ * XXX - Certain (newer?) 3Com cards need epb->cmd_off ==
+ * 2. Sadly, you need to have a correct cmd_off in order to
+ * identify the card. So we have to hit it with both and
+ * cross our virtual fingers. There's got to be a better way
+ * to do this. jyoung@accessus.net 09/11/1999
+ */
- if (sc == 0) {
- if ((sc = ep_alloc(is->id_unit, epb)) == 0) {
- return (ENXIO);
- }
- ep_unit++;
- }
-
- /* get_e() requires these. */
- sc->ep_io_addr = is->id_iobase;
- sc->unit = is->id_unit;
- epb->epb_addr = is->id_iobase;
- epb->epb_used = 1;
-
- /*
- * XXX - Certain (newer?) 3Com cards need epb->cmd_off == 2. Sadly,
- * you need to have a correct cmd_off in order to identify the card.
- * So we have to hit it with both and cross our virtual fingers. There's
- * got to be a better way to do this. jyoung@accessus.net 09/11/1999
- */
-
- epb->cmd_off = 0;
- epb->prod_id = get_e(sc, EEPROM_PROD_ID);
- if (!ep_pccard_identify(epb, is->id_unit)) {
- if (bootverbose) printf("ep%d: Pass 1 of 2 detection failed (nonfatal)\n", is->id_unit);
- epb->cmd_off = 2;
+ epb->cmd_off = 0;
epb->prod_id = get_e(sc, EEPROM_PROD_ID);
- if (!ep_pccard_identify(epb, is->id_unit)) {
- if (bootverbose) printf("ep%d: Pass 2 of 2 detection failed (fatal!)\n", is->id_unit);
- printf("ep%d: Unit failed to come ready or product ID unknown! (id 0x%x)\n", is->id_unit, epb->prod_id);
- return (ENXIO);
+ if ((desc = ep_pccard_identify(epb->prod_id)) == NULL) {
+ if (bootverbose)
+ device_printf(dev, "Pass 1 of 2 detection "
+ "failed (nonfatal)\n");
+ epb->cmd_off = 2;
+ epb->prod_id = get_e(sc, EEPROM_PROD_ID);
+ if ((desc = ep_pccard_identify(epb->prod_id))) {
+ device_printf(dev, "Unit failed to come ready or "
+ "product ID unknown! (id 0x%x)\n", epb->prod_id);
+ return (ENXIO);
+ }
}
- }
- epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
- for (i = 0; i < 3; i++)
- sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
-
- if (ep_pccard_attach(devi) == 0)
- return (ENXIO);
+ return (0);
+}
- sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
- return (0);
+static const char *
+ep_pccard_identify(u_short id)
+{
+ /* Determine device type and associated MII capabilities */
+ switch (id) {
+ case 0x6055: /* 3C556 */
+ return ("3Com 3C556");
+ case 0x4057: /* 3C574 */
+ return("3Com 3C574");
+ case 0x4b57: /* 3C574B */
+ return("3Com 3C574B, Megahertz 3CCFE574BT or "
+ "Fast Etherlink 3C574-TX");
+ case 0x9058: /* 3C589 */
+ return("3Com Etherlink III 3C589[B/C/D]");
+ }
+ return (0);
}
static int
-ep_pccard_identify(epb, unit)
- struct ep_board *epb;
- int unit;
+ep_pccard_card_attach(struct ep_board *epb)
{
- /* Determine device type and associated MII capabilities */
- switch (epb->prod_id) {
+ /* Determine device type and associated MII capabilities */
+ switch (epb->prod_id) {
case 0x6055: /* 3C556 */
- if (bootverbose) printf("ep%d: 3Com 3C556\n", unit);
- epb->mii_trans = 1;
- return (1);
- break; /* NOTREACHED */
+ epb->mii_trans = 1;
+ return (1);
case 0x4057: /* 3C574 */
- if (bootverbose) printf("ep%d: 3Com 3C574\n", unit);
- epb->mii_trans = 1;
- return (1);
- break; /* NOTREACHED */
+ epb->mii_trans = 1;
+ return (1);
case 0x4b57: /* 3C574B */
- if (bootverbose) printf("ep%d: 3Com 3C574B, Megahertz 3CCFE574BT or Fast Etherlink 3C574-TX\n", unit);
- epb->mii_trans = 1;
- return (1);
- break; /* NOTREACHED */
+ epb->mii_trans = 1;
+ return (1);
case 0x9058: /* 3C589 */
- if (bootverbose) printf("ep%d: 3Com Etherlink III 3C589[B/C/D]\n", unit);
- epb->mii_trans = 0;
- return (1);
- break; /* NOTREACHED */
- }
- return (0);
+ epb->mii_trans = 0;
+ return (1);
+ }
+ return (0);
}
static int
-ep_pccard_attach(devi)
- struct pccard_devinfo *devi;
+ep_pccard_attach(device_t dev)
{
- struct isa_device *is = &devi->isahd;
- struct ep_softc *sc = ep_softc[is->id_unit];
- u_short config;
-
- sc->ep_connectors = 0;
- config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
- if (config & IS_BNC) {
- sc->ep_connectors |= BNC;
- }
- if (config & IS_UTP) {
- sc->ep_connectors |= UTP;
- }
- if (!(sc->ep_connectors & 7))
- /* (Apparently) non-fatal */
- if(bootverbose) printf("ep%d: No connectors or MII.\n", is->id_unit);
-
- sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
-
- /* ROM size = 0, ROM base = 0 */
- /* For now, ignore AUTO SELECT feature of 3C589B and later. */
- outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
-
- /* Fake IRQ must be 3 */
- outw(BASE + EP_W0_RESOURCE_CFG, (sc->epb->res_cfg & 0x0fff) | 0x3000);
-
- outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
-
- if (sc->epb->mii_trans) {
- /*
- * turn on the MII transciever
- */
- GO_WINDOW(3);
- outw(BASE + EP_W3_OPTIONS, 0x8040);
- DELAY(1000);
- outw(BASE + EP_W3_OPTIONS, 0xc040);
- outw(BASE + EP_COMMAND, RX_RESET);
- outw(BASE + EP_COMMAND, TX_RESET);
- while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
- DELAY(1000);
- outw(BASE + EP_W3_OPTIONS, 0x8040);
- }
-
- ep_attach(sc);
-
- return 1;
+ struct ep_softc *sc = 0;
+ struct ep_board *epb;
+ struct resource *io = 0;
+ struct resource *irq = 0;
+ int unit = device_get_unit(dev);
+ int i, rid;
+ u_short config;
+
+ rid = 0;
+ io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!io) {
+ device_printf(dev, "No I/O space?!\n");
+ goto bad;
+ }
+
+ epb = &ep_board[ep_boards];
+
+ epb->epb_addr = rman_get_start(io);
+ epb->epb_used = 1;
+
+ if ((sc = ep_alloc(unit, epb)) == 0)
+ goto bad;
+ ep_boards++;
+
+ epb->cmd_off = 0;
+ epb->prod_id = get_e(sc, EEPROM_PROD_ID);
+ if (!ep_pccard_card_attach(epb)) {
+ epb->cmd_off = 2;
+ epb->prod_id = get_e(sc, EEPROM_PROD_ID);
+ if (!ep_pccard_card_attach(epb)) {
+ device_printf(dev,
+ "Probe found ID, attach failed so ignore card!\n");
+ ep_free(sc);
+ return (ENXIO);
+ }
+ }
+
+ sc->ep_connectors = 0;
+ epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
+ for (i = 0; i < 3; i++)
+ sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
+
+ config = inw(rman_get_start(io) + EP_W0_CONFIG_CTRL);
+ if (config & IS_BNC) {
+ sc->ep_connectors |= BNC;
+ }
+ if (config & IS_UTP) {
+ sc->ep_connectors |= UTP;
+ }
+ if (!(sc->ep_connectors & 7))
+ /* (Apparently) non-fatal */
+ if (bootverbose)
+ device_printf(dev, "No connectors or MII.\n");
+
+ sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
+
+ /* ROM size = 0, ROM base = 0 */
+ /* For now, ignore AUTO SELECT feature of 3C589B and later. */
+ outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
+
+ /* Fake IRQ must be 3 */
+ outw(BASE + EP_W0_RESOURCE_CFG, (sc->epb->res_cfg & 0x0fff) | 0x3000);
+
+ outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
+
+ if (sc->epb->mii_trans) {
+ /*
+ * turn on the MII transciever
+ */
+ GO_WINDOW(3);
+ outw(BASE + EP_W3_OPTIONS, 0x8040);
+ DELAY(1000);
+ outw(BASE + EP_W3_OPTIONS, 0xc040);
+ outw(BASE + EP_COMMAND, RX_RESET);
+ outw(BASE + EP_COMMAND, TX_RESET);
+ while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
+ DELAY(1000);
+ outw(BASE + EP_W3_OPTIONS, 0x8040);
+ }
+
+ sc->irq = irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!irq) {
+ device_printf(dev, "No irq?!\n");
+ goto bad;
+ }
+
+ ep_attach(sc);
+ if (bus_setup_intr(dev, irq, INTR_TYPE_NET, ep_intr, sc, &sc->ih)) {
+ device_printf(dev, "cannot setup intr\n");
+ goto bad;
+ }
+ sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
+
+ return 0;
+bad:
+ if (io)
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
+ if (irq)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
+ if (sc)
+ ep_free(sc);
+ return ENXIO;
}
static void
-ep_pccard_unload(devi)
- struct pccard_devinfo *devi;
+ep_pccard_detach(device_t dev)
{
- struct ep_softc *sc = ep_softc[devi->isahd.id_unit];
-
- if (sc->gone) {
- printf("ep%d: already unloaded\n", devi->isahd.id_unit);
- return;
- }
- sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
- sc->gone = 1;
- printf("ep%d: unload\n", devi->isahd.id_unit);
+ struct ep_softc *sc = device_get_softc(dev);
+
+ printf("detach\n");
+
+ if (sc->gone) {
+ device_printf(dev, "already unloaded\n");
+ return;
+ }
+ sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+ if_down(&sc->arpcom.ac_if);
+ sc->gone = 1;
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ device_printf(dev, "unload\n");
}
-/*
- * card_intr - Shared interrupt called from
- * front end of PC-Card handler.
- */
-static int
-ep_pccard_intr(devi)
- struct pccard_devinfo *devi;
-{
- struct ep_softc *sc = ep_softc[devi->isahd.id_unit];
+static device_method_t ep_pccard_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ep_pccard_probe),
+ DEVMETHOD(device_attach, ep_pccard_attach),
+ DEVMETHOD(device_detach, ep_pccard_detach),
- if (sc->gone) {
- return;
- }
+ { 0, 0 }
+};
- ep_intr((void *)sc);
+static driver_t ep_pccard_driver = {
+ "ep",
+ ep_pccard_methods,
+ 1, /* unused */
+};
- return(1);
-}
+extern devclass_t ep_devclass;
+
+DRIVER_MODULE(ep, pccard, ep_pccard_driver, ep_devclass, 0, 0);
diff --git a/sys/dev/ep/if_epvar.h b/sys/dev/ep/if_epvar.h
index 4ad224f..f11c3f7 100644
--- a/sys/dev/ep/if_epvar.h
+++ b/sys/dev/ep/if_epvar.h
@@ -35,6 +35,8 @@ struct ep_softc {
u_char ep_connector; /* Configured connector. */
int stat; /* some flags */
int gone; /* adapter is not present (for PCCARD) */
+ struct resource *irq; /* IRQ resource */
+ void *ih; /* Interrupt handle cookie */
#define F_RX_FIRST 0x1
#define F_PROMISC 0x8
OpenPOWER on IntegriCloud