]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/en/midway.c
This commit was generated by cvs2svn to compensate for changes in r163976,
[FreeBSD/FreeBSD.git] / sys / dev / en / midway.c
1 /*      $NetBSD: midway.c,v 1.30 1997/09/29 17:40:38 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  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Charles D. Cranor and
19  *      Washington University.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 /*
38  *
39  * m i d w a y . c   e n i 1 5 5   d r i v e r 
40  *
41  * author: Chuck Cranor <chuck@ccrc.wustl.edu>
42  * started: spring, 1996 (written from scratch).
43  *
44  * notes from the author:
45  *   Extra special thanks go to Werner Almesberger, EPFL LRC.   Werner's
46  *   ENI driver was especially useful in figuring out how this card works.
47  *   I would also like to thank Werner for promptly answering email and being
48  *   generally helpful.
49  */
50
51 #define EN_DIAG
52 #define EN_DDBHOOK      1       /* compile in ddb functions */
53
54 /*
55  * Note on EN_ENIDMAFIX: the byte aligner on the ENI version of the card
56  * appears to be broken.   it works just fine if there is no load... however
57  * when the card is loaded the data get corrupted.   to see this, one only
58  * has to use "telnet" over ATM.   do the following command in "telnet":
59  *      cat /usr/share/misc/termcap
60  * "telnet" seems to generate lots of 1023 byte mbufs (which make great
61  * use of the byte aligner).   watch "netstat -s" for checksum errors.
62  * 
63  * I further tested this by adding a function that compared the transmit 
64  * data on the card's SRAM with the data in the mbuf chain _after_ the 
65  * "transmit DMA complete" interrupt.   using the "telnet" test I got data
66  * mismatches where the byte-aligned data should have been.   using ddb
67  * and en_dumpmem() I verified that the DTQs fed into the card were 
68  * absolutely correct.   thus, we are forced to concluded that the ENI
69  * hardware is buggy.   note that the Adaptec version of the card works
70  * just fine with byte DMA.
71  *
72  * bottom line: we set EN_ENIDMAFIX to 1 to avoid byte DMAs on the ENI
73  * card.
74  */
75
76 #if defined(DIAGNOSTIC) && !defined(EN_DIAG)
77 #define EN_DIAG                 /* link in with master DIAG option */
78 #endif
79
80 #define EN_COUNT(X) (X)++
81
82 #ifdef EN_DEBUG
83
84 #undef  EN_DDBHOOK
85 #define EN_DDBHOOK      1
86
87 /*
88  * This macro removes almost all the EN_DEBUG conditionals in the code that make
89  * to code a good deal less readable.
90  */
91 #define DBG(SC, FL, PRINT) do {                                         \
92         if ((SC)->debug & DBG_##FL) {                                   \
93                 device_printf((SC)->dev, "%s: "#FL": ", __func__);      \
94                 printf PRINT;                                           \
95                 printf("\n");                                           \
96         }                                                               \
97     } while (0)
98
99 enum {
100         DBG_INIT        = 0x0001,       /* debug attach/detach */
101         DBG_TX          = 0x0002,       /* debug transmitting */
102         DBG_SERV        = 0x0004,       /* debug service interrupts */
103         DBG_IOCTL       = 0x0008,       /* debug ioctls */
104         DBG_VC          = 0x0010,       /* debug VC handling */
105         DBG_INTR        = 0x0020,       /* debug interrupts */
106         DBG_DMA         = 0x0040,       /* debug DMA probing */
107         DBG_IPACKETS    = 0x0080,       /* print input packets */
108         DBG_REG         = 0x0100,       /* print all register access */
109         DBG_LOCK        = 0x0200,       /* debug locking */
110 };
111
112 #else /* EN_DEBUG */
113
114 #define DBG(SC, FL, PRINT) do { } while (0)
115
116 #endif /* EN_DEBUG */
117
118 #include "opt_inet.h"
119 #include "opt_natm.h"
120 #include "opt_ddb.h"
121
122 #ifdef DDB
123 #undef  EN_DDBHOOK
124 #define EN_DDBHOOK      1
125 #endif
126
127 #include <sys/param.h>
128 #include <sys/systm.h>
129 #include <sys/kdb.h>
130 #include <sys/queue.h>
131 #include <sys/sockio.h>
132 #include <sys/socket.h>
133 #include <sys/mbuf.h>
134 #include <sys/endian.h>
135 #include <sys/stdint.h>
136 #include <sys/lock.h>
137 #include <sys/mutex.h>
138 #include <sys/condvar.h>
139 #include <vm/uma.h>
140
141 #include <net/if.h>
142 #include <net/if_media.h>
143 #include <net/if_atm.h>
144
145 #if defined(INET) || defined(INET6)
146 #include <netinet/in.h>
147 #include <netinet/if_atm.h>
148 #endif
149
150 #ifdef NATM
151 #include <netnatm/natm.h>
152 #endif
153
154 #include <sys/bus.h>
155 #include <machine/bus.h>
156 #include <sys/rman.h>
157 #include <sys/module.h>
158 #include <sys/sysctl.h>
159 #include <sys/malloc.h>
160 #include <machine/resource.h>
161 #include <dev/utopia/utopia.h>
162 #include <dev/en/midwayreg.h>
163 #include <dev/en/midwayvar.h>
164
165 #include <net/bpf.h>
166
167 /*
168  * params
169  */
170 #ifndef EN_TXHIWAT
171 #define EN_TXHIWAT      (64 * 1024)     /* max 64 KB waiting to be DMAd out */
172 #endif
173
174 SYSCTL_DECL(_hw_atm);
175
176 /*
177  * dma tables
178  *
179  * The plan is indexed by the number of words to transfer.
180  * The maximum index is 15 for 60 words.
181  */
182 struct en_dmatab {
183         uint8_t bcode;          /* code */
184         uint8_t divshift;       /* byte divisor */
185 };
186
187 static const struct en_dmatab en_dmaplan[] = {
188   { 0, 0 },             /* 0 */         { MIDDMA_WORD, 2},      /* 1 */
189   { MIDDMA_2WORD, 3},   /* 2 */         { MIDDMA_WORD, 2},      /* 3 */
190   { MIDDMA_4WORD, 4},   /* 4 */         { MIDDMA_WORD, 2},      /* 5 */
191   { MIDDMA_2WORD, 3},   /* 6 */         { MIDDMA_WORD, 2},      /* 7 */
192   { MIDDMA_8WORD, 5},   /* 8 */         { MIDDMA_WORD, 2},      /* 9 */
193   { MIDDMA_2WORD, 3},   /* 10 */        { MIDDMA_WORD, 2},      /* 11 */
194   { MIDDMA_4WORD, 4},   /* 12 */        { MIDDMA_WORD, 2},      /* 13 */
195   { MIDDMA_2WORD, 3},   /* 14 */        { MIDDMA_WORD, 2},      /* 15 */
196   { MIDDMA_16WORD,6},   /* 16 */
197 };
198
199 /*
200  * prototypes
201  */
202 #ifdef EN_DDBHOOK
203 int en_dump(int unit, int level);
204 int en_dumpmem(int,int,int);
205 #endif
206 static void en_close_finish(struct en_softc *sc, struct en_vcc *vc);
207
208 #define EN_LOCK(SC)     do {                            \
209         DBG(SC, LOCK, ("ENLOCK %d\n", __LINE__));       \
210         mtx_lock(&sc->en_mtx);                          \
211     } while (0)
212 #define EN_UNLOCK(SC)   do {                            \
213         DBG(SC, LOCK, ("ENUNLOCK %d\n", __LINE__));     \
214         mtx_unlock(&sc->en_mtx);                        \
215     } while (0)
216 #define EN_CHECKLOCK(sc)        mtx_assert(&sc->en_mtx, MA_OWNED)
217
218 /*
219  * While a transmit mbuf is waiting to get transmit DMA resources we
220  * need to keep some information with it. We don't want to allocate
221  * additional memory for this so we stuff it into free fields in the
222  * mbuf packet header. Neither the checksum fields nor the rcvif field are used
223  * so use these.
224  */
225 #define TX_AAL5         0x1     /* transmit AAL5 PDU */
226 #define TX_HAS_TBD      0x2     /* TBD did fit into mbuf */
227 #define TX_HAS_PAD      0x4     /* padding did fit into mbuf */
228 #define TX_HAS_PDU      0x8     /* PDU trailer did fit into mbuf */
229
230 #define MBUF_SET_TX(M, VCI, FLAGS, DATALEN, PAD, MAP) do {              \
231         (M)->m_pkthdr.csum_data = (VCI) | ((FLAGS) << MID_VCI_BITS);    \
232         (M)->m_pkthdr.csum_flags = ((DATALEN) & 0xffff) |               \
233             ((PAD & 0x3f) << 16);                                       \
234         (M)->m_pkthdr.rcvif = (void *)(MAP);                            \
235     } while (0)
236
237 #define MBUF_GET_TX(M, VCI, FLAGS, DATALEN, PAD, MAP) do {              \
238         (VCI) = (M)->m_pkthdr.csum_data & ((1 << MID_VCI_BITS) - 1);    \
239         (FLAGS) = ((M)->m_pkthdr.csum_data >> MID_VCI_BITS) & 0xf;      \
240         (DATALEN) = (M)->m_pkthdr.csum_flags & 0xffff;                  \
241         (PAD) = ((M)->m_pkthdr.csum_flags >> 16) & 0x3f;                \
242         (MAP) = (void *)((M)->m_pkthdr.rcvif);                          \
243     } while (0)
244
245
246 #define EN_WRAPADD(START, STOP, CUR, VAL) do {                  \
247         (CUR) = (CUR) + (VAL);                                  \
248         if ((CUR) >= (STOP))                                    \
249                 (CUR) = (START) + ((CUR) - (STOP));             \
250     } while (0)
251
252 #define WORD_IDX(START, X) (((X) - (START)) / sizeof(uint32_t))
253
254 #define SETQ_END(SC, VAL) ((SC)->is_adaptec ?                   \
255         ((VAL) | (MID_DMA_END >> 4)) :                          \
256         ((VAL) | (MID_DMA_END)))
257
258 /*
259  * The dtq and drq members are set for each END entry in the corresponding
260  * card queue entry. It is used to find out, when a buffer has been
261  * finished DMAing and can be freed.
262  *
263  * We store sc->dtq and sc->drq data in the following format...
264  * the 0x80000 ensures we != 0
265  */
266 #define EN_DQ_MK(SLOT, LEN)     (((SLOT) << 20) | (LEN) | (0x80000))
267 #define EN_DQ_SLOT(X)           ((X) >> 20)
268 #define EN_DQ_LEN(X)            ((X) & 0x3ffff)
269
270 /*
271  * Variables
272  */
273 static uma_zone_t en_vcc_zone;
274
275 /***********************************************************************/
276
277 /*
278  * en_read{x}: read a word from the card. These are the only functions
279  * that read from the card.
280  */
281 static __inline uint32_t
282 en_readx(struct en_softc *sc, uint32_t r)
283 {
284         uint32_t v;
285
286 #ifdef EN_DIAG
287         if (r > MID_MAXOFF || (r % 4))
288                 panic("en_read out of range, r=0x%x", r);
289 #endif
290         v = bus_space_read_4(sc->en_memt, sc->en_base, r);
291         return (v);
292 }
293
294 static __inline uint32_t
295 en_read(struct en_softc *sc, uint32_t r)
296 {
297         uint32_t v;
298
299 #ifdef EN_DIAG
300         if (r > MID_MAXOFF || (r % 4))
301                 panic("en_read out of range, r=0x%x", r);
302 #endif
303         v = bus_space_read_4(sc->en_memt, sc->en_base, r);
304         DBG(sc, REG, ("en_read(%#x) -> %08x", r, v));
305         return (v);
306 }
307
308 /*
309  * en_write: write a word to the card. This is the only function that
310  * writes to the card.
311  */
312 static __inline void
313 en_write(struct en_softc *sc, uint32_t r, uint32_t v)
314 {
315 #ifdef EN_DIAG
316         if (r > MID_MAXOFF || (r % 4))
317                 panic("en_write out of range, r=0x%x", r);
318 #endif
319         DBG(sc, REG, ("en_write(%#x) <- %08x", r, v));
320         bus_space_write_4(sc->en_memt, sc->en_base, r, v);
321 }
322
323 /*
324  * en_k2sz: convert KBytes to a size parameter (a log2)
325  */
326 static __inline int
327 en_k2sz(int k)
328 {
329         switch(k) {
330           case 1:   return (0);
331           case 2:   return (1);
332           case 4:   return (2);
333           case 8:   return (3);
334           case 16:  return (4);
335           case 32:  return (5);
336           case 64:  return (6);
337           case 128: return (7);
338           default:
339                 panic("en_k2sz");
340         }
341         return (0);
342 }
343 #define en_log2(X) en_k2sz(X)
344
345 /*
346  * en_b2sz: convert a DMA burst code to its byte size
347  */
348 static __inline int
349 en_b2sz(int b)
350 {
351         switch (b) {
352           case MIDDMA_WORD:   return (1*4);
353           case MIDDMA_2WMAYBE:
354           case MIDDMA_2WORD:  return (2*4);
355           case MIDDMA_4WMAYBE:
356           case MIDDMA_4WORD:  return (4*4);
357           case MIDDMA_8WMAYBE:
358           case MIDDMA_8WORD:  return (8*4);
359           case MIDDMA_16WMAYBE:
360           case MIDDMA_16WORD: return (16*4);
361           default:
362                 panic("en_b2sz");
363         }
364         return (0);
365 }
366
367 /*
368  * en_sz2b: convert a burst size (bytes) to DMA burst code
369  */
370 static __inline int
371 en_sz2b(int sz)
372 {
373         switch (sz) {
374           case 1*4:  return (MIDDMA_WORD);
375           case 2*4:  return (MIDDMA_2WORD);
376           case 4*4:  return (MIDDMA_4WORD);
377           case 8*4:  return (MIDDMA_8WORD);
378           case 16*4: return (MIDDMA_16WORD);
379           default:
380                 panic("en_sz2b");
381         }
382         return(0);
383 }
384
385 #ifdef EN_DEBUG
386 /*
387  * Dump a packet
388  */
389 static void
390 en_dump_packet(struct en_softc *sc, struct mbuf *m)
391 {
392         int plen = m->m_pkthdr.len;
393         u_int pos = 0;
394         u_int totlen = 0;
395         int len;
396         u_char *ptr;
397
398         device_printf(sc->dev, "packet len=%d", plen);
399         while (m != NULL) {
400                 totlen += m->m_len;
401                 ptr = mtod(m, u_char *);
402                 for (len = 0; len < m->m_len; len++, pos++, ptr++) {
403                         if (pos % 16 == 8)
404                                 printf(" ");
405                         if (pos % 16 == 0)
406                                 printf("\n");
407                         printf(" %02x", *ptr);
408                 }
409                 m = m->m_next;
410         }
411         printf("\n");
412         if (totlen != plen)
413                 printf("sum of m_len=%u\n", totlen);
414 }
415 #endif
416
417 /*********************************************************************/
418 /*
419  * DMA maps
420  */
421
422 /*
423  * Map constructor for a MAP.
424  *
425  * This is called each time when a map is allocated
426  * from the pool and about to be returned to the user. Here we actually
427  * allocate the map if there isn't one. The problem is that we may fail
428  * to allocate the DMA map yet have no means to signal this error. Therefor
429  * when allocating a map, the call must check that there is a map. An
430  * additional problem is, that i386 maps will be NULL, yet are ok and must
431  * be freed so let's use a flag to signal allocation.
432  *
433  * Caveat: we have no way to know that we are called from an interrupt context
434  * here. We rely on the fact, that bus_dmamap_create uses M_NOWAIT in all
435  * its allocations.
436  *
437  * LOCK: any, not needed
438  */
439 static int
440 en_map_ctor(void *mem, int size, void *arg, int flags)
441 {
442         struct en_softc *sc = arg;
443         struct en_map *map = mem;
444         int err;
445
446         err = bus_dmamap_create(sc->txtag, 0, &map->map);
447         if (err != 0) {
448                 device_printf(sc->dev, "cannot create DMA map %d\n", err);
449                 return (err);
450         }
451         map->flags = ENMAP_ALLOC;
452         map->sc = sc;
453         return (0);
454 }
455
456 /*
457  * Map destructor.
458  *
459  * Called when a map is disposed into the zone. If the map is loaded, unload
460  * it.
461  *
462  * LOCK: any, not needed
463  */
464 static void
465 en_map_dtor(void *mem, int size, void *arg)
466 {
467         struct en_map *map = mem;
468
469         if (map->flags & ENMAP_LOADED) {
470                 bus_dmamap_unload(map->sc->txtag, map->map);
471                 map->flags &= ~ENMAP_LOADED;
472         }
473 }
474
475 /*
476  * Map finializer.
477  *
478  * This is called each time a map is returned from the zone to the system.
479  * Get rid of the dmamap here.
480  *
481  * LOCK: any, not needed
482  */
483 static void
484 en_map_fini(void *mem, int size)
485 {
486         struct en_map *map = mem;
487
488         bus_dmamap_destroy(map->sc->txtag, map->map);
489 }
490
491 /*********************************************************************/
492 /*
493  * Transmission
494  */
495
496 /*
497  * Argument structure to load a transmit DMA map
498  */
499 struct txarg {
500         struct en_softc *sc;
501         struct mbuf *m;
502         u_int vci;
503         u_int chan;             /* transmit channel */
504         u_int datalen;          /* length of user data */
505         u_int flags;
506         u_int wait;             /* return: out of resources */
507 };
508
509 /*
510  * TX DMA map loader helper. This function is the callback when the map
511  * is loaded. It should fill the DMA segment descriptors into the hardware.
512  *
513  * LOCK: locked, needed
514  */
515 static void
516 en_txdma_load(void *uarg, bus_dma_segment_t *segs, int nseg, bus_size_t mapsize,
517     int error)
518 {
519         struct txarg *tx = uarg;
520         struct en_softc *sc = tx->sc;
521         struct en_txslot *slot = &sc->txslot[tx->chan];
522         uint32_t cur;           /* on-card buffer position (bytes offset) */
523         uint32_t dtq;           /* on-card queue position (byte offset) */
524         uint32_t last_dtq;      /* last DTQ we have written */
525         uint32_t tmp;
526         u_int free;             /* free queue entries on card */
527         u_int needalign, cnt;
528         bus_size_t rest;        /* remaining bytes in current segment */
529         bus_addr_t addr;
530         bus_dma_segment_t *s;
531         uint32_t count, bcode;
532         int i;
533
534         if (error != 0)
535                 return;
536
537         cur = slot->cur;
538         dtq = sc->dtq_us;
539         free = sc->dtq_free;
540
541         last_dtq = 0;           /* make gcc happy */
542
543         /*
544          * Local macro to add an entry to the transmit DMA area. If there
545          * are no entries left, return. Save the byte offset of the entry
546          * in last_dtq for later use.
547          */
548 #define PUT_DTQ_ENTRY(ENI, BCODE, COUNT, ADDR)                          \
549         if (free == 0) {                                                \
550                 EN_COUNT(sc->stats.txdtqout);                           \
551                 tx->wait = 1;                                           \
552                 return;                                                 \
553         }                                                               \
554         last_dtq = dtq;                                                 \
555         en_write(sc, dtq + 0, (ENI || !sc->is_adaptec) ?                \
556             MID_MK_TXQ_ENI(COUNT, tx->chan, 0, BCODE) :                 \
557             MID_MK_TXQ_ADP(COUNT, tx->chan, 0, BCODE));                 \
558         en_write(sc, dtq + 4, ADDR);                                    \
559                                                                         \
560         EN_WRAPADD(MID_DTQOFF, MID_DTQEND, dtq, 8);                     \
561         free--;
562
563         /*
564          * Local macro to generate a DMA entry to DMA cnt bytes. Updates
565          * the current buffer byte offset accordingly.
566          */
567 #define DO_DTQ(TYPE) do {                                               \
568         rest -= cnt;                                                    \
569         EN_WRAPADD(slot->start, slot->stop, cur, cnt);                  \
570         DBG(sc, TX, ("tx%d: "TYPE" %u bytes, %ju left, cur %#x",        \
571             tx->chan, cnt, (uintmax_t)rest, cur));                      \
572                                                                         \
573         PUT_DTQ_ENTRY(1, bcode, count, addr);                           \
574                                                                         \
575         addr += cnt;                                                    \
576     } while (0)
577
578         if (!(tx->flags & TX_HAS_TBD)) {
579                 /*
580                  * Prepend the TBD - it did not fit into the first mbuf
581                  */
582                 tmp = MID_TBD_MK1((tx->flags & TX_AAL5) ?
583                     MID_TBD_AAL5 : MID_TBD_NOAAL5,
584                     sc->vccs[tx->vci]->txspeed,
585                     tx->m->m_pkthdr.len / MID_ATMDATASZ);
586                 en_write(sc, cur, tmp);
587                 EN_WRAPADD(slot->start, slot->stop, cur, 4);
588
589                 tmp = MID_TBD_MK2(tx->vci, 0, 0);
590                 en_write(sc, cur, tmp);
591                 EN_WRAPADD(slot->start, slot->stop, cur, 4);
592
593                 /* update DMA address */
594                 PUT_DTQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
595         }
596
597         for (i = 0, s = segs; i < nseg; i++, s++) {
598                 rest = s->ds_len;
599                 addr = s->ds_addr;
600
601                 if (sc->is_adaptec) {
602                         /* adaptec card - simple */
603
604                         /* advance the on-card buffer pointer */
605                         EN_WRAPADD(slot->start, slot->stop, cur, rest);
606                         DBG(sc, TX, ("tx%d: adp %ju bytes %#jx (cur now 0x%x)",
607                             tx->chan, (uintmax_t)rest, (uintmax_t)addr, cur));
608
609                         PUT_DTQ_ENTRY(0, 0, rest, addr);
610
611                         continue;
612                 }
613
614                 /*
615                  * do we need to do a DMA op to align to the maximum
616                  * burst? Note, that we are alway 32-bit aligned.
617                  */
618                 if (sc->alburst &&
619                     (needalign = (addr & sc->bestburstmask)) != 0) {
620                         /* compute number of bytes, words and code */
621                         cnt = sc->bestburstlen - needalign;
622                         if (cnt > rest)
623                                 cnt = rest;
624                         count = cnt / sizeof(uint32_t);
625                         if (sc->noalbursts) {
626                                 bcode = MIDDMA_WORD;
627                         } else {
628                                 bcode = en_dmaplan[count].bcode;
629                                 count = cnt >> en_dmaplan[count].divshift;
630                         }
631                         DO_DTQ("al_dma");
632                 }
633
634                 /* do we need to do a max-sized burst? */
635                 if (rest >= sc->bestburstlen) {
636                         count = rest >> sc->bestburstshift;
637                         cnt = count << sc->bestburstshift;
638                         bcode = sc->bestburstcode;
639                         DO_DTQ("best_dma");
640                 }
641
642                 /* do we need to do a cleanup burst? */
643                 if (rest != 0) {
644                         cnt = rest;
645                         count = rest / sizeof(uint32_t);
646                         if (sc->noalbursts) {
647                                 bcode = MIDDMA_WORD;
648                         } else {
649                                 bcode = en_dmaplan[count].bcode;
650                                 count = cnt >> en_dmaplan[count].divshift;
651                         }
652                         DO_DTQ("clean_dma");
653                 }
654         }
655
656         KASSERT (tx->flags & TX_HAS_PAD, ("PDU not padded"));
657
658         if ((tx->flags & TX_AAL5) && !(tx->flags & TX_HAS_PDU)) {
659                 /*
660                  * Append the AAL5 PDU trailer
661                  */
662                 tmp = MID_PDU_MK1(0, 0, tx->datalen);
663                 en_write(sc, cur, tmp);
664                 EN_WRAPADD(slot->start, slot->stop, cur, 4);
665
666                 en_write(sc, cur, 0);
667                 EN_WRAPADD(slot->start, slot->stop, cur, 4);
668
669                 /* update DMA address */
670                 PUT_DTQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
671         }
672
673         /* record the end for the interrupt routine */
674         sc->dtq[MID_DTQ_A2REG(last_dtq)] =
675             EN_DQ_MK(tx->chan, tx->m->m_pkthdr.len);
676
677         /* set the end flag in the last descriptor */
678         en_write(sc, last_dtq + 0, SETQ_END(sc, en_read(sc, last_dtq + 0)));
679
680 #undef PUT_DTQ_ENTRY
681 #undef DO_DTQ
682
683         /* commit */
684         slot->cur = cur;
685         sc->dtq_free = free;
686         sc->dtq_us = dtq;
687
688         /* tell card */
689         en_write(sc, MID_DMA_WRTX, MID_DTQ_A2REG(sc->dtq_us));
690 }
691
692 /*
693  * en_txdma: start transmit DMA on the given channel, if possible
694  *
695  * This is called from two places: when we got new packets from the upper
696  * layer or when we found that buffer space has freed up during interrupt
697  * processing.
698  *
699  * LOCK: locked, needed
700  */
701 static void
702 en_txdma(struct en_softc *sc, struct en_txslot *slot)
703 {
704         struct en_map *map;
705         struct mbuf *lastm;
706         struct txarg tx;
707         u_int pad;
708         int error;
709
710         DBG(sc, TX, ("tx%td: starting ...", slot - sc->txslot));
711   again:
712         bzero(&tx, sizeof(tx));
713         tx.chan = slot - sc->txslot;
714         tx.sc = sc;
715
716         /*
717          * get an mbuf waiting for DMA
718          */
719         _IF_DEQUEUE(&slot->q, tx.m);
720         if (tx.m == NULL) {
721                 DBG(sc, TX, ("tx%td: ...done!", slot - sc->txslot));
722                 return;
723         }
724         MBUF_GET_TX(tx.m, tx.vci, tx.flags, tx.datalen, pad, map);
725
726         /*
727          * note: don't use the entire buffer space.  if WRTX becomes equal
728          * to RDTX, the transmitter stops assuming the buffer is empty!  --kjc
729          */
730         if (tx.m->m_pkthdr.len >= slot->bfree) {
731                 EN_COUNT(sc->stats.txoutspace);
732                 DBG(sc, TX, ("tx%td: out of transmit space", slot - sc->txslot));
733                 goto waitres;
734         }
735   
736         lastm = NULL;
737         if (!(tx.flags & TX_HAS_PAD)) {
738                 if (pad != 0) {
739                         /* Append the padding buffer */
740                         (void)m_length(tx.m, &lastm);
741                         lastm->m_next = sc->padbuf;
742                         sc->padbuf->m_len = pad;
743                 }
744                 tx.flags |= TX_HAS_PAD;
745         }
746
747         /*
748          * Try to load that map
749          */
750         error = bus_dmamap_load_mbuf(sc->txtag, map->map, tx.m,
751             en_txdma_load, &tx, BUS_DMA_NOWAIT);
752
753         if (lastm != NULL)
754                 lastm->m_next = NULL;
755
756         if (error != 0) {
757                 device_printf(sc->dev, "loading TX map failed %d\n",
758                     error);
759                 goto dequeue_drop;
760         }
761         map->flags |= ENMAP_LOADED;
762         if (tx.wait) {
763                 /* probably not enough space */
764                 bus_dmamap_unload(map->sc->txtag, map->map);
765                 map->flags &= ~ENMAP_LOADED;
766
767                 sc->need_dtqs = 1;
768                 DBG(sc, TX, ("tx%td: out of transmit DTQs", slot - sc->txslot));
769                 goto waitres;
770         }
771
772         EN_COUNT(sc->stats.launch);
773         sc->ifp->if_opackets++;
774
775         sc->vccs[tx.vci]->opackets++;
776         sc->vccs[tx.vci]->obytes += tx.datalen;
777
778 #ifdef ENABLE_BPF
779         if (sc->ifp->if_bpf != NULL) {
780                 /*
781                  * adjust the top of the mbuf to skip the TBD if present
782                  * before passing the packet to bpf.
783                  * Also remove padding and the PDU trailer. Assume both of
784                  * them to be in the same mbuf. pktlen, m_len and m_data
785                  * are not needed anymore so we can change them.
786                  */
787                 if (tx.flags & TX_HAS_TBD) {
788                         tx.m->m_data += MID_TBD_SIZE;
789                         tx.m->m_len -= MID_TBD_SIZE;
790                 }
791                 tx.m->m_pkthdr.len = m_length(tx.m, &lastm);
792                 if (tx.m->m_pkthdr.len > tx.datalen) {
793                         lastm->m_len -= tx.m->m_pkthdr.len - tx.datalen;
794                         tx.m->m_pkthdr.len = tx.datalen;
795                 }
796
797                 BPF_MTAP(sc->ifp, tx.m);
798         }
799 #endif
800
801         /*
802          * do some housekeeping and get the next packet
803          */
804         slot->bfree -= tx.m->m_pkthdr.len;
805         _IF_ENQUEUE(&slot->indma, tx.m);
806
807         goto again;
808
809         /*
810          * error handling. This is jumped to when we just want to drop
811          * the packet. Must be unlocked here.
812          */
813   dequeue_drop:
814         if (map != NULL)
815                 uma_zfree(sc->map_zone, map);
816
817         slot->mbsize -= tx.m->m_pkthdr.len;
818
819         m_freem(tx.m);
820
821         goto again;
822
823   waitres:
824         _IF_PREPEND(&slot->q, tx.m);
825 }
826
827 /*
828  * Create a copy of a single mbuf. It can have either internal or
829  * external data, it may have a packet header. External data is really
830  * copied, so the new buffer is writeable.
831  *
832  * LOCK: any, not needed
833  */
834 static struct mbuf *
835 copy_mbuf(struct mbuf *m)
836 {
837         struct mbuf *new;
838
839         MGET(new, M_TRYWAIT, MT_DATA);
840         if (new == NULL)
841                 return (NULL);
842
843         if (m->m_flags & M_PKTHDR) {
844                 M_MOVE_PKTHDR(new, m);
845                 if (m->m_len > MHLEN) {
846                         MCLGET(new, M_TRYWAIT);
847                         if ((m->m_flags & M_EXT) == 0) {
848                                 m_free(new);
849                                 return (NULL);
850                         }
851                 }
852         } else {
853                 if (m->m_len > MLEN) {
854                         MCLGET(new, M_TRYWAIT);
855                         if ((m->m_flags & M_EXT) == 0) {
856                                 m_free(new);
857                                 return (NULL);
858                         }
859                 }
860         }
861
862         bcopy(m->m_data, new->m_data, m->m_len);
863         new->m_len = m->m_len;
864         new->m_flags &= ~M_RDONLY;
865
866         return (new);
867 }
868
869 /*
870  * This function is called when we have an ENI adapter. It fixes the
871  * mbuf chain, so that all addresses and lengths are 4 byte aligned.
872  * The overall length is already padded to multiple of cells plus the
873  * TBD so this must always succeed. The routine can fail, when it
874  * needs to copy an mbuf (this may happen if an mbuf is readonly).
875  *
876  * We assume here, that aligning the virtual addresses to 4 bytes also
877  * aligns the physical addresses.
878  *
879  * LOCK: locked, needed
880  */
881 static struct mbuf *
882 en_fix_mchain(struct en_softc *sc, struct mbuf *m0, u_int *pad)
883 {
884         struct mbuf **prev = &m0;
885         struct mbuf *m = m0;
886         struct mbuf *new;
887         u_char *d;
888         int off;
889
890         while (m != NULL) {
891                 d = mtod(m, u_char *);
892                 if ((off = (uintptr_t)d % sizeof(uint32_t)) != 0) {
893                         EN_COUNT(sc->stats.mfixaddr);
894                         if (M_WRITABLE(m)) {
895                                 bcopy(d, d - off, m->m_len);
896                                 m->m_data -= off;
897                         } else {
898                                 if ((new = copy_mbuf(m)) == NULL) {
899                                         EN_COUNT(sc->stats.mfixfail);
900                                         m_freem(m0);
901                                         return (NULL);
902                                 }
903                                 new->m_next = m_free(m);
904                                 *prev = m = new;
905                         }
906                 }
907
908                 if ((off = m->m_len % sizeof(uint32_t)) != 0) {
909                         EN_COUNT(sc->stats.mfixlen);
910                         if (!M_WRITABLE(m)) {
911                                 if ((new = copy_mbuf(m)) == NULL) {
912                                         EN_COUNT(sc->stats.mfixfail);
913                                         m_freem(m0);
914                                         return (NULL);
915                                 }
916                                 new->m_next = m_free(m);
917                                 *prev = m = new;
918                         }
919                         d = mtod(m, u_char *) + m->m_len;
920                         off = 4 - off;
921                         while (off) {
922                                 while (m->m_next && m->m_next->m_len == 0)
923                                         m->m_next = m_free(m->m_next);
924
925                                 if (m->m_next == NULL) {
926                                         *d++ = 0;
927                                         KASSERT(*pad > 0, ("no padding space"));
928                                         (*pad)--;
929                                 } else {
930                                         *d++ = *mtod(m->m_next, u_char *);
931                                         m->m_next->m_len--;
932                                         m->m_next->m_data++;
933                                 }
934                                 m->m_len++;
935                                 off--;
936                         }
937                 }
938
939                 prev = &m->m_next;
940                 m = m->m_next;
941         }
942
943         return (m0);
944 }
945
946 /*
947  * en_start: start transmitting the next packet that needs to go out
948  * if there is one. We take off all packets from the interface's queue and
949  * put them into the channels queue.
950  *
951  * Here we also prepend the transmit packet descriptor and append the padding
952  * and (for aal5) the PDU trailer. This is different from the original driver:
953  * we assume, that allocating one or two additional mbufs is actually cheaper
954  * than all this algorithmic fiddling we would need otherwise.
955  *
956  * While the packet is on the channels wait queue we use the csum_* fields
957  * in the packet header to hold the original datalen, the AAL5 flag and the
958  * VCI. The packet length field in the header holds the needed buffer space.
959  * This may actually be more than the length of the current mbuf chain (when
960  * one or more of TBD, padding and PDU do not fit).
961  *
962  * LOCK: unlocked, needed
963  */
964 static void
965 en_start(struct ifnet *ifp)
966 {
967         struct en_softc *sc = (struct en_softc *)ifp->if_softc;
968         struct mbuf *m, *lastm;
969         struct atm_pseudohdr *ap;
970         u_int pad;              /* 0-bytes to pad at PDU end */
971         u_int datalen;          /* length of user data */
972         u_int vci;              /* the VCI we are transmitting on */
973         u_int flags;
974         uint32_t tbd[2];
975         uint32_t pdu[2];
976         struct en_vcc *vc;
977         struct en_map *map;
978         struct en_txslot *tx;
979
980         while (1) {
981                 IF_DEQUEUE(&ifp->if_snd, m);
982                 if (m == NULL)
983                         return;
984
985                 flags = 0;
986
987                 ap = mtod(m, struct atm_pseudohdr *);
988                 vci = ATM_PH_VCI(ap);
989
990                 if (ATM_PH_VPI(ap) != 0 || vci >= MID_N_VC ||
991                     (vc = sc->vccs[vci]) == NULL ||
992                     (vc->vflags & VCC_CLOSE_RX)) {
993                         DBG(sc, TX, ("output vpi=%u, vci=%u -- drop",
994                             ATM_PH_VPI(ap), vci));
995                         m_freem(m);
996                         continue;
997                 }
998                 if (vc->vcc.aal == ATMIO_AAL_5)
999                         flags |= TX_AAL5;
1000                 m_adj(m, sizeof(struct atm_pseudohdr));
1001
1002                 /*
1003                  * (re-)calculate size of packet (in bytes)
1004                  */
1005                 m->m_pkthdr.len = datalen = m_length(m, &lastm);
1006
1007                 /*
1008                  * computing how much padding we need on the end of the mbuf,
1009                  * then see if we can put the TBD at the front of the mbuf
1010                  * where the link header goes (well behaved protocols will
1011                  * reserve room for us). Last, check if room for PDU tail.
1012                  */
1013                 if (flags & TX_AAL5)
1014                         m->m_pkthdr.len += MID_PDU_SIZE;
1015                 m->m_pkthdr.len = roundup(m->m_pkthdr.len, MID_ATMDATASZ);
1016                 pad = m->m_pkthdr.len - datalen;
1017                 if (flags & TX_AAL5)
1018                         pad -= MID_PDU_SIZE;
1019                 m->m_pkthdr.len += MID_TBD_SIZE;
1020
1021                 DBG(sc, TX, ("txvci%d: buflen=%u datalen=%u lead=%d trail=%d",
1022                     vci, m->m_pkthdr.len, datalen, (int)M_LEADINGSPACE(m),
1023                     (int)M_TRAILINGSPACE(lastm)));
1024
1025                 /*
1026                  * From here on we need access to sc
1027                  */
1028                 EN_LOCK(sc);
1029
1030                 /*
1031                  * Allocate a map. We do this here rather then in en_txdma,
1032                  * because en_txdma is also called from the interrupt handler
1033                  * and we are going to have a locking problem then. We must
1034                  * use NOWAIT here, because the ip_output path holds various
1035                  * locks.
1036                  */
1037                 map = uma_zalloc_arg(sc->map_zone, sc, M_NOWAIT);
1038                 if (map == NULL) {
1039                         /* drop that packet */
1040                         EN_COUNT(sc->stats.txnomap);
1041                         EN_UNLOCK(sc);
1042                         m_freem(m);
1043                         continue;
1044                 }
1045
1046                 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1047                         EN_UNLOCK(sc);
1048                         uma_zfree(sc->map_zone, map);
1049                         m_freem(m);
1050                         continue;
1051                 }
1052
1053                 /*
1054                  * Look, whether we can prepend the TBD (8 byte)
1055                  */
1056                 if (M_WRITABLE(m) && M_LEADINGSPACE(m) >= MID_TBD_SIZE) {
1057                         tbd[0] = htobe32(MID_TBD_MK1((flags & TX_AAL5) ?
1058                             MID_TBD_AAL5 : MID_TBD_NOAAL5,
1059                             vc->txspeed, m->m_pkthdr.len / MID_ATMDATASZ));
1060                         tbd[1] = htobe32(MID_TBD_MK2(vci, 0, 0));
1061
1062                         m->m_data -= MID_TBD_SIZE;
1063                         bcopy(tbd, m->m_data, MID_TBD_SIZE);
1064                         m->m_len += MID_TBD_SIZE;
1065                         flags |= TX_HAS_TBD;
1066                 }
1067
1068                 /*
1069                  * Check whether the padding fits (must be writeable -
1070                  * we pad with zero).
1071                  */
1072                 if (M_WRITABLE(lastm) && M_TRAILINGSPACE(lastm) >= pad) {
1073                         bzero(lastm->m_data + lastm->m_len, pad);
1074                         lastm->m_len += pad;
1075                         flags |= TX_HAS_PAD;
1076
1077                         if ((flags & TX_AAL5) &&
1078                             M_TRAILINGSPACE(lastm) > MID_PDU_SIZE) {
1079                                 pdu[0] = htobe32(MID_PDU_MK1(0, 0, datalen));
1080                                 pdu[1] = 0;
1081                                 bcopy(pdu, lastm->m_data + lastm->m_len,
1082                                     MID_PDU_SIZE);
1083                                 lastm->m_len += MID_PDU_SIZE;
1084                                 flags |= TX_HAS_PDU;
1085                         }
1086                 }
1087
1088                 if (!sc->is_adaptec &&
1089                     (m = en_fix_mchain(sc, m, &pad)) == NULL) {
1090                         EN_UNLOCK(sc);
1091                         uma_zfree(sc->map_zone, map);
1092                         continue;
1093                 }
1094
1095                 /*
1096                  * get assigned channel (will be zero unless txspeed is set)
1097                  */
1098                 tx = vc->txslot;
1099
1100                 if (m->m_pkthdr.len > EN_TXSZ * 1024) {
1101                         DBG(sc, TX, ("tx%td: packet larger than xmit buffer "
1102                             "(%d > %d)\n", tx - sc->txslot, m->m_pkthdr.len,
1103                             EN_TXSZ * 1024));
1104                         EN_UNLOCK(sc);
1105                         m_freem(m);
1106                         uma_zfree(sc->map_zone, map);
1107                         continue;
1108                 }
1109
1110                 if (tx->mbsize > EN_TXHIWAT) {
1111                         EN_COUNT(sc->stats.txmbovr);
1112                         DBG(sc, TX, ("tx%td: buffer space shortage",
1113                             tx - sc->txslot));
1114                         EN_UNLOCK(sc);
1115                         m_freem(m);
1116                         uma_zfree(sc->map_zone, map);
1117                         continue;
1118                 }
1119
1120                 /* commit */
1121                 tx->mbsize += m->m_pkthdr.len;
1122
1123                 DBG(sc, TX, ("tx%td: VCI=%d, speed=0x%x, buflen=%d, mbsize=%d",
1124                     tx - sc->txslot, vci, sc->vccs[vci]->txspeed,
1125                     m->m_pkthdr.len, tx->mbsize));
1126
1127                 MBUF_SET_TX(m, vci, flags, datalen, pad, map);
1128
1129                 _IF_ENQUEUE(&tx->q, m);
1130
1131                 en_txdma(sc, tx);
1132
1133                 EN_UNLOCK(sc);
1134         }
1135 }
1136
1137 /*********************************************************************/
1138 /*
1139  * VCs
1140  */
1141
1142 /*
1143  * en_loadvc: load a vc tab entry from a slot
1144  *
1145  * LOCK: locked, needed
1146  */
1147 static void
1148 en_loadvc(struct en_softc *sc, struct en_vcc *vc)
1149 {
1150         uint32_t reg = en_read(sc, MID_VC(vc->vcc.vci));
1151
1152         reg = MIDV_SETMODE(reg, MIDV_TRASH);
1153         en_write(sc, MID_VC(vc->vcc.vci), reg);
1154         DELAY(27);
1155
1156         /* no need to set CRC */
1157
1158         /* read pointer = 0, desc. start = 0 */
1159         en_write(sc, MID_DST_RP(vc->vcc.vci), 0);
1160         /* write pointer = 0 */
1161         en_write(sc, MID_WP_ST_CNT(vc->vcc.vci), 0);
1162         /* set mode, size, loc */
1163         en_write(sc, MID_VC(vc->vcc.vci), vc->rxslot->mode);
1164
1165         vc->rxslot->cur = vc->rxslot->start;
1166
1167         DBG(sc, VC, ("rx%td: assigned to VCI %d", vc->rxslot - sc->rxslot,
1168             vc->vcc.vci));
1169 }
1170
1171 /*
1172  * Open the given vcc.
1173  *
1174  * LOCK: unlocked, needed
1175  */
1176 static int
1177 en_open_vcc(struct en_softc *sc, struct atmio_openvcc *op)
1178 {
1179         uint32_t oldmode, newmode;
1180         struct en_rxslot *slot;
1181         struct en_vcc *vc;
1182         int error = 0;
1183
1184         DBG(sc, IOCTL, ("enable vpi=%d, vci=%d, flags=%#x",
1185             op->param.vpi, op->param.vci, op->param.flags));
1186
1187         if (op->param.vpi != 0 || op->param.vci >= MID_N_VC)
1188                 return (EINVAL);
1189
1190         vc = uma_zalloc(en_vcc_zone, M_NOWAIT | M_ZERO);
1191         if (vc == NULL)
1192                 return (ENOMEM);
1193
1194         EN_LOCK(sc);
1195
1196         if (sc->vccs[op->param.vci] != NULL) {
1197                 error = EBUSY;
1198                 goto done;
1199         }
1200
1201         /* find a free receive slot */
1202         for (slot = sc->rxslot; slot < &sc->rxslot[sc->en_nrx]; slot++)
1203                 if (slot->vcc == NULL)
1204                         break;
1205         if (slot == &sc->rxslot[sc->en_nrx]) {
1206                 error = ENOSPC;
1207                 goto done;
1208         }
1209
1210         vc->rxslot = slot;
1211         vc->rxhand = op->rxhand;
1212         vc->vcc = op->param;
1213
1214         oldmode = slot->mode;
1215         newmode = (op->param.aal == ATMIO_AAL_5) ? MIDV_AAL5 : MIDV_NOAAL;
1216         slot->mode = MIDV_SETMODE(oldmode, newmode);
1217         slot->vcc = vc;
1218
1219         KASSERT (_IF_QLEN(&slot->indma) == 0 && _IF_QLEN(&slot->q) == 0,
1220             ("en_rxctl: left over mbufs on enable slot=%td",
1221             vc->rxslot - sc->rxslot));
1222
1223         vc->txspeed = 0;
1224         vc->txslot = sc->txslot;
1225         vc->txslot->nref++;     /* bump reference count */
1226
1227         en_loadvc(sc, vc);      /* does debug printf for us */
1228
1229         /* don't free below */
1230         sc->vccs[vc->vcc.vci] = vc;
1231         vc = NULL;
1232         sc->vccs_open++;
1233
1234   done:
1235         if (vc != NULL)
1236                 uma_zfree(en_vcc_zone, vc);
1237
1238         EN_UNLOCK(sc);
1239         return (error);
1240 }
1241
1242 /*
1243  * Close finished
1244  */
1245 static void
1246 en_close_finish(struct en_softc *sc, struct en_vcc *vc)
1247 {
1248
1249         if (vc->rxslot != NULL)
1250                 vc->rxslot->vcc = NULL;
1251
1252         DBG(sc, VC, ("vci: %u free (%p)", vc->vcc.vci, vc));
1253
1254         sc->vccs[vc->vcc.vci] = NULL;
1255         uma_zfree(en_vcc_zone, vc);
1256         sc->vccs_open--;
1257 }
1258
1259 /*
1260  * LOCK: unlocked, needed
1261  */
1262 static int
1263 en_close_vcc(struct en_softc *sc, struct atmio_closevcc *cl)
1264 {
1265         uint32_t oldmode, newmode;
1266         struct en_vcc *vc;
1267         int error = 0;
1268
1269         DBG(sc, IOCTL, ("disable vpi=%d, vci=%d", cl->vpi, cl->vci));
1270
1271         if (cl->vpi != 0 || cl->vci >= MID_N_VC)
1272                 return (EINVAL);
1273
1274         EN_LOCK(sc);
1275         if ((vc = sc->vccs[cl->vci]) == NULL) {
1276                 error = ENOTCONN;
1277                 goto done;
1278         }
1279
1280         /*
1281          * turn off VCI
1282          */
1283         if (vc->rxslot == NULL) {
1284                 error = ENOTCONN;
1285                 goto done;
1286         }
1287         if (vc->vflags & VCC_DRAIN) {
1288                 error = EINVAL;
1289                 goto done;
1290         }
1291
1292         oldmode = en_read(sc, MID_VC(cl->vci));
1293         newmode = MIDV_SETMODE(oldmode, MIDV_TRASH) & ~MIDV_INSERVICE;
1294         en_write(sc, MID_VC(cl->vci), (newmode | (oldmode & MIDV_INSERVICE)));
1295
1296         /* halt in tracks, be careful to preserve inservice bit */
1297         DELAY(27);
1298         vc->rxslot->mode = newmode;
1299
1300         vc->txslot->nref--;
1301
1302         /* if stuff is still going on we are going to have to drain it out */
1303         if (_IF_QLEN(&vc->rxslot->indma) == 0 &&
1304             _IF_QLEN(&vc->rxslot->q) == 0 &&
1305             (vc->vflags & VCC_SWSL) == 0) {
1306                 en_close_finish(sc, vc);
1307                 goto done;
1308         }
1309
1310         vc->vflags |= VCC_DRAIN;
1311         DBG(sc, IOCTL, ("VCI %u now draining", cl->vci));
1312
1313         if (vc->vcc.flags & ATMIO_FLAG_ASYNC)
1314                 goto done;
1315
1316         vc->vflags |= VCC_CLOSE_RX;
1317         while ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) &&
1318             (vc->vflags & VCC_DRAIN))
1319                 cv_wait(&sc->cv_close, &sc->en_mtx);
1320
1321         en_close_finish(sc, vc);
1322         if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1323                 error = EIO;
1324                 goto done;
1325         }
1326
1327
1328   done:
1329         EN_UNLOCK(sc);
1330         return (error);
1331 }
1332
1333 /*********************************************************************/
1334 /*
1335  * starting/stopping the card
1336  */
1337
1338 /*
1339  * en_reset_ul: reset the board, throw away work in progress.
1340  * must en_init to recover.
1341  *
1342  * LOCK: locked, needed
1343  */
1344 static void
1345 en_reset_ul(struct en_softc *sc)
1346 {
1347         struct en_map *map;
1348         struct mbuf *m;
1349         struct en_rxslot *rx;
1350         int lcv;
1351
1352         device_printf(sc->dev, "reset\n");
1353         sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1354
1355         if (sc->en_busreset)
1356                 sc->en_busreset(sc);
1357         en_write(sc, MID_RESID, 0x0);   /* reset hardware */
1358
1359         /*
1360          * recv: dump any mbufs we are dma'ing into, if DRAINing, then a reset
1361          * will free us! Don't release the rxslot from the channel.
1362          */
1363         for (lcv = 0 ; lcv < MID_N_VC ; lcv++) {
1364                 if (sc->vccs[lcv] == NULL)
1365                         continue;
1366                 rx = sc->vccs[lcv]->rxslot;
1367
1368                 for (;;) {
1369                         _IF_DEQUEUE(&rx->indma, m);
1370                         if (m == NULL)
1371                                 break;
1372                         map = (void *)m->m_pkthdr.rcvif;
1373                         uma_zfree(sc->map_zone, map);
1374                         m_freem(m);
1375                 }
1376                 for (;;) {
1377                         _IF_DEQUEUE(&rx->q, m);
1378                         if (m == NULL)
1379                                 break;
1380                         m_freem(m);
1381                 }
1382                 sc->vccs[lcv]->vflags = 0;
1383         }
1384
1385         /*
1386          * xmit: dump everything
1387          */
1388         for (lcv = 0 ; lcv < EN_NTX ; lcv++) {
1389                 for (;;) {
1390                         _IF_DEQUEUE(&sc->txslot[lcv].indma, m);
1391                         if (m == NULL)
1392                                 break;
1393                         map = (void *)m->m_pkthdr.rcvif;
1394                         uma_zfree(sc->map_zone, map);
1395                         m_freem(m);
1396                 }
1397                 for (;;) {
1398                         _IF_DEQUEUE(&sc->txslot[lcv].q, m);
1399                         if (m == NULL)
1400                                 break;
1401                         map = (void *)m->m_pkthdr.rcvif;
1402                         uma_zfree(sc->map_zone, map);
1403                         m_freem(m);
1404                 }
1405                 sc->txslot[lcv].mbsize = 0;
1406         }
1407
1408         /*
1409          * Unstop all waiters
1410          */
1411         cv_broadcast(&sc->cv_close);
1412 }
1413
1414 /*
1415  * en_reset: reset the board, throw away work in progress.
1416  * must en_init to recover.
1417  *
1418  * LOCK: unlocked, needed
1419  *
1420  * Use en_reset_ul if you alreay have the lock
1421  */
1422 void
1423 en_reset(struct en_softc *sc)
1424 {
1425         EN_LOCK(sc);
1426         en_reset_ul(sc);
1427         EN_UNLOCK(sc);
1428 }
1429
1430
1431 /*
1432  * en_init: init board and sync the card with the data in the softc.
1433  *
1434  * LOCK: locked, needed
1435  */
1436 static void
1437 en_init(struct en_softc *sc)
1438 {
1439         int vc, slot;
1440         uint32_t loc;
1441
1442         if ((sc->ifp->if_flags & IFF_UP) == 0) {
1443                 DBG(sc, INIT, ("going down"));
1444                 en_reset(sc);                           /* to be safe */
1445                 return;
1446         }
1447
1448         DBG(sc, INIT, ("going up"));
1449         sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;       /* enable */
1450
1451         if (sc->en_busreset)
1452                 sc->en_busreset(sc);
1453         en_write(sc, MID_RESID, 0x0);           /* reset */
1454
1455         /* zero memory */
1456         bus_space_set_region_4(sc->en_memt, sc->en_base,
1457             MID_RAMOFF, 0, sc->en_obmemsz / 4);
1458
1459         /*
1460          * init obmem data structures: vc tab, dma q's, slist.
1461          *
1462          * note that we set drq_free/dtq_free to one less than the total number
1463          * of DTQ/DRQs present.   we do this because the card uses the condition
1464          * (drq_chip == drq_us) to mean "list is empty"... but if you allow the
1465          * circular list to be completely full then (drq_chip == drq_us) [i.e.
1466          * the drq_us pointer will wrap all the way around].   by restricting
1467          * the number of active requests to (N - 1) we prevent the list from
1468          * becoming completely full.    note that the card will sometimes give
1469          * us an interrupt for a DTQ/DRQ we have already processes... this helps
1470          * keep that interrupt from messing us up.
1471          */
1472         bzero(&sc->drq, sizeof(sc->drq));
1473         sc->drq_free = MID_DRQ_N - 1;
1474         sc->drq_chip = MID_DRQ_REG2A(en_read(sc, MID_DMA_RDRX));
1475         en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_chip)); 
1476         sc->drq_us = sc->drq_chip;
1477
1478         bzero(&sc->dtq, sizeof(sc->dtq));
1479         sc->dtq_free = MID_DTQ_N - 1;
1480         sc->dtq_chip = MID_DTQ_REG2A(en_read(sc, MID_DMA_RDTX));
1481         en_write(sc, MID_DMA_WRTX, MID_DRQ_A2REG(sc->dtq_chip)); 
1482         sc->dtq_us = sc->dtq_chip;
1483
1484         sc->hwslistp = MID_SL_REG2A(en_read(sc, MID_SERV_WRITE));
1485         sc->swsl_size = sc->swsl_head = sc->swsl_tail = 0;
1486
1487         DBG(sc, INIT, ("drq free/chip: %d/0x%x, dtq free/chip: %d/0x%x, "
1488             "hwslist: 0x%x", sc->drq_free, sc->drq_chip, sc->dtq_free,
1489             sc->dtq_chip, sc->hwslistp));
1490
1491         for (slot = 0 ; slot < EN_NTX ; slot++) {
1492                 sc->txslot[slot].bfree = EN_TXSZ * 1024;
1493                 en_write(sc, MIDX_READPTR(slot), 0);
1494                 en_write(sc, MIDX_DESCSTART(slot), 0);
1495                 loc = sc->txslot[slot].cur = sc->txslot[slot].start;
1496                 loc = loc - MID_RAMOFF;
1497                 /* mask, cvt to words */
1498                 loc = (loc & ~((EN_TXSZ * 1024) - 1)) >> 2;
1499                 /* top 11 bits */
1500                 loc = loc >> MIDV_LOCTOPSHFT;
1501                 en_write(sc, MIDX_PLACE(slot), MIDX_MKPLACE(en_k2sz(EN_TXSZ),
1502                     loc));
1503                 DBG(sc, INIT, ("tx%d: place 0x%x", slot,
1504                     (u_int)en_read(sc, MIDX_PLACE(slot))));
1505         }
1506
1507         for (vc = 0; vc < MID_N_VC; vc++) 
1508                 if (sc->vccs[vc] != NULL)
1509                         en_loadvc(sc, sc->vccs[vc]);
1510
1511         /*
1512          * enable!
1513          */
1514         en_write(sc, MID_INTENA, MID_INT_TX | MID_INT_DMA_OVR | MID_INT_IDENT |
1515             MID_INT_LERR | MID_INT_DMA_ERR | MID_INT_DMA_RX | MID_INT_DMA_TX |
1516             MID_INT_SERVICE | MID_INT_SUNI | MID_INT_STATS);
1517         en_write(sc, MID_MAST_CSR, MID_SETIPL(sc->ipl) | MID_MCSR_ENDMA |
1518             MID_MCSR_ENTX | MID_MCSR_ENRX);
1519 }
1520
1521 /*********************************************************************/
1522 /*
1523  * Ioctls
1524  */
1525 /*
1526  * en_ioctl: handle ioctl requests
1527  *
1528  * NOTE: if you add an ioctl to set txspeed, you should choose a new
1529  * TX channel/slot.   Choose the one with the lowest sc->txslot[slot].nref
1530  * value, subtract one from sc->txslot[0].nref, add one to the
1531  * sc->txslot[slot].nref, set sc->txvc2slot[vci] = slot, and then set
1532  * txspeed[vci].
1533  *
1534  * LOCK: unlocked, needed
1535  */
1536 static int
1537 en_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1538 {
1539         struct en_softc *sc = (struct en_softc *)ifp->if_softc;
1540         struct ifaddr *ifa = (struct ifaddr *)data;
1541         struct ifreq *ifr = (struct ifreq *)data;
1542         struct atmio_vcctable *vtab;
1543         int error = 0;
1544
1545         switch (cmd) {
1546
1547           case SIOCSIFADDR: 
1548                 EN_LOCK(sc);
1549                 ifp->if_flags |= IFF_UP;
1550 #if defined(INET) || defined(INET6)
1551                 if (ifa->ifa_addr->sa_family == AF_INET
1552                     || ifa->ifa_addr->sa_family == AF_INET6) {
1553                         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1554                                 en_reset_ul(sc);
1555                                 en_init(sc);
1556                         }
1557                         ifa->ifa_rtrequest = atm_rtrequest; /* ??? */
1558                         EN_UNLOCK(sc);
1559                         break;
1560                 }
1561 #endif /* INET */
1562                 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1563                         en_reset_ul(sc);
1564                         en_init(sc);
1565                 }
1566                 EN_UNLOCK(sc);
1567                 break;
1568
1569         case SIOCSIFFLAGS: 
1570                 EN_LOCK(sc);
1571                 if (ifp->if_flags & IFF_UP) {
1572                         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
1573                                 en_init(sc);
1574                 } else {
1575                         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1576                                 en_reset_ul(sc);
1577                 }
1578                 EN_UNLOCK(sc);
1579                 break;
1580
1581           case SIOCSIFMTU:
1582                 /*
1583                  * Set the interface MTU.
1584                  */
1585                 if (ifr->ifr_mtu > ATMMTU) {
1586                         error = EINVAL;
1587                         break;
1588                 }
1589                 ifp->if_mtu = ifr->ifr_mtu;
1590                 break;
1591
1592           case SIOCSIFMEDIA:
1593           case SIOCGIFMEDIA:
1594                 error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);
1595                 break;
1596
1597           case SIOCATMOPENVCC:          /* kernel internal use */
1598                 error = en_open_vcc(sc, (struct atmio_openvcc *)data);
1599                 break;
1600
1601           case SIOCATMCLOSEVCC:         /* kernel internal use */
1602                 error = en_close_vcc(sc, (struct atmio_closevcc *)data);
1603                 break;
1604
1605           case SIOCATMGETVCCS:  /* internal netgraph use */
1606                 vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
1607                     MID_N_VC, sc->vccs_open, &sc->en_mtx, 0);
1608                 if (vtab == NULL) {
1609                         error = ENOMEM;
1610                         break;
1611                 }
1612                 *(void **)data = vtab;
1613                 break;
1614
1615           case SIOCATMGVCCS:    /* return vcc table */
1616                 vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
1617                     MID_N_VC, sc->vccs_open, &sc->en_mtx, 1);
1618                 error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) +
1619                     vtab->count * sizeof(vtab->vccs[0]));
1620                 free(vtab, M_DEVBUF);
1621                 break;
1622
1623           default: 
1624                 error = EINVAL;
1625                 break;
1626         }
1627         return (error);
1628 }
1629
1630 /*********************************************************************/
1631 /*
1632  * Sysctl's
1633  */
1634
1635 /*
1636  * Sysctl handler for internal statistics
1637  *
1638  * LOCK: unlocked, needed
1639  */
1640 static int
1641 en_sysctl_istats(SYSCTL_HANDLER_ARGS)
1642 {
1643         struct en_softc *sc = arg1;
1644         uint32_t *ret;
1645         int error;
1646
1647         ret = malloc(sizeof(sc->stats), M_TEMP, M_WAITOK);
1648
1649         EN_LOCK(sc);
1650         bcopy(&sc->stats, ret, sizeof(sc->stats));
1651         EN_UNLOCK(sc);
1652
1653         error = SYSCTL_OUT(req, ret, sizeof(sc->stats));
1654         free(ret, M_TEMP);
1655
1656         return (error);
1657 }
1658
1659 /*********************************************************************/
1660 /*
1661  * Interrupts
1662  */
1663
1664 /*
1665  * Transmit interrupt handler
1666  *
1667  * check for tx complete, if detected then this means that some space
1668  * has come free on the card.   we must account for it and arrange to
1669  * kick the channel to life (in case it is stalled waiting on the card).
1670  *
1671  * LOCK: locked, needed
1672  */
1673 static uint32_t
1674 en_intr_tx(struct en_softc *sc, uint32_t reg)
1675 {
1676         uint32_t kick;
1677         uint32_t mask;
1678         uint32_t val;
1679         int chan;
1680
1681         kick = 0;               /* bitmask of channels to kick */
1682
1683         for (mask = 1, chan = 0; chan < EN_NTX; chan++, mask *= 2) {
1684                 if (!(reg & MID_TXCHAN(chan)))
1685                         continue;
1686
1687                 kick = kick | mask;
1688
1689                 /* current read pointer */
1690                 val = en_read(sc, MIDX_READPTR(chan));
1691                 /* as offset */
1692                 val = (val * sizeof(uint32_t)) + sc->txslot[chan].start;
1693                 if (val > sc->txslot[chan].cur)
1694                         sc->txslot[chan].bfree = val - sc->txslot[chan].cur;
1695                 else
1696                         sc->txslot[chan].bfree = (val + (EN_TXSZ * 1024)) -
1697                             sc->txslot[chan].cur;
1698                 DBG(sc, INTR, ("tx%d: transmit done. %d bytes now free in "
1699                     "buffer", chan, sc->txslot[chan].bfree));
1700         }
1701         return (kick);
1702 }
1703
1704 /*
1705  * TX DMA interrupt
1706  *
1707  * check for TX DMA complete, if detected then this means
1708  * that some DTQs are now free.   it also means some indma
1709  * mbufs can be freed. if we needed DTQs, kick all channels.
1710  *
1711  * LOCK: locked, needed
1712  */
1713 static uint32_t
1714 en_intr_tx_dma(struct en_softc *sc)
1715 {
1716         uint32_t kick = 0;
1717         uint32_t val;
1718         uint32_t idx;
1719         uint32_t slot;
1720         uint32_t dtq;
1721         struct en_map *map;
1722         struct mbuf *m;
1723
1724         val = en_read(sc, MID_DMA_RDTX);        /* chip's current location */
1725         idx = MID_DTQ_A2REG(sc->dtq_chip);      /* where we last saw chip */
1726
1727         if (sc->need_dtqs) {
1728                 kick = MID_NTX_CH - 1;  /* assume power of 2, kick all! */
1729                 sc->need_dtqs = 0;      /* recalculated in "kick" loop below */
1730                 DBG(sc, INTR, ("cleared need DTQ condition"));
1731         }
1732
1733         while (idx != val) {
1734                 sc->dtq_free++;
1735                 if ((dtq = sc->dtq[idx]) != 0) {
1736                         /* don't forget to zero it out when done */
1737                         sc->dtq[idx] = 0;
1738                         slot = EN_DQ_SLOT(dtq);
1739
1740                         _IF_DEQUEUE(&sc->txslot[slot].indma, m);
1741                         if (m == NULL)
1742                                 panic("enintr: dtqsync");
1743                         map = (void *)m->m_pkthdr.rcvif;
1744                         uma_zfree(sc->map_zone, map);
1745                         m_freem(m);
1746
1747                         sc->txslot[slot].mbsize -= EN_DQ_LEN(dtq);
1748                         DBG(sc, INTR, ("tx%d: free %d dma bytes, mbsize now "
1749                             "%d", slot, EN_DQ_LEN(dtq), 
1750                             sc->txslot[slot].mbsize));
1751                 }
1752                 EN_WRAPADD(0, MID_DTQ_N, idx, 1);
1753         }
1754         sc->dtq_chip = MID_DTQ_REG2A(val);      /* sync softc */
1755
1756         return (kick);
1757 }
1758
1759 /*
1760  * Service interrupt
1761  *
1762  * LOCK: locked, needed
1763  */
1764 static int
1765 en_intr_service(struct en_softc *sc)
1766 {
1767         uint32_t chip;
1768         uint32_t vci;
1769         int need_softserv = 0;
1770         struct en_vcc *vc;
1771
1772         chip = MID_SL_REG2A(en_read(sc, MID_SERV_WRITE));
1773
1774         while (sc->hwslistp != chip) {
1775                 /* fetch and remove it from hardware service list */
1776                 vci = en_read(sc, sc->hwslistp);
1777                 EN_WRAPADD(MID_SLOFF, MID_SLEND, sc->hwslistp, 4);
1778
1779                 if ((vc = sc->vccs[vci]) == NULL ||
1780                     (vc->vcc.flags & ATMIO_FLAG_NORX)) {
1781                         DBG(sc, INTR, ("unexpected rx interrupt VCI %d", vci));
1782                         en_write(sc, MID_VC(vci), MIDV_TRASH);  /* rx off */
1783                         continue;
1784                 }
1785
1786                 /* remove from hwsl */
1787                 en_write(sc, MID_VC(vci), vc->rxslot->mode);
1788                 EN_COUNT(sc->stats.hwpull);
1789
1790                 DBG(sc, INTR, ("pulled VCI %d off hwslist", vci));
1791
1792                 /* add it to the software service list (if needed) */
1793                 if ((vc->vflags & VCC_SWSL) == 0) {
1794                         EN_COUNT(sc->stats.swadd);
1795                         need_softserv = 1;
1796                         vc->vflags |= VCC_SWSL;
1797                         sc->swslist[sc->swsl_tail] = vci;
1798                         EN_WRAPADD(0, MID_SL_N, sc->swsl_tail, 1);
1799                         sc->swsl_size++;
1800                         DBG(sc, INTR, ("added VCI %d to swslist", vci));
1801                 }
1802         }
1803         return (need_softserv);
1804 }
1805
1806 /*
1807  * Handle a receive DMA completion
1808  */
1809 static void
1810 en_rx_drain(struct en_softc *sc, u_int drq)
1811 {
1812         struct en_rxslot *slot;
1813         struct en_vcc *vc;
1814         struct mbuf *m;
1815         struct atm_pseudohdr ah;
1816
1817         slot = &sc->rxslot[EN_DQ_SLOT(drq)];
1818
1819         m = NULL;       /* assume "JK" trash DMA */
1820         if (EN_DQ_LEN(drq) != 0) {
1821                 _IF_DEQUEUE(&slot->indma, m);
1822                 KASSERT(m != NULL, ("drqsync: %s: lost mbuf in slot %td!",
1823                     sc->ifp->if_xname, slot - sc->rxslot));
1824                 uma_zfree(sc->map_zone, (struct en_map *)m->m_pkthdr.rcvif);
1825         }
1826         if ((vc = slot->vcc) == NULL) {
1827                 /* ups */
1828                 if (m != NULL)
1829                         m_freem(m);
1830                 return;
1831         }
1832
1833         /* do something with this mbuf */
1834         if (vc->vflags & VCC_DRAIN) {
1835                 /* drain? */
1836                 if (m != NULL)
1837                         m_freem(m);
1838                 if (_IF_QLEN(&slot->indma) == 0 && _IF_QLEN(&slot->q) == 0 &&
1839                     (en_read(sc, MID_VC(vc->vcc.vci)) & MIDV_INSERVICE) == 0 &&
1840                     (vc->vflags & VCC_SWSL) == 0) {
1841                         vc->vflags &= ~VCC_CLOSE_RX;
1842                         if (vc->vcc.flags & ATMIO_FLAG_ASYNC)
1843                                 en_close_finish(sc, vc);
1844                         else
1845                                 cv_signal(&sc->cv_close);
1846                 }
1847                 return;
1848         }
1849
1850         if (m != NULL) {
1851                 ATM_PH_FLAGS(&ah) = vc->vcc.flags;
1852                 ATM_PH_VPI(&ah) = 0;
1853                 ATM_PH_SETVCI(&ah, vc->vcc.vci);
1854
1855                 DBG(sc, INTR, ("rx%td: rxvci%d: atm_input, mbuf %p, len %d, "
1856                     "hand %p", slot - sc->rxslot, vc->vcc.vci, m,
1857                     EN_DQ_LEN(drq), vc->rxhand));
1858
1859                 m->m_pkthdr.rcvif = sc->ifp;
1860                 sc->ifp->if_ipackets++;
1861
1862                 vc->ipackets++;
1863                 vc->ibytes += m->m_pkthdr.len;
1864
1865 #ifdef EN_DEBUG
1866                 if (sc->debug & DBG_IPACKETS)
1867                         en_dump_packet(sc, m);
1868 #endif
1869 #ifdef ENABLE_BPF
1870                 BPF_MTAP(sc->ifp, m);
1871 #endif
1872                 EN_UNLOCK(sc);
1873                 atm_input(sc->ifp, &ah, m, vc->rxhand);
1874                 EN_LOCK(sc);
1875         }
1876 }
1877
1878 /*
1879  * check for RX DMA complete, and pass the data "upstairs"
1880  *
1881  * LOCK: locked, needed
1882  */
1883 static int
1884 en_intr_rx_dma(struct en_softc *sc)
1885 {
1886         uint32_t val;
1887         uint32_t idx;
1888         uint32_t drq;
1889
1890         val = en_read(sc, MID_DMA_RDRX);        /* chip's current location */
1891         idx = MID_DRQ_A2REG(sc->drq_chip);      /* where we last saw chip */
1892
1893         while (idx != val) {
1894                 sc->drq_free++;
1895                 if ((drq = sc->drq[idx]) != 0) {
1896                         /* don't forget to zero it out when done */
1897                         sc->drq[idx] = 0;
1898                         en_rx_drain(sc, drq);
1899                 }
1900                 EN_WRAPADD(0, MID_DRQ_N, idx, 1);
1901         }
1902         sc->drq_chip = MID_DRQ_REG2A(val);      /* sync softc */
1903
1904         if (sc->need_drqs) {
1905                 /* true if we had a DRQ shortage */
1906                 sc->need_drqs = 0;
1907                 DBG(sc, INTR, ("cleared need DRQ condition"));
1908                 return (1);
1909         } else
1910                 return (0);
1911 }
1912
1913 /*
1914  * en_mget: get an mbuf chain that can hold totlen bytes and return it
1915  * (for recv). For the actual allocation totlen is rounded up to a multiple
1916  * of 4. We also ensure, that each mbuf has a multiple of 4 bytes.
1917  *
1918  * After this call the sum of all the m_len's in the chain will be totlen.
1919  * This is called at interrupt time, so we can't wait here.
1920  *
1921  * LOCK: any, not needed
1922  */
1923 static struct mbuf *
1924 en_mget(struct en_softc *sc, u_int pktlen)
1925 {
1926         struct mbuf *m, *tmp;
1927         u_int totlen, pad;
1928
1929         totlen = roundup(pktlen, sizeof(uint32_t));
1930         pad = totlen - pktlen;
1931
1932         /*
1933          * First get an mbuf with header. Keep space for a couple of
1934          * words at the begin.
1935          */
1936         /* called from interrupt context */
1937         MGETHDR(m, M_DONTWAIT, MT_DATA);
1938         if (m == NULL)
1939                 return (NULL);
1940
1941         m->m_pkthdr.rcvif = NULL;
1942         m->m_pkthdr.len = pktlen;
1943         m->m_len = EN_RX1BUF;
1944         MH_ALIGN(m, EN_RX1BUF);
1945         if (m->m_len >= totlen) {
1946                 m->m_len = totlen;
1947
1948         } else {
1949                 totlen -= m->m_len;
1950
1951                 /* called from interrupt context */
1952                 tmp = m_getm(m, totlen, M_DONTWAIT, MT_DATA);
1953                 if (tmp == NULL) {
1954                         m_free(m);
1955                         return (NULL);
1956                 }
1957                 tmp = m->m_next;
1958                 /* m_getm could do this for us */
1959                 while (tmp != NULL) {
1960                         tmp->m_len = min(MCLBYTES, totlen);
1961                         totlen -= tmp->m_len;
1962                         tmp = tmp->m_next;
1963                 }
1964         }
1965
1966         return (m);
1967 }
1968
1969 /*
1970  * Argument for RX DMAMAP loader.
1971  */
1972 struct rxarg {
1973         struct en_softc *sc;
1974         struct mbuf *m;
1975         u_int pre_skip;         /* number of bytes to skip at begin */
1976         u_int post_skip;        /* number of bytes to skip at end */
1977         struct en_vcc *vc;      /* vc we are receiving on */
1978         int wait;               /* wait for DRQ entries */
1979 };
1980
1981 /*
1982  * Copy the segment table to the buffer for later use. And compute the
1983  * number of dma queue entries we need.
1984  *
1985  * LOCK: locked, needed
1986  */
1987 static void
1988 en_rxdma_load(void *uarg, bus_dma_segment_t *segs, int nseg,
1989     bus_size_t mapsize, int error)
1990 {
1991         struct rxarg *rx = uarg;
1992         struct en_softc *sc = rx->sc;
1993         struct en_rxslot *slot = rx->vc->rxslot;
1994         u_int           free;           /* number of free DRQ entries */
1995         uint32_t        cur;            /* current buffer offset */
1996         uint32_t        drq;            /* DRQ entry pointer */
1997         uint32_t        last_drq;       /* where we have written last */
1998         u_int           needalign, cnt, count, bcode;
1999         bus_addr_t      addr;
2000         bus_size_t      rest;
2001         int             i;
2002
2003         if (error != 0)
2004                 return;
2005         if (nseg > EN_MAX_DMASEG)
2006                 panic("too many DMA segments");
2007
2008         rx->wait = 0;
2009
2010         free = sc->drq_free;
2011         drq = sc->drq_us;
2012         cur = slot->cur;
2013
2014         last_drq = 0;
2015
2016         /*
2017          * Local macro to add an entry to the receive DMA area. If there
2018          * are no entries left, return. Save the byte offset of the entry
2019          * in last_drq for later use.
2020          */
2021 #define PUT_DRQ_ENTRY(ENI, BCODE, COUNT, ADDR)                          \
2022         if (free == 0) {                                                \
2023                 EN_COUNT(sc->stats.rxdrqout);                           \
2024                 rx->wait = 1;                                           \
2025                 return;                                                 \
2026         }                                                               \
2027         last_drq = drq;                                                 \
2028         en_write(sc, drq + 0, (ENI || !sc->is_adaptec) ?                \
2029             MID_MK_RXQ_ENI(COUNT, rx->vc->vcc.vci, 0, BCODE) :          \
2030             MID_MK_RXQ_ADP(COUNT, rx->vc->vcc.vci, 0, BCODE));          \
2031         en_write(sc, drq + 4, ADDR);                                    \
2032                                                                         \
2033         EN_WRAPADD(MID_DRQOFF, MID_DRQEND, drq, 8);                     \
2034         free--;
2035
2036         /*
2037          * Local macro to generate a DMA entry to DMA cnt bytes. Updates
2038          * the current buffer byte offset accordingly.
2039          */
2040 #define DO_DRQ(TYPE) do {                                               \
2041         rest -= cnt;                                                    \
2042         EN_WRAPADD(slot->start, slot->stop, cur, cnt);                  \
2043         DBG(sc, SERV, ("rx%td: "TYPE" %u bytes, %ju left, cur %#x",     \
2044             slot - sc->rxslot, cnt, (uintmax_t)rest, cur));             \
2045                                                                         \
2046         PUT_DRQ_ENTRY(1, bcode, count, addr);                           \
2047                                                                         \
2048         addr += cnt;                                                    \
2049     } while (0)
2050
2051         /*
2052          * Skip the RBD at the beginning
2053          */
2054         if (rx->pre_skip > 0) {
2055                 /* update DMA address */
2056                 EN_WRAPADD(slot->start, slot->stop, cur, rx->pre_skip);
2057
2058                 PUT_DRQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
2059         }
2060
2061         for (i = 0; i < nseg; i++, segs++) {
2062                 addr = segs->ds_addr;
2063                 rest = segs->ds_len;
2064
2065                 if (sc->is_adaptec) {
2066                         /* adaptec card - simple */
2067
2068                         /* advance the on-card buffer pointer */
2069                         EN_WRAPADD(slot->start, slot->stop, cur, rest);
2070                         DBG(sc, SERV, ("rx%td: adp %ju bytes %#jx "
2071                             "(cur now 0x%x)", slot - sc->rxslot,
2072                             (uintmax_t)rest, (uintmax_t)addr, cur));
2073
2074                         PUT_DRQ_ENTRY(0, 0, rest, addr);
2075
2076                         continue;
2077                 }
2078
2079                 /*
2080                  * do we need to do a DMA op to align to the maximum
2081                  * burst? Note, that we are alway 32-bit aligned.
2082                  */
2083                 if (sc->alburst &&
2084                     (needalign = (addr & sc->bestburstmask)) != 0) {
2085                         /* compute number of bytes, words and code */
2086                         cnt = sc->bestburstlen - needalign;
2087                         if (cnt > rest)
2088                                 cnt = rest;
2089                         count = cnt / sizeof(uint32_t);
2090                         if (sc->noalbursts) {
2091                                 bcode = MIDDMA_WORD;
2092                         } else {
2093                                 bcode = en_dmaplan[count].bcode;
2094                                 count = cnt >> en_dmaplan[count].divshift;
2095                         }
2096                         DO_DRQ("al_dma");
2097                 }
2098
2099                 /* do we need to do a max-sized burst? */
2100                 if (rest >= sc->bestburstlen) {
2101                         count = rest >> sc->bestburstshift;
2102                         cnt = count << sc->bestburstshift;
2103                         bcode = sc->bestburstcode;
2104                         DO_DRQ("best_dma");
2105                 }
2106
2107                 /* do we need to do a cleanup burst? */
2108                 if (rest != 0) {
2109                         cnt = rest;
2110                         count = rest / sizeof(uint32_t);
2111                         if (sc->noalbursts) {
2112                                 bcode = MIDDMA_WORD;
2113                         } else {
2114                                 bcode = en_dmaplan[count].bcode;
2115                                 count = cnt >> en_dmaplan[count].divshift;
2116                         }
2117                         DO_DRQ("clean_dma");
2118                 }
2119         }
2120
2121         /*
2122          * Skip stuff at the end
2123          */
2124         if (rx->post_skip > 0) {
2125                 /* update DMA address */
2126                 EN_WRAPADD(slot->start, slot->stop, cur, rx->post_skip);
2127
2128                 PUT_DRQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
2129         }
2130
2131         /* record the end for the interrupt routine */
2132         sc->drq[MID_DRQ_A2REG(last_drq)] =
2133             EN_DQ_MK(slot - sc->rxslot, rx->m->m_pkthdr.len);
2134
2135         /* set the end flag in the last descriptor */
2136         en_write(sc, last_drq + 0, SETQ_END(sc, en_read(sc, last_drq + 0)));
2137
2138 #undef PUT_DRQ_ENTRY
2139 #undef DO_DRQ
2140
2141         /* commit */
2142         slot->cur = cur;
2143         sc->drq_free = free;
2144         sc->drq_us = drq;
2145
2146         /* signal to card */
2147         en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_us));
2148 }
2149
2150 /*
2151  * en_service: handle a service interrupt
2152  *
2153  * Q: why do we need a software service list?
2154  *
2155  * A: if we remove a VCI from the hardware list and we find that we are
2156  *    out of DRQs we must defer processing until some DRQs become free.
2157  *    so we must remember to look at this RX VCI/slot later, but we can't
2158  *    put it back on the hardware service list (since that isn't allowed).
2159  *    so we instead save it on the software service list.   it would be nice 
2160  *    if we could peek at the VCI on top of the hwservice list without removing
2161  *    it, however this leads to a race condition: if we peek at it and
2162  *    decide we are done with it new data could come in before we have a 
2163  *    chance to remove it from the hwslist.   by the time we get it out of
2164  *    the list the interrupt for the new data will be lost.   oops!
2165  *
2166  * LOCK: locked, needed
2167  */
2168 static void
2169 en_service(struct en_softc *sc)
2170 {
2171         struct mbuf     *m, *lastm;
2172         struct en_map   *map;
2173         struct rxarg    rx;
2174         uint32_t        cur;
2175         uint32_t        dstart;         /* data start (as reported by card) */
2176         uint32_t        rbd;            /* receive buffer descriptor */
2177         uint32_t        pdu;            /* AAL5 trailer */
2178         int             mlen;
2179         int             error;
2180         struct en_rxslot *slot;
2181         struct en_vcc *vc;
2182
2183         rx.sc = sc;
2184
2185   next_vci:
2186         if (sc->swsl_size == 0) {
2187                 DBG(sc, SERV, ("en_service done"));
2188                 return;
2189         }
2190
2191         /*
2192          * get vcc to service
2193          */
2194         rx.vc = vc = sc->vccs[sc->swslist[sc->swsl_head]];
2195         slot = vc->rxslot;
2196         KASSERT (slot->vcc->rxslot == slot, ("en_service: rx slot/vci sync"));
2197
2198         /*
2199          * determine our mode and if we've got any work to do
2200          */
2201         DBG(sc, SERV, ("rx%td: service vci=%d start/stop/cur=0x%x 0x%x "
2202             "0x%x", slot - sc->rxslot, vc->vcc.vci, slot->start,
2203             slot->stop, slot->cur));
2204
2205   same_vci:
2206         cur = slot->cur;
2207
2208         dstart = MIDV_DSTART(en_read(sc, MID_DST_RP(vc->vcc.vci)));
2209         dstart = (dstart * sizeof(uint32_t)) + slot->start;
2210
2211         /* check to see if there is any data at all */
2212         if (dstart == cur) {
2213                 EN_WRAPADD(0, MID_SL_N, sc->swsl_head, 1); 
2214                 /* remove from swslist */
2215                 vc->vflags &= ~VCC_SWSL;
2216                 sc->swsl_size--;
2217                 DBG(sc, SERV, ("rx%td: remove vci %d from swslist",
2218                     slot - sc->rxslot, vc->vcc.vci));
2219                 goto next_vci;
2220         }
2221
2222         /*
2223          * figure out how many bytes we need
2224          * [mlen = # bytes to go in mbufs]
2225          */
2226         rbd = en_read(sc, cur);
2227         if (MID_RBD_ID(rbd) != MID_RBD_STDID) 
2228                 panic("en_service: id mismatch");
2229
2230         if (rbd & MID_RBD_T) {
2231                 mlen = 0;               /* we've got trash */
2232                 rx.pre_skip = MID_RBD_SIZE;
2233                 rx.post_skip = 0;
2234                 EN_COUNT(sc->stats.ttrash);
2235                 DBG(sc, SERV, ("RX overflow lost %d cells!", MID_RBD_CNT(rbd)));
2236
2237         } else if (vc->vcc.aal != ATMIO_AAL_5) {
2238                 /* 1 cell (ick!) */
2239                 mlen = MID_CHDR_SIZE + MID_ATMDATASZ;
2240                 rx.pre_skip = MID_RBD_SIZE;
2241                 rx.post_skip = 0;
2242
2243         } else {
2244                 rx.pre_skip = MID_RBD_SIZE;
2245
2246                 /* get PDU trailer in correct byte order */
2247                 pdu = cur + MID_RBD_CNT(rbd) * MID_ATMDATASZ +
2248                     MID_RBD_SIZE - MID_PDU_SIZE;
2249                 if (pdu >= slot->stop)
2250                         pdu -= EN_RXSZ * 1024;
2251                 pdu = en_read(sc, pdu);
2252
2253                 if (MID_RBD_CNT(rbd) * MID_ATMDATASZ <
2254                     MID_PDU_LEN(pdu)) {
2255                         device_printf(sc->dev, "invalid AAL5 length\n");
2256                         rx.post_skip = MID_RBD_CNT(rbd) * MID_ATMDATASZ;
2257                         mlen = 0;
2258                         sc->ifp->if_ierrors++;
2259
2260                 } else if (rbd & MID_RBD_CRCERR) {
2261                         device_printf(sc->dev, "CRC error\n");
2262                         rx.post_skip = MID_RBD_CNT(rbd) * MID_ATMDATASZ;
2263                         mlen = 0;
2264                         sc->ifp->if_ierrors++;
2265
2266                 } else {
2267                         mlen = MID_PDU_LEN(pdu);
2268                         rx.post_skip = MID_RBD_CNT(rbd) * MID_ATMDATASZ - mlen;
2269                 }
2270         }
2271
2272         /*
2273          * now allocate mbufs for mlen bytes of data, if out of mbufs, trash all
2274          *
2275          * notes:
2276          *  1. it is possible that we've already allocated an mbuf for this pkt
2277          *     but ran out of DRQs, in which case we saved the allocated mbuf
2278          *     on "q".
2279          *  2. if we save an buf in "q" we store the "cur" (pointer) in the
2280          *     buf as an identity (that we can check later).
2281          *  3. after this block of code, if m is still NULL then we ran out of
2282          *     mbufs
2283          */
2284         _IF_DEQUEUE(&slot->q, m);
2285         if (m != NULL) {
2286                 if (m->m_pkthdr.csum_data != cur) {
2287                         /* wasn't ours */
2288                         DBG(sc, SERV, ("rx%td: q'ed buf %p not ours",
2289                             slot - sc->rxslot, m));
2290                         _IF_PREPEND(&slot->q, m);
2291                         m = NULL;
2292                         EN_COUNT(sc->stats.rxqnotus);
2293                 } else {
2294                         EN_COUNT(sc->stats.rxqus);
2295                         DBG(sc, SERV, ("rx%td: recovered q'ed buf %p",
2296                             slot - sc->rxslot, m));
2297                 }
2298         }
2299         if (mlen == 0 && m != NULL) {
2300                 /* should not happen */
2301                 m_freem(m);
2302                 m = NULL;
2303         }
2304
2305         if (mlen != 0 && m == NULL) {
2306                 m = en_mget(sc, mlen);
2307                 if (m == NULL) {
2308                         rx.post_skip += mlen;
2309                         mlen = 0;
2310                         EN_COUNT(sc->stats.rxmbufout);
2311                         DBG(sc, SERV, ("rx%td: out of mbufs",
2312                             slot - sc->rxslot));
2313                 } else
2314                         rx.post_skip -= roundup(mlen, sizeof(uint32_t)) - mlen;
2315
2316                 DBG(sc, SERV, ("rx%td: allocate buf %p, mlen=%d",
2317                     slot - sc->rxslot, m, mlen));
2318         }
2319
2320         DBG(sc, SERV, ("rx%td: VCI %d, rbuf %p, mlen %d, skip %u/%u",
2321             slot - sc->rxslot, vc->vcc.vci, m, mlen, rx.pre_skip,
2322             rx.post_skip));
2323
2324         if (m != NULL) {
2325                 /* M_NOWAIT - called from interrupt context */
2326                 map = uma_zalloc_arg(sc->map_zone, sc, M_NOWAIT);
2327                 if (map == NULL) {
2328                         rx.post_skip += mlen;
2329                         m_freem(m);
2330                         DBG(sc, SERV, ("rx%td: out of maps",
2331                             slot - sc->rxslot));
2332                         goto skip;
2333                 }
2334                 rx.m = m;
2335                 error = bus_dmamap_load_mbuf(sc->txtag, map->map, m,
2336                     en_rxdma_load, &rx, BUS_DMA_NOWAIT);
2337
2338                 if (error != 0) {
2339                         device_printf(sc->dev, "loading RX map failed "
2340                             "%d\n", error);
2341                         uma_zfree(sc->map_zone, map);
2342                         m_freem(m);
2343                         rx.post_skip += mlen;
2344                         goto skip;
2345
2346                 }
2347                 map->flags |= ENMAP_LOADED;
2348
2349                 if (rx.wait) {
2350                         /* out of DRQs - wait */
2351                         uma_zfree(sc->map_zone, map);
2352
2353                         m->m_pkthdr.csum_data = cur;
2354                         _IF_ENQUEUE(&slot->q, m);
2355                         EN_COUNT(sc->stats.rxdrqout);
2356
2357                         sc->need_drqs = 1;      /* flag condition */
2358                         return;
2359
2360                 }
2361                 (void)m_length(m, &lastm);
2362                 lastm->m_len -= roundup(mlen, sizeof(uint32_t)) - mlen;
2363
2364                 m->m_pkthdr.rcvif = (void *)map;
2365                 _IF_ENQUEUE(&slot->indma, m);
2366
2367                 /* get next packet in this slot */
2368                 goto same_vci;
2369         }
2370   skip:
2371         /*
2372          * Here we end if we should drop the packet from the receive buffer.
2373          * The number of bytes to drop is in fill. We can do this with on
2374          * JK entry. If we don't even have that one - wait.
2375          */
2376         if (sc->drq_free == 0) {
2377                 sc->need_drqs = 1;      /* flag condition */
2378                 return;
2379         }
2380         rx.post_skip += rx.pre_skip;
2381         DBG(sc, SERV, ("rx%td: skipping %u", slot - sc->rxslot, rx.post_skip));
2382
2383         /* advance buffer address */
2384         EN_WRAPADD(slot->start, slot->stop, cur, rx.post_skip);
2385
2386         /* write DRQ entry */
2387         if (sc->is_adaptec)
2388                 en_write(sc, sc->drq_us,
2389                     MID_MK_RXQ_ADP(WORD_IDX(slot->start, cur),
2390                     vc->vcc.vci, MID_DMA_END, MIDDMA_JK));
2391         else
2392                 en_write(sc, sc->drq_us,
2393                     MID_MK_RXQ_ENI(WORD_IDX(slot->start, cur),
2394                     vc->vcc.vci, MID_DMA_END, MIDDMA_JK));
2395         en_write(sc, sc->drq_us + 4, 0);
2396         EN_WRAPADD(MID_DRQOFF, MID_DRQEND, sc->drq_us, 8);
2397         sc->drq_free--;
2398
2399         /* signal to RX interrupt */
2400         sc->drq[MID_DRQ_A2REG(sc->drq_us)] = EN_DQ_MK(slot - sc->rxslot, 0);
2401         slot->cur = cur;
2402
2403         /* signal to card */
2404         en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_us));
2405
2406         goto same_vci;
2407 }
2408
2409 /*
2410  * interrupt handler
2411  *
2412  * LOCK: unlocked, needed
2413  */
2414 void
2415 en_intr(void *arg)
2416 {
2417         struct en_softc *sc = arg;
2418         uint32_t reg, kick, mask;
2419         int lcv, need_softserv;
2420
2421         EN_LOCK(sc);
2422
2423         reg = en_read(sc, MID_INTACK);
2424         DBG(sc, INTR, ("interrupt=0x%b", reg, MID_INTBITS));
2425
2426         if ((reg & MID_INT_ANY) == 0) {
2427                 EN_UNLOCK(sc);
2428                 return;
2429         }
2430
2431         /*
2432          * unexpected errors that need a reset
2433          */
2434         if ((reg & (MID_INT_IDENT | MID_INT_LERR | MID_INT_DMA_ERR)) != 0) {
2435                 device_printf(sc->dev, "unexpected interrupt=0x%b, "
2436                     "resetting\n", reg, MID_INTBITS);
2437 #ifdef EN_DEBUG
2438                 kdb_enter("en: unexpected error");
2439                 sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* FREEZE! */
2440 #else
2441                 en_reset_ul(sc);
2442                 en_init(sc);
2443 #endif
2444                 EN_UNLOCK(sc);
2445                 return;
2446         }
2447
2448         if (reg & MID_INT_SUNI)
2449                 utopia_intr(&sc->utopia);
2450
2451         kick = 0;
2452         if (reg & MID_INT_TX)
2453                 kick |= en_intr_tx(sc, reg);
2454
2455         if (reg & MID_INT_DMA_TX)
2456                 kick |= en_intr_tx_dma(sc);
2457
2458         /*
2459          * kick xmit channels as needed.
2460          */
2461         if (kick) {
2462                 DBG(sc, INTR, ("tx kick mask = 0x%x", kick));
2463                 for (mask = 1, lcv = 0 ; lcv < EN_NTX ; lcv++, mask = mask * 2)
2464                         if ((kick & mask) && _IF_QLEN(&sc->txslot[lcv].q) != 0)
2465                                 en_txdma(sc, &sc->txslot[lcv]);
2466         }
2467
2468         need_softserv = 0;
2469         if (reg & MID_INT_DMA_RX)
2470                 need_softserv |= en_intr_rx_dma(sc);
2471
2472         if (reg & MID_INT_SERVICE)
2473                 need_softserv |= en_intr_service(sc);
2474
2475         if (need_softserv)
2476                 en_service(sc);
2477
2478         /*
2479          * keep our stats
2480          */
2481         if (reg & MID_INT_DMA_OVR) {
2482                 EN_COUNT(sc->stats.dmaovr);
2483                 DBG(sc, INTR, ("MID_INT_DMA_OVR"));
2484         }
2485         reg = en_read(sc, MID_STAT);
2486         sc->stats.otrash += MID_OTRASH(reg);
2487         sc->stats.vtrash += MID_VTRASH(reg);
2488
2489         EN_UNLOCK(sc);
2490 }
2491
2492 /*
2493  * Read at most n SUNI regs starting at reg into val
2494  */
2495 static int
2496 en_utopia_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n)
2497 {
2498         struct en_softc *sc = ifatm->ifp->if_softc;
2499         u_int i;
2500
2501         EN_CHECKLOCK(sc);
2502         if (reg >= MID_NSUNI)
2503                 return (EINVAL);
2504         if (reg + *n > MID_NSUNI)
2505                 *n = MID_NSUNI - reg;
2506
2507         for (i = 0; i < *n; i++)
2508                 val[i] = en_read(sc, MID_SUNIOFF + 4 * (reg + i));
2509
2510         return (0);
2511 }
2512
2513 /*
2514  * change the bits given by mask to them in val in register reg
2515  */
2516 static int
2517 en_utopia_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val)
2518 {
2519         struct en_softc *sc = ifatm->ifp->if_softc;
2520         uint32_t regval;
2521
2522         EN_CHECKLOCK(sc);
2523         if (reg >= MID_NSUNI)
2524                 return (EINVAL);
2525         regval = en_read(sc, MID_SUNIOFF + 4 * reg);
2526         regval = (regval & ~mask) | (val & mask);
2527         en_write(sc, MID_SUNIOFF + 4 * reg, regval);
2528         return (0);
2529 }
2530
2531 static const struct utopia_methods en_utopia_methods = {
2532         en_utopia_readregs,
2533         en_utopia_writereg
2534 };
2535
2536 /*********************************************************************/
2537 /*
2538  * Probing the DMA brokeness of the card
2539  */
2540
2541 /*
2542  * Physical address load helper function for DMA probe
2543  *
2544  * LOCK: unlocked, not needed
2545  */
2546 static void
2547 en_dmaprobe_load(void *uarg, bus_dma_segment_t *segs, int nseg, int error)
2548 {
2549         if (error == 0)
2550                 *(bus_addr_t *)uarg = segs[0].ds_addr;
2551 }
2552
2553 /*
2554  * en_dmaprobe: helper function for en_attach.
2555  *
2556  * see how the card handles DMA by running a few DMA tests.   we need
2557  * to figure out the largest number of bytes we can DMA in one burst
2558  * ("bestburstlen"), and if the starting address for a burst needs to
2559  * be aligned on any sort of boundary or not ("alburst").
2560  *
2561  * Things turn out more complex than that, because on my (harti) brand
2562  * new motherboard (2.4GHz) we can do 64byte aligned DMAs, but everything
2563  * we more than 4 bytes fails (with an RX DMA timeout) for physical
2564  * addresses that end with 0xc. Therefor we search not only the largest
2565  * burst that is supported (hopefully 64) but also check what is the largerst
2566  * unaligned supported size. If that appears to be lesser than 4 words,
2567  * set the noalbursts flag. That will be set only if also alburst is set.
2568  */
2569
2570 /*
2571  * en_dmaprobe_doit: do actual testing for the DMA test.
2572  * Cycle through all bursts sizes from 8 up to 64 and try whether it works.
2573  * Return the largest one that works.
2574  *
2575  * LOCK: unlocked, not needed
2576  */
2577 static int
2578 en_dmaprobe_doit(struct en_softc *sc, uint8_t *sp, bus_addr_t psp)
2579 {
2580         uint8_t *dp = sp + MIDDMA_MAXBURST;
2581         bus_addr_t pdp = psp + MIDDMA_MAXBURST;
2582         int lcv, retval = 4, cnt;
2583         uint32_t reg, bcode, midvloc;
2584
2585         if (sc->en_busreset)
2586                 sc->en_busreset(sc);
2587         en_write(sc, MID_RESID, 0x0);   /* reset card before touching RAM */
2588
2589         /*
2590          * set up a 1k buffer at MID_BUFOFF
2591          */
2592         midvloc = ((MID_BUFOFF - MID_RAMOFF) / sizeof(uint32_t))
2593             >> MIDV_LOCTOPSHFT;
2594         en_write(sc, MIDX_PLACE(0), MIDX_MKPLACE(en_k2sz(1), midvloc));
2595         en_write(sc, MID_VC(0), (midvloc << MIDV_LOCSHIFT) 
2596             | (en_k2sz(1) << MIDV_SZSHIFT) | MIDV_TRASH);
2597         en_write(sc, MID_DST_RP(0), 0);
2598         en_write(sc, MID_WP_ST_CNT(0), 0);
2599
2600         /* set up sample data */
2601         for (lcv = 0 ; lcv < MIDDMA_MAXBURST; lcv++)
2602                 sp[lcv] = lcv + 1;
2603
2604         /* enable DMA (only) */
2605         en_write(sc, MID_MAST_CSR, MID_MCSR_ENDMA);
2606
2607         sc->drq_chip = MID_DRQ_REG2A(en_read(sc, MID_DMA_RDRX));
2608         sc->dtq_chip = MID_DTQ_REG2A(en_read(sc, MID_DMA_RDTX));
2609
2610         /*
2611          * try it now . . .  DMA it out, then DMA it back in and compare
2612          *
2613          * note: in order to get the dma stuff to reverse directions it wants
2614          * the "end" flag set!   since we are not dma'ing valid data we may
2615          * get an ident mismatch interrupt (which we will ignore).
2616          */
2617         DBG(sc, DMA, ("test sp=%p/%#lx, dp=%p/%#lx", 
2618             sp, (u_long)psp, dp, (u_long)pdp));
2619         for (lcv = 8 ; lcv <= MIDDMA_MAXBURST ; lcv = lcv * 2) {
2620                 DBG(sc, DMA, ("test lcv=%d", lcv));
2621
2622                 /* zero SRAM and dest buffer */
2623                 bus_space_set_region_4(sc->en_memt, sc->en_base,
2624                     MID_BUFOFF, 0, 1024 / 4);
2625                 bzero(dp, MIDDMA_MAXBURST);
2626
2627                 bcode = en_sz2b(lcv);
2628
2629                 /* build lcv-byte-DMA x NBURSTS */
2630                 if (sc->is_adaptec)
2631                         en_write(sc, sc->dtq_chip,
2632                             MID_MK_TXQ_ADP(lcv, 0, MID_DMA_END, 0));
2633                 else
2634                         en_write(sc, sc->dtq_chip,
2635                             MID_MK_TXQ_ENI(1, 0, MID_DMA_END, bcode));
2636                 en_write(sc, sc->dtq_chip + 4, psp);
2637                 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, sc->dtq_chip, 8);
2638                 en_write(sc, MID_DMA_WRTX, MID_DTQ_A2REG(sc->dtq_chip));
2639
2640                 cnt = 1000;
2641                 while ((reg = en_readx(sc, MID_DMA_RDTX)) !=
2642                     MID_DTQ_A2REG(sc->dtq_chip)) {
2643                         DELAY(1);
2644                         if (--cnt == 0) {
2645                                 DBG(sc, DMA, ("unexpected timeout in tx "
2646                                     "DMA test\n  alignment=0x%lx, burst size=%d"
2647                                     ", dma addr reg=%#x, rdtx=%#x, stat=%#x\n",
2648                                     (u_long)sp & 63, lcv,
2649                                     en_read(sc, MID_DMA_ADDR), reg,
2650                                     en_read(sc, MID_INTSTAT)));
2651                                 return (retval);
2652                         }
2653                 }
2654
2655                 reg = en_read(sc, MID_INTACK); 
2656                 if ((reg & MID_INT_DMA_TX) != MID_INT_DMA_TX) {
2657                         DBG(sc, DMA, ("unexpected status in tx DMA test: %#x\n",
2658                             reg));
2659                         return (retval);
2660                 }
2661                 /* re-enable DMA (only) */
2662                 en_write(sc, MID_MAST_CSR, MID_MCSR_ENDMA);
2663
2664                 /* "return to sender..."  address is known ... */
2665
2666                 /* build lcv-byte-DMA x NBURSTS */
2667                 if (sc->is_adaptec)
2668                         en_write(sc, sc->drq_chip,
2669                             MID_MK_RXQ_ADP(lcv, 0, MID_DMA_END, 0));
2670                 else
2671                         en_write(sc, sc->drq_chip,
2672                             MID_MK_RXQ_ENI(1, 0, MID_DMA_END, bcode));
2673                 en_write(sc, sc->drq_chip + 4, pdp);
2674                 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, sc->drq_chip, 8);
2675                 en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_chip));
2676                 cnt = 1000;
2677                 while ((reg = en_readx(sc, MID_DMA_RDRX)) !=
2678                     MID_DRQ_A2REG(sc->drq_chip)) {
2679                         DELAY(1);
2680                         cnt--;
2681                         if (--cnt == 0) {
2682                                 DBG(sc, DMA, ("unexpected timeout in rx "
2683                                     "DMA test, rdrx=%#x\n", reg));
2684                                 return (retval);
2685                         }
2686                 }
2687                 reg = en_read(sc, MID_INTACK); 
2688                 if ((reg & MID_INT_DMA_RX) != MID_INT_DMA_RX) {
2689                         DBG(sc, DMA, ("unexpected status in rx DMA "
2690                             "test: 0x%x\n", reg));
2691                         return (retval);
2692                 }
2693                 if (bcmp(sp, dp, lcv)) {
2694                         DBG(sc, DMA, ("DMA test failed! lcv=%d, sp=%p, "
2695                             "dp=%p", lcv, sp, dp));
2696                         return (retval);
2697                 }
2698
2699                 retval = lcv;
2700         }
2701         return (retval);        /* studly 64 byte DMA present!  oh baby!! */
2702 }
2703
2704 /*
2705  * Find the best DMA parameters
2706  *
2707  * LOCK: unlocked, not needed
2708  */
2709 static void
2710 en_dmaprobe(struct en_softc *sc)
2711 {
2712         bus_dma_tag_t tag;
2713         bus_dmamap_t map;
2714         int err;
2715         void *buffer;
2716         int bestalgn, lcv, try, bestnoalgn;
2717         bus_addr_t phys;
2718         uint8_t *addr;
2719
2720         sc->alburst = 0;
2721         sc->noalbursts = 0;
2722
2723         /*
2724          * Allocate some DMA-able memory.
2725          * We need 3 times the max burst size aligned to the max burst size.
2726          */
2727         err = bus_dma_tag_create(NULL, MIDDMA_MAXBURST, 0,
2728             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
2729             3 * MIDDMA_MAXBURST, 1, 3 * MIDDMA_MAXBURST, 0,
2730             NULL, NULL, &tag);
2731         if (err)
2732                 panic("%s: cannot create test DMA tag %d", __func__, err);
2733
2734         err = bus_dmamem_alloc(tag, &buffer, 0, &map);
2735         if (err)
2736                 panic("%s: cannot allocate test DMA memory %d", __func__, err);
2737
2738         err = bus_dmamap_load(tag, map, buffer, 3 * MIDDMA_MAXBURST,
2739             en_dmaprobe_load, &phys, BUS_DMA_NOWAIT);
2740         if (err)
2741                 panic("%s: cannot load test DMA map %d", __func__, err);
2742         addr = buffer;
2743         DBG(sc, DMA, ("phys=%#lx addr=%p", (u_long)phys, addr));
2744
2745         /*
2746          * Now get the best burst size of the aligned case.
2747          */
2748         bestalgn = bestnoalgn = en_dmaprobe_doit(sc, addr, phys);
2749
2750         /*
2751          * Now try unaligned. 
2752          */
2753         for (lcv = 4; lcv < MIDDMA_MAXBURST; lcv += 4) {
2754                 try = en_dmaprobe_doit(sc, addr + lcv, phys + lcv);
2755
2756                 if (try < bestnoalgn)
2757                         bestnoalgn = try;
2758         }
2759
2760         if (bestnoalgn < bestalgn) {
2761                 sc->alburst = 1;
2762                 if (bestnoalgn < 32)
2763                         sc->noalbursts = 1;
2764         }
2765
2766         sc->bestburstlen = bestalgn;
2767         sc->bestburstshift = en_log2(bestalgn);
2768         sc->bestburstmask = sc->bestburstlen - 1; /* must be power of 2 */
2769         sc->bestburstcode = en_sz2b(bestalgn);
2770
2771         /*
2772          * Reset the chip before freeing the buffer. It may still be trying
2773          * to DMA.
2774          */
2775         if (sc->en_busreset)
2776                 sc->en_busreset(sc);
2777         en_write(sc, MID_RESID, 0x0);   /* reset card before touching RAM */
2778
2779         DELAY(10000);                   /* may still do DMA */
2780
2781         /*
2782          * Free the DMA stuff
2783          */
2784         bus_dmamap_unload(tag, map);
2785         bus_dmamem_free(tag, buffer, map);
2786         bus_dma_tag_destroy(tag);
2787 }
2788
2789 /*********************************************************************/
2790 /*
2791  * Attach/detach.
2792  */
2793
2794 /*
2795  * Attach to the card.
2796  *
2797  * LOCK: unlocked, not needed (but initialized)
2798  */
2799 int
2800 en_attach(struct en_softc *sc)
2801 {
2802         struct ifnet *ifp = sc->ifp;
2803         int sz;
2804         uint32_t reg, lcv, check, ptr, sav, midvloc;
2805
2806 #ifdef EN_DEBUG
2807         sc->debug = EN_DEBUG;
2808 #endif
2809
2810         /*
2811          * Probe card to determine memory size.
2812          *
2813          * The stupid ENI card always reports to PCI that it needs 4MB of
2814          * space (2MB regs and 2MB RAM). If it has less than 2MB RAM the
2815          * addresses wrap in the RAM address space (i.e. on a 512KB card
2816          * addresses 0x3ffffc, 0x37fffc, and 0x2ffffc are aliases for
2817          * 0x27fffc  [note that RAM starts at offset 0x200000]).
2818          */
2819
2820         /* reset card before touching RAM */
2821         if (sc->en_busreset)
2822                 sc->en_busreset(sc);
2823         en_write(sc, MID_RESID, 0x0);
2824
2825         for (lcv = MID_PROBEOFF; lcv <= MID_MAXOFF ; lcv += MID_PROBSIZE) {
2826                 en_write(sc, lcv, lcv); /* data[address] = address */
2827                 for (check = MID_PROBEOFF; check < lcv ;check += MID_PROBSIZE) {
2828                         reg = en_read(sc, check);
2829                         if (reg != check)
2830                                 /* found an alias! - quit */
2831                                 goto done_probe;
2832                 }
2833         }
2834   done_probe:
2835         lcv -= MID_PROBSIZE;                    /* take one step back */
2836         sc->en_obmemsz = (lcv + 4) - MID_RAMOFF;
2837
2838         /*
2839          * determine the largest DMA burst supported
2840          */
2841         en_dmaprobe(sc);
2842
2843         /*
2844          * "hello world"
2845          */
2846
2847         /* reset */
2848         if (sc->en_busreset)
2849                 sc->en_busreset(sc);
2850         en_write(sc, MID_RESID, 0x0);           /* reset */
2851
2852         /* zero memory */
2853         bus_space_set_region_4(sc->en_memt, sc->en_base,
2854             MID_RAMOFF, 0, sc->en_obmemsz / 4);
2855
2856         reg = en_read(sc, MID_RESID);
2857
2858         device_printf(sc->dev, "ATM midway v%d, board IDs %d.%d, %s%s%s, "
2859             "%ldKB on-board RAM\n", MID_VER(reg), MID_MID(reg), MID_DID(reg), 
2860             (MID_IS_SABRE(reg)) ? "sabre controller, " : "",
2861             (MID_IS_SUNI(reg)) ? "SUNI" : "Utopia",
2862             (!MID_IS_SUNI(reg) && MID_IS_UPIPE(reg)) ? " (pipelined)" : "",
2863             (long)sc->en_obmemsz / 1024);
2864
2865         /*
2866          * fill in common ATM interface stuff
2867          */
2868         IFP2IFATM(sc->ifp)->mib.hw_version = (MID_VER(reg) << 16) |
2869             (MID_MID(reg) << 8) | MID_DID(reg);
2870         if (MID_DID(reg) & 0x4)
2871                 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_UTP_155;
2872         else
2873                 IFP2IFATM(sc->ifp)->mib.media = IFM_ATM_MM_155;
2874
2875         IFP2IFATM(sc->ifp)->mib.pcr = ATM_RATE_155M;
2876         IFP2IFATM(sc->ifp)->mib.vpi_bits = 0;
2877         IFP2IFATM(sc->ifp)->mib.vci_bits = MID_VCI_BITS;
2878         IFP2IFATM(sc->ifp)->mib.max_vccs = MID_N_VC;
2879         IFP2IFATM(sc->ifp)->mib.max_vpcs = 0;
2880
2881         if (sc->is_adaptec) {
2882                 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_ADP155P;
2883                 if (sc->bestburstlen == 64 && sc->alburst == 0)
2884                         device_printf(sc->dev,
2885                             "passed 64 byte DMA test\n");
2886                 else
2887                         device_printf(sc->dev, "FAILED DMA TEST: "
2888                             "burst=%d, alburst=%d\n", sc->bestburstlen,
2889                             sc->alburst);
2890         } else {
2891                 IFP2IFATM(sc->ifp)->mib.device = ATM_DEVICE_ENI155P;
2892                 device_printf(sc->dev, "maximum DMA burst length = %d "
2893                     "bytes%s\n", sc->bestburstlen, sc->alburst ?
2894                     sc->noalbursts ?  " (no large bursts)" : " (must align)" :
2895                     "");
2896         }
2897
2898         /*
2899          * link into network subsystem and prepare card
2900          */
2901         sc->ifp->if_softc = sc;
2902         ifp->if_flags = IFF_SIMPLEX;
2903         ifp->if_ioctl = en_ioctl;
2904         ifp->if_start = en_start;
2905
2906         mtx_init(&sc->en_mtx, device_get_nameunit(sc->dev),
2907             MTX_NETWORK_LOCK, MTX_DEF);
2908         cv_init(&sc->cv_close, "VC close");
2909
2910         /*
2911          * Make the sysctl tree
2912          */
2913         sysctl_ctx_init(&sc->sysctl_ctx);
2914
2915         if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
2916             SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO,
2917             device_get_nameunit(sc->dev), CTLFLAG_RD, 0, "")) == NULL)
2918                 goto fail;
2919
2920         if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
2921             OID_AUTO, "istats", CTLFLAG_RD, sc, 0, en_sysctl_istats,
2922             "S", "internal statistics") == NULL)
2923                 goto fail;
2924
2925 #ifdef EN_DEBUG
2926         if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
2927             OID_AUTO, "debug", CTLFLAG_RW , &sc->debug, 0, "") == NULL)
2928                 goto fail;
2929 #endif
2930
2931         IFP2IFATM(sc->ifp)->phy = &sc->utopia;
2932         utopia_attach(&sc->utopia, IFP2IFATM(sc->ifp), &sc->media, &sc->en_mtx,
2933             &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
2934             &en_utopia_methods);
2935         utopia_init_media(&sc->utopia);
2936
2937         MGET(sc->padbuf, M_TRYWAIT, MT_DATA);
2938         if (sc->padbuf == NULL)
2939                 goto fail;
2940         bzero(sc->padbuf->m_data, MLEN);
2941
2942         if (bus_dma_tag_create(NULL, 1, 0,
2943             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
2944             EN_TXSZ * 1024, EN_MAX_DMASEG, EN_TXSZ * 1024, 0,
2945             NULL, NULL, &sc->txtag))
2946                 goto fail;
2947
2948         sc->map_zone = uma_zcreate("en dma maps", sizeof(struct en_map),
2949             en_map_ctor, en_map_dtor, NULL, en_map_fini, UMA_ALIGN_PTR,
2950             UMA_ZONE_ZINIT);
2951         if (sc->map_zone == NULL)
2952                 goto fail;
2953         uma_zone_set_max(sc->map_zone, EN_MAX_MAPS);
2954
2955         /*
2956          * init softc
2957          */
2958         sc->vccs = malloc(MID_N_VC * sizeof(sc->vccs[0]),
2959             M_DEVBUF, M_ZERO | M_WAITOK);
2960
2961         sz = sc->en_obmemsz - (MID_BUFOFF - MID_RAMOFF);
2962         ptr = sav = MID_BUFOFF;
2963         ptr = roundup(ptr, EN_TXSZ * 1024);     /* align */
2964         sz = sz - (ptr - sav);
2965         if (EN_TXSZ*1024 * EN_NTX > sz) {
2966                 device_printf(sc->dev, "EN_NTX/EN_TXSZ too big\n");
2967                 goto fail;
2968         }
2969         for (lcv = 0 ;lcv < EN_NTX ;lcv++) {
2970                 sc->txslot[lcv].mbsize = 0;
2971                 sc->txslot[lcv].start = ptr;
2972                 ptr += (EN_TXSZ * 1024);
2973                 sz -= (EN_TXSZ * 1024);
2974                 sc->txslot[lcv].stop = ptr;
2975                 sc->txslot[lcv].nref = 0;
2976                 DBG(sc, INIT, ("tx%d: start 0x%x, stop 0x%x", lcv,
2977                     sc->txslot[lcv].start, sc->txslot[lcv].stop));
2978         }
2979
2980         sav = ptr;
2981         ptr = roundup(ptr, EN_RXSZ * 1024);     /* align */
2982         sz = sz - (ptr - sav);
2983         sc->en_nrx = sz / (EN_RXSZ * 1024);
2984         if (sc->en_nrx <= 0) {
2985                 device_printf(sc->dev, "EN_NTX/EN_TXSZ/EN_RXSZ too big\n");
2986                 goto fail;
2987         }
2988
2989         /* 
2990          * ensure that there is always one VC slot on the service list free
2991          * so that we can tell the difference between a full and empty list.
2992          */
2993         if (sc->en_nrx >= MID_N_VC)
2994                 sc->en_nrx = MID_N_VC - 1;
2995
2996         for (lcv = 0 ; lcv < sc->en_nrx ; lcv++) {
2997                 sc->rxslot[lcv].vcc = NULL;
2998                 midvloc = sc->rxslot[lcv].start = ptr;
2999                 ptr += (EN_RXSZ * 1024);
3000                 sz -= (EN_RXSZ * 1024);
3001                 sc->rxslot[lcv].stop = ptr;
3002                 midvloc = midvloc - MID_RAMOFF;
3003                 /* mask, cvt to words */
3004                 midvloc = (midvloc & ~((EN_RXSZ*1024) - 1)) >> 2;
3005                 /* we only want the top 11 bits */
3006                 midvloc = midvloc >> MIDV_LOCTOPSHFT;
3007                 midvloc = (midvloc & MIDV_LOCMASK) << MIDV_LOCSHIFT;
3008                 sc->rxslot[lcv].mode = midvloc | 
3009                     (en_k2sz(EN_RXSZ) << MIDV_SZSHIFT) | MIDV_TRASH;
3010
3011                 DBG(sc, INIT, ("rx%d: start 0x%x, stop 0x%x, mode 0x%x", lcv,
3012                     sc->rxslot[lcv].start, sc->rxslot[lcv].stop,
3013                     sc->rxslot[lcv].mode));
3014         }
3015
3016         device_printf(sc->dev, "%d %dKB receive buffers, %d %dKB transmit "
3017             "buffers\n", sc->en_nrx, EN_RXSZ, EN_NTX, EN_TXSZ);
3018         device_printf(sc->dev, "end station identifier (mac address) "
3019             "%6D\n", IFP2IFATM(sc->ifp)->mib.esi, ":");
3020
3021         /*
3022          * Start SUNI stuff. This will call our readregs/writeregs
3023          * functions and these assume the lock to be held so we must get it
3024          * here.
3025          */
3026         EN_LOCK(sc);
3027         utopia_start(&sc->utopia);
3028         utopia_reset(&sc->utopia);
3029         EN_UNLOCK(sc);
3030
3031         /*
3032          * final commit
3033          */
3034         atm_ifattach(ifp); 
3035
3036 #ifdef ENABLE_BPF
3037         bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
3038 #endif
3039
3040         return (0);
3041
3042  fail:
3043         en_destroy(sc);
3044         return (-1);
3045 }
3046
3047 /*
3048  * Free all internal resources. No access to bus resources here.
3049  * No locking required here (interrupt is already disabled).
3050  *
3051  * LOCK: unlocked, needed (but destroyed)
3052  */
3053 void
3054 en_destroy(struct en_softc *sc)
3055 {
3056         u_int i;
3057
3058         if (sc->utopia.state & UTP_ST_ATTACHED) {
3059                 /* these assume the lock to be held */
3060                 EN_LOCK(sc);
3061                 utopia_stop(&sc->utopia);
3062                 utopia_detach(&sc->utopia);
3063                 EN_UNLOCK(sc);
3064         }
3065
3066         if (sc->vccs != NULL) {
3067                 /* get rid of sticky VCCs */
3068                 for (i = 0; i < MID_N_VC; i++)
3069                         if (sc->vccs[i] != NULL)
3070                                 uma_zfree(en_vcc_zone, sc->vccs[i]);
3071                 free(sc->vccs, M_DEVBUF);
3072         }
3073
3074         if (sc->padbuf != NULL)
3075                 m_free(sc->padbuf);
3076
3077         /*
3078          * Destroy the map zone before the tag (the fini function will
3079          * destroy the DMA maps using the tag)
3080          */
3081         if (sc->map_zone != NULL)
3082                 uma_zdestroy(sc->map_zone);
3083
3084         if (sc->txtag != NULL)
3085                 bus_dma_tag_destroy(sc->txtag);
3086
3087         (void)sysctl_ctx_free(&sc->sysctl_ctx);
3088
3089         cv_destroy(&sc->cv_close);
3090         mtx_destroy(&sc->en_mtx);
3091 }
3092
3093 /*
3094  * Module loaded/unloaded
3095  */
3096 int
3097 en_modevent(module_t mod __unused, int event, void *arg __unused)
3098 {
3099
3100         switch (event) {
3101
3102           case MOD_LOAD:
3103                 en_vcc_zone = uma_zcreate("EN vccs", sizeof(struct en_vcc),
3104                     NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
3105                 if (en_vcc_zone == NULL)
3106                         return (ENOMEM);
3107                 break;
3108
3109           case MOD_UNLOAD:
3110                 uma_zdestroy(en_vcc_zone);
3111                 break;
3112         }
3113         return (0);
3114 }
3115
3116 /*********************************************************************/
3117 /*
3118  * Debugging support
3119  */
3120
3121 #ifdef EN_DDBHOOK
3122 /*
3123  * functions we can call from ddb
3124  */
3125
3126 /*
3127  * en_dump: dump the state
3128  */
3129 #define END_SWSL        0x00000040              /* swsl state */
3130 #define END_DRQ         0x00000020              /* drq state */
3131 #define END_DTQ         0x00000010              /* dtq state */
3132 #define END_RX          0x00000008              /* rx state */
3133 #define END_TX          0x00000004              /* tx state */
3134 #define END_MREGS       0x00000002              /* registers */
3135 #define END_STATS       0x00000001              /* dump stats */
3136
3137 #define END_BITS "\20\7SWSL\6DRQ\5DTQ\4RX\3TX\2MREGS\1STATS"
3138
3139 static void
3140 en_dump_stats(const struct en_stats *s)
3141 {
3142         printf("en_stats:\n");
3143         printf("\t%d/%d mfix (%d failed)\n", s->mfixaddr, s->mfixlen,
3144             s->mfixfail);
3145         printf("\t%d rx dma overflow interrupts\n", s->dmaovr);
3146         printf("\t%d times out of TX space and stalled\n", s->txoutspace);
3147         printf("\t%d times out of DTQs\n", s->txdtqout);
3148         printf("\t%d times launched a packet\n", s->launch);
3149         printf("\t%d times pulled the hw service list\n", s->hwpull);
3150         printf("\t%d times pushed a vci on the sw service list\n", s->swadd);
3151         printf("\t%d times RX pulled an mbuf from Q that wasn't ours\n",
3152             s->rxqnotus);
3153         printf("\t%d times RX pulled a good mbuf from Q\n", s->rxqus);
3154         printf("\t%d times ran out of DRQs\n", s->rxdrqout);
3155         printf("\t%d transmit packets dropped due to mbsize\n", s->txmbovr);
3156         printf("\t%d cells trashed due to turned off rxvc\n", s->vtrash);
3157         printf("\t%d cells trashed due to totally full buffer\n", s->otrash);
3158         printf("\t%d cells trashed due almost full buffer\n", s->ttrash);
3159         printf("\t%d rx mbuf allocation failures\n", s->rxmbufout);
3160         printf("\t%d times out of tx maps\n", s->txnomap);
3161 #ifdef NATM
3162 #ifdef NATM_STAT
3163         printf("\tnatmintr so_rcv: ok/drop cnt: %d/%d, ok/drop bytes: %d/%d\n",
3164             natm_sookcnt, natm_sodropcnt, natm_sookbytes, natm_sodropbytes);
3165 #endif
3166 #endif
3167 }
3168
3169 static void
3170 en_dump_mregs(struct en_softc *sc)
3171 {
3172         u_int cnt;
3173
3174         printf("mregs:\n");
3175         printf("resid = 0x%x\n", en_read(sc, MID_RESID));
3176         printf("interrupt status = 0x%b\n",
3177             (int)en_read(sc, MID_INTSTAT), MID_INTBITS);
3178         printf("interrupt enable = 0x%b\n", 
3179              (int)en_read(sc, MID_INTENA), MID_INTBITS);
3180         printf("mcsr = 0x%b\n", (int)en_read(sc, MID_MAST_CSR), MID_MCSRBITS);
3181         printf("serv_write = [chip=%u] [us=%u]\n", en_read(sc, MID_SERV_WRITE),
3182              MID_SL_A2REG(sc->hwslistp));
3183         printf("dma addr = 0x%x\n", en_read(sc, MID_DMA_ADDR));
3184         printf("DRQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3185             MID_DRQ_REG2A(en_read(sc, MID_DMA_RDRX)), 
3186             MID_DRQ_REG2A(en_read(sc, MID_DMA_WRRX)), sc->drq_chip, sc->drq_us);
3187         printf("DTQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3188             MID_DTQ_REG2A(en_read(sc, MID_DMA_RDTX)), 
3189             MID_DTQ_REG2A(en_read(sc, MID_DMA_WRTX)), sc->dtq_chip, sc->dtq_us);
3190
3191         printf("  unusal txspeeds:");
3192         for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3193                 if (sc->vccs[cnt]->txspeed)
3194                         printf(" vci%d=0x%x", cnt, sc->vccs[cnt]->txspeed);
3195         printf("\n");
3196
3197         printf("  rxvc slot mappings:");
3198         for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3199                 if (sc->vccs[cnt]->rxslot != NULL)
3200                         printf("  %d->%td", cnt,
3201                             sc->vccs[cnt]->rxslot - sc->rxslot);
3202         printf("\n");
3203 }
3204
3205 static void
3206 en_dump_tx(struct en_softc *sc)
3207 {
3208         u_int slot;
3209
3210         printf("tx:\n");
3211         for (slot = 0 ; slot < EN_NTX; slot++) {
3212                 printf("tx%d: start/stop/cur=0x%x/0x%x/0x%x [%d]  ", slot,
3213                     sc->txslot[slot].start, sc->txslot[slot].stop,
3214                     sc->txslot[slot].cur,
3215                     (sc->txslot[slot].cur - sc->txslot[slot].start) / 4);
3216                 printf("mbsize=%d, bfree=%d\n", sc->txslot[slot].mbsize,
3217                     sc->txslot[slot].bfree);
3218                 printf("txhw: base_address=0x%x, size=%u, read=%u, "
3219                     "descstart=%u\n",
3220                     (u_int)MIDX_BASE(en_read(sc, MIDX_PLACE(slot))), 
3221                     MIDX_SZ(en_read(sc, MIDX_PLACE(slot))),
3222                     en_read(sc, MIDX_READPTR(slot)),
3223                     en_read(sc, MIDX_DESCSTART(slot)));
3224         }
3225 }
3226
3227 static void
3228 en_dump_rx(struct en_softc *sc)
3229 {
3230         struct en_rxslot *slot;
3231
3232         printf("  recv slots:\n");
3233         for (slot = sc->rxslot ; slot < &sc->rxslot[sc->en_nrx]; slot++) {
3234                 printf("rx%td: start/stop/cur=0x%x/0x%x/0x%x mode=0x%x ",
3235                     slot - sc->rxslot, slot->start, slot->stop, slot->cur,
3236                     slot->mode);
3237                 if (slot->vcc != NULL) {
3238                         printf("vci=%u\n", slot->vcc->vcc.vci);
3239                         printf("RXHW: mode=0x%x, DST_RP=0x%x, WP_ST_CNT=0x%x\n",
3240                             en_read(sc, MID_VC(slot->vcc->vcc.vci)),
3241                             en_read(sc, MID_DST_RP(slot->vcc->vcc.vci)),
3242                             en_read(sc, MID_WP_ST_CNT(slot->vcc->vcc.vci)));
3243                 }
3244         }
3245 }
3246
3247 /*
3248  * This is only correct for non-adaptec adapters
3249  */
3250 static void
3251 en_dump_dtqs(struct en_softc *sc)
3252 {
3253         uint32_t ptr, reg;
3254
3255         printf("  dtq [need_dtqs=%d,dtq_free=%d]:\n", sc->need_dtqs,
3256             sc->dtq_free);
3257         ptr = sc->dtq_chip;
3258         while (ptr != sc->dtq_us) {
3259                 reg = en_read(sc, ptr);
3260                 printf("\t0x%x=[%#x cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n", 
3261                     sc->dtq[MID_DTQ_A2REG(ptr)], reg, MID_DMA_CNT(reg),
3262                     MID_DMA_TXCHAN(reg), (reg & MID_DMA_END) != 0,
3263                     MID_DMA_TYPE(reg), en_read(sc, ptr + 4));
3264                 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, ptr, 8);
3265         }
3266 }
3267
3268 static void
3269 en_dump_drqs(struct en_softc *sc)
3270 {
3271         uint32_t ptr, reg;
3272
3273         printf("  drq [need_drqs=%d,drq_free=%d]:\n", sc->need_drqs,
3274             sc->drq_free);
3275         ptr = sc->drq_chip;
3276         while (ptr != sc->drq_us) {
3277                 reg = en_read(sc, ptr);
3278                 printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n", 
3279                     sc->drq[MID_DRQ_A2REG(ptr)], MID_DMA_CNT(reg),
3280                     MID_DMA_RXVCI(reg), (reg & MID_DMA_END) != 0,
3281                     MID_DMA_TYPE(reg), en_read(sc, ptr + 4));
3282                 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, ptr, 8);
3283         }
3284 }
3285
3286 /* Do not staticize - meant for calling from DDB! */
3287 int
3288 en_dump(int unit, int level)
3289 {
3290         struct en_softc *sc;
3291         int lcv, cnt;
3292         devclass_t dc;
3293         int maxunit;
3294
3295         dc = devclass_find("en");
3296         if (dc == NULL) {
3297                 printf("%s: can't find devclass!\n", __func__);
3298                 return (0);
3299         }
3300         maxunit = devclass_get_maxunit(dc);
3301         for (lcv = 0 ; lcv < maxunit ; lcv++) {
3302                 sc = devclass_get_softc(dc, lcv);
3303                 if (sc == NULL)
3304                         continue;
3305                 if (unit != -1 && unit != lcv)
3306                         continue;
3307
3308                 device_printf(sc->dev, "dumping device at level 0x%b\n",
3309                     level, END_BITS);
3310
3311                 if (sc->dtq_us == 0) {
3312                         printf("<hasn't been en_init'd yet>\n");
3313                         continue;
3314                 }
3315
3316                 if (level & END_STATS)
3317                         en_dump_stats(&sc->stats);
3318                 if (level & END_MREGS)
3319                         en_dump_mregs(sc);
3320                 if (level & END_TX)
3321                         en_dump_tx(sc);
3322                 if (level & END_RX)
3323                         en_dump_rx(sc);
3324                 if (level & END_DTQ)
3325                         en_dump_dtqs(sc);
3326                 if (level & END_DRQ)
3327                         en_dump_drqs(sc);
3328
3329                 if (level & END_SWSL) {
3330                         printf(" swslist [size=%d]: ", sc->swsl_size);
3331                         for (cnt = sc->swsl_head ; cnt != sc->swsl_tail ; 
3332                             cnt = (cnt + 1) % MID_SL_N)
3333                                 printf("0x%x ", sc->swslist[cnt]);
3334                         printf("\n");
3335                 }
3336         }
3337         return (0);
3338 }
3339
3340 /*
3341  * en_dumpmem: dump the memory
3342  *
3343  * Do not staticize - meant for calling from DDB!
3344  */
3345 int
3346 en_dumpmem(int unit, int addr, int len)
3347 {
3348         struct en_softc *sc;
3349         uint32_t reg;
3350         devclass_t dc;
3351
3352         dc = devclass_find("en");
3353         if (dc == NULL) {
3354                 printf("%s: can't find devclass\n", __func__);
3355                 return (0);
3356         }
3357         sc = devclass_get_softc(dc, unit);
3358         if (sc == NULL) {
3359                 printf("%s: invalid unit number: %d\n", __func__, unit);
3360                 return (0);
3361         }
3362
3363         addr = addr & ~3;
3364         if (addr < MID_RAMOFF || addr + len * 4 > MID_MAXOFF || len <= 0) {
3365                 printf("invalid addr/len number: %d, %d\n", addr, len);
3366                 return (0);
3367         }
3368         printf("dumping %d words starting at offset 0x%x\n", len, addr);
3369         while (len--) {
3370                 reg = en_read(sc, addr);
3371                 printf("mem[0x%x] = 0x%x\n", addr, reg);
3372                 addr += 4;
3373         }
3374         return (0);
3375 }
3376 #endif