[BACK]Return to midway.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/midway.c, Revision 1.1

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

CVSweb