Pull down from marc-pcmcia branch:

Minor tweaks to deal with PCMCIA differences, and support for power
management.
This commit is contained in:
thorpej 1997-10-14 21:28:37 +00:00
parent 340335d484
commit 10708da893
6 changed files with 165 additions and 51 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ep_eisa.c,v 1.13 1997/04/18 00:50:33 cgd Exp $ */
/* $NetBSD: if_ep_eisa.c,v 1.14 1997/10/14 21:30:59 thorpej Exp $ */
/*
* Copyright (c) 1997 Jonathan Stone <jonathan@NetBSD.org>
@ -205,5 +205,9 @@ ep_eisa_attach(parent, self, aux)
printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname,
intrstr);
epconfig(sc, chipset);
sc->enable = NULL;
sc->disable = NULL;
sc->enabled = 1;
epconfig(sc, chipset, NULL);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: elink3.c,v 1.33 1997/07/30 18:26:23 jonathan Exp $ */
/* $NetBSD: elink3.c,v 1.34 1997/10/14 21:28:37 thorpej Exp $ */
/*
* Copyright (c) 1996, 1997 Jonathan Stone <jonathan@NetBSD.org>
@ -163,7 +163,10 @@ struct mbuf *epget __P((struct ep_softc *, int));
void epmbuffill __P((void *));
void epmbufempty __P((struct ep_softc *));
void epsetfilter __P((struct ep_softc *));
int epsetmedia __P((struct ep_softc *, int epmedium));
void epsetmedia __P((struct ep_softc *, int epmedium));
int epenable __P((struct ep_softc *));
void epdisable __P((struct ep_softc *));
/* ifmedia callbacks */
int ep_media_change __P((struct ifnet *ifp));
@ -201,15 +204,14 @@ ep_complete_cmd(sc, cmd, arg)
#endif
}
/*
* Back-end attach and configure.
*/
void
epconfig(sc, chipset)
epconfig(sc, chipset, enaddr)
struct ep_softc *sc;
u_short chipset;
u_int8_t *enaddr;
{
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
bus_space_tag_t iot = sc->sc_iot;
@ -226,24 +228,27 @@ epconfig(sc, chipset)
*/
GO_WINDOW(0);
/*
* Read the station address from the eeprom
*/
for (i = 0; i < 3; i++) {
u_int16_t x;
if (epbusyeeprom(sc))
return; /* XXX why is eeprom busy? */
bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
READ_EEPROM | i);
if (epbusyeeprom(sc))
return; /* XXX why is eeprom busy? */
x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA);
myla[(i << 1)] = x >> 8;
myla[(i << 1) + 1] = x;
if (enaddr == NULL) {
/*
* Read the station address from the eeprom
*/
for (i = 0; i < 3; i++) {
u_int16_t x;
if (epbusyeeprom(sc))
return; /* XXX why is eeprom busy? */
bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
READ_EEPROM | i);
if (epbusyeeprom(sc))
return; /* XXX why is eeprom busy? */
x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA);
myla[(i << 1)] = x >> 8;
myla[(i << 1) + 1] = x;
}
enaddr = myla;
}
printf("%s: MAC address %s\n", sc->sc_dev.dv_xname,
ether_sprintf(myla));
ether_sprintf(enaddr));
/*
* Vortex-based (3c59x pci,eisa) and Boomerang (3c900,3c515?) cards
@ -274,9 +279,9 @@ epconfig(sc, chipset)
break;
default:
printf("%s: wrote %d to TX_AVAIL_THRESH, read back %d. "
printf("%s: wrote 0x%x to TX_AVAIL_THRESH, read back 0x%x. "
"Interface disabled\n",
sc->sc_dev.dv_xname, EP_THRESH_DISABLE, (int) i);
sc->sc_dev.dv_xname, EP_LARGEWIN_PROBE, (int) i);
return;
}
@ -297,7 +302,7 @@ epconfig(sc, chipset)
IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
if_attach(ifp);
ether_ifattach(ifp, myla);
ether_ifattach(ifp, enaddr);
/*
* Finish configuration:
@ -311,12 +316,13 @@ epconfig(sc, chipset)
ifmedia_init(&sc->sc_media, 0, ep_media_change, ep_media_status);
/*
* If we've got an indirect (ISA, PCMCIA?) board, the chipset
* is unknown. If the board has large-packet support, it's a
* Vortex/Boomerang, otherwise it's a 3c509.
* XXX use eeprom capability word instead?
/*
* If we've got an indirect (ISA) board, the chipset is
* unknown. If the board has large-packet support, it's a
* Vortex/Boomerang, otherwise it's a 3c509. XXX use eeprom
* capability word instead?
*/
if (sc->ep_chipset == EP_CHIPSET_UNKNOWN && sc->ep_pktlenshift) {
printf("warning: unknown chipset, possibly 3c515?\n");
#ifdef notyet
@ -629,7 +635,16 @@ ep_media_change(ifp)
{
register struct ep_softc *sc = ifp->if_softc;
return epsetmedia(sc, sc->sc_media.ifm_cur->ifm_data);
/*
* If the interface is not currently powered on, just return.
* When it is enabled later, epinit() will properly set up the
* media for us.
*/
if (sc->enabled == 0)
return (0);
epsetmedia(sc, sc->sc_media.ifm_cur->ifm_data);
return (0);
}
/*
@ -639,7 +654,7 @@ ep_media_change(ifp)
* For 3c509-generation cards (3c509/3c579/3c589/3c509B),
* update media field in w0_address_config, and power on selected xcvr.
*/
int
void
epsetmedia(sc, medium)
register struct ep_softc *sc;
int medium;
@ -740,7 +755,6 @@ epsetmedia(sc, medium)
}
GO_WINDOW(1); /* Window 1 is operating window */
return (0);
}
/*
@ -758,6 +772,12 @@ ep_media_status(ifp, req)
u_int config1;
u_int ep_mediastatus;
if (sc->enabled == 0) {
req->ifm_active = IFM_ETHER|IFM_NONE;
req->ifm_status = 0;
return;
}
/* XXX read from softc when we start autosensing media */
req->ifm_active = sc->sc_media.ifm_cur->ifm_media;
@ -798,7 +818,6 @@ ep_media_status(ifp, req)
/* XXX look for softc heartbeat for other chips or media */
GO_WINDOW(1);
return;
}
@ -953,6 +972,12 @@ readcheck:
epread(sc);
} else {
/* Got an interrupt, return so that it gets serviced. */
#if 0
printf("%s: S_INTR_LATCH %04x mask=%04x ipending=%04x (%04x)\n",
sc->sc_dev.dv_xname, status,
cpl, ipending, imask[IPL_NET]);
#endif
return;
}
} else {
@ -1073,14 +1098,24 @@ epintr(arg)
u_int16_t status;
int ret = 0;
if (sc->enabled == 0)
return (0);
for (;;) {
bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
status = bus_space_read_2(iot, ioh, EP_STATUS);
if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
S_RX_COMPLETE | S_CARD_FAILURE)) == 0)
break;
S_RX_COMPLETE | S_CARD_FAILURE)) == 0) {
if ((status & S_INTR_LATCH) == 0) {
#if 0
printf("%s: intr latch cleared\n",
sc->sc_dev.dv_xname);
#endif
break;
}
}
ret = 1;
@ -1090,7 +1125,25 @@ epintr(arg)
* Due to the i386 interrupt queueing, we may get spurious
* interrupts occasionally.
*/
bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | status);
bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR |
(status & (C_INTR_LATCH |
C_CARD_FAILURE |
C_TX_COMPLETE |
C_TX_AVAIL |
C_RX_COMPLETE |
C_RX_EARLY |
C_INT_RQD |
C_UPD_STATS)));
#if 0
status = bus_space_read_2(iot, ioh, EP_STATUS);
printf("%s: intr%s%s%s%s\n", sc->sc_dev.dv_xname,
(status & S_RX_COMPLETE)?" RX_COMPLETE":"",
(status & S_TX_COMPLETE)?" TX_COMPLETE":"",
(status & S_TX_AVAIL)?" TX_AVAIL":"",
(status & S_CARD_FAILURE)?" CARD_FAILURE":"");
#endif
if (status & S_RX_COMPLETE)
epread(sc);
@ -1391,8 +1444,10 @@ epioctl(ifp, cmd, data)
switch (cmd) {
case SIOCSIFADDR:
if ((error = epenable(sc)) != 0)
break;
/* epinit is called just below */
ifp->if_flags |= IFF_UP;
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
@ -1437,14 +1492,17 @@ epioctl(ifp, cmd, data)
*/
epstop(sc);
ifp->if_flags &= ~IFF_RUNNING;
epdisable(sc);
} else if ((ifp->if_flags & IFF_UP) != 0 &&
(ifp->if_flags & IFF_RUNNING) == 0) {
/*
* If interface is marked up and it is stopped, then
* start it.
*/
if ((error = epenable(sc)) != 0)
break;
epinit(sc);
} else {
} else if (sc->enabled) {
/*
* deal with flags changes:
* IFF_MULTICAST, IFF_PROMISC.
@ -1455,6 +1513,11 @@ epioctl(ifp, cmd, data)
case SIOCADDMULTI:
case SIOCDELMULTI:
if (sc->enabled == 0) {
error = EIO;
break;
}
error = (cmd == SIOCADDMULTI) ?
ether_addmulti(ifr, &sc->sc_ethercom) :
ether_delmulti(ifr, &sc->sc_ethercom);
@ -1537,8 +1600,10 @@ epshutdown(arg)
{
register struct ep_softc *sc = arg;
epstop(sc);
ep_complete_cmd(sc, EP_COMMAND, GLOBAL_RESET);
if (sc->enabled) {
epstop(sc);
ep_complete_cmd(sc, EP_COMMAND, GLOBAL_RESET);
}
}
/*
@ -1647,3 +1712,31 @@ epmbufempty(sc)
untimeout(epmbuffill, sc);
splx(s);
}
int
epenable(sc)
struct ep_softc *sc;
{
if (sc->enabled == 0 && sc->enable != NULL) {
if ((*sc->enable)(sc) != 0) {
printf("%s: device enable failed\n",
sc->sc_dev.dv_xname);
return (EIO);
}
}
sc->enabled = 1;
return (0);
}
void
epdisable(sc)
struct ep_softc *sc;
{
if (sc->enabled != 0 && sc->disable != NULL) {
(*sc->disable)(sc);
sc->enabled = 0;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: elink3var.h,v 1.12 1997/03/30 22:47:11 jonathan Exp $ */
/* $NetBSD: elink3var.h,v 1.13 1997/10/14 21:28:39 thorpej Exp $ */
/*
* Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org>
@ -81,10 +81,15 @@ struct ep_softc {
#define EP_IS_BUS_32(a) ((a) & 0x2)
int ep_pktlenshift; /* scale factor for pkt lengths */
/* power management hooks */
int (*enable) __P((struct ep_softc *));
void (*disable) __P((struct ep_softc *));
int enabled;
};
u_int16_t epreadeeprom __P((bus_space_tag_t, bus_space_handle_t, int));
void epconfig __P((struct ep_softc *, u_short));
void epconfig __P((struct ep_softc *, u_short, u_int8_t *));
int epintr __P((void *));
void epstop __P((struct ep_softc *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ep_isa.c,v 1.16 1997/10/05 18:37:02 thorpej Exp $ */
/* $NetBSD: if_ep_isa.c,v 1.17 1997/10/14 21:32:48 thorpej Exp $ */
/*-
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@ -337,17 +337,21 @@ ep_isa_attach(parent, self, aux)
sc->sc_ioh = ioh;
sc->bustype = EP_BUS_ISA;
sc->enable = NULL;
sc->disable = NULL;
sc->enabled = 1;
chipset = (int)(long)ia->ia_aux;
if ((chipset & 0xfff0) == PROD_ID_3C509) {
printf(": 3Com 3C509 Ethernet\n");
epconfig(sc, EP_CHIPSET_3C509);
epconfig(sc, EP_CHIPSET_3C509, NULL);
} else {
/*
* XXX: Maybe a 3c515, but the check in ep_isa_probe looks
* at the moment only for a 3c509.
*/
printf(": unknown 3Com Ethernet card: %04x\n", chipset);
epconfig(sc, EP_CHIPSET_UNKNOWN);
epconfig(sc, EP_CHIPSET_UNKNOWN, NULL);
}
sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ep_isapnp.c,v 1.8 1997/08/07 19:46:22 christos Exp $ */
/* $NetBSD: if_ep_isapnp.c,v 1.9 1997/10/14 21:34:30 thorpej Exp $ */
/*
* Copyright (c) 1997 Jonathan Stone <jonathan@NetBSD.org>
@ -134,13 +134,17 @@ ep_isapnp_attach(parent, self, aux)
sc->sc_ih = isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num,
IST_EDGE, IPL_NET, epintr, sc);
sc->enable = NULL;
sc->disable = NULL;
sc->enabled = 1;
if (strcmp(ipa->ipa_devlogic, "TCM5090") &&
strcmp(ipa->ipa_devlogic, "TCM5091") &&
strcmp(ipa->ipa_devlogic, "TCM5094") &&
strcmp(ipa->ipa_devlogic, "TCM5095") &&
strcmp(ipa->ipa_devlogic, "TCM5098")) {
epconfig(sc, EP_CHIPSET_UNKNOWN); /* XXX: 3c515 ? */
epconfig(sc, EP_CHIPSET_UNKNOWN, NULL); /* XXX: 3c515 ? */
} else {
epconfig(sc, EP_CHIPSET_3C509);
epconfig(sc, EP_CHIPSET_3C509, NULL);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ep_pci.c,v 1.23 1997/04/13 20:14:29 cgd Exp $ */
/* $NetBSD: if_ep_pci.c,v 1.24 1997/10/14 21:37:00 thorpej Exp $ */
/*
* Copyright (c) 1997 Jonathan Stone <jonathan@NetBSD.org>
@ -173,7 +173,11 @@ ep_pci_attach(parent, self, aux)
printf(": %s\n", model);
epconfig(sc, EP_CHIPSET_VORTEX);
sc->enable = NULL;
sc->disable = NULL;
sc->enabled = 1;
epconfig(sc, EP_CHIPSET_VORTEX, NULL);
/* Enable the card. */
pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,