diff options
Diffstat (limited to 'sys/dev/ep')
-rw-r--r-- | sys/dev/ep/if_ep.c | 213 | ||||
-rw-r--r-- | sys/dev/ep/if_epreg.h | 9 |
2 files changed, 219 insertions, 3 deletions
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c index 772e043..ad3aa94 100644 --- a/sys/dev/ep/if_ep.c +++ b/sys/dev/ep/if_ep.c @@ -38,7 +38,7 @@ */ /* - * $Id: if_ep.c,v 1.45 1996/06/12 05:03:38 gpalmer Exp $ + * $Id: if_ep.c,v 1.46 1996/06/14 21:28:35 nate Exp $ * * Promiscuous mode added and interrupt logic slightly changed * to reduce the number of adapter failures. Transceiver select @@ -50,6 +50,12 @@ * babkin@hq.icb.chel.su */ +/* + * Pccard support for 3C589 by: + * HAMADA Naoki + * nao@tom-yam.or.jp + */ + #include "ep.h" #if NEP > 0 @@ -131,7 +137,9 @@ static void epstart __P((struct ifnet *)); static void epstop __P((struct ep_softc *)); static void epwatchdog __P((struct ifnet *)); +#if 0 static int send_ID_sequence __P((int)); +#endif static int get_eeprom_data __P((int, int)); static struct ep_softc* ep_softc[NEP]; @@ -160,6 +168,171 @@ static struct kern_devconf kdc_isa_ep = { DC_CLS_NETIF /* class */ }; +#include "crd.h" + +#if NCRD > 0 +#include "apm.h" +#include <sys/select.h> +#include <pccard/card.h> +#include <pccard/driver.h> +#include <pccard/slot.h> + +/* + * PC-Card (PCMCIA) specific code. + */ +static int card_intr __P((struct pccard_dev *)); +static void ep_unload __P((struct pccard_dev *)); +static void ep_suspend __P((struct pccard_dev *)); +static int ep_pccard_init __P((struct pccard_dev *, int)); +static int ep_pccard_attach __P((struct pccard_dev *)); + +static struct pccard_drv ep_info = { + "ep", + card_intr, + ep_unload, + ep_suspend, + ep_pccard_init, + 0, /* Attributes - presently unused */ + &net_imask +}; + +/* Resume is done by executing ep_pccard_init(dp, 0). */ +static void +ep_suspend(dp) + struct pccard_dev *dp; +{ + struct ep_softc *sc = ep_softc[dp->isahd.id_unit]; + + printf("ep%d: suspending\n", dp->isahd.id_unit); + sc->gone = 1; +} + +/* + * + */ +static int +ep_pccard_init(dp, first) + struct pccard_dev *dp; + int first; +{ + struct isa_device *is = &dp->isahd; + struct ep_softc *sc = ep_softc[is->id_unit]; + struct ep_board *epb; + int i; + + epb = &ep_board[is->id_unit]; + + if (sc == 0) { + if ((sc = ep_alloc(is->id_unit, epb)) == 0) { + return (ENXIO); + } + ep_unit++; + ep_isa_registerdev(sc, is); + } + + /* get_e() requires these. */ + sc->ep_io_addr = is->id_iobase; + sc->unit = is->id_unit; + + epb->epb_addr = is->id_iobase; + epb->epb_used = 1; + epb->prod_id = get_e(sc, EEPROM_PROD_ID); + + if (epb->prod_id != 0x9058) { /* 3C589's product id */ + if (first) { + printf("ep%d: failed to come ready.\n", is->id_unit); + } else { + printf("ep%d: failed to resume.\n", is->id_unit); + } + return (ENXIO); + } + + 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); + } + + if (first) { + if (ep_pccard_attach(dp) == 0) { + return (ENXIO); + } + sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen; + } + + if (!first) { + sc->kdc->kdc_state = DC_IDLE; + sc->gone = 0; + printf("ep%d: resumed.\n", is->id_unit); + epinit(sc); + } + + return (0); +} + +static int +ep_pccard_attach(dp) + struct pccard_dev *dp; +{ + struct isa_device *is = &dp->isahd; + struct ep_softc *sc = ep_softc[is->id_unit]; + u_short config; + + sc->ep_connectors = 0; + config = inw(IS_BASE + 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)) + printf("no connectors!"); + 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_PRODUCT_ID, sc->epb->prod_id); + + ep_attach(sc); + + return 1; +} + +static void +ep_unload(dp) + struct pccard_dev *dp; +{ + struct ep_softc *sc = ep_softc[dp->isahd.id_unit]; + + if (sc->kdc->kdc_state == DC_UNCONFIGURED) { + printf("ep%d: already unloaded\n", dp->isahd.id_unit); + return; + } + sc->kdc->kdc_state = DC_UNCONFIGURED; + sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; + sc->gone = 1; + printf("ep%d: unload\n", dp->isahd.id_unit); +} + +/* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ +static int +card_intr(dp) + struct pccard_dev *dp; +{ + epintr(dp->isahd.id_unit); + return(1); +} + +#endif /* NCRD > 0 */ + static void ep_isa_registerdev(sc, id) struct ep_softc *sc; @@ -365,6 +538,10 @@ ep_isa_probe(is) struct ep_board *epb; u_short k; +#if NCRD > 0 + pccard_add_driver(&ep_info); +#endif /* NCRD > 0 */ + if(( epb=ep_look_for_board_at(is) )==0) return (0); @@ -466,6 +643,10 @@ ep_attach(sc) struct sockaddr_dl *sdl; u_short *p; int i; + int attached; + + sc->gone = 0; + attached = (ifp->if_softc != 0); printf("ep%d: ", sc->unit); /* @@ -508,8 +689,10 @@ ep_attach(sc) ifp->if_ioctl = epioctl; ifp->if_watchdog = epwatchdog; + if (!attached) { if_attach(ifp); ether_ifattach(ifp); + } /* device attach does transition from UNCONFIGURED to IDLE state */ sc->kdc->kdc_state=DC_IDLE; @@ -557,7 +740,9 @@ ep_attach(sc) sc->top = sc->mcur = 0; #if NBPFILTER > 0 + if (!attached) { bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); + } #endif return 0; } @@ -572,7 +757,10 @@ epinit(sc) struct ep_softc *sc; { register struct ifnet *ifp = &sc->arpcom.ac_if; - int s, i; + int s, i, j; + + if (sc->gone) + return; /* if (ifp->if_addrlist == (struct ifaddr *) 0) @@ -736,6 +924,10 @@ epstart(ifp) struct mbuf *top; int s, pad; + if (sc->gone) { + return; + } + s = splimp(); if (ifp->if_flags & IFF_OACTIVE) { splx(s); @@ -850,6 +1042,11 @@ epintr(unit) int unit; { register struct ep_softc *sc = ep_softc[unit]; + + if (sc->gone) { + return; + } + ep_intr(sc); } @@ -1349,6 +1546,8 @@ static void epwatchdog(ifp) struct ifnet *ifp; { + struct ep_softc *sc = ifp->if_softc; + /* printf("ep: watchdog\n"); @@ -1356,6 +1555,10 @@ epwatchdog(ifp) ifp->if_oerrors++; */ + if (sc->gone) { + return; + } + ifp->if_flags &= ~IFF_OACTIVE; epstart(ifp); ep_intr(ifp->if_softc); @@ -1365,6 +1568,10 @@ static void epstop(sc) struct ep_softc *sc; { + if (sc->gone) { + return; + } + outw(BASE + EP_COMMAND, RX_DISABLE); outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); @@ -1379,6 +1586,7 @@ epstop(sc) } +#if 0 static int send_ID_sequence(port) int port; @@ -1393,6 +1601,7 @@ send_ID_sequence(port) } return (1); } +#endif /* diff --git a/sys/dev/ep/if_epreg.h b/sys/dev/ep/if_epreg.h index aaa8ce5..3ad7e03 100644 --- a/sys/dev/ep/if_epreg.h +++ b/sys/dev/ep/if_epreg.h @@ -31,7 +31,7 @@ */ /* - * $Id: if_epreg.h,v 1.12 1996/02/26 01:05:36 gibbs Exp $ + * $Id: if_epreg.h,v 1.13 1996/02/28 17:19:04 gibbs Exp $ * * Promiscuous mode added and interrupt logic slightly changed * to reduce the number of adapter failures. Transceiver select @@ -44,6 +44,12 @@ */ /* + * Pccard support for 3C589 by: + * HAMADA Naoki + * nao@tom-yam.or.jp + */ + +/* * Ethernet software status per interface. */ struct ep_softc { @@ -64,6 +70,7 @@ struct ep_softc { 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) */ #define F_RX_FIRST 0x1 #define F_WAIT_TRAIL 0x2 #define F_RX_TRAILER 0x4 |