diff options
author | mdodd <mdodd@FreeBSD.org> | 1999-10-27 06:25:16 +0000 |
---|---|---|
committer | mdodd <mdodd@FreeBSD.org> | 1999-10-27 06:25:16 +0000 |
commit | 5b7d331b4dc9d7b8fd701fbb5328ef1b7fcd5dfb (patch) | |
tree | e829fbdae4384eba77df0f37236cbb52bd7bb73c | |
parent | 21f0026c8502ee6b99ec2b4554601965e4ff56c4 (diff) | |
download | FreeBSD-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.c | 534 | ||||
-rw-r--r-- | sys/dev/ep/if_ep_eisa.c | 153 | ||||
-rw-r--r-- | sys/dev/ep/if_ep_isa.c | 492 | ||||
-rw-r--r-- | sys/dev/ep/if_ep_mca.c | 98 | ||||
-rw-r--r-- | sys/dev/ep/if_ep_pccard.c | 142 | ||||
-rw-r--r-- | sys/dev/ep/if_epreg.h | 7 | ||||
-rw-r--r-- | sys/dev/ep/if_epvar.h | 77 |
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); |