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