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