This source file includes following definitions.
- ether_cmp
- am7990_config
- am7990_reset
- am7990_meminit
- am7990_stop
- am7990_init
- am7990_put
- am7990_get
- am7990_read
- am7990_rint
- am7990_tint
- am7990_intr
- am7990_watchdog
- am7990_start
- am7990_ioctl
- am7990_shutdown
- am7990_recv_print
- am7990_xmit_print
- am7990_setladrf
- am7990_copytobuf_contig
- am7990_copyfrombuf_contig
- am7990_zerobuf_contig
- am7990_copytobuf_gap2
- am7990_copyfrombuf_gap2
- am7990_zerobuf_gap2
- am7990_copytobuf_gap16
- am7990_copyfrombuf_gap16
- am7990_zerobuf_gap16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include "bpfilter.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/mbuf.h>
44 #include <sys/syslog.h>
45 #include <sys/socket.h>
46 #include <sys/device.h>
47 #include <sys/malloc.h>
48 #include <sys/ioctl.h>
49 #include <sys/errno.h>
50
51 #include <net/if.h>
52 #include <net/if_media.h>
53
54 #ifdef INET
55 #include <netinet/in.h>
56 #include <netinet/if_ether.h>
57 #include <netinet/in_systm.h>
58 #include <netinet/in_var.h>
59 #include <netinet/ip.h>
60 #endif
61
62 #if NBPFILTER > 0
63 #include <net/bpf.h>
64 #endif
65
66 #include <dev/ic/am7990reg.h>
67 #include <dev/ic/am7990var.h>
68
69 #ifdef LEDEBUG
70 void am7990_recv_print(struct am7990_softc *, int);
71 void am7990_xmit_print(struct am7990_softc *, int);
72 #endif
73
74 integrate void am7990_rint(struct am7990_softc *);
75 integrate void am7990_tint(struct am7990_softc *);
76
77 integrate int am7990_put(struct am7990_softc *, int, struct mbuf *);
78 integrate struct mbuf *am7990_get(struct am7990_softc *, int, int);
79 integrate void am7990_read(struct am7990_softc *, int, int);
80
81 hide void am7990_shutdown(void *);
82
83 #define ifp (&sc->sc_arpcom.ac_if)
84
85 #if 0
86 static inline u_int16_t ether_cmp(void *, void *);
87
88
89
90
91
92
93
94
95
96 static inline u_short
97 ether_cmp(one, two)
98 void *one, *two;
99 {
100 register u_int16_t *a = (u_short *) one;
101 register u_int16_t *b = (u_short *) two;
102 register u_int16_t diff;
103
104 diff = *a++ - *b++;
105 diff |= *a++ - *b++;
106 diff |= *a++ - *b++;
107
108 return (diff);
109 }
110
111 #define ETHER_CMP ether_cmp
112 #endif
113
114 #ifndef ETHER_CMP
115 #define ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN)
116 #endif
117
118
119
120
121
122 struct cfdriver le_cd = {
123 NULL, "le", DV_IFNET
124 };
125
126 void
127 am7990_config(sc)
128 struct am7990_softc *sc;
129 {
130 int mem;
131
132
133 am7990_stop(sc);
134
135
136 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
137 ifp->if_softc = sc;
138 ifp->if_start = am7990_start;
139 ifp->if_ioctl = am7990_ioctl;
140 ifp->if_watchdog = am7990_watchdog;
141 ifp->if_flags =
142 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
143 #ifdef LANCE_REVC_BUG
144 ifp->if_flags &= ~IFF_MULTICAST;
145 #endif
146 ifp->if_baudrate = IF_Mbps(10);
147 IFQ_SET_READY(&ifp->if_snd);
148
149 ifp->if_capabilities = IFCAP_VLAN_MTU;
150
151
152 if_attach(ifp);
153 ether_ifattach(ifp);
154
155 if (sc->sc_memsize > 262144)
156 sc->sc_memsize = 262144;
157
158 switch (sc->sc_memsize) {
159 case 8192:
160 sc->sc_nrbuf = 4;
161 sc->sc_ntbuf = 1;
162 break;
163 case 16384:
164 sc->sc_nrbuf = 8;
165 sc->sc_ntbuf = 2;
166 break;
167 case 32768:
168 sc->sc_nrbuf = 16;
169 sc->sc_ntbuf = 4;
170 break;
171 case 65536:
172 sc->sc_nrbuf = 32;
173 sc->sc_ntbuf = 8;
174 break;
175 case 131072:
176 sc->sc_nrbuf = 64;
177 sc->sc_ntbuf = 16;
178 break;
179 case 262144:
180 sc->sc_nrbuf = 128;
181 sc->sc_ntbuf = 32;
182 break;
183 default:
184 panic("am7990_config: weird memory size %lu", sc->sc_memsize);
185 }
186
187 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
188 printf("%s: %d receive buffers, %d transmit buffers\n",
189 sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
190
191 sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc);
192 if (sc->sc_sh == NULL)
193 panic("am7990_config: can't establish shutdownhook");
194
195 mem = 0;
196 sc->sc_initaddr = mem;
197 mem += sizeof(struct leinit);
198 sc->sc_rmdaddr = mem;
199 mem += sizeof(struct lermd) * sc->sc_nrbuf;
200 sc->sc_tmdaddr = mem;
201 mem += sizeof(struct letmd) * sc->sc_ntbuf;
202 sc->sc_rbufaddr = mem;
203 mem += ETHER_MAX_DIX_LEN * sc->sc_nrbuf;
204 sc->sc_tbufaddr = mem;
205 mem += ETHER_MAX_DIX_LEN * sc->sc_ntbuf;
206 #ifdef notyet
207 if (mem > ...)
208 panic(...);
209 #endif
210 }
211
212 void
213 am7990_reset(sc)
214 struct am7990_softc *sc;
215 {
216 int s;
217
218 s = splnet();
219 am7990_init(sc);
220 splx(s);
221 }
222
223
224
225
226 void
227 am7990_meminit(sc)
228 register struct am7990_softc *sc;
229 {
230 u_long a;
231 int bix;
232 struct leinit init;
233 struct lermd rmd;
234 struct letmd tmd;
235
236 #if NBPFILTER > 0
237 if (ifp->if_flags & IFF_PROMISC)
238 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
239 else
240 #endif
241 init.init_mode = LE_MODE_NORMAL;
242 init.init_padr[0] =
243 (sc->sc_arpcom.ac_enaddr[1] << 8) | sc->sc_arpcom.ac_enaddr[0];
244 init.init_padr[1] =
245 (sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2];
246 init.init_padr[2] =
247 (sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4];
248 am7990_setladrf(&sc->sc_arpcom, init.init_ladrf);
249
250 sc->sc_last_rd = 0;
251 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
252
253 a = sc->sc_addr + LE_RMDADDR(sc, 0);
254 init.init_rdra = a;
255 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
256
257 a = sc->sc_addr + LE_TMDADDR(sc, 0);
258 init.init_tdra = a;
259 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
260
261 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
262
263
264
265
266 for (bix = 0; bix < sc->sc_nrbuf; bix++) {
267 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
268 rmd.rmd0 = a;
269 rmd.rmd1_hadr = a >> 16;
270 rmd.rmd1_bits = LE_R1_OWN;
271 rmd.rmd2 = -ETHER_MAX_DIX_LEN | LE_XMD2_ONES;
272 rmd.rmd3 = 0;
273 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
274 sizeof(rmd));
275 }
276
277
278
279
280 for (bix = 0; bix < sc->sc_ntbuf; bix++) {
281 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
282 tmd.tmd0 = a;
283 tmd.tmd1_hadr = a >> 16;
284 tmd.tmd1_bits = 0;
285 tmd.tmd2 = 0 | LE_XMD2_ONES;
286 tmd.tmd3 = 0;
287 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
288 sizeof(tmd));
289 }
290 }
291
292 void
293 am7990_stop(sc)
294 struct am7990_softc *sc;
295 {
296
297 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
298 }
299
300
301
302
303
304 void
305 am7990_init(sc)
306 register struct am7990_softc *sc;
307 {
308 register int timo;
309 u_long a;
310
311 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
312 DELAY(100);
313
314
315 if (sc->sc_hwreset)
316 (*sc->sc_hwreset)(sc);
317
318
319 (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
320
321
322 am7990_meminit(sc);
323
324
325 a = sc->sc_addr + LE_INITADDR(sc);
326 (*sc->sc_wrcsr)(sc, LE_CSR1, a);
327 (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
328
329
330 DELAY(100);
331 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
332
333
334 for (timo = 100000; timo; timo--)
335 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
336 break;
337
338 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
339
340 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |
341 LE_C0_IDON);
342 ifp->if_flags |= IFF_RUNNING;
343 ifp->if_flags &= ~IFF_OACTIVE;
344 ifp->if_timer = 0;
345 am7990_start(ifp);
346 } else
347 printf("%s: controller failed to initialize\n", sc->sc_dev.dv_xname);
348 if (sc->sc_hwinit)
349 (*sc->sc_hwinit)(sc);
350 }
351
352
353
354
355
356 integrate int
357 am7990_put(sc, boff, m)
358 struct am7990_softc *sc;
359 int boff;
360 register struct mbuf *m;
361 {
362 register struct mbuf *n;
363 register int len, tlen = 0;
364
365 for (; m; m = n) {
366 len = m->m_len;
367 if (len == 0) {
368 MFREE(m, n);
369 continue;
370 }
371 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);
372 boff += len;
373 tlen += len;
374 MFREE(m, n);
375 }
376 if (tlen < LEMINSIZE) {
377 (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
378 tlen = LEMINSIZE;
379 }
380 return (tlen);
381 }
382
383
384
385
386
387
388
389 integrate struct mbuf *
390 am7990_get(sc, boff, totlen)
391 struct am7990_softc *sc;
392 int boff, totlen;
393 {
394 register struct mbuf *m;
395 struct mbuf *top, **mp;
396 int len, pad;
397
398 MGETHDR(m, M_DONTWAIT, MT_DATA);
399 if (m == 0)
400 return (0);
401 m->m_pkthdr.rcvif = ifp;
402 m->m_pkthdr.len = totlen;
403 pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
404 m->m_data += pad;
405 len = MHLEN - pad;
406 top = 0;
407 mp = ⊤
408
409 while (totlen > 0) {
410 if (top) {
411 MGET(m, M_DONTWAIT, MT_DATA);
412 if (m == 0) {
413 m_freem(top);
414 return 0;
415 }
416 len = MLEN;
417 }
418 if (totlen >= MINCLSIZE) {
419 MCLGET(m, M_DONTWAIT);
420 if (m->m_flags & M_EXT) {
421 len = MCLBYTES;
422 if (!top) {
423 m->m_data += pad;
424 len -= pad;
425 }
426 }
427 }
428 m->m_len = len = min(totlen, len);
429 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);
430 boff += len;
431 totlen -= len;
432 *mp = m;
433 mp = &m->m_next;
434 }
435
436 return (top);
437 }
438
439
440
441
442 integrate void
443 am7990_read(sc, boff, len)
444 register struct am7990_softc *sc;
445 int boff, len;
446 {
447 struct mbuf *m;
448 #ifdef LANCE_REVC_BUG
449 struct ether_header *eh;
450 #endif
451
452 if (len <= sizeof(struct ether_header) ||
453 len > ETHERMTU + ETHER_VLAN_ENCAP_LEN + sizeof(struct ether_header)) {
454 #ifdef LEDEBUG
455 printf("%s: invalid packet size %d; dropping\n",
456 sc->sc_dev.dv_xname, len);
457 #endif
458 ifp->if_ierrors++;
459 return;
460 }
461
462
463 m = am7990_get(sc, boff, len);
464 if (m == 0) {
465 ifp->if_ierrors++;
466 return;
467 }
468
469 ifp->if_ipackets++;
470
471 #if NBPFILTER > 0
472
473
474
475
476 if (ifp->if_bpf)
477 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
478 #endif
479
480 #ifdef LANCE_REVC_BUG
481
482
483
484
485
486
487
488 eh = mtod(m, struct ether_header *);
489 if (ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr) &&
490 ETHER_CMP(eh->ether_dhost, etherbroadcastaddr)) {
491 m_freem(m);
492 return;
493 }
494 #endif
495
496
497 ether_input_mbuf(ifp, m);
498 }
499
500 integrate void
501 am7990_rint(sc)
502 struct am7990_softc *sc;
503 {
504 register int bix;
505 int rp;
506 struct lermd rmd;
507
508 bix = sc->sc_last_rd;
509
510
511 for (;;) {
512 rp = LE_RMDADDR(sc, bix);
513 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
514
515 if (rmd.rmd1_bits & LE_R1_OWN)
516 break;
517
518 if (rmd.rmd1_bits & LE_R1_ERR) {
519 if (rmd.rmd1_bits & LE_R1_ENP) {
520 #ifdef LEDEBUG
521 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
522 if (rmd.rmd1_bits & LE_R1_FRAM)
523 printf("%s: framing error\n",
524 sc->sc_dev.dv_xname);
525 if (rmd.rmd1_bits & LE_R1_CRC)
526 printf("%s: crc mismatch\n",
527 sc->sc_dev.dv_xname);
528 }
529 #endif
530 } else {
531 if (rmd.rmd1_bits & LE_R1_OFLO)
532 printf("%s: overflow\n",
533 sc->sc_dev.dv_xname);
534 }
535 if (rmd.rmd1_bits & LE_R1_BUFF)
536 printf("%s: receive buffer error\n",
537 sc->sc_dev.dv_xname);
538 ifp->if_ierrors++;
539 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
540 (LE_R1_STP | LE_R1_ENP)) {
541 printf("%s: dropping chained buffer\n",
542 sc->sc_dev.dv_xname);
543 ifp->if_ierrors++;
544 } else {
545 #ifdef LEDEBUG1
546 if (sc->sc_debug)
547 am7990_recv_print(sc, sc->sc_last_rd);
548 #endif
549 am7990_read(sc, LE_RBUFADDR(sc, bix),
550 (int)rmd.rmd3 - 4);
551 }
552
553 rmd.rmd1_bits = LE_R1_OWN;
554 rmd.rmd2 = -ETHER_MAX_DIX_LEN | LE_XMD2_ONES;
555 rmd.rmd3 = 0;
556 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
557
558 #ifdef LEDEBUG1
559 if (sc->sc_debug)
560 printf("sc->sc_last_rd = %x, rmd: "
561 "ladr %04x, hadr %02x, flags %02x, "
562 "bcnt %04x, mcnt %04x\n",
563 sc->sc_last_rd,
564 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
565 rmd.rmd2, rmd.rmd3);
566 #endif
567
568 if (++bix == sc->sc_nrbuf)
569 bix = 0;
570 }
571
572 sc->sc_last_rd = bix;
573 }
574
575 integrate void
576 am7990_tint(sc)
577 register struct am7990_softc *sc;
578 {
579 register int bix;
580 struct letmd tmd;
581
582 bix = sc->sc_first_td;
583
584 for (;;) {
585 if (sc->sc_no_td <= 0)
586 break;
587
588 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
589 sizeof(tmd));
590
591 #ifdef LEDEBUG
592 if (sc->sc_debug)
593 printf("trans tmd: "
594 "ladr %04x, hadr %02x, flags %02x, "
595 "bcnt %04x, mcnt %04x\n",
596 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
597 tmd.tmd2, tmd.tmd3);
598 #endif
599
600 if (tmd.tmd1_bits & LE_T1_OWN)
601 break;
602
603 ifp->if_flags &= ~IFF_OACTIVE;
604
605 if (tmd.tmd1_bits & LE_T1_ERR) {
606 if (tmd.tmd3 & LE_T3_BUFF)
607 printf("%s: transmit buffer error\n",
608 sc->sc_dev.dv_xname);
609 else if (tmd.tmd3 & LE_T3_UFLO)
610 printf("%s: underflow\n", sc->sc_dev.dv_xname);
611 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
612 am7990_reset(sc);
613 return;
614 }
615 if (tmd.tmd3 & LE_T3_LCAR) {
616 if (sc->sc_nocarrier)
617 (*sc->sc_nocarrier)(sc);
618 }
619 if (tmd.tmd3 & LE_T3_LCOL)
620 ifp->if_collisions++;
621 if (tmd.tmd3 & LE_T3_RTRY) {
622 printf("%s: excessive collisions, tdr %d\n",
623 sc->sc_dev.dv_xname,
624 tmd.tmd3 & LE_T3_TDR_MASK);
625 ifp->if_collisions += 16;
626 }
627 ifp->if_oerrors++;
628 } else {
629 if (tmd.tmd1_bits & LE_T1_ONE)
630 ifp->if_collisions++;
631 else if (tmd.tmd1_bits & LE_T1_MORE)
632
633 ifp->if_collisions += 2;
634 ifp->if_opackets++;
635 }
636
637 if (++bix == sc->sc_ntbuf)
638 bix = 0;
639
640 --sc->sc_no_td;
641 }
642
643 sc->sc_first_td = bix;
644
645 am7990_start(ifp);
646
647 if (sc->sc_no_td == 0)
648 ifp->if_timer = 0;
649 }
650
651
652
653
654 int
655 am7990_intr(arg)
656 register void *arg;
657 {
658 register struct am7990_softc *sc = arg;
659 register u_int16_t isr;
660
661 isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
662 #ifdef LEDEBUG
663 if (sc->sc_debug){
664 printf("%s: am7990_intr entering with isr=%04x\n",
665 sc->sc_dev.dv_xname, isr);
666 printf(" isr: 0x%b\n", isr, LE_C0_BITS);
667 }
668 #endif
669 if ((isr & LE_C0_INTR) == 0)
670 return (0);
671
672
673
674
675
676
677 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~LE_C0_INEA);
678 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
679
680 if (isr & LE_C0_ERR) {
681 if (isr & LE_C0_BABL) {
682 #ifdef LEDEBUG
683 printf("%s: babble\n", sc->sc_dev.dv_xname);
684 #endif
685 ifp->if_oerrors++;
686 }
687 #if 0
688 if (isr & LE_C0_CERR) {
689 printf("%s: collision error\n", sc->sc_dev.dv_xname);
690 ifp->if_collisions++;
691 }
692 #endif
693 if (isr & LE_C0_MISS) {
694 #ifdef LEDEBUG
695 printf("%s: missed packet\n", sc->sc_dev.dv_xname);
696 #endif
697 ifp->if_ierrors++;
698 }
699 if (isr & LE_C0_MERR) {
700 printf("%s: memory error\n", sc->sc_dev.dv_xname);
701 am7990_reset(sc);
702 return (1);
703 }
704 }
705
706 if ((isr & LE_C0_RXON) == 0) {
707 printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
708 ifp->if_ierrors++;
709 am7990_reset(sc);
710 return (1);
711 }
712 if ((isr & LE_C0_TXON) == 0) {
713 printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
714 ifp->if_oerrors++;
715 am7990_reset(sc);
716 return (1);
717 }
718
719 if (isr & LE_C0_RINT)
720 am7990_rint(sc);
721 if (isr & LE_C0_TINT)
722 am7990_tint(sc);
723
724 return (1);
725 }
726
727 #undef ifp
728
729 void
730 am7990_watchdog(ifp)
731 struct ifnet *ifp;
732 {
733 struct am7990_softc *sc = ifp->if_softc;
734
735 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
736 ++ifp->if_oerrors;
737
738 am7990_reset(sc);
739 }
740
741
742
743
744
745
746
747 void
748 am7990_start(ifp)
749 register struct ifnet *ifp;
750 {
751 register struct am7990_softc *sc = ifp->if_softc;
752 register int bix;
753 register struct mbuf *m;
754 struct letmd tmd;
755 int rp;
756 int len;
757
758 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
759 return;
760
761 bix = sc->sc_last_td;
762
763 for (;;) {
764 rp = LE_TMDADDR(sc, bix);
765 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
766
767 if (tmd.tmd1_bits & LE_T1_OWN) {
768 ifp->if_flags |= IFF_OACTIVE;
769 printf("missing buffer, no_td = %d, last_td = %d\n",
770 sc->sc_no_td, sc->sc_last_td);
771 }
772
773 IFQ_DEQUEUE(&ifp->if_snd, m);
774 if (m == 0)
775 break;
776
777 #if NBPFILTER > 0
778
779
780
781
782 if (ifp->if_bpf)
783 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
784 #endif
785
786
787
788
789 len = am7990_put(sc, LE_TBUFADDR(sc, bix), m);
790
791 #ifdef LEDEBUG
792 if (len > ETHERMTU + sizeof(struct ether_header))
793 printf("packet length %d\n", len);
794 #endif
795
796 ifp->if_timer = 5;
797
798
799
800
801 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
802 tmd.tmd2 = -len | LE_XMD2_ONES;
803 tmd.tmd3 = 0;
804
805 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
806
807 #ifdef LEDEBUG
808 if (sc->sc_debug)
809 am7990_xmit_print(sc, sc->sc_last_td);
810 #endif
811
812 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
813
814 if (++bix == sc->sc_ntbuf)
815 bix = 0;
816
817 if (++sc->sc_no_td == sc->sc_ntbuf) {
818 #ifdef LEDEBUG
819 printf("\nequal!\n");
820 #endif
821 ifp->if_flags |= IFF_OACTIVE;
822 break;
823 }
824
825 }
826
827 sc->sc_last_td = bix;
828 }
829
830
831
832
833 int
834 am7990_ioctl(ifp, cmd, data)
835 register struct ifnet *ifp;
836 u_long cmd;
837 caddr_t data;
838 {
839 register struct am7990_softc *sc = ifp->if_softc;
840 struct ifaddr *ifa = (struct ifaddr *)data;
841 struct ifreq *ifr = (struct ifreq *)data;
842 int s, error = 0;
843
844 s = splnet();
845
846 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
847 splx(s);
848 return error;
849 }
850
851 switch (cmd) {
852
853 case SIOCSIFADDR:
854 ifp->if_flags |= IFF_UP;
855
856 switch (ifa->ifa_addr->sa_family) {
857 #ifdef INET
858 case AF_INET:
859 am7990_init(sc);
860 arp_ifinit(&sc->sc_arpcom, ifa);
861 break;
862 #endif
863 default:
864 am7990_init(sc);
865 break;
866 }
867 break;
868
869 case SIOCSIFFLAGS:
870 if ((ifp->if_flags & IFF_UP) == 0 &&
871 (ifp->if_flags & IFF_RUNNING) != 0) {
872
873
874
875
876 am7990_stop(sc);
877 ifp->if_flags &= ~IFF_RUNNING;
878 } else if ((ifp->if_flags & IFF_UP) != 0 &&
879 (ifp->if_flags & IFF_RUNNING) == 0) {
880
881
882
883
884 am7990_init(sc);
885 } else {
886
887
888
889
890
891 am7990_init(sc);
892 }
893 #ifdef LEDEBUG
894 if (ifp->if_flags & IFF_DEBUG)
895 sc->sc_debug = 1;
896 else
897 sc->sc_debug = 0;
898 #endif
899 break;
900
901 case SIOCADDMULTI:
902 case SIOCDELMULTI:
903 error = (cmd == SIOCADDMULTI) ?
904 ether_addmulti(ifr, &sc->sc_arpcom) :
905 ether_delmulti(ifr, &sc->sc_arpcom);
906
907 if (error == ENETRESET) {
908
909
910
911
912 if (ifp->if_flags & IFF_RUNNING)
913 am7990_reset(sc);
914 error = 0;
915 }
916 break;
917
918 case SIOCGIFMEDIA:
919 case SIOCSIFMEDIA:
920 if (sc->sc_hasifmedia)
921 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
922 else
923 error = EINVAL;
924 break;
925
926 default:
927 error = EINVAL;
928 break;
929 }
930
931 splx(s);
932 return (error);
933 }
934
935 hide void
936 am7990_shutdown(arg)
937 void *arg;
938 {
939
940 am7990_stop((struct am7990_softc *)arg);
941 }
942
943 #ifdef LEDEBUG
944 void
945 am7990_recv_print(sc, no)
946 struct am7990_softc *sc;
947 int no;
948 {
949 struct lermd rmd;
950 u_int16_t len;
951 struct ether_header eh;
952
953 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
954 len = rmd.rmd3;
955 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
956 len);
957 printf("%s: status %04x\n", sc->sc_dev.dv_xname,
958 (*sc->sc_rdcsr)(sc, LE_CSR0));
959 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
960 sc->sc_dev.dv_xname,
961 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
962 if (len >= sizeof(eh)) {
963 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
964 printf("%s: dst %s", sc->sc_dev.dv_xname,
965 ether_sprintf(eh.ether_dhost));
966 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
967 ntohs(eh.ether_type));
968 }
969 }
970
971 void
972 am7990_xmit_print(sc, no)
973 struct am7990_softc *sc;
974 int no;
975 {
976 struct letmd tmd;
977 u_int16_t len;
978 struct ether_header eh;
979
980 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
981 len = -tmd.tmd2;
982 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
983 len);
984 printf("%s: status %04x\n", sc->sc_dev.dv_xname,
985 (*sc->sc_rdcsr)(sc, LE_CSR0));
986 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
987 sc->sc_dev.dv_xname,
988 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
989 if (len >= sizeof(eh)) {
990 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
991 printf("%s: dst %s", sc->sc_dev.dv_xname,
992 ether_sprintf(eh.ether_dhost));
993 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
994 ntohs(eh.ether_type));
995 }
996 }
997 #endif
998
999
1000
1001
1002 void
1003 am7990_setladrf(ac, af)
1004 struct arpcom *ac;
1005 u_int16_t *af;
1006 {
1007 struct ifnet *ifp = &ac->ac_if;
1008 struct ether_multi *enm;
1009 register u_int32_t crc;
1010 struct ether_multistep step;
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 if (ifp->if_flags & IFF_PROMISC)
1021 goto allmulti;
1022
1023 af[0] = af[1] = af[2] = af[3] = 0x0000;
1024 ETHER_FIRST_MULTI(step, ac, enm);
1025 while (enm != NULL) {
1026 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
1027
1028
1029
1030
1031
1032
1033
1034
1035 goto allmulti;
1036 }
1037
1038 crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
1039
1040
1041 af[crc >> 4] |= 1 << (crc & 0xf);
1042
1043 ETHER_NEXT_MULTI(step, enm);
1044 }
1045 ifp->if_flags &= ~IFF_ALLMULTI;
1046 return;
1047
1048 allmulti:
1049 ifp->if_flags |= IFF_ALLMULTI;
1050 af[0] = af[1] = af[2] = af[3] = 0xffff;
1051 }
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 void
1071 am7990_copytobuf_contig(sc, from, boff, len)
1072 struct am7990_softc *sc;
1073 void *from;
1074 int boff, len;
1075 {
1076 volatile caddr_t buf = sc->sc_mem;
1077
1078
1079
1080
1081 bcopy(from, buf + boff, len);
1082 }
1083
1084 void
1085 am7990_copyfrombuf_contig(sc, to, boff, len)
1086 struct am7990_softc *sc;
1087 void *to;
1088 int boff, len;
1089 {
1090 volatile caddr_t buf = sc->sc_mem;
1091
1092
1093
1094
1095 bcopy(buf + boff, to, len);
1096 }
1097
1098 void
1099 am7990_zerobuf_contig(sc, boff, len)
1100 struct am7990_softc *sc;
1101 int boff, len;
1102 {
1103 volatile caddr_t buf = sc->sc_mem;
1104
1105
1106
1107
1108 bzero(buf + boff, len);
1109 }
1110
1111 #if 0
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124 void
1125 am7990_copytobuf_gap2(sc, fromv, boff, len)
1126 struct am7990_softc *sc;
1127 void *fromv;
1128 int boff;
1129 register int len;
1130 {
1131 volatile caddr_t buf = sc->sc_mem;
1132 register caddr_t from = fromv;
1133 register volatile u_int16_t *bptr;
1134
1135 if (boff & 0x1) {
1136
1137 bptr = ((volatile u_int16_t *)buf) + (boff - 1);
1138 *bptr = (*from++ << 8) | (*bptr & 0xff);
1139 bptr += 2;
1140 len--;
1141 } else
1142 bptr = ((volatile u_int16_t *)buf) + boff;
1143 while (len > 1) {
1144 *bptr = (from[1] << 8) | (from[0] & 0xff);
1145 bptr += 2;
1146 from += 2;
1147 len -= 2;
1148 }
1149 if (len == 1)
1150 *bptr = (u_int16_t)*from;
1151 }
1152
1153 void
1154 am7990_copyfrombuf_gap2(sc, tov, boff, len)
1155 struct am7990_softc *sc;
1156 void *tov;
1157 int boff, len;
1158 {
1159 volatile caddr_t buf = sc->sc_mem;
1160 register caddr_t to = tov;
1161 register volatile u_int16_t *bptr;
1162 register u_int16_t tmp;
1163
1164 if (boff & 0x1) {
1165
1166 bptr = ((volatile u_int16_t *)buf) + (boff - 1);
1167 *to++ = (*bptr >> 8) & 0xff;
1168 bptr += 2;
1169 len--;
1170 } else
1171 bptr = ((volatile u_int16_t *)buf) + boff;
1172 while (len > 1) {
1173 tmp = *bptr;
1174 *to++ = tmp & 0xff;
1175 *to++ = (tmp >> 8) & 0xff;
1176 bptr += 2;
1177 len -= 2;
1178 }
1179 if (len == 1)
1180 *to = *bptr & 0xff;
1181 }
1182
1183 void
1184 am7990_zerobuf_gap2(sc, boff, len)
1185 struct am7990_softc *sc;
1186 int boff, len;
1187 {
1188 volatile caddr_t buf = sc->sc_mem;
1189 register volatile u_int16_t *bptr;
1190
1191 if ((unsigned)boff & 0x1) {
1192 bptr = ((volatile u_int16_t *)buf) + (boff - 1);
1193 *bptr &= 0xff;
1194 bptr += 2;
1195 len--;
1196 } else
1197 bptr = ((volatile u_int16_t *)buf) + boff;
1198 while (len > 0) {
1199 *bptr = 0;
1200 bptr += 2;
1201 len -= 2;
1202 }
1203 }
1204
1205
1206
1207
1208
1209
1210
1211 void
1212 am7990_copytobuf_gap16(sc, fromv, boff, len)
1213 struct am7990_softc *sc;
1214 void *fromv;
1215 int boff;
1216 register int len;
1217 {
1218 volatile caddr_t buf = sc->sc_mem;
1219 register caddr_t from = fromv;
1220 register caddr_t bptr;
1221 register int xfer;
1222
1223 bptr = buf + ((boff << 1) & ~0x1f);
1224 boff &= 0xf;
1225 xfer = min(len, 16 - boff);
1226 while (len > 0) {
1227 bcopy(from, bptr + boff, xfer);
1228 from += xfer;
1229 bptr += 32;
1230 boff = 0;
1231 len -= xfer;
1232 xfer = min(len, 16);
1233 }
1234 }
1235
1236 void
1237 am7990_copyfrombuf_gap16(sc, tov, boff, len)
1238 struct am7990_softc *sc;
1239 void *tov;
1240 int boff, len;
1241 {
1242 volatile caddr_t buf = sc->sc_mem;
1243 register caddr_t to = tov;
1244 register caddr_t bptr;
1245 register int xfer;
1246
1247 bptr = buf + ((boff << 1) & ~0x1f);
1248 boff &= 0xf;
1249 xfer = min(len, 16 - boff);
1250 while (len > 0) {
1251 bcopy(bptr + boff, to, xfer);
1252 to += xfer;
1253 bptr += 32;
1254 boff = 0;
1255 len -= xfer;
1256 xfer = min(len, 16);
1257 }
1258 }
1259
1260 void
1261 am7990_zerobuf_gap16(sc, boff, len)
1262 struct am7990_softc *sc;
1263 int boff, len;
1264 {
1265 volatile caddr_t buf = sc->sc_mem;
1266 register caddr_t bptr;
1267 register int xfer;
1268
1269 bptr = buf + ((boff << 1) & ~0x1f);
1270 boff &= 0xf;
1271 xfer = min(len, 16 - boff);
1272 while (len > 0) {
1273 bzero(bptr + boff, xfer);
1274 bptr += 32;
1275 boff = 0;
1276 len -= xfer;
1277 xfer = min(len, 16);
1278 }
1279 }
1280 #endif