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