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:
Matthew N. Dodd 1999-10-27 06:25:16 +00:00
parent fac207b0b2
commit 79a9057038
7 changed files with 731 additions and 820 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);