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.
This commit is contained in:
parent
fac207b0b2
commit
79a9057038
@ -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 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 *));
|
||||
static int ep_media2if_media[] =
|
||||
{ IFM_10_T, IFM_10_5, IFM_NONE, IFM_10_2, IFM_NONE };
|
||||
|
||||
#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 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 *));
|
||||
|
||||
/* 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(sc);
|
||||
}
|
||||
|
||||
void
|
||||
ep_free(sc)
|
||||
struct ep_softc *sc;
|
||||
{
|
||||
ep_softc[sc->unit] = NULL;
|
||||
free(sc, M_DEVBUF);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
ep_attach(sc)
|
||||
struct ep_softc *sc;
|
||||
ep_alloc(device_t dev)
|
||||
{
|
||||
struct ifnet *ifp = &sc->arpcom.ac_if;
|
||||
u_short *p;
|
||||
int i;
|
||||
int attached;
|
||||
struct ep_softc * sc = device_get_softc(dev);
|
||||
int rid;
|
||||
int error = 0;
|
||||
|
||||
sc->gone = 0;
|
||||
attached = (ifp->if_softc != 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;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
printf("[*%s*]", ep_conn_type[sc->ep_connector]);
|
||||
sc->dev = dev;
|
||||
sc->unit = device_get_unit(dev);
|
||||
sc->stat = 0; /* 16 bit access */
|
||||
|
||||
/*
|
||||
* 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, ":");
|
||||
sc->ep_io_addr = rman_get_start(sc->iobase);
|
||||
|
||||
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;
|
||||
sc->ep_btag = rman_get_bustag(sc->iobase);
|
||||
sc->ep_bhandle = rman_get_bushandle(sc->iobase);
|
||||
|
||||
if (!attached) {
|
||||
if_attach(ifp);
|
||||
ether_ifattach(ifp);
|
||||
}
|
||||
sc->ep_connectors = 0;
|
||||
sc->ep_connector = 0;
|
||||
|
||||
#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;
|
||||
#endif
|
||||
EP_FSET(sc, F_RX_FIRST);
|
||||
sc->top = sc->mcur = 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);
|
||||
|
||||
if (!attached) {
|
||||
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
|
||||
}
|
||||
return 0;
|
||||
bad:
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
ep_get_media(sc)
|
||||
struct ep_softc * sc;
|
||||
{
|
||||
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 ifnet * ifp = NULL;
|
||||
struct ifmedia * ifm = NULL;
|
||||
u_short * p;
|
||||
int i;
|
||||
int attached;
|
||||
|
||||
sc->gone = 0;
|
||||
|
||||
ep_get_macaddr(sc, (u_char *)&sc->arpcom.ac_enaddr);
|
||||
|
||||
/*
|
||||
* 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]));
|
||||
}
|
||||
|
||||
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;
|
||||
#endif
|
||||
EP_FSET(sc, F_RX_FIRST);
|
||||
sc->top = sc->mcur = 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 @@ ep_intr(arg)
|
||||
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 @@ ep_intr(arg)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
epinit(sc);
|
||||
ep_if_init(sc);
|
||||
splx(x);
|
||||
return;
|
||||
}
|
||||
@ -606,7 +636,7 @@ ep_intr(arg)
|
||||
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 @@ epread(sc)
|
||||
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;
|
||||
|
||||
s = splimp();
|
||||
GO_WINDOW(0);
|
||||
outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
|
||||
GO_WINDOW(4);
|
||||
outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP);
|
||||
GO_WINDOW(0);
|
||||
|
||||
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);
|
||||
break;
|
||||
} else {
|
||||
/* reinitialize card on any parameter change */
|
||||
epinit(sc);
|
||||
break;
|
||||
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");
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
#ifdef notdef
|
||||
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:
|
||||
error = EINVAL;
|
||||
}
|
||||
GO_WINDOW(0);
|
||||
j = inw(BASE + EP_W0_ADDRESS_CFG) & 0x3fff;
|
||||
outw(BASE + EP_W0_ADDRESS_CFG, j | (i << ACF_CONNECTOR_BITS));
|
||||
|
||||
splx(s);
|
||||
|
||||
return (error);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
epwatchdog(ifp)
|
||||
ep_ifmedia_sts(ifp, ifmr)
|
||||
struct ifnet * ifp;
|
||||
struct ifmediareq * ifmr;
|
||||
{
|
||||
struct ep_softc * sc = ifp->if_softc;
|
||||
|
||||
ifmr->ifm_active = sc->ifmedia.ifm_media;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
#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;
|
||||
case SIOCSIFMEDIA:
|
||||
case SIOCGIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
(void)splx(s);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
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 */
|
||||
|
@ -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);
|
||||
|
||||
/* 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 ((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 = 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");
|
||||
ep_get_media(sc);
|
||||
|
||||
irq = rman_get_start(sc->irq);
|
||||
if (irq == 9)
|
||||
irq = 2;
|
||||
|
||||
GO_WINDOW(0);
|
||||
SET_IRQ(BASE, irq);
|
||||
|
||||
if ((error = ep_attach(sc))) {
|
||||
device_printf(dev, "ep_attach() failed! (%d)\n", error);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Now the registers are availible through the lower ioport */
|
||||
|
||||
/*
|
||||
* Retrieve our ethernet address
|
||||
*/
|
||||
GO_WINDOW(0);
|
||||
for(i = 0; i < 3; i++)
|
||||
sc->epb->eth_addr[i] = get_e(sc, i);
|
||||
|
||||
/* 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);
|
||||
|
||||
bus_setup_intr(dev, irq, INTR_TYPE_NET, ep_intr, sc, &ih);
|
||||
|
||||
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 */
|
||||
|
@ -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);
|
||||
static int get_eeprom_data (int, int);
|
||||
|
||||
#if 0
|
||||
static int send_ID_sequence (int);
|
||||
#endif
|
||||
static void ep_isa_identify (driver_t *, device_t);
|
||||
static int ep_isa_probe (device_t);
|
||||
static int ep_isa_attach (device_t);
|
||||
|
||||
static int ep_current_tag = EP_LAST_TAG + 1;
|
||||
struct isa_ident {
|
||||
u_int32_t id;
|
||||
char * name;
|
||||
};
|
||||
const char * ep_isa_match_id (u_int32_t, struct isa_ident *);
|
||||
|
||||
struct isa_driver epdriver = {
|
||||
ep_isa_probe,
|
||||
ep_isa_attach,
|
||||
"ep",
|
||||
0
|
||||
#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;
|
||||
{
|
||||
register struct ep_softc *sc = ep_softc[unit];
|
||||
|
||||
ep_intr(sc);
|
||||
|
||||
return;
|
||||
struct isa_ident * i = isa_devs;
|
||||
while(i->name != NULL) {
|
||||
if (id == i->id)
|
||||
return (i->name);
|
||||
i++;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
send_ID_sequence(port)
|
||||
int port;
|
||||
static void
|
||||
ep_isa_identify (driver_t *driver, device_t parent)
|
||||
{
|
||||
int cx, al;
|
||||
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;
|
||||
|
||||
for (al = 0xff, cx = 0; cx < 255; cx++) {
|
||||
outb(port, al);
|
||||
al <<= 1;
|
||||
if (al & 0x100)
|
||||
al ^= 0xcf;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
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));
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
ep_isa_probe (device_t dev)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
struct ep_softc * sc = device_get_softc(dev);
|
||||
int error = 0;
|
||||
|
||||
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");
|
||||
if ((error = ep_alloc(dev))) {
|
||||
device_printf(dev, "ep_alloc() failed! (%d)\n", error);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
rid = 0;
|
||||
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
if (!irq) {
|
||||
device_printf(dev, "No irq?!\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
epb = &ep_board[ep_boards];
|
||||
|
||||
epb->epb_addr = rman_get_start(io);
|
||||
epb->epb_used = 1;
|
||||
|
||||
if(!(sc = ep_alloc(unit, epb)))
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
||||
GO_WINDOW(0);
|
||||
SET_IRQ(BASE, rman_get_start(irq));
|
||||
|
||||
ep_attach(sc);
|
||||
|
||||
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;
|
||||
|
@ -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/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/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_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;
|
||||
struct ep_softc * sc = device_get_softc(dev);
|
||||
int error = 0;
|
||||
|
||||
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");
|
||||
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)) == 0)
|
||||
goto bad;
|
||||
ep_boards++;
|
||||
|
||||
epb->cmd_off = 0;
|
||||
epb->prod_id = get_e(sc, EEPROM_PROD_ID);
|
||||
if (!ep_pccard_card_attach(epb)) {
|
||||
epb->cmd_off = 2;
|
||||
epb->prod_id = get_e(sc, EEPROM_PROD_ID);
|
||||
if (!ep_pccard_card_attach(epb)) {
|
||||
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;
|
||||
|
@ -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)
|
||||
|
@ -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) */
|
||||
|
||||
int unit;
|
||||
struct ep_board epb;
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user