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