Home | History | Annotate | Line # | Download | only in isa
if_eg.c revision 1.1
      1 /*
      2  * Copyright (c) 1993 Dean Huxley <dean (at) fsa.ca>
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *      This product includes software developed by Dean Huxley.
     16  * 4. The name of Dean Huxley may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  *
     30  *	$Id: if_eg.c,v 1.1 1994/08/23 18:00:08 deraadt Exp $
     31  */
     32 
     33 /* To do:
     34  * - multicast
     35  * - promiscuous
     36  */
     37 #include "bpfilter.h"
     38 
     39 #include <sys/types.h>
     40 #include <sys/param.h>
     41 #include <sys/mbuf.h>
     42 #include <sys/socket.h>
     43 #include <sys/ioctl.h>
     44 #include <sys/errno.h>
     45 #include <sys/syslog.h>
     46 #include <sys/select.h>
     47 #include <sys/device.h>
     48 
     49 #include <net/if.h>
     50 #include <net/netisr.h>
     51 #include <net/if_dl.h>
     52 #include <net/if_types.h>
     53 #include <net/netisr.h>
     54 
     55 #ifdef INET
     56 #include <netinet/in.h>
     57 #include <netinet/in_systm.h>
     58 #include <netinet/in_var.h>
     59 #include <netinet/ip.h>
     60 #include <netinet/if_ether.h>
     61 #endif
     62 
     63 #ifdef NS
     64 #include <netns/ns.h>
     65 #include <netns/ns_if.h>
     66 #endif
     67 
     68 #if NBPFILTER > 0
     69 #include <net/bpf.h>
     70 #include <net/bpfdesc.h>
     71 #endif
     72 
     73 #include <machine/cpu.h>
     74 #include <machine/pio.h>
     75 
     76 #include <i386/isa/isavar.h>
     77 #include <i386/isa/if_egreg.h>
     78 #include <i386/isa/elink.h>
     79 
     80 /* for debugging convenience */
     81 #ifdef EGDEBUG
     82 #define dlog(x) log x
     83 #else
     84 #define dlog(x)
     85 #endif
     86 
     87 #define ETHER_MIN_LEN	64
     88 #define ETHER_MAX_LEN	1518
     89 #define ETHER_ADDR_LEN	6
     90 
     91 #define EG_INLEN  	10
     92 #define EG_BUFLEN	0x0670
     93 
     94 /*
     95  * Ethernet software status per interface.
     96  */
     97 struct eg_softc {
     98 	struct device sc_dev;
     99 	struct intrhand sc_ih;
    100 	struct arpcom sc_arpcom;	/* Ethernet common part */
    101 	short   eg_cmd;			/* Command register R/W */
    102 	short   eg_ctl;			/* Control register R/W (EG_CTL_*) */
    103 	short   eg_stat;		/* Status register R/O (EG_STAT_*) */
    104 	short   eg_data;		/* Data register R/W (16 bits) */
    105 	u_char  eg_rom_major;		/* Cards ROM version (major number) */
    106 	u_char  eg_rom_minor;		/* Cards ROM version (minor number) */
    107 	short	eg_ram;			/* Amount of RAM on the card */
    108 	u_char	eg_pcb[64];		/* Primary Command Block buffer */
    109 	u_char  eg_incount;		/* Number of buffers currently used */
    110 	u_char  *eg_inbuf;		/* Incoming packet buffer */
    111 	u_char  *eg_outbuf;		/* Outgoing packet buffer */
    112 };
    113 
    114 static int egprobe();
    115 static void egattach();
    116 
    117 struct cfdriver egcd = {
    118 	NULL, "eg", egprobe, egattach, DV_IFNET, sizeof(struct eg_softc)
    119 };
    120 
    121 int egintr __P((struct eg_softc *));
    122 static void eginit __P((struct eg_softc *));
    123 static int egioctl __P((struct ifnet *, int, caddr_t));
    124 static int egrecv __P((struct eg_softc *));
    125 static int egstart __P((struct ifnet *));
    126 static int egwatchdog __P((int));
    127 static void egreset __P((struct eg_softc *));
    128 static inline void egread __P((struct eg_softc *, caddr_t, int));
    129 static struct mbuf *egget __P((caddr_t, int, struct ifnet *));
    130 static void egstop __P((struct eg_softc *));
    131 
    132 /*
    133  * Support stuff
    134  */
    135 
    136 static inline void
    137 egprintpcb(sc)
    138 	struct eg_softc *sc;
    139 {
    140 	int i;
    141 
    142 	for (i = 0; i < sc->eg_pcb[1] + 2; i++)
    143 		dlog((LOG_DEBUG, "pcb[%2d] = %x\n", sc->eg_pcb[i]));
    144 }
    145 
    146 
    147 static inline void
    148 egprintstat(b)
    149 	u_char b;
    150 {
    151 	dlog((LOG_DEBUG, "%s %s %s %s %s %s %s\n",
    152 		 (b & EG_STAT_HCRE)?"HCRE":"",
    153 		 (b & EG_STAT_ACRF)?"ACRF":"",
    154 		 (b & EG_STAT_DIR )?"DIR ":"",
    155 		 (b & EG_STAT_DONE)?"DONE":"",
    156 		 (b & EG_STAT_ASF3)?"ASF3":"",
    157 		 (b & EG_STAT_ASF2)?"ASF2":"",
    158 		 (b & EG_STAT_ASF1)?"ASF1":""));
    159 }
    160 
    161 static int
    162 egoutPCB(sc, b)
    163 	struct eg_softc *sc;
    164 	u_char b;
    165 {
    166 	int i;
    167 
    168 	for (i=0; i < 4000; i++) {
    169 		if (inb(sc->eg_stat) & EG_STAT_HCRE) {
    170 			outb(sc->eg_cmd, b);
    171 			return 0;
    172 		}
    173 		delay(10);
    174 	}
    175 	dlog((LOG_DEBUG, "egoutPCB failed\n"));
    176 	return 1;
    177 }
    178 
    179 static int
    180 egreadPCBstat(sc, statb)
    181 	struct eg_softc *sc;
    182 	u_char statb;
    183 {
    184 	int i;
    185 
    186 	for (i=0; i < 5000; i++) {
    187 		if (EG_PCB_STAT(inb(sc->eg_stat)))
    188 			break;
    189 		delay(10);
    190 	}
    191 	if (EG_PCB_STAT(inb(sc->eg_stat)) == statb)
    192 		return 0;
    193 	return 1;
    194 }
    195 
    196 static int
    197 egreadPCBready(sc)
    198 	struct eg_softc *sc;
    199 {
    200 	int i;
    201 
    202 	for (i=0; i < 10000; i++) {
    203 		if (inb(sc->eg_stat) & EG_STAT_ACRF)
    204 			return 0;
    205 		delay(5);
    206 	}
    207 	dlog((LOG_DEBUG, "PCB read not ready\n"));
    208 	return 1;
    209 }
    210 
    211 static int
    212 egwritePCB(sc)
    213 	struct eg_softc *sc;
    214 {
    215 	int i;
    216 	u_char len;
    217 
    218 
    219 	outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)));
    220 
    221 	len = sc->eg_pcb[1] + 2;
    222 	for (i = 0; i < len; i++)
    223 		egoutPCB(sc, sc->eg_pcb[i]);
    224 
    225 	for (i=0; i < 4000; i++) {
    226 		if (inb(sc->eg_stat) & EG_STAT_HCRE)
    227 			break;
    228 		delay(10);
    229 	}
    230 	outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)) | EG_PCB_DONE);
    231 	egoutPCB(sc, len);
    232 
    233 	if (egreadPCBstat(sc, EG_PCB_ACCEPT))
    234 		return 1;
    235 	return 0;
    236 }
    237 
    238 static int
    239 egreadPCB(sc)
    240 	struct eg_softc *sc;
    241 {
    242 	int i;
    243 	u_char b;
    244 
    245 	outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)));
    246 
    247 	bzero(sc->eg_pcb, sizeof(sc->eg_pcb));
    248 
    249 	if (egreadPCBready(sc))
    250 		return 1;
    251 
    252 	sc->eg_pcb[0] = inb(sc->eg_cmd);
    253 
    254 	if (egreadPCBready(sc))
    255 		return 1;
    256 
    257 	sc->eg_pcb[1] = inb(sc->eg_cmd);
    258 
    259 	if (sc->eg_pcb[1] > 62) {
    260 		dlog((LOG_DEBUG, "len %d too large\n", sc->eg_pcb[1]));
    261 		return 1;
    262 	}
    263 
    264 	for (i = 0; i < sc->eg_pcb[1]; i++) {
    265 		if (egreadPCBready(sc))
    266 			return 1;
    267 		sc->eg_pcb[2+i] = inb(sc->eg_cmd);
    268 	}
    269 	if (egreadPCBready(sc))
    270 		return 1;
    271 	if (egreadPCBstat(sc, EG_PCB_DONE))
    272 		return 1;
    273 	if ((b = inb(sc->eg_cmd)) != sc->eg_pcb[1]+2) {
    274 		dlog((LOG_DEBUG, "%d != %d\n", b, sc->eg_pcb[1]+2));
    275 		return 1;
    276 	}
    277         outb(sc->eg_ctl, EG_PCB_MASK(inb(sc->eg_ctl)) | EG_PCB_ACCEPT);
    278 	return 0;
    279 }
    280 
    281 /*
    282  * Real stuff
    283  */
    284 
    285 int
    286 egprobe(parent, self, aux)
    287 	struct device *parent, *self;
    288 	void *aux;
    289 {
    290         struct eg_softc *sc = (void *)self;
    291 	struct isa_attach_args *ia = aux;
    292 	int i;
    293 
    294         if (ia->ia_iobase & ~0x07f0 != 0) {
    295 		dlog((LOG_DEBUG, "Weird iobase %x\n", ia->ia_iobase));
    296 		return 0;
    297 	}
    298 
    299 	sc->eg_cmd = ia->ia_iobase + EG_COMMAND;
    300 	sc->eg_ctl = ia->ia_iobase + EG_CONTROL;
    301 	sc->eg_stat = ia->ia_iobase + EG_STATUS;
    302 	sc->eg_data = ia->ia_iobase + EG_DATA;
    303 
    304 	/* hard reset card */
    305 	outb(sc->eg_ctl, EG_CTL_RESET);
    306 	outb(sc->eg_ctl, 0);
    307 	for (i = 0; i < 5000; i++) {
    308 		delay(1000);
    309 		if (EG_PCB_STAT(inb(sc->eg_stat)) == 0)
    310 			break;
    311 	}
    312 	if (EG_PCB_STAT(inb(sc->eg_stat)) != 0) {
    313 		dlog((LOG_DEBUG, "eg: Reset failed\n"));
    314 		return 0;
    315 	}
    316 	sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
    317 	sc->eg_pcb[1] = 0;
    318 	if (egwritePCB(sc) != 0)
    319 		return 0;
    320 
    321 	if (egreadPCB(sc) != 0) {
    322 		egprintpcb(sc);
    323 		return 0;
    324 	}
    325 
    326 	if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
    327 	    sc->eg_pcb[1] != 0x0a) {
    328 		egprintpcb(sc);
    329 		return 0;
    330 	}
    331 	sc->eg_rom_major = sc->eg_pcb[3];
    332 	sc->eg_rom_minor = sc->eg_pcb[2];
    333 	sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
    334 
    335 	ia->ia_iosize = 0x08;
    336 	ia->ia_msize = 0;
    337 	return 1;
    338 }
    339 
    340 static void
    341 egattach(parent, self, aux)
    342 	struct device *parent, *self;
    343 	void *aux;
    344 {
    345         struct eg_softc *sc = (void *)self;
    346         struct isa_attach_args *ia = aux;
    347 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    348 	int i;
    349 
    350 	outb(sc->eg_ctl, 0); /* make sure board is in a nice state */
    351 
    352 	sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */
    353 	sc->eg_pcb[1] = 0;
    354 	if (egwritePCB(sc) != 0) {
    355 		dlog((LOG_DEBUG, "write error\n"));
    356 		return;
    357 	}
    358 	if (egreadPCB(sc) != 0) {
    359 		dlog((LOG_DEBUG, "read error\n"));
    360 		egprintpcb(sc);
    361 		return;
    362 	}
    363 
    364 	/* check Get station address response */
    365 	if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) {
    366 		dlog((LOG_DEBUG, "parse error\n"));
    367 		egprintpcb(sc);
    368 		return;
    369 	}
    370 	bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
    371 
    372 	printf(": ROM v%d.%02d %dk address %s\n",
    373 	       sc->eg_rom_major,
    374 	       sc->eg_rom_minor,
    375 	       sc->eg_ram,
    376 	       ether_sprintf(sc->sc_arpcom.ac_enaddr));
    377 
    378 	sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */
    379 	if (egwritePCB(sc) != 0) {
    380 		dlog((LOG_DEBUG, "write error2\n"));
    381 		return;
    382 	}
    383 	if (egreadPCB(sc) != 0) {
    384 		dlog((LOG_DEBUG, "read error2\n"));
    385 		egprintpcb(sc);
    386 		return;
    387 	}
    388         if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||
    389 	   sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {
    390 		dlog((LOG_DEBUG, "parse error2\n"));
    391 		egprintpcb(sc);
    392 		return;
    393 	}
    394 
    395         /* Initialize ifnet structure. */
    396 	ifp->if_unit = sc->sc_dev.dv_unit;
    397 	ifp->if_name = egcd.cd_name;
    398 	ifp->if_mtu = ETHERMTU;
    399 	ifp->if_output = ether_output;
    400 	ifp->if_start = egstart;
    401 	ifp->if_ioctl = egioctl;
    402 	ifp->if_watchdog = egwatchdog;
    403 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
    404 
    405 	/* Now we can attach the interface. */
    406 	if_attach(ifp);
    407 	ether_ifattach(ifp);
    408 
    409 #if NBPFILTER > 0
    410 	bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
    411 #endif
    412 
    413         sc->sc_ih.ih_fun = egintr;
    414         sc->sc_ih.ih_arg = sc;
    415         sc->sc_ih.ih_level = IPL_NET;
    416         intr_establish(ia->ia_irq, &sc->sc_ih);
    417 }
    418 
    419 static void
    420 eginit(sc)
    421 	register struct eg_softc *sc;
    422 {
    423 	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    424 	int s;
    425 
    426 	if (ifp->if_addrlist == 0)
    427 		return;
    428 
    429 	s = splimp();
    430 
    431 	/* soft reset the board */
    432 	outb(sc->eg_ctl, EG_CTL_FLSH);
    433 	delay(100);
    434 	outb(sc->eg_ctl, EG_CTL_ATTN);
    435 	delay(100);
    436 	outb(sc->eg_ctl, 0);
    437 	delay(200);
    438 
    439 	sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */
    440 	sc->eg_pcb[1] = 2;
    441 	sc->eg_pcb[2] = 3; /* receive broadcast & multicast */
    442 	sc->eg_pcb[3] = 0;
    443 	if (egwritePCB(sc) != 0)
    444 		dlog((LOG_DEBUG, "write error3\n"));
    445 
    446 	if (egreadPCB(sc) != 0) {
    447 		dlog((LOG_DEBUG, "read error\n"));
    448 		egprintpcb(sc);
    449 	} else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)
    450 			printf("eg: configure card command failed.\n");
    451 
    452 	if(sc->eg_inbuf == NULL)
    453 		sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
    454 	sc->eg_incount = 0;
    455 
    456 	if(sc->eg_outbuf == NULL)
    457 		sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
    458 
    459 	ifp->if_flags |= IFF_RUNNING;
    460 	ifp->if_flags &= ~IFF_OACTIVE;
    461 
    462 	outb(sc->eg_ctl, EG_CTL_CMDE);
    463 
    464 	egstart(ifp);
    465 	egrecv(sc);
    466 
    467 	splx(s);
    468 }
    469 
    470 static int
    471 egrecv(sc)
    472 	struct eg_softc *sc;
    473 {
    474 	while (sc->eg_incount < EG_INLEN) {
    475 		sc->eg_pcb[0] = EG_CMD_RECVPACKET;
    476 		sc->eg_pcb[1] = 0x08;
    477 		sc->eg_pcb[2] = 0; /* address not used.. we send zero */
    478 		sc->eg_pcb[3] = 0;
    479 		sc->eg_pcb[4] = 0;
    480 		sc->eg_pcb[5] = 0;
    481 		sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
    482 		sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
    483 		sc->eg_pcb[8] = 0; /* timeout, 0 == none */
    484 		sc->eg_pcb[9] = 0;
    485 		if (egwritePCB(sc) == 0) {
    486 			sc->eg_incount++;
    487 		} else
    488 			break;
    489 	}
    490 }
    491 
    492 static int
    493 egstart(ifp)
    494 	struct ifnet *ifp;
    495 {
    496 	register struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
    497 	struct mbuf *m0, *m;
    498 	int len;
    499 	short *ptr;
    500 
    501 	/* Don't transmit if interface is busy or not running */
    502 	if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
    503 		return 0;
    504 
    505 	/* Dequeue the next datagram. */
    506 	IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
    507 	if (m0 == NULL)
    508 		return 0;
    509 
    510 	sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
    511 
    512 	/* Copy the datagram to the buffer. */
    513 	len = 0;
    514 	for (m = m0; m; m = m->m_next) {
    515 		if (m->m_len == 0)
    516 			continue;
    517 		if (len + m->m_len > EG_BUFLEN) {
    518 			dlog((LOG_DEBUG, "Packet too large to send\n"));
    519 			m_freem(m0);
    520 			sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    521 			sc->sc_arpcom.ac_if.if_oerrors++;
    522 			return 0;
    523 		}
    524 		bcopy(mtod(m, caddr_t), sc->eg_outbuf + len, m->m_len);
    525 		len += m->m_len;
    526 	}
    527 #if NBPFILTER > 0
    528 	if (sc->sc_arpcom.ac_if.if_bpf)
    529 		bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
    530 #endif
    531 	m_freem(m0);
    532 
    533 	/* length must be a minimum of ETHER_MIN_LEN bytes */
    534 	len = max(len, ETHER_MIN_LEN);
    535 
    536 	/* set direction bit: host -> adapter */
    537 	outb(sc->eg_ctl, inb(sc->eg_ctl) & ~EG_CTL_DIR);
    538 
    539 	sc->eg_pcb[0] = EG_CMD_SENDPACKET;
    540 	sc->eg_pcb[1] = 0x06;
    541 	sc->eg_pcb[2] = 0; /* address not used, we send zero */
    542 	sc->eg_pcb[3] = 0;
    543 	sc->eg_pcb[4] = 0;
    544 	sc->eg_pcb[5] = 0;
    545 	sc->eg_pcb[6] = len & 0xff; /* length of packet */
    546 	sc->eg_pcb[7] = (len >> 8) & 0xff;
    547 	if (egwritePCB(sc) == 0) {
    548 		for (ptr = (short *) sc->eg_outbuf; len > 0; len -= 2) {
    549 			outw(sc->eg_data, *ptr++);
    550 			while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
    551 				; /* XXX need timeout here */
    552 		}
    553 	} else {
    554 		dlog((LOG_DEBUG, "egwritePCB in egstart failed\n"));
    555 		sc->sc_arpcom.ac_if.if_oerrors++;
    556 		sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    557 	}
    558 
    559 	/* Set direction bit : Adapter -> host */
    560 	outb(sc->eg_ctl, inb(sc->eg_ctl) | EG_CTL_DIR);
    561 
    562 	return 0;
    563 }
    564 
    565 int
    566 egintr(sc)
    567 	register struct eg_softc *sc;
    568 {
    569 	int i, len;
    570 	short *ptr;
    571 
    572 	while (inb(sc->eg_stat) & EG_STAT_ACRF) {
    573 		egreadPCB(sc);
    574 		switch(sc->eg_pcb[0]) {
    575 		case EG_RSP_RECVPACKET:
    576 			len = sc->eg_pcb[6]+(sc->eg_pcb[7]<<8);
    577 			for (ptr = (short *) sc->eg_inbuf; len > 0; len -= 2) {
    578 				while (!(inb(sc->eg_stat) & EG_STAT_HRDY))
    579 					;
    580 				*ptr++ = inw(sc->eg_data);
    581 			}
    582 			len = sc->eg_pcb[8]+(sc->eg_pcb[9]<<8);
    583 			egrecv(sc);
    584 			sc->sc_arpcom.ac_if.if_ipackets++;
    585 			egread(sc, sc->eg_inbuf, len);
    586 			sc->eg_incount--;
    587 			break;
    588 
    589 		case EG_RSP_SENDPACKET:
    590 			if (sc->eg_pcb[6] || sc->eg_pcb[7]) {
    591 				dlog((LOG_DEBUG, "packet dropped\n"));
    592 				sc->sc_arpcom.ac_if.if_oerrors++;
    593 			}
    594 			sc->sc_arpcom.ac_if.if_opackets++;
    595 			sc->sc_arpcom.ac_if.if_collisions += sc->eg_pcb[8] & 0xf;
    596 			sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    597 			egstart(&sc->sc_arpcom.ac_if);
    598 			break;
    599 
    600 		case EG_RSP_GETSTATS:
    601 			egprintpcb();
    602 			dlog((LOG_DEBUG, "Card Statistics\n"));
    603 			break;
    604 
    605 		default:
    606 			dlog((LOG_DEBUG, "egintr: Unknown response %x??\n",
    607 			      sc->eg_pcb[0]));
    608 			break;
    609 		}
    610 	}
    611 
    612 	return 0;
    613 }
    614 
    615 /*
    616  * Pass a packet up to the higher levels.
    617  */
    618 static inline void
    619 egread(sc, buf, len)
    620 	struct eg_softc *sc;
    621 	caddr_t buf;
    622 	int len;
    623 {
    624 	register struct ether_header *eh;
    625 	struct mbuf *m;
    626 	int i;
    627 
    628 	eh = (struct ether_header *)buf;
    629 	if (len <= sizeof(struct ether_header) ||
    630 	    len > ETHER_MAX_LEN) {
    631 		dlog((LOG_DEBUG, "Unacceptable packet size %d\n", len));
    632 		sc->sc_arpcom.ac_if.if_ierrors++;
    633 		return;
    634 	}
    635 	len -= sizeof(struct ether_header);
    636 
    637 	m = egget(buf, len, &sc->sc_arpcom.ac_if);
    638 	if (m == 0) {
    639 		dlog((LOG_DEBUG, "egget returned 0\n"));
    640 		sc->sc_arpcom.ac_if.if_ierrors++;
    641 		return;
    642 	}
    643 
    644 #if NBPFILTER > 0
    645 	/*
    646 	 * Check if there's a BPF listener on this interface.
    647 	 * If so, hand off the raw packet to bpf.
    648 	 */
    649 	if (sc->sc_arpcom.ac_if.if_bpf) {
    650 		bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);
    651 
    652 		/*
    653 		 * Note that the interface cannot be in promiscuous mode if
    654 		 * there are no BPF listeners.  And if we are in promiscuous
    655 		 * mode, we have to check if this packet is really ours.
    656 		 */
    657 		if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
    658 		    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
    659 		    bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
    660 			    sizeof(eh->ether_dhost)) != 0) {
    661 			m_freem(m);
    662 			return;
    663 		}
    664 	}
    665 #endif
    666 
    667 	ether_input(&sc->sc_arpcom.ac_if, eh, m);
    668 }
    669 
    670 /*
    671  * convert buf into mbufs
    672  */
    673 
    674 static struct mbuf *
    675 egget(buf, totlen, ifp)
    676         caddr_t buf;
    677         int totlen;
    678         struct ifnet *ifp;
    679 {
    680         struct mbuf *top, **mp, *m, *p;
    681         int len;
    682         register caddr_t cp = buf;
    683         char *epkt;
    684 
    685         buf += sizeof(struct ether_header);
    686         cp = buf;
    687         epkt = cp + totlen;
    688 
    689         MGETHDR(m, M_DONTWAIT, MT_DATA);
    690         if (m == 0) {
    691 		dlog((LOG_DEBUG, "MGETHDR returns 0\n"));
    692                 return 0;
    693 	}
    694         m->m_pkthdr.rcvif = ifp;
    695         m->m_pkthdr.len = totlen;
    696         m->m_len = MHLEN;
    697         top = 0;
    698         mp = &top;
    699 
    700         while (totlen > 0) {
    701                 if (top) {
    702                         MGET(m, M_DONTWAIT, MT_DATA);
    703                         if (m == 0) {
    704                                 m_freem(top);
    705 				dlog((LOG_DEBUG, "MGET returns 0\n"));
    706                                 return 0;
    707                         }
    708                         m->m_len = MLEN;
    709                 }
    710                 len = min(totlen, epkt - cp);
    711                 if (len >= MINCLSIZE) {
    712                         MCLGET(m, M_DONTWAIT);
    713                         if (m->m_flags & M_EXT)
    714                                 m->m_len = len = min(len, MCLBYTES);
    715                         else
    716                                 len = m->m_len;
    717                 } else {
    718                         /*
    719                          * Place initial small packet/header at end of mbuf.
    720                          */
    721                         if (len < m->m_len) {
    722                                 if (top == 0 && len + max_linkhdr <= m->m_len)
    723                                         m->m_data += max_linkhdr;
    724                                 m->m_len = len;
    725                         } else
    726                                 len = m->m_len;
    727                 }
    728                 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
    729                 cp += len;
    730                 *mp = m;
    731                 mp = &m->m_next;
    732                 totlen -= len;
    733                 if (cp == epkt)
    734                         cp = buf;
    735         }
    736 
    737         return top;
    738 }
    739 
    740 static int
    741 egioctl(ifp, cmd, data)
    742 	register struct ifnet *ifp;
    743 	int     cmd;
    744 	caddr_t data;
    745 {
    746 	register struct ifaddr *ifa = (struct ifaddr *) data;
    747 	struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
    748 	struct ifreq *ifr = (struct ifreq *) data;
    749 	int error = 0;
    750 
    751 	switch (cmd) {
    752 	case SIOCSIFADDR:
    753 		ifp->if_flags |= IFF_UP;
    754 		switch (ifa->ifa_addr->sa_family) {
    755 #ifdef INET
    756 		case AF_INET:
    757 			eginit(sc);     /* before arpwhohas */
    758 			((struct arpcom *) ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;
    759 			arpwhohas((struct arpcom *) ifp, &IA_SIN(ifa)->sin_addr);
    760 			break;
    761 #endif
    762 #ifdef NS
    763 		case AF_NS:
    764 			{
    765 				register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
    766 
    767 				if (ns_nullhost(*ina))
    768 					ina->x_host =
    769 						*(union ns_host *)(sc->sc_arpcom.ac_enaddr);
    770 				else {
    771 					ifp->if_flags &= ~IFF_RUNNING;
    772 					bcopy(ina->x_host.c_host,
    773 					      sc->sc_arpcom.ac_enaddr,
    774 					      sizeof(sc->sc_arpcom.ac_enaddr));
    775 				}
    776 				eginit(sc);
    777 				break;
    778 			}
    779 #endif
    780 		default:
    781 			eginit(sc);
    782 			break;
    783 		}
    784 		break;
    785 	case SIOCSIFFLAGS:
    786 		if ((ifp->if_flags & IFF_UP) == 0 &&
    787 		    (ifp->if_flags & IFF_RUNNING) != 0) {
    788 			ifp->if_flags &= ~IFF_RUNNING;
    789 			egstop(sc);
    790 			break;
    791 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
    792 			   (ifp->if_flags & IFF_RUNNING) == 0) {
    793 			eginit(sc);
    794 		} else {
    795 			/*
    796 			 * XXX deal with flags changes:
    797 			 * IFF_MULTICAST, IFF_PROMISC,
    798 			 * IFF_LINK0, IFF_LINK1,
    799 			 */
    800 		}
    801 		break;
    802 	default:
    803 		error = EINVAL;
    804 	}
    805 	return (error);
    806 }
    807 
    808 static void
    809 egreset(sc)
    810 	struct eg_softc *sc;
    811 {
    812         int s;
    813 
    814         dlog((LOG_DEBUG, "egreset()\n"));
    815         s = splimp();
    816         egstop(sc);
    817         eginit(sc);
    818         splx(s);
    819 }
    820 
    821 static int
    822 egwatchdog(unit)
    823 	int     unit;
    824 {
    825         struct eg_softc *sc = egcd.cd_devs[unit];
    826 
    827 	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
    828 	sc->sc_arpcom.ac_if.if_oerrors++;
    829 
    830 	egreset(sc);
    831 	return 0;
    832 }
    833 
    834 static void
    835 egstop(sc)
    836 	register struct eg_softc *sc;
    837 {
    838 
    839 	outb(sc->eg_ctl, 0);
    840 }
    841