1 /* $NetBSD: midway.c,v 1.30 1997/09/29 17:40:38 chuck Exp $ */
2 /* (sync'd to midway.c 1.68) */
5 * Copyright (c) 1996 Charles D. Cranor and Washington University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles D. Cranor and
19 * Washington University.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
39 * m i d w a y . c e n i 1 5 5 d r i v e r
41 * author: Chuck Cranor <chuck@ccrc.wustl.edu>
42 * started: spring, 1996 (written from scratch).
44 * notes from the author:
45 * Extra special thanks go to Werner Almesberger, EPFL LRC. Werner's
46 * ENI driver was especially useful in figuring out how this card works.
47 * I would also like to thank Werner for promptly answering email and being
52 #define EN_DDBHOOK 1 /* compile in ddb functions */
55 * Note on EN_ENIDMAFIX: the byte aligner on the ENI version of the card
56 * appears to be broken. it works just fine if there is no load... however
57 * when the card is loaded the data get corrupted. to see this, one only
58 * has to use "telnet" over ATM. do the following command in "telnet":
59 * cat /usr/share/misc/termcap
60 * "telnet" seems to generate lots of 1023 byte mbufs (which make great
61 * use of the byte aligner). watch "netstat -s" for checksum errors.
63 * I further tested this by adding a function that compared the transmit
64 * data on the card's SRAM with the data in the mbuf chain _after_ the
65 * "transmit DMA complete" interrupt. using the "telnet" test I got data
66 * mismatches where the byte-aligned data should have been. using ddb
67 * and en_dumpmem() I verified that the DTQs fed into the card were
68 * absolutely correct. thus, we are forced to concluded that the ENI
69 * hardware is buggy. note that the Adaptec version of the card works
70 * just fine with byte DMA.
72 * bottom line: we set EN_ENIDMAFIX to 1 to avoid byte DMAs on the ENI
76 #if defined(DIAGNOSTIC) && !defined(EN_DIAG)
77 #define EN_DIAG /* link in with master DIAG option */
80 #define EN_COUNT(X) (X)++
88 * This macro removes almost all the EN_DEBUG conditionals in the code that make
89 * to code a good deal less readable.
91 #define DBG(SC, FL, PRINT) do { \
92 if ((SC)->debug & DBG_##FL) { \
93 if_printf(&(SC)->ifatm.ifnet, "%s: "#FL": ", __func__); \
100 DBG_INIT = 0x0001, /* debug attach/detach */
101 DBG_TX = 0x0002, /* debug transmitting */
102 DBG_SERV = 0x0004, /* debug service interrupts */
103 DBG_IOCTL = 0x0008, /* debug ioctls */
104 DBG_VC = 0x0010, /* debug VC handling */
105 DBG_INTR = 0x0020, /* debug interrupts */
106 DBG_DMA = 0x0040, /* debug DMA probing */
107 DBG_IPACKETS = 0x0080, /* print input packets */
108 DBG_REG = 0x0100, /* print all register access */
109 DBG_LOCK = 0x0200, /* debug locking */
114 #define DBG(SC, FL, PRINT) do { } while (0)
116 #endif /* EN_DEBUG */
118 #include "opt_inet.h"
119 #include "opt_natm.h"
127 #include <sys/param.h>
128 #include <sys/systm.h>
130 #include <sys/queue.h>
131 #include <sys/sockio.h>
132 #include <sys/socket.h>
133 #include <sys/mbuf.h>
134 #include <sys/endian.h>
135 #include <sys/stdint.h>
136 #include <sys/lock.h>
137 #include <sys/mutex.h>
138 #include <sys/condvar.h>
142 #include <net/if_media.h>
143 #include <net/if_atm.h>
145 #if defined(INET) || defined(INET6)
146 #include <netinet/in.h>
147 #include <netinet/if_atm.h>
151 #include <netnatm/natm.h>
155 #include <machine/bus.h>
156 #include <sys/rman.h>
157 #include <sys/module.h>
158 #include <sys/sysctl.h>
159 #include <sys/malloc.h>
160 #include <machine/resource.h>
161 #include <dev/utopia/utopia.h>
162 #include <dev/en/midwayreg.h>
163 #include <dev/en/midwayvar.h>
171 #define EN_TXHIWAT (64 * 1024) /* max 64 KB waiting to be DMAd out */
174 SYSCTL_DECL(_hw_atm);
179 * The plan is indexed by the number of words to transfer.
180 * The maximum index is 15 for 60 words.
183 uint8_t bcode; /* code */
184 uint8_t divshift; /* byte divisor */
187 static const struct en_dmatab en_dmaplan[] = {
188 { 0, 0 }, /* 0 */ { MIDDMA_WORD, 2}, /* 1 */
189 { MIDDMA_2WORD, 3}, /* 2 */ { MIDDMA_WORD, 2}, /* 3 */
190 { MIDDMA_4WORD, 4}, /* 4 */ { MIDDMA_WORD, 2}, /* 5 */
191 { MIDDMA_2WORD, 3}, /* 6 */ { MIDDMA_WORD, 2}, /* 7 */
192 { MIDDMA_8WORD, 5}, /* 8 */ { MIDDMA_WORD, 2}, /* 9 */
193 { MIDDMA_2WORD, 3}, /* 10 */ { MIDDMA_WORD, 2}, /* 11 */
194 { MIDDMA_4WORD, 4}, /* 12 */ { MIDDMA_WORD, 2}, /* 13 */
195 { MIDDMA_2WORD, 3}, /* 14 */ { MIDDMA_WORD, 2}, /* 15 */
196 { MIDDMA_16WORD,6}, /* 16 */
203 int en_dump(int unit, int level);
204 int en_dumpmem(int,int,int);
206 static void en_close_finish(struct en_softc *sc, struct en_vcc *vc);
208 #define EN_LOCK(SC) do { \
209 DBG(SC, LOCK, ("ENLOCK %d\n", __LINE__)); \
210 mtx_lock(&sc->en_mtx); \
212 #define EN_UNLOCK(SC) do { \
213 DBG(SC, LOCK, ("ENUNLOCK %d\n", __LINE__)); \
214 mtx_unlock(&sc->en_mtx); \
216 #define EN_CHECKLOCK(sc) mtx_assert(&sc->en_mtx, MA_OWNED)
219 * While a transmit mbuf is waiting to get transmit DMA resources we
220 * need to keep some information with it. We don't want to allocate
221 * additional memory for this so we stuff it into free fields in the
222 * mbuf packet header. Neither the checksum fields nor the rcvif field are used
225 #define TX_AAL5 0x1 /* transmit AAL5 PDU */
226 #define TX_HAS_TBD 0x2 /* TBD did fit into mbuf */
227 #define TX_HAS_PAD 0x4 /* padding did fit into mbuf */
228 #define TX_HAS_PDU 0x8 /* PDU trailer did fit into mbuf */
230 #define MBUF_SET_TX(M, VCI, FLAGS, DATALEN, PAD, MAP) do { \
231 (M)->m_pkthdr.csum_data = (VCI) | ((FLAGS) << MID_VCI_BITS); \
232 (M)->m_pkthdr.csum_flags = ((DATALEN) & 0xffff) | \
233 ((PAD & 0x3f) << 16); \
234 (M)->m_pkthdr.rcvif = (void *)(MAP); \
237 #define MBUF_GET_TX(M, VCI, FLAGS, DATALEN, PAD, MAP) do { \
238 (VCI) = (M)->m_pkthdr.csum_data & ((1 << MID_VCI_BITS) - 1); \
239 (FLAGS) = ((M)->m_pkthdr.csum_data >> MID_VCI_BITS) & 0xf; \
240 (DATALEN) = (M)->m_pkthdr.csum_flags & 0xffff; \
241 (PAD) = ((M)->m_pkthdr.csum_flags >> 16) & 0x3f; \
242 (MAP) = (void *)((M)->m_pkthdr.rcvif); \
246 #define EN_WRAPADD(START, STOP, CUR, VAL) do { \
247 (CUR) = (CUR) + (VAL); \
248 if ((CUR) >= (STOP)) \
249 (CUR) = (START) + ((CUR) - (STOP)); \
252 #define WORD_IDX(START, X) (((X) - (START)) / sizeof(uint32_t))
254 #define SETQ_END(SC, VAL) ((SC)->is_adaptec ? \
255 ((VAL) | (MID_DMA_END >> 4)) : \
256 ((VAL) | (MID_DMA_END)))
259 * The dtq and drq members are set for each END entry in the corresponding
260 * card queue entry. It is used to find out, when a buffer has been
261 * finished DMAing and can be freed.
263 * We store sc->dtq and sc->drq data in the following format...
264 * the 0x80000 ensures we != 0
266 #define EN_DQ_MK(SLOT, LEN) (((SLOT) << 20) | (LEN) | (0x80000))
267 #define EN_DQ_SLOT(X) ((X) >> 20)
268 #define EN_DQ_LEN(X) ((X) & 0x3ffff)
273 static uma_zone_t en_vcc_zone;
275 /***********************************************************************/
278 * en_read{x}: read a word from the card. These are the only functions
279 * that read from the card.
281 static __inline uint32_t
282 en_readx(struct en_softc *sc, uint32_t r)
287 if (r > MID_MAXOFF || (r % 4))
288 panic("en_read out of range, r=0x%x", r);
290 v = bus_space_read_4(sc->en_memt, sc->en_base, r);
294 static __inline uint32_t
295 en_read(struct en_softc *sc, uint32_t r)
300 if (r > MID_MAXOFF || (r % 4))
301 panic("en_read out of range, r=0x%x", r);
303 v = bus_space_read_4(sc->en_memt, sc->en_base, r);
304 DBG(sc, REG, ("en_read(%#x) -> %08x", r, v));
309 * en_write: write a word to the card. This is the only function that
310 * writes to the card.
313 en_write(struct en_softc *sc, uint32_t r, uint32_t v)
316 if (r > MID_MAXOFF || (r % 4))
317 panic("en_write out of range, r=0x%x", r);
319 DBG(sc, REG, ("en_write(%#x) <- %08x", r, v));
320 bus_space_write_4(sc->en_memt, sc->en_base, r, v);
324 * en_k2sz: convert KBytes to a size parameter (a log2)
337 case 128: return (7);
343 #define en_log2(X) en_k2sz(X)
346 * en_b2sz: convert a DMA burst code to its byte size
352 case MIDDMA_WORD: return (1*4);
354 case MIDDMA_2WORD: return (2*4);
356 case MIDDMA_4WORD: return (4*4);
358 case MIDDMA_8WORD: return (8*4);
359 case MIDDMA_16WMAYBE:
360 case MIDDMA_16WORD: return (16*4);
368 * en_sz2b: convert a burst size (bytes) to DMA burst code
374 case 1*4: return (MIDDMA_WORD);
375 case 2*4: return (MIDDMA_2WORD);
376 case 4*4: return (MIDDMA_4WORD);
377 case 8*4: return (MIDDMA_8WORD);
378 case 16*4: return (MIDDMA_16WORD);
390 en_dump_packet(struct en_softc *sc, struct mbuf *m)
392 int plen = m->m_pkthdr.len;
398 if_printf(&sc->ifatm.ifnet, "packet len=%d", plen);
401 ptr = mtod(m, u_char *);
402 for (len = 0; len < m->m_len; len++, pos++, ptr++) {
407 printf(" %02x", *ptr);
413 printf("sum of m_len=%u\n", totlen);
417 /*********************************************************************/
423 * Map constructor for a MAP.
425 * This is called each time when a map is allocated
426 * from the pool and about to be returned to the user. Here we actually
427 * allocate the map if there isn't one. The problem is that we may fail
428 * to allocate the DMA map yet have no means to signal this error. Therefor
429 * when allocating a map, the call must check that there is a map. An
430 * additional problem is, that i386 maps will be NULL, yet are ok and must
431 * be freed so let's use a flag to signal allocation.
433 * Caveat: we have no way to know that we are called from an interrupt context
434 * here. We rely on the fact, that bus_dmamap_create uses M_NOWAIT in all
437 * LOCK: any, not needed
440 en_map_ctor(void *mem, int size, void *arg, int flags)
442 struct en_softc *sc = arg;
443 struct en_map *map = mem;
446 err = bus_dmamap_create(sc->txtag, 0, &map->map);
448 if_printf(&sc->ifatm.ifnet, "cannot create DMA map %d\n", err);
451 map->flags = ENMAP_ALLOC;
459 * Called when a map is disposed into the zone. If the map is loaded, unload
462 * LOCK: any, not needed
465 en_map_dtor(void *mem, int size, void *arg)
467 struct en_map *map = mem;
469 if (map->flags & ENMAP_LOADED) {
470 bus_dmamap_unload(map->sc->txtag, map->map);
471 map->flags &= ~ENMAP_LOADED;
478 * This is called each time a map is returned from the zone to the system.
479 * Get rid of the dmamap here.
481 * LOCK: any, not needed
484 en_map_fini(void *mem, int size)
486 struct en_map *map = mem;
488 bus_dmamap_destroy(map->sc->txtag, map->map);
491 /*********************************************************************/
497 * Argument structure to load a transmit DMA map
503 u_int chan; /* transmit channel */
504 u_int datalen; /* length of user data */
506 u_int wait; /* return: out of resources */
510 * TX DMA map loader helper. This function is the callback when the map
511 * is loaded. It should fill the DMA segment descriptors into the hardware.
513 * LOCK: locked, needed
516 en_txdma_load(void *uarg, bus_dma_segment_t *segs, int nseg, bus_size_t mapsize,
519 struct txarg *tx = uarg;
520 struct en_softc *sc = tx->sc;
521 struct en_txslot *slot = &sc->txslot[tx->chan];
522 uint32_t cur; /* on-card buffer position (bytes offset) */
523 uint32_t dtq; /* on-card queue position (byte offset) */
524 uint32_t last_dtq; /* last DTQ we have written */
526 u_int free; /* free queue entries on card */
527 u_int needalign, cnt;
528 bus_size_t rest; /* remaining bytes in current segment */
530 bus_dma_segment_t *s;
531 uint32_t count, bcode;
541 last_dtq = 0; /* make gcc happy */
544 * Local macro to add an entry to the transmit DMA area. If there
545 * are no entries left, return. Save the byte offset of the entry
546 * in last_dtq for later use.
548 #define PUT_DTQ_ENTRY(ENI, BCODE, COUNT, ADDR) \
550 EN_COUNT(sc->stats.txdtqout); \
555 en_write(sc, dtq + 0, (ENI || !sc->is_adaptec) ? \
556 MID_MK_TXQ_ENI(COUNT, tx->chan, 0, BCODE) : \
557 MID_MK_TXQ_ADP(COUNT, tx->chan, 0, BCODE)); \
558 en_write(sc, dtq + 4, ADDR); \
560 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, dtq, 8); \
564 * Local macro to generate a DMA entry to DMA cnt bytes. Updates
565 * the current buffer byte offset accordingly.
567 #define DO_DTQ(TYPE) do { \
569 EN_WRAPADD(slot->start, slot->stop, cur, cnt); \
570 DBG(sc, TX, ("tx%d: "TYPE" %u bytes, %ju left, cur %#x", \
571 tx->chan, cnt, (uintmax_t)rest, cur)); \
573 PUT_DTQ_ENTRY(1, bcode, count, addr); \
578 if (!(tx->flags & TX_HAS_TBD)) {
580 * Prepend the TBD - it did not fit into the first mbuf
582 tmp = MID_TBD_MK1((tx->flags & TX_AAL5) ?
583 MID_TBD_AAL5 : MID_TBD_NOAAL5,
584 sc->vccs[tx->vci]->txspeed,
585 tx->m->m_pkthdr.len / MID_ATMDATASZ);
586 en_write(sc, cur, tmp);
587 EN_WRAPADD(slot->start, slot->stop, cur, 4);
589 tmp = MID_TBD_MK2(tx->vci, 0, 0);
590 en_write(sc, cur, tmp);
591 EN_WRAPADD(slot->start, slot->stop, cur, 4);
593 /* update DMA address */
594 PUT_DTQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
597 for (i = 0, s = segs; i < nseg; i++, s++) {
601 if (sc->is_adaptec) {
602 /* adaptec card - simple */
604 /* advance the on-card buffer pointer */
605 EN_WRAPADD(slot->start, slot->stop, cur, rest);
606 DBG(sc, TX, ("tx%d: adp %ju bytes %#jx (cur now 0x%x)",
607 tx->chan, (uintmax_t)rest, (uintmax_t)addr, cur));
609 PUT_DTQ_ENTRY(0, 0, rest, addr);
615 * do we need to do a DMA op to align to the maximum
616 * burst? Note, that we are alway 32-bit aligned.
619 (needalign = (addr & sc->bestburstmask)) != 0) {
620 /* compute number of bytes, words and code */
621 cnt = sc->bestburstlen - needalign;
624 count = cnt / sizeof(uint32_t);
625 if (sc->noalbursts) {
628 bcode = en_dmaplan[count].bcode;
629 count = cnt >> en_dmaplan[count].divshift;
634 /* do we need to do a max-sized burst? */
635 if (rest >= sc->bestburstlen) {
636 count = rest >> sc->bestburstshift;
637 cnt = count << sc->bestburstshift;
638 bcode = sc->bestburstcode;
642 /* do we need to do a cleanup burst? */
645 count = rest / sizeof(uint32_t);
646 if (sc->noalbursts) {
649 bcode = en_dmaplan[count].bcode;
650 count = cnt >> en_dmaplan[count].divshift;
656 KASSERT (tx->flags & TX_HAS_PAD, ("PDU not padded"));
658 if ((tx->flags & TX_AAL5) && !(tx->flags & TX_HAS_PDU)) {
660 * Append the AAL5 PDU trailer
662 tmp = MID_PDU_MK1(0, 0, tx->datalen);
663 en_write(sc, cur, tmp);
664 EN_WRAPADD(slot->start, slot->stop, cur, 4);
666 en_write(sc, cur, 0);
667 EN_WRAPADD(slot->start, slot->stop, cur, 4);
669 /* update DMA address */
670 PUT_DTQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
673 /* record the end for the interrupt routine */
674 sc->dtq[MID_DTQ_A2REG(last_dtq)] =
675 EN_DQ_MK(tx->chan, tx->m->m_pkthdr.len);
677 /* set the end flag in the last descriptor */
678 en_write(sc, last_dtq + 0, SETQ_END(sc, en_read(sc, last_dtq + 0)));
689 en_write(sc, MID_DMA_WRTX, MID_DTQ_A2REG(sc->dtq_us));
693 * en_txdma: start transmit DMA on the given channel, if possible
695 * This is called from two places: when we got new packets from the upper
696 * layer or when we found that buffer space has freed up during interrupt
699 * LOCK: locked, needed
702 en_txdma(struct en_softc *sc, struct en_txslot *slot)
710 DBG(sc, TX, ("tx%td: starting ...", slot - sc->txslot));
712 bzero(&tx, sizeof(tx));
713 tx.chan = slot - sc->txslot;
717 * get an mbuf waiting for DMA
719 _IF_DEQUEUE(&slot->q, tx.m);
721 DBG(sc, TX, ("tx%td: ...done!", slot - sc->txslot));
724 MBUF_GET_TX(tx.m, tx.vci, tx.flags, tx.datalen, pad, map);
727 * note: don't use the entire buffer space. if WRTX becomes equal
728 * to RDTX, the transmitter stops assuming the buffer is empty! --kjc
730 if (tx.m->m_pkthdr.len >= slot->bfree) {
731 EN_COUNT(sc->stats.txoutspace);
732 DBG(sc, TX, ("tx%td: out of transmit space", slot - sc->txslot));
737 if (!(tx.flags & TX_HAS_PAD)) {
739 /* Append the padding buffer */
740 (void)m_length(tx.m, &lastm);
741 lastm->m_next = sc->padbuf;
742 sc->padbuf->m_len = pad;
744 tx.flags |= TX_HAS_PAD;
748 * Try to load that map
750 error = bus_dmamap_load_mbuf(sc->txtag, map->map, tx.m,
751 en_txdma_load, &tx, BUS_DMA_NOWAIT);
754 lastm->m_next = NULL;
757 if_printf(&sc->ifatm.ifnet, "loading TX map failed %d\n",
761 map->flags |= ENMAP_LOADED;
763 /* probably not enough space */
764 bus_dmamap_unload(map->sc->txtag, map->map);
765 map->flags &= ~ENMAP_LOADED;
768 DBG(sc, TX, ("tx%td: out of transmit DTQs", slot - sc->txslot));
772 EN_COUNT(sc->stats.launch);
773 sc->ifatm.ifnet.if_opackets++;
775 sc->vccs[tx.vci]->opackets++;
776 sc->vccs[tx.vci]->obytes += tx.datalen;
779 if (sc->ifatm.ifnet.if_bpf != NULL) {
781 * adjust the top of the mbuf to skip the TBD if present
782 * before passing the packet to bpf.
783 * Also remove padding and the PDU trailer. Assume both of
784 * them to be in the same mbuf. pktlen, m_len and m_data
785 * are not needed anymore so we can change them.
787 if (tx.flags & TX_HAS_TBD) {
788 tx.m->m_data += MID_TBD_SIZE;
789 tx.m->m_len -= MID_TBD_SIZE;
791 tx.m->m_pkthdr.len = m_length(tx.m, &lastm);
792 if (tx.m->m_pkthdr.len > tx.datalen) {
793 lastm->m_len -= tx.m->m_pkthdr.len - tx.datalen;
794 tx.m->m_pkthdr.len = tx.datalen;
797 BPF_MTAP(&sc->ifatm.ifnet, tx.m);
802 * do some housekeeping and get the next packet
804 slot->bfree -= tx.m->m_pkthdr.len;
805 _IF_ENQUEUE(&slot->indma, tx.m);
810 * error handling. This is jumped to when we just want to drop
811 * the packet. Must be unlocked here.
815 uma_zfree(sc->map_zone, map);
817 slot->mbsize -= tx.m->m_pkthdr.len;
824 _IF_PREPEND(&slot->q, tx.m);
828 * Create a copy of a single mbuf. It can have either internal or
829 * external data, it may have a packet header. External data is really
830 * copied, so the new buffer is writeable.
832 * LOCK: any, not needed
835 copy_mbuf(struct mbuf *m)
839 MGET(new, M_TRYWAIT, MT_DATA);
843 if (m->m_flags & M_PKTHDR) {
844 M_MOVE_PKTHDR(new, m);
845 if (m->m_len > MHLEN) {
846 MCLGET(new, M_TRYWAIT);
847 if ((m->m_flags & M_EXT) == 0) {
853 if (m->m_len > MLEN) {
854 MCLGET(new, M_TRYWAIT);
855 if ((m->m_flags & M_EXT) == 0) {
862 bcopy(m->m_data, new->m_data, m->m_len);
863 new->m_len = m->m_len;
864 new->m_flags &= ~M_RDONLY;
870 * This function is called when we have an ENI adapter. It fixes the
871 * mbuf chain, so that all addresses and lengths are 4 byte aligned.
872 * The overall length is already padded to multiple of cells plus the
873 * TBD so this must always succeed. The routine can fail, when it
874 * needs to copy an mbuf (this may happen if an mbuf is readonly).
876 * We assume here, that aligning the virtual addresses to 4 bytes also
877 * aligns the physical addresses.
879 * LOCK: locked, needed
882 en_fix_mchain(struct en_softc *sc, struct mbuf *m0, u_int *pad)
884 struct mbuf **prev = &m0;
891 d = mtod(m, u_char *);
892 if ((off = (uintptr_t)d % sizeof(uint32_t)) != 0) {
893 EN_COUNT(sc->stats.mfixaddr);
895 bcopy(d, d - off, m->m_len);
898 if ((new = copy_mbuf(m)) == NULL) {
899 EN_COUNT(sc->stats.mfixfail);
903 new->m_next = m_free(m);
908 if ((off = m->m_len % sizeof(uint32_t)) != 0) {
909 EN_COUNT(sc->stats.mfixlen);
910 if (!M_WRITABLE(m)) {
911 if ((new = copy_mbuf(m)) == NULL) {
912 EN_COUNT(sc->stats.mfixfail);
916 new->m_next = m_free(m);
919 d = mtod(m, u_char *) + m->m_len;
922 while (m->m_next && m->m_next->m_len == 0)
923 m->m_next = m_free(m->m_next);
925 if (m->m_next == NULL) {
927 KASSERT(*pad > 0, ("no padding space"));
930 *d++ = *mtod(m->m_next, u_char *);
947 * en_start: start transmitting the next packet that needs to go out
948 * if there is one. We take off all packets from the interface's queue and
949 * put them into the channels queue.
951 * Here we also prepend the transmit packet descriptor and append the padding
952 * and (for aal5) the PDU trailer. This is different from the original driver:
953 * we assume, that allocating one or two additional mbufs is actually cheaper
954 * than all this algorithmic fiddling we would need otherwise.
956 * While the packet is on the channels wait queue we use the csum_* fields
957 * in the packet header to hold the original datalen, the AAL5 flag and the
958 * VCI. The packet length field in the header holds the needed buffer space.
959 * This may actually be more than the length of the current mbuf chain (when
960 * one or more of TBD, padding and PDU do not fit).
962 * LOCK: unlocked, needed
965 en_start(struct ifnet *ifp)
967 struct en_softc *sc = (struct en_softc *)ifp->if_softc;
968 struct mbuf *m, *lastm;
969 struct atm_pseudohdr *ap;
970 u_int pad; /* 0-bytes to pad at PDU end */
971 u_int datalen; /* length of user data */
972 u_int vci; /* the VCI we are transmitting on */
978 struct en_txslot *tx;
981 IF_DEQUEUE(&ifp->if_snd, m);
987 ap = mtod(m, struct atm_pseudohdr *);
988 vci = ATM_PH_VCI(ap);
990 if (ATM_PH_VPI(ap) != 0 || vci >= MID_N_VC ||
991 (vc = sc->vccs[vci]) == NULL ||
992 (vc->vflags & VCC_CLOSE_RX)) {
993 DBG(sc, TX, ("output vpi=%u, vci=%u -- drop",
994 ATM_PH_VPI(ap), vci));
998 if (vc->vcc.aal == ATMIO_AAL_5)
1000 m_adj(m, sizeof(struct atm_pseudohdr));
1003 * (re-)calculate size of packet (in bytes)
1005 m->m_pkthdr.len = datalen = m_length(m, &lastm);
1008 * computing how much padding we need on the end of the mbuf,
1009 * then see if we can put the TBD at the front of the mbuf
1010 * where the link header goes (well behaved protocols will
1011 * reserve room for us). Last, check if room for PDU tail.
1013 if (flags & TX_AAL5)
1014 m->m_pkthdr.len += MID_PDU_SIZE;
1015 m->m_pkthdr.len = roundup(m->m_pkthdr.len, MID_ATMDATASZ);
1016 pad = m->m_pkthdr.len - datalen;
1017 if (flags & TX_AAL5)
1018 pad -= MID_PDU_SIZE;
1019 m->m_pkthdr.len += MID_TBD_SIZE;
1021 DBG(sc, TX, ("txvci%d: buflen=%u datalen=%u lead=%d trail=%d",
1022 vci, m->m_pkthdr.len, datalen, (int)M_LEADINGSPACE(m),
1023 (int)M_TRAILINGSPACE(lastm)));
1026 * From here on we need access to sc
1031 * Allocate a map. We do this here rather then in en_txdma,
1032 * because en_txdma is also called from the interrupt handler
1033 * and we are going to have a locking problem then. We must
1034 * use NOWAIT here, because the ip_output path holds various
1037 map = uma_zalloc_arg(sc->map_zone, sc, M_NOWAIT);
1039 /* drop that packet */
1040 EN_COUNT(sc->stats.txnomap);
1046 if ((ifp->if_flags & IFF_RUNNING) == 0) {
1048 uma_zfree(sc->map_zone, map);
1054 * Look, whether we can prepend the TBD (8 byte)
1056 if (M_WRITABLE(m) && M_LEADINGSPACE(m) >= MID_TBD_SIZE) {
1057 tbd[0] = htobe32(MID_TBD_MK1((flags & TX_AAL5) ?
1058 MID_TBD_AAL5 : MID_TBD_NOAAL5,
1059 vc->txspeed, m->m_pkthdr.len / MID_ATMDATASZ));
1060 tbd[1] = htobe32(MID_TBD_MK2(vci, 0, 0));
1062 m->m_data -= MID_TBD_SIZE;
1063 bcopy(tbd, m->m_data, MID_TBD_SIZE);
1064 m->m_len += MID_TBD_SIZE;
1065 flags |= TX_HAS_TBD;
1069 * Check whether the padding fits (must be writeable -
1070 * we pad with zero).
1072 if (M_WRITABLE(lastm) && M_TRAILINGSPACE(lastm) >= pad) {
1073 bzero(lastm->m_data + lastm->m_len, pad);
1074 lastm->m_len += pad;
1075 flags |= TX_HAS_PAD;
1077 if ((flags & TX_AAL5) &&
1078 M_TRAILINGSPACE(lastm) > MID_PDU_SIZE) {
1079 pdu[0] = htobe32(MID_PDU_MK1(0, 0, datalen));
1081 bcopy(pdu, lastm->m_data + lastm->m_len,
1083 lastm->m_len += MID_PDU_SIZE;
1084 flags |= TX_HAS_PDU;
1088 if (!sc->is_adaptec &&
1089 (m = en_fix_mchain(sc, m, &pad)) == NULL) {
1091 uma_zfree(sc->map_zone, map);
1096 * get assigned channel (will be zero unless txspeed is set)
1100 if (m->m_pkthdr.len > EN_TXSZ * 1024) {
1101 DBG(sc, TX, ("tx%zu: packet larger than xmit buffer "
1102 "(%d > %d)\n", tx - sc->txslot, m->m_pkthdr.len,
1106 uma_zfree(sc->map_zone, map);
1110 if (tx->mbsize > EN_TXHIWAT) {
1111 EN_COUNT(sc->stats.txmbovr);
1112 DBG(sc, TX, ("tx%d: buffer space shortage",
1116 uma_zfree(sc->map_zone, map);
1121 tx->mbsize += m->m_pkthdr.len;
1123 DBG(sc, TX, ("tx%zu: VCI=%d, speed=0x%x, buflen=%d, mbsize=%d",
1124 tx - sc->txslot, vci, sc->vccs[vci]->txspeed,
1125 m->m_pkthdr.len, tx->mbsize));
1127 MBUF_SET_TX(m, vci, flags, datalen, pad, map);
1129 _IF_ENQUEUE(&tx->q, m);
1137 /*********************************************************************/
1143 * en_loadvc: load a vc tab entry from a slot
1145 * LOCK: locked, needed
1148 en_loadvc(struct en_softc *sc, struct en_vcc *vc)
1150 uint32_t reg = en_read(sc, MID_VC(vc->vcc.vci));
1152 reg = MIDV_SETMODE(reg, MIDV_TRASH);
1153 en_write(sc, MID_VC(vc->vcc.vci), reg);
1156 /* no need to set CRC */
1158 /* read pointer = 0, desc. start = 0 */
1159 en_write(sc, MID_DST_RP(vc->vcc.vci), 0);
1160 /* write pointer = 0 */
1161 en_write(sc, MID_WP_ST_CNT(vc->vcc.vci), 0);
1162 /* set mode, size, loc */
1163 en_write(sc, MID_VC(vc->vcc.vci), vc->rxslot->mode);
1165 vc->rxslot->cur = vc->rxslot->start;
1167 DBG(sc, VC, ("rx%d: assigned to VCI %d", vc->rxslot - sc->rxslot,
1172 * Open the given vcc.
1174 * LOCK: unlocked, needed
1177 en_open_vcc(struct en_softc *sc, struct atmio_openvcc *op)
1179 uint32_t oldmode, newmode;
1180 struct en_rxslot *slot;
1184 DBG(sc, IOCTL, ("enable vpi=%d, vci=%d, flags=%#x",
1185 op->param.vpi, op->param.vci, op->param.flags));
1187 if (op->param.vpi != 0 || op->param.vci >= MID_N_VC)
1190 vc = uma_zalloc(en_vcc_zone, M_NOWAIT | M_ZERO);
1196 if (sc->vccs[op->param.vci] != NULL) {
1201 /* find a free receive slot */
1202 for (slot = sc->rxslot; slot < &sc->rxslot[sc->en_nrx]; slot++)
1203 if (slot->vcc == NULL)
1205 if (slot == &sc->rxslot[sc->en_nrx]) {
1211 vc->rxhand = op->rxhand;
1212 vc->vcc = op->param;
1214 oldmode = slot->mode;
1215 newmode = (op->param.aal == ATMIO_AAL_5) ? MIDV_AAL5 : MIDV_NOAAL;
1216 slot->mode = MIDV_SETMODE(oldmode, newmode);
1219 KASSERT (_IF_QLEN(&slot->indma) == 0 && _IF_QLEN(&slot->q) == 0,
1220 ("en_rxctl: left over mbufs on enable slot=%tu",
1221 vc->rxslot - sc->rxslot));
1224 vc->txslot = sc->txslot;
1225 vc->txslot->nref++; /* bump reference count */
1227 en_loadvc(sc, vc); /* does debug printf for us */
1229 /* don't free below */
1230 sc->vccs[vc->vcc.vci] = vc;
1236 uma_zfree(en_vcc_zone, vc);
1246 en_close_finish(struct en_softc *sc, struct en_vcc *vc)
1249 if (vc->rxslot != NULL)
1250 vc->rxslot->vcc = NULL;
1252 DBG(sc, VC, ("vci: %u free (%p)", vc->vcc.vci, vc));
1254 sc->vccs[vc->vcc.vci] = NULL;
1255 uma_zfree(en_vcc_zone, vc);
1260 * LOCK: unlocked, needed
1263 en_close_vcc(struct en_softc *sc, struct atmio_closevcc *cl)
1265 uint32_t oldmode, newmode;
1269 DBG(sc, IOCTL, ("disable vpi=%d, vci=%d", cl->vpi, cl->vci));
1271 if (cl->vpi != 0 || cl->vci >= MID_N_VC)
1275 if ((vc = sc->vccs[cl->vci]) == NULL) {
1283 if (vc->rxslot == NULL) {
1287 if (vc->vflags & VCC_DRAIN) {
1292 oldmode = en_read(sc, MID_VC(cl->vci));
1293 newmode = MIDV_SETMODE(oldmode, MIDV_TRASH) & ~MIDV_INSERVICE;
1294 en_write(sc, MID_VC(cl->vci), (newmode | (oldmode & MIDV_INSERVICE)));
1296 /* halt in tracks, be careful to preserve inservice bit */
1298 vc->rxslot->mode = newmode;
1302 /* if stuff is still going on we are going to have to drain it out */
1303 if (_IF_QLEN(&vc->rxslot->indma) == 0 &&
1304 _IF_QLEN(&vc->rxslot->q) == 0 &&
1305 (vc->vflags & VCC_SWSL) == 0) {
1306 en_close_finish(sc, vc);
1310 vc->vflags |= VCC_DRAIN;
1311 DBG(sc, IOCTL, ("VCI %u now draining", cl->vci));
1313 if (vc->vcc.flags & ATMIO_FLAG_ASYNC)
1316 vc->vflags |= VCC_CLOSE_RX;
1317 while ((sc->ifatm.ifnet.if_flags & IFF_RUNNING) &&
1318 (vc->vflags & VCC_DRAIN))
1319 cv_wait(&sc->cv_close, &sc->en_mtx);
1321 en_close_finish(sc, vc);
1322 if (!(sc->ifatm.ifnet.if_flags & IFF_RUNNING)) {
1333 /*********************************************************************/
1335 * starting/stopping the card
1339 * en_reset_ul: reset the board, throw away work in progress.
1340 * must en_init to recover.
1342 * LOCK: locked, needed
1345 en_reset_ul(struct en_softc *sc)
1349 struct en_rxslot *rx;
1352 if_printf(&sc->ifatm.ifnet, "reset\n");
1353 sc->ifatm.ifnet.if_flags &= ~IFF_RUNNING;
1355 if (sc->en_busreset)
1356 sc->en_busreset(sc);
1357 en_write(sc, MID_RESID, 0x0); /* reset hardware */
1360 * recv: dump any mbufs we are dma'ing into, if DRAINing, then a reset
1361 * will free us! Don't release the rxslot from the channel.
1363 for (lcv = 0 ; lcv < MID_N_VC ; lcv++) {
1364 if (sc->vccs[lcv] == NULL)
1366 rx = sc->vccs[lcv]->rxslot;
1369 _IF_DEQUEUE(&rx->indma, m);
1372 map = (void *)m->m_pkthdr.rcvif;
1373 uma_zfree(sc->map_zone, map);
1377 _IF_DEQUEUE(&rx->q, m);
1382 sc->vccs[lcv]->vflags = 0;
1386 * xmit: dump everything
1388 for (lcv = 0 ; lcv < EN_NTX ; lcv++) {
1390 _IF_DEQUEUE(&sc->txslot[lcv].indma, m);
1393 map = (void *)m->m_pkthdr.rcvif;
1394 uma_zfree(sc->map_zone, map);
1398 _IF_DEQUEUE(&sc->txslot[lcv].q, m);
1401 map = (void *)m->m_pkthdr.rcvif;
1402 uma_zfree(sc->map_zone, map);
1405 sc->txslot[lcv].mbsize = 0;
1409 * Unstop all waiters
1411 cv_broadcast(&sc->cv_close);
1415 * en_reset: reset the board, throw away work in progress.
1416 * must en_init to recover.
1418 * LOCK: unlocked, needed
1420 * Use en_reset_ul if you alreay have the lock
1423 en_reset(struct en_softc *sc)
1432 * en_init: init board and sync the card with the data in the softc.
1434 * LOCK: locked, needed
1437 en_init(struct en_softc *sc)
1442 if ((sc->ifatm.ifnet.if_flags & IFF_UP) == 0) {
1443 DBG(sc, INIT, ("going down"));
1444 en_reset(sc); /* to be safe */
1448 DBG(sc, INIT, ("going up"));
1449 sc->ifatm.ifnet.if_flags |= IFF_RUNNING; /* enable */
1451 if (sc->en_busreset)
1452 sc->en_busreset(sc);
1453 en_write(sc, MID_RESID, 0x0); /* reset */
1456 bus_space_set_region_4(sc->en_memt, sc->en_base,
1457 MID_RAMOFF, 0, sc->en_obmemsz / 4);
1460 * init obmem data structures: vc tab, dma q's, slist.
1462 * note that we set drq_free/dtq_free to one less than the total number
1463 * of DTQ/DRQs present. we do this because the card uses the condition
1464 * (drq_chip == drq_us) to mean "list is empty"... but if you allow the
1465 * circular list to be completely full then (drq_chip == drq_us) [i.e.
1466 * the drq_us pointer will wrap all the way around]. by restricting
1467 * the number of active requests to (N - 1) we prevent the list from
1468 * becoming completely full. note that the card will sometimes give
1469 * us an interrupt for a DTQ/DRQ we have already processes... this helps
1470 * keep that interrupt from messing us up.
1472 bzero(&sc->drq, sizeof(sc->drq));
1473 sc->drq_free = MID_DRQ_N - 1;
1474 sc->drq_chip = MID_DRQ_REG2A(en_read(sc, MID_DMA_RDRX));
1475 en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_chip));
1476 sc->drq_us = sc->drq_chip;
1478 bzero(&sc->dtq, sizeof(sc->dtq));
1479 sc->dtq_free = MID_DTQ_N - 1;
1480 sc->dtq_chip = MID_DTQ_REG2A(en_read(sc, MID_DMA_RDTX));
1481 en_write(sc, MID_DMA_WRTX, MID_DRQ_A2REG(sc->dtq_chip));
1482 sc->dtq_us = sc->dtq_chip;
1484 sc->hwslistp = MID_SL_REG2A(en_read(sc, MID_SERV_WRITE));
1485 sc->swsl_size = sc->swsl_head = sc->swsl_tail = 0;
1487 DBG(sc, INIT, ("drq free/chip: %d/0x%x, dtq free/chip: %d/0x%x, "
1488 "hwslist: 0x%x", sc->drq_free, sc->drq_chip, sc->dtq_free,
1489 sc->dtq_chip, sc->hwslistp));
1491 for (slot = 0 ; slot < EN_NTX ; slot++) {
1492 sc->txslot[slot].bfree = EN_TXSZ * 1024;
1493 en_write(sc, MIDX_READPTR(slot), 0);
1494 en_write(sc, MIDX_DESCSTART(slot), 0);
1495 loc = sc->txslot[slot].cur = sc->txslot[slot].start;
1496 loc = loc - MID_RAMOFF;
1497 /* mask, cvt to words */
1498 loc = (loc & ~((EN_TXSZ * 1024) - 1)) >> 2;
1500 loc = loc >> MIDV_LOCTOPSHFT;
1501 en_write(sc, MIDX_PLACE(slot), MIDX_MKPLACE(en_k2sz(EN_TXSZ),
1503 DBG(sc, INIT, ("tx%d: place 0x%x", slot,
1504 (u_int)en_read(sc, MIDX_PLACE(slot))));
1507 for (vc = 0; vc < MID_N_VC; vc++)
1508 if (sc->vccs[vc] != NULL)
1509 en_loadvc(sc, sc->vccs[vc]);
1514 en_write(sc, MID_INTENA, MID_INT_TX | MID_INT_DMA_OVR | MID_INT_IDENT |
1515 MID_INT_LERR | MID_INT_DMA_ERR | MID_INT_DMA_RX | MID_INT_DMA_TX |
1516 MID_INT_SERVICE | MID_INT_SUNI | MID_INT_STATS);
1517 en_write(sc, MID_MAST_CSR, MID_SETIPL(sc->ipl) | MID_MCSR_ENDMA |
1518 MID_MCSR_ENTX | MID_MCSR_ENRX);
1521 /*********************************************************************/
1526 * en_ioctl: handle ioctl requests
1528 * NOTE: if you add an ioctl to set txspeed, you should choose a new
1529 * TX channel/slot. Choose the one with the lowest sc->txslot[slot].nref
1530 * value, subtract one from sc->txslot[0].nref, add one to the
1531 * sc->txslot[slot].nref, set sc->txvc2slot[vci] = slot, and then set
1534 * LOCK: unlocked, needed
1537 en_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1539 struct en_softc *sc = (struct en_softc *)ifp->if_softc;
1540 struct ifaddr *ifa = (struct ifaddr *)data;
1541 struct ifreq *ifr = (struct ifreq *)data;
1542 struct atmio_vcctable *vtab;
1549 ifp->if_flags |= IFF_UP;
1550 #if defined(INET) || defined(INET6)
1551 if (ifa->ifa_addr->sa_family == AF_INET
1552 || ifa->ifa_addr->sa_family == AF_INET6) {
1553 if (!(ifp->if_flags & IFF_RUNNING)) {
1557 ifa->ifa_rtrequest = atm_rtrequest; /* ??? */
1562 if (!(ifp->if_flags & IFF_RUNNING)) {
1571 if (ifp->if_flags & IFF_UP) {
1572 if (!(ifp->if_flags & IFF_RUNNING))
1575 if (ifp->if_flags & IFF_RUNNING)
1583 * Set the interface MTU.
1585 if (ifr->ifr_mtu > ATMMTU) {
1589 ifp->if_mtu = ifr->ifr_mtu;
1594 error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);
1597 case SIOCATMOPENVCC: /* kernel internal use */
1598 error = en_open_vcc(sc, (struct atmio_openvcc *)data);
1601 case SIOCATMCLOSEVCC: /* kernel internal use */
1602 error = en_close_vcc(sc, (struct atmio_closevcc *)data);
1605 case SIOCATMGETVCCS: /* internal netgraph use */
1606 vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
1607 MID_N_VC, sc->vccs_open, &sc->en_mtx, 0);
1612 *(void **)data = vtab;
1615 case SIOCATMGVCCS: /* return vcc table */
1616 vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
1617 MID_N_VC, sc->vccs_open, &sc->en_mtx, 1);
1618 error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) +
1619 vtab->count * sizeof(vtab->vccs[0]));
1620 free(vtab, M_DEVBUF);
1630 /*********************************************************************/
1636 * Sysctl handler for internal statistics
1638 * LOCK: unlocked, needed
1641 en_sysctl_istats(SYSCTL_HANDLER_ARGS)
1643 struct en_softc *sc = arg1;
1647 ret = malloc(sizeof(sc->stats), M_TEMP, M_WAITOK);
1650 bcopy(&sc->stats, ret, sizeof(sc->stats));
1653 error = SYSCTL_OUT(req, ret, sizeof(sc->stats));
1659 /*********************************************************************/
1665 * Transmit interrupt handler
1667 * check for tx complete, if detected then this means that some space
1668 * has come free on the card. we must account for it and arrange to
1669 * kick the channel to life (in case it is stalled waiting on the card).
1671 * LOCK: locked, needed
1674 en_intr_tx(struct en_softc *sc, uint32_t reg)
1681 kick = 0; /* bitmask of channels to kick */
1683 for (mask = 1, chan = 0; chan < EN_NTX; chan++, mask *= 2) {
1684 if (!(reg & MID_TXCHAN(chan)))
1689 /* current read pointer */
1690 val = en_read(sc, MIDX_READPTR(chan));
1692 val = (val * sizeof(uint32_t)) + sc->txslot[chan].start;
1693 if (val > sc->txslot[chan].cur)
1694 sc->txslot[chan].bfree = val - sc->txslot[chan].cur;
1696 sc->txslot[chan].bfree = (val + (EN_TXSZ * 1024)) -
1697 sc->txslot[chan].cur;
1698 DBG(sc, INTR, ("tx%d: transmit done. %d bytes now free in "
1699 "buffer", chan, sc->txslot[chan].bfree));
1707 * check for TX DMA complete, if detected then this means
1708 * that some DTQs are now free. it also means some indma
1709 * mbufs can be freed. if we needed DTQs, kick all channels.
1711 * LOCK: locked, needed
1714 en_intr_tx_dma(struct en_softc *sc)
1724 val = en_read(sc, MID_DMA_RDTX); /* chip's current location */
1725 idx = MID_DTQ_A2REG(sc->dtq_chip); /* where we last saw chip */
1727 if (sc->need_dtqs) {
1728 kick = MID_NTX_CH - 1; /* assume power of 2, kick all! */
1729 sc->need_dtqs = 0; /* recalculated in "kick" loop below */
1730 DBG(sc, INTR, ("cleared need DTQ condition"));
1733 while (idx != val) {
1735 if ((dtq = sc->dtq[idx]) != 0) {
1736 /* don't forget to zero it out when done */
1738 slot = EN_DQ_SLOT(dtq);
1740 _IF_DEQUEUE(&sc->txslot[slot].indma, m);
1742 panic("enintr: dtqsync");
1743 map = (void *)m->m_pkthdr.rcvif;
1744 uma_zfree(sc->map_zone, map);
1747 sc->txslot[slot].mbsize -= EN_DQ_LEN(dtq);
1748 DBG(sc, INTR, ("tx%d: free %d dma bytes, mbsize now "
1749 "%d", slot, EN_DQ_LEN(dtq),
1750 sc->txslot[slot].mbsize));
1752 EN_WRAPADD(0, MID_DTQ_N, idx, 1);
1754 sc->dtq_chip = MID_DTQ_REG2A(val); /* sync softc */
1762 * LOCK: locked, needed
1765 en_intr_service(struct en_softc *sc)
1769 int need_softserv = 0;
1772 chip = MID_SL_REG2A(en_read(sc, MID_SERV_WRITE));
1774 while (sc->hwslistp != chip) {
1775 /* fetch and remove it from hardware service list */
1776 vci = en_read(sc, sc->hwslistp);
1777 EN_WRAPADD(MID_SLOFF, MID_SLEND, sc->hwslistp, 4);
1779 if ((vc = sc->vccs[vci]) == NULL ||
1780 (vc->vcc.flags & ATMIO_FLAG_NORX)) {
1781 DBG(sc, INTR, ("unexpected rx interrupt VCI %d", vci));
1782 en_write(sc, MID_VC(vci), MIDV_TRASH); /* rx off */
1786 /* remove from hwsl */
1787 en_write(sc, MID_VC(vci), vc->rxslot->mode);
1788 EN_COUNT(sc->stats.hwpull);
1790 DBG(sc, INTR, ("pulled VCI %d off hwslist", vci));
1792 /* add it to the software service list (if needed) */
1793 if ((vc->vflags & VCC_SWSL) == 0) {
1794 EN_COUNT(sc->stats.swadd);
1796 vc->vflags |= VCC_SWSL;
1797 sc->swslist[sc->swsl_tail] = vci;
1798 EN_WRAPADD(0, MID_SL_N, sc->swsl_tail, 1);
1800 DBG(sc, INTR, ("added VCI %d to swslist", vci));
1803 return (need_softserv);
1807 * Handle a receive DMA completion
1810 en_rx_drain(struct en_softc *sc, u_int drq)
1812 struct en_rxslot *slot;
1815 struct atm_pseudohdr ah;
1817 slot = &sc->rxslot[EN_DQ_SLOT(drq)];
1819 m = NULL; /* assume "JK" trash DMA */
1820 if (EN_DQ_LEN(drq) != 0) {
1821 _IF_DEQUEUE(&slot->indma, m);
1822 KASSERT(m != NULL, ("drqsync: %s: lost mbuf in slot %zu!",
1823 sc->ifatm.ifnet.if_xname, slot - sc->rxslot));
1824 uma_zfree(sc->map_zone, (struct en_map *)m->m_pkthdr.rcvif);
1826 if ((vc = slot->vcc) == NULL) {
1833 /* do something with this mbuf */
1834 if (vc->vflags & VCC_DRAIN) {
1838 if (_IF_QLEN(&slot->indma) == 0 && _IF_QLEN(&slot->q) == 0 &&
1839 (en_read(sc, MID_VC(vc->vcc.vci)) & MIDV_INSERVICE) == 0 &&
1840 (vc->vflags & VCC_SWSL) == 0) {
1841 vc->vflags &= ~VCC_CLOSE_RX;
1842 if (vc->vcc.flags & ATMIO_FLAG_ASYNC)
1843 en_close_finish(sc, vc);
1845 cv_signal(&sc->cv_close);
1851 ATM_PH_FLAGS(&ah) = vc->vcc.flags;
1852 ATM_PH_VPI(&ah) = 0;
1853 ATM_PH_SETVCI(&ah, vc->vcc.vci);
1855 DBG(sc, INTR, ("rx%zu: rxvci%d: atm_input, mbuf %p, len %d, "
1856 "hand %p", slot - sc->rxslot, vc->vcc.vci, m,
1857 EN_DQ_LEN(drq), vc->rxhand));
1859 m->m_pkthdr.rcvif = &sc->ifatm.ifnet;
1860 sc->ifatm.ifnet.if_ipackets++;
1863 vc->ibytes += m->m_pkthdr.len;
1866 if (sc->debug & DBG_IPACKETS)
1867 en_dump_packet(sc, m);
1870 BPF_MTAP(&sc->ifatm.ifnet, m);
1872 atm_input(&sc->ifatm.ifnet, &ah, m, vc->rxhand);
1877 * check for RX DMA complete, and pass the data "upstairs"
1879 * LOCK: locked, needed
1882 en_intr_rx_dma(struct en_softc *sc)
1888 val = en_read(sc, MID_DMA_RDRX); /* chip's current location */
1889 idx = MID_DRQ_A2REG(sc->drq_chip); /* where we last saw chip */
1891 while (idx != val) {
1893 if ((drq = sc->drq[idx]) != 0) {
1894 /* don't forget to zero it out when done */
1896 en_rx_drain(sc, drq);
1898 EN_WRAPADD(0, MID_DRQ_N, idx, 1);
1900 sc->drq_chip = MID_DRQ_REG2A(val); /* sync softc */
1902 if (sc->need_drqs) {
1903 /* true if we had a DRQ shortage */
1905 DBG(sc, INTR, ("cleared need DRQ condition"));
1912 * en_mget: get an mbuf chain that can hold totlen bytes and return it
1913 * (for recv). For the actual allocation totlen is rounded up to a multiple
1914 * of 4. We also ensure, that each mbuf has a multiple of 4 bytes.
1916 * After this call the sum of all the m_len's in the chain will be totlen.
1917 * This is called at interrupt time, so we can't wait here.
1919 * LOCK: any, not needed
1921 static struct mbuf *
1922 en_mget(struct en_softc *sc, u_int pktlen)
1924 struct mbuf *m, *tmp;
1927 totlen = roundup(pktlen, sizeof(uint32_t));
1928 pad = totlen - pktlen;
1931 * First get an mbuf with header. Keep space for a couple of
1932 * words at the begin.
1934 /* called from interrupt context */
1935 MGETHDR(m, M_DONTWAIT, MT_DATA);
1939 m->m_pkthdr.rcvif = NULL;
1940 m->m_pkthdr.len = pktlen;
1941 m->m_len = EN_RX1BUF;
1942 MH_ALIGN(m, EN_RX1BUF);
1943 if (m->m_len >= totlen) {
1949 /* called from interrupt context */
1950 tmp = m_getm(m, totlen, M_DONTWAIT, MT_DATA);
1956 /* m_getm could do this for us */
1957 while (tmp != NULL) {
1958 tmp->m_len = min(MCLBYTES, totlen);
1959 totlen -= tmp->m_len;
1968 * Argument for RX DMAMAP loader.
1971 struct en_softc *sc;
1973 u_int pre_skip; /* number of bytes to skip at begin */
1974 u_int post_skip; /* number of bytes to skip at end */
1975 struct en_vcc *vc; /* vc we are receiving on */
1976 int wait; /* wait for DRQ entries */
1980 * Copy the segment table to the buffer for later use. And compute the
1981 * number of dma queue entries we need.
1983 * LOCK: locked, needed
1986 en_rxdma_load(void *uarg, bus_dma_segment_t *segs, int nseg,
1987 bus_size_t mapsize, int error)
1989 struct rxarg *rx = uarg;
1990 struct en_softc *sc = rx->sc;
1991 struct en_rxslot *slot = rx->vc->rxslot;
1992 u_int free; /* number of free DRQ entries */
1993 uint32_t cur; /* current buffer offset */
1994 uint32_t drq; /* DRQ entry pointer */
1995 uint32_t last_drq; /* where we have written last */
1996 u_int needalign, cnt, count, bcode;
2003 if (nseg > EN_MAX_DMASEG)
2004 panic("too many DMA segments");
2008 free = sc->drq_free;
2015 * Local macro to add an entry to the receive DMA area. If there
2016 * are no entries left, return. Save the byte offset of the entry
2017 * in last_drq for later use.
2019 #define PUT_DRQ_ENTRY(ENI, BCODE, COUNT, ADDR) \
2021 EN_COUNT(sc->stats.rxdrqout); \
2026 en_write(sc, drq + 0, (ENI || !sc->is_adaptec) ? \
2027 MID_MK_RXQ_ENI(COUNT, rx->vc->vcc.vci, 0, BCODE) : \
2028 MID_MK_RXQ_ADP(COUNT, rx->vc->vcc.vci, 0, BCODE)); \
2029 en_write(sc, drq + 4, ADDR); \
2031 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, drq, 8); \
2035 * Local macro to generate a DMA entry to DMA cnt bytes. Updates
2036 * the current buffer byte offset accordingly.
2038 #define DO_DRQ(TYPE) do { \
2040 EN_WRAPADD(slot->start, slot->stop, cur, cnt); \
2041 DBG(sc, SERV, ("rx%td: "TYPE" %u bytes, %ju left, cur %#x", \
2042 slot - sc->rxslot, cnt, (uintmax_t)rest, cur)); \
2044 PUT_DRQ_ENTRY(1, bcode, count, addr); \
2050 * Skip the RBD at the beginning
2052 if (rx->pre_skip > 0) {
2053 /* update DMA address */
2054 EN_WRAPADD(slot->start, slot->stop, cur, rx->pre_skip);
2056 PUT_DRQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
2059 for (i = 0; i < nseg; i++, segs++) {
2060 addr = segs->ds_addr;
2061 rest = segs->ds_len;
2063 if (sc->is_adaptec) {
2064 /* adaptec card - simple */
2066 /* advance the on-card buffer pointer */
2067 EN_WRAPADD(slot->start, slot->stop, cur, rest);
2068 DBG(sc, SERV, ("rx%td: adp %ju bytes %#jx "
2069 "(cur now 0x%x)", slot - sc->rxslot,
2070 (uintmax_t)rest, (uintmax_t)addr, cur));
2072 PUT_DRQ_ENTRY(0, 0, rest, addr);
2078 * do we need to do a DMA op to align to the maximum
2079 * burst? Note, that we are alway 32-bit aligned.
2082 (needalign = (addr & sc->bestburstmask)) != 0) {
2083 /* compute number of bytes, words and code */
2084 cnt = sc->bestburstlen - needalign;
2087 count = cnt / sizeof(uint32_t);
2088 if (sc->noalbursts) {
2089 bcode = MIDDMA_WORD;
2091 bcode = en_dmaplan[count].bcode;
2092 count = cnt >> en_dmaplan[count].divshift;
2097 /* do we need to do a max-sized burst? */
2098 if (rest >= sc->bestburstlen) {
2099 count = rest >> sc->bestburstshift;
2100 cnt = count << sc->bestburstshift;
2101 bcode = sc->bestburstcode;
2105 /* do we need to do a cleanup burst? */
2108 count = rest / sizeof(uint32_t);
2109 if (sc->noalbursts) {
2110 bcode = MIDDMA_WORD;
2112 bcode = en_dmaplan[count].bcode;
2113 count = cnt >> en_dmaplan[count].divshift;
2115 DO_DRQ("clean_dma");
2120 * Skip stuff at the end
2122 if (rx->post_skip > 0) {
2123 /* update DMA address */
2124 EN_WRAPADD(slot->start, slot->stop, cur, rx->post_skip);
2126 PUT_DRQ_ENTRY(0, MIDDMA_JK, WORD_IDX(slot->start, cur), 0);
2129 /* record the end for the interrupt routine */
2130 sc->drq[MID_DRQ_A2REG(last_drq)] =
2131 EN_DQ_MK(slot - sc->rxslot, rx->m->m_pkthdr.len);
2133 /* set the end flag in the last descriptor */
2134 en_write(sc, last_drq + 0, SETQ_END(sc, en_read(sc, last_drq + 0)));
2136 #undef PUT_DRQ_ENTRY
2141 sc->drq_free = free;
2144 /* signal to card */
2145 en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_us));
2149 * en_service: handle a service interrupt
2151 * Q: why do we need a software service list?
2153 * A: if we remove a VCI from the hardware list and we find that we are
2154 * out of DRQs we must defer processing until some DRQs become free.
2155 * so we must remember to look at this RX VCI/slot later, but we can't
2156 * put it back on the hardware service list (since that isn't allowed).
2157 * so we instead save it on the software service list. it would be nice
2158 * if we could peek at the VCI on top of the hwservice list without removing
2159 * it, however this leads to a race condition: if we peek at it and
2160 * decide we are done with it new data could come in before we have a
2161 * chance to remove it from the hwslist. by the time we get it out of
2162 * the list the interrupt for the new data will be lost. oops!
2164 * LOCK: locked, needed
2167 en_service(struct en_softc *sc)
2169 struct mbuf *m, *lastm;
2173 uint32_t dstart; /* data start (as reported by card) */
2174 uint32_t rbd; /* receive buffer descriptor */
2175 uint32_t pdu; /* AAL5 trailer */
2178 struct en_rxslot *slot;
2184 if (sc->swsl_size == 0) {
2185 DBG(sc, SERV, ("en_service done"));
2190 * get vcc to service
2192 rx.vc = vc = sc->vccs[sc->swslist[sc->swsl_head]];
2194 KASSERT (slot->vcc->rxslot == slot, ("en_service: rx slot/vci sync"));
2197 * determine our mode and if we've got any work to do
2199 DBG(sc, SERV, ("rx%td: service vci=%d start/stop/cur=0x%x 0x%x "
2200 "0x%x", slot - sc->rxslot, vc->vcc.vci, slot->start,
2201 slot->stop, slot->cur));
2206 dstart = MIDV_DSTART(en_read(sc, MID_DST_RP(vc->vcc.vci)));
2207 dstart = (dstart * sizeof(uint32_t)) + slot->start;
2209 /* check to see if there is any data at all */
2210 if (dstart == cur) {
2211 EN_WRAPADD(0, MID_SL_N, sc->swsl_head, 1);
2212 /* remove from swslist */
2213 vc->vflags &= ~VCC_SWSL;
2215 DBG(sc, SERV, ("rx%td: remove vci %d from swslist",
2216 slot - sc->rxslot, vc->vcc.vci));
2221 * figure out how many bytes we need
2222 * [mlen = # bytes to go in mbufs]
2224 rbd = en_read(sc, cur);
2225 if (MID_RBD_ID(rbd) != MID_RBD_STDID)
2226 panic("en_service: id mismatch");
2228 if (rbd & MID_RBD_T) {
2229 mlen = 0; /* we've got trash */
2230 rx.pre_skip = MID_RBD_SIZE;
2232 EN_COUNT(sc->stats.ttrash);
2233 DBG(sc, SERV, ("RX overflow lost %d cells!", MID_RBD_CNT(rbd)));
2235 } else if (vc->vcc.aal != ATMIO_AAL_5) {
2237 mlen = MID_CHDR_SIZE + MID_ATMDATASZ;
2238 rx.pre_skip = MID_RBD_SIZE;
2242 rx.pre_skip = MID_RBD_SIZE;
2244 /* get PDU trailer in correct byte order */
2245 pdu = cur + MID_RBD_CNT(rbd) * MID_ATMDATASZ +
2246 MID_RBD_SIZE - MID_PDU_SIZE;
2247 if (pdu >= slot->stop)
2248 pdu -= EN_RXSZ * 1024;
2249 pdu = en_read(sc, pdu);
2251 if (MID_RBD_CNT(rbd) * MID_ATMDATASZ <
2253 if_printf(&sc->ifatm.ifnet, "invalid AAL5 length\n");
2254 rx.post_skip = MID_RBD_CNT(rbd) * MID_ATMDATASZ;
2256 sc->ifatm.ifnet.if_ierrors++;
2258 } else if (rbd & MID_RBD_CRCERR) {
2259 if_printf(&sc->ifatm.ifnet, "CRC error\n");
2260 rx.post_skip = MID_RBD_CNT(rbd) * MID_ATMDATASZ;
2262 sc->ifatm.ifnet.if_ierrors++;
2265 mlen = MID_PDU_LEN(pdu);
2266 rx.post_skip = MID_RBD_CNT(rbd) * MID_ATMDATASZ - mlen;
2271 * now allocate mbufs for mlen bytes of data, if out of mbufs, trash all
2274 * 1. it is possible that we've already allocated an mbuf for this pkt
2275 * but ran out of DRQs, in which case we saved the allocated mbuf
2277 * 2. if we save an buf in "q" we store the "cur" (pointer) in the
2278 * buf as an identity (that we can check later).
2279 * 3. after this block of code, if m is still NULL then we ran out of
2282 _IF_DEQUEUE(&slot->q, m);
2284 if (m->m_pkthdr.csum_data != cur) {
2286 DBG(sc, SERV, ("rx%td: q'ed buf %p not ours",
2287 slot - sc->rxslot, m));
2288 _IF_PREPEND(&slot->q, m);
2290 EN_COUNT(sc->stats.rxqnotus);
2292 EN_COUNT(sc->stats.rxqus);
2293 DBG(sc, SERV, ("rx%td: recovered q'ed buf %p",
2294 slot - sc->rxslot, m));
2297 if (mlen == 0 && m != NULL) {
2298 /* should not happen */
2303 if (mlen != 0 && m == NULL) {
2304 m = en_mget(sc, mlen);
2306 rx.post_skip += mlen;
2308 EN_COUNT(sc->stats.rxmbufout);
2309 DBG(sc, SERV, ("rx%td: out of mbufs",
2310 slot - sc->rxslot));
2312 rx.post_skip -= roundup(mlen, sizeof(uint32_t)) - mlen;
2314 DBG(sc, SERV, ("rx%td: allocate buf %p, mlen=%d",
2315 slot - sc->rxslot, m, mlen));
2318 DBG(sc, SERV, ("rx%td: VCI %d, rbuf %p, mlen %d, skip %u/%u",
2319 slot - sc->rxslot, vc->vcc.vci, m, mlen, rx.pre_skip,
2323 /* M_NOWAIT - called from interrupt context */
2324 map = uma_zalloc_arg(sc->map_zone, sc, M_NOWAIT);
2326 rx.post_skip += mlen;
2328 DBG(sc, SERV, ("rx%td: out of maps",
2329 slot - sc->rxslot));
2333 error = bus_dmamap_load_mbuf(sc->txtag, map->map, m,
2334 en_rxdma_load, &rx, BUS_DMA_NOWAIT);
2337 if_printf(&sc->ifatm.ifnet, "loading RX map failed "
2339 uma_zfree(sc->map_zone, map);
2341 rx.post_skip += mlen;
2345 map->flags |= ENMAP_LOADED;
2348 /* out of DRQs - wait */
2349 uma_zfree(sc->map_zone, map);
2351 m->m_pkthdr.csum_data = cur;
2352 _IF_ENQUEUE(&slot->q, m);
2353 EN_COUNT(sc->stats.rxdrqout);
2355 sc->need_drqs = 1; /* flag condition */
2359 (void)m_length(m, &lastm);
2360 lastm->m_len -= roundup(mlen, sizeof(uint32_t)) - mlen;
2362 m->m_pkthdr.rcvif = (void *)map;
2363 _IF_ENQUEUE(&slot->indma, m);
2365 /* get next packet in this slot */
2370 * Here we end if we should drop the packet from the receive buffer.
2371 * The number of bytes to drop is in fill. We can do this with on
2372 * JK entry. If we don't even have that one - wait.
2374 if (sc->drq_free == 0) {
2375 sc->need_drqs = 1; /* flag condition */
2378 rx.post_skip += rx.pre_skip;
2379 DBG(sc, SERV, ("rx%td: skipping %u", slot - sc->rxslot, rx.post_skip));
2381 /* advance buffer address */
2382 EN_WRAPADD(slot->start, slot->stop, cur, rx.post_skip);
2384 /* write DRQ entry */
2386 en_write(sc, sc->drq_us,
2387 MID_MK_RXQ_ADP(WORD_IDX(slot->start, cur),
2388 vc->vcc.vci, MID_DMA_END, MIDDMA_JK));
2390 en_write(sc, sc->drq_us,
2391 MID_MK_RXQ_ENI(WORD_IDX(slot->start, cur),
2392 vc->vcc.vci, MID_DMA_END, MIDDMA_JK));
2393 en_write(sc, sc->drq_us + 4, 0);
2394 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, sc->drq_us, 8);
2397 /* signal to RX interrupt */
2398 sc->drq[MID_DRQ_A2REG(sc->drq_us)] = EN_DQ_MK(slot - sc->rxslot, 0);
2401 /* signal to card */
2402 en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_us));
2410 * LOCK: unlocked, needed
2415 struct en_softc *sc = arg;
2416 uint32_t reg, kick, mask;
2417 int lcv, need_softserv;
2421 reg = en_read(sc, MID_INTACK);
2422 DBG(sc, INTR, ("interrupt=0x%b", reg, MID_INTBITS));
2424 if ((reg & MID_INT_ANY) == 0) {
2430 * unexpected errors that need a reset
2432 if ((reg & (MID_INT_IDENT | MID_INT_LERR | MID_INT_DMA_ERR)) != 0) {
2433 if_printf(&sc->ifatm.ifnet, "unexpected interrupt=0x%b, "
2434 "resetting\n", reg, MID_INTBITS);
2436 kdb_enter("en: unexpected error");
2437 sc->ifatm.ifnet.if_flags &= ~IFF_RUNNING; /* FREEZE! */
2446 if (reg & MID_INT_SUNI)
2447 utopia_intr(&sc->utopia);
2450 if (reg & MID_INT_TX)
2451 kick |= en_intr_tx(sc, reg);
2453 if (reg & MID_INT_DMA_TX)
2454 kick |= en_intr_tx_dma(sc);
2457 * kick xmit channels as needed.
2460 DBG(sc, INTR, ("tx kick mask = 0x%x", kick));
2461 for (mask = 1, lcv = 0 ; lcv < EN_NTX ; lcv++, mask = mask * 2)
2462 if ((kick & mask) && _IF_QLEN(&sc->txslot[lcv].q) != 0)
2463 en_txdma(sc, &sc->txslot[lcv]);
2467 if (reg & MID_INT_DMA_RX)
2468 need_softserv |= en_intr_rx_dma(sc);
2470 if (reg & MID_INT_SERVICE)
2471 need_softserv |= en_intr_service(sc);
2479 if (reg & MID_INT_DMA_OVR) {
2480 EN_COUNT(sc->stats.dmaovr);
2481 DBG(sc, INTR, ("MID_INT_DMA_OVR"));
2483 reg = en_read(sc, MID_STAT);
2484 sc->stats.otrash += MID_OTRASH(reg);
2485 sc->stats.vtrash += MID_VTRASH(reg);
2491 * Read at most n SUNI regs starting at reg into val
2494 en_utopia_readregs(struct ifatm *ifatm, u_int reg, uint8_t *val, u_int *n)
2496 struct en_softc *sc = ifatm->ifnet.if_softc;
2500 if (reg >= MID_NSUNI)
2502 if (reg + *n > MID_NSUNI)
2503 *n = MID_NSUNI - reg;
2505 for (i = 0; i < *n; i++)
2506 val[i] = en_read(sc, MID_SUNIOFF + 4 * (reg + i));
2512 * change the bits given by mask to them in val in register reg
2515 en_utopia_writereg(struct ifatm *ifatm, u_int reg, u_int mask, u_int val)
2517 struct en_softc *sc = ifatm->ifnet.if_softc;
2521 if (reg >= MID_NSUNI)
2523 regval = en_read(sc, MID_SUNIOFF + 4 * reg);
2524 regval = (regval & ~mask) | (val & mask);
2525 en_write(sc, MID_SUNIOFF + 4 * reg, regval);
2529 static const struct utopia_methods en_utopia_methods = {
2534 /*********************************************************************/
2536 * Probing the DMA brokeness of the card
2540 * Physical address load helper function for DMA probe
2542 * LOCK: unlocked, not needed
2545 en_dmaprobe_load(void *uarg, bus_dma_segment_t *segs, int nseg, int error)
2548 *(bus_addr_t *)uarg = segs[0].ds_addr;
2552 * en_dmaprobe: helper function for en_attach.
2554 * see how the card handles DMA by running a few DMA tests. we need
2555 * to figure out the largest number of bytes we can DMA in one burst
2556 * ("bestburstlen"), and if the starting address for a burst needs to
2557 * be aligned on any sort of boundary or not ("alburst").
2559 * Things turn out more complex than that, because on my (harti) brand
2560 * new motherboard (2.4GHz) we can do 64byte aligned DMAs, but everything
2561 * we more than 4 bytes fails (with an RX DMA timeout) for physical
2562 * addresses that end with 0xc. Therefor we search not only the largest
2563 * burst that is supported (hopefully 64) but also check what is the largerst
2564 * unaligned supported size. If that appears to be lesser than 4 words,
2565 * set the noalbursts flag. That will be set only if also alburst is set.
2569 * en_dmaprobe_doit: do actual testing for the DMA test.
2570 * Cycle through all bursts sizes from 8 up to 64 and try whether it works.
2571 * Return the largest one that works.
2573 * LOCK: unlocked, not needed
2576 en_dmaprobe_doit(struct en_softc *sc, uint8_t *sp, bus_addr_t psp)
2578 uint8_t *dp = sp + MIDDMA_MAXBURST;
2579 bus_addr_t pdp = psp + MIDDMA_MAXBURST;
2580 int lcv, retval = 4, cnt;
2581 uint32_t reg, bcode, midvloc;
2583 if (sc->en_busreset)
2584 sc->en_busreset(sc);
2585 en_write(sc, MID_RESID, 0x0); /* reset card before touching RAM */
2588 * set up a 1k buffer at MID_BUFOFF
2590 midvloc = ((MID_BUFOFF - MID_RAMOFF) / sizeof(uint32_t))
2592 en_write(sc, MIDX_PLACE(0), MIDX_MKPLACE(en_k2sz(1), midvloc));
2593 en_write(sc, MID_VC(0), (midvloc << MIDV_LOCSHIFT)
2594 | (en_k2sz(1) << MIDV_SZSHIFT) | MIDV_TRASH);
2595 en_write(sc, MID_DST_RP(0), 0);
2596 en_write(sc, MID_WP_ST_CNT(0), 0);
2598 /* set up sample data */
2599 for (lcv = 0 ; lcv < MIDDMA_MAXBURST; lcv++)
2602 /* enable DMA (only) */
2603 en_write(sc, MID_MAST_CSR, MID_MCSR_ENDMA);
2605 sc->drq_chip = MID_DRQ_REG2A(en_read(sc, MID_DMA_RDRX));
2606 sc->dtq_chip = MID_DTQ_REG2A(en_read(sc, MID_DMA_RDTX));
2609 * try it now . . . DMA it out, then DMA it back in and compare
2611 * note: in order to get the dma stuff to reverse directions it wants
2612 * the "end" flag set! since we are not dma'ing valid data we may
2613 * get an ident mismatch interrupt (which we will ignore).
2615 DBG(sc, DMA, ("test sp=%p/%#lx, dp=%p/%#lx",
2616 sp, (u_long)psp, dp, (u_long)pdp));
2617 for (lcv = 8 ; lcv <= MIDDMA_MAXBURST ; lcv = lcv * 2) {
2618 DBG(sc, DMA, ("test lcv=%d", lcv));
2620 /* zero SRAM and dest buffer */
2621 bus_space_set_region_4(sc->en_memt, sc->en_base,
2622 MID_BUFOFF, 0, 1024 / 4);
2623 bzero(dp, MIDDMA_MAXBURST);
2625 bcode = en_sz2b(lcv);
2627 /* build lcv-byte-DMA x NBURSTS */
2629 en_write(sc, sc->dtq_chip,
2630 MID_MK_TXQ_ADP(lcv, 0, MID_DMA_END, 0));
2632 en_write(sc, sc->dtq_chip,
2633 MID_MK_TXQ_ENI(1, 0, MID_DMA_END, bcode));
2634 en_write(sc, sc->dtq_chip + 4, psp);
2635 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, sc->dtq_chip, 8);
2636 en_write(sc, MID_DMA_WRTX, MID_DTQ_A2REG(sc->dtq_chip));
2639 while ((reg = en_readx(sc, MID_DMA_RDTX)) !=
2640 MID_DTQ_A2REG(sc->dtq_chip)) {
2643 DBG(sc, DMA, ("unexpected timeout in tx "
2644 "DMA test\n alignment=0x%lx, burst size=%d"
2645 ", dma addr reg=%#x, rdtx=%#x, stat=%#x\n",
2646 (u_long)sp & 63, lcv,
2647 en_read(sc, MID_DMA_ADDR), reg,
2648 en_read(sc, MID_INTSTAT)));
2653 reg = en_read(sc, MID_INTACK);
2654 if ((reg & MID_INT_DMA_TX) != MID_INT_DMA_TX) {
2655 DBG(sc, DMA, ("unexpected status in tx DMA test: %#x\n",
2659 /* re-enable DMA (only) */
2660 en_write(sc, MID_MAST_CSR, MID_MCSR_ENDMA);
2662 /* "return to sender..." address is known ... */
2664 /* build lcv-byte-DMA x NBURSTS */
2666 en_write(sc, sc->drq_chip,
2667 MID_MK_RXQ_ADP(lcv, 0, MID_DMA_END, 0));
2669 en_write(sc, sc->drq_chip,
2670 MID_MK_RXQ_ENI(1, 0, MID_DMA_END, bcode));
2671 en_write(sc, sc->drq_chip + 4, pdp);
2672 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, sc->drq_chip, 8);
2673 en_write(sc, MID_DMA_WRRX, MID_DRQ_A2REG(sc->drq_chip));
2675 while ((reg = en_readx(sc, MID_DMA_RDRX)) !=
2676 MID_DRQ_A2REG(sc->drq_chip)) {
2680 DBG(sc, DMA, ("unexpected timeout in rx "
2681 "DMA test, rdrx=%#x\n", reg));
2685 reg = en_read(sc, MID_INTACK);
2686 if ((reg & MID_INT_DMA_RX) != MID_INT_DMA_RX) {
2687 DBG(sc, DMA, ("unexpected status in rx DMA "
2688 "test: 0x%x\n", reg));
2691 if (bcmp(sp, dp, lcv)) {
2692 DBG(sc, DMA, ("DMA test failed! lcv=%d, sp=%p, "
2693 "dp=%p", lcv, sp, dp));
2699 return (retval); /* studly 64 byte DMA present! oh baby!! */
2703 * Find the best DMA parameters
2705 * LOCK: unlocked, not needed
2708 en_dmaprobe(struct en_softc *sc)
2714 int bestalgn, lcv, try, bestnoalgn;
2722 * Allocate some DMA-able memory.
2723 * We need 3 times the max burst size aligned to the max burst size.
2725 err = bus_dma_tag_create(NULL, MIDDMA_MAXBURST, 0,
2726 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
2727 3 * MIDDMA_MAXBURST, 1, 3 * MIDDMA_MAXBURST, 0,
2730 panic("%s: cannot create test DMA tag %d", __func__, err);
2732 err = bus_dmamem_alloc(tag, &buffer, 0, &map);
2734 panic("%s: cannot allocate test DMA memory %d", __func__, err);
2736 err = bus_dmamap_load(tag, map, buffer, 3 * MIDDMA_MAXBURST,
2737 en_dmaprobe_load, &phys, BUS_DMA_NOWAIT);
2739 panic("%s: cannot load test DMA map %d", __func__, err);
2741 DBG(sc, DMA, ("phys=%#lx addr=%p", (u_long)phys, addr));
2744 * Now get the best burst size of the aligned case.
2746 bestalgn = bestnoalgn = en_dmaprobe_doit(sc, addr, phys);
2749 * Now try unaligned.
2751 for (lcv = 4; lcv < MIDDMA_MAXBURST; lcv += 4) {
2752 try = en_dmaprobe_doit(sc, addr + lcv, phys + lcv);
2754 if (try < bestnoalgn)
2758 if (bestnoalgn < bestalgn) {
2760 if (bestnoalgn < 32)
2764 sc->bestburstlen = bestalgn;
2765 sc->bestburstshift = en_log2(bestalgn);
2766 sc->bestburstmask = sc->bestburstlen - 1; /* must be power of 2 */
2767 sc->bestburstcode = en_sz2b(bestalgn);
2770 * Reset the chip before freeing the buffer. It may still be trying
2773 if (sc->en_busreset)
2774 sc->en_busreset(sc);
2775 en_write(sc, MID_RESID, 0x0); /* reset card before touching RAM */
2777 DELAY(10000); /* may still do DMA */
2780 * Free the DMA stuff
2782 bus_dmamap_unload(tag, map);
2783 bus_dmamem_free(tag, buffer, map);
2784 bus_dma_tag_destroy(tag);
2787 /*********************************************************************/
2793 * Attach to the card.
2795 * LOCK: unlocked, not needed (but initialized)
2798 en_attach(struct en_softc *sc)
2800 struct ifnet *ifp = &sc->ifatm.ifnet;
2802 uint32_t reg, lcv, check, ptr, sav, midvloc;
2805 sc->debug = EN_DEBUG;
2808 * Probe card to determine memory size.
2810 * The stupid ENI card always reports to PCI that it needs 4MB of
2811 * space (2MB regs and 2MB RAM). If it has less than 2MB RAM the
2812 * addresses wrap in the RAM address space (i.e. on a 512KB card
2813 * addresses 0x3ffffc, 0x37fffc, and 0x2ffffc are aliases for
2814 * 0x27fffc [note that RAM starts at offset 0x200000]).
2817 /* reset card before touching RAM */
2818 if (sc->en_busreset)
2819 sc->en_busreset(sc);
2820 en_write(sc, MID_RESID, 0x0);
2822 for (lcv = MID_PROBEOFF; lcv <= MID_MAXOFF ; lcv += MID_PROBSIZE) {
2823 en_write(sc, lcv, lcv); /* data[address] = address */
2824 for (check = MID_PROBEOFF; check < lcv ;check += MID_PROBSIZE) {
2825 reg = en_read(sc, check);
2827 /* found an alias! - quit */
2832 lcv -= MID_PROBSIZE; /* take one step back */
2833 sc->en_obmemsz = (lcv + 4) - MID_RAMOFF;
2836 * determine the largest DMA burst supported
2845 if (sc->en_busreset)
2846 sc->en_busreset(sc);
2847 en_write(sc, MID_RESID, 0x0); /* reset */
2850 bus_space_set_region_4(sc->en_memt, sc->en_base,
2851 MID_RAMOFF, 0, sc->en_obmemsz / 4);
2853 reg = en_read(sc, MID_RESID);
2855 if_printf(&sc->ifatm.ifnet, "ATM midway v%d, board IDs %d.%d, %s%s%s, "
2856 "%ldKB on-board RAM\n", MID_VER(reg), MID_MID(reg), MID_DID(reg),
2857 (MID_IS_SABRE(reg)) ? "sabre controller, " : "",
2858 (MID_IS_SUNI(reg)) ? "SUNI" : "Utopia",
2859 (!MID_IS_SUNI(reg) && MID_IS_UPIPE(reg)) ? " (pipelined)" : "",
2860 (long)sc->en_obmemsz / 1024);
2863 * fill in common ATM interface stuff
2865 sc->ifatm.mib.hw_version = (MID_VER(reg) << 16) |
2866 (MID_MID(reg) << 8) | MID_DID(reg);
2867 if (MID_DID(reg) & 0x4)
2868 sc->ifatm.mib.media = IFM_ATM_UTP_155;
2870 sc->ifatm.mib.media = IFM_ATM_MM_155;
2872 sc->ifatm.mib.pcr = ATM_RATE_155M;
2873 sc->ifatm.mib.vpi_bits = 0;
2874 sc->ifatm.mib.vci_bits = MID_VCI_BITS;
2875 sc->ifatm.mib.max_vccs = MID_N_VC;
2876 sc->ifatm.mib.max_vpcs = 0;
2878 if (sc->is_adaptec) {
2879 sc->ifatm.mib.device = ATM_DEVICE_ADP155P;
2880 if (sc->bestburstlen == 64 && sc->alburst == 0)
2881 if_printf(&sc->ifatm.ifnet,
2882 "passed 64 byte DMA test\n");
2884 if_printf(&sc->ifatm.ifnet, "FAILED DMA TEST: "
2885 "burst=%d, alburst=%d\n", sc->bestburstlen,
2888 sc->ifatm.mib.device = ATM_DEVICE_ENI155P;
2889 if_printf(&sc->ifatm.ifnet, "maximum DMA burst length = %d "
2890 "bytes%s\n", sc->bestburstlen, sc->alburst ?
2891 sc->noalbursts ? " (no large bursts)" : " (must align)" :
2896 * link into network subsystem and prepare card
2898 sc->ifatm.ifnet.if_softc = sc;
2899 ifp->if_flags = IFF_SIMPLEX;
2900 ifp->if_ioctl = en_ioctl;
2901 ifp->if_start = en_start;
2903 mtx_init(&sc->en_mtx, device_get_nameunit(sc->dev),
2904 MTX_NETWORK_LOCK, MTX_DEF);
2905 cv_init(&sc->cv_close, "VC close");
2908 * Make the sysctl tree
2910 sysctl_ctx_init(&sc->sysctl_ctx);
2912 if ((sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
2913 SYSCTL_STATIC_CHILDREN(_hw_atm), OID_AUTO,
2914 device_get_nameunit(sc->dev), CTLFLAG_RD, 0, "")) == NULL)
2917 if (SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
2918 OID_AUTO, "istats", CTLFLAG_RD, sc, 0, en_sysctl_istats,
2919 "S", "internal statistics") == NULL)
2923 if (SYSCTL_ADD_UINT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
2924 OID_AUTO, "debug", CTLFLAG_RW , &sc->debug, 0, "") == NULL)
2928 sc->ifatm.phy = &sc->utopia;
2929 utopia_attach(&sc->utopia, &sc->ifatm, &sc->media, &sc->en_mtx,
2930 &sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
2931 &en_utopia_methods);
2932 utopia_init_media(&sc->utopia);
2934 MGET(sc->padbuf, M_TRYWAIT, MT_DATA);
2935 if (sc->padbuf == NULL)
2937 bzero(sc->padbuf->m_data, MLEN);
2939 if (bus_dma_tag_create(NULL, 1, 0,
2940 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
2941 EN_TXSZ * 1024, EN_MAX_DMASEG, EN_TXSZ * 1024, 0,
2942 NULL, NULL, &sc->txtag))
2945 sc->map_zone = uma_zcreate("en dma maps", sizeof(struct en_map),
2946 en_map_ctor, en_map_dtor, NULL, en_map_fini, UMA_ALIGN_PTR,
2948 if (sc->map_zone == NULL)
2950 uma_zone_set_max(sc->map_zone, EN_MAX_MAPS);
2955 sc->vccs = malloc(MID_N_VC * sizeof(sc->vccs[0]),
2956 M_DEVBUF, M_ZERO | M_WAITOK);
2958 sz = sc->en_obmemsz - (MID_BUFOFF - MID_RAMOFF);
2959 ptr = sav = MID_BUFOFF;
2960 ptr = roundup(ptr, EN_TXSZ * 1024); /* align */
2961 sz = sz - (ptr - sav);
2962 if (EN_TXSZ*1024 * EN_NTX > sz) {
2963 if_printf(&sc->ifatm.ifnet, "EN_NTX/EN_TXSZ too big\n");
2966 for (lcv = 0 ;lcv < EN_NTX ;lcv++) {
2967 sc->txslot[lcv].mbsize = 0;
2968 sc->txslot[lcv].start = ptr;
2969 ptr += (EN_TXSZ * 1024);
2970 sz -= (EN_TXSZ * 1024);
2971 sc->txslot[lcv].stop = ptr;
2972 sc->txslot[lcv].nref = 0;
2973 DBG(sc, INIT, ("tx%d: start 0x%x, stop 0x%x", lcv,
2974 sc->txslot[lcv].start, sc->txslot[lcv].stop));
2978 ptr = roundup(ptr, EN_RXSZ * 1024); /* align */
2979 sz = sz - (ptr - sav);
2980 sc->en_nrx = sz / (EN_RXSZ * 1024);
2981 if (sc->en_nrx <= 0) {
2982 if_printf(&sc->ifatm.ifnet, "EN_NTX/EN_TXSZ/EN_RXSZ too big\n");
2987 * ensure that there is always one VC slot on the service list free
2988 * so that we can tell the difference between a full and empty list.
2990 if (sc->en_nrx >= MID_N_VC)
2991 sc->en_nrx = MID_N_VC - 1;
2993 for (lcv = 0 ; lcv < sc->en_nrx ; lcv++) {
2994 sc->rxslot[lcv].vcc = NULL;
2995 midvloc = sc->rxslot[lcv].start = ptr;
2996 ptr += (EN_RXSZ * 1024);
2997 sz -= (EN_RXSZ * 1024);
2998 sc->rxslot[lcv].stop = ptr;
2999 midvloc = midvloc - MID_RAMOFF;
3000 /* mask, cvt to words */
3001 midvloc = (midvloc & ~((EN_RXSZ*1024) - 1)) >> 2;
3002 /* we only want the top 11 bits */
3003 midvloc = midvloc >> MIDV_LOCTOPSHFT;
3004 midvloc = (midvloc & MIDV_LOCMASK) << MIDV_LOCSHIFT;
3005 sc->rxslot[lcv].mode = midvloc |
3006 (en_k2sz(EN_RXSZ) << MIDV_SZSHIFT) | MIDV_TRASH;
3008 DBG(sc, INIT, ("rx%d: start 0x%x, stop 0x%x, mode 0x%x", lcv,
3009 sc->rxslot[lcv].start, sc->rxslot[lcv].stop,
3010 sc->rxslot[lcv].mode));
3013 if_printf(&sc->ifatm.ifnet, "%d %dKB receive buffers, %d %dKB transmit "
3014 "buffers\n", sc->en_nrx, EN_RXSZ, EN_NTX, EN_TXSZ);
3015 if_printf(&sc->ifatm.ifnet, "end station identifier (mac address) "
3016 "%6D\n", sc->ifatm.mib.esi, ":");
3019 * Start SUNI stuff. This will call our readregs/writeregs
3020 * functions and these assume the lock to be held so we must get it
3024 utopia_start(&sc->utopia);
3025 utopia_reset(&sc->utopia);
3034 bpfattach(ifp, DLT_ATM_RFC1483, sizeof(struct atmllc));
3045 * Free all internal resources. No access to bus resources here.
3046 * No locking required here (interrupt is already disabled).
3048 * LOCK: unlocked, needed (but destroyed)
3051 en_destroy(struct en_softc *sc)
3055 if (sc->utopia.state & UTP_ST_ATTACHED) {
3056 /* these assume the lock to be held */
3058 utopia_stop(&sc->utopia);
3059 utopia_detach(&sc->utopia);
3063 if (sc->vccs != NULL) {
3064 /* get rid of sticky VCCs */
3065 for (i = 0; i < MID_N_VC; i++)
3066 if (sc->vccs[i] != NULL)
3067 uma_zfree(en_vcc_zone, sc->vccs[i]);
3068 free(sc->vccs, M_DEVBUF);
3071 if (sc->padbuf != NULL)
3075 * Destroy the map zone before the tag (the fini function will
3076 * destroy the DMA maps using the tag)
3078 if (sc->map_zone != NULL)
3079 uma_zdestroy(sc->map_zone);
3081 if (sc->txtag != NULL)
3082 bus_dma_tag_destroy(sc->txtag);
3084 (void)sysctl_ctx_free(&sc->sysctl_ctx);
3086 cv_destroy(&sc->cv_close);
3087 mtx_destroy(&sc->en_mtx);
3091 * Module loaded/unloaded
3094 en_modevent(module_t mod __unused, int event, void *arg __unused)
3100 en_vcc_zone = uma_zcreate("EN vccs", sizeof(struct en_vcc),
3101 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
3102 if (en_vcc_zone == NULL)
3107 uma_zdestroy(en_vcc_zone);
3113 /*********************************************************************/
3120 * functions we can call from ddb
3124 * en_dump: dump the state
3126 #define END_SWSL 0x00000040 /* swsl state */
3127 #define END_DRQ 0x00000020 /* drq state */
3128 #define END_DTQ 0x00000010 /* dtq state */
3129 #define END_RX 0x00000008 /* rx state */
3130 #define END_TX 0x00000004 /* tx state */
3131 #define END_MREGS 0x00000002 /* registers */
3132 #define END_STATS 0x00000001 /* dump stats */
3134 #define END_BITS "\20\7SWSL\6DRQ\5DTQ\4RX\3TX\2MREGS\1STATS"
3137 en_dump_stats(const struct en_stats *s)
3139 printf("en_stats:\n");
3140 printf("\t%d/%d mfix (%d failed)\n", s->mfixaddr, s->mfixlen,
3142 printf("\t%d rx dma overflow interrupts\n", s->dmaovr);
3143 printf("\t%d times out of TX space and stalled\n", s->txoutspace);
3144 printf("\t%d times out of DTQs\n", s->txdtqout);
3145 printf("\t%d times launched a packet\n", s->launch);
3146 printf("\t%d times pulled the hw service list\n", s->hwpull);
3147 printf("\t%d times pushed a vci on the sw service list\n", s->swadd);
3148 printf("\t%d times RX pulled an mbuf from Q that wasn't ours\n",
3150 printf("\t%d times RX pulled a good mbuf from Q\n", s->rxqus);
3151 printf("\t%d times ran out of DRQs\n", s->rxdrqout);
3152 printf("\t%d transmit packets dropped due to mbsize\n", s->txmbovr);
3153 printf("\t%d cells trashed due to turned off rxvc\n", s->vtrash);
3154 printf("\t%d cells trashed due to totally full buffer\n", s->otrash);
3155 printf("\t%d cells trashed due almost full buffer\n", s->ttrash);
3156 printf("\t%d rx mbuf allocation failures\n", s->rxmbufout);
3157 printf("\t%d times out of tx maps\n", s->txnomap);
3160 printf("\tnatmintr so_rcv: ok/drop cnt: %d/%d, ok/drop bytes: %d/%d\n",
3161 natm_sookcnt, natm_sodropcnt, natm_sookbytes, natm_sodropbytes);
3167 en_dump_mregs(struct en_softc *sc)
3172 printf("resid = 0x%x\n", en_read(sc, MID_RESID));
3173 printf("interrupt status = 0x%b\n",
3174 (int)en_read(sc, MID_INTSTAT), MID_INTBITS);
3175 printf("interrupt enable = 0x%b\n",
3176 (int)en_read(sc, MID_INTENA), MID_INTBITS);
3177 printf("mcsr = 0x%b\n", (int)en_read(sc, MID_MAST_CSR), MID_MCSRBITS);
3178 printf("serv_write = [chip=%u] [us=%u]\n", en_read(sc, MID_SERV_WRITE),
3179 MID_SL_A2REG(sc->hwslistp));
3180 printf("dma addr = 0x%x\n", en_read(sc, MID_DMA_ADDR));
3181 printf("DRQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3182 MID_DRQ_REG2A(en_read(sc, MID_DMA_RDRX)),
3183 MID_DRQ_REG2A(en_read(sc, MID_DMA_WRRX)), sc->drq_chip, sc->drq_us);
3184 printf("DTQ: chip[rd=0x%x,wr=0x%x], sc[chip=0x%x,us=0x%x]\n",
3185 MID_DTQ_REG2A(en_read(sc, MID_DMA_RDTX)),
3186 MID_DTQ_REG2A(en_read(sc, MID_DMA_WRTX)), sc->dtq_chip, sc->dtq_us);
3188 printf(" unusal txspeeds:");
3189 for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3190 if (sc->vccs[cnt]->txspeed)
3191 printf(" vci%d=0x%x", cnt, sc->vccs[cnt]->txspeed);
3194 printf(" rxvc slot mappings:");
3195 for (cnt = 0 ; cnt < MID_N_VC ; cnt++)
3196 if (sc->vccs[cnt]->rxslot != NULL)
3197 printf(" %d->%zu", cnt,
3198 sc->vccs[cnt]->rxslot - sc->rxslot);
3203 en_dump_tx(struct en_softc *sc)
3208 for (slot = 0 ; slot < EN_NTX; slot++) {
3209 printf("tx%d: start/stop/cur=0x%x/0x%x/0x%x [%d] ", slot,
3210 sc->txslot[slot].start, sc->txslot[slot].stop,
3211 sc->txslot[slot].cur,
3212 (sc->txslot[slot].cur - sc->txslot[slot].start) / 4);
3213 printf("mbsize=%d, bfree=%d\n", sc->txslot[slot].mbsize,
3214 sc->txslot[slot].bfree);
3215 printf("txhw: base_address=0x%x, size=%u, read=%u, "
3217 (u_int)MIDX_BASE(en_read(sc, MIDX_PLACE(slot))),
3218 MIDX_SZ(en_read(sc, MIDX_PLACE(slot))),
3219 en_read(sc, MIDX_READPTR(slot)),
3220 en_read(sc, MIDX_DESCSTART(slot)));
3225 en_dump_rx(struct en_softc *sc)
3227 struct en_rxslot *slot;
3229 printf(" recv slots:\n");
3230 for (slot = sc->rxslot ; slot < &sc->rxslot[sc->en_nrx]; slot++) {
3231 printf("rx%zu: start/stop/cur=0x%x/0x%x/0x%x mode=0x%x ",
3232 slot - sc->rxslot, slot->start, slot->stop, slot->cur,
3234 if (slot->vcc != NULL) {
3235 printf("vci=%u\n", slot->vcc->vcc.vci);
3236 printf("RXHW: mode=0x%x, DST_RP=0x%x, WP_ST_CNT=0x%x\n",
3237 en_read(sc, MID_VC(slot->vcc->vcc.vci)),
3238 en_read(sc, MID_DST_RP(slot->vcc->vcc.vci)),
3239 en_read(sc, MID_WP_ST_CNT(slot->vcc->vcc.vci)));
3245 * This is only correct for non-adaptec adapters
3248 en_dump_dtqs(struct en_softc *sc)
3252 printf(" dtq [need_dtqs=%d,dtq_free=%d]:\n", sc->need_dtqs,
3255 while (ptr != sc->dtq_us) {
3256 reg = en_read(sc, ptr);
3257 printf("\t0x%x=[%#x cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n",
3258 sc->dtq[MID_DTQ_A2REG(ptr)], reg, MID_DMA_CNT(reg),
3259 MID_DMA_TXCHAN(reg), (reg & MID_DMA_END) != 0,
3260 MID_DMA_TYPE(reg), en_read(sc, ptr + 4));
3261 EN_WRAPADD(MID_DTQOFF, MID_DTQEND, ptr, 8);
3266 en_dump_drqs(struct en_softc *sc)
3270 printf(" drq [need_drqs=%d,drq_free=%d]:\n", sc->need_drqs,
3273 while (ptr != sc->drq_us) {
3274 reg = en_read(sc, ptr);
3275 printf("\t0x%x=[cnt=%d, chan=%d, end=%d, type=%d @ 0x%x]\n",
3276 sc->drq[MID_DRQ_A2REG(ptr)], MID_DMA_CNT(reg),
3277 MID_DMA_RXVCI(reg), (reg & MID_DMA_END) != 0,
3278 MID_DMA_TYPE(reg), en_read(sc, ptr + 4));
3279 EN_WRAPADD(MID_DRQOFF, MID_DRQEND, ptr, 8);
3283 /* Do not staticize - meant for calling from DDB! */
3285 en_dump(int unit, int level)
3287 struct en_softc *sc;
3292 dc = devclass_find("en");
3294 printf("%s: can't find devclass!\n", __func__);
3297 maxunit = devclass_get_maxunit(dc);
3298 for (lcv = 0 ; lcv < maxunit ; lcv++) {
3299 sc = devclass_get_softc(dc, lcv);
3302 if (unit != -1 && unit != lcv)
3305 if_printf(&sc->ifatm.ifnet, "dumping device at level 0x%b\n",
3308 if (sc->dtq_us == 0) {
3309 printf("<hasn't been en_init'd yet>\n");
3313 if (level & END_STATS)
3314 en_dump_stats(&sc->stats);
3315 if (level & END_MREGS)
3321 if (level & END_DTQ)
3323 if (level & END_DRQ)
3326 if (level & END_SWSL) {
3327 printf(" swslist [size=%d]: ", sc->swsl_size);
3328 for (cnt = sc->swsl_head ; cnt != sc->swsl_tail ;
3329 cnt = (cnt + 1) % MID_SL_N)
3330 printf("0x%x ", sc->swslist[cnt]);
3338 * en_dumpmem: dump the memory
3340 * Do not staticize - meant for calling from DDB!
3343 en_dumpmem(int unit, int addr, int len)
3345 struct en_softc *sc;
3349 dc = devclass_find("en");
3351 printf("%s: can't find devclass\n", __func__);
3354 sc = devclass_get_softc(dc, unit);
3356 printf("%s: invalid unit number: %d\n", __func__, unit);
3361 if (addr < MID_RAMOFF || addr + len * 4 > MID_MAXOFF || len <= 0) {
3362 printf("invalid addr/len number: %d, %d\n", addr, len);
3365 printf("dumping %d words starting at offset 0x%x\n", len, addr);
3367 reg = en_read(sc, addr);
3368 printf("mem[0x%x] = 0x%x\n", addr, reg);