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