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