This source file includes following definitions.
- en_read
- en_write
- en_k2sz
- en_b2sz
- en_sz2b
- en_dqneed
- en_mget
- en_attach
- en_dmaprobe
- en_dmaprobe_doit
- en_ioctl
- en_rxctl
- en_reset
- en_init
- en_loadvc
- en_start
- en_mfix
- en_txdma
- en_txlaunch
- en_intr
- en_service
- en_dump
- en_dumpmem
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
40
41
42
43
44
45
46
47
48
49
50
51 #undef EN_DEBUG
52 #undef EN_DEBUG_RANGE
53 #define EN_MBUF_OPT
54 #define EN_DIAG
55 #define EN_STAT
56 #ifndef EN_DMA
57 #define EN_DMA 1
58 #endif
59 #define EN_NOTXDMA 0
60 #define EN_NORXDMA 0
61 #define EN_NOWMAYBE 1
62
63 #define EN_DDBHOOK 1
64 #if defined(MIDWAY_ADPONLY)
65 #define EN_ENIDMAFIX 0
66 #else
67 #define EN_ENIDMAFIX 1
68 #endif
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 #if defined(DIAGNOSTIC) && !defined(EN_DIAG)
93 #define EN_DIAG
94 #endif
95 #ifdef EN_STAT
96 #define EN_COUNT(X) (X)++
97 #else
98 #define EN_COUNT(X)
99 #endif
100
101 #ifdef EN_DEBUG
102 #undef EN_DDBHOOK
103 #define EN_DDBHOOK 1
104 #define STATIC
105 #define INLINE
106 #else
107 #define STATIC static
108 #define INLINE inline
109 #endif
110
111 #include "bpfilter.h"
112
113 #ifdef __FreeBSD__
114 #include "en.h"
115 #endif
116
117 #if NEN > 0 || !defined(__FreeBSD__)
118
119 #include <sys/param.h>
120 #include <sys/systm.h>
121 #include <sys/types.h>
122 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
123 #include <sys/device.h>
124 #endif
125 #if defined(__FreeBSD__)
126 #include <sys/sockio.h>
127 #else
128 #include <sys/ioctl.h>
129 #endif
130 #include <sys/mbuf.h>
131 #include <sys/socket.h>
132 #include <sys/socketvar.h>
133
134 #include <net/if.h>
135 #include <net/if_atm.h>
136
137 #include <uvm/uvm_extern.h>
138
139 #ifdef INET
140 #include <netinet/if_atm.h>
141 #endif
142
143 #ifdef NATM
144 #include <netinet/in.h>
145 #include <netnatm/natm.h>
146 #endif
147
148
149 #if !defined(__sparc__) && !defined(__FreeBSD__)
150 #include <machine/bus.h>
151 #endif
152
153 #if defined(__NetBSD__) || defined(__OpenBSD__)
154 #include <dev/ic/midwayreg.h>
155 #include <dev/ic/midwayvar.h>
156 #if defined(__alpha__)
157
158 #undef vtophys
159 #define vtophys(va) alpha_XXX_dmamap((vaddr_t)(va))
160 #endif
161 #elif defined(__FreeBSD__)
162 #include <machine/cpufunc.h>
163 #include <machine/clock.h>
164 #include <dev/en/midwayreg.h>
165 #include <dev/en/midwayvar.h>
166 #include <vm/pmap.h>
167
168
169
170
171
172 #ifdef IFF_NOTRAILERS
173 #define MISSING_IF_SOFTC
174 #else
175 #define IFF_NOTRAILERS 0
176 #endif
177
178 #endif
179
180 #if NBPFILTER > 0
181 #include <net/bpf.h>
182 #endif
183
184
185
186
187
188 #ifndef EN_TXHIWAT
189 #define EN_TXHIWAT (64*1024)
190 #endif
191
192 #ifndef EN_MINDMA
193 #define EN_MINDMA 32
194 #endif
195
196 #define RX_NONE 0xffff
197
198 #define EN_OBHDR ATM_PH_DRIVER7
199 #define EN_OBTRL ATM_PH_DRIVER8
200
201 #define ENOTHER_FREE 0x01
202 #define ENOTHER_DRAIN 0x02
203 #define ENOTHER_RAW 0x04
204 #define ENOTHER_SWSL 0x08
205
206 int en_dma = EN_DMA;
207
208
209
210
211
212 struct cfdriver en_cd = {
213 0, "en", DV_IFNET,
214 };
215
216
217
218
219
220
221
222
223
224 struct en_launch {
225 u_int32_t tbd1;
226 u_int32_t tbd2;
227 u_int32_t pdu1;
228 int nodma;
229 int need;
230 int mlen;
231 struct mbuf *t;
232 u_int32_t aal;
233 u_int32_t atm_vci;
234 u_int8_t atm_flags;
235 };
236
237
238
239
240
241
242
243
244
245 struct en_dmatab {
246 u_int8_t bcode;
247 u_int8_t divshift;
248 };
249
250 static struct en_dmatab en_dma_planA[] = {
251 { 0, 0 }, { MIDDMA_WORD, 2 },
252 { MIDDMA_2WORD, 3}, { MIDDMA_4WMAYBE, 2},
253 { MIDDMA_4WORD, 4}, { MIDDMA_8WMAYBE, 2},
254 { MIDDMA_8WMAYBE, 2}, { MIDDMA_8WMAYBE, 2},
255 { MIDDMA_8WORD, 5}, { MIDDMA_16WMAYBE, 2},
256 { MIDDMA_16WMAYBE,2}, { MIDDMA_16WMAYBE, 2},
257 { MIDDMA_16WMAYBE,2}, { MIDDMA_16WMAYBE, 2},
258 { MIDDMA_16WMAYBE,2}, { MIDDMA_16WMAYBE, 2},
259 { MIDDMA_16WORD, 6},
260 };
261
262 static struct en_dmatab en_dma_planB[] = {
263 { 0, 0 }, { MIDDMA_WORD, 2},
264 { MIDDMA_2WORD, 3}, { MIDDMA_WORD, 2},
265 { MIDDMA_4WORD, 4}, { MIDDMA_WORD, 2},
266 { MIDDMA_2WORD, 3}, { MIDDMA_WORD, 2},
267 { MIDDMA_8WORD, 5}, { MIDDMA_WORD, 2},
268 { MIDDMA_2WORD, 3}, { MIDDMA_WORD, 2},
269 { MIDDMA_4WORD, 4}, { MIDDMA_WORD, 2},
270 { MIDDMA_2WORD, 3}, { MIDDMA_WORD, 2},
271 { MIDDMA_16WORD, 6},
272 };
273
274 static struct en_dmatab *en_dmaplan = en_dma_planA;
275
276
277
278
279
280 STATIC INLINE int en_b2sz(int) __attribute__ ((unused));
281 #ifdef EN_DDBHOOK
282 int en_dump(int,int);
283 int en_dumpmem(int,int,int);
284 #endif
285 STATIC void en_dmaprobe(struct en_softc *);
286 STATIC int en_dmaprobe_doit(struct en_softc *, u_int8_t *,
287 u_int8_t *, int);
288 STATIC INLINE int en_dqneed(struct en_softc *, caddr_t, u_int,
289 u_int) __attribute__ ((unused));
290 STATIC void en_init(struct en_softc *);
291 STATIC int en_ioctl(struct ifnet *, EN_IOCTL_CMDT, caddr_t);
292 STATIC INLINE int en_k2sz(int) __attribute__ ((unused));
293 STATIC void en_loadvc(struct en_softc *, int);
294 STATIC int en_mfix(struct en_softc *, struct mbuf **,
295 struct mbuf *);
296 STATIC INLINE struct mbuf *en_mget(struct en_softc *, u_int,
297 u_int *) __attribute__ ((unused));
298 STATIC INLINE u_int32_t en_read(struct en_softc *,
299 u_int32_t) __attribute__ ((unused));
300 STATIC int en_rxctl(struct en_softc *, struct atm_pseudoioctl *,
301 int);
302 STATIC void en_txdma(struct en_softc *, int);
303 STATIC void en_txlaunch(struct en_softc *, int,
304 struct en_launch *);
305 STATIC void en_service(struct en_softc *);
306 STATIC void en_start(struct ifnet *);
307 STATIC INLINE int en_sz2b(int) __attribute__ ((unused));
308 STATIC INLINE void en_write(struct en_softc *, u_int32_t,
309 u_int32_t) __attribute__ ((unused));
310
311
312
313
314
315
316
317
318
319 #define EN_READDAT(SC,R) en_read(SC,R)
320 #define EN_WRITEDAT(SC,R,V) en_write(SC,R,V)
321
322
323
324
325
326 #define EN_READ(SC,R) ntohl(en_read(SC,R))
327 #define EN_WRITE(SC,R,V) en_write(SC,R, htonl(V))
328
329 #define EN_WRAPADD(START,STOP,CUR,VAL) { \
330 (CUR) = (CUR) + (VAL); \
331 if ((CUR) >= (STOP)) \
332 (CUR) = (START) + ((CUR) - (STOP)); \
333 }
334
335 #define WORD_IDX(START, X) (((X) - (START)) / sizeof(u_int32_t))
336
337
338 #define EN_DQ_MK(SLOT,LEN) (((SLOT) << 20)|(LEN)|(0x80000))
339
340 #define EN_DQ_SLOT(X) ((X) >> 20)
341 #define EN_DQ_LEN(X) ((X) & 0x3ffff)
342
343
344 #if defined(MIDWAY_ENIONLY)
345
346 #define MID_MK_TXQ(SC,CNT,CHAN,END,BCODE) \
347 EN_WRITE((SC), (SC)->dtq_us, \
348 MID_MK_TXQ_ENI((CNT), (CHAN), (END), (BCODE)));
349
350 #define MID_MK_RXQ(SC,CNT,VCI,END,BCODE) \
351 EN_WRITE((SC), (SC)->drq_us, \
352 MID_MK_RXQ_ENI((CNT), (VCI), (END), (BCODE)));
353
354 #elif defined(MIDWAY_ADPONLY)
355
356 #define MID_MK_TXQ(SC,CNT,CHAN,END,JK) \
357 EN_WRITE((SC), (SC)->dtq_us, \
358 MID_MK_TXQ_ADP((CNT), (CHAN), (END), (JK)));
359
360 #define MID_MK_RXQ(SC,CNT,VCI,END,JK) \
361 EN_WRITE((SC), (SC)->drq_us, \
362 MID_MK_RXQ_ADP((CNT), (VCI), (END), (JK)));
363
364 #else
365
366 #define MID_MK_TXQ(SC,CNT,CHAN,END,JK_OR_BCODE) { \
367 if ((SC)->is_adaptec) \
368 EN_WRITE((SC), (SC)->dtq_us, \
369 MID_MK_TXQ_ADP((CNT), (CHAN), (END), (JK_OR_BCODE))); \
370 else \
371 EN_WRITE((SC), (SC)->dtq_us, \
372 MID_MK_TXQ_ENI((CNT), (CHAN), (END), (JK_OR_BCODE))); \
373 }
374
375 #define MID_MK_RXQ(SC,CNT,VCI,END,JK_OR_BCODE) { \
376 if ((SC)->is_adaptec) \
377 EN_WRITE((SC), (SC)->drq_us, \
378 MID_MK_RXQ_ADP((CNT), (VCI), (END), (JK_OR_BCODE))); \
379 else \
380 EN_WRITE((SC), (SC)->drq_us, \
381 MID_MK_RXQ_ENI((CNT), (VCI), (END), (JK_OR_BCODE))); \
382 }
383
384 #endif
385
386
387 #define EN_DTQADD(SC,CNT,CHAN,JK_OR_BCODE,ADDR,LEN,END) { \
388 if (END) \
389 (SC)->dtq[MID_DTQ_A2REG((SC)->dtq_us)] = EN_DQ_MK(CHAN,LEN); \
390 MID_MK_TXQ(SC,CNT,CHAN,END,JK_OR_BCODE); \
391 (SC)->dtq_us += 4; \
392 EN_WRITE((SC), (SC)->dtq_us, (ADDR)); \
393 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, (SC)->dtq_us, 4); \
394 (SC)->dtq_free--; \
395 if (END) \
396 EN_WRITE((SC), MID_DMA_WRTX, MID_DTQ_A2REG((SC)->dtq_us)); \
397 }
398
399
400 #define EN_DRQADD(SC,CNT,VCI,JK_OR_BCODE,ADDR,LEN,SLOT,END) { \
401 if (END) \
402 (SC)->drq[MID_DRQ_A2REG((SC)->drq_us)] = EN_DQ_MK(SLOT,LEN); \
403 MID_MK_RXQ(SC,CNT,VCI,END,JK_OR_BCODE); \
404 (SC)->drq_us += 4; \
405 EN_WRITE((SC), (SC)->drq_us, (ADDR)); \
406 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, (SC)->drq_us, 4); \
407 (SC)->drq_free--; \
408 if (END) \
409 EN_WRITE((SC), MID_DMA_WRRX, MID_DRQ_A2REG((SC)->drq_us)); \
410 }
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 STATIC INLINE u_int32_t en_read(sc, r)
431
432 struct en_softc *sc;
433 u_int32_t r;
434
435 {
436
437 #ifdef EN_DEBUG_RANGE
438 if (r > MID_MAXOFF || (r % 4)) {
439 panic("en_read: out of range, r=0x%x", r);
440 }
441 #endif
442
443 return(bus_space_read_4(sc->en_memt, sc->en_base, r));
444 }
445
446
447
448
449
450
451 STATIC INLINE void en_write(sc, r, v)
452
453 struct en_softc *sc;
454 u_int32_t r, v;
455
456 {
457 #ifdef EN_DEBUG_RANGE
458 if (r > MID_MAXOFF || (r % 4)) {
459 panic("en_write: out of range, r=0x%x", r);
460 }
461 #endif
462
463 bus_space_write_4(sc->en_memt, sc->en_base, r, v);
464 }
465
466
467
468
469
470 STATIC INLINE int en_k2sz(k)
471
472 int k;
473
474 {
475 switch(k) {
476 case 1: return(0);
477 case 2: return(1);
478 case 4: return(2);
479 case 8: return(3);
480 case 16: return(4);
481 case 32: return(5);
482 case 64: return(6);
483 case 128: return(7);
484 default: panic("en_k2sz");
485 }
486 return(0);
487 }
488 #define en_log2(X) en_k2sz(X)
489
490
491
492
493
494
495 STATIC INLINE int en_b2sz(b)
496
497 int b;
498
499 {
500 switch (b) {
501 case MIDDMA_WORD: return(1*4);
502 case MIDDMA_2WMAYBE:
503 case MIDDMA_2WORD: return(2*4);
504 case MIDDMA_4WMAYBE:
505 case MIDDMA_4WORD: return(4*4);
506 case MIDDMA_8WMAYBE:
507 case MIDDMA_8WORD: return(8*4);
508 case MIDDMA_16WMAYBE:
509 case MIDDMA_16WORD: return(16*4);
510 default: panic("en_b2sz");
511 }
512 return(0);
513 }
514
515
516
517
518
519
520 STATIC INLINE int en_sz2b(sz)
521
522 int sz;
523
524 {
525 switch (sz) {
526 case 1*4: return(MIDDMA_WORD);
527 case 2*4: return(MIDDMA_2WORD);
528 case 4*4: return(MIDDMA_4WORD);
529 case 8*4: return(MIDDMA_8WORD);
530 case 16*4: return(MIDDMA_16WORD);
531 default: panic("en_sz2b");
532 }
533 return(0);
534 }
535
536
537
538
539
540
541 STATIC INLINE int en_dqneed(sc, data, len, tx)
542
543 struct en_softc *sc;
544 caddr_t data;
545 u_int len, tx;
546
547 {
548 int result, needalign, sz;
549
550 #if !defined(MIDWAY_ENIONLY)
551 #if !defined(MIDWAY_ADPONLY)
552 if (sc->is_adaptec)
553 #endif
554 return(1);
555 #endif
556
557 #if !defined(MIDWAY_ADPONLY)
558 result = 0;
559 if (len < EN_MINDMA) {
560 if (!tx)
561 return(1);
562 }
563
564 if (tx) {
565 needalign = (((unsigned long) data) % sizeof(u_int32_t));
566 if (needalign) {
567 result++;
568 sz = min(len, sizeof(u_int32_t) - needalign);
569 len -= sz;
570 data += sz;
571 }
572 }
573
574 if (sc->alburst && len) {
575 needalign = (((unsigned long) data) & sc->bestburstmask);
576 if (needalign) {
577 result++;
578 sz = min(len, sc->bestburstlen - needalign);
579 len -= sz;
580 }
581 }
582
583 if (len >= sc->bestburstlen) {
584 sz = len / sc->bestburstlen;
585 sz = sz * sc->bestburstlen;
586 len -= sz;
587 result++;
588 }
589
590 if (len) {
591 result++;
592 if (tx && (len % sizeof(u_int32_t)) != 0)
593 result++;
594 }
595
596 return(result);
597 #endif
598 }
599
600
601
602
603
604
605
606
607 STATIC INLINE struct mbuf *en_mget(sc, totlen, drqneed)
608
609 struct en_softc *sc;
610 u_int totlen, *drqneed;
611
612 {
613 struct mbuf *m;
614 struct mbuf *top, **mp;
615 *drqneed = 0;
616
617 MGETHDR(m, M_DONTWAIT, MT_DATA);
618 if (m == NULL)
619 return(NULL);
620 m->m_pkthdr.rcvif = &sc->enif;
621 m->m_pkthdr.len = totlen;
622 m->m_len = MHLEN;
623 top = NULL;
624 mp = ⊤
625
626
627 while (totlen > 0) {
628 if (top) {
629 MGET(m, M_DONTWAIT, MT_DATA);
630 if (!m) {
631 m_freem(top);
632 return(NULL);
633 }
634 m->m_len = MLEN;
635 }
636 if (totlen >= MINCLSIZE) {
637 MCLGET(m, M_DONTWAIT);
638 if ((m->m_flags & M_EXT) == 0) {
639 m_free(m);
640 m_freem(top);
641 return(NULL);
642 }
643 m->m_len = MCLBYTES;
644 }
645 m->m_len = min(totlen, m->m_len);
646 totlen -= m->m_len;
647 *mp = m;
648 mp = &m->m_next;
649
650 *drqneed += en_dqneed(sc, m->m_data, m->m_len, 0);
651
652 }
653 return(top);
654 }
655
656
657
658
659
660
661
662 void en_attach(sc)
663
664 struct en_softc *sc;
665
666 {
667 struct ifnet *ifp = &sc->enif;
668 int sz;
669 u_int32_t reg, lcv, check, ptr, sav, midvloc;
670
671
672
673
674
675
676
677
678
679 if (sc->en_busreset)
680 sc->en_busreset(sc);
681 EN_WRITE(sc, MID_RESID, 0x0);
682 for (lcv = MID_PROBEOFF; lcv <= MID_MAXOFF ; lcv += MID_PROBSIZE) {
683 EN_WRITE(sc, lcv, lcv);
684 for (check = MID_PROBEOFF ; check < lcv ; check += MID_PROBSIZE) {
685 reg = EN_READ(sc, check);
686 if (reg != check) {
687 goto done_probe;
688 }
689 }
690 }
691 done_probe:
692 lcv -= MID_PROBSIZE;
693 sc->en_obmemsz = (lcv + 4) - MID_RAMOFF;
694
695
696
697
698
699 en_dmaprobe(sc);
700
701
702
703
704
705 if (sc->en_busreset)
706 sc->en_busreset(sc);
707 EN_WRITE(sc, MID_RESID, 0x0);
708 for (lcv = MID_RAMOFF ; lcv < MID_RAMOFF + sc->en_obmemsz ; lcv += 4)
709 EN_WRITE(sc, lcv, 0);
710
711 reg = EN_READ(sc, MID_RESID);
712
713 printf("%s: ATM midway v%d, board IDs %d.%d, %s%s%s, %ldKB on-board RAM\n",
714 sc->sc_dev.dv_xname, MID_VER(reg), MID_MID(reg), MID_DID(reg),
715 (MID_IS_SABRE(reg)) ? "sabre controller, " : "",
716 (MID_IS_SUNI(reg)) ? "SUNI" : "Utopia",
717 (!MID_IS_SUNI(reg) && MID_IS_UPIPE(reg)) ? " (pipelined)" : "",
718 sc->en_obmemsz / 1024);
719
720 if (sc->is_adaptec) {
721 if (sc->bestburstlen == 64 && sc->alburst == 0)
722 printf("%s: passed 64 byte DMA test\n", sc->sc_dev.dv_xname);
723 else
724 printf("%s: FAILED DMA TEST: burst=%d, alburst=%d\n",
725 sc->sc_dev.dv_xname, sc->bestburstlen, sc->alburst);
726 } else {
727 printf("%s: maximum DMA burst length = %d bytes%s\n", sc->sc_dev.dv_xname,
728 sc->bestburstlen, (sc->alburst) ? " (must align)" : "");
729 }
730
731 #if 0
732
733 if (en_dmaplan == en_dma_planB)
734 printf("%s: note: WMAYBE DMA has been disabled\n", sc->sc_dev.dv_xname);
735 #endif
736
737
738
739
740
741 #if defined(__NetBSD__) || defined(__OpenBSD__)
742 bcopy(sc->sc_dev.dv_xname, sc->enif.if_xname, IFNAMSIZ);
743 #endif
744 #if !defined(MISSING_IF_SOFTC)
745 sc->enif.if_softc = sc;
746 #endif
747 ifp->if_flags = IFF_SIMPLEX|IFF_NOTRAILERS;
748 ifp->if_ioctl = en_ioctl;
749 ifp->if_start = en_start;
750 IFQ_SET_READY(&ifp->if_snd);
751
752
753
754
755
756 for (lcv = 0 ; lcv < MID_N_VC ; lcv++) {
757 sc->rxvc2slot[lcv] = RX_NONE;
758 sc->txspeed[lcv] = 0;
759 sc->txvc2slot[lcv] = 0;
760 }
761
762 sz = sc->en_obmemsz - (MID_BUFOFF - MID_RAMOFF);
763 ptr = sav = MID_BUFOFF;
764 ptr = roundup(ptr, EN_TXSZ * 1024);
765 sz = sz - (ptr - sav);
766 if (EN_TXSZ*1024 * EN_NTX > sz) {
767 printf("%s: EN_NTX/EN_TXSZ too big\n", sc->sc_dev.dv_xname);
768 return;
769 }
770 for (lcv = 0 ; lcv < EN_NTX ; lcv++) {
771 sc->txslot[lcv].mbsize = 0;
772 sc->txslot[lcv].start = ptr;
773 ptr += (EN_TXSZ * 1024);
774 sz -= (EN_TXSZ * 1024);
775 sc->txslot[lcv].stop = ptr;
776 sc->txslot[lcv].nref = 0;
777 bzero(&sc->txslot[lcv].indma, sizeof(sc->txslot[lcv].indma));
778 bzero(&sc->txslot[lcv].q, sizeof(sc->txslot[lcv].q));
779 #ifdef EN_DEBUG
780 printf("%s: tx%d: start 0x%x, stop 0x%x\n", sc->sc_dev.dv_xname, lcv,
781 sc->txslot[lcv].start, sc->txslot[lcv].stop);
782 #endif
783 }
784
785 sav = ptr;
786 ptr = roundup(ptr, EN_RXSZ * 1024);
787 sz = sz - (ptr - sav);
788 sc->en_nrx = sz / (EN_RXSZ * 1024);
789 if (sc->en_nrx <= 0) {
790 printf("%s: EN_NTX/EN_TXSZ/EN_RXSZ too big\n", sc->sc_dev.dv_xname);
791 return;
792 }
793
794
795
796
797
798 if (sc->en_nrx >= MID_N_VC)
799 sc->en_nrx = MID_N_VC - 1;
800
801 for (lcv = 0 ; lcv < sc->en_nrx ; lcv++) {
802 sc->rxslot[lcv].rxhand = NULL;
803 sc->rxslot[lcv].oth_flags = ENOTHER_FREE;
804 bzero(&sc->rxslot[lcv].indma, sizeof(sc->rxslot[lcv].indma));
805 bzero(&sc->rxslot[lcv].q, sizeof(sc->rxslot[lcv].q));
806 midvloc = sc->rxslot[lcv].start = ptr;
807 ptr += (EN_RXSZ * 1024);
808 sz -= (EN_RXSZ * 1024);
809 sc->rxslot[lcv].stop = ptr;
810 midvloc = midvloc - MID_RAMOFF;
811 midvloc = (midvloc & ~((EN_RXSZ*1024) - 1)) >> 2;
812 midvloc = midvloc >> MIDV_LOCTOPSHFT;
813 midvloc = (midvloc & MIDV_LOCMASK) << MIDV_LOCSHIFT;
814 sc->rxslot[lcv].mode = midvloc |
815 (en_k2sz(EN_RXSZ) << MIDV_SZSHIFT) | MIDV_TRASH;
816
817 #ifdef EN_DEBUG
818 printf("%s: rx%d: start 0x%x, stop 0x%x, mode 0x%x\n", sc->sc_dev.dv_xname,
819 lcv, sc->rxslot[lcv].start, sc->rxslot[lcv].stop, sc->rxslot[lcv].mode);
820 #endif
821 }
822
823 #ifdef EN_STAT
824 sc->vtrash = sc->otrash = sc->mfix = sc->txmbovr = sc->dmaovr = 0;
825 sc->txoutspace = sc->txdtqout = sc->launch = sc->lheader = sc->ltail = 0;
826 sc->hwpull = sc->swadd = sc->rxqnotus = sc->rxqus = sc->rxoutboth = 0;
827 sc->rxdrqout = sc->ttrash = sc->rxmbufout = sc->mfixfail = 0;
828 sc->headbyte = sc->tailbyte = sc->tailflush = 0;
829 #endif
830 sc->need_drqs = sc->need_dtqs = 0;
831
832 printf("%s: %d %dKB receive buffers, %d %dKB transmit buffers allocated\n",
833 sc->sc_dev.dv_xname, sc->en_nrx, EN_RXSZ, EN_NTX, EN_TXSZ);
834
835
836
837
838
839 if_attach(ifp);
840 atm_ifattach(ifp);
841
842
843 #if NBPFILTER > 0
844 bpfattach(&ifp->if_bpf, ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
845 #endif
846
847 }
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864 STATIC void en_dmaprobe(sc)
865
866 struct en_softc *sc;
867
868 {
869 u_int32_t srcbuf[64], dstbuf[64];
870 u_int8_t *sp, *dp;
871 int bestalgn, bestnotalgn, lcv, try, fail;
872
873 sc->alburst = 0;
874
875 sp = (u_int8_t *) srcbuf;
876 while ((((unsigned long) sp) % MIDDMA_MAXBURST) != 0)
877 sp += 4;
878 dp = (u_int8_t *) dstbuf;
879 while ((((unsigned long) dp) % MIDDMA_MAXBURST) != 0)
880 dp += 4;
881
882 bestalgn = bestnotalgn = en_dmaprobe_doit(sc, sp, dp, 0);
883
884 for (lcv = 4 ; lcv < MIDDMA_MAXBURST ; lcv += 4) {
885 try = en_dmaprobe_doit(sc, sp+lcv, dp+lcv, 0);
886 if (try < bestnotalgn)
887 bestnotalgn = try;
888 }
889
890 if (bestalgn != bestnotalgn)
891 sc->alburst = 1;
892
893 sc->bestburstlen = bestalgn;
894 sc->bestburstshift = en_log2(bestalgn);
895 sc->bestburstmask = sc->bestburstlen - 1;
896 sc->bestburstcode = en_sz2b(bestalgn);
897
898 if (sc->bestburstlen <= 2*sizeof(u_int32_t))
899 return;
900
901
902
903
904
905 if (sc->is_adaptec) {
906
907 en_dmaplan = en_dma_planB;
908 return;
909 }
910
911
912
913
914
915
916 try = sc->bestburstlen - 4;
917 fail = 0;
918 fail += en_dmaprobe_doit(sc, sp, dp, try);
919 for (lcv = 4 ; lcv < sc->bestburstlen ; lcv += 4) {
920 fail += en_dmaprobe_doit(sc, sp+lcv, dp+lcv, try);
921 if (sc->alburst)
922 try -= 4;
923 }
924 if (EN_NOWMAYBE || fail) {
925 if (fail)
926 printf("%s: WARNING: WMAYBE DMA test failed %d time(s)\n",
927 sc->sc_dev.dv_xname, fail);
928 en_dmaplan = en_dma_planB;
929 }
930
931 }
932
933
934
935
936
937
938 int
939 en_dmaprobe_doit(sc, sp, dp, wmtry)
940
941 struct en_softc *sc;
942 u_int8_t *sp, *dp;
943 int wmtry;
944
945 {
946 int lcv, retval = 4, cnt, count;
947 u_int32_t reg, bcode, midvloc;
948
949
950
951
952
953 if (sc->en_busreset)
954 sc->en_busreset(sc);
955 EN_WRITE(sc, MID_RESID, 0x0);
956
957 midvloc = ((MID_BUFOFF - MID_RAMOFF) / sizeof(u_int32_t)) >> MIDV_LOCTOPSHFT;
958 EN_WRITE(sc, MIDX_PLACE(0), MIDX_MKPLACE(en_k2sz(1), midvloc));
959 EN_WRITE(sc, MID_VC(0), (midvloc << MIDV_LOCSHIFT)
960 | (en_k2sz(1) << MIDV_SZSHIFT) | MIDV_TRASH);
961 EN_WRITE(sc, MID_DST_RP(0), 0);
962 EN_WRITE(sc, MID_WP_ST_CNT(0), 0);
963
964 for (lcv = 0 ; lcv < 68 ; lcv++)
965 sp[lcv] = lcv+1;
966 EN_WRITE(sc, MID_MAST_CSR, MID_MCSR_ENDMA);
967
968 sc->drq_chip = MID_DRQ_REG2A(EN_READ(sc, MID_DMA_RDRX));
969 sc->dtq_chip = MID_DTQ_REG2A(EN_READ(sc, MID_DMA_RDTX));
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984 for (lcv = 8 ; lcv <= MIDDMA_MAXBURST ; lcv = lcv * 2) {
985
986
987 for (cnt = 0 ; cnt < 1024; cnt += 4)
988 EN_WRITE(sc, MID_BUFOFF+cnt, 0);
989 for (cnt = 0 ; cnt < 68 ; cnt++)
990 dp[cnt] = 0;
991
992 if (wmtry) {
993 count = (sc->bestburstlen - sizeof(u_int32_t)) / sizeof(u_int32_t);
994 bcode = en_dmaplan[count].bcode;
995 count = wmtry >> en_dmaplan[count].divshift;
996 } else {
997 bcode = en_sz2b(lcv);
998 count = 1;
999 }
1000 if (sc->is_adaptec)
1001 EN_WRITE(sc, sc->dtq_chip, MID_MK_TXQ_ADP(lcv, 0, MID_DMA_END, 0));
1002 else
1003 EN_WRITE(sc, sc->dtq_chip, MID_MK_TXQ_ENI(count, 0, MID_DMA_END, bcode));
1004 EN_WRITE(sc, sc->dtq_chip+4, vtophys(sp));
1005 EN_WRITE(sc, MID_DMA_WRTX, MID_DTQ_A2REG(sc->dtq_chip+8));
1006 cnt = 1000;
1007 while (EN_READ(sc, MID_DMA_RDTX) == MID_DTQ_A2REG(sc->dtq_chip)) {
1008 DELAY(1);
1009 cnt--;
1010 if (cnt == 0) {
1011 printf("%s: unexpected timeout in tx DMA test\n", sc->sc_dev.dv_xname);
1012 return(retval);
1013 }
1014 }
1015 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, sc->dtq_chip, 8);
1016 reg = EN_READ(sc, MID_INTACK);
1017 if ((reg & MID_INT_DMA_TX) != MID_INT_DMA_TX) {
1018 printf("%s: unexpected status in tx DMA test: 0x%x\n",
1019 sc->sc_dev.dv_xname, reg);
1020 return(retval);
1021 }
1022 EN_WRITE(sc, MID_MAST_CSR, MID_MCSR_ENDMA);
1023
1024
1025
1026 if (sc->is_adaptec)
1027 EN_WRITE(sc, sc->drq_chip, MID_MK_RXQ_ADP(lcv, 0, MID_DMA_END, 0));
1028 else
1029 EN_WRITE(sc, sc->drq_chip, MID_MK_RXQ_ENI(count, 0, MID_DMA_END, bcode));
1030 EN_WRITE(sc, sc->drq_chip+4, vtophys(dp));
1031 EN_WRITE(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_chip+8));
1032 cnt = 1000;
1033 while (EN_READ(sc, MID_DMA_RDRX) == MID_DRQ_A2REG(sc->drq_chip)) {
1034 DELAY(1);
1035 cnt--;
1036 if (cnt == 0) {
1037 printf("%s: unexpected timeout in rx DMA test\n", sc->sc_dev.dv_xname);
1038 return(retval);
1039 }
1040 }
1041 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, sc->drq_chip, 8);
1042 reg = EN_READ(sc, MID_INTACK);
1043 if ((reg & MID_INT_DMA_RX) != MID_INT_DMA_RX) {
1044 printf("%s: unexpected status in rx DMA test: 0x%x\n",
1045 sc->sc_dev.dv_xname, reg);
1046 return(retval);
1047 }
1048 EN_WRITE(sc, MID_MAST_CSR, MID_MCSR_ENDMA);
1049
1050 if (wmtry) {
1051 return(bcmp(sp, dp, wmtry));
1052 }
1053
1054 if (bcmp(sp, dp, lcv))
1055 return(retval);
1056
1057 retval = lcv;
1058
1059 }
1060 return(retval);
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075 STATIC int en_ioctl(ifp, cmd, data)
1076
1077 struct ifnet *ifp;
1078 EN_IOCTL_CMDT cmd;
1079 caddr_t data;
1080
1081 {
1082 #ifdef MISSING_IF_SOFTC
1083 struct en_softc *sc = (struct en_softc *) en_cd.cd_devs[ifp->if_unit];
1084 #else
1085 struct en_softc *sc = (struct en_softc *) ifp->if_softc;
1086 #endif
1087 struct ifaddr *ifa = (struct ifaddr *) data;
1088 struct ifreq *ifr = (struct ifreq *) data;
1089 struct atm_pseudoioctl *api = (struct atm_pseudoioctl *)data;
1090 #ifdef NATM
1091 struct atm_rawioctl *ario = (struct atm_rawioctl *)data;
1092 int slot;
1093 #endif
1094 int s, error = 0;
1095
1096 s = splnet();
1097
1098 switch (cmd) {
1099 case SIOCATMENA:
1100 error = en_rxctl(sc, api, 1);
1101 break;
1102
1103 case SIOCATMDIS:
1104 error = en_rxctl(sc, api, 0);
1105 break;
1106
1107 #ifdef NATM
1108 case SIOCXRAWATM:
1109 if ((slot = sc->rxvc2slot[ario->npcb->npcb_vci]) == RX_NONE) {
1110 error = EINVAL;
1111 break;
1112 }
1113 if (ario->rawvalue > EN_RXSZ*1024)
1114 ario->rawvalue = EN_RXSZ*1024;
1115 if (ario->rawvalue) {
1116 sc->rxslot[slot].oth_flags |= ENOTHER_RAW;
1117 sc->rxslot[slot].raw_threshold = ario->rawvalue;
1118 } else {
1119 sc->rxslot[slot].oth_flags &= (~ENOTHER_RAW);
1120 sc->rxslot[slot].raw_threshold = 0;
1121 }
1122 #ifdef EN_DEBUG
1123 printf("%s: rxvci%d: turn %s raw (boodi) mode\n",
1124 sc->sc_dev.dv_xname, ario->npcb->npcb_vci,
1125 (ario->rawvalue) ? "on" : "off");
1126 #endif
1127 break;
1128 #endif
1129 case SIOCSIFADDR:
1130 ifp->if_flags |= IFF_UP;
1131 #ifdef INET
1132 if (ifa->ifa_addr->sa_family == AF_INET) {
1133 en_reset(sc);
1134 en_init(sc);
1135 ifa->ifa_rtrequest = atm_rtrequest;
1136 break;
1137 }
1138 #endif
1139
1140 en_reset(sc);
1141 en_init(sc);
1142 break;
1143
1144 case SIOCGIFADDR:
1145 error = EINVAL;
1146 break;
1147
1148 case SIOCSIFFLAGS:
1149 error = EINVAL;
1150 break;
1151
1152 case SIOCSIFMTU:
1153
1154
1155
1156 #ifdef notsure
1157 if (ifr->ifr_mtu > ATMMTU) {
1158 error = EINVAL;
1159 break;
1160 }
1161 #endif
1162 ifp->if_mtu = ifr->ifr_mtu;
1163
1164 en_reset(sc);
1165 en_init(sc);
1166 break;
1167
1168 default:
1169 error = EINVAL;
1170 break;
1171 }
1172 splx(s);
1173 return error;
1174 }
1175
1176
1177
1178
1179
1180
1181 STATIC int en_rxctl(sc, pi, on)
1182
1183 struct en_softc *sc;
1184 struct atm_pseudoioctl *pi;
1185 int on;
1186
1187 {
1188 u_int s, vci, flags, slot;
1189 u_int32_t oldmode, newmode;
1190
1191 vci = ATM_PH_VCI(&pi->aph);
1192 flags = ATM_PH_FLAGS(&pi->aph);
1193
1194 #ifdef EN_DEBUG
1195 printf("%s: %s vpi=%d, vci=%d, flags=%d\n", sc->sc_dev.dv_xname,
1196 (on) ? "enable" : "disable", ATM_PH_VPI(&pi->aph), vci, flags);
1197 #endif
1198
1199 if (ATM_PH_VPI(&pi->aph) || vci >= MID_N_VC)
1200 return(EINVAL);
1201
1202
1203
1204
1205
1206 if (on) {
1207 if (sc->rxvc2slot[vci] != RX_NONE)
1208 return(EINVAL);
1209 for (slot = 0 ; slot < sc->en_nrx ; slot++)
1210 if (sc->rxslot[slot].oth_flags & ENOTHER_FREE)
1211 break;
1212 if (slot == sc->en_nrx)
1213 return(ENOSPC);
1214 sc->rxvc2slot[vci] = slot;
1215 sc->rxslot[slot].rxhand = NULL;
1216 oldmode = sc->rxslot[slot].mode;
1217 newmode = (flags & ATM_PH_AAL5) ? MIDV_AAL5 : MIDV_NOAAL;
1218 sc->rxslot[slot].mode = MIDV_SETMODE(oldmode, newmode);
1219 sc->rxslot[slot].atm_vci = vci;
1220 sc->rxslot[slot].atm_flags = flags;
1221 sc->rxslot[slot].oth_flags = 0;
1222 sc->rxslot[slot].rxhand = pi->rxhand;
1223 if (sc->rxslot[slot].indma.ifq_head || sc->rxslot[slot].q.ifq_head)
1224 panic("en_rxctl: left over mbufs on enable");
1225 sc->txspeed[vci] = 0;
1226 sc->txvc2slot[vci] = 0;
1227 sc->txslot[0].nref++;
1228 en_loadvc(sc, vci);
1229 return(0);
1230 }
1231
1232
1233
1234
1235
1236 if (sc->rxvc2slot[vci] == RX_NONE)
1237 return(EINVAL);
1238 slot = sc->rxvc2slot[vci];
1239 if ((sc->rxslot[slot].oth_flags & (ENOTHER_FREE|ENOTHER_DRAIN)) != 0)
1240 return(EINVAL);
1241 s = splnet();
1242 oldmode = EN_READ(sc, MID_VC(vci));
1243 newmode = MIDV_SETMODE(oldmode, MIDV_TRASH) & ~MIDV_INSERVICE;
1244 EN_WRITE(sc, MID_VC(vci), (newmode | (oldmode & MIDV_INSERVICE)));
1245
1246 DELAY(27);
1247 sc->rxslot[slot].rxhand = NULL;
1248 sc->rxslot[slot].mode = newmode;
1249
1250 sc->txslot[sc->txvc2slot[vci]].nref--;
1251 sc->txspeed[vci] = 0;
1252 sc->txvc2slot[vci] = 0;
1253
1254
1255 if (sc->rxslot[slot].indma.ifq_head ||
1256 sc->rxslot[slot].q.ifq_head ||
1257 (sc->rxslot[slot].oth_flags & ENOTHER_SWSL) != 0) {
1258 sc->rxslot[slot].oth_flags |= ENOTHER_DRAIN;
1259 } else {
1260 sc->rxslot[slot].oth_flags = ENOTHER_FREE;
1261 sc->rxslot[slot].atm_vci = RX_NONE;
1262 sc->rxvc2slot[vci] = RX_NONE;
1263 }
1264 splx(s);
1265 #ifdef EN_DEBUG
1266 printf("%s: rx%d: VCI %d is now %s\n", sc->sc_dev.dv_xname, slot, vci,
1267 (sc->rxslot[slot].oth_flags & ENOTHER_DRAIN) ? "draining" : "free");
1268 #endif
1269 return(0);
1270 }
1271
1272
1273
1274
1275
1276
1277
1278
1279 void en_reset(sc)
1280
1281 struct en_softc *sc;
1282
1283 {
1284 struct mbuf *m;
1285 int lcv, slot;
1286
1287 #ifdef EN_DEBUG
1288 printf("%s: reset\n", sc->sc_dev.dv_xname);
1289 #endif
1290
1291 if (sc->en_busreset)
1292 sc->en_busreset(sc);
1293 EN_WRITE(sc, MID_RESID, 0x0);
1294
1295
1296
1297
1298
1299
1300 for (lcv = 0 ; lcv < MID_N_VC ; lcv++) {
1301 if (sc->rxvc2slot[lcv] == RX_NONE)
1302 continue;
1303 slot = sc->rxvc2slot[lcv];
1304 while (1) {
1305 IF_DEQUEUE(&sc->rxslot[slot].indma, m);
1306 if (m == NULL)
1307 break;
1308 m_freem(m);
1309 }
1310 while (1) {
1311 IF_DEQUEUE(&sc->rxslot[slot].q, m);
1312 if (m == NULL)
1313 break;
1314 m_freem(m);
1315 }
1316 sc->rxslot[slot].oth_flags &= ~ENOTHER_SWSL;
1317 if (sc->rxslot[slot].oth_flags & ENOTHER_DRAIN) {
1318 sc->rxslot[slot].oth_flags = ENOTHER_FREE;
1319 sc->rxvc2slot[lcv] = RX_NONE;
1320 #ifdef EN_DEBUG
1321 printf("%s: rx%d: VCI %d is now free\n", sc->sc_dev.dv_xname, slot, lcv);
1322 #endif
1323 }
1324 }
1325
1326
1327
1328
1329
1330 for (lcv = 0 ; lcv < EN_NTX ; lcv++) {
1331 while (1) {
1332 IF_DEQUEUE(&sc->txslot[lcv].indma, m);
1333 if (m == NULL)
1334 break;
1335 m_freem(m);
1336 }
1337 while (1) {
1338 IF_DEQUEUE(&sc->txslot[lcv].q, m);
1339 if (m == NULL)
1340 break;
1341 m_freem(m);
1342 }
1343 sc->txslot[lcv].mbsize = 0;
1344 }
1345
1346 return;
1347 }
1348
1349
1350
1351
1352
1353
1354 STATIC void en_init(sc)
1355
1356 struct en_softc *sc;
1357
1358 {
1359 int vc, slot;
1360 u_int32_t loc;
1361
1362 if ((sc->enif.if_flags & IFF_UP) == 0) {
1363 #ifdef EN_DEBUG
1364 printf("%s: going down\n", sc->sc_dev.dv_xname);
1365 #endif
1366 en_reset(sc);
1367 sc->enif.if_flags &= ~IFF_RUNNING;
1368 return;
1369 }
1370
1371 #ifdef EN_DEBUG
1372 printf("%s: going up\n", sc->sc_dev.dv_xname);
1373 #endif
1374 sc->enif.if_flags |= IFF_RUNNING;
1375
1376 if (sc->en_busreset)
1377 sc->en_busreset(sc);
1378 EN_WRITE(sc, MID_RESID, 0x0);
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394 for (vc = 0 ; vc < MID_N_VC ; vc++)
1395 en_loadvc(sc, vc);
1396
1397 bzero(&sc->drq, sizeof(sc->drq));
1398 sc->drq_free = MID_DRQ_N - 1;
1399 sc->drq_chip = MID_DRQ_REG2A(EN_READ(sc, MID_DMA_RDRX));
1400 EN_WRITE(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_chip));
1401
1402 sc->drq_us = sc->drq_chip;
1403
1404 bzero(&sc->dtq, sizeof(sc->dtq));
1405 sc->dtq_free = MID_DTQ_N - 1;
1406 sc->dtq_chip = MID_DTQ_REG2A(EN_READ(sc, MID_DMA_RDTX));
1407 EN_WRITE(sc, MID_DMA_WRTX, MID_DRQ_A2REG(sc->dtq_chip));
1408
1409 sc->dtq_us = sc->dtq_chip;
1410
1411 sc->hwslistp = MID_SL_REG2A(EN_READ(sc, MID_SERV_WRITE));
1412 sc->swsl_size = sc->swsl_head = sc->swsl_tail = 0;
1413
1414 #ifdef EN_DEBUG
1415 printf("%s: drq free/chip: %d/0x%x, dtq free/chip: %d/0x%x, hwslist: 0x%x\n",
1416 sc->sc_dev.dv_xname, sc->drq_free, sc->drq_chip,
1417 sc->dtq_free, sc->dtq_chip, sc->hwslistp);
1418 #endif
1419
1420 for (slot = 0 ; slot < EN_NTX ; slot++) {
1421 sc->txslot[slot].bfree = EN_TXSZ * 1024;
1422 EN_WRITE(sc, MIDX_READPTR(slot), 0);
1423 EN_WRITE(sc, MIDX_DESCSTART(slot), 0);
1424 loc = sc->txslot[slot].cur = sc->txslot[slot].start;
1425 loc = loc - MID_RAMOFF;
1426 loc = (loc & ~((EN_TXSZ*1024) - 1)) >> 2;
1427 loc = loc >> MIDV_LOCTOPSHFT;
1428 EN_WRITE(sc, MIDX_PLACE(slot), MIDX_MKPLACE(en_k2sz(EN_TXSZ), loc));
1429 #ifdef EN_DEBUG
1430 printf("%s: tx%d: place 0x%x\n", sc->sc_dev.dv_xname, slot,
1431 EN_READ(sc, MIDX_PLACE(slot)));
1432 #endif
1433 }
1434
1435
1436
1437
1438
1439 EN_WRITE(sc, MID_INTENA, MID_INT_TX|MID_INT_DMA_OVR|MID_INT_IDENT|
1440 MID_INT_LERR|MID_INT_DMA_ERR|MID_INT_DMA_RX|MID_INT_DMA_TX|
1441 MID_INT_SERVICE| MID_INT_STATS);
1442 EN_WRITE(sc, MID_MAST_CSR, MID_SETIPL(sc->ipl)|MID_MCSR_ENDMA|
1443 MID_MCSR_ENTX|MID_MCSR_ENRX);
1444
1445 }
1446
1447
1448
1449
1450
1451
1452 STATIC void en_loadvc(sc, vc)
1453
1454 struct en_softc *sc;
1455 int vc;
1456
1457 {
1458 int slot;
1459 u_int32_t reg = EN_READ(sc, MID_VC(vc));
1460
1461 reg = MIDV_SETMODE(reg, MIDV_TRASH);
1462 EN_WRITE(sc, MID_VC(vc), reg);
1463 DELAY(27);
1464
1465 if ((slot = sc->rxvc2slot[vc]) == RX_NONE)
1466 return;
1467
1468
1469 EN_WRITE(sc, MID_DST_RP(vc), 0);
1470 EN_WRITE(sc, MID_WP_ST_CNT(vc), 0);
1471 EN_WRITE(sc, MID_VC(vc), sc->rxslot[slot].mode);
1472 sc->rxslot[slot].cur = sc->rxslot[slot].start;
1473
1474 #ifdef EN_DEBUG
1475 printf("%s: rx%d: assigned to VCI %d\n", sc->sc_dev.dv_xname, slot, vc);
1476 #endif
1477 }
1478
1479
1480
1481
1482
1483
1484
1485 STATIC void en_start(ifp)
1486
1487 struct ifnet *ifp;
1488
1489 {
1490 #ifdef MISSING_IF_SOFTC
1491 struct en_softc *sc = (struct en_softc *) en_cd.cd_devs[ifp->if_unit];
1492 #else
1493 struct en_softc *sc = (struct en_softc *) ifp->if_softc;
1494 #endif
1495 struct mbuf *m, *lastm, *prev;
1496 struct atm_pseudohdr *ap, *new_ap;
1497 int txchan, mlen, got, need, toadd, cellcnt, first;
1498 u_int32_t atm_vpi, atm_vci, atm_flags, *dat, aal;
1499 u_int8_t *cp;
1500
1501 if ((ifp->if_flags & IFF_RUNNING) == 0)
1502 return;
1503
1504
1505
1506
1507
1508
1509 while (1) {
1510
1511 IFQ_DEQUEUE(&ifp->if_snd, m);
1512 if (m == NULL)
1513 return;
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525 lastm = m;
1526 mlen = 0;
1527 prev = NULL;
1528 while (1) {
1529
1530 if ((!sc->is_adaptec && EN_ENIDMAFIX) || EN_NOTXDMA || !en_dma) {
1531 if ( (mtod(lastm, unsigned long) % sizeof(u_int32_t)) != 0 ||
1532 ((lastm->m_len % sizeof(u_int32_t)) != 0 && lastm->m_next)) {
1533 first = (lastm == m);
1534 if (en_mfix(sc, &lastm, prev) == 0) {
1535 m_freem(m);
1536 m = NULL;
1537 break;
1538 }
1539 if (first)
1540 m = lastm;
1541 }
1542 prev = lastm;
1543 }
1544 mlen += lastm->m_len;
1545 if (lastm->m_next == NULL)
1546 break;
1547 lastm = lastm->m_next;
1548 }
1549
1550 if (m == NULL)
1551 continue;
1552
1553 ap = mtod(m, struct atm_pseudohdr *);
1554
1555 atm_vpi = ATM_PH_VPI(ap);
1556 atm_vci = ATM_PH_VCI(ap);
1557 atm_flags = ATM_PH_FLAGS(ap) & ~(EN_OBHDR|EN_OBTRL);
1558 aal = ((atm_flags & ATM_PH_AAL5) != 0)
1559 ? MID_TBD_AAL5 : MID_TBD_NOAAL5;
1560
1561
1562
1563
1564
1565 if (atm_vpi || atm_vci > MID_N_VC) {
1566 printf("%s: output vpi=%d, vci=%d out of card range, dropping...\n",
1567 sc->sc_dev.dv_xname, atm_vpi, atm_vci);
1568 m_freem(m);
1569 continue;
1570 }
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585 got = mlen - sizeof(struct atm_pseudohdr);
1586 toadd = (aal == MID_TBD_AAL5) ? MID_PDU_SIZE : 0;
1587 cellcnt = (got + toadd + (MID_ATMDATASZ - 1)) / MID_ATMDATASZ;
1588 need = cellcnt * MID_ATMDATASZ;
1589 toadd = need - got;
1590
1591 #ifdef EN_DEBUG
1592 printf("%s: txvci%d: mlen=%d, got=%d, need=%d, toadd=%d, cell#=%d\n",
1593 sc->sc_dev.dv_xname, atm_vci, mlen, got, need, toadd, cellcnt);
1594 printf(" leading_space=%d, trailing_space=%d\n",
1595 M_LEADINGSPACE(m), M_TRAILINGSPACE(lastm));
1596 #endif
1597
1598 #ifdef EN_MBUF_OPT
1599
1600
1601
1602
1603
1604
1605
1606
1607 if (M_LEADINGSPACE(m) >= MID_TBD_SIZE && (m->m_flags & M_EXT) == 0) {
1608 m->m_data -= MID_TBD_SIZE;
1609 m->m_len += MID_TBD_SIZE;
1610 mlen += MID_TBD_SIZE;
1611 new_ap = mtod(m, struct atm_pseudohdr *);
1612 *new_ap = *ap;
1613 ap = new_ap;
1614 dat = ((u_int32_t *) ap) + 1;
1615
1616 *dat++ = htonl(MID_TBD_MK1(aal, sc->txspeed[atm_vci], cellcnt));
1617 *dat = htonl(MID_TBD_MK2(atm_vci, 0, 0));
1618 atm_flags |= EN_OBHDR;
1619 }
1620
1621 if (toadd && (lastm->m_flags & M_EXT) == 0 &&
1622 M_TRAILINGSPACE(lastm) >= toadd) {
1623 cp = mtod(lastm, u_int8_t *) + lastm->m_len;
1624 lastm->m_len += toadd;
1625 mlen += toadd;
1626 if (aal == MID_TBD_AAL5) {
1627 bzero(cp, toadd - MID_PDU_SIZE);
1628 dat = (u_int32_t *)(cp + toadd - MID_PDU_SIZE);
1629
1630 *dat = htonl(MID_PDU_MK1(0, 0, got));
1631 } else {
1632 bzero(cp, toadd);
1633 }
1634 atm_flags |= EN_OBTRL;
1635 }
1636 ATM_PH_FLAGS(ap) = atm_flags;
1637 #endif
1638
1639
1640
1641
1642
1643 txchan = sc->txvc2slot[atm_vci];
1644
1645 if (sc->txslot[txchan].mbsize > EN_TXHIWAT) {
1646 EN_COUNT(sc->txmbovr);
1647 m_freem(m);
1648 #ifdef EN_DEBUG
1649 printf("%s: tx%d: buffer space shortage\n", sc->sc_dev.dv_xname,
1650 txchan);
1651 #endif
1652 continue;
1653 }
1654
1655 sc->txslot[txchan].mbsize += mlen;
1656
1657 #ifdef EN_DEBUG
1658 printf("%s: tx%d: VPI=%d, VCI=%d, FLAGS=0x%x, speed=0x%x\n",
1659 sc->sc_dev.dv_xname, txchan, atm_vpi, atm_vci, atm_flags,
1660 sc->txspeed[atm_vci]);
1661 printf(" adjusted mlen=%d, mbsize=%d\n", mlen,
1662 sc->txslot[txchan].mbsize);
1663 #endif
1664
1665 IF_ENQUEUE(&sc->txslot[txchan].q, m);
1666 en_txdma(sc, txchan);
1667
1668 }
1669
1670 }
1671
1672
1673
1674
1675
1676
1677 STATIC int en_mfix(sc, mm, prev)
1678
1679 struct en_softc *sc;
1680 struct mbuf **mm, *prev;
1681
1682 {
1683 struct mbuf *m, *new;
1684 u_char *d, *cp;
1685 int off;
1686 struct mbuf *nxt;
1687
1688 m = *mm;
1689
1690 EN_COUNT(sc->mfix);
1691 #ifdef EN_DEBUG
1692 printf("%s: mfix mbuf m_data=%p, m_len=%d\n", sc->sc_dev.dv_xname,
1693 m->m_data, m->m_len);
1694 #endif
1695
1696 d = mtod(m, u_char *);
1697 off = ((unsigned long) d) % sizeof(u_int32_t);
1698
1699 if (off) {
1700 if ((m->m_flags & M_EXT) == 0) {
1701 bcopy(d, d - off, m->m_len);
1702 d -= off;
1703 m->m_data = (caddr_t)d;
1704 } else {
1705
1706 MGET(new, M_DONTWAIT, MT_DATA);
1707 if (!new) {
1708 EN_COUNT(sc->mfixfail);
1709 return(0);
1710 }
1711 MCLGET(new, M_DONTWAIT);
1712 if ((new->m_flags & M_EXT) == 0) {
1713 m_free(new);
1714 EN_COUNT(sc->mfixfail);
1715 return(0);
1716 }
1717 bcopy(d, new->m_data, m->m_len);
1718 new->m_len = m->m_len;
1719 new->m_next = m->m_next;
1720 if (prev)
1721 prev->m_next = new;
1722 m_free(m);
1723 *mm = m = new;
1724 }
1725 }
1726
1727 off = m->m_len % sizeof(u_int32_t);
1728 if (off == 0)
1729 return(1);
1730
1731 d = mtod(m, u_char *) + m->m_len;
1732 off = sizeof(u_int32_t) - off;
1733
1734 nxt = m->m_next;
1735 while (off--) {
1736 for ( ; nxt != NULL && nxt->m_len == 0 ; nxt = nxt->m_next)
1737 ;
1738 if (nxt == NULL) {
1739 *d++ = 0;
1740 continue;
1741 }
1742 cp = mtod(nxt, u_char *);
1743 *d++ = *cp++;
1744 m->m_len++;
1745 nxt->m_len--;
1746 nxt->m_data = (caddr_t)cp;
1747 }
1748 return(1);
1749 }
1750
1751
1752
1753
1754
1755
1756 STATIC void en_txdma(sc, chan)
1757
1758 struct en_softc *sc;
1759 int chan;
1760
1761 {
1762 struct mbuf *tmp;
1763 struct atm_pseudohdr *ap;
1764 struct en_launch launch;
1765 int datalen = 0, dtqneed, len, ncells;
1766 u_int8_t *cp;
1767
1768 #ifdef EN_DEBUG
1769 printf("%s: tx%d: starting...\n", sc->sc_dev.dv_xname, chan);
1770 #endif
1771
1772
1773
1774
1775
1776
1777
1778 launch.nodma = (EN_NOTXDMA || !en_dma);
1779
1780 again:
1781
1782
1783
1784
1785
1786 launch.t = sc->txslot[chan].q.ifq_head;
1787
1788 if (launch.t == NULL) {
1789 #ifdef EN_DEBUG
1790 printf("%s: tx%d: ...done!\n", sc->sc_dev.dv_xname, chan);
1791 #endif
1792 return;
1793 }
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803 ap = mtod(launch.t, struct atm_pseudohdr *);
1804 launch.atm_vci = ATM_PH_VCI(ap);
1805 launch.atm_flags = ATM_PH_FLAGS(ap);
1806 launch.aal = ((launch.atm_flags & ATM_PH_AAL5) != 0) ?
1807 MID_TBD_AAL5 : MID_TBD_NOAAL5;
1808
1809
1810
1811
1812
1813
1814
1815 if ((launch.atm_flags & EN_OBHDR) == 0) {
1816 dtqneed = 1;
1817 launch.need = MID_TBD_SIZE;
1818 } else {
1819 dtqneed = 0;
1820 launch.need = 0;
1821 }
1822
1823 launch.mlen = 0;
1824 for (tmp = launch.t ; tmp != NULL ; tmp = tmp->m_next) {
1825 len = tmp->m_len;
1826 launch.mlen += len;
1827 cp = mtod(tmp, u_int8_t *);
1828 if (tmp == launch.t) {
1829 len -= sizeof(struct atm_pseudohdr);
1830 cp += sizeof(struct atm_pseudohdr);
1831 }
1832 launch.need += len;
1833 if (len == 0)
1834 continue;
1835
1836 dtqneed += en_dqneed(sc, (caddr_t) cp, len, 1);
1837 }
1838
1839 if ((launch.need % sizeof(u_int32_t)) != 0)
1840 dtqneed++;
1841
1842 if ((launch.atm_flags & EN_OBTRL) == 0) {
1843 if (launch.aal == MID_TBD_AAL5) {
1844 datalen = launch.need - MID_TBD_SIZE;
1845 launch.need += MID_PDU_SIZE;
1846 }
1847 dtqneed++;
1848 }
1849
1850
1851
1852
1853
1854
1855
1856
1857 launch.need = roundup(launch.need - MID_TBD_SIZE, MID_ATMDATASZ);
1858 ncells = launch.need / MID_ATMDATASZ;
1859 launch.need += MID_TBD_SIZE;
1860
1861 if (launch.need > EN_TXSZ * 1024) {
1862 printf("%s: tx%d: packet larger than xmit buffer (%d > %d)\n",
1863 sc->sc_dev.dv_xname, chan, launch.need, EN_TXSZ * 1024);
1864 goto dequeue_drop;
1865 }
1866
1867
1868
1869
1870
1871
1872
1873
1874 if (launch.need >= sc->txslot[chan].bfree) {
1875 EN_COUNT(sc->txoutspace);
1876 #ifdef EN_DEBUG
1877 printf("%s: tx%d: out of transmit space\n", sc->sc_dev.dv_xname, chan);
1878 #endif
1879 return;
1880 }
1881
1882
1883
1884
1885
1886 if (launch.nodma) {
1887 dtqneed = 1;
1888 }
1889 if (dtqneed > sc->dtq_free) {
1890 sc->need_dtqs = 1;
1891 EN_COUNT(sc->txdtqout);
1892 #ifdef EN_DEBUG
1893 printf("%s: tx%d: out of transmit DTQs\n", sc->sc_dev.dv_xname, chan);
1894 #endif
1895 return;
1896 }
1897
1898
1899
1900
1901
1902 IF_DEQUEUE(&sc->txslot[chan].q, tmp);
1903 #ifdef EN_DIAG
1904 if (launch.t != tmp)
1905 panic("en dequeue");
1906 #endif
1907
1908
1909
1910
1911
1912 EN_COUNT(sc->launch);
1913 sc->enif.if_opackets++;
1914 if ((launch.atm_flags & EN_OBHDR) == 0) {
1915 EN_COUNT(sc->lheader);
1916
1917 launch.tbd1 = MID_TBD_MK1(launch.aal, sc->txspeed[launch.atm_vci], ncells);
1918 launch.tbd2 = MID_TBD_MK2(launch.atm_vci, 0, 0);
1919 }
1920 if ((launch.atm_flags & EN_OBTRL) == 0 && launch.aal == MID_TBD_AAL5) {
1921 EN_COUNT(sc->ltail);
1922 launch.pdu1 = MID_PDU_MK1(0, 0, datalen);
1923 }
1924
1925 #if NBPFILTER > 0
1926 if (sc->enif.if_bpf != NULL) {
1927
1928
1929
1930
1931
1932
1933
1934 int size = sizeof(struct atm_pseudohdr);
1935 if (launch.atm_flags & EN_OBHDR)
1936 size += MID_TBD_SIZE;
1937
1938 launch.t->m_data += size;
1939 launch.t->m_len -= size;
1940
1941 bpf_mtap(sc->enif.if_bpf, launch.t, BPF_DIRECTION_OUT);
1942
1943 launch.t->m_data -= size;
1944 launch.t->m_len += size;
1945 }
1946 #endif
1947
1948 en_txlaunch(sc, chan, &launch);
1949
1950
1951
1952
1953
1954 sc->txslot[chan].bfree -= launch.need;
1955 IF_ENQUEUE(&sc->txslot[chan].indma, launch.t);
1956 goto again;
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966 dequeue_drop:
1967 IF_DEQUEUE(&sc->txslot[chan].q, tmp);
1968 if (launch.t != tmp)
1969 panic("en dequeue drop");
1970 m_freem(launch.t);
1971 sc->txslot[chan].mbsize -= launch.mlen;
1972 goto again;
1973 }
1974
1975
1976
1977
1978
1979
1980 STATIC void en_txlaunch(sc, chan, l)
1981
1982 struct en_softc *sc;
1983 int chan;
1984 struct en_launch *l;
1985
1986 {
1987 struct mbuf *tmp;
1988 u_int32_t cur = sc->txslot[chan].cur,
1989 start = sc->txslot[chan].start,
1990 stop = sc->txslot[chan].stop,
1991 dma, *data, *datastop, count, bcode;
1992 int pad, addtail, need, len, needalign, cnt, end, mx;
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014 need = l->need;
2015 dma = cur;
2016 addtail = (l->atm_flags & EN_OBTRL) == 0;
2017
2018 #ifdef EN_DIAG
2019 if ((need - MID_TBD_SIZE) % MID_ATMDATASZ)
2020 printf("%s: tx%d: bogus transmit needs (%d)\n", sc->sc_dev.dv_xname, chan,
2021 need);
2022 #endif
2023 #ifdef EN_DEBUG
2024 printf("%s: tx%d: launch mbuf %p! cur=0x%x[%d], need=%d, addtail=%d\n",
2025 sc->sc_dev.dv_xname, chan, l->t, cur, (cur-start)/4, need, addtail);
2026 count = EN_READ(sc, MIDX_PLACE(chan));
2027 printf(" HW: base_address=0x%x, size=%d, read=%d, descstart=%d\n",
2028 MIDX_BASE(count), MIDX_SZ(count), EN_READ(sc, MIDX_READPTR(chan)),
2029 EN_READ(sc, MIDX_DESCSTART(chan)));
2030 #endif
2031
2032
2033
2034
2035
2036
2037 if ((l->atm_flags & EN_OBHDR) == 0) {
2038 #ifdef EN_DEBUG
2039 printf("%s: tx%d: insert header 0x%x 0x%x\n", sc->sc_dev.dv_xname,
2040 chan, l->tbd1, l->tbd2);
2041 #endif
2042 EN_WRITE(sc, cur, l->tbd1);
2043 EN_WRAPADD(start, stop, cur, 4);
2044 EN_WRITE(sc, cur, l->tbd2);
2045 EN_WRAPADD(start, stop, cur, 4);
2046 need -= 8;
2047 }
2048
2049
2050
2051
2052
2053 for (tmp = l->t ; tmp != NULL ; tmp = tmp->m_next) {
2054
2055
2056 data = mtod(tmp, u_int32_t *);
2057 len = tmp->m_len;
2058 if (tmp == l->t) {
2059 data += sizeof(struct atm_pseudohdr)/sizeof(u_int32_t);
2060 len -= sizeof(struct atm_pseudohdr);
2061 }
2062
2063
2064 if (l->nodma || (len < EN_MINDMA &&
2065 (len % 4) == 0 && ((unsigned long) data % 4) == 0 && (cur % 4) == 0)) {
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075 len = roundup(len, sizeof(u_int32_t));
2076 datastop = data + (len / sizeof(u_int32_t));
2077
2078 while (data != datastop) {
2079 EN_WRITEDAT(sc, cur, *data);
2080 data++;
2081 EN_WRAPADD(start, stop, cur, 4);
2082 }
2083 need -= len;
2084 #ifdef EN_DEBUG
2085 printf("%s: tx%d: copied %d bytes (%d left, cur now 0x%x)\n",
2086 sc->sc_dev.dv_xname, chan, len, need, cur);
2087 #endif
2088 continue;
2089 }
2090
2091
2092 if (dma != cur) {
2093 EN_DTQADD(sc, WORD_IDX(start,cur), chan, MIDDMA_JK, 0, 0, 0);
2094 #ifdef EN_DEBUG
2095 printf("%s: tx%d: dtq_sync: advance pointer to %d\n",
2096 sc->sc_dev.dv_xname, chan, cur);
2097 #endif
2098 }
2099
2100
2101
2102
2103
2104
2105
2106 if (tmp->m_next == NULL) {
2107 cnt = (need - len) % sizeof(u_int32_t);
2108 if (cnt && M_TRAILINGSPACE(tmp) >= cnt)
2109 len += cnt;
2110 }
2111
2112 #if !defined(MIDWAY_ENIONLY)
2113
2114
2115
2116
2117
2118 if (sc->is_adaptec) {
2119
2120 need -= len;
2121 EN_WRAPADD(start, stop, cur, len);
2122 #ifdef EN_DEBUG
2123 printf("%s: tx%d: adp_dma %d bytes (%d left, cur now 0x%x)\n",
2124 sc->sc_dev.dv_xname, chan, len, need, cur);
2125 #endif
2126 end = (need == 0) ? MID_DMA_END : 0;
2127 EN_DTQADD(sc, len, chan, 0, vtophys(data), l->mlen, end);
2128 if (end)
2129 goto done;
2130 dma = cur;
2131 continue;
2132 }
2133 #endif
2134
2135 #if !defined(MIDWAY_ADPONLY)
2136
2137
2138
2139
2140
2141
2142 needalign = (unsigned long) data % sizeof(u_int32_t);
2143 if (needalign) {
2144 EN_COUNT(sc->headbyte);
2145 cnt = sizeof(u_int32_t) - needalign;
2146 if (cnt == 2 && len >= cnt) {
2147 count = 1;
2148 bcode = MIDDMA_2BYTE;
2149 } else {
2150 cnt = min(cnt, len);
2151 count = cnt;
2152 bcode = MIDDMA_BYTE;
2153 }
2154 need -= cnt;
2155 EN_WRAPADD(start, stop, cur, cnt);
2156 #ifdef EN_DEBUG
2157 printf("%s: tx%d: small al_dma %d bytes (%d left, cur now 0x%x)\n",
2158 sc->sc_dev.dv_xname, chan, cnt, need, cur);
2159 #endif
2160 len -= cnt;
2161 end = (need == 0) ? MID_DMA_END : 0;
2162 EN_DTQADD(sc, count, chan, bcode, vtophys(data), l->mlen, end);
2163 if (end)
2164 goto done;
2165 data = (u_int32_t *) ((u_char *)data + cnt);
2166 }
2167
2168
2169 if (sc->alburst &&
2170 (needalign = (((unsigned long) data) & sc->bestburstmask)) != 0
2171 && len >= sizeof(u_int32_t)) {
2172 cnt = sc->bestburstlen - needalign;
2173 mx = len & ~(sizeof(u_int32_t)-1);
2174 if (cnt > mx) {
2175 cnt = mx;
2176 count = cnt / sizeof(u_int32_t);
2177 bcode = MIDDMA_WORD;
2178 } else {
2179 count = cnt / sizeof(u_int32_t);
2180 bcode = en_dmaplan[count].bcode;
2181 count = cnt >> en_dmaplan[count].divshift;
2182 }
2183 need -= cnt;
2184 EN_WRAPADD(start, stop, cur, cnt);
2185 #ifdef EN_DEBUG
2186 printf("%s: tx%d: al_dma %d bytes (%d left, cur now 0x%x)\n",
2187 sc->sc_dev.dv_xname, chan, cnt, need, cur);
2188 #endif
2189 len -= cnt;
2190 end = (need == 0) ? MID_DMA_END : 0;
2191 EN_DTQADD(sc, count, chan, bcode, vtophys(data), l->mlen, end);
2192 if (end)
2193 goto done;
2194 data = (u_int32_t *) ((u_char *)data + cnt);
2195 }
2196
2197
2198 if (len >= sc->bestburstlen) {
2199 count = len >> sc->bestburstshift;
2200 cnt = count << sc->bestburstshift;
2201 bcode = sc->bestburstcode;
2202 need -= cnt;
2203 EN_WRAPADD(start, stop, cur, cnt);
2204 #ifdef EN_DEBUG
2205 printf("%s: tx%d: best_dma %d bytes (%d left, cur now 0x%x)\n",
2206 sc->sc_dev.dv_xname, chan, cnt, need, cur);
2207 #endif
2208 len -= cnt;
2209 end = (need == 0) ? MID_DMA_END : 0;
2210 EN_DTQADD(sc, count, chan, bcode, vtophys(data), l->mlen, end);
2211 if (end)
2212 goto done;
2213 data = (u_int32_t *) ((u_char *)data + cnt);
2214 }
2215
2216
2217 cnt = len & ~(sizeof(u_int32_t)-1);
2218 if (cnt) {
2219 count = cnt / sizeof(u_int32_t);
2220 bcode = en_dmaplan[count].bcode;
2221 count = cnt >> en_dmaplan[count].divshift;
2222 need -= cnt;
2223 EN_WRAPADD(start, stop, cur, cnt);
2224 #ifdef EN_DEBUG
2225 printf("%s: tx%d: cleanup_dma %d bytes (%d left, cur now 0x%x)\n",
2226 sc->sc_dev.dv_xname, chan, cnt, need, cur);
2227 #endif
2228 len -= cnt;
2229 end = (need == 0) ? MID_DMA_END : 0;
2230 EN_DTQADD(sc, count, chan, bcode, vtophys(data), l->mlen, end);
2231 if (end)
2232 goto done;
2233 data = (u_int32_t *) ((u_char *)data + cnt);
2234 }
2235
2236
2237 if (len) {
2238 EN_COUNT(sc->tailbyte);
2239 if (len == 2) {
2240 count = 1;
2241 bcode = MIDDMA_2BYTE;
2242 } else {
2243 count = len;
2244 bcode = MIDDMA_BYTE;
2245 }
2246 need -= len;
2247 EN_WRAPADD(start, stop, cur, len);
2248 #ifdef EN_DEBUG
2249 printf("%s: tx%d: byte cleanup_dma %d bytes (%d left, cur now 0x%x)\n",
2250 sc->sc_dev.dv_xname, chan, len, need, cur);
2251 #endif
2252 end = (need == 0) ? MID_DMA_END : 0;
2253 EN_DTQADD(sc, count, chan, bcode, vtophys(data), l->mlen, end);
2254 if (end)
2255 goto done;
2256 }
2257
2258 dma = cur;
2259 #endif
2260
2261 }
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277 if (addtail) {
2278
2279 pad = need % sizeof(u_int32_t);
2280 if (pad) {
2281
2282
2283
2284
2285 bcode = (sc->is_adaptec) ? 0 : MIDDMA_BYTE;
2286 EN_COUNT(sc->tailflush);
2287 EN_WRAPADD(start, stop, cur, pad);
2288 EN_DTQADD(sc, pad, chan, bcode, vtophys(l->t->m_data), 0, 0);
2289 need -= pad;
2290 #ifdef EN_DEBUG
2291 printf("%s: tx%d: pad/FLUSH dma %d bytes (%d left, cur now 0x%x)\n",
2292 sc->sc_dev.dv_xname, chan, pad, need, cur);
2293 #endif
2294 }
2295
2296
2297 pad = need / sizeof(u_int32_t);
2298 if (l->aal == MID_TBD_AAL5)
2299 pad -= 2;
2300 #ifdef EN_DEBUG
2301 printf("%s: tx%d: padding %d bytes (cur now 0x%x)\n",
2302 sc->sc_dev.dv_xname, chan, pad * sizeof(u_int32_t), cur);
2303 #endif
2304 while (pad--) {
2305 EN_WRITEDAT(sc, cur, 0);
2306 EN_WRAPADD(start, stop, cur, 4);
2307 }
2308 if (l->aal == MID_TBD_AAL5) {
2309 EN_WRITE(sc, cur, l->pdu1);
2310 EN_WRAPADD(start, stop, cur, 8);
2311 }
2312 }
2313
2314 if (addtail || dma != cur) {
2315
2316 EN_DTQADD(sc, WORD_IDX(start,cur), chan, MIDDMA_JK, 0,
2317 l->mlen, MID_DMA_END);
2318
2319 }
2320
2321 done:
2322
2323 sc->txslot[chan].cur = cur;
2324 #ifdef EN_DEBUG
2325 printf("%s: tx%d: DONE! cur now = 0x%x\n",
2326 sc->sc_dev.dv_xname, chan, cur);
2327 #endif
2328
2329 return;
2330 }
2331
2332
2333
2334
2335
2336
2337 EN_INTR_TYPE en_intr(arg)
2338
2339 void *arg;
2340
2341 {
2342 struct en_softc *sc = (struct en_softc *) arg;
2343 struct mbuf *m;
2344 struct atm_pseudohdr ah;
2345 u_int32_t reg, kick, val, mask, chip, vci, slot, dtq, drq;
2346 int lcv, idx, need_softserv = 0;
2347
2348 reg = EN_READ(sc, MID_INTACK);
2349
2350 if ((reg & MID_INT_ANY) == 0)
2351 EN_INTR_RET(0);
2352
2353 #ifdef EN_DEBUG
2354 printf("%s: interrupt=0x%b\n", sc->sc_dev.dv_xname, reg, MID_INTBITS);
2355 #endif
2356
2357
2358
2359
2360
2361 if ((reg & (MID_INT_IDENT|MID_INT_LERR|MID_INT_DMA_ERR|MID_INT_SUNI)) != 0) {
2362 printf("%s: unexpected interrupt=0x%b, resetting card\n",
2363 sc->sc_dev.dv_xname, reg, MID_INTBITS);
2364 #ifdef EN_DEBUG
2365 #ifdef DDB
2366 Debugger();
2367 #endif
2368 sc->enif.if_flags &= ~IFF_RUNNING;
2369 #else
2370 en_reset(sc);
2371 en_init(sc);
2372 #endif
2373 EN_INTR_RET(1);
2374 }
2375
2376
2377
2378
2379
2380 kick = 0;
2381 if (reg & MID_INT_TX) {
2382
2383
2384
2385
2386
2387
2388 for (mask = 1, lcv = 0 ; lcv < EN_NTX ; lcv++, mask = mask * 2) {
2389 if (reg & MID_TXCHAN(lcv)) {
2390 kick = kick | mask;
2391 val = EN_READ(sc, MIDX_READPTR(lcv));
2392 val = (val * sizeof(u_int32_t)) + sc->txslot[lcv].start;
2393
2394 if (val > sc->txslot[lcv].cur)
2395 sc->txslot[lcv].bfree = val - sc->txslot[lcv].cur;
2396 else
2397 sc->txslot[lcv].bfree = (val + (EN_TXSZ*1024)) - sc->txslot[lcv].cur;
2398 #ifdef EN_DEBUG
2399 printf("%s: tx%d: transmit done. %d bytes now free in buffer\n",
2400 sc->sc_dev.dv_xname, lcv, sc->txslot[lcv].bfree);
2401 #endif
2402 }
2403 }
2404 }
2405
2406 if (reg & MID_INT_DMA_TX) {
2407
2408
2409
2410
2411
2412
2413 val = EN_READ(sc, MID_DMA_RDTX);
2414 idx = MID_DTQ_A2REG(sc->dtq_chip);
2415 if (sc->need_dtqs) {
2416 kick = MID_NTX_CH - 1;
2417 sc->need_dtqs = 0;
2418 #ifdef EN_DEBUG
2419 printf("%s: cleared need DTQ condition\n", sc->sc_dev.dv_xname);
2420 #endif
2421 }
2422 while (idx != val) {
2423 sc->dtq_free++;
2424 if ((dtq = sc->dtq[idx]) != 0) {
2425 sc->dtq[idx] = 0;
2426 slot = EN_DQ_SLOT(dtq);
2427 IF_DEQUEUE(&sc->txslot[slot].indma, m);
2428 if (!m) panic("enintr: dtqsync");
2429 sc->txslot[slot].mbsize -= EN_DQ_LEN(dtq);
2430 #ifdef EN_DEBUG
2431 printf("%s: tx%d: free %d dma bytes, mbsize now %d\n",
2432 sc->sc_dev.dv_xname, slot, EN_DQ_LEN(dtq),
2433 sc->txslot[slot].mbsize);
2434 #endif
2435 m_freem(m);
2436 }
2437 EN_WRAPADD(0, MID_DTQ_N, idx, 1);
2438 }
2439 sc->dtq_chip = MID_DTQ_REG2A(val);
2440 }
2441
2442
2443
2444
2445
2446
2447 if (kick) {
2448 #ifdef EN_DEBUG
2449 printf("%s: tx kick mask = 0x%x\n", sc->sc_dev.dv_xname, kick);
2450 #endif
2451 for (mask = 1, lcv = 0 ; lcv < EN_NTX ; lcv++, mask = mask * 2) {
2452 if ((kick & mask) && sc->txslot[lcv].q.ifq_head) {
2453 en_txdma(sc, lcv);
2454 }
2455 }
2456 }
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467 if (reg & MID_INT_DMA_RX) {
2468 val = EN_READ(sc, MID_DMA_RDRX);
2469 idx = MID_DRQ_A2REG(sc->drq_chip);
2470 while (idx != val) {
2471 sc->drq_free++;
2472 if ((drq = sc->drq[idx]) != 0) {
2473 sc->drq[idx] = 0;
2474 slot = EN_DQ_SLOT(drq);
2475 if (EN_DQ_LEN(drq) == 0) {
2476 m = NULL;
2477 } else {
2478 IF_DEQUEUE(&sc->rxslot[slot].indma, m);
2479 if (!m) {
2480 panic("enintr: drqsync: %s: lost mbuf in slot %d!",
2481 sc->sc_dev.dv_xname, slot);
2482 }
2483 }
2484
2485 if (sc->rxslot[slot].oth_flags & ENOTHER_DRAIN) {
2486 if (m)
2487 m_freem(m);
2488 vci = sc->rxslot[slot].atm_vci;
2489 if (sc->rxslot[slot].indma.ifq_head == NULL &&
2490 sc->rxslot[slot].q.ifq_head == NULL &&
2491 (EN_READ(sc, MID_VC(vci)) & MIDV_INSERVICE) == 0 &&
2492 (sc->rxslot[slot].oth_flags & ENOTHER_SWSL) == 0) {
2493 sc->rxslot[slot].oth_flags = ENOTHER_FREE;
2494 sc->rxslot[slot].atm_vci = RX_NONE;
2495 sc->rxvc2slot[vci] = RX_NONE;
2496 #ifdef EN_DEBUG
2497 printf("%s: rx%d: VCI %d now free\n", sc->sc_dev.dv_xname,
2498 slot, vci);
2499 #endif
2500 }
2501 } else if (m != NULL) {
2502 ATM_PH_FLAGS(&ah) = sc->rxslot[slot].atm_flags;
2503 ATM_PH_VPI(&ah) = 0;
2504 ATM_PH_SETVCI(&ah, sc->rxslot[slot].atm_vci);
2505 #ifdef EN_DEBUG
2506 printf("%s: rx%d: rxvci%d: atm_input, mbuf %p, len %d, hand %p\n",
2507 sc->sc_dev.dv_xname, slot, sc->rxslot[slot].atm_vci, m,
2508 EN_DQ_LEN(drq), sc->rxslot[slot].rxhand);
2509 #endif
2510 sc->enif.if_ipackets++;
2511
2512 #if NBPFILTER > 0
2513 if (sc->enif.if_bpf)
2514 bpf_mtap(sc->enif.if_bpf, m, BPF_DIRECTION_IN);
2515 #endif
2516
2517 atm_input(&sc->enif, &ah, m, sc->rxslot[slot].rxhand);
2518 }
2519
2520 }
2521 EN_WRAPADD(0, MID_DRQ_N, idx, 1);
2522 }
2523 sc->drq_chip = MID_DRQ_REG2A(val);
2524
2525 if (sc->need_drqs) {
2526 need_softserv = 1;
2527 sc->need_drqs = 0;
2528 #ifdef EN_DEBUG
2529 printf("%s: cleared need DRQ condition\n", sc->sc_dev.dv_xname);
2530 #endif
2531 }
2532 }
2533
2534
2535
2536
2537
2538 if (reg & MID_INT_SERVICE) {
2539 chip = MID_SL_REG2A(EN_READ(sc, MID_SERV_WRITE));
2540
2541 while (sc->hwslistp != chip) {
2542
2543
2544 vci = EN_READ(sc, sc->hwslistp);
2545 EN_WRAPADD(MID_SLOFF, MID_SLEND, sc->hwslistp, 4);
2546 slot = sc->rxvc2slot[vci];
2547 if (slot == RX_NONE) {
2548 #ifdef EN_DEBUG
2549 printf("%s: unexpected rx interrupt on VCI %d\n",
2550 sc->sc_dev.dv_xname, vci);
2551 #endif
2552 EN_WRITE(sc, MID_VC(vci), MIDV_TRASH);
2553 continue;
2554 }
2555 EN_WRITE(sc, MID_VC(vci), sc->rxslot[slot].mode);
2556 EN_COUNT(sc->hwpull);
2557
2558 #ifdef EN_DEBUG
2559 printf("%s: pulled VCI %d off hwslist\n", sc->sc_dev.dv_xname, vci);
2560 #endif
2561
2562
2563 if ((sc->rxslot[slot].oth_flags & ENOTHER_SWSL) == 0) {
2564 EN_COUNT(sc->swadd);
2565 need_softserv = 1;
2566 sc->rxslot[slot].oth_flags |= ENOTHER_SWSL;
2567 sc->swslist[sc->swsl_tail] = slot;
2568 EN_WRAPADD(0, MID_SL_N, sc->swsl_tail, 1);
2569 sc->swsl_size++;
2570 #ifdef EN_DEBUG
2571 printf("%s: added VCI %d to swslist\n", sc->sc_dev.dv_xname, vci);
2572 #endif
2573 }
2574 }
2575 }
2576
2577
2578
2579
2580
2581 if (need_softserv)
2582 en_service(sc);
2583
2584
2585
2586
2587
2588 if (reg & MID_INT_DMA_OVR) {
2589 EN_COUNT(sc->dmaovr);
2590 #ifdef EN_DEBUG
2591 printf("%s: MID_INT_DMA_OVR\n", sc->sc_dev.dv_xname);
2592 #endif
2593 }
2594 reg = EN_READ(sc, MID_STAT);
2595 #ifdef EN_STAT
2596 sc->otrash += MID_OTRASH(reg);
2597 sc->vtrash += MID_VTRASH(reg);
2598 #endif
2599
2600 EN_INTR_RET(1);
2601 }
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622 STATIC void en_service(sc)
2623
2624 struct en_softc *sc;
2625
2626 {
2627 struct mbuf *m, *tmp;
2628 u_int32_t cur, dstart, rbd, pdu, *sav, dma, bcode, count, *data, *datastop;
2629 u_int32_t start, stop, cnt, needalign;
2630 int slot, raw, aal5, llc, vci, fill, mlen, tlen, drqneed, need, needfill, end;
2631
2632 aal5 = 0;
2633 next_vci:
2634 if (sc->swsl_size == 0) {
2635 #ifdef EN_DEBUG
2636 printf("%s: en_service done\n", sc->sc_dev.dv_xname);
2637 #endif
2638 return;
2639 }
2640
2641
2642
2643
2644
2645 slot = sc->swslist[sc->swsl_head];
2646 vci = sc->rxslot[slot].atm_vci;
2647 #ifdef EN_DIAG
2648 if (sc->rxvc2slot[vci] != slot) panic("en_service rx slot/vci sync");
2649 #endif
2650
2651
2652
2653
2654
2655 raw = sc->rxslot[slot].oth_flags & ENOTHER_RAW;
2656 start= sc->rxslot[slot].start;
2657 stop= sc->rxslot[slot].stop;
2658 cur = sc->rxslot[slot].cur;
2659
2660 #ifdef EN_DEBUG
2661 printf("%s: rx%d: service vci=%d raw=%d start/stop/cur=0x%x 0x%x 0x%x\n",
2662 sc->sc_dev.dv_xname, slot, vci, raw, start, stop, cur);
2663 #endif
2664
2665 same_vci:
2666 dstart = MIDV_DSTART(EN_READ(sc, MID_DST_RP(vci)));
2667 dstart = (dstart * sizeof(u_int32_t)) + start;
2668
2669
2670 if (dstart == cur) {
2671 defer:
2672 EN_WRAPADD(0, MID_SL_N, sc->swsl_head, 1);
2673 sc->rxslot[slot].oth_flags &= ~ENOTHER_SWSL;
2674 sc->swsl_size--;
2675
2676 #ifdef EN_DEBUG
2677 printf("%s: rx%d: remove vci %d from swslist\n",
2678 sc->sc_dev.dv_xname, slot, vci);
2679 #endif
2680 goto next_vci;
2681 }
2682
2683
2684
2685
2686
2687
2688 if (raw) {
2689
2690
2691 fill = 0;
2692 if (dstart > cur)
2693 mlen = dstart - cur;
2694 else
2695 mlen = (dstart + (EN_RXSZ*1024)) - cur;
2696
2697 if (mlen < sc->rxslot[slot].raw_threshold)
2698 goto defer;
2699
2700 } else {
2701
2702
2703 aal5 = (sc->rxslot[slot].atm_flags & ATM_PH_AAL5);
2704 llc = (aal5 && (sc->rxslot[slot].atm_flags & ATM_PH_LLCSNAP)) ? 1 : 0;
2705 rbd = EN_READ(sc, cur);
2706 if (MID_RBD_ID(rbd) != MID_RBD_STDID)
2707 panic("en_service: id mismatch");
2708
2709 if (rbd & MID_RBD_T) {
2710 mlen = 0;
2711 fill = MID_RBD_SIZE;
2712 EN_COUNT(sc->ttrash);
2713 } else if (!aal5) {
2714 mlen = MID_RBD_SIZE + MID_CHDR_SIZE + MID_ATMDATASZ;
2715 fill = 0;
2716 } else {
2717 tlen = (MID_RBD_CNT(rbd) * MID_ATMDATASZ) + MID_RBD_SIZE;
2718 pdu = cur + tlen - MID_PDU_SIZE;
2719 if (pdu >= stop)
2720 pdu -= (EN_RXSZ*1024);
2721 pdu = EN_READ(sc, pdu);
2722 fill = tlen - MID_RBD_SIZE - MID_PDU_LEN(pdu);
2723 if (fill < 0 || (rbd & MID_RBD_CRCERR) != 0) {
2724 printf("%s: %s, dropping frame\n", sc->sc_dev.dv_xname,
2725 (rbd & MID_RBD_CRCERR) ? "CRC error" : "invalid AAL5 PDU length");
2726 printf("%s: got %d cells (%d bytes), AAL5 len is %d bytes (pdu=0x%x)\n",
2727 sc->sc_dev.dv_xname, MID_RBD_CNT(rbd), tlen - MID_RBD_SIZE,
2728 MID_PDU_LEN(pdu), pdu);
2729 fill = tlen;
2730 }
2731 mlen = tlen - fill;
2732 }
2733
2734 }
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749 m = sc->rxslot[slot].q.ifq_head;
2750 drqneed = 1;
2751 if (m) {
2752 sav = mtod(m, u_int32_t *);
2753 if (sav[0] != cur) {
2754 #ifdef EN_DEBUG
2755 printf("%s: rx%d: q'ed mbuf %p not ours\n",
2756 sc->sc_dev.dv_xname, slot, m);
2757 #endif
2758 m = NULL;
2759 EN_COUNT(sc->rxqnotus);
2760 } else {
2761 EN_COUNT(sc->rxqus);
2762 IF_DEQUEUE(&sc->rxslot[slot].q, m);
2763 drqneed = sav[1];
2764 #ifdef EN_DEBUG
2765 printf("%s: rx%d: recovered q'ed mbuf %p (drqneed=%d)\n",
2766 sc->sc_dev.dv_xname, slot, m, drqneed);
2767 #endif
2768 }
2769 }
2770
2771 if (mlen != 0 && m == NULL) {
2772 m = en_mget(sc, mlen, &drqneed);
2773 if (m == NULL) {
2774 fill += mlen;
2775 mlen = 0;
2776 EN_COUNT(sc->rxmbufout);
2777 #ifdef EN_DEBUG
2778 printf("%s: rx%d: out of mbufs\n", sc->sc_dev.dv_xname, slot);
2779 #endif
2780 }
2781 #ifdef EN_DEBUG
2782 printf("%s: rx%d: allocate mbuf %p, mlen=%d, drqneed=%d\n",
2783 sc->sc_dev.dv_xname, slot, m, mlen, drqneed);
2784 #endif
2785 }
2786
2787 #ifdef EN_DEBUG
2788 printf("%s: rx%d: VCI %d, mbuf_chain %p, mlen %d, fill %d\n",
2789 sc->sc_dev.dv_xname, slot, vci, m, mlen, fill);
2790 #endif
2791
2792
2793
2794
2795
2796
2797 needfill = (fill) ? 1 : 0;
2798 if (drqneed + needfill > sc->drq_free) {
2799 sc->need_drqs = 1;
2800 if (m == NULL) {
2801 EN_COUNT(sc->rxoutboth);
2802 #ifdef EN_DEBUG
2803 printf("%s: rx%d: out of DRQs *and* mbufs!\n", sc->sc_dev.dv_xname, slot);
2804 #endif
2805 return;
2806 }
2807 sav = mtod(m, u_int32_t *);
2808 sav[0] = cur;
2809 sav[1] = drqneed;
2810 IF_ENQUEUE(&sc->rxslot[slot].q, m);
2811 EN_COUNT(sc->rxdrqout);
2812 #ifdef EN_DEBUG
2813 printf("%s: rx%d: out of DRQs\n", sc->sc_dev.dv_xname, slot);
2814 #endif
2815 return;
2816 }
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833 dma = cur;
2834 need = roundup(mlen, sizeof(u_int32_t));
2835 fill = fill - (need - mlen);
2836
2837 for (tmp = m ; tmp != NULL && need > 0 ; tmp = tmp->m_next) {
2838 tlen = roundup(tmp->m_len, sizeof(u_int32_t));
2839 data = mtod(tmp, u_int32_t *);
2840
2841 #ifdef EN_DEBUG
2842 printf("%s: rx%d: load mbuf %p, m_len=%d, m_data=%p, tlen=%d\n",
2843 sc->sc_dev.dv_xname, slot, tmp, tmp->m_len, tmp->m_data, tlen);
2844 #endif
2845
2846
2847 if (EN_NORXDMA || !en_dma || tlen < EN_MINDMA) {
2848 datastop = (u_int32_t *)((u_char *) data + tlen);
2849
2850 while (data != datastop) {
2851 *data = EN_READDAT(sc, cur);
2852 data++;
2853 EN_WRAPADD(start, stop, cur, 4);
2854 }
2855 need -= tlen;
2856 #ifdef EN_DEBUG
2857 printf("%s: rx%d: vci%d: copied %d bytes (%d left)\n",
2858 sc->sc_dev.dv_xname, slot, vci, tlen, need);
2859 #endif
2860 continue;
2861 }
2862
2863
2864 if (dma != cur) {
2865 EN_DRQADD(sc, WORD_IDX(start,cur), vci, MIDDMA_JK, 0, 0, 0, 0);
2866 #ifdef EN_DEBUG
2867 printf("%s: rx%d: vci%d: drq_sync: advance pointer to %d\n",
2868 sc->sc_dev.dv_xname, slot, vci, cur);
2869 #endif
2870 }
2871
2872 #if !defined(MIDWAY_ENIONLY)
2873
2874
2875
2876
2877
2878 if (sc->is_adaptec) {
2879 need -= tlen;
2880 EN_WRAPADD(start, stop, cur, tlen);
2881 #ifdef EN_DEBUG
2882 printf("%s: rx%d: vci%d: adp_dma %d bytes (%d left)\n",
2883 sc->sc_dev.dv_xname, slot, vci, tlen, need);
2884 #endif
2885 end = (need == 0 && !fill) ? MID_DMA_END : 0;
2886 EN_DRQADD(sc, tlen, vci, 0, vtophys(data), mlen, slot, end);
2887 if (end)
2888 goto done;
2889 dma = cur;
2890 continue;
2891 }
2892 #endif
2893
2894
2895 #if !defined(MIDWAY_ADPONLY)
2896
2897
2898
2899
2900
2901
2902 if (sc->alburst &&
2903 (needalign = (((unsigned long) data) & sc->bestburstmask)) != 0) {
2904 cnt = sc->bestburstlen - needalign;
2905 if (cnt > tlen) {
2906 cnt = tlen;
2907 count = cnt / sizeof(u_int32_t);
2908 bcode = MIDDMA_WORD;
2909 } else {
2910 count = cnt / sizeof(u_int32_t);
2911 bcode = en_dmaplan[count].bcode;
2912 count = cnt >> en_dmaplan[count].divshift;
2913 }
2914 need -= cnt;
2915 EN_WRAPADD(start, stop, cur, cnt);
2916 #ifdef EN_DEBUG
2917 printf("%s: rx%d: vci%d: al_dma %d bytes (%d left)\n",
2918 sc->sc_dev.dv_xname, slot, vci, cnt, need);
2919 #endif
2920 tlen -= cnt;
2921 end = (need == 0 && !fill) ? MID_DMA_END : 0;
2922 EN_DRQADD(sc, count, vci, bcode, vtophys(data), mlen, slot, end);
2923 if (end)
2924 goto done;
2925 data = (u_int32_t *)((u_char *) data + cnt);
2926 }
2927
2928
2929 if (tlen >= sc->bestburstlen) {
2930 count = tlen >> sc->bestburstshift;
2931 cnt = count << sc->bestburstshift;
2932 bcode = sc->bestburstcode;
2933 need -= cnt;
2934 EN_WRAPADD(start, stop, cur, cnt);
2935 #ifdef EN_DEBUG
2936 printf("%s: rx%d: vci%d: best_dma %d bytes (%d left)\n",
2937 sc->sc_dev.dv_xname, slot, vci, cnt, need);
2938 #endif
2939 tlen -= cnt;
2940 end = (need == 0 && !fill) ? MID_DMA_END : 0;
2941 EN_DRQADD(sc, count, vci, bcode, vtophys(data), mlen, slot, end);
2942 if (end)
2943 goto done;
2944 data = (u_int32_t *)((u_char *) data + cnt);
2945 }
2946
2947
2948 if (tlen) {
2949 count = tlen / sizeof(u_int32_t);
2950 bcode = en_dmaplan[count].bcode;
2951 count = tlen >> en_dmaplan[count].divshift;
2952 need -= tlen;
2953 EN_WRAPADD(start, stop, cur, tlen);
2954 #ifdef EN_DEBUG
2955 printf("%s: rx%d: vci%d: cleanup_dma %d bytes (%d left)\n",
2956 sc->sc_dev.dv_xname, slot, vci, tlen, need);
2957 #endif
2958 end = (need == 0 && !fill) ? MID_DMA_END : 0;
2959 EN_DRQADD(sc, count, vci, bcode, vtophys(data), mlen, slot, end);
2960 if (end)
2961 goto done;
2962 }
2963
2964 dma = cur;
2965
2966 #endif
2967
2968 }
2969
2970
2971 if (fill || dma != cur) {
2972 #ifdef EN_DEBUG
2973 if (fill)
2974 printf("%s: rx%d: vci%d: skipping %d bytes of fill\n",
2975 sc->sc_dev.dv_xname, slot, vci, fill);
2976 else
2977 printf("%s: rx%d: vci%d: syncing chip from 0x%x to 0x%x [cur]\n",
2978 sc->sc_dev.dv_xname, slot, vci, dma, cur);
2979 #endif
2980 EN_WRAPADD(start, stop, cur, fill);
2981 EN_DRQADD(sc, WORD_IDX(start,cur), vci, MIDDMA_JK, 0, mlen,
2982 slot, MID_DMA_END);
2983
2984 }
2985
2986
2987
2988
2989
2990
2991
2992
2993 done:
2994 if (m) {
2995 if (!raw) {
2996 cnt = MID_RBD_SIZE;
2997 if (!aal5) cnt += MID_CHDR_SIZE;
2998 m->m_len -= cnt;
2999 m->m_pkthdr.len -= cnt;
3000 m->m_data += cnt;
3001 }
3002 IF_ENQUEUE(&sc->rxslot[slot].indma, m);
3003 }
3004 sc->rxslot[slot].cur = cur;
3005
3006 #ifdef EN_DEBUG
3007 printf("%s: rx%d: vci%d: DONE! cur now =0x%x\n",
3008 sc->sc_dev.dv_xname, slot, vci, cur);
3009 #endif
3010
3011 goto same_vci;
3012 }
3013
3014
3015 #ifdef EN_DDBHOOK
3016
3017
3018
3019
3020
3021
3022
3023
3024 #define END_SWSL 0x00000040
3025 #define END_DRQ 0x00000020
3026 #define END_DTQ 0x00000010
3027 #define END_RX 0x00000008
3028 #define END_TX 0x00000004
3029 #define END_MREGS 0x00000002
3030 #define END_STATS 0x00000001
3031
3032 #define END_BITS "\20\7SWSL\6DRQ\5DTQ\4RX\3TX\2MREGS\1STATS"
3033
3034 int en_dump(unit, level)
3035
3036 int unit, level;
3037
3038 {
3039 struct en_softc *sc;
3040 int lcv, cnt, slot;
3041 u_int32_t ptr, reg;
3042
3043 for (lcv = 0 ; lcv < en_cd.cd_ndevs ; lcv++) {
3044 sc = (struct en_softc *) en_cd.cd_devs[lcv];
3045 if (sc == NULL) continue;
3046 if (unit != -1 && unit != lcv)
3047 continue;
3048
3049 printf("dumping device %s at level 0x%b\n", sc->sc_dev.dv_xname, level,
3050 END_BITS);
3051
3052 if (sc->dtq_us == 0) {
3053 printf("<hasn't been en_init'd yet>\n");
3054 continue;
3055 }
3056
3057 if (level & END_STATS) {
3058 printf(" en_stats:\n");
3059 printf(" %d mfix (%d failed); %d/%d head/tail byte DMAs, %d flushes\n",
3060 sc->mfix, sc->mfixfail, sc->headbyte, sc->tailbyte, sc->tailflush);
3061 printf(" %d rx dma overflow interrupts\n", sc->dmaovr);
3062 printf(" %d times we ran out of TX space and stalled\n",
3063 sc->txoutspace);
3064 printf(" %d times we ran out of DTQs\n", sc->txdtqout);
3065 printf(" %d times we launched a packet\n", sc->launch);
3066 printf(" %d times we launched without on-board header\n", sc->lheader);
3067 printf(" %d times we launched without on-board tail\n", sc->ltail);
3068 printf(" %d times we pulled the hw service list\n", sc->hwpull);
3069 printf(" %d times we pushed a vci on the sw service list\n",
3070 sc->swadd);
3071 printf(" %d times RX pulled an mbuf from Q that wasn't ours\n",
3072 sc->rxqnotus);
3073 printf(" %d times RX pulled a good mbuf from Q\n", sc->rxqus);
3074 printf(" %d times we ran out of mbufs *and* DRQs\n", sc->rxoutboth);
3075 printf(" %d times we ran out of DRQs\n", sc->rxdrqout);
3076
3077 printf(" %d transmit packets dropped due to mbsize\n", sc->txmbovr);
3078 printf(" %d cells trashed due to turned off rxvc\n", sc->vtrash);
3079 printf(" %d cells trashed due to totally full buffer\n", sc->otrash);
3080 printf(" %d cells trashed due almost full buffer\n", sc->ttrash);
3081 printf(" %d rx mbuf allocation failures\n", sc->rxmbufout);
3082 #ifdef NATM
3083 printf(" %d drops at natmintrq\n", natmintrq.ifq_drops);
3084 #ifdef NATM_STAT
3085 printf(" natmintr so_rcv: ok/drop cnt: %d/%d, ok/drop bytes: %d/%d\n",
3086 natm_sookcnt, natm_sodropcnt, natm_sookbytes, natm_sodropbytes);
3087 #endif
3088 #endif
3089 }
3090
3091 if (level & END_MREGS) {
3092 printf("mregs:\n");
3093 printf("resid = 0x%x\n", EN_READ(sc, MID_RESID));
3094 printf("interrupt status = 0x%b\n",
3095 EN_READ(sc, MID_INTSTAT), MID_INTBITS);
3096 printf("interrupt enable = 0x%b\n",
3097 EN_READ(sc, MID_INTENA), MID_INTBITS);
3098 printf("mcsr = 0x%b\n", EN_READ(sc, MID_MAST_CSR), MID_MCSRBITS);
3099 printf("serv_write = [chip=%d] [us=%d]\n", EN_READ(sc, MID_SERV_WRITE),
3100 MID_SL_A2REG(sc->hwslistp));
3101 printf("dma addr = 0x%x\n", EN_READ(sc, MID_DMA_ADDR));
3102 printf("DRQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3103 MID_DRQ_REG2A(EN_READ(sc, MID_DMA_RDRX)),
3104 MID_DRQ_REG2A(EN_READ(sc, MID_DMA_WRRX)), sc->drq_chip, sc->drq_us);
3105 printf("DTQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3106 MID_DTQ_REG2A(EN_READ(sc, MID_DMA_RDTX)),
3107 MID_DTQ_REG2A(EN_READ(sc, MID_DMA_WRTX)), sc->dtq_chip, sc->dtq_us);
3108
3109 printf(" unusal txspeeds: ");
3110 for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3111 if (sc->txspeed[cnt])
3112 printf(" vci%d=0x%x", cnt, sc->txspeed[cnt]);
3113 printf("\n");
3114
3115 printf(" rxvc slot mappings: ");
3116 for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3117 if (sc->rxvc2slot[cnt] != RX_NONE)
3118 printf(" %d->%d", cnt, sc->rxvc2slot[cnt]);
3119 printf("\n");
3120
3121 }
3122
3123 if (level & END_TX) {
3124 printf("tx:\n");
3125 for (slot = 0 ; slot < EN_NTX; slot++) {
3126 printf("tx%d: start/stop/cur=0x%x/0x%x/0x%x [%d] ", slot,
3127 sc->txslot[slot].start, sc->txslot[slot].stop, sc->txslot[slot].cur,
3128 (sc->txslot[slot].cur - sc->txslot[slot].start)/4);
3129 printf("mbsize=%d, bfree=%d\n", sc->txslot[slot].mbsize,
3130 sc->txslot[slot].bfree);
3131 printf("txhw: base_address=0x%x, size=%d, read=%d, descstart=%d\n",
3132 MIDX_BASE(EN_READ(sc, MIDX_PLACE(slot))),
3133 MIDX_SZ(EN_READ(sc, MIDX_PLACE(slot))),
3134 EN_READ(sc, MIDX_READPTR(slot)), EN_READ(sc, MIDX_DESCSTART(slot)));
3135 }
3136 }
3137
3138 if (level & END_RX) {
3139 printf(" recv slots:\n");
3140 for (slot = 0 ; slot < sc->en_nrx; slot++) {
3141 printf("rx%d: vci=%d: start/stop/cur=0x%x/0x%x/0x%x ", slot,
3142 sc->rxslot[slot].atm_vci, sc->rxslot[slot].start,
3143 sc->rxslot[slot].stop, sc->rxslot[slot].cur);
3144 printf("mode=0x%x, atm_flags=0x%x, oth_flags=0x%x\n",
3145 sc->rxslot[slot].mode, sc->rxslot[slot].atm_flags,
3146 sc->rxslot[slot].oth_flags);
3147 printf("RXHW: mode=0x%x, DST_RP=0x%x, WP_ST_CNT=0x%x\n",
3148 EN_READ(sc, MID_VC(sc->rxslot[slot].atm_vci)),
3149 EN_READ(sc, MID_DST_RP(sc->rxslot[slot].atm_vci)),
3150 EN_READ(sc, MID_WP_ST_CNT(sc->rxslot[slot].atm_vci)));
3151 }
3152 }
3153
3154 if (level & END_DTQ) {
3155 printf(" dtq [need_dtqs=%d,dtq_free=%d]:\n",
3156 sc->need_dtqs, sc->dtq_free);
3157 ptr = sc->dtq_chip;
3158 while (ptr != sc->dtq_us) {
3159 reg = EN_READ(sc, ptr);
3160 printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n",
3161 sc->dtq[MID_DTQ_A2REG(ptr)], MID_DMA_CNT(reg), MID_DMA_TXCHAN(reg),
3162 (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg), EN_READ(sc, ptr+4));
3163 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, ptr, 8);
3164 }
3165 }
3166
3167 if (level & END_DRQ) {
3168 printf(" drq [need_drqs=%d,drq_free=%d]:\n",
3169 sc->need_drqs, sc->drq_free);
3170 ptr = sc->drq_chip;
3171 while (ptr != sc->drq_us) {
3172 reg = EN_READ(sc, ptr);
3173 printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n",
3174 sc->drq[MID_DRQ_A2REG(ptr)], MID_DMA_CNT(reg), MID_DMA_RXVCI(reg),
3175 (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg), EN_READ(sc, ptr+4));
3176 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, ptr, 8);
3177 }
3178 }
3179
3180 if (level & END_SWSL) {
3181 printf(" swslist [size=%d]: ", sc->swsl_size);
3182 for (cnt = sc->swsl_head ; cnt != sc->swsl_tail ;
3183 cnt = (cnt + 1) % MID_SL_N)
3184 printf("0x%x ", sc->swslist[cnt]);
3185 printf("\n");
3186 }
3187
3188 }
3189 return(0);
3190 }
3191
3192
3193
3194
3195
3196 int en_dumpmem(unit, addr, len)
3197
3198 int unit, addr, len;
3199
3200 {
3201 struct en_softc *sc;
3202 u_int32_t reg;
3203
3204 if (unit < 0 || unit >= en_cd.cd_ndevs ||
3205 (sc = (struct en_softc *) en_cd.cd_devs[unit]) == NULL) {
3206 printf("invalid unit number: %d\n", unit);
3207 return(0);
3208 }
3209 addr = addr & ~3;
3210 if (addr < MID_RAMOFF || addr + len*4 > MID_MAXOFF || len <= 0) {
3211 printf("invalid addr/len number: %d, %d\n", addr, len);
3212 return(0);
3213 }
3214 printf("dumping %d words starting at offset 0x%x\n", len, addr);
3215 while (len--) {
3216 reg = EN_READ(sc, addr);
3217 printf("mem[0x%x] = 0x%x\n", addr, reg);
3218 addr += 4;
3219 }
3220 return(0);
3221 }
3222 #endif
3223
3224
3225 #endif