1/*	$NetBSD: midway.c,v 1.92 2011/02/01 19:50:03 chuck 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.92 2011/02/01 19:50:03 chuck 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
248int en_dma = EN_DMA;			/* use DMA (switch off for dbg) */
249
250/*
251 * autoconfig attachments
252 */
253
254extern struct cfdriver en_cd;
255
256/*
257 * local structures
258 */
259
260/*
261 * params to en_txlaunch() function
262 */
263
264struct 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
285struct en_dmatab {
286  u_int8_t bcode;		/* code */
287  u_int8_t divshift;		/* byte divisor */
288};
289
290static 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
302static 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
314static struct en_dmatab *en_dmaplan = en_dma_planA;
315
316/*
317 * prototypes
318 */
319
320STATIC 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
325STATIC		void en_dmaprobe(struct en_softc *);
326STATIC		int en_dmaprobe_doit(struct en_softc *, u_int8_t *,
327		    u_int8_t *, int);
328STATIC INLINE	int en_dqneed(struct en_softc *, void *, u_int,
329		    u_int) __unused;
330STATIC		void en_init(struct en_softc *);
331STATIC		int en_ioctl(struct ifnet *, EN_IOCTL_CMDT, void *);
332STATIC INLINE	int en_k2sz(int) __unused;
333STATIC		void en_loadvc(struct en_softc *, int);
334STATIC		int en_mfix(struct en_softc *, struct mbuf **,
335		    struct mbuf *);
336STATIC INLINE	struct mbuf *en_mget(struct en_softc *, u_int,
337		    u_int *) __unused;
338STATIC INLINE	u_int32_t en_read(struct en_softc *,
339		    u_int32_t) __unused;
340STATIC		int en_rxctl(struct en_softc *, struct atm_pseudoioctl *, int);
341STATIC		void en_txdma(struct en_softc *, int);
342STATIC		void en_txlaunch(struct en_softc *, int, struct en_launch *);
343STATIC		void en_service(struct en_softc *);
344STATIC		void en_start(struct ifnet *);
345STATIC INLINE	int en_sz2b(int) __unused;
346STATIC INLINE	void en_write(struct en_softc *, u_int32_t,
347		    u_int32_t) __unused;
348
349#ifdef ATM_PVCEXT
350static void rrp_add(struct en_softc *, struct ifnet *);
351static struct ifnet *en_pvcattach(struct ifnet *);
352static int en_txctl(struct en_softc *, int, int, int);
353static int en_pvctx(struct en_softc *, struct pvctxreq *);
354static int en_pvctxget(struct en_softc *, struct pvctxreq *);
355static int en_pcr2txspeed(int);
356static int en_txspeed2pcr(int);
357static 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
479STATIC 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
495STATIC 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
509STATIC 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
531STATIC 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
553STATIC 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
571STATIC 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
632STATIC 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->m_pkthdr.rcvif = &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
683void 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  }
709done_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
889STATIC 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
960int
961en_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
1092STATIC 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_generic(curlwp->l_cred,
1241		     KAUTH_GENERIC_ISSUSER, NULL)) != 0)
1242		    break;
1243
1244		  if ((sifp = en_pvcattach(ifp)) != NULL) {
1245#ifdef __NetBSD__
1246		    strlcpy(ifr->ifr_name, sifp->if_xname,
1247		        sizeof(ifr->ifr_name));
1248#else
1249		    snprintf(ifr->ifr_name, sizeof(ifr->ifr_name), "%s%d",
1250		        sifp->if_name, sifp->if_unit);
1251#endif
1252#if defined(__KAME__) && defined(INET6)
1253		    /* get EUI64 for PVC, from ATM hardware interface */
1254		    in6_ifattach(sifp, ifp);
1255#endif
1256		  }
1257		  else
1258		    error = ENOMEM;
1259		}
1260		else
1261		  error = EINVAL;
1262		break;
1263
1264	case SIOCGPVCTX:
1265		error = en_pvctxget(sc, (struct pvctxreq *)data);
1266		break;
1267
1268	case SIOCSPVCTX:
1269		if ((error = kauth_authorize_network(curlwp->l_cred,
1270		    KAUTH_NETWORK_INTERFACE,
1271		    KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, KAUTH_ARG(cmd),
1272		    NULL)) == 0)
1273			error = en_pvctx(sc, (struct pvctxreq *)data);
1274		break;
1275
1276#endif /* ATM_PVCEXT */
1277
1278	default:
1279	    error = ifioctl_common(ifp, cmd, data);
1280	    break;
1281    }
1282    splx(s);
1283    return error;
1284}
1285
1286
1287/*
1288 * en_rxctl: turn on and off VCs for recv.
1289 */
1290
1291STATIC int en_rxctl(struct en_softc *sc, struct atm_pseudoioctl *pi, int on)
1292{
1293  u_int s, vci, flags, slot;
1294  u_int32_t oldmode, newmode;
1295
1296  vci = ATM_PH_VCI(&pi->aph);
1297  flags = ATM_PH_FLAGS(&pi->aph);
1298
1299#ifdef EN_DEBUG
1300  printf("%s: %s vpi=%d, vci=%d, flags=%d\n", device_xname(sc->sc_dev),
1301	(on) ? "enable" : "disable", ATM_PH_VPI(&pi->aph), vci, flags);
1302#endif
1303
1304  if (ATM_PH_VPI(&pi->aph) || vci >= MID_N_VC)
1305    return(EINVAL);
1306
1307  /*
1308   * turn on VCI!
1309   */
1310
1311  if (on) {
1312    if (sc->rxvc2slot[vci] != RX_NONE)
1313      return(EINVAL);
1314    for (slot = 0 ; slot < sc->en_nrx ; slot++)
1315      if (sc->rxslot[slot].oth_flags & ENOTHER_FREE)
1316	break;
1317    if (slot == sc->en_nrx)
1318      return(ENOSPC);
1319    sc->rxvc2slot[vci] = slot;
1320    sc->rxslot[slot].rxhand = NULL;
1321    oldmode = sc->rxslot[slot].mode;
1322    newmode = (flags & ATM_PH_AAL5) ? MIDV_AAL5 : MIDV_NOAAL;
1323    sc->rxslot[slot].mode = MIDV_SETMODE(oldmode, newmode);
1324    sc->rxslot[slot].atm_vci = vci;
1325    sc->rxslot[slot].atm_flags = flags;
1326    sc->rxslot[slot].oth_flags = 0;
1327    sc->rxslot[slot].rxhand = pi->rxhand;
1328    if (sc->rxslot[slot].indma.ifq_head || sc->rxslot[slot].q.ifq_head)
1329      panic("en_rxctl: left over mbufs on enable");
1330    sc->txspeed[vci] = 0;	/* full speed to start */
1331    sc->txvc2slot[vci] = 0;	/* init value */
1332    sc->txslot[0].nref++;	/* bump reference count */
1333    en_loadvc(sc, vci);		/* does debug printf for us */
1334    return(0);
1335  }
1336
1337  /*
1338   * turn off VCI
1339   */
1340
1341  if (sc->rxvc2slot[vci] == RX_NONE)
1342    return(EINVAL);
1343  slot = sc->rxvc2slot[vci];
1344  if ((sc->rxslot[slot].oth_flags & (ENOTHER_FREE|ENOTHER_DRAIN)) != 0)
1345    return(EINVAL);
1346  s = splnet();		/* block out enintr() */
1347  oldmode = EN_READ(sc, MID_VC(vci));
1348  newmode = MIDV_SETMODE(oldmode, MIDV_TRASH) & ~MIDV_INSERVICE;
1349  EN_WRITE(sc, MID_VC(vci), (newmode | (oldmode & MIDV_INSERVICE)));
1350		/* halt in tracks, be careful to preserve inserivce bit */
1351  DELAY(27);
1352  sc->rxslot[slot].rxhand = NULL;
1353  sc->rxslot[slot].mode = newmode;
1354
1355  sc->txslot[sc->txvc2slot[vci]].nref--;
1356  sc->txspeed[vci] = 0;
1357  sc->txvc2slot[vci] = 0;
1358
1359  /* if stuff is still going on we are going to have to drain it out */
1360  if (sc->rxslot[slot].indma.ifq_head ||
1361		sc->rxslot[slot].q.ifq_head ||
1362		(sc->rxslot[slot].oth_flags & ENOTHER_SWSL) != 0) {
1363    sc->rxslot[slot].oth_flags |= ENOTHER_DRAIN;
1364  } else {
1365    sc->rxslot[slot].oth_flags = ENOTHER_FREE;
1366    sc->rxslot[slot].atm_vci = RX_NONE;
1367    sc->rxvc2slot[vci] = RX_NONE;
1368  }
1369  splx(s);		/* enable enintr() */
1370#ifdef EN_DEBUG
1371  printf("%s: rx%d: VCI %d is now %s\n", device_xname(sc->sc_dev), slot, vci,
1372	(sc->rxslot[slot].oth_flags & ENOTHER_DRAIN) ? "draining" : "free");
1373#endif
1374  return(0);
1375}
1376
1377/***********************************************************************/
1378
1379/*
1380 * en_reset: reset the board, throw away work in progress.
1381 * must en_init to recover.
1382 */
1383
1384void en_reset(struct en_softc *sc)
1385{
1386  struct mbuf *m;
1387  int lcv, slot;
1388
1389#ifdef EN_DEBUG
1390  printf("%s: reset\n", device_xname(sc->sc_dev));
1391#endif
1392
1393  if (sc->en_busreset)
1394    sc->en_busreset(sc);
1395  EN_WRITE(sc, MID_RESID, 0x0);	/* reset hardware */
1396
1397  /*
1398   * recv: dump any mbufs we are DMA'ing into, if DRAINing, then a reset
1399   * will free us!
1400   */
1401
1402  for (lcv = 0 ; lcv < MID_N_VC ; lcv++) {
1403    if (sc->rxvc2slot[lcv] == RX_NONE)
1404      continue;
1405    slot = sc->rxvc2slot[lcv];
1406    while (1) {
1407      IF_DEQUEUE(&sc->rxslot[slot].indma, m);
1408      if (m == NULL)
1409	break;		/* >>> exit 'while(1)' here <<< */
1410      m_freem(m);
1411    }
1412    while (1) {
1413      IF_DEQUEUE(&sc->rxslot[slot].q, m);
1414      if (m == NULL)
1415	break;		/* >>> exit 'while(1)' here <<< */
1416      m_freem(m);
1417    }
1418    sc->rxslot[slot].oth_flags &= ~ENOTHER_SWSL;
1419    if (sc->rxslot[slot].oth_flags & ENOTHER_DRAIN) {
1420      sc->rxslot[slot].oth_flags = ENOTHER_FREE;
1421      sc->rxvc2slot[lcv] = RX_NONE;
1422#ifdef EN_DEBUG
1423  printf("%s: rx%d: VCI %d is now free\n", device_xname(sc->sc_dev), slot, lcv);
1424#endif
1425    }
1426  }
1427
1428  /*
1429   * xmit: dump everything
1430   */
1431
1432  for (lcv = 0 ; lcv < EN_NTX ; lcv++) {
1433    while (1) {
1434      IF_DEQUEUE(&sc->txslot[lcv].indma, m);
1435      if (m == NULL)
1436	break;		/* >>> exit 'while(1)' here <<< */
1437      m_freem(m);
1438    }
1439    while (1) {
1440      IF_DEQUEUE(&sc->txslot[lcv].q, m);
1441      if (m == NULL)
1442	break;		/* >>> exit 'while(1)' here <<< */
1443      m_freem(m);
1444    }
1445    sc->txslot[lcv].mbsize = 0;
1446  }
1447
1448  return;
1449}
1450
1451
1452/*
1453 * en_init: init board and sync the card with the data in the softc.
1454 */
1455
1456STATIC void en_init(struct en_softc *sc)
1457{
1458  int vc, slot;
1459  u_int32_t loc;
1460#ifdef ATM_PVCEXT
1461    struct pvcsif *pvcsif;
1462#endif
1463
1464  if ((sc->enif.if_flags & IFF_UP) == 0) {
1465#ifdef ATM_PVCEXT
1466    LIST_FOREACH(pvcsif, &sc->sif_list, sif_links) {
1467      if (pvcsif->sif_if.if_flags & IFF_UP) {
1468	/*
1469	 * down the device only when there is no active pvc subinterface.
1470	 * if there is, we have to go through the init sequence to reflect
1471	 * the software states to the device.
1472	 */
1473	goto up;
1474      }
1475    }
1476#endif
1477#ifdef EN_DEBUG
1478    printf("%s: going down\n", device_xname(sc->sc_dev));
1479#endif
1480    en_reset(sc);			/* to be safe */
1481    sc->enif.if_flags &= ~IFF_RUNNING;	/* disable */
1482    return;
1483  }
1484
1485#ifdef ATM_PVCEXT
1486 up:
1487#endif
1488#ifdef EN_DEBUG
1489  printf("%s: going up\n", device_xname(sc->sc_dev));
1490#endif
1491  sc->enif.if_flags |= IFF_RUNNING;	/* enable */
1492#ifdef ATM_PVCEXT
1493  LIST_FOREACH(pvcsif, &sc->sif_list, sif_links) {
1494    pvcsif->sif_if.if_flags |= IFF_RUNNING;
1495  }
1496#endif
1497
1498  if (sc->en_busreset)
1499    sc->en_busreset(sc);
1500  EN_WRITE(sc, MID_RESID, 0x0);		/* reset */
1501
1502  /*
1503   * init obmem data structures: vc tab, DMA q's, slist.
1504   *
1505   * note that we set drq_free/dtq_free to one less than the total number
1506   * of DTQ/DRQs present.   we do this because the card uses the condition
1507   * (drq_chip == drq_us) to mean "list is empty"... but if you allow the
1508   * circular list to be completely full then (drq_chip == drq_us) [i.e.
1509   * the drq_us pointer will wrap all the way around].   by restricting
1510   * the number of active requests to (N - 1) we prevent the list from
1511   * becoming completely full.    note that the card will sometimes give
1512   * us an interrupt for a DTQ/DRQ we have already processes... this helps
1513   * keep that interrupt from messing us up.
1514   */
1515
1516  for (vc = 0 ; vc < MID_N_VC ; vc++)
1517    en_loadvc(sc, vc);
1518
1519  memset(&sc->drq, 0, sizeof(sc->drq));
1520  sc->drq_free = MID_DRQ_N - 1;		/* N - 1 */
1521  sc->drq_chip = MID_DRQ_REG2A(EN_READ(sc, MID_DMA_RDRX));
1522  EN_WRITE(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_chip));
1523						/* ensure zero queue */
1524  sc->drq_us = sc->drq_chip;
1525
1526  memset(&sc->dtq, 0, sizeof(sc->dtq));
1527  sc->dtq_free = MID_DTQ_N - 1;		/* N - 1 */
1528  sc->dtq_chip = MID_DTQ_REG2A(EN_READ(sc, MID_DMA_RDTX));
1529  EN_WRITE(sc, MID_DMA_WRTX, MID_DRQ_A2REG(sc->dtq_chip));
1530						/* ensure zero queue */
1531  sc->dtq_us = sc->dtq_chip;
1532
1533  sc->hwslistp = MID_SL_REG2A(EN_READ(sc, MID_SERV_WRITE));
1534  sc->swsl_size = sc->swsl_head = sc->swsl_tail = 0;
1535
1536#ifdef EN_DEBUG
1537  printf("%s: drq free/chip: %d/0x%x, dtq free/chip: %d/0x%x, hwslist: 0x%x\n",
1538    device_xname(sc->sc_dev), sc->drq_free, sc->drq_chip,
1539    sc->dtq_free, sc->dtq_chip, sc->hwslistp);
1540#endif
1541
1542  for (slot = 0 ; slot < EN_NTX ; slot++) {
1543    sc->txslot[slot].bfree = EN_TXSZ * 1024;
1544    EN_WRITE(sc, MIDX_READPTR(slot), 0);
1545    EN_WRITE(sc, MIDX_DESCSTART(slot), 0);
1546    loc = sc->txslot[slot].cur = sc->txslot[slot].start;
1547    loc = loc - MID_RAMOFF;
1548    loc = (loc & ~((EN_TXSZ*1024) - 1)) >> 2; /* mask, cvt to words */
1549    loc = loc >> MIDV_LOCTOPSHFT;	/* top 11 bits */
1550    EN_WRITE(sc, MIDX_PLACE(slot), MIDX_MKPLACE(en_k2sz(EN_TXSZ), loc));
1551#ifdef EN_DEBUG
1552    printf("%s: tx%d: place 0x%x\n", device_xname(sc->sc_dev),  slot,
1553	EN_READ(sc, MIDX_PLACE(slot)));
1554#endif
1555  }
1556
1557  /*
1558   * enable!
1559   */
1560
1561  EN_WRITE(sc, MID_INTENA, MID_INT_TX|MID_INT_DMA_OVR|MID_INT_IDENT|
1562	MID_INT_LERR|MID_INT_DMA_ERR|MID_INT_DMA_RX|MID_INT_DMA_TX|
1563	MID_INT_SERVICE| /* >>> MID_INT_SUNI| XXXCDC<<< */ MID_INT_STATS);
1564  EN_WRITE(sc, MID_MAST_CSR, MID_SETIPL(sc->ipl)|MID_MCSR_ENDMA|
1565	MID_MCSR_ENTX|MID_MCSR_ENRX);
1566
1567}
1568
1569
1570/*
1571 * en_loadvc: load a vc tab entry from a slot
1572 */
1573
1574STATIC void en_loadvc(struct en_softc *sc, int vc)
1575{
1576  int slot;
1577  u_int32_t reg = EN_READ(sc, MID_VC(vc));
1578
1579  reg = MIDV_SETMODE(reg, MIDV_TRASH);
1580  EN_WRITE(sc, MID_VC(vc), reg);
1581  DELAY(27);
1582
1583  if ((slot = sc->rxvc2slot[vc]) == RX_NONE)
1584    return;
1585
1586  /* no need to set CRC */
1587  EN_WRITE(sc, MID_DST_RP(vc), 0);	/* read pointer = 0, desc. start = 0 */
1588  EN_WRITE(sc, MID_WP_ST_CNT(vc), 0);	/* write pointer = 0 */
1589  EN_WRITE(sc, MID_VC(vc), sc->rxslot[slot].mode);  /* set mode, size, loc */
1590  sc->rxslot[slot].cur = sc->rxslot[slot].start;
1591
1592#ifdef EN_DEBUG
1593    printf("%s: rx%d: assigned to VCI %d\n", device_xname(sc->sc_dev), slot, vc);
1594#endif
1595}
1596
1597
1598/*
1599 * en_start: start transmitting the next packet that needs to go out
1600 * if there is one.    note that atm_output() has already splnet()'d us.
1601 */
1602
1603STATIC void en_start(struct ifnet *ifp)
1604{
1605#ifdef MISSING_IF_SOFTC
1606    struct en_softc *sc = (struct en_softc *)device_lookup_private(&en_cd, ifp->if_unit);
1607#else
1608    struct en_softc *sc = (struct en_softc *) ifp->if_softc;
1609#endif
1610    struct mbuf *m, *lastm, *prev;
1611    struct atm_pseudohdr *ap, *new_ap;
1612    int txchan, mlen, got, need, toadd, cellcnt, first;
1613    u_int32_t atm_vpi, atm_vci, atm_flags, *dat, aal;
1614    u_int8_t *cp;
1615
1616    if ((ifp->if_flags & IFF_RUNNING) == 0)
1617	return;
1618
1619    /*
1620     * remove everything from interface queue since we handle all queueing
1621     * locally ...
1622     */
1623
1624    while (1) {
1625
1626      IFQ_DEQUEUE(&ifp->if_snd, m);
1627      if (m == NULL)
1628	return;		/* EMPTY: >>> exit here <<< */
1629
1630      /*
1631       * calculate size of packet (in bytes)
1632       * also, if we are not doing transmit DMA we eliminate all stupid
1633       * (non-word) alignments here using en_mfix().   calls to en_mfix()
1634       * seem to be due to tcp retransmits for the most part.
1635       *
1636       * after this loop mlen total length of mbuf chain (including atm_ph),
1637       * and lastm is a pointer to the last mbuf on the chain.
1638       */
1639
1640      lastm = m;
1641      mlen = 0;
1642      prev = NULL;
1643      while (1) {
1644	/* no DMA? */
1645        if ((!sc->is_adaptec && EN_ENIDMAFIX) || EN_NOTXDMA || !en_dma) {
1646	  if ( (mtod(lastm, unsigned long) % sizeof(u_int32_t)) != 0 ||
1647	    ((lastm->m_len % sizeof(u_int32_t)) != 0 && lastm->m_next)) {
1648	    first = (lastm == m);
1649	    if (en_mfix(sc, &lastm, prev) == 0) {	/* failed? */
1650	      m_freem(m);
1651	      m = NULL;
1652              break;
1653            }
1654	    if (first)
1655	      m = lastm;		/* update */
1656          }
1657          prev = lastm;
1658        }
1659	mlen += lastm->m_len;
1660	if (lastm->m_next == NULL)
1661	  break;
1662	lastm = lastm->m_next;
1663      }
1664
1665      if (m == NULL)		/* happens only if mfix fails */
1666        continue;
1667
1668      ap = mtod(m, struct atm_pseudohdr *);
1669
1670      atm_vpi = ATM_PH_VPI(ap);
1671      atm_vci = ATM_PH_VCI(ap);
1672      atm_flags = ATM_PH_FLAGS(ap) & ~(EN_OBHDR|EN_OBTRL);
1673      aal = ((atm_flags & ATM_PH_AAL5) != 0)
1674			? MID_TBD_AAL5 : MID_TBD_NOAAL5;
1675
1676      /*
1677       * check that vpi/vci is one we can use
1678       */
1679
1680      if (atm_vpi || atm_vci >= MID_N_VC) {
1681	printf("%s: output vpi=%d, vci=%d out of card range, dropping...\n",
1682		device_xname(sc->sc_dev), atm_vpi, atm_vci);
1683	m_freem(m);
1684	continue;
1685      }
1686
1687      /*
1688       * computing how much padding we need on the end of the mbuf, then
1689       * see if we can put the TBD at the front of the mbuf where the
1690       * link header goes (well behaved protocols will reserve room for us).
1691       * last, check if room for PDU tail.
1692       *
1693       * got = number of bytes of data we have
1694       * cellcnt = number of cells in this mbuf
1695       * need = number of bytes of data + padding we need (excludes TBD)
1696       * toadd = number of bytes of data we need to add to end of mbuf,
1697       *	[including AAL5 PDU, if AAL5]
1698       */
1699
1700      got = mlen - sizeof(struct atm_pseudohdr);
1701      toadd = (aal == MID_TBD_AAL5) ? MID_PDU_SIZE : 0;	/* PDU */
1702      cellcnt = (got + toadd + (MID_ATMDATASZ - 1)) / MID_ATMDATASZ;
1703      need = cellcnt * MID_ATMDATASZ;
1704      toadd = need - got;		/* recompute, including zero padding */
1705
1706#ifdef EN_DEBUG
1707      printf("%s: txvci%d: mlen=%d, got=%d, need=%d, toadd=%d, cell#=%d\n",
1708	device_xname(sc->sc_dev), atm_vci, mlen, got, need, toadd, cellcnt);
1709      printf("     leading_space=%d, trailing_space=%d\n",
1710	M_LEADINGSPACE(m), M_TRAILINGSPACE(lastm));
1711#endif
1712
1713#ifdef EN_MBUF_OPT
1714
1715      /*
1716       * note: external storage (M_EXT) can be shared between mbufs
1717       * to avoid copying (see m_copym()).    this means that the same
1718       * data buffer could be shared by several mbufs, and thus it isn't
1719       * a good idea to try and write TBDs or PDUs to M_EXT data areas.
1720       */
1721
1722      if (M_LEADINGSPACE(m) >= MID_TBD_SIZE && (m->m_flags & M_EXT) == 0) {
1723	m->m_data -= MID_TBD_SIZE;
1724	m->m_len += MID_TBD_SIZE;
1725	mlen += MID_TBD_SIZE;
1726	new_ap = mtod(m, struct atm_pseudohdr *);
1727	*new_ap = *ap;			/* move it back */
1728	ap = new_ap;
1729	dat = ((u_int32_t *) ap) + 1;
1730	/* make sure the TBD is in proper byte order */
1731	*dat++ = htonl(MID_TBD_MK1(aal, sc->txspeed[atm_vci], cellcnt));
1732	*dat = htonl(MID_TBD_MK2(atm_vci, 0, 0));
1733	atm_flags |= EN_OBHDR;
1734      }
1735
1736      if (toadd && (lastm->m_flags & M_EXT) == 0 &&
1737					M_TRAILINGSPACE(lastm) >= toadd) {
1738	cp = mtod(lastm, u_int8_t *) + lastm->m_len;
1739	lastm->m_len += toadd;
1740	mlen += toadd;
1741	if (aal == MID_TBD_AAL5) {
1742	  memset(cp, 0, toadd - MID_PDU_SIZE);
1743	  dat = (u_int32_t *)(cp + toadd - MID_PDU_SIZE);
1744	  /* make sure the PDU is in proper byte order */
1745	  *dat = htonl(MID_PDU_MK1(0, 0, got));
1746	} else {
1747	  memset(cp, 0, toadd);
1748	}
1749	atm_flags |= EN_OBTRL;
1750      }
1751      ATM_PH_FLAGS(ap) = atm_flags;	/* update EN_OBHDR/EN_OBTRL bits */
1752#endif	/* EN_MBUF_OPT */
1753
1754      /*
1755       * get assigned channel (will be zero unless txspeed[atm_vci] is set)
1756       */
1757
1758      txchan = sc->txvc2slot[atm_vci];
1759
1760      if (sc->txslot[txchan].mbsize > EN_TXHIWAT) {
1761	EN_COUNT(sc->txmbovr);
1762	m_freem(m);
1763#ifdef EN_DEBUG
1764	printf("%s: tx%d: buffer space shortage\n", device_xname(sc->sc_dev),
1765		txchan);
1766#endif
1767	continue;
1768      }
1769
1770      sc->txslot[txchan].mbsize += mlen;
1771
1772#ifdef EN_DEBUG
1773      printf("%s: tx%d: VPI=%d, VCI=%d, FLAGS=0x%x, speed=0x%x\n",
1774	device_xname(sc->sc_dev), txchan, atm_vpi, atm_vci, atm_flags,
1775	sc->txspeed[atm_vci]);
1776      printf("     adjusted mlen=%d, mbsize=%d\n", mlen,
1777		sc->txslot[txchan].mbsize);
1778#endif
1779
1780      IF_ENQUEUE(&sc->txslot[txchan].q, m);
1781      en_txdma(sc, txchan);
1782
1783  }
1784  /*NOTREACHED*/
1785}
1786
1787
1788/*
1789 * en_mfix: fix a stupid mbuf
1790 */
1791
1792#ifndef __FreeBSD__
1793
1794STATIC int en_mfix(struct en_softc *sc, struct mbuf **mm, struct mbuf *prev)
1795{
1796  struct mbuf *m, *new;
1797  u_char *d, *cp;
1798  int off;
1799  struct mbuf *nxt;
1800
1801  m = *mm;
1802
1803  EN_COUNT(sc->mfix);			/* count # of calls */
1804#ifdef EN_DEBUG
1805  printf("%s: mfix mbuf m_data=%p, m_len=%d\n", device_xname(sc->sc_dev),
1806	m->m_data, m->m_len);
1807#endif
1808
1809  d = mtod(m, u_char *);
1810  off = ((unsigned long) d) % sizeof(u_int32_t);
1811
1812  if (off) {
1813    if ((m->m_flags & M_EXT) == 0) {
1814      memmove(d - off, d, m->m_len);   /* ALIGN! (with costly data copy...) */
1815      d -= off;
1816      m->m_data = (void *)d;
1817    } else {
1818      /* can't write to an M_EXT mbuf since it may be shared */
1819      MGET(new, M_DONTWAIT, MT_DATA);
1820      if (!new) {
1821        EN_COUNT(sc->mfixfail);
1822        return(0);
1823      }
1824      MCLGET(new, M_DONTWAIT);
1825      if ((new->m_flags & M_EXT) == 0) {
1826        m_free(new);
1827        EN_COUNT(sc->mfixfail);
1828        return(0);
1829      }
1830      memcpy(new->m_data, d, m->m_len);	/* ALIGN! (with costly data copy...) */
1831      new->m_len = m->m_len;
1832      new->m_next = m->m_next;
1833      if (prev)
1834        prev->m_next = new;
1835      m_free(m);
1836      *mm = m = new;	/* note: 'd' now invalid */
1837    }
1838  }
1839
1840  off = m->m_len % sizeof(u_int32_t);
1841  if (off == 0)
1842    return(1);
1843
1844  d = mtod(m, u_char *) + m->m_len;
1845  off = sizeof(u_int32_t) - off;
1846
1847  nxt = m->m_next;
1848  while (off--) {
1849    for ( ; nxt != NULL && nxt->m_len == 0 ; nxt = nxt->m_next)
1850      /*null*/;
1851    if (nxt == NULL) {		/* out of data, zero fill */
1852      *d++ = 0;
1853      continue;			/* next "off" */
1854    }
1855    cp = mtod(nxt, u_char *);
1856    *d++ = *cp++;
1857    m->m_len++;
1858    nxt->m_len--;
1859    nxt->m_data = (void *)cp;
1860  }
1861  return(1);
1862}
1863
1864#else /* __FreeBSD__ */
1865
1866STATIC int en_makeexclusive(struct en_softc *, struct mbuf **, struct mbuf *);
1867
1868STATIC int en_makeexclusive(sc, mm, prev)
1869    struct en_softc *sc;
1870    struct mbuf **mm, *prev;
1871{
1872    struct mbuf *m, *new;
1873
1874    m = *mm;
1875
1876    if (m->m_flags & M_EXT) {
1877	if (m->m_ext.ext_free) {
1878	    /* external buffer isn't an ordinary mbuf cluster! */
1879	    aprint_error_dev(sc->sc_dev, "mfix: special buffer! can't make a copy!\n");
1880	    return (0);
1881	}
1882
1883	if (mclrefcnt[mtocl(m->m_ext.ext_buf)] > 1) {
1884	    /* make a real copy of the M_EXT mbuf since it is shared */
1885	    MGET(new, M_DONTWAIT, MT_DATA);
1886	    if (!new) {
1887		EN_COUNT(sc->mfixfail);
1888		return(0);
1889	    }
1890	    if (m->m_flags & M_PKTHDR)
1891		M_COPY_PKTHDR(new, m);
1892	    MCLGET(new, M_DONTWAIT);
1893	    if ((new->m_flags & M_EXT) == 0) {
1894		m_free(new);
1895		EN_COUNT(sc->mfixfail);
1896		return(0);
1897	    }
1898	    memcpy(new->m_data, m->m_data, m->m_len);
1899	    new->m_len = m->m_len;
1900	    new->m_next = m->m_next;
1901	    if (prev)
1902		prev->m_next = new;
1903	    m_free(m);
1904	    *mm = new;
1905	}
1906	else {
1907	    /* the buffer is not shared, align the data offset using
1908	       this buffer. */
1909	    u_char *d = mtod(m, u_char *);
1910	    int off = ((u_long)d) % sizeof(u_int32_t);
1911
1912	    if (off > 0) {
1913		memmove(d - off, d, m->m_len);
1914		m->m_data = (void *)d - off;
1915	    }
1916	}
1917    }
1918    return (1);
1919}
1920
1921STATIC int en_mfix(sc, mm, prev)
1922
1923struct en_softc *sc;
1924struct mbuf **mm, *prev;
1925
1926{
1927  struct mbuf *m;
1928  u_char *d, *cp;
1929  int off;
1930  struct mbuf *nxt;
1931
1932  m = *mm;
1933
1934  EN_COUNT(sc->mfix);			/* count # of calls */
1935#ifdef EN_DEBUG
1936  printf("%s: mfix mbuf m_data=0x%x, m_len=%d\n", device_xname(sc->sc_dev),
1937	m->m_data, m->m_len);
1938#endif
1939
1940  d = mtod(m, u_char *);
1941  off = ((unsigned long) d) % sizeof(u_int32_t);
1942
1943  if (off) {
1944    if ((m->m_flags & M_EXT) == 0) {
1945      memmove(d - off, d, m->m_len);   /* ALIGN! (with costly data copy...) */
1946      d -= off;
1947      m->m_data = (void *)d;
1948    } else {
1949      /* can't write to an M_EXT mbuf since it may be shared */
1950      if (en_makeexclusive(sc, &m, prev) == 0)
1951	  return (0);
1952      *mm = m;	/* note: 'd' now invalid */
1953    }
1954  }
1955
1956  off = m->m_len % sizeof(u_int32_t);
1957  if (off == 0)
1958    return(1);
1959
1960  if (m->m_flags & M_EXT) {
1961      /* can't write to an M_EXT mbuf since it may be shared */
1962      if (en_makeexclusive(sc, &m, prev) == 0)
1963	  return (0);
1964      *mm = m;	/* note: 'd' now invalid */
1965  }
1966
1967  d = mtod(m, u_char *) + m->m_len;
1968  off = sizeof(u_int32_t) - off;
1969
1970  nxt = m->m_next;
1971  while (off--) {
1972    if (nxt != NULL && nxt->m_len == 0) {
1973	/* remove an empty mbuf.  this avoids odd byte padding to an empty
1974	   last mbuf.  */
1975	m->m_next = nxt = m_free(nxt);
1976    }
1977    if (nxt == NULL) {		/* out of data, zero fill */
1978      *d++ = 0;
1979      continue;			/* next "off" */
1980    }
1981    cp = mtod(nxt, u_char *);
1982    *d++ = *cp++;
1983    m->m_len++;
1984    nxt->m_len--;
1985    nxt->m_data = (void *)cp;
1986  }
1987  if (nxt != NULL && nxt->m_len == 0)
1988      m->m_next = m_free(nxt);
1989  return(1);
1990}
1991
1992#endif /* __FreeBSD__ */
1993
1994/*
1995 * en_txdma: start transmit DMA, if possible
1996 */
1997
1998STATIC void en_txdma(struct en_softc *sc, int chan)
1999{
2000  struct mbuf *tmp;
2001  struct atm_pseudohdr *ap;
2002  struct en_launch launch;
2003  int datalen = 0, dtqneed, len, ncells;
2004  u_int8_t *cp;
2005  struct ifnet *ifp;
2006
2007  memset(&launch, 0, sizeof launch);	/* XXX gcc */
2008
2009#ifdef EN_DEBUG
2010  printf("%s: tx%d: starting...\n", device_xname(sc->sc_dev), chan);
2011#endif
2012
2013  /*
2014   * note: now that txlaunch handles non-word aligned/sized requests
2015   * the only time you can safely set launch.nodma is if you've en_mfix()'d
2016   * the mbuf chain.    this happens only if EN_NOTXDMA || !en_dma.
2017   */
2018
2019  launch.nodma = (EN_NOTXDMA || !en_dma);
2020
2021again:
2022
2023  /*
2024   * get an mbuf waiting for DMA
2025   */
2026
2027  launch.t = sc->txslot[chan].q.ifq_head; /* peek at head of queue */
2028
2029  if (launch.t == NULL) {
2030#ifdef EN_DEBUG
2031    printf("%s: tx%d: ...done!\n", device_xname(sc->sc_dev), chan);
2032#endif
2033    return;	/* >>> exit here if no data waiting for DMA <<< */
2034  }
2035
2036  /*
2037   * get flags, vci
2038   *
2039   * note: launch.need = # bytes we need to get on the card
2040   *	   dtqneed = # of DTQs we need for this packet
2041   *       launch.mlen = # of bytes in in mbuf chain (<= launch.need)
2042   */
2043
2044  ap = mtod(launch.t, struct atm_pseudohdr *);
2045  launch.atm_vci = ATM_PH_VCI(ap);
2046  launch.atm_flags = ATM_PH_FLAGS(ap);
2047  launch.aal = ((launch.atm_flags & ATM_PH_AAL5) != 0) ?
2048		MID_TBD_AAL5 : MID_TBD_NOAAL5;
2049
2050  /*
2051   * XXX: have to recompute the length again, even though we already did
2052   * it in en_start().   might as well compute dtqneed here as well, so
2053   * this isn't that bad.
2054   */
2055
2056  if ((launch.atm_flags & EN_OBHDR) == 0) {
2057    dtqneed = 1;		/* header still needs to be added */
2058    launch.need = MID_TBD_SIZE;	/* not included with mbuf */
2059  } else {
2060    dtqneed = 0;		/* header on-board, DMA with mbuf */
2061    launch.need = 0;
2062  }
2063
2064  launch.mlen = 0;
2065  for (tmp = launch.t ; tmp != NULL ; tmp = tmp->m_next) {
2066    len = tmp->m_len;
2067    launch.mlen += len;
2068    cp = mtod(tmp, u_int8_t *);
2069    if (tmp == launch.t) {
2070      len -= sizeof(struct atm_pseudohdr); /* don't count this! */
2071      cp += sizeof(struct atm_pseudohdr);
2072    }
2073    launch.need += len;
2074    if (len == 0)
2075      continue;			/* atm_pseudohdr alone in first mbuf */
2076
2077    dtqneed += en_dqneed(sc, (void *) cp, len, 1);
2078  }
2079
2080  if ((launch.need % sizeof(u_int32_t)) != 0)
2081    dtqneed++;			/* need DTQ to FLUSH internal buffer */
2082
2083  if ((launch.atm_flags & EN_OBTRL) == 0) {
2084    if (launch.aal == MID_TBD_AAL5) {
2085      datalen = launch.need - MID_TBD_SIZE;
2086      launch.need += MID_PDU_SIZE;		/* AAL5: need PDU tail */
2087    }
2088    dtqneed++;			/* need to work on the end a bit */
2089  }
2090
2091  /*
2092   * finish calculation of launch.need (need to figure out how much padding
2093   * we will need).   launch.need includes MID_TBD_SIZE, but we need to
2094   * remove that to so we can round off properly.     we have to add
2095   * MID_TBD_SIZE back in after calculating ncells.
2096   */
2097
2098  launch.need = roundup(launch.need - MID_TBD_SIZE, MID_ATMDATASZ);
2099  ncells = launch.need / MID_ATMDATASZ;
2100  launch.need += MID_TBD_SIZE;
2101
2102  if (launch.need > EN_TXSZ * 1024) {
2103    printf("%s: tx%d: packet larger than xmit buffer (%d > %d)\n",
2104      device_xname(sc->sc_dev), chan, launch.need, EN_TXSZ * 1024);
2105    goto dequeue_drop;
2106  }
2107
2108  /*
2109   * note: note that we cannot totally fill the circular buffer (i.e.
2110   * we can't use up all of the remaining sc->txslot[chan].bfree free
2111   * bytes) because that would cause the circular buffer read pointer
2112   * to become equal to the write pointer, thus signaling 'empty buffer'
2113   * to the hardware and stopping the transmitter.
2114   */
2115  if (launch.need >= sc->txslot[chan].bfree) {
2116    EN_COUNT(sc->txoutspace);
2117#ifdef EN_DEBUG
2118    printf("%s: tx%d: out of transmit space\n", device_xname(sc->sc_dev), chan);
2119#endif
2120    return;		/* >>> exit here if out of obmem buffer space <<< */
2121  }
2122
2123  /*
2124   * ensure we have enough dtqs to go, if not, wait for more.
2125   */
2126
2127  if (launch.nodma) {
2128    dtqneed = 1;
2129  }
2130  if (dtqneed > sc->dtq_free) {
2131    sc->need_dtqs = 1;
2132    EN_COUNT(sc->txdtqout);
2133#ifdef EN_DEBUG
2134    printf("%s: tx%d: out of transmit DTQs\n", device_xname(sc->sc_dev), chan);
2135#endif
2136    return;		/* >>> exit here if out of dtqs <<< */
2137  }
2138
2139  /*
2140   * it is a go, commit!  dequeue mbuf start working on the xfer.
2141   */
2142
2143  IF_DEQUEUE(&sc->txslot[chan].q, tmp);
2144#ifdef EN_DIAG
2145  if (launch.t != tmp)
2146    panic("en dequeue");
2147#endif /* EN_DIAG */
2148
2149  /*
2150   * launch!
2151   */
2152
2153  EN_COUNT(sc->launch);
2154#ifdef ATM_PVCEXT
2155  /* if there's a subinterface for this vci, override ifp. */
2156  ifp = en_vci2ifp(sc, launch.atm_vci);
2157#else
2158  ifp = &sc->enif;
2159#endif
2160  ifp->if_opackets++;
2161
2162  if ((launch.atm_flags & EN_OBHDR) == 0) {
2163    EN_COUNT(sc->lheader);
2164    /* store tbd1/tbd2 in host byte order */
2165    launch.tbd1 = MID_TBD_MK1(launch.aal, sc->txspeed[launch.atm_vci], ncells);
2166    launch.tbd2 = MID_TBD_MK2(launch.atm_vci, 0, 0);
2167  }
2168  if ((launch.atm_flags & EN_OBTRL) == 0 && launch.aal == MID_TBD_AAL5) {
2169    EN_COUNT(sc->ltail);
2170    launch.pdu1 = MID_PDU_MK1(0, 0, datalen);  /* host byte order */
2171  }
2172
2173  en_txlaunch(sc, chan, &launch);
2174
2175  if (ifp->if_bpf) {
2176      /*
2177       * adjust the top of the mbuf to skip the pseudo atm header
2178       * (and TBD, if present) before passing the packet to bpf,
2179       * restore it afterwards.
2180       */
2181      int size = sizeof(struct atm_pseudohdr);
2182      if (launch.atm_flags & EN_OBHDR)
2183	  size += MID_TBD_SIZE;
2184
2185      launch.t->m_data += size;
2186      launch.t->m_len -= size;
2187
2188      bpf_mtap(ifp, launch.t);
2189
2190      launch.t->m_data -= size;
2191      launch.t->m_len += size;
2192  }
2193  /*
2194   * do some housekeeping and get the next packet
2195   */
2196
2197  sc->txslot[chan].bfree -= launch.need;
2198  IF_ENQUEUE(&sc->txslot[chan].indma, launch.t);
2199  goto again;
2200
2201  /*
2202   * END of txdma loop!
2203   */
2204
2205  /*
2206   * error handles
2207   */
2208
2209dequeue_drop:
2210  IF_DEQUEUE(&sc->txslot[chan].q, tmp);
2211  if (launch.t != tmp)
2212    panic("en dequeue drop");
2213  m_freem(launch.t);
2214  sc->txslot[chan].mbsize -= launch.mlen;
2215  goto again;
2216}
2217
2218
2219/*
2220 * en_txlaunch: launch an mbuf into the DMA pool!
2221 */
2222
2223STATIC void en_txlaunch(struct en_softc *sc, int chan, struct en_launch *l)
2224{
2225  struct mbuf *tmp;
2226  u_int32_t cur = sc->txslot[chan].cur,
2227	    start = sc->txslot[chan].start,
2228	    stop = sc->txslot[chan].stop,
2229	    dma, *data, *datastop, count, bcode;
2230  int pad, addtail, need, len, needalign, cnt, end, mx;
2231
2232
2233 /*
2234  * vars:
2235  *   need = # bytes card still needs (decr. to zero)
2236  *   len = # of bytes left in current mbuf
2237  *   cur = our current pointer
2238  *   dma = last place we programmed into the DMA
2239  *   data = pointer into data area of mbuf that needs to go next
2240  *   cnt = # of bytes to transfer in this DTQ
2241  *   bcode/count = DMA burst code, and chip's version of cnt
2242  *
2243  *   a single buffer can require up to 5 DTQs depending on its size
2244  *   and alignment requirements.   the 5 possible requests are:
2245  *   [1] 1, 2, or 3 byte DMA to align src data pointer to word boundary
2246  *   [2] alburst DMA to align src data pointer to bestburstlen
2247  *   [3] 1 or more bestburstlen DMAs
2248  *   [4] clean up burst (to last word boundary)
2249  *   [5] 1, 2, or 3 byte final clean up DMA
2250  */
2251
2252 need = l->need;
2253 dma = cur;
2254 addtail = (l->atm_flags & EN_OBTRL) == 0;	/* add a tail? */
2255
2256#ifdef EN_DIAG
2257  if ((need - MID_TBD_SIZE) % MID_ATMDATASZ)
2258    printf("%s: tx%d: bogus transmit needs (%d)\n", device_xname(sc->sc_dev), chan,
2259		need);
2260#endif
2261#ifdef EN_DEBUG
2262  printf("%s: tx%d: launch mbuf %p!   cur=0x%x[%d], need=%d, addtail=%d\n",
2263	device_xname(sc->sc_dev), chan, l->t, cur, (cur-start)/4, need, addtail);
2264  count = EN_READ(sc, MIDX_PLACE(chan));
2265  printf("     HW: base_address=0x%x, size=%d, read=%d, descstart=%d\n",
2266	MIDX_BASE(count), MIDX_SZ(count), EN_READ(sc, MIDX_READPTR(chan)),
2267	EN_READ(sc, MIDX_DESCSTART(chan)));
2268#endif
2269
2270 /*
2271  * do we need to insert the TBD by hand?
2272  * note that tbd1/tbd2/pdu1 are in host byte order.
2273  */
2274
2275  if ((l->atm_flags & EN_OBHDR) == 0) {
2276#ifdef EN_DEBUG
2277    printf("%s: tx%d: insert header 0x%x 0x%x\n", device_xname(sc->sc_dev),
2278	chan, l->tbd1, l->tbd2);
2279#endif
2280    EN_WRITE(sc, cur, l->tbd1);
2281    EN_WRAPADD(start, stop, cur, 4);
2282    EN_WRITE(sc, cur, l->tbd2);
2283    EN_WRAPADD(start, stop, cur, 4);
2284    need -= 8;
2285  }
2286
2287  /*
2288   * now do the mbufs...
2289   */
2290
2291  for (tmp = l->t ; tmp != NULL ; tmp = tmp->m_next) {
2292
2293    /* get pointer to data and length */
2294    data = mtod(tmp, u_int32_t *);
2295    len = tmp->m_len;
2296    if (tmp == l->t) {
2297      data += sizeof(struct atm_pseudohdr)/sizeof(u_int32_t);
2298      len -= sizeof(struct atm_pseudohdr);
2299    }
2300
2301    /* now, determine if we should copy it */
2302    if (l->nodma || (len < EN_MINDMA &&
2303       (len % 4) == 0 && ((unsigned long) data % 4) == 0 && (cur % 4) == 0)) {
2304
2305      /*
2306       * roundup len: the only time this will change the value of len
2307       * is when l->nodma is true, tmp is the last mbuf, and there is
2308       * a non-word number of bytes to transmit.   in this case it is
2309       * safe to round up because we've en_mfix'd the mbuf (so the first
2310       * byte is word aligned there must be enough free bytes at the end
2311       * to round off to the next word boundary)...
2312       */
2313      len = roundup(len, sizeof(u_int32_t));
2314      datastop = data + (len / sizeof(u_int32_t));
2315      /* copy loop: preserve byte order!!!  use WRITEDAT */
2316      while (data != datastop) {
2317	EN_WRITEDAT(sc, cur, *data);
2318	data++;
2319	EN_WRAPADD(start, stop, cur, 4);
2320      }
2321      need -= len;
2322#ifdef EN_DEBUG
2323      printf("%s: tx%d: copied %d bytes (%d left, cur now 0x%x)\n",
2324		device_xname(sc->sc_dev), chan, len, need, cur);
2325#endif
2326      continue;		/* continue on to next mbuf */
2327    }
2328
2329    /* going to do DMA, first make sure the dtq is in sync. */
2330    if (dma != cur) {
2331      EN_DTQADD(sc, WORD_IDX(start,cur), chan, MIDDMA_JK, 0, 0, 0);
2332#ifdef EN_DEBUG
2333      printf("%s: tx%d: dtq_sync: advance pointer to %d\n",
2334		device_xname(sc->sc_dev), chan, cur);
2335#endif
2336    }
2337
2338    /*
2339     * if this is the last buffer, and it looks like we are going to need to
2340     * flush the internal buffer, can we extend the length of this mbuf to
2341     * avoid the FLUSH?
2342     */
2343
2344    if (tmp->m_next == NULL) {
2345      cnt = (need - len) % sizeof(u_int32_t);
2346      if (cnt && M_TRAILINGSPACE(tmp) >= cnt)
2347        len += cnt;			/* pad for FLUSH */
2348    }
2349
2350#if !defined(MIDWAY_ENIONLY)
2351
2352    /*
2353     * the adaptec DMA engine is smart and handles everything for us.
2354     */
2355
2356    if (sc->is_adaptec) {
2357      /* need to DMA "len" bytes out to card */
2358      need -= len;
2359      EN_WRAPADD(start, stop, cur, len);
2360#ifdef EN_DEBUG
2361      printf("%s: tx%d: adp_dma %d bytes (%d left, cur now 0x%x)\n",
2362              device_xname(sc->sc_dev), chan, len, need, cur);
2363#endif
2364      end = (need == 0) ? MID_DMA_END : 0;
2365      EN_DTQADD(sc, len, chan, 0, vtophys((vaddr_t)data), l->mlen, end);
2366      if (end)
2367        goto done;
2368      dma = cur;	/* update DMA pointer */
2369      continue;
2370    }
2371#endif /* !MIDWAY_ENIONLY */
2372
2373#if !defined(MIDWAY_ADPONLY)
2374
2375    /*
2376     * the ENI DMA engine is not so smart and need more help from us
2377     */
2378
2379    /* do we need to do a DMA op to align to word boundary? */
2380    needalign = (unsigned long) data % sizeof(u_int32_t);
2381    if (needalign) {
2382      EN_COUNT(sc->headbyte);
2383      cnt = sizeof(u_int32_t) - needalign;
2384      if (cnt == 2 && len >= cnt) {
2385        count = 1;
2386        bcode = MIDDMA_2BYTE;
2387      } else {
2388        cnt = min(cnt, len);		/* prevent overflow */
2389        count = cnt;
2390        bcode = MIDDMA_BYTE;
2391      }
2392      need -= cnt;
2393      EN_WRAPADD(start, stop, cur, cnt);
2394#ifdef EN_DEBUG
2395      printf("%s: tx%d: small al_dma %d bytes (%d left, cur now 0x%x)\n",
2396              device_xname(sc->sc_dev), chan, cnt, need, cur);
2397#endif
2398      len -= cnt;
2399      end = (need == 0) ? MID_DMA_END : 0;
2400      EN_DTQADD(sc, count, chan, bcode, vtophys((vaddr_t)data), l->mlen, end);
2401      if (end)
2402        goto done;
2403      data = (u_int32_t *) ((u_char *)data + cnt);
2404    }
2405
2406    /* do we need to do a DMA op to align? */
2407    if (sc->alburst &&
2408	(needalign = (((unsigned long) data) & sc->bestburstmask)) != 0
2409	&& len >= sizeof(u_int32_t)) {
2410      cnt = sc->bestburstlen - needalign;
2411      mx = len & ~(sizeof(u_int32_t)-1);	/* don't go past end */
2412      if (cnt > mx) {
2413        cnt = mx;
2414        count = cnt / sizeof(u_int32_t);
2415        bcode = MIDDMA_WORD;
2416      } else {
2417        count = cnt / sizeof(u_int32_t);
2418        bcode = en_dmaplan[count].bcode;
2419        count = cnt >> en_dmaplan[count].divshift;
2420      }
2421      need -= cnt;
2422      EN_WRAPADD(start, stop, cur, cnt);
2423#ifdef EN_DEBUG
2424      printf("%s: tx%d: al_dma %d bytes (%d left, cur now 0x%x)\n",
2425		device_xname(sc->sc_dev), chan, cnt, need, cur);
2426#endif
2427      len -= cnt;
2428      end = (need == 0) ? MID_DMA_END : 0;
2429      EN_DTQADD(sc, count, chan, bcode, vtophys((vaddr_t)data), l->mlen, end);
2430      if (end)
2431        goto done;
2432      data = (u_int32_t *) ((u_char *)data + cnt);
2433    }
2434
2435    /* do we need to do a max-sized burst? */
2436    if (len >= sc->bestburstlen) {
2437      count = len >> sc->bestburstshift;
2438      cnt = count << sc->bestburstshift;
2439      bcode = sc->bestburstcode;
2440      need -= cnt;
2441      EN_WRAPADD(start, stop, cur, cnt);
2442#ifdef EN_DEBUG
2443      printf("%s: tx%d: best_dma %d bytes (%d left, cur now 0x%x)\n",
2444		device_xname(sc->sc_dev), chan, cnt, need, cur);
2445#endif
2446      len -= cnt;
2447      end = (need == 0) ? MID_DMA_END : 0;
2448      EN_DTQADD(sc, count, chan, bcode, vtophys((vaddr_t)data), l->mlen, end);
2449      if (end)
2450        goto done;
2451      data = (u_int32_t *) ((u_char *)data + cnt);
2452    }
2453
2454    /* do we need to do a cleanup burst? */
2455    cnt = len & ~(sizeof(u_int32_t)-1);
2456    if (cnt) {
2457      count = cnt / sizeof(u_int32_t);
2458      bcode = en_dmaplan[count].bcode;
2459      count = cnt >> en_dmaplan[count].divshift;
2460      need -= cnt;
2461      EN_WRAPADD(start, stop, cur, cnt);
2462#ifdef EN_DEBUG
2463      printf("%s: tx%d: cleanup_dma %d bytes (%d left, cur now 0x%x)\n",
2464		device_xname(sc->sc_dev), chan, cnt, need, cur);
2465#endif
2466      len -= cnt;
2467      end = (need == 0) ? MID_DMA_END : 0;
2468      EN_DTQADD(sc, count, chan, bcode, vtophys((vaddr_t)data), l->mlen, end);
2469      if (end)
2470        goto done;
2471      data = (u_int32_t *) ((u_char *)data + cnt);
2472    }
2473
2474    /* any word fragments left? */
2475    if (len) {
2476      EN_COUNT(sc->tailbyte);
2477      if (len == 2) {
2478        count = 1;
2479        bcode = MIDDMA_2BYTE;                 /* use 2byte mode */
2480      } else {
2481        count = len;
2482        bcode = MIDDMA_BYTE;                  /* use 1 byte mode */
2483      }
2484      need -= len;
2485      EN_WRAPADD(start, stop, cur, len);
2486#ifdef EN_DEBUG
2487      printf("%s: tx%d: byte cleanup_dma %d bytes (%d left, cur now 0x%x)\n",
2488		device_xname(sc->sc_dev), chan, len, need, cur);
2489#endif
2490      end = (need == 0) ? MID_DMA_END : 0;
2491      EN_DTQADD(sc, count, chan, bcode, vtophys((vaddr_t)data), l->mlen, end);
2492      if (end)
2493        goto done;
2494    }
2495
2496    dma = cur;		/* update DMA pointer */
2497#endif /* !MIDWAY_ADPONLY */
2498
2499  } /* next mbuf, please */
2500
2501  /*
2502   * all mbuf data has been copied out to the obmem (or set up to be DMAd).
2503   * if the trailer or padding needs to be put in, do it now.
2504   *
2505   * NOTE: experimental results reveal the following fact:
2506   *   if you DMA "X" bytes to the card, where X is not a multiple of 4,
2507   *   then the card will internally buffer the last (X % 4) bytes (in
2508   *   hopes of getting (4 - (X % 4)) more bytes to make a complete word).
2509   *   it is imporant to make sure we don't leave any important data in
2510   *   this internal buffer because it is discarded on the last (end) DTQ.
2511   *   one way to do this is to DMA in (4 - (X % 4)) more bytes to flush
2512   *   the darn thing out.
2513   */
2514
2515  if (addtail) {
2516
2517    pad = need % sizeof(u_int32_t);
2518    if (pad) {
2519      /*
2520       * FLUSH internal data buffer.  pad out with random data from the front
2521       * of the mbuf chain...
2522       */
2523      bcode = (sc->is_adaptec) ? 0 : MIDDMA_BYTE;
2524      EN_COUNT(sc->tailflush);
2525      EN_WRAPADD(start, stop, cur, pad);
2526      EN_DTQADD(sc, pad, chan, bcode, vtophys((vaddr_t)l->t->m_data), 0, 0);
2527      need -= pad;
2528#ifdef EN_DEBUG
2529      printf("%s: tx%d: pad/FLUSH DMA %d bytes (%d left, cur now 0x%x)\n",
2530		device_xname(sc->sc_dev), chan, pad, need, cur);
2531#endif
2532    }
2533
2534    /* copy data */
2535    pad = need / sizeof(u_int32_t);	/* round *down* */
2536    if (l->aal == MID_TBD_AAL5)
2537      pad -= 2;
2538#ifdef EN_DEBUG
2539      printf("%s: tx%d: padding %d bytes (cur now 0x%x)\n",
2540		device_xname(sc->sc_dev), chan, pad * sizeof(u_int32_t), cur);
2541#endif
2542    while (pad--) {
2543      EN_WRITEDAT(sc, cur, 0);	/* no byte order issues with zero */
2544      EN_WRAPADD(start, stop, cur, 4);
2545    }
2546    if (l->aal == MID_TBD_AAL5) {
2547      EN_WRITE(sc, cur, l->pdu1); /* in host byte order */
2548      EN_WRAPADD(start, stop, cur, 8);
2549    }
2550  }
2551
2552  if (addtail || dma != cur) {
2553   /* write final descriptor  */
2554    EN_DTQADD(sc, WORD_IDX(start,cur), chan, MIDDMA_JK, 0,
2555				l->mlen, MID_DMA_END);
2556    /* dma = cur; */ 	/* not necessary since we are done */
2557  }
2558
2559done:
2560  /* update current pointer */
2561  sc->txslot[chan].cur = cur;
2562#ifdef EN_DEBUG
2563      printf("%s: tx%d: DONE!   cur now = 0x%x\n",
2564		device_xname(sc->sc_dev), chan, cur);
2565#endif
2566
2567  return;
2568}
2569
2570
2571/*
2572 * interrupt handler
2573 */
2574
2575EN_INTR_TYPE en_intr(void *arg)
2576{
2577  struct en_softc *sc = (struct en_softc *) arg;
2578  struct mbuf *m;
2579  struct atm_pseudohdr ah;
2580  struct ifnet *ifp;
2581  u_int32_t reg, kick, val, mask, chip, vci, slot, dtq, drq;
2582  int lcv, idx, need_softserv = 0;
2583
2584  reg = EN_READ(sc, MID_INTACK);
2585
2586  if ((reg & MID_INT_ANY) == 0)
2587    EN_INTR_RET(0); /* not us */
2588
2589#ifdef EN_DEBUG
2590  {
2591    char sbuf[256];
2592
2593    snprintb(sbuf, sizeof(sbuf), MID_INTBITS, reg);
2594    printf("%s: interrupt=0x%s\n", device_xname(sc->sc_dev), sbuf);
2595  }
2596#endif
2597
2598  /*
2599   * unexpected errors that need a reset
2600   */
2601
2602  if ((reg & (MID_INT_IDENT|MID_INT_LERR|MID_INT_DMA_ERR|MID_INT_SUNI)) != 0) {
2603    char sbuf[256];
2604
2605    snprintb(sbuf, sizeof(sbuf), MID_INTBITS, reg);
2606    printf("%s: unexpected interrupt=0x%s, resetting card\n",
2607           device_xname(sc->sc_dev), sbuf);
2608#ifdef EN_DEBUG
2609#ifdef DDB
2610#ifdef __FreeBSD__
2611    Debugger("en: unexpected error");
2612#else
2613    Debugger();
2614#endif
2615#endif	/* DDB */
2616    sc->enif.if_flags &= ~IFF_RUNNING; /* FREEZE! */
2617#else
2618    en_reset(sc);
2619    en_init(sc);
2620#endif
2621    EN_INTR_RET(1); /* for us */
2622  }
2623
2624  /*******************
2625   * xmit interrupts *
2626   ******************/
2627
2628  kick = 0;				/* bitmask of channels to kick */
2629  if (reg & MID_INT_TX) {		/* TX done! */
2630
2631    /*
2632     * check for tx complete, if detected then this means that some space
2633     * has come free on the card.   we must account for it and arrange to
2634     * kick the channel to life (in case it is stalled waiting on the card).
2635     */
2636    for (mask = 1, lcv = 0 ; lcv < EN_NTX ; lcv++, mask = mask * 2) {
2637      if (reg & MID_TXCHAN(lcv)) {
2638	kick = kick | mask;	/* want to kick later */
2639	val = EN_READ(sc, MIDX_READPTR(lcv));	/* current read pointer */
2640	val = (val * sizeof(u_int32_t)) + sc->txslot[lcv].start;
2641						/* convert to offset */
2642	if (val > sc->txslot[lcv].cur)
2643	  sc->txslot[lcv].bfree = val - sc->txslot[lcv].cur;
2644	else
2645	  sc->txslot[lcv].bfree = (val + (EN_TXSZ*1024)) - sc->txslot[lcv].cur;
2646#ifdef EN_DEBUG
2647	printf("%s: tx%d: transmit done.   %d bytes now free in buffer\n",
2648		device_xname(sc->sc_dev), lcv, sc->txslot[lcv].bfree);
2649#endif
2650      }
2651    }
2652  }
2653
2654  if (reg & MID_INT_DMA_TX) {		/* TX DMA done! */
2655
2656  /*
2657   * check for TX DMA complete, if detected then this means that some DTQs
2658   * are now free.   it also means some indma mbufs can be freed.
2659   * if we needed DTQs, kick all channels.
2660   */
2661    val = EN_READ(sc, MID_DMA_RDTX);	/* chip's current location */
2662    idx = MID_DTQ_A2REG(sc->dtq_chip);/* where we last saw chip */
2663    if (sc->need_dtqs) {
2664      kick = MID_NTX_CH - 1;		/* assume power of 2, kick all! */
2665      sc->need_dtqs = 0;		/* recalculated in "kick" loop below */
2666#ifdef EN_DEBUG
2667      printf("%s: cleared need DTQ condition\n", device_xname(sc->sc_dev));
2668#endif
2669    }
2670    while (idx != val) {
2671      sc->dtq_free++;
2672      if ((dtq = sc->dtq[idx]) != 0) {
2673        sc->dtq[idx] = 0;	/* don't forget to zero it out when done */
2674	slot = EN_DQ_SLOT(dtq);
2675	IF_DEQUEUE(&sc->txslot[slot].indma, m);
2676	if (!m) panic("enintr: dtqsync");
2677	sc->txslot[slot].mbsize -= EN_DQ_LEN(dtq);
2678#ifdef EN_DEBUG
2679	printf("%s: tx%d: free %d DMA bytes, mbsize now %d\n",
2680		device_xname(sc->sc_dev), slot, EN_DQ_LEN(dtq),
2681		sc->txslot[slot].mbsize);
2682#endif
2683	m_freem(m);
2684      }
2685      EN_WRAPADD(0, MID_DTQ_N, idx, 1);
2686    };
2687    sc->dtq_chip = MID_DTQ_REG2A(val);	/* sync softc */
2688  }
2689
2690
2691  /*
2692   * kick xmit channels as needed
2693   */
2694
2695  if (kick) {
2696#ifdef EN_DEBUG
2697  printf("%s: tx kick mask = 0x%x\n", device_xname(sc->sc_dev), kick);
2698#endif
2699    for (mask = 1, lcv = 0 ; lcv < EN_NTX ; lcv++, mask = mask * 2) {
2700      if ((kick & mask) && sc->txslot[lcv].q.ifq_head) {
2701	en_txdma(sc, lcv);		/* kick it! */
2702      }
2703    }		/* for each slot */
2704  }		/* if kick */
2705
2706
2707  /*******************
2708   * recv interrupts *
2709   ******************/
2710
2711  /*
2712   * check for RX DMA complete, and pass the data "upstairs"
2713   */
2714
2715  if (reg & MID_INT_DMA_RX) {
2716    val = EN_READ(sc, MID_DMA_RDRX); /* chip's current location */
2717    idx = MID_DRQ_A2REG(sc->drq_chip);/* where we last saw chip */
2718    while (idx != val) {
2719      sc->drq_free++;
2720      if ((drq = sc->drq[idx]) != 0) {
2721        sc->drq[idx] = 0;	/* don't forget to zero it out when done */
2722	slot = EN_DQ_SLOT(drq);
2723        if (EN_DQ_LEN(drq) == 0) {  /* "JK" trash DMA? */
2724          m = NULL;
2725        } else {
2726	  IF_DEQUEUE(&sc->rxslot[slot].indma, m);
2727	  if (!m)
2728	    panic("enintr: drqsync: %s: lost mbuf in slot %d!",
2729		  device_xname(sc->sc_dev), slot);
2730        }
2731	/* do something with this mbuf */
2732	if (sc->rxslot[slot].oth_flags & ENOTHER_DRAIN) {  /* drain? */
2733          if (m)
2734	    m_freem(m);
2735	  vci = sc->rxslot[slot].atm_vci;
2736	  if (sc->rxslot[slot].indma.ifq_head == NULL &&
2737		sc->rxslot[slot].q.ifq_head == NULL &&
2738		(EN_READ(sc, MID_VC(vci)) & MIDV_INSERVICE) == 0 &&
2739		(sc->rxslot[slot].oth_flags & ENOTHER_SWSL) == 0) {
2740	    sc->rxslot[slot].oth_flags = ENOTHER_FREE; /* done drain */
2741	    sc->rxslot[slot].atm_vci = RX_NONE;
2742	    sc->rxvc2slot[vci] = RX_NONE;
2743#ifdef EN_DEBUG
2744	    printf("%s: rx%d: VCI %d now free\n", device_xname(sc->sc_dev),
2745			slot, vci);
2746#endif
2747	  }
2748	} else if (m != NULL) {
2749	  ATM_PH_FLAGS(&ah) = sc->rxslot[slot].atm_flags;
2750	  ATM_PH_VPI(&ah) = 0;
2751	  ATM_PH_SETVCI(&ah, sc->rxslot[slot].atm_vci);
2752#ifdef EN_DEBUG
2753	  printf("%s: rx%d: rxvci%d: atm_input, mbuf %p, len %d, hand %p\n",
2754		device_xname(sc->sc_dev), slot, sc->rxslot[slot].atm_vci, m,
2755		EN_DQ_LEN(drq), sc->rxslot[slot].rxhand);
2756#endif
2757
2758#ifdef ATM_PVCEXT
2759	  /* if there's a subinterface for this vci, override ifp. */
2760	  ifp = en_vci2ifp(sc, sc->rxslot[slot].atm_vci);
2761	  ifp->if_ipackets++;
2762	  m->m_pkthdr.rcvif = ifp;	/* XXX */
2763#else
2764	  ifp = &sc->enif;
2765	  ifp->if_ipackets++;
2766#endif
2767
2768	  bpf_mtap(ifp, m);
2769
2770	  atm_input(ifp, &ah, m, sc->rxslot[slot].rxhand);
2771	}
2772
2773      }
2774      EN_WRAPADD(0, MID_DRQ_N, idx, 1);
2775    };
2776    sc->drq_chip = MID_DRQ_REG2A(val);	/* sync softc */
2777
2778    if (sc->need_drqs) {	/* true if we had a DRQ shortage */
2779      need_softserv = 1;
2780      sc->need_drqs = 0;
2781#ifdef EN_DEBUG
2782	printf("%s: cleared need DRQ condition\n", device_xname(sc->sc_dev));
2783#endif
2784    }
2785  }
2786
2787  /*
2788   * handle service interrupts
2789   */
2790
2791  if (reg & MID_INT_SERVICE) {
2792    chip = MID_SL_REG2A(EN_READ(sc, MID_SERV_WRITE));
2793
2794    while (sc->hwslistp != chip) {
2795
2796      /* fetch and remove it from hardware service list */
2797      vci = EN_READ(sc, sc->hwslistp);
2798      EN_WRAPADD(MID_SLOFF, MID_SLEND, sc->hwslistp, 4);/* advance hw ptr */
2799      slot = sc->rxvc2slot[vci];
2800      if (slot == RX_NONE) {
2801#ifdef EN_DEBUG
2802	printf("%s: unexpected rx interrupt on VCI %d\n",
2803		device_xname(sc->sc_dev), vci);
2804#endif
2805	EN_WRITE(sc, MID_VC(vci), MIDV_TRASH);  /* rx off, damn it! */
2806	continue;				/* next */
2807      }
2808      EN_WRITE(sc, MID_VC(vci), sc->rxslot[slot].mode); /* remove from hwsl */
2809      EN_COUNT(sc->hwpull);
2810
2811#ifdef EN_DEBUG
2812      printf("%s: pulled VCI %d off hwslist\n", device_xname(sc->sc_dev), vci);
2813#endif
2814
2815      /* add it to the software service list (if needed) */
2816      if ((sc->rxslot[slot].oth_flags & ENOTHER_SWSL) == 0) {
2817	EN_COUNT(sc->swadd);
2818	need_softserv = 1;
2819	sc->rxslot[slot].oth_flags |= ENOTHER_SWSL;
2820	sc->swslist[sc->swsl_tail] = slot;
2821	EN_WRAPADD(0, MID_SL_N, sc->swsl_tail, 1);
2822	sc->swsl_size++;
2823#ifdef EN_DEBUG
2824      printf("%s: added VCI %d to swslist\n", device_xname(sc->sc_dev), vci);
2825#endif
2826      }
2827    };
2828  }
2829
2830  /*
2831   * now service (function too big to include here)
2832   */
2833
2834  if (need_softserv)
2835    en_service(sc);
2836
2837  /*
2838   * keep our stats
2839   */
2840
2841  if (reg & MID_INT_DMA_OVR) {
2842    EN_COUNT(sc->dmaovr);
2843#ifdef EN_DEBUG
2844    printf("%s: MID_INT_DMA_OVR\n", device_xname(sc->sc_dev));
2845#endif
2846  }
2847  reg = EN_READ(sc, MID_STAT);
2848#ifdef EN_STAT
2849  sc->otrash += MID_OTRASH(reg);
2850  sc->vtrash += MID_VTRASH(reg);
2851#endif
2852
2853  EN_INTR_RET(1); /* for us */
2854}
2855
2856
2857/*
2858 * en_service: handle a service interrupt
2859 *
2860 * Q: why do we need a software service list?
2861 *
2862 * A: if we remove a VCI from the hardware list and we find that we are
2863 *    out of DRQs we must defer processing until some DRQs become free.
2864 *    so we must remember to look at this RX VCI/slot later, but we can't
2865 *    put it back on the hardware service list (since that isn't allowed).
2866 *    so we instead save it on the software service list.   it would be nice
2867 *    if we could peek at the VCI on top of the hwservice list without removing
2868 *    it, however this leads to a race condition: if we peek at it and
2869 *    decide we are done with it new data could come in before we have a
2870 *    chance to remove it from the hwslist.   by the time we get it out of
2871 *    the list the interrupt for the new data will be lost.   oops!
2872 *
2873 */
2874
2875STATIC void en_service(struct en_softc *sc)
2876{
2877  struct mbuf *m, *tmp;
2878  u_int32_t cur, dstart, rbd, pdu, *sav, dma, bcode, count, *data, *datastop;
2879  u_int32_t start, stop, cnt, needalign;
2880  int slot, raw, aal5, vci, fill, mlen, tlen, drqneed, need, needfill, end;
2881
2882  aal5 = 0;		/* Silence gcc */
2883next_vci:
2884  if (sc->swsl_size == 0) {
2885#ifdef EN_DEBUG
2886    printf("%s: en_service done\n", device_xname(sc->sc_dev));
2887#endif
2888    return;		/* >>> exit here if swsl now empty <<< */
2889  }
2890
2891  /*
2892   * get slot/vci to service
2893   */
2894
2895  slot = sc->swslist[sc->swsl_head];
2896  vci = sc->rxslot[slot].atm_vci;
2897#ifdef EN_DIAG
2898  if (sc->rxvc2slot[vci] != slot) panic("en_service rx slot/vci sync");
2899#endif
2900
2901  /*
2902   * determine our mode and if we've got any work to do
2903   */
2904
2905  raw = sc->rxslot[slot].oth_flags & ENOTHER_RAW;
2906  start= sc->rxslot[slot].start;
2907  stop= sc->rxslot[slot].stop;
2908  cur = sc->rxslot[slot].cur;
2909
2910#ifdef EN_DEBUG
2911  printf("%s: rx%d: service vci=%d raw=%d start/stop/cur=0x%x 0x%x 0x%x\n",
2912	device_xname(sc->sc_dev), slot, vci, raw, start, stop, cur);
2913#endif
2914
2915same_vci:
2916  dstart = MIDV_DSTART(EN_READ(sc, MID_DST_RP(vci)));
2917  dstart = (dstart * sizeof(u_int32_t)) + start;
2918
2919  /* check to see if there is any data at all */
2920  if (dstart == cur) {
2921defer:					/* defer processing */
2922    EN_WRAPADD(0, MID_SL_N, sc->swsl_head, 1);
2923    sc->rxslot[slot].oth_flags &= ~ENOTHER_SWSL;
2924    sc->swsl_size--;
2925					/* >>> remove from swslist <<< */
2926#ifdef EN_DEBUG
2927    printf("%s: rx%d: remove vci %d from swslist\n",
2928	device_xname(sc->sc_dev), slot, vci);
2929#endif
2930    goto next_vci;
2931  }
2932
2933  /*
2934   * figure out how many bytes we need
2935   * [mlen = # bytes to go in mbufs, fill = # bytes to dump (MIDDMA_JK)]
2936   */
2937
2938  if (raw) {
2939
2940    /* raw mode (aka boodi mode) */
2941    fill = 0;
2942    if (dstart > cur)
2943      mlen = dstart - cur;
2944    else
2945      mlen = (dstart + (EN_RXSZ*1024)) - cur;
2946
2947    if (mlen < sc->rxslot[slot].raw_threshold)
2948      goto defer; 		/* too little data to deal with */
2949
2950  } else {
2951
2952    /* normal mode */
2953    aal5 = (sc->rxslot[slot].atm_flags & ATM_PH_AAL5);
2954    rbd = EN_READ(sc, cur);
2955    if (MID_RBD_ID(rbd) != MID_RBD_STDID)
2956      panic("en_service: id mismatch");
2957
2958    if (rbd & MID_RBD_T) {
2959      mlen = 0;			/* we've got trash */
2960      fill = MID_RBD_SIZE;
2961      EN_COUNT(sc->ttrash);
2962#ifdef EN_DEBUG
2963      printf("RX overflow lost %d cells!\n", MID_RBD_CNT(rbd));
2964#endif
2965    } else if (!aal5) {
2966      mlen = MID_RBD_SIZE + MID_CHDR_SIZE + MID_ATMDATASZ; /* 1 cell (ick!) */
2967      fill = 0;
2968    } else {
2969      struct ifnet *ifp;
2970
2971      tlen = (MID_RBD_CNT(rbd) * MID_ATMDATASZ) + MID_RBD_SIZE;
2972      pdu = cur + tlen - MID_PDU_SIZE;
2973      if (pdu >= stop)
2974	pdu -= (EN_RXSZ*1024);
2975      pdu = EN_READ(sc, pdu);	/* get PDU in correct byte order */
2976      fill = tlen - MID_RBD_SIZE - MID_PDU_LEN(pdu);
2977      if (fill < 0 || (rbd & MID_RBD_CRCERR) != 0) {
2978	static int first = 1;
2979
2980	if (first) {
2981	  printf("%s: %s, dropping frame\n", device_xname(sc->sc_dev),
2982		 (rbd & MID_RBD_CRCERR) ?
2983		 "CRC error" : "invalid AAL5 PDU length");
2984	  printf("%s: got %d cells (%d bytes), AAL5 len is %d bytes (pdu=0x%x)\n",
2985		 device_xname(sc->sc_dev), MID_RBD_CNT(rbd),
2986		 tlen - MID_RBD_SIZE, MID_PDU_LEN(pdu), pdu);
2987#ifndef EN_DEBUG
2988	  printf("CRC error report disabled from now on!\n");
2989	  first = 0;
2990#endif
2991	}
2992	fill = tlen;
2993
2994#ifdef ATM_PVCEXT
2995	ifp = en_vci2ifp(sc, vci);
2996#else
2997	ifp = &sc->enif;
2998#endif
2999	ifp->if_ierrors++;
3000
3001      }
3002      mlen = tlen - fill;
3003    }
3004
3005  }
3006
3007  /*
3008   * now allocate mbufs for mlen bytes of data, if out of mbufs, trash all
3009   *
3010   * notes:
3011   *  1. it is possible that we've already allocated an mbuf for this pkt
3012   *	 but ran out of DRQs, in which case we saved the allocated mbuf on
3013   *	 "q".
3014   *  2. if we save an mbuf in "q" we store the "cur" (pointer) in the front
3015   *     of the mbuf as an identity (that we can check later), and we also
3016   *     store drqneed (so we don't have to recompute it).
3017   *  3. after this block of code, if m is still NULL then we ran out of mbufs
3018   */
3019
3020  m = sc->rxslot[slot].q.ifq_head;
3021  drqneed = 1;
3022  if (m) {
3023    sav = mtod(m, u_int32_t *);
3024    if (sav[0] != cur) {
3025#ifdef EN_DEBUG
3026      printf("%s: rx%d: q'ed mbuf %p not ours\n",
3027		device_xname(sc->sc_dev), slot, m);
3028#endif
3029      m = NULL;			/* wasn't ours */
3030      EN_COUNT(sc->rxqnotus);
3031    } else {
3032      EN_COUNT(sc->rxqus);
3033      IF_DEQUEUE(&sc->rxslot[slot].q, m);
3034      drqneed = sav[1];
3035#ifdef EN_DEBUG
3036      printf("%s: rx%d: recovered q'ed mbuf %p (drqneed=%d)\n",
3037	device_xname(sc->sc_dev), slot, m, drqneed);
3038#endif
3039    }
3040  }
3041
3042  if (mlen != 0 && m == NULL) {
3043    m = en_mget(sc, mlen, &drqneed);		/* allocate! */
3044    if (m == NULL) {
3045      fill += mlen;
3046      mlen = 0;
3047      EN_COUNT(sc->rxmbufout);
3048#ifdef EN_DEBUG
3049      printf("%s: rx%d: out of mbufs\n", device_xname(sc->sc_dev), slot);
3050#endif
3051    }
3052#ifdef EN_DEBUG
3053    printf("%s: rx%d: allocate mbuf %p, mlen=%d, drqneed=%d\n",
3054	device_xname(sc->sc_dev), slot, m, mlen, drqneed);
3055#endif
3056  }
3057
3058#ifdef EN_DEBUG
3059  printf("%s: rx%d: VCI %d, mbuf_chain %p, mlen %d, fill %d\n",
3060	device_xname(sc->sc_dev), slot, vci, m, mlen, fill);
3061#endif
3062
3063  /*
3064   * now check to see if we've got the DRQs needed.    if we are out of
3065   * DRQs we must quit (saving our mbuf, if we've got one).
3066   */
3067
3068  needfill = (fill) ? 1 : 0;
3069  if (drqneed + needfill > sc->drq_free) {
3070    sc->need_drqs = 1;	/* flag condition */
3071    if (m == NULL) {
3072      EN_COUNT(sc->rxoutboth);
3073#ifdef EN_DEBUG
3074      printf("%s: rx%d: out of DRQs *and* mbufs!\n", device_xname(sc->sc_dev), slot);
3075#endif
3076      return;		/* >>> exit here if out of both mbufs and DRQs <<< */
3077    }
3078    sav = mtod(m, u_int32_t *);
3079    sav[0] = cur;
3080    sav[1] = drqneed;
3081    IF_ENQUEUE(&sc->rxslot[slot].q, m);
3082    EN_COUNT(sc->rxdrqout);
3083#ifdef EN_DEBUG
3084    printf("%s: rx%d: out of DRQs\n", device_xname(sc->sc_dev), slot);
3085#endif
3086    return;		/* >>> exit here if out of DRQs <<< */
3087  }
3088
3089  /*
3090   * at this point all resources have been allocated and we are commited
3091   * to servicing this slot.
3092   *
3093   * dma = last location we told chip about
3094   * cur = current location
3095   * mlen = space in the mbuf we want
3096   * need = bytes to xfer in (decrs to zero)
3097   * fill = how much fill we need
3098   * tlen = how much data to transfer to this mbuf
3099   * cnt/bcode/count = <same as xmit>
3100   *
3101   * 'needfill' not used after this point
3102   */
3103
3104  dma = cur;		/* dma = last location we told chip about */
3105  need = roundup(mlen, sizeof(u_int32_t));
3106  fill = fill - (need - mlen);  /* note: may invalidate 'needfill' */
3107
3108  for (tmp = m ; tmp != NULL && need > 0 ; tmp = tmp->m_next) {
3109    tlen = roundup(tmp->m_len, sizeof(u_int32_t)); /* m_len set by en_mget */
3110    data = mtod(tmp, u_int32_t *);
3111
3112#ifdef EN_DEBUG
3113    printf("%s: rx%d: load mbuf %p, m_len=%d, m_data=%p, tlen=%d\n",
3114	device_xname(sc->sc_dev), slot, tmp, tmp->m_len, tmp->m_data, tlen);
3115#endif
3116
3117    /* copy data */
3118    if (EN_NORXDMA || !en_dma || tlen < EN_MINDMA) {
3119      datastop = (u_int32_t *)((u_char *) data + tlen);
3120      /* copy loop: preserve byte order!!!  use READDAT */
3121      while (data != datastop) {
3122	*data = EN_READDAT(sc, cur);
3123	data++;
3124	EN_WRAPADD(start, stop, cur, 4);
3125      }
3126      need -= tlen;
3127#ifdef EN_DEBUG
3128      printf("%s: rx%d: vci%d: copied %d bytes (%d left)\n",
3129		device_xname(sc->sc_dev), slot, vci, tlen, need);
3130#endif
3131      continue;
3132    }
3133
3134    /* DMA data (check to see if we need to sync DRQ first) */
3135    if (dma != cur) {
3136      EN_DRQADD(sc, WORD_IDX(start,cur), vci, MIDDMA_JK, 0, 0, 0, 0);
3137#ifdef EN_DEBUG
3138      printf("%s: rx%d: vci%d: drq_sync: advance pointer to %d\n",
3139		device_xname(sc->sc_dev), slot, vci, cur);
3140#endif
3141    }
3142
3143#if !defined(MIDWAY_ENIONLY)
3144
3145    /*
3146     * the adaptec DMA engine is smart and handles everything for us.
3147     */
3148
3149    if (sc->is_adaptec) {
3150      need -= tlen;
3151      EN_WRAPADD(start, stop, cur, tlen);
3152#ifdef EN_DEBUG
3153      printf("%s: rx%d: vci%d: adp_dma %d bytes (%d left)\n",
3154		device_xname(sc->sc_dev), slot, vci, tlen, need);
3155#endif
3156      end = (need == 0 && !fill) ? MID_DMA_END : 0;
3157      EN_DRQADD(sc, tlen, vci, 0, vtophys((vaddr_t)data), mlen, slot, end);
3158      if (end)
3159        goto done;
3160      dma = cur;	/* update DMA pointer */
3161      continue;
3162    }
3163#endif /* !MIDWAY_ENIONLY */
3164
3165
3166#if !defined(MIDWAY_ADPONLY)
3167
3168    /*
3169     * the ENI DMA engine is not so smart and need more help from us
3170     */
3171
3172    /* do we need to do a DMA op to align? */
3173    if (sc->alburst &&
3174      (needalign = (((unsigned long) data) & sc->bestburstmask)) != 0) {
3175      cnt = sc->bestburstlen - needalign;
3176      if (cnt > tlen) {
3177        cnt = tlen;
3178        count = cnt / sizeof(u_int32_t);
3179        bcode = MIDDMA_WORD;
3180      } else {
3181        count = cnt / sizeof(u_int32_t);
3182        bcode = en_dmaplan[count].bcode;
3183        count = cnt >> en_dmaplan[count].divshift;
3184      }
3185      need -= cnt;
3186      EN_WRAPADD(start, stop, cur, cnt);
3187#ifdef EN_DEBUG
3188      printf("%s: rx%d: vci%d: al_dma %d bytes (%d left)\n",
3189		device_xname(sc->sc_dev), slot, vci, cnt, need);
3190#endif
3191      tlen -= cnt;
3192      end = (need == 0 && !fill) ? MID_DMA_END : 0;
3193      EN_DRQADD(sc, count, vci, bcode, vtophys((vaddr_t)data), mlen, slot, end);
3194      if (end)
3195        goto done;
3196      data = (u_int32_t *)((u_char *) data + cnt);
3197    }
3198
3199    /* do we need a max-sized burst? */
3200    if (tlen >= sc->bestburstlen) {
3201      count = tlen >> sc->bestburstshift;
3202      cnt = count << sc->bestburstshift;
3203      bcode = sc->bestburstcode;
3204      need -= cnt;
3205      EN_WRAPADD(start, stop, cur, cnt);
3206#ifdef EN_DEBUG
3207      printf("%s: rx%d: vci%d: best_dma %d bytes (%d left)\n",
3208		device_xname(sc->sc_dev), slot, vci, cnt, need);
3209#endif
3210      tlen -= cnt;
3211      end = (need == 0 && !fill) ? MID_DMA_END : 0;
3212      EN_DRQADD(sc, count, vci, bcode, vtophys((vaddr_t)data), mlen, slot, end);
3213      if (end)
3214        goto done;
3215      data = (u_int32_t *)((u_char *) data + cnt);
3216    }
3217
3218    /* do we need to do a cleanup burst? */
3219    if (tlen) {
3220      count = tlen / sizeof(u_int32_t);
3221      bcode = en_dmaplan[count].bcode;
3222      count = tlen >> en_dmaplan[count].divshift;
3223      need -= tlen;
3224      EN_WRAPADD(start, stop, cur, tlen);
3225#ifdef EN_DEBUG
3226      printf("%s: rx%d: vci%d: cleanup_dma %d bytes (%d left)\n",
3227		device_xname(sc->sc_dev), slot, vci, tlen, need);
3228#endif
3229      end = (need == 0 && !fill) ? MID_DMA_END : 0;
3230      EN_DRQADD(sc, count, vci, bcode, vtophys((vaddr_t)data), mlen, slot, end);
3231      if (end)
3232        goto done;
3233    }
3234
3235    dma = cur;		/* update DMA pointer */
3236
3237#endif /* !MIDWAY_ADPONLY */
3238
3239  }
3240
3241  /* skip the end */
3242  if (fill || dma != cur) {
3243#ifdef EN_DEBUG
3244      if (fill)
3245        printf("%s: rx%d: vci%d: skipping %d bytes of fill\n",
3246		device_xname(sc->sc_dev), slot, vci, fill);
3247      else
3248        printf("%s: rx%d: vci%d: syncing chip from 0x%x to 0x%x [cur]\n",
3249		device_xname(sc->sc_dev), slot, vci, dma, cur);
3250#endif
3251    EN_WRAPADD(start, stop, cur, fill);
3252    EN_DRQADD(sc, WORD_IDX(start,cur), vci, MIDDMA_JK, 0, mlen,
3253					slot, MID_DMA_END);
3254    /* dma = cur; */	/* not necessary since we are done */
3255  }
3256
3257  /*
3258   * done, remove stuff we don't want to pass up:
3259   *   raw mode (boodi mode): pass everything up for later processing
3260   *   aal5: remove RBD
3261   *   aal0: remove RBD + cell header
3262   */
3263
3264done:
3265  if (m) {
3266    if (!raw) {
3267      cnt = MID_RBD_SIZE;
3268      if (!aal5) cnt += MID_CHDR_SIZE;
3269      m->m_len -= cnt;				/* chop! */
3270      m->m_pkthdr.len -= cnt;
3271      m->m_data += cnt;
3272    }
3273    IF_ENQUEUE(&sc->rxslot[slot].indma, m);
3274  }
3275  sc->rxslot[slot].cur = cur;		/* update master copy of 'cur' */
3276
3277#ifdef EN_DEBUG
3278  printf("%s: rx%d: vci%d: DONE!   cur now =0x%x\n",
3279	device_xname(sc->sc_dev), slot, vci, cur);
3280#endif
3281
3282  goto same_vci;	/* get next packet in this slot */
3283}
3284
3285
3286#ifdef EN_DDBHOOK
3287/*
3288 * functions we can call from ddb
3289 */
3290
3291/*
3292 * en_dump: dump the state
3293 */
3294
3295#define END_SWSL	0x00000040		/* swsl state */
3296#define END_DRQ		0x00000020		/* drq state */
3297#define END_DTQ		0x00000010		/* dtq state */
3298#define END_RX		0x00000008		/* rx state */
3299#define END_TX		0x00000004		/* tx state */
3300#define END_MREGS	0x00000002		/* registers */
3301#define END_STATS	0x00000001		/* dump stats */
3302
3303#define END_BITS "\20\7SWSL\6DRQ\5DTQ\4RX\3TX\2MREGS\1STATS"
3304
3305int en_dump(int unit, int level)
3306{
3307  struct en_softc *sc;
3308  int lcv, cnt, slot;
3309  u_int32_t ptr, reg;
3310
3311  for (lcv = 0 ; lcv < en_cd.cd_ndevs ; lcv++) {
3312    char sbuf[256];
3313
3314    sc = device_lookup_private(&en_cd, lcv);
3315    if (sc == NULL) continue;
3316    if (unit != -1 && unit != lcv)
3317      continue;
3318
3319    snprintb(sbuf, sizeof(sbuf), END_BITS, level);
3320    printf("dumping device %s at level 0x%s\n", device_xname(sc->sc_dev), sbuf);
3321
3322    if (sc->dtq_us == 0) {
3323      printf("<hasn't been en_init'd yet>\n");
3324      continue;
3325    }
3326
3327    if (level & END_STATS) {
3328      printf("  en_stats:\n");
3329      printf("    %d mfix (%d failed); %d/%d head/tail byte DMAs, %d flushes\n",
3330	   sc->mfix, sc->mfixfail, sc->headbyte, sc->tailbyte, sc->tailflush);
3331      printf("    %d rx DMA overflow interrupts\n", sc->dmaovr);
3332      printf("    %d times we ran out of TX space and stalled\n",
3333							sc->txoutspace);
3334      printf("    %d times we ran out of DTQs\n", sc->txdtqout);
3335      printf("    %d times we launched a packet\n", sc->launch);
3336      printf("    %d times we launched without on-board header\n", sc->lheader);
3337      printf("    %d times we launched without on-board tail\n", sc->ltail);
3338      printf("    %d times we pulled the hw service list\n", sc->hwpull);
3339      printf("    %d times we pushed a vci on the sw service list\n",
3340								sc->swadd);
3341      printf("    %d times RX pulled an mbuf from Q that wasn't ours\n",
3342							 sc->rxqnotus);
3343      printf("    %d times RX pulled a good mbuf from Q\n", sc->rxqus);
3344      printf("    %d times we ran out of mbufs *and* DRQs\n", sc->rxoutboth);
3345      printf("    %d times we ran out of DRQs\n", sc->rxdrqout);
3346
3347      printf("    %d transmit packets dropped due to mbsize\n", sc->txmbovr);
3348      printf("    %d cells trashed due to turned off rxvc\n", sc->vtrash);
3349      printf("    %d cells trashed due to totally full buffer\n", sc->otrash);
3350      printf("    %d cells trashed due almost full buffer\n", sc->ttrash);
3351      printf("    %d rx mbuf allocation failures\n", sc->rxmbufout);
3352#ifdef NATM
3353      printf("    %d drops at natmintrq\n", natmintrq.ifq_drops);
3354#ifdef NATM_STAT
3355      printf("    natmintr so_rcv: ok/drop cnt: %d/%d, ok/drop bytes: %d/%d\n",
3356	natm_sookcnt, natm_sodropcnt, natm_sookbytes, natm_sodropbytes);
3357#endif
3358#endif
3359    }
3360
3361    if (level & END_MREGS) {
3362      char ybuf[256];
3363
3364      printf("mregs:\n");
3365      printf("resid = 0x%x\n", EN_READ(sc, MID_RESID));
3366
3367      snprintb(ybuf, sizeof(ybuf), MID_INTBITS, EN_READ(sc, MID_INTSTAT));
3368      printf("interrupt status = 0x%s\n", ybuf);
3369
3370      snprintb(ybuf, sizeof(ybuf), MID_INTBITS, EN_READ(sc, MID_INTENA));
3371      printf("interrupt enable = 0x%s\n", ybuf);
3372
3373      snprintb(ybuf, sizeof(ybuf), MID_MCSRBITS, EN_READ(sc, MID_MAST_CSR));
3374      printf("mcsr = 0x%s\n", ybuf);
3375
3376      printf("serv_write = [chip=%d] [us=%d]\n", EN_READ(sc, MID_SERV_WRITE),
3377			MID_SL_A2REG(sc->hwslistp));
3378      printf("DMA addr = 0x%x\n", EN_READ(sc, MID_DMA_ADDR));
3379      printf("DRQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3380	MID_DRQ_REG2A(EN_READ(sc, MID_DMA_RDRX)),
3381	MID_DRQ_REG2A(EN_READ(sc, MID_DMA_WRRX)), sc->drq_chip, sc->drq_us);
3382      printf("DTQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3383	MID_DTQ_REG2A(EN_READ(sc, MID_DMA_RDTX)),
3384	MID_DTQ_REG2A(EN_READ(sc, MID_DMA_WRTX)), sc->dtq_chip, sc->dtq_us);
3385
3386      printf("  unusal txspeeds: ");
3387      for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3388	if (sc->txspeed[cnt])
3389	  printf(" vci%d=0x%x", cnt, sc->txspeed[cnt]);
3390      printf("\n");
3391
3392      printf("  rxvc slot mappings: ");
3393      for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3394	if (sc->rxvc2slot[cnt] != RX_NONE)
3395	  printf("  %d->%d", cnt, sc->rxvc2slot[cnt]);
3396      printf("\n");
3397
3398    }
3399
3400    if (level & END_TX) {
3401      printf("tx:\n");
3402      for (slot = 0 ; slot < EN_NTX; slot++) {
3403	printf("tx%d: start/stop/cur=0x%x/0x%x/0x%x [%d]  ", slot,
3404	  sc->txslot[slot].start, sc->txslot[slot].stop, sc->txslot[slot].cur,
3405		(sc->txslot[slot].cur - sc->txslot[slot].start)/4);
3406	printf("mbsize=%d, bfree=%d\n", sc->txslot[slot].mbsize,
3407		sc->txslot[slot].bfree);
3408        printf("txhw: base_address=0x%lx, size=%d, read=%d, descstart=%d\n",
3409	  (u_long)MIDX_BASE(EN_READ(sc, MIDX_PLACE(slot))),
3410	  MIDX_SZ(EN_READ(sc, MIDX_PLACE(slot))),
3411	  EN_READ(sc, MIDX_READPTR(slot)), EN_READ(sc, MIDX_DESCSTART(slot)));
3412      }
3413    }
3414
3415    if (level & END_RX) {
3416      printf("  recv slots:\n");
3417      for (slot = 0 ; slot < sc->en_nrx; slot++) {
3418	printf("rx%d: vci=%d: start/stop/cur=0x%x/0x%x/0x%x ", slot,
3419	  sc->rxslot[slot].atm_vci, sc->rxslot[slot].start,
3420	  sc->rxslot[slot].stop, sc->rxslot[slot].cur);
3421	printf("mode=0x%x, atm_flags=0x%x, oth_flags=0x%x\n",
3422	sc->rxslot[slot].mode, sc->rxslot[slot].atm_flags,
3423		sc->rxslot[slot].oth_flags);
3424        printf("RXHW: mode=0x%x, DST_RP=0x%x, WP_ST_CNT=0x%x\n",
3425	  EN_READ(sc, MID_VC(sc->rxslot[slot].atm_vci)),
3426	  EN_READ(sc, MID_DST_RP(sc->rxslot[slot].atm_vci)),
3427	  EN_READ(sc, MID_WP_ST_CNT(sc->rxslot[slot].atm_vci)));
3428      }
3429    }
3430
3431    if (level & END_DTQ) {
3432      printf("  dtq [need_dtqs=%d,dtq_free=%d]:\n",
3433					sc->need_dtqs, sc->dtq_free);
3434      ptr = sc->dtq_chip;
3435      while (ptr != sc->dtq_us) {
3436        reg = EN_READ(sc, ptr);
3437        printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n",
3438	    sc->dtq[MID_DTQ_A2REG(ptr)], MID_DMA_CNT(reg), MID_DMA_TXCHAN(reg),
3439	    (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg), EN_READ(sc, ptr+4));
3440        EN_WRAPADD(MID_DTQOFF, MID_DTQEND, ptr, 8);
3441      }
3442    }
3443
3444    if (level & END_DRQ) {
3445      printf("  drq [need_drqs=%d,drq_free=%d]:\n",
3446					sc->need_drqs, sc->drq_free);
3447      ptr = sc->drq_chip;
3448      while (ptr != sc->drq_us) {
3449        reg = EN_READ(sc, ptr);
3450	printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n",
3451	  sc->drq[MID_DRQ_A2REG(ptr)], MID_DMA_CNT(reg), MID_DMA_RXVCI(reg),
3452	  (reg & MID_DMA_END) != 0, MID_DMA_TYPE(reg), EN_READ(sc, ptr+4));
3453	EN_WRAPADD(MID_DRQOFF, MID_DRQEND, ptr, 8);
3454      }
3455    }
3456
3457    if (level & END_SWSL) {
3458      printf(" swslist [size=%d]: ", sc->swsl_size);
3459      for (cnt = sc->swsl_head ; cnt != sc->swsl_tail ;
3460			cnt = (cnt + 1) % MID_SL_N)
3461        printf("0x%x ", sc->swslist[cnt]);
3462      printf("\n");
3463    }
3464  }
3465  return(0);
3466}
3467
3468/*
3469 * en_dumpmem: dump the memory
3470 */
3471
3472int en_dumpmem(int unit, int addr, int len)
3473{
3474  struct en_softc *sc;
3475  u_int32_t reg;
3476
3477  sc = device_lookup_private(&en_cd, unit);
3478  if (sc == NULL) {
3479    printf("invalid unit number: %d\n", unit);
3480    return(0);
3481  }
3482  addr = addr & ~3;
3483  if (addr < MID_RAMOFF || addr + len*4 > MID_MAXOFF || len <= 0) {
3484    printf("invalid addr/len number: %d, %d\n", addr, len);
3485    return(0);
3486  }
3487  printf("dumping %d words starting at offset 0x%x\n", len, addr);
3488  while (len--) {
3489    reg = EN_READ(sc, addr);
3490    printf("mem[0x%x] = 0x%x\n", addr, reg);
3491    addr += 4;
3492  }
3493  return(0);
3494}
3495#endif
3496
3497#ifdef ATM_PVCEXT
3498/*
3499 * ATM PVC extension: shaper control and pvc subinterfaces
3500 */
3501
3502/*
3503 * the list of the interfaces sharing the physical device.
3504 * in order to avoid starvation, the interfaces are scheduled in
3505 * a round-robin fashion when en_start is called from tx complete
3506 * interrupts.
3507 */
3508static void rrp_add(struct en_softc *sc, struct ifnet *ifp)
3509{
3510	struct rrp *head, *p, *new;
3511
3512	head = sc->txrrp;
3513	if ((p = head) != NULL) {
3514		while (1) {
3515			if (p->ifp == ifp) {
3516				/* an entry for this ifp already exits */
3517				p->nref++;
3518				return;
3519			}
3520			if (p->next == head)
3521				break;
3522			p = p->next;
3523		}
3524	}
3525
3526	/* create a new entry */
3527	new = malloc(sizeof(struct rrp), M_DEVBUF, M_WAITOK);
3528	if (new == NULL) {
3529		printf("en_rrp_add: malloc failed!\n");
3530		return;
3531	}
3532
3533	new->ifp = ifp;
3534	new->nref = 1;
3535
3536	if (p == NULL) {
3537		/* this is the only one in the list */
3538		new->next = new;
3539		sc->txrrp = new;
3540	}
3541	else {
3542		/* add the new entry at the tail of the list */
3543		new->next = p->next;
3544		p->next = new;
3545	}
3546}
3547
3548#if 0 /* not used */
3549static void rrp_delete(struct en_softc *sc, struct ifnet *ifp)
3550{
3551	struct rrp *head, *p, *prev;
3552
3553	head = sc->txrrp;
3554
3555	prev = head;
3556	if (prev == NULL) {
3557		printf("rrp_delete: no list!\n");
3558		return;
3559	}
3560	p = prev->next;
3561
3562	while (1) {
3563		if (p->ifp == ifp) {
3564			p->nref--;
3565			if (p->nref > 0)
3566				return;
3567			/* remove this entry */
3568			if (p == prev) {
3569				/* this is the only entry in the list */
3570				sc->txrrp = NULL;
3571			}
3572			else {
3573				prev->next = p->next;
3574				if (head == p)
3575					sc->txrrp = p->next;
3576			}
3577			free(p, M_DEVBUF);
3578		}
3579		prev = p;
3580		p = prev->next;
3581		if (prev == head) {
3582			printf("rrp_delete: no matching entry!\n");
3583			return;
3584		}
3585	}
3586}
3587#endif
3588
3589static struct ifnet *
3590en_vci2ifp(struct en_softc *sc, int vci)
3591{
3592	struct pvcsif *pvcsif;
3593
3594	LIST_FOREACH(pvcsif, &sc->sif_list, sif_links) {
3595		if (vci == pvcsif->sif_vci)
3596			return (&pvcsif->sif_if);
3597	}
3598	return (&sc->enif);
3599}
3600
3601/*
3602 * create and attach per pvc subinterface
3603 * (currently detach is not supported)
3604 */
3605static struct ifnet *
3606en_pvcattach(struct ifnet *ifp)
3607{
3608	struct en_softc *sc = (struct en_softc *) ifp->if_softc;
3609	struct ifnet *pvc_ifp;
3610	int s;
3611
3612	if ((pvc_ifp = pvcsif_alloc()) == NULL)
3613		return (NULL);
3614
3615	pvc_ifp->if_softc = sc;
3616	pvc_ifp->if_ioctl = en_ioctl;
3617	pvc_ifp->if_start = en_start;
3618	pvc_ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST) |
3619		(ifp->if_flags & (IFF_RUNNING|IFF_SIMPLEX|IFF_NOTRAILERS));
3620
3621	s = splnet();
3622	LIST_INSERT_HEAD(&sc->sif_list, (struct pvcsif *)pvc_ifp, sif_links);
3623	if_attach(pvc_ifp);
3624	atm_ifattach(pvc_ifp);
3625
3626#ifdef ATM_PVCEXT
3627	rrp_add(sc, pvc_ifp);
3628#endif
3629	splx(s);
3630
3631	return (pvc_ifp);
3632}
3633
3634
3635/* txspeed conversion derived from linux drivers/atm/eni.c
3636   by Werner Almesberger, EPFL LRC */
3637static const int pre_div[] = { 4,16,128,2048 };
3638
3639static int en_pcr2txspeed(int pcr)
3640{
3641	int pre, res, div;
3642
3643	if (pcr == 0 || pcr > 347222)
3644		pre = res = 0;	/* max rate */
3645	else {
3646		for (pre = 0; pre < 3; pre++)
3647			if (25000000/pre_div[pre]/64 <= pcr)
3648				break;
3649		div = pre_div[pre]*(pcr);
3650#if 1
3651		/*
3652		 * the shaper value should be rounded down,
3653		 * instead of rounded up.
3654		 * (which means "res" should be rounded up.)
3655		 */
3656		res = (25000000 + div -1)/div - 1;
3657#else
3658		res = 25000000/div-1;
3659#endif
3660		if (res < 0)
3661			res = 0;
3662		if (res > 63)
3663			res = 63;
3664	}
3665	return ((pre << 6) + res);
3666}
3667
3668static int en_txspeed2pcr(int txspeed)
3669{
3670	int pre, res, pcr;
3671
3672	pre = (txspeed >> 6) & 0x3;
3673	res = txspeed & 0x3f;
3674	pcr = 25000000 / pre_div[pre] / (res+1);
3675	return (pcr);
3676}
3677
3678/*
3679 * en_txctl selects a hardware transmit channel and sets the shaper value.
3680 * en_txctl should be called after enabling the vc by en_rxctl
3681 * since it assumes a transmit channel is already assigned by en_rxctl
3682 * to the vc.
3683 */
3684static int en_txctl(struct en_softc *sc, int vci, int joint_vci, int pcr)
3685{
3686	int txspeed, txchan, s;
3687
3688	if (pcr)
3689		txspeed = en_pcr2txspeed(pcr);
3690	else
3691		txspeed = 0;
3692
3693	s = splnet();
3694	txchan = sc->txvc2slot[vci];
3695	sc->txslot[txchan].nref--;
3696
3697	/* select a slot */
3698	if (joint_vci != 0)
3699		/* use the same channel */
3700		txchan = sc->txvc2slot[joint_vci];
3701	else if (pcr == 0)
3702		txchan = 0;
3703	else {
3704		for (txchan = 1; txchan < EN_NTX; txchan++) {
3705			if (sc->txslot[txchan].nref == 0)
3706				break;
3707		}
3708	}
3709	if (txchan == EN_NTX) {
3710#if 1
3711		/* no free slot! */
3712		splx(s);
3713		return (ENOSPC);
3714#else
3715		/*
3716		 * to allow multiple vc's to share a slot,
3717		 * use a slot with the smallest reference count
3718		 */
3719		int slot = 1;
3720		txchan = 1;
3721		for (slot = 2; slot < EN_NTX; slot++)
3722			if (sc->txslot[slot].nref < sc->txslot[txchan].nref)
3723				txchan = slot;
3724#endif
3725	}
3726
3727	sc->txvc2slot[vci] = txchan;
3728	sc->txslot[txchan].nref++;
3729
3730	/* set the shaper parameter */
3731	sc->txspeed[vci] = (u_int8_t)txspeed;
3732
3733	splx(s);
3734#ifdef EN_DEBUG
3735	printf("VCI:%d PCR set to %d, tx channel %d\n", vci, pcr, txchan);
3736	if (joint_vci != 0)
3737		printf("  slot shared with VCI:%d\n", joint_vci);
3738#endif
3739	return (0);
3740}
3741
3742static int en_pvctx(struct en_softc *sc, struct pvctxreq *pvcreq)
3743{
3744	struct ifnet *ifp;
3745	struct atm_pseudoioctl api;
3746	struct atm_pseudohdr *pvc_aph, *pvc_joint;
3747	int vci, joint_vci, pcr;
3748	int error = 0;
3749
3750	/* check vpi:vci values */
3751	pvc_aph = &pvcreq->pvc_aph;
3752	pvc_joint = &pvcreq->pvc_joint;
3753
3754	vci = ATM_PH_VCI(pvc_aph);
3755	joint_vci = ATM_PH_VCI(pvc_joint);
3756	pcr = pvcreq->pvc_pcr;
3757
3758	if (ATM_PH_VPI(pvc_aph) != 0 || vci >= MID_N_VC ||
3759	    ATM_PH_VPI(pvc_joint) != 0 || joint_vci >= MID_N_VC)
3760		return (EADDRNOTAVAIL);
3761
3762	if ((ifp = ifunit(pvcreq->pvc_ifname)) == NULL)
3763		return (ENXIO);
3764
3765	if (pcr < 0) {
3766		/* negative pcr means disable the vc. */
3767		if (sc->rxvc2slot[vci] == RX_NONE)
3768			/* already disabled */
3769			return 0;
3770
3771		ATM_PH_FLAGS(&api.aph) = 0;
3772		ATM_PH_VPI(&api.aph) = 0;
3773		ATM_PH_SETVCI(&api.aph, vci);
3774		api.rxhand = NULL;
3775
3776		error = en_rxctl(sc, &api, 0);
3777
3778		if (error == 0 && &sc->enif != ifp) {
3779			/* clear vc info of this subinterface */
3780			struct pvcsif *pvcsif = (struct pvcsif *)ifp;
3781
3782			ATM_PH_SETVCI(&api.aph, 0);
3783			pvcsif->sif_aph = api.aph;
3784			pvcsif->sif_vci = 0;
3785		}
3786		return (error);
3787	}
3788
3789	if (&sc->enif == ifp) {
3790		/* called for an en interface */
3791		if (sc->rxvc2slot[vci] == RX_NONE) {
3792			/* vc is not active */
3793#ifdef __NetBSD__
3794			printf("%s: en_pvctx: rx not active! vci=%d\n",
3795			       ifp->if_xname, vci);
3796#else
3797			printf("%s%d: en_pvctx: rx not active! vci=%d\n",
3798			       ifp->if_name, ifp->if_unit, vci);
3799#endif
3800			return (EINVAL);
3801		}
3802	}
3803	else {
3804		/* called for a pvc subinterface */
3805		struct pvcsif *pvcsif = (struct pvcsif *)ifp;
3806
3807#ifdef __NetBSD__
3808    		strlcpy(pvcreq->pvc_ifname, sc->enif.if_xname,
3809		    sizeof(pvcreq->pvc_ifname));
3810#else
3811    		snprintf(pvcreq->pvc_ifname, sizeof(pvcreq->pvc_ifname), "%s%d",
3812		    sc->enif.if_name, sc->enif.if_unit);
3813#endif
3814		ATM_PH_FLAGS(&api.aph) =
3815			(ATM_PH_FLAGS(pvc_aph) & (ATM_PH_AAL5|ATM_PH_LLCSNAP));
3816		ATM_PH_VPI(&api.aph) = 0;
3817		ATM_PH_SETVCI(&api.aph, vci);
3818		api.rxhand = NULL;
3819		pvcsif->sif_aph = api.aph;
3820		pvcsif->sif_vci = ATM_PH_VCI(&api.aph);
3821
3822		if (sc->rxvc2slot[vci] == RX_NONE) {
3823			/* vc is not active, enable rx */
3824			error = en_rxctl(sc, &api, 1);
3825			if (error)
3826				return error;
3827		}
3828		else {
3829			/* vc is already active, update aph in softc */
3830			sc->rxslot[sc->rxvc2slot[vci]].atm_flags =
3831				ATM_PH_FLAGS(&api.aph);
3832		}
3833	}
3834
3835	error = en_txctl(sc, vci, joint_vci, pcr);
3836
3837	if (error == 0) {
3838		if (sc->txspeed[vci] != 0)
3839			pvcreq->pvc_pcr = en_txspeed2pcr(sc->txspeed[vci]);
3840		else
3841			pvcreq->pvc_pcr = 0;
3842	}
3843
3844	return error;
3845}
3846
3847static int en_pvctxget(struct en_softc *sc, struct pvctxreq *pvcreq)
3848{
3849	struct pvcsif *pvcsif;
3850	struct ifnet *ifp;
3851	int vci, slot;
3852
3853	if ((ifp = ifunit(pvcreq->pvc_ifname)) == NULL)
3854		return (ENXIO);
3855
3856	if (ifp == &sc->enif) {
3857		/* physical interface: assume vci is specified */
3858		struct atm_pseudohdr *pvc_aph;
3859
3860		pvc_aph = &pvcreq->pvc_aph;
3861		vci = ATM_PH_VCI(pvc_aph);
3862		if ((slot = sc->rxvc2slot[vci]) == RX_NONE)
3863			ATM_PH_FLAGS(pvc_aph) = 0;
3864		else
3865			ATM_PH_FLAGS(pvc_aph) = sc->rxslot[slot].atm_flags;
3866		ATM_PH_VPI(pvc_aph) = 0;
3867	}
3868	else {
3869		/* pvc subinterface */
3870#ifdef __NetBSD__
3871		strlcpy(pvcreq->pvc_ifname, sc->enif.if_xname,
3872		    sizeof(pvcreq->pvc_ifname));
3873#else
3874		snprintf(pvcreq->pvc_ifname, sizeof(pvcreq->pvc_ifname), "%s%d",
3875		    sc->enif.if_name, sc->enif.if_unit);
3876#endif
3877
3878		pvcsif = (struct pvcsif *)ifp;
3879		pvcreq->pvc_aph = pvcsif->sif_aph;
3880		vci = pvcsif->sif_vci;
3881	}
3882
3883	if ((slot = sc->rxvc2slot[vci]) == RX_NONE) {
3884		/* vc is not active */
3885		ATM_PH_FLAGS(&pvcreq->pvc_aph) = 0;
3886		pvcreq->pvc_pcr = -1;
3887	}
3888	else if (sc->txspeed[vci])
3889		pvcreq->pvc_pcr = en_txspeed2pcr(sc->txspeed[vci]);
3890	else
3891		pvcreq->pvc_pcr = 0;
3892
3893	return (0);
3894}
3895
3896#endif /* ATM_PVCEXT */
3897
3898#endif /* NEN > 0 || !defined(__FreeBSD__) */
3899