summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormdodd <mdodd@FreeBSD.org>1999-10-27 06:25:16 +0000
committermdodd <mdodd@FreeBSD.org>1999-10-27 06:25:16 +0000
commit5b7d331b4dc9d7b8fd701fbb5328ef1b7fcd5dfb (patch)
treee829fbdae4384eba77df0f37236cbb52bd7bb73c
parent21f0026c8502ee6b99ec2b4554601965e4ff56c4 (diff)
downloadFreeBSD-src-5b7d331b4dc9d7b8fd701fbb5328ef1b7fcd5dfb.zip
FreeBSD-src-5b7d331b4dc9d7b8fd701fbb5328ef1b7fcd5dfb.tar.gz
HEADS UP! All 3c5x9 users!
- Rip out all the static softc stuff and do softc allocation the right way. - Rewrite most of the ISA code so that it provides a DEVICE_IDENTIFY method to enumerate all non-PnP ISA devices. This has the following consequences: - No 'ep' devices may be hardwired. - All hardwired devices will probably be detected twice. By hardwired I mean: device ep0 at isa? port 0x300 irq 10 - 'ep' devices are ordered by bus, slot, and then MAC address. - Make 3c509B cards work in PnP mode. Yes, they really work. - Convert over to using ifmedia for media selection. No more of this lame 'linkX' stuff. - Consolidate a lot of duplicated code. - Make a stab at not breaking MII based PCCARD devices. I doubt that the PCCARD stuff works any more than it did before my changes but theres hope. My PCCARD hardware should arrive in a week or so. - Retreive the media settings from the card EEPROM rather than guessing. I've got a 3c509-TPO that thinks its got an AUI port and if others can report similar problems I'll write a bit of clever code that will fix this but right now it works correctly on all but 1 card. - Clean up a few things and make some cosmetic changes. - Add myself as the MAINTAINER since nobody else wants to. I'm in the best position to do this as I've got an example of most of the cards: EISA 3c579 bnc/aui MCA 3c529 tp/aui ISA 3c509 tpo ISA-PnP 3c509B combo If someone wants to send me a any cards I don't have I'd appriciate it. Also welcome are 3c59x boards since I'll be folding if_vx and if_ep at some point.
-rw-r--r--sys/dev/ep/if_ep.c534
-rw-r--r--sys/dev/ep/if_ep_eisa.c153
-rw-r--r--sys/dev/ep/if_ep_isa.c492
-rw-r--r--sys/dev/ep/if_ep_mca.c98
-rw-r--r--sys/dev/ep/if_ep_pccard.c142
-rw-r--r--sys/dev/ep/if_epreg.h7
-rw-r--r--sys/dev/ep/if_epvar.h77
7 files changed, 707 insertions, 796 deletions
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index 508dd8a..1b31212 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -56,8 +56,10 @@
* nao@tom-yam.or.jp
*/
-#include "ep.h"
-#if NEP > 0
+/*
+ * MAINTAINER: Matthew N. Dodd <winter@jurai.net>
+ * <mdodd@FreeBSD.org>
+ */
#include <sys/param.h>
#include <sys/kernel.h>
@@ -66,40 +68,58 @@
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
+
+#include <sys/module.h>
#include <sys/bus.h>
-#include <net/ethernet.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
+#include <net/ethernet.h>
+#include <net/bpf.h>
+
#include <netinet/in.h>
#include <netinet/if_ether.h>
-#include <net/bpf.h>
#include <machine/clock.h>
-#include <i386/isa/elink.h>
#include <dev/ep/if_epreg.h>
#include <dev/ep/if_epvar.h>
+#include <i386/isa/elink.h>
/* Exported variables */
-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"};
+#if 0
+static char * ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
+static int if_media2ep_media[] = { 0, 0, 0, UTP, BNC, AUI };
+#endif
+
+static int ep_media2if_media[] =
+ { IFM_10_T, IFM_10_5, IFM_NONE, IFM_10_2, IFM_NONE };
-static int eeprom_rdy __P((struct ep_softc *sc));
-static int epioctl __P((struct ifnet * ifp, u_long, caddr_t));
-static void epinit __P((void *));
-static void epread __P((struct ep_softc *));
-static void epstart __P((struct ifnet *));
-static void epstop __P((struct ep_softc *));
-static void epwatchdog __P((struct ifnet *));
+/* if functions */
+static void ep_if_init __P((void *));
+static int ep_if_ioctl __P((struct ifnet *, u_long, caddr_t));
+static void ep_if_start __P((struct ifnet *));
+static void ep_if_watchdog __P((struct ifnet *));
-#define EP_FTST(sc, f) (sc->stat&(f))
-#define EP_FSET(sc, f) (sc->stat|=(f))
-#define EP_FRST(sc, f) (sc->stat&=~(f))
+/* if_media functions */
+static int ep_ifmedia_upd __P((struct ifnet *));
+static void ep_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
+
+static void ep_get_macaddr __P((struct ep_softc *, u_char *));
+static void epstop __P((struct ep_softc *));
+static void epread __P((struct ep_softc *));
+static int eeprom_rdy __P((struct ep_softc *));
+
+#define EP_FTST(sc, f) (sc->stat & (f))
+#define EP_FSET(sc, f) (sc->stat |= (f))
+#define EP_FRST(sc, f) (sc->stat &= ~(f))
static int
eeprom_rdy(sc)
@@ -127,141 +147,203 @@ get_e(sc, offset)
{
if (!eeprom_rdy(sc))
return (0xffff);
- outw(BASE + EP_W0_EEPROM_COMMAND, (EEPROM_CMD_RD << sc->epb->cmd_off) | offset);
+ outw(BASE + EP_W0_EEPROM_COMMAND, (EEPROM_CMD_RD << sc->epb.cmd_off) | offset);
if (!eeprom_rdy(sc))
return (0xffff);
return (inw(BASE + EP_W0_EEPROM_DATA));
}
-struct ep_softc *
-ep_alloc(unit, epb)
- int unit;
- struct ep_board *epb;
+static void
+ep_get_macaddr(sc, addr)
+ struct ep_softc * sc;
+ u_char * addr;
{
- struct ep_softc *sc;
+ int i;
+ u_int16_t * macaddr = (u_int16_t *)addr;
- if (unit >= NEP) {
- printf("ep: unit number (%d) too high\n", unit);
- return NULL;
- }
-
- /*
- * Allocate a storage area for us
- */
- if (ep_softc[unit]) {
- printf("ep%d: unit number already allocated to another "
- "adaptor\n", unit);
- return NULL;
- }
+ GO_WINDOW(0);
+ for(i = EEPROM_NODE_ADDR_0; i <= EEPROM_NODE_ADDR_2; i++) {
+ macaddr[i] = htons(get_e(sc, i));
+ }
- sc = malloc(sizeof(struct ep_softc), M_DEVBUF, M_NOWAIT);
- if (!sc) {
- printf("ep%d: cannot malloc!\n", unit);
- return NULL;
- }
- bzero(sc, sizeof(struct ep_softc));
- ep_softc[unit] = sc;
- sc->unit = unit;
- sc->ep_io_addr = epb->epb_addr;
- sc->epb = epb;
+ return;
+}
- return(sc);
+int
+ep_alloc(device_t dev)
+{
+ struct ep_softc * sc = device_get_softc(dev);
+ int rid;
+ int error = 0;
+
+ rid = 0;
+ sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!sc->iobase) {
+ device_printf(dev, "No I/O space?!\n");
+ error = ENXIO;
+ goto bad;
+ }
+
+ rid = 0;
+ sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!sc->irq) {
+ device_printf(dev, "No irq?!\n");
+ error = ENXIO;
+ goto bad;
+ }
+
+ sc->dev = dev;
+ sc->unit = device_get_unit(dev);
+ sc->stat = 0; /* 16 bit access */
+
+ sc->ep_io_addr = rman_get_start(sc->iobase);
+
+ sc->ep_btag = rman_get_bustag(sc->iobase);
+ sc->ep_bhandle = rman_get_bushandle(sc->iobase);
+
+ sc->ep_connectors = 0;
+ sc->ep_connector = 0;
+
+ sc->epb.cmd_off = 0;
+ sc->epb.prod_id = get_e(sc, EEPROM_PROD_ID);
+ sc->epb.res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
+
+bad:
+ return (error);
}
void
-ep_free(sc)
- struct ep_softc *sc;
+ep_get_media(sc)
+ struct ep_softc * sc;
{
- ep_softc[sc->unit] = NULL;
- free(sc, M_DEVBUF);
- return;
+ u_int16_t config;
+
+ GO_WINDOW(0);
+ config = inw(BASE + EP_W0_CONFIG_CTRL);
+ if (config & IS_AUI)
+ sc->ep_connectors |= AUI;
+ if (config & IS_BNC)
+ sc->ep_connectors |= BNC;
+ if (config & IS_UTP)
+ sc->ep_connectors |= UTP;
+
+ if (!(sc->ep_connectors & 7)) {
+ if (bootverbose)
+ device_printf(sc->dev, "no connectors!\n");
+ }
+
+ /*
+ * This works for most of the cards so we'll do it here.
+ * The cards that require something different can override
+ * this later on.
+ */
+ sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
+
+ return;
}
+void
+ep_free(device_t dev)
+{
+ struct ep_softc * sc = device_get_softc(dev);
+
+ if (sc->iobase)
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->iobase);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+
+ return;
+}
+
int
ep_attach(sc)
- struct ep_softc *sc;
+ struct ep_softc * sc;
{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- u_short *p;
- int i;
- int attached;
+ struct ifnet * ifp = NULL;
+ struct ifmedia * ifm = NULL;
+ u_short * p;
+ int i;
+ int attached;
- sc->gone = 0;
- attached = (ifp->if_softc != 0);
+ sc->gone = 0;
- printf("ep%d: ", sc->unit);
- /*
- * Current media type
- */
- if (sc->ep_connectors & AUI) {
- printf("aui");
- if (sc->ep_connectors & ~AUI)
- printf("/");
- }
- if (sc->ep_connectors & UTP) {
- printf("utp");
- if (sc->ep_connectors & BNC)
- printf("/");
- }
- if (sc->ep_connectors & BNC) {
- printf("bnc");
- }
+ ep_get_macaddr(sc, (u_char *)&sc->arpcom.ac_enaddr);
- printf("[*%s*]", ep_conn_type[sc->ep_connector]);
+ /*
+ * Setup the station address
+ */
+ p = (u_short *)&sc->arpcom.ac_enaddr;
+ GO_WINDOW(2);
+ for (i = 0; i < 3; i++) {
+ outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
+ }
- /*
- * Setup the station address
- */
- p = (u_short *) & sc->arpcom.ac_enaddr;
- GO_WINDOW(2);
- for (i = 0; i < 3; i++) {
- p[i] = htons(sc->epb->eth_addr[i]);
- outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
- }
- printf(" address %6D\n", sc->arpcom.ac_enaddr, ":");
-
- ifp->if_softc = sc;
- ifp->if_unit = sc->unit;
- ifp->if_name = "ep";
- ifp->if_mtu = ETHERMTU;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_output = ether_output;
- ifp->if_start = epstart;
- ifp->if_ioctl = epioctl;
- ifp->if_watchdog = epwatchdog;
- ifp->if_init = epinit;
-
- if (!attached) {
- if_attach(ifp);
- ether_ifattach(ifp);
- }
+ device_printf(sc->dev, "Ethernet address %6D\n",
+ sc->arpcom.ac_enaddr, ":");
+
+ ifp = &sc->arpcom.ac_if;
+ attached = (ifp->if_softc != 0);
+
+ ifp->if_softc = sc;
+ ifp->if_unit = sc->unit;
+ ifp->if_name = "ep";
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_output = ether_output;
+ ifp->if_start = ep_if_start;
+ ifp->if_ioctl = ep_if_ioctl;
+ ifp->if_watchdog = ep_if_watchdog;
+ ifp->if_init = ep_if_init;
+ ifp->if_snd.ifq_maxlen = 8;
+
+ if (!sc->epb.mii_trans) {
+ ifmedia_init(&sc->ifmedia, 0, ep_ifmedia_upd, ep_ifmedia_sts);
+
+ if (sc->ep_connectors & AUI)
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL);
+ if (sc->ep_connectors & UTP)
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
+ if (sc->ep_connectors & BNC)
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL);
+ if (!sc->ep_connectors)
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_NONE, 0, NULL);
+
+ ifmedia_set(&sc->ifmedia, IFM_ETHER|ep_media2if_media[sc->ep_connector]);
+
+ ifm = &sc->ifmedia;
+ ifm->ifm_media = ifm->ifm_cur->ifm_media;
+ ep_ifmedia_upd(ifp);
+ }
+
+ if (!attached) {
+ if_attach(ifp);
+ ether_ifattach(ifp);
+ bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
+ }
#ifdef EP_LOCAL_STATS
- sc->rx_no_first = sc->rx_no_mbuf =
- sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
- sc->tx_underrun = 0;
+ sc->rx_no_first = sc->rx_no_mbuf = sc->rx_bpf_disc =
+ sc->rx_overrunf = sc->rx_overrunl = sc->tx_underrun = 0;
#endif
- EP_FSET(sc, F_RX_FIRST);
- sc->top = sc->mcur = 0;
+ EP_FSET(sc, F_RX_FIRST);
+ sc->top = sc->mcur = 0;
- if (!attached) {
- bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
- }
- return 0;
+ return 0;
}
-
/*
* The order in here seems important. Otherwise we may not receive
* interrupts. ?!
*/
static void
-epinit(xsc)
+ep_if_init(xsc)
void *xsc;
{
struct ep_softc *sc = xsc;
register struct ifnet *ifp = &sc->arpcom.ac_if;
- int s, i, j;
+ int s, i;
if (sc->gone)
return;
@@ -315,59 +397,7 @@ epinit(xsc)
outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
FIL_GROUP | FIL_BRDCST);
- /*
- * S.B.
- *
- * Now behavior was slightly changed:
- *
- * if any of flags link[0-2] is used and its connector is
- * physically present the following connectors are used:
- *
- * link0 - AUI * highest precedence
- * link1 - BNC
- * link2 - UTP * lowest precedence
- *
- * If none of them is specified then
- * connector specified in the EEPROM is used
- * (if present on card or AUI if not).
- *
- */
-
- /* Set the xcvr. */
- if (ifp->if_flags & IFF_LINK0 && sc->ep_connectors & AUI) {
- i = ACF_CONNECTOR_AUI;
- } else if (ifp->if_flags & IFF_LINK1 && sc->ep_connectors & BNC) {
- i = ACF_CONNECTOR_BNC;
- } else if (ifp->if_flags & IFF_LINK2 && sc->ep_connectors & UTP) {
- i = ACF_CONNECTOR_UTP;
- } else {
- i = sc->ep_connector;
- }
- GO_WINDOW(0);
- j = inw(BASE + EP_W0_ADDRESS_CFG) & 0x3fff;
- outw(BASE + EP_W0_ADDRESS_CFG, j | (i << ACF_CONNECTOR_BITS));
-
- switch(i) {
- case ACF_CONNECTOR_UTP:
- if (sc->ep_connectors & UTP) {
- GO_WINDOW(4);
- outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
- }
- break;
- case ACF_CONNECTOR_BNC:
- if (sc->ep_connectors & BNC) {
- outw(BASE + EP_COMMAND, START_TRANSCEIVER);
- DELAY(DELAY_MULTIPLE * 1000);
- }
- break;
- case ACF_CONNECTOR_AUI:
- /* nothing to do */
- break;
- default:
- printf("ep%d: strange connector type in EEPROM: assuming AUI\n",
- sc->unit);
- break;
- }
+ ep_ifmedia_upd(ifp);
outw(BASE + EP_COMMAND, RX_ENABLE);
outw(BASE + EP_COMMAND, TX_ENABLE);
@@ -395,7 +425,7 @@ epinit(xsc)
*/
GO_WINDOW(1);
- epstart(ifp);
+ ep_if_start(ifp);
splx(s);
}
@@ -403,7 +433,7 @@ epinit(xsc)
static const char padmap[] = {0, 3, 2, 1};
static void
-epstart(ifp)
+ep_if_start(ifp)
struct ifnet *ifp;
{
register struct ep_softc *sc = ifp->if_softc;
@@ -543,7 +573,7 @@ rescan:
ifp->if_flags &= ~IFF_OACTIVE;
GO_WINDOW(1);
inw(BASE + EP_W1_FREE_TX);
- epstart(ifp);
+ ep_if_start(ifp);
}
if (status & S_CARD_FAILURE) {
ifp->if_timer = 0;
@@ -566,7 +596,7 @@ rescan:
#endif
#endif
- epinit(sc);
+ ep_if_init(sc);
splx(x);
return;
}
@@ -606,7 +636,7 @@ rescan:
ifp->if_flags &= ~IFF_OACTIVE;
GO_WINDOW(1);
inw(BASE + EP_W1_FREE_TX);
- epstart(ifp);
+ ep_if_start(ifp);
} /* end TX_COMPLETE */
}
@@ -784,69 +814,125 @@ out:
outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
}
-/*
- * Look familiar?
- */
-static int
-epioctl(ifp, cmd, data)
- register struct ifnet *ifp;
- u_long cmd;
- caddr_t data;
+static int
+ep_ifmedia_upd(ifp)
+ struct ifnet * ifp;
{
- struct ep_softc *sc = ifp->if_softc;
- int s, error = 0;
+ struct ep_softc * sc = ifp->if_softc;
+ int i = 0, j;
+
+ GO_WINDOW(0);
+ outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
+ GO_WINDOW(4);
+ outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP);
+ GO_WINDOW(0);
+
+ switch (IFM_SUBTYPE(sc->ifmedia.ifm_media)) {
+ case IFM_10_T:
+ if (sc->ep_connectors & UTP) {
+ i = ACF_CONNECTOR_UTP;
+ GO_WINDOW(4);
+ outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
+ }
+ break;
+ case IFM_10_2:
+ if (sc->ep_connectors & BNC) {
+ i = ACF_CONNECTOR_BNC;
+ outw(BASE + EP_COMMAND, START_TRANSCEIVER);
+ DELAY(DELAY_MULTIPLE * 1000);
+ }
+ break;
+ case IFM_10_5:
+ if (sc->ep_connectors & AUI)
+ i = ACF_CONNECTOR_AUI;
+ break;
+ default:
+ i = sc->ep_connector;
+ device_printf(sc->dev,
+ "strange connector type in EEPROM: assuming AUI\n");
+ }
- s = splimp();
+ GO_WINDOW(0);
+ j = inw(BASE + EP_W0_ADDRESS_CFG) & 0x3fff;
+ outw(BASE + EP_W0_ADDRESS_CFG, j | (i << ACF_CONNECTOR_BITS));
- switch (cmd) {
- case SIOCSIFADDR:
- case SIOCGIFADDR:
- case SIOCSIFMTU:
- error = ether_ioctl(ifp, cmd, data);
- break;
+ return (0);
+}
- case SIOCSIFFLAGS:
+static void
+ep_ifmedia_sts(ifp, ifmr)
+ struct ifnet * ifp;
+ struct ifmediareq * ifmr;
+{
+ struct ep_softc * sc = ifp->if_softc;
- if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
- ifp->if_flags &= ~IFF_RUNNING;
- epstop(sc);
- break;
- } else {
- /* reinitialize card on any parameter change */
- epinit(sc);
- break;
- }
+ ifmr->ifm_active = sc->ifmedia.ifm_media;
+
+ return;
+}
- /* NOTREACHED */
+static int
+ep_if_ioctl(ifp, cmd, data)
+ struct ifnet * ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ep_softc * sc = ifp->if_softc;
+ struct ifreq * ifr = (struct ifreq *)data;
+ int s, error = 0;
+
+ s = splimp();
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCGIFADDR:
+ case SIOCSIFMTU:
+ error = ether_ioctl(ifp, cmd, data);
break;
+
+ case SIOCSIFFLAGS:
+ if (((ifp->if_flags & IFF_UP) == 0) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ ifp->if_flags &= ~IFF_RUNNING;
+ epstop(sc);
+ } else {
+ /* reinitialize card on any parameter change */
+ ep_if_init(sc);
+ }
+ break;
#ifdef notdef
- case SIOCGHWADDR:
- bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
- sizeof(sc->sc_addr));
- break;
+ case SIOCGHWADDR:
+ bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
+ sizeof(sc->sc_addr));
+ break;
#endif
case SIOCADDMULTI:
case SIOCDELMULTI:
- /*
- * The Etherlink III has no programmable multicast
- * filter. We always initialize the card to be
- * promiscuous to multicast, since we're always a
- * member of the ALL-SYSTEMS group, so there's no
- * need to process SIOC*MULTI requests.
- */
- error = 0;
- break;
- default:
+ /*
+ * The Etherlink III has no programmable multicast
+ * filter. We always initialize the card to be
+ * promiscuous to multicast, since we're always a
+ * member of the ALL-SYSTEMS group, so there's no
+ * need to process SIOC*MULTI requests.
+ */
+ error = 0;
+ break;
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
+ break;
+ default:
error = EINVAL;
- }
+ break;
+ }
- splx(s);
+ (void)splx(s);
- return (error);
+ return (error);
}
static void
-epwatchdog(ifp)
+ep_if_watchdog(ifp)
struct ifnet *ifp;
{
struct ep_softc *sc = ifp->if_softc;
@@ -863,7 +949,7 @@ epwatchdog(ifp)
}
ifp->if_flags &= ~IFF_OACTIVE;
- epstart(ifp);
+ ep_if_start(ifp);
ep_intr(ifp->if_softc);
}
@@ -888,5 +974,3 @@ epstop(sc)
outw(BASE + EP_COMMAND, SET_INTR_MASK);
outw(BASE + EP_COMMAND, SET_RX_FILTER);
}
-
-#endif /* NEP > 0 */
diff --git a/sys/dev/ep/if_ep_eisa.c b/sys/dev/ep/if_ep_eisa.c
index 42ae2b6..ee1a50f 100644
--- a/sys/dev/ep/if_ep_eisa.c
+++ b/sys/dev/ep/if_ep_eisa.c
@@ -22,25 +22,23 @@
* $FreeBSD$
*/
-#include "eisa.h"
-#if NEISA > 0
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+
#include <sys/module.h>
#include <sys/bus.h>
-#include <machine/clock.h>
#include <machine/bus.h>
#include <machine/resource.h>
-#include <sys/rman.h>
+#include <sys/rman.h>
#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
+#include <machine/clock.h>
#include <i386/eisa/eisaconf.h>
@@ -111,6 +109,7 @@ ep_eisa_probe(device_t dev)
u_short conf;
u_long port;
int irq;
+ int int_trig;
desc = ep_match(eisa_get_id(dev));
if (!desc)
@@ -162,7 +161,18 @@ ep_eisa_probe(device_t dev)
eisa_get_slot(dev));
return ENXIO;
}
- eisa_add_intr(dev, irq, EISA_TRIGGER_EDGE);
+
+ switch(eisa_get_id(dev)) {
+ case EISA_DEVICE_ID_3COM_3C579_BNC:
+ case EISA_DEVICE_ID_3COM_3C579_TP:
+ int_trig = EISA_TRIGGER_LEVEL;
+ break;
+ default:
+ int_trig = EISA_TRIGGER_EDGE;
+ break;
+ }
+
+ eisa_add_intr(dev, irq, int_trig);
return 0;
}
@@ -170,124 +180,71 @@ ep_eisa_probe(device_t dev)
static int
ep_eisa_attach(device_t dev)
{
- struct ep_softc *sc;
- struct ep_board *epb;
- struct resource *io = 0;
- struct resource *eisa_io = 0;
- struct resource *irq = 0;
- int unit = device_get_unit(dev);
- u_char level_intr;
- int i, rid, shared;
- void *ih;
-
- /*
- * The addresses are sorted in increasing order
- * so we know the port to pass to the core ep
- * driver comes first.
- */
- 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;
- }
+ struct ep_softc * sc = device_get_softc(dev);
+ struct resource * eisa_io = NULL;
+ u_int32_t eisa_iobase;
+ int irq;
+ int error = 0;
+ int rid;
rid = 1;
eisa_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
0, ~0, 1, RF_ACTIVE);
if (!eisa_io) {
device_printf(dev, "No I/O space?!\n");
+ error = ENXIO;
goto bad;
}
+ eisa_iobase = rman_get_start(eisa_io);
- epb = &ep_board[ep_boards];
-
- epb->epb_addr = rman_get_start(io);
- epb->epb_used = 1;
+ /* Reset and Enable the card */
+ outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
+ DELAY(1000); /* we must wait at least 1 ms */
+ outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
+ /* Now the registers are availible through the lower ioport */
- if(!(sc = ep_alloc(unit, epb)))
+ if ((error = ep_alloc(dev))) {
+ device_printf(dev, "ep_alloc() failed! (%d)\n", error);
goto bad;
+ }
- ep_boards++;
-
- sc->stat = 0;
- level_intr = FALSE;
switch(eisa_get_id(dev)) {
- case EISA_DEVICE_ID_3COM_3C509_TP:
- sc->ep_connectors = UTP|AUI;
- break;
- case EISA_DEVICE_ID_3COM_3C509_BNC:
- sc->ep_connectors = BNC|AUI;
- break;
- case EISA_DEVICE_ID_3COM_3C579_TP:
- sc->ep_connectors = UTP|AUI;
- sc->stat = F_ACCESS_32_BITS;
- level_intr = TRUE;
- break;
case EISA_DEVICE_ID_3COM_3C579_BNC:
- sc->ep_connectors = BNC|AUI;
+ case EISA_DEVICE_ID_3COM_3C579_TP:
sc->stat = F_ACCESS_32_BITS;
- level_intr = TRUE;
- break;
- case EISA_DEVICE_ID_3COM_3C509_COMBO:
- sc->ep_connectors = UTP|BNC|AUI;
- break;
- case EISA_DEVICE_ID_3COM_3C509_TPO:
- sc->ep_connectors = UTP;
break;
default:
break;
- }
- /*
- * Set the eisa config selected media type
- */
- sc->ep_connector = inw(rman_get_start(eisa_io) + EISA_BPROM_MEDIA_CONF)
- >> ACF_CONNECTOR_BITS;
-
- shared = level_intr ? RF_SHAREABLE : 0;
- rid = 0;
- irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
- 0, ~0, 1, shared | RF_ACTIVE);
- if (!irq) {
- device_printf(dev, "No irq?!\n");
- goto bad;
}
- /* Reset and Enable the card */
- outb(rman_get_start(eisa_io) + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
- DELAY(1000); /* we must wait at least 1 ms */
- outb(rman_get_start(eisa_io) + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
+ ep_get_media(sc);
- /* Now the registers are availible through the lower ioport */
+ irq = rman_get_start(sc->irq);
+ if (irq == 9)
+ irq = 2;
- /*
- * Retrieve our ethernet address
- */
GO_WINDOW(0);
- for(i = 0; i < 3; i++)
- sc->epb->eth_addr[i] = get_e(sc, i);
+ SET_IRQ(BASE, irq);
- /* Even we get irq number from board, we should tell him..
- Otherwise we never get a H/W interrupt anymore...*/
- if ( rman_get_start(irq) == 9 )
- rman_get_start(irq) = 2;
- SET_IRQ(rman_get_start(eisa_io), rman_get_start(irq));
-
- ep_attach(sc);
+ if ((error = ep_attach(sc))) {
+ device_printf(dev, "ep_attach() failed! (%d)\n", error);
+ goto bad;
+ }
- bus_setup_intr(dev, irq, INTR_TYPE_NET, ep_intr, sc, &ih);
+ if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ep_intr,
+ sc, &sc->ep_intrhand))) {
+ device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
+ goto bad;
+ }
- return 0;
+ return (0);
bad:
- if (io)
- bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
if (eisa_io)
bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
- if (irq)
- bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
- return -1;
+
+ ep_free(dev);
+ return (error);
}
static device_method_t ep_eisa_methods[] = {
@@ -301,11 +258,9 @@ static device_method_t ep_eisa_methods[] = {
static driver_t ep_eisa_driver = {
"ep",
ep_eisa_methods,
- 1, /* unused */
+ sizeof(struct ep_softc),
};
extern devclass_t ep_devclass;
DRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0);
-
-#endif /* NEISA > 0 */
diff --git a/sys/dev/ep/if_ep_isa.c b/sys/dev/ep/if_ep_isa.c
index b36ff57..537f5d2 100644
--- a/sys/dev/ep/if_ep_isa.c
+++ b/sys/dev/ep/if_ep_isa.c
@@ -31,262 +31,63 @@
*/
#include <sys/param.h>
-#include <sys/kernel.h>
#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
+#include <sys/kernel.h>
#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <net/ethernet.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
#include <machine/clock.h>
-#include <i386/isa/isa_device.h>
+#include <isa/isavar.h>
+#include <isa/pnpvar.h>
#include <dev/ep/if_epreg.h>
#include <dev/ep/if_epvar.h>
#include <i386/isa/elink.h>
-static int ep_isa_probe (struct isa_device *);
-static int ep_isa_attach (struct isa_device *);
-static struct ep_board *ep_look_for_board_at (struct isa_device *is);
-static int get_eeprom_data (int, int);
-static void epintr (int);
-
-#if 0
-static int send_ID_sequence (int);
-#endif
+static int get_eeprom_data (int, int);
-static int ep_current_tag = EP_LAST_TAG + 1;
+static void ep_isa_identify (driver_t *, device_t);
+static int ep_isa_probe (device_t);
+static int ep_isa_attach (device_t);
-struct isa_driver epdriver = {
- ep_isa_probe,
- ep_isa_attach,
- "ep",
- 0
+struct isa_ident {
+ u_int32_t id;
+ char * name;
+};
+const char * ep_isa_match_id (u_int32_t, struct isa_ident *);
+
+#define ISA_ID_3C509_TP 0x506d5090
+#define ISA_ID_3C509_BNC 0x506d5091
+#define ISA_ID_3C509_COMBO 0x506d5094
+#define ISA_ID_3C509_TPO 0x506d5095
+
+static struct isa_ident ep_isa_devs[] = {
+ { ISA_ID_3C509_TP, "3Com EtherLink III (3c509-TP)" },
+ { ISA_ID_3C509_BNC, "3Com EtherLink III (3c509-BNC)" },
+ { ISA_ID_3C509_COMBO, "3Com EtherLink III (3c509-Combo)" },
+ { ISA_ID_3C509_TPO, "3Com EtherLink III (3c509-TPO)" },
+ { 0, NULL },
};
-int
-ep_isa_probe(is)
- struct isa_device *is;
-{
- struct ep_softc *sc;
- struct ep_board *epb;
- u_short k;
-
- if ((epb = ep_look_for_board_at(is)) == 0)
- return (0);
-
- /*
- * Allocate a storage area for us
- */
- sc = ep_alloc(ep_unit, epb);
- if (!sc)
- return (0);
-
- is->id_unit = ep_unit++;
-
- /*
- * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
- * 0x9[0-f]50 (IBM-PC)
- * 0x9[0-f]5[0-f] (PC-98)
- */
- GO_WINDOW(0);
- k = sc->epb->prod_id;
-#ifdef PC98
- if ((k & 0xf0f0) != (PROD_ID & 0xf0f0)) {
-#else
- if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) {
-#endif
- printf("ep_isa_probe: ignoring model %04x\n", k);
- ep_free(sc);
- return (0);
- }
-
- k = sc->epb->res_cfg;
-
- k >>= 12;
-
- /* Now we have two cases again:
- *
- * 1. Device was configured with 'irq?'
- * In this case we use irq read from the board
- *
- * 2. Device was configured with 'irq xxx'
- * In this case we set up the board to use specified interrupt
- *
- */
-
- if (is->id_irq == 0) { /* irq? */
- is->id_irq = 1 << ((k == 2) ? 9 : k);
- }
-
- sc->stat = 0; /* 16 bit access */
-
- /* By now, the adapter is already activated */
-
- return (EP_IOSIZE); /* 16 bytes of I/O space used. */
-}
-
-static int
-ep_isa_attach(is)
- struct isa_device *is;
-{
- struct ep_softc *sc = ep_softc[is->id_unit];
- u_short config;
- int irq;
-
- is->id_ointr = epintr;
- sc->ep_connectors = 0;
- config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
- if (config & IS_AUI) {
- sc->ep_connectors |= AUI;
- }
- if (config & IS_BNC) {
- sc->ep_connectors |= BNC;
- }
- if (config & IS_UTP) {
- sc->ep_connectors |= UTP;
- }
- if (!(sc->ep_connectors & 7))
- printf("no connectors!");
- sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
- /*
- * Write IRQ value to board
- */
-
- irq = ffs(is->id_irq) - 1;
- if (irq == -1) {
- printf(" invalid irq... cannot attach\n");
- return 0;
- }
-
- GO_WINDOW(0);
- SET_IRQ(BASE, irq);
-
- ep_attach(sc);
- return 1;
-}
-
-static struct ep_board *
-ep_look_for_board_at(is)
- struct isa_device *is;
-{
- int data, i, j, id_port = ELINK_ID_PORT;
- int count = 0;
-
- if (ep_current_tag == (EP_LAST_TAG + 1)) {
- /* Come here just one time */
-
- ep_current_tag--;
-
- /* Look for the ISA boards. Init and leave them actived */
- outb(id_port, 0);
- outb(id_port, 0);
-
- elink_idseq(0xCF);
-
- elink_reset();
- DELAY(DELAY_MULTIPLE * 10000);
- for (i = 0; i < EP_MAX_BOARDS; i++) {
- outb(id_port, 0);
- outb(id_port, 0);
- elink_idseq(0xCF);
-
- data = get_eeprom_data(id_port, EEPROM_MFG_ID);
- if (data != MFG_ID)
- break;
-
- /* resolve contention using the Ethernet address */
-
- for (j = 0; j < 3; j++)
- get_eeprom_data(id_port, j);
-
- /* and save this address for later use */
-
- for (j = 0; j < 3; j++)
- ep_board[ep_boards].eth_addr[j] = get_eeprom_data(id_port, j);
-
- ep_board[ep_boards].res_cfg =
- get_eeprom_data(id_port, EEPROM_RESOURCE_CFG);
-
- ep_board[ep_boards].prod_id =
- get_eeprom_data(id_port, EEPROM_PROD_ID);
-
- ep_board[ep_boards].epb_used = 0;
-#ifdef PC98
- ep_board[ep_boards].epb_addr =
- (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) *
- 0x100 + 0x40d0;
-#else
- ep_board[ep_boards].epb_addr =
- (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) *
- 0x10 + 0x200;
-
- if (ep_board[ep_boards].epb_addr > 0x3E0)
- /* Board in EISA configuration mode */
- continue;
-#endif /* PC98 */
-
- outb(id_port, ep_current_tag); /* tags board */
- outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
- ep_boards++;
- count++;
- ep_current_tag--;
- }
-
- ep_board[ep_boards].epb_addr = 0;
- if (count) {
- printf("%d 3C5x9 board(s) on ISA found at", count);
- for (j = 0; ep_board[j].epb_addr; j++)
- if (ep_board[j].epb_addr <= 0x3E0)
- printf(" 0x%x", ep_board[j].epb_addr);
- printf("\n");
- }
- }
-
- /* we have two cases:
- *
- * 1. Device was configured with 'port ?'
- * In this case we search for the first unused card in list
- *
- * 2. Device was configured with 'port xxx'
- * In this case we search for the unused card with that address
- *
- */
-
- if (IS_BASE == -1) { /* port? */
- for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++)
- ;
- if (ep_board[i].epb_addr == 0)
- return 0;
-
- IS_BASE = ep_board[i].epb_addr;
- ep_board[i].epb_used = 1;
-
- return &ep_board[i];
- } else {
- for (i = 0;
- ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE;
- i++)
- ;
-
- if (ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE)
- return 0;
-
- if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) {
- printf("ep%d: 3c5x9 at 0x%x in PnP mode. Disable PnP mode!\n",
- is->id_unit, IS_BASE);
- }
- ep_board[i].epb_used = 1;
-
- return &ep_board[i];
- }
-}
+static struct isa_pnp_id ep_ids[] = {
+ { 0x90506d50, NULL }, /* TCM5090 */
+ { 0x91506d50, NULL }, /* TCM5091 */
+ { 0x94506d50, NULL }, /* TCM5094 */
+ { 0x95506d50, NULL }, /* TCM5095 */
+ { 0xf780d041, NULL }, /* PNP80f7 */
+ { 0, NULL },
+};
/*
* We get eeprom data from the id_port given an offset into the eeprom.
@@ -309,36 +110,207 @@ get_eeprom_data(id_port, offset)
int i, data = 0;
outb(id_port, 0x80 + offset);
for (i = 0; i < 16; i++) {
- DELAY(BIT_DELAY_MULTIPLE * 1000);
- data = (data << 1) | (inw(id_port) & 1);
+ DELAY(BIT_DELAY_MULTIPLE * 1000);
+ data = (data << 1) | (inw(id_port) & 1);
}
return (data);
}
-void
-epintr(unit)
- int unit;
+const char *
+ep_isa_match_id (id, isa_devs)
+ u_int32_t id;
+ struct isa_ident * isa_devs;
+{
+ struct isa_ident * i = isa_devs;
+ while(i->name != NULL) {
+ if (id == i->id)
+ return (i->name);
+ i++;
+ }
+ return (NULL);
+}
+
+static void
+ep_isa_identify (driver_t *driver, device_t parent)
{
- register struct ep_softc *sc = ep_softc[unit];
+ int tag = EP_LAST_TAG;
+ int found = 0;
+ int i;
+ int j;
+ const char * desc;
+ u_int32_t data;
+ u_int32_t irq;
+ u_int32_t ioport;
+ u_int32_t isa_id;
+ device_t child;
+
+ outb(ELINK_ID_PORT, 0);
+ outb(ELINK_ID_PORT, 0);
+
+ elink_idseq(ELINK_509_POLY);
+ elink_reset();
+
+ DELAY(DELAY_MULTIPLE * 10000);
+
+ for (i = 0; i < EP_MAX_BOARDS; i++) {
+
+ outb(ELINK_ID_PORT, 0);
+ outb(ELINK_ID_PORT, 0);
+ elink_idseq(0xCF);
+
+ /* For the first probe, clear all
+ * board's tag registers.
+ * Otherwise kill off already-found
+ * boards. -- linux 3c509.c
+ */
+ if (i == 0) {
+ outb(ELINK_ID_PORT, 0xd0);
+ } else {
+ outb(ELINK_ID_PORT, 0xd8);
+ }
+
+ /*
+ * Construct an 'isa_id' in 'EISA'
+ * format.
+ */
+ data = get_eeprom_data(ELINK_ID_PORT, EEPROM_MFG_ID);
+ isa_id = (htons(data) << 16);
+ data = get_eeprom_data(ELINK_ID_PORT, EEPROM_PROD_ID);
+ isa_id |= htons(data);
+
+ /* Find known ISA boards */
+ desc = ep_isa_match_id(isa_id, ep_isa_devs);
+ if (!desc) {
+ if (bootverbose) {
+ device_printf(parent, "if_ep: unknown ID 0x%08x\n",
+ isa_id);
+ }
+ break;
+ }
+
+ /* resolve contention using the Ethernet address */
+ for (j = 0; j < 3; j++) {
+ get_eeprom_data(ELINK_ID_PORT, j);
+ }
+
+ /* Retreive IRQ */
+ data = get_eeprom_data(ELINK_ID_PORT, EEPROM_RESOURCE_CFG);
+ irq = (data >> 12);
+
+ /* Retreive IOPORT */
+ data = get_eeprom_data(ELINK_ID_PORT, EEPROM_ADDR_CFG);
+#ifdef PC98
+ ioport = ((data * 0x100) + 0x40d0);
+#else
+ ioport = ((data << 4) + 0x200);
+#endif
+
+ /* Set the adaptor tag so that the next card can be found. */
+ outb(ELINK_ID_PORT, tag--);
+
+ /* Activate the adaptor at the EEPROM location. */
+ outb(ELINK_ID_PORT, ((ioport >> 4) | 0xe0));
- ep_intr(sc);
+ /* Test for an adapter in PnP mode */
+ data = inw(ioport + EP_W0_EEPROM_COMMAND);
+ if (data & EEPROM_TST_MODE) {
+ device_printf(parent, "if_ep: Adapter at 0x%03x in PnP mode!\n",
+ ioport);
+ continue;
+ }
- return;
+ child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ep", -1);
+ device_set_desc_copy(child, desc);
+ device_set_driver(child, driver);
+ bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
+ bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, EP_IOSIZE);
+
+ if (bootverbose) {
+ device_printf(parent, "if_ep: <%s> at port 0x%03x-0x%03x irq %d\n",
+ desc, ioport, ioport + EP_IOSIZE, irq);
+ }
+
+ found++;
+ }
+
+ return;
}
-#if 0
static int
-send_ID_sequence(port)
- int port;
+ep_isa_probe (device_t dev)
{
- int cx, al;
+ int error = 0;
- for (al = 0xff, cx = 0; cx < 255; cx++) {
- outb(port, al);
- al <<= 1;
- if (al & 0x100)
- al ^= 0xcf;
- }
- return (1);
+ /* Check isapnp ids */
+ error = ISA_PNP_PROBE(device_get_parent(dev), dev, ep_ids);
+
+ /* If the card had a PnP ID that didn't match any we know about */
+ if (error == ENXIO) {
+ return (error);
+ }
+
+ /* If we had some other problem. */
+ if (!(error == 0 || error == ENOENT)) {
+ return (error);
+ }
+
+ /* If we have the resources we need then we're good to go. */
+ if ((bus_get_resource_start(dev, SYS_RES_IOPORT, 0) != 0) &&
+ (bus_get_resource_start(dev, SYS_RES_IRQ, 0) != 0)) {
+ return (0);
+ }
+
+ return (ENXIO);
}
-#endif
+
+static int
+ep_isa_attach (device_t dev)
+{
+ struct ep_softc * sc = device_get_softc(dev);
+ int error = 0;
+
+ if ((error = ep_alloc(dev))) {
+ device_printf(dev, "ep_alloc() failed! (%d)\n", error);
+ goto bad;
+ }
+
+ ep_get_media(sc);
+
+ GO_WINDOW(0);
+ SET_IRQ(BASE, rman_get_start(sc->irq));
+
+ if ((error = ep_attach(sc))) {
+ device_printf(dev, "ep_attach() failed! (%d)\n", error);
+ goto bad;
+ }
+
+ if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ep_intr,
+ sc, &sc->ep_intrhand))) {
+ device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
+ goto bad;
+ }
+
+ return (0);
+bad:
+ ep_free(dev);
+ return (error);
+}
+
+static device_method_t ep_isa_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, ep_isa_identify),
+ DEVMETHOD(device_probe, ep_isa_probe),
+ DEVMETHOD(device_attach, ep_isa_attach),
+
+ { 0, 0 }
+};
+
+static driver_t ep_isa_driver = {
+ "ep",
+ ep_isa_methods,
+ sizeof(struct ep_softc),
+};
+
+extern devclass_t ep_devclass;
+
+DRIVER_MODULE(ep, isa, ep_isa_driver, ep_devclass, 0, 0);
diff --git a/sys/dev/ep/if_ep_mca.c b/sys/dev/ep/if_ep_mca.c
index 6e0b9e3..778b42b 100644
--- a/sys/dev/ep/if_ep_mca.c
+++ b/sys/dev/ep/if_ep_mca.c
@@ -26,31 +26,21 @@
* $FreeBSD$
*/
-#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <machine/clock.h>
-#include <machine/cpufunc.h>
-#include <machine/md_var.h>
-
#include <sys/module.h>
#include <sys/bus.h>
+
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
-#include <net/if_mib.h>
-
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
#include <dev/mca/mca_busreg.h>
#include <dev/mca/mca_busvar.h>
@@ -85,7 +75,7 @@ static struct mca_ident ep_mca_devs[] = {
#define EP_MCA_IOPORT_POS MCA_ADP_POS(MCA_POS2)
#define EP_MCA_IOPORT_MASK 0xfc
-#define EP_MCA_IOPORT_SIZE 0x0f
+#define EP_MCA_IOPORT_SIZE EP_IOSIZE
#define EP_MCA_IOPORT(pos) ((((u_int32_t)pos & EP_MCA_IOPORT_MASK) \
| 0x02) << 8)
@@ -125,79 +115,35 @@ ep_mca_probe (device_t dev)
static int
ep_mca_attach (device_t dev)
{
- struct ep_softc * sc;
- struct ep_board * epb;
- struct resource * io = 0;
- struct resource * irq = 0;
- u_int8_t pos;
- int unit = device_get_unit(dev);
- int i, rid;
- void * ih;
-
- 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;
- }
+ struct ep_softc * sc = device_get_softc(dev);
+ int error = 0;
- rid = 0;
- irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
- 0, ~0, 1, RF_ACTIVE);
- if (!irq) {
- device_printf(dev, "No irq?!\n");
+ if ((error = ep_alloc(dev))) {
+ device_printf(dev, "ep_alloc() failed! (%d)\n", error);
goto bad;
}
-
- epb = &ep_board[ep_boards];
-
- epb->epb_addr = rman_get_start(io);
- epb->epb_used = 1;
-
- if(!(sc = ep_alloc(unit, epb)))
- goto bad;
-
- ep_boards++;
-
sc->stat = F_ACCESS_32_BITS;
- switch(mca_get_id(dev)) {
- case EP_MCA_627C:
- sc->ep_connectors = BNC|AUI;
- break;
- case EP_MCA_627D:
- sc->ep_connectors = UTP|AUI;
- break;
- default:
- break;
- }
- pos = mca_pos_read(dev, EP_MCA_MEDIA_POS);
- sc->ep_connector = EP_MCA_MEDIA(pos);
-
- /*
- * Retrieve our ethernet address
- */
- GO_WINDOW(0);
- for(i = 0; i < 3; i++)
- sc->epb->eth_addr[i] = get_e(sc, i);
+ ep_get_media(sc);
GO_WINDOW(0);
- SET_IRQ(BASE, rman_get_start(irq));
+ SET_IRQ(BASE, rman_get_start(sc->irq));
- ep_attach(sc);
+ if ((error = ep_attach(sc))) {
+ device_printf(dev, "ep_attach() failed! (%d)\n", error);
+ goto bad;
+ }
- bus_setup_intr(dev, irq, INTR_TYPE_NET, ep_intr, sc, &ih);
+ if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ep_intr,
+ sc, &sc->ep_intrhand))) {
+ device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
+ goto bad;
+ }
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);
-
- return (-1);
+ ep_free(dev);
+ return (error);
}
static device_method_t ep_mca_methods[] = {
@@ -211,7 +157,7 @@ static device_method_t ep_mca_methods[] = {
static driver_t ep_mca_driver = {
"ep",
ep_mca_methods,
- 1, /* unusep */
+ sizeof(struct ep_softc),
};
static devclass_t ep_devclass;
diff --git a/sys/dev/ep/if_ep_pccard.c b/sys/dev/ep/if_ep_pccard.c
index 7b373e1..84a438c 100644
--- a/sys/dev/ep/if_ep_pccard.c
+++ b/sys/dev/ep/if_ep_pccard.c
@@ -37,21 +37,20 @@
*/
#include <sys/param.h>
-#include <sys/kernel.h>
#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
+#include <sys/kernel.h>
#include <sys/socket.h>
-#include <sys/sockio.h>
+
+#include <sys/module.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>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
#include <machine/clock.h>
@@ -72,30 +71,25 @@ static const char *ep_pccard_identify(u_short id);
static int
ep_pccard_probe(device_t dev)
{
- 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;
+ struct ep_softc * sc = device_get_softc(dev);
+ struct ep_board * epb = &sc->epb;
+ u_int32_t port_start;
+ u_int32_t port_count;
+ const char * desc;
+ const char * name;
+ int error;
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);
+ 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;
/*
* XXX - Certain (newer?) 3Com cards need epb->cmd_off ==
@@ -165,73 +159,36 @@ ep_pccard_card_attach(struct ep_board *epb)
static int
ep_pccard_attach(device_t dev)
{
- 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;
+ struct ep_softc * sc = device_get_softc(dev);
+ int error = 0;
- if ((sc = ep_alloc(unit, epb)) == 0)
+ if (error = ep_alloc(dev)) {
+ device_printf(dev, "ep_alloc() failed! (%d)\n", error);
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)) {
+ if (!ep_pccard_card_attach(&sc->epb)) {
+ sc->epb.cmd_off = 2;
+ sc->epb.prod_id = get_e(sc, EEPROM_PROD_ID);
+ sc->epb.res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
+ if (!ep_pccard_card_attach(&sc->epb)) {
device_printf(dev,
"Probe found ID, attach failed so ignore card!\n");
- ep_free(sc);
- return (ENXIO);
+ error = ENXIO;
+ goto bad;
}
}
- 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_RESOURCE_CFG, (sc->epb.res_cfg & 0x0fff) | 0x3000);
- outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
+ outw(BASE + EP_W0_PRODUCT_ID, sc->epb.prod_id);
- if (sc->epb->mii_trans) {
+ if (sc->epb.mii_trans) {
/*
* turn on the MII transciever
*/
@@ -244,31 +201,25 @@ ep_pccard_attach(device_t dev)
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
DELAY(1000);
outw(BASE + EP_W3_OPTIONS, 0x8040);
+ } else {
+ ep_get_media(sc);
}
- sc->irq = irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
- 0, ~0, 1, RF_ACTIVE);
- if (!irq) {
- device_printf(dev, "No irq?!\n");
+ if ((error = ep_attach(sc))) {
+ device_printf(dev, "ep_attach() failed! (%d)\n", error);
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");
+ if (error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ep_intr,
+ sc, &sc->ep_intrhand)) {
+ device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
goto bad;
}
- sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
- return 0;
+ 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;
+ ep_free(sc);
+ return (error);
}
static void
@@ -285,7 +236,8 @@ ep_pccard_detach(device_t dev)
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);
+ bus_teardown_intr(dev, sc->irq, sc->ep_intrhand);
+ ep_free(dev);
device_printf(dev, "unload\n");
}
@@ -301,7 +253,7 @@ static device_method_t ep_pccard_methods[] = {
static driver_t ep_pccard_driver = {
"ep",
ep_pccard_methods,
- 1, /* unused */
+ sizeof(struct ep_softc),
};
extern devclass_t ep_devclass;
diff --git a/sys/dev/ep/if_epreg.h b/sys/dev/ep/if_epreg.h
index fb729cb..55cb4d5 100644
--- a/sys/dev/ep/if_epreg.h
+++ b/sys/dev/ep/if_epreg.h
@@ -62,7 +62,6 @@
/*
* some macros to acces long named fields
*/
-#define IS_BASE (is->id_iobase)
#define BASE (sc->ep_io_addr)
/*
@@ -235,10 +234,10 @@
#define SET_INTR_MASK (u_short) (0xe<<11)
#define SET_RD_0_MASK (u_short) (0xf<<11)
#define SET_RX_FILTER (u_short) (0x10<<11)
-#define FIL_INDIVIDUAL (u_short) (0x1)
+#define FIL_INDIVIDUAL (u_short) (0x1)
#define FIL_GROUP (u_short) (0x2)
-#define FIL_BRDCST (u_short) (0x4)
-#define FIL_ALL (u_short) (0x8)
+#define FIL_BRDCST (u_short) (0x4)
+#define FIL_ALL (u_short) (0x8)
#define SET_RX_EARLY_THRESH (u_short) (0x11<<11)
#define SET_TX_AVAIL_THRESH (u_short) (0x12<<11)
#define SET_TX_START_THRESH (u_short) (0x13<<11)
diff --git a/sys/dev/ep/if_epvar.h b/sys/dev/ep/if_epvar.h
index f11c3f7..397a6b9 100644
--- a/sys/dev/ep/if_epvar.h
+++ b/sys/dev/ep/if_epvar.h
@@ -22,29 +22,48 @@
* $FreeBSD$
*/
+struct ep_board {
+ u_short prod_id; /* product ID */
+ int cmd_off; /* command offset (bit shift) */
+ int mii_trans; /* activate MII transiever */
+ u_short res_cfg; /* resource configuration */
+};
+
/*
* Ethernet software status per interface.
*/
struct ep_softc {
- struct arpcom arpcom; /* Ethernet common part */
- int ep_io_addr; /* i/o bus address */
- struct mbuf * top;
- struct mbuf * mcur;
- short cur_len;
- u_short ep_connectors; /* Connectors on this card. */
- 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
+ struct arpcom arpcom; /* Ethernet common part */
+ struct ifmedia ifmedia; /* media info */
+
+ device_t dev;
+
+ struct resource * iobase;
+ struct resource * irq;
+
+ bus_space_handle_t ep_bhandle;
+ bus_space_tag_t ep_btag;
+ void * ep_intrhand;
+
+ int ep_io_addr; /* i/o bus address */
+
+ u_short ep_connectors; /* Connectors on this card. */
+ u_char ep_connector; /* Configured connector.*/
+ struct mbuf * top;
+ struct mbuf * mcur;
+ short cur_len;
+
+ int stat; /* some flags */
+#define F_RX_FIRST 0x001
+#define F_PROMISC 0x008
#define F_ACCESS_32_BITS 0x100
- struct ep_board *epb;
+ int gone; /* adapter is not present (for PCCARD) */
+
+ struct ep_board epb;
- int unit;
+ int unit;
#ifdef EP_LOCAL_STATS
short tx_underrun;
@@ -56,25 +75,9 @@ struct ep_softc {
#endif
};
-struct ep_board {
- int epb_addr; /* address of this board */
- char epb_used; /* was this entry already used for configuring ? */
- /* data from EEPROM for later use */
- u_short eth_addr[3]; /* Ethernet address */
- u_short prod_id; /* product ID */
- int cmd_off; /* command offset (bit shift) */
- int mii_trans; /* activate MII transiever */
- u_short res_cfg; /* resource configuration */
-};
-
-extern struct ep_softc* ep_softc[];
-extern struct ep_board ep_board[];
-extern int ep_boards;
-extern u_long ep_unit;
-
-extern struct ep_softc* ep_alloc (int, struct ep_board *);
-extern int ep_attach (struct ep_softc *);
-extern void ep_free (struct ep_softc *);
-extern void ep_intr (void *);
-
-extern u_int16_t get_e (struct ep_softc *, int);
+int ep_alloc (device_t);
+void ep_free (device_t);
+void ep_get_media (struct ep_softc *);
+int ep_attach (struct ep_softc *);
+void ep_intr (void *);
+u_int16_t get_e (struct ep_softc *, int);
OpenPOWER on IntegriCloud