3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * The TST allocation algorithm is from the IDT driver which is:
29 * Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
30 * All rights reserved.
32 * Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
33 * All rights reserved.
35 * Author: Hartmut Brandt <harti@freebsd.org>
37 * Driver for IDT77252 based cards like ProSum's.
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
46 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/malloc.h>
50 #include <sys/kernel.h>
52 #include <sys/errno.h>
54 #include <sys/module.h>
56 #include <sys/mutex.h>
57 #include <sys/sysctl.h>
58 #include <sys/queue.h>
59 #include <sys/condvar.h>
60 #include <sys/endian.h>
63 #include <sys/sockio.h>
65 #include <sys/socket.h>
68 #include <net/if_var.h>
69 #include <net/if_media.h>
70 #include <net/if_atm.h>
71 #include <net/route.h>
75 #include <netinet/in.h>
76 #include <netinet/if_atm.h>
78 #include <machine/bus.h>
79 #include <machine/resource.h>
82 #include <sys/mbpool.h>
84 #include <dev/utopia/utopia.h>
85 #include <dev/patm/idt77252reg.h>
86 #include <dev/patm/if_patmvar.h>
88 static struct mbuf *patm_tx_pad(struct patm_softc *sc, struct mbuf *m0);
89 static void patm_launch(struct patm_softc *sc, struct patm_scd *scd);
91 static struct patm_txmap *patm_txmap_get(struct patm_softc *);
92 static void patm_load_txbuf(void *, bus_dma_segment_t *, int,
95 static void patm_tst_alloc(struct patm_softc *sc, struct patm_vcc *vcc);
96 static void patm_tst_free(struct patm_softc *sc, struct patm_vcc *vcc);
97 static void patm_tst_timer(void *p);
98 static void patm_tst_update(struct patm_softc *);
100 static void patm_tct_start(struct patm_softc *sc, struct patm_vcc *);
102 static const char *dump_scd(struct patm_softc *sc, struct patm_scd *scd)
104 static void patm_tct_print(struct patm_softc *sc, u_int cid) __unused;
107 * Structure for communication with the loader function for transmission
110 struct patm_softc *sc;
111 struct patm_scd *scd; /* scheduling channel */
112 struct patm_vcc *vcc; /* the VCC of this PDU */
114 u_int hdr; /* cell header */
117 static __inline u_int
118 cbr2slots(struct patm_softc *sc, struct patm_vcc *vcc)
120 /* compute the number of slots we need, make sure to get at least
121 * the specified PCR */
122 return ((u_int)(((uint64_t)(sc->mmap->tst_size - 1) *
123 vcc->vcc.tparam.pcr + IFP2IFATM(sc->ifp)->mib.pcr - 1) / IFP2IFATM(sc->ifp)->mib.pcr));
126 static __inline u_int
127 slots2cr(struct patm_softc *sc, u_int slots)
129 return ((slots * IFP2IFATM(sc->ifp)->mib.pcr + sc->mmap->tst_size - 2) /
130 (sc->mmap->tst_size - 1));
133 /* check if we can open this one */
135 patm_tx_vcc_can_open(struct patm_softc *sc, struct patm_vcc *vcc)
138 /* check resources */
139 switch (vcc->vcc.traffic) {
141 case ATMIO_TRAFFIC_CBR:
143 u_int slots = cbr2slots(sc, vcc);
145 if (slots > sc->tst_free + sc->tst_reserve)
150 case ATMIO_TRAFFIC_VBR:
151 if (vcc->vcc.tparam.scr > sc->bwrem)
153 if (vcc->vcc.tparam.pcr > IFP2IFATM(sc->ifp)->mib.pcr)
155 if (vcc->vcc.tparam.scr > vcc->vcc.tparam.pcr ||
156 vcc->vcc.tparam.mbs == 0)
160 case ATMIO_TRAFFIC_ABR:
161 if (vcc->vcc.tparam.tbe == 0 ||
162 vcc->vcc.tparam.nrm == 0)
163 /* needed to compute CRM */
165 if (vcc->vcc.tparam.pcr > IFP2IFATM(sc->ifp)->mib.pcr ||
166 vcc->vcc.tparam.icr > vcc->vcc.tparam.pcr ||
167 vcc->vcc.tparam.mcr > vcc->vcc.tparam.icr)
169 if (vcc->vcc.tparam.mcr > sc->bwrem ||
170 vcc->vcc.tparam.icr > sc->bwrem)
178 #define NEXT_TAG(T) do { \
179 (T) = ((T) + 1) % IDT_TSQE_TAG_SPACE; \
186 patm_tx_vcc_open(struct patm_softc *sc, struct patm_vcc *vcc)
188 struct patm_scd *scd;
190 if (vcc->vcc.traffic == ATMIO_TRAFFIC_UBR) {
193 vcc->vflags |= PATM_VCC_TX_OPEN;
198 scd = patm_scd_alloc(sc);
200 /* should not happen */
201 patm_printf(sc, "out of SCDs\n");
205 patm_scd_setup(sc, scd);
206 patm_tct_setup(sc, scd, vcc);
208 if (vcc->vcc.traffic != ATMIO_TRAFFIC_CBR)
209 patm_tct_start(sc, vcc);
211 vcc->vflags |= PATM_VCC_TX_OPEN;
215 * close the given vcc for transmission
218 patm_tx_vcc_close(struct patm_softc *sc, struct patm_vcc *vcc)
220 struct patm_scd *scd;
223 vcc->vflags |= PATM_VCC_TX_CLOSING;
225 if (vcc->vcc.traffic == ATMIO_TRAFFIC_UBR) {
226 /* let the queue PDUs go out */
228 vcc->vflags &= ~(PATM_VCC_TX_OPEN | PATM_VCC_TX_CLOSING);
233 /* empty the waitq */
235 _IF_DEQUEUE(&scd->q, m);
241 if (scd->num_on_card == 0) {
243 vcc->vflags &= ~PATM_VCC_TX_OPEN;
245 if (vcc->vcc.traffic == ATMIO_TRAFFIC_CBR)
246 patm_tst_free(sc, vcc);
248 patm_sram_write4(sc, scd->sram + 0, 0, 0, 0, 0);
249 patm_sram_write4(sc, scd->sram + 4, 0, 0, 0, 0);
250 patm_scd_free(sc, scd);
253 vcc->vflags &= ~PATM_VCC_TX_CLOSING;
258 /* speed up transmission */
259 patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_UIER(vcc->cid, 0xff));
260 patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_ULACR(vcc->cid, 0xff));
262 /* wait for the interrupt to drop the number to 0 */
263 patm_debug(sc, VCC, "%u buffers still on card", scd->num_on_card);
266 /* transmission side finally closed */
268 patm_tx_vcc_closed(struct patm_softc *sc, struct patm_vcc *vcc)
271 patm_debug(sc, VCC, "%u.%u TX closed", vcc->vcc.vpi, vcc->vcc.vci);
273 if (vcc->vcc.traffic == ATMIO_TRAFFIC_VBR)
274 sc->bwrem += vcc->vcc.tparam.scr;
278 * Pull off packets from the interface queue and try to transmit them.
279 * If the transmission fails because of a full transmit channel, we drop
280 * packets for CBR and queue them for other channels up to limit.
281 * This limit should depend on the CDVT for VBR and ABR, but it doesn't.
284 patm_start(struct ifnet *ifp)
286 struct patm_softc *sc = ifp->if_softc;
288 struct atm_pseudohdr *aph;
290 struct patm_vcc *vcc;
293 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
294 mtx_unlock(&sc->mtx);
300 IF_DEQUEUE(&ifp->if_snd, m);
304 /* split of pseudo header */
305 if (m->m_len < sizeof(*aph) &&
306 (m = m_pullup(m, sizeof(*aph))) == NULL) {
307 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
311 aph = mtod(m, struct atm_pseudohdr *);
312 vci = ATM_PH_VCI(aph);
313 vpi = ATM_PH_VPI(aph);
314 m_adj(m, sizeof(*aph));
316 /* reject empty packets */
317 if (m->m_pkthdr.len == 0) {
319 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
323 /* check whether this is a legal vcc */
324 if (!LEGAL_VPI(sc, vpi) || !LEGAL_VCI(sc, vci) || vci == 0) {
326 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
329 cid = PATM_CID(sc, vpi, vci);
333 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
337 /* must be multiple of 48 if not AAL5 */
338 if (vcc->vcc.aal == ATMIO_AAL_0 ||
339 vcc->vcc.aal == ATMIO_AAL_34) {
340 /* XXX AAL3/4 format? */
341 if (m->m_pkthdr.len % 48 != 0 &&
342 (m = patm_tx_pad(sc, m)) == NULL) {
343 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
346 } else if (vcc->vcc.aal == ATMIO_AAL_RAW) {
347 switch (vcc->vflags & PATM_RAW_FORMAT) {
351 if (m->m_pkthdr.len != 53) {
352 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
359 if (m->m_pkthdr.len != 52) {
360 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
367 if (m->m_pkthdr.len != 64) {
368 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
377 m->m_pkthdr.PH_loc.ptr = vcc;
379 /* try to put it on the channels queue */
380 if (_IF_QFULL(&vcc->scd->q)) {
381 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
382 sc->stats.tx_qfull++;
386 _IF_ENQUEUE(&vcc->scd->q, m);
389 if (!(vcc->vcc.flags & ATMIO_FLAG_NG) &&
390 (vcc->vcc.aal == ATMIO_AAL_5) &&
391 (vcc->vcc.flags & ATM_PH_LLCSNAP))
395 /* kick the channel to life */
396 patm_launch(sc, vcc->scd);
399 mtx_unlock(&sc->mtx);
403 * Pad non-AAL5 packet to a multiple of 48-byte.
404 * We assume AAL0 only. We have still to decide on the format of AAL3/4.
407 patm_tx_pad(struct patm_softc *sc, struct mbuf *m0)
409 struct mbuf *last, *m;
410 u_int plen, pad, space;
412 plen = m_length(m0, &last);
413 if (plen != m0->m_pkthdr.len) {
414 patm_printf(sc, "%s: mbuf length mismatch %d %u\n", __func__,
415 m0->m_pkthdr.len, plen);
416 m0->m_pkthdr.len = plen;
419 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
425 pad = 48 - plen % 48;
426 m0->m_pkthdr.len += pad;
427 if (M_WRITABLE(last)) {
428 if (M_TRAILINGSPACE(last) >= pad) {
429 bzero(last->m_data + last->m_len, pad);
433 space = M_LEADINGSPACE(last);
434 if (space + M_TRAILINGSPACE(last) >= pad) {
435 bcopy(last->m_data, last->m_data + space, last->m_len);
436 last->m_data -= space;
437 bzero(last->m_data + last->m_len, pad);
442 MGET(m, M_NOWAIT, MT_DATA);
445 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
448 bzero(mtod(m, u_char *), pad);
456 * Try to put as many packets from the channels queue onto the channel
459 patm_launch(struct patm_softc *sc, struct patm_scd *scd)
462 struct mbuf *m, *tmp;
464 struct patm_txmap *map;
470 /* limit the number of outstanding packets to the tag space */
471 while (scd->num_on_card < IDT_TSQE_TAG_SPACE) {
472 /* get the next packet */
473 _IF_DEQUEUE(&scd->q, m);
477 a.vcc = m->m_pkthdr.PH_loc.ptr;
479 /* we must know the number of segments beforehand - count
480 * this may actually give a wrong number of segments for
481 * AAL_RAW where we still need to remove the cell header */
483 for (tmp = m; tmp != NULL; tmp = tmp->m_next)
487 /* check whether there is space in the queue */
488 if (segs >= scd->space) {
490 _IF_PREPEND(&scd->q, m);
491 sc->stats.tx_out_of_tbds++;
496 if ((map = patm_txmap_get(sc)) == NULL) {
497 _IF_PREPEND(&scd->q, m);
498 sc->stats.tx_out_of_maps++;
503 m->m_pkthdr.PH_loc.ptr = map;
507 if (a.vcc->vcc.aal == ATMIO_AAL_RAW) {
510 m_copydata(m, 0, 4, hdr);
511 a.hdr = (hdr[0] << 24) | (hdr[1] << 16) |
512 (hdr[2] << 8) | hdr[3];
514 switch (a.vcc->vflags & PATM_RAW_FORMAT) {
530 a.hdr = IDT_TBD_HDR(a.vcc->vcc.vpi, a.vcc->vcc.vci,
533 error = bus_dmamap_load_mbuf(sc->tx_tag, map->map, m,
534 patm_load_txbuf, &a, BUS_DMA_NOWAIT);
535 if (error == EFBIG) {
536 if ((m = m_defrag(m, M_NOWAIT)) == NULL) {
537 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
540 error = bus_dmamap_load_mbuf(sc->tx_tag, map->map, m,
541 patm_load_txbuf, &a, BUS_DMA_NOWAIT);
544 sc->stats.tx_load_err++;
545 if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
546 SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
551 if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1);
556 * Load the DMA segments into the scheduling channel
559 patm_load_txbuf(void *uarg, bus_dma_segment_t *segs, int nseg,
560 bus_size_t mapsize, int error)
562 struct txarg *a= uarg;
563 struct patm_scd *scd = a->scd;
565 struct idt_tbd *tbd = NULL;
566 u_int rest = mapsize;
573 if (segs->ds_len == 0) {
574 /* transmit buffer length must be > 0 */
579 /* rest after this buffer */
580 rest -= segs->ds_len;
582 /* put together status word */
584 if (rest < 48 /* && a->vcc->vcc.aal != ATMIO_AAL_5 */)
585 /* last cell is in this buffer */
588 if (a->vcc->vcc.aal == ATMIO_AAL_5)
590 else if (a->vcc->vcc.aal == ATMIO_AAL_34)
597 /* AAL5 PDU length (unpadded) */
598 if (a->vcc->vcc.aal == ATMIO_AAL_5)
604 w1 |= IDT_TBD_TSIF | IDT_TBD_GTSI |
605 (scd->tag << IDT_TBD_TAG_SHIFT);
607 tbd = &scd->scq[scd->tail];
609 tbd->flags = htole32(w1);
610 tbd->addr = htole32(segs->ds_addr);
611 tbd->aal5 = htole32(w3);
612 tbd->hdr = htole32(a->hdr);
614 patm_debug(a->sc, TX, "TBD(%u): %08x %08x %08x %08x",
615 scd->tail, w1, segs->ds_addr, w3, a->hdr);
617 /* got to next entry */
618 if (++scd->tail == IDT_SCQ_SIZE)
627 KASSERT(rest == 0, ("bad mbuf"));
628 KASSERT(cnt > 0, ("no segs"));
629 KASSERT(scd->space > 0, ("scq full"));
631 KASSERT(scd->on_card[scd->tag] == NULL,
632 ("scd on_card wedged %u%s", scd->tag, dump_scd(a->sc, scd)));
633 scd->on_card[scd->tag] = a->mbuf;
634 a->mbuf->m_pkthdr.csum_data = cnt;
638 patm_debug(a->sc, TX, "SCD tail %u (%lx:%lx)", scd->tail,
639 (u_long)scd->phy, (u_long)scd->phy + (scd->tail << IDT_TBD_SHIFT));
640 patm_sram_write(a->sc, scd->sram,
641 scd->phy + (scd->tail << IDT_TBD_SHIFT));
643 if (patm_sram_read(a->sc, a->vcc->cid * 8 + 3) & IDT_TCT_IDLE) {
645 * if the connection is idle start it. We cannot rely
646 * on a flag set by patm_tx_idle() here, because sometimes
647 * the card seems to place an idle TSI into the TSQ but
648 * forgets to raise an interrupt.
650 patm_nor_write(a->sc, IDT_NOR_TCMDQ,
651 IDT_TCMDQ_START(a->vcc->cid));
659 patm_tx(struct patm_softc *sc, u_int stamp, u_int status)
661 u_int cid, tag, last;
663 struct patm_vcc *vcc;
664 struct patm_scd *scd;
665 struct patm_txmap *map;
667 /* get the connection */
668 cid = PATM_CID(sc, IDT_TBD_VPI(status), IDT_TBD_VCI(status));
669 if ((vcc = sc->vccs[cid]) == NULL) {
670 /* closed UBR connection */
675 tag = IDT_TSQE_TAG(stamp);
677 last = scd->last_tag;
679 patm_printf(sc, "same tag %u\n", tag);
683 /* Errata 12 requests us to free all entries up to the one
684 * with the given tag. */
686 /* next tag to try */
689 m = scd->on_card[last];
690 KASSERT(m != NULL, ("%stag=%u", dump_scd(sc, scd), tag));
691 scd->on_card[last] = NULL;
692 patm_debug(sc, TX, "ok tag=%x", last);
694 map = m->m_pkthdr.PH_loc.ptr;
695 scd->space += m->m_pkthdr.csum_data;
697 bus_dmamap_sync(sc->tx_tag, map->map,
698 BUS_DMASYNC_POSTWRITE);
699 bus_dmamap_unload(sc->tx_tag, map->map);
701 SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
704 if (vcc->vflags & PATM_VCC_TX_CLOSING) {
705 if (scd->num_on_card == 0) {
706 /* done with this VCC */
707 if (vcc->vcc.traffic == ATMIO_TRAFFIC_CBR)
708 patm_tst_free(sc, vcc);
710 patm_sram_write4(sc, scd->sram + 0, 0, 0, 0, 0);
711 patm_sram_write4(sc, scd->sram + 4, 0, 0, 0, 0);
712 patm_scd_free(sc, scd);
715 vcc->vflags &= ~PATM_VCC_TX_CLOSING;
717 if (vcc->vcc.flags & ATMIO_FLAG_ASYNC) {
718 patm_tx_vcc_closed(sc, vcc);
719 if (!(vcc->vflags & PATM_VCC_OPEN))
720 patm_vcc_closed(sc, vcc);
722 cv_signal(&sc->vcc_cv);
725 patm_debug(sc, VCC, "%u buffers still on card",
728 if (vcc->vcc.traffic == ATMIO_TRAFFIC_ABR) {
729 /* insist on speeding up transmission for ABR */
730 patm_nor_write(sc, IDT_NOR_TCMDQ,
731 IDT_TCMDQ_UIER(vcc->cid, 0xff));
732 patm_nor_write(sc, IDT_NOR_TCMDQ,
733 IDT_TCMDQ_ULACR(vcc->cid, 0xff));
737 } while (last != tag);
740 if (vcc->vcc.traffic == ATMIO_TRAFFIC_ABR) {
743 acri = (patm_sram_read(sc, 8 * cid + 2) >> IDT_TCT_ACRI_SHIFT)
745 cps = IFP2IFATM(sc->ifp)->mib.pcr * 32 /
746 ((1 << (acri >> 10)) * (acri & 0x3ff));
748 if (cps != vcc->cps) {
749 patm_debug(sc, VCC, "ACRI=%04x CPS=%u", acri, cps);
750 ATMEV_SEND_ACR_CHANGED(IFP2IFATM(sc->ifp), vcc->vcc.vpi,
756 patm_launch(sc, scd);
760 * VBR/ABR connection went idle
761 * Either restart it or set the idle flag.
764 patm_tx_idle(struct patm_softc *sc, u_int cid)
766 struct patm_vcc *vcc;
768 patm_debug(sc, VCC, "idle %u", cid);
770 if ((vcc = sc->vccs[cid]) != NULL &&
771 (vcc->vflags & (PATM_VCC_TX_OPEN | PATM_VCC_TX_CLOSING)) != 0 &&
772 vcc->scd != NULL && (vcc->scd->num_on_card != 0 ||
773 _IF_QLEN(&vcc->scd->q) != 0)) {
775 * If there is any packet outstanding in the SCD re-activate
776 * the channel and kick it.
778 patm_nor_write(sc, IDT_NOR_TCMDQ,
779 IDT_TCMDQ_START(vcc->cid));
781 patm_launch(sc, vcc->scd);
786 * Convert a (24bit) rate to the atm-forum form
787 * Our rate is never larger than 19 bit.
798 while (cps > (1024 - 1)) {
802 return ((1 << 14) | (e << 9) | (cps & 0x1ff));
806 * Do a binary search on the log2rate table to convert the rate
807 * to its log form. This assumes that the ATM-Forum form is monotonically
808 * increasing with the plain cell rate.
811 rate2log(struct patm_softc *sc, u_int rate)
814 u_int lower, upper, mid, done, val, afr;
816 afr = cps2atmf(rate);
818 if (sc->flags & PATM_25M)
819 tbl = patm_rtables25;
821 tbl = patm_rtables155;
827 mid = (lower + upper) / 2;
828 val = tbl[mid] >> 17;
829 if (val == afr || upper == lower)
836 if (val > afr && mid > 0)
842 * Return the table index for an increase table. The increase table
843 * must be selected not by the RIF itself, but by PCR/2^RIF. Each table
844 * represents an additive increase of a cell rate that can be computed
845 * from the first table entry (the value in this entry will not be clamped
849 get_air_table(struct patm_softc *sc, u_int rif, u_int pcr)
852 u_int increase, base, lair0, ret, t, cps;
854 #define GET_ENTRY(TAB, IDX) (0xffff & ((IDX & 1) ? \
855 (tbl[512 + (IDX / 2) + 128 * (TAB)] >> 16) : \
856 (tbl[512 + (IDX / 2) + 128 * (TAB)])))
861 #define DIFF_TO_FP(D) (((D) & ((1 << MANT_BITS) - 1)) << ((D) >> MANT_BITS))
862 #define AFR_TO_INT(A) ((1 << (((A) >> 9) & 0x1f)) * \
863 (512 + ((A) & 0x1ff)) / 512 * ((A) >> 14))
865 if (sc->flags & PATM_25M)
866 tbl = patm_rtables25;
868 tbl = patm_rtables155;
869 if (rif >= patm_rtables_ntab)
870 rif = patm_rtables_ntab - 1;
871 increase = pcr >> rif;
874 for (t = 0; t < patm_rtables_ntab; t++) {
875 /* get base rate of this table */
876 base = GET_ENTRY(t, 0);
877 /* convert this to fixed point */
878 lair0 = DIFF_TO_FP(base) >> FRAC_BITS;
880 /* get the CPS from the log2rate table */
881 cps = AFR_TO_INT(tbl[lair0] >> 17) - 10;
895 patm_tct_setup(struct patm_softc *sc, struct patm_scd *scd,
896 struct patm_vcc *vcc)
901 u_int tmp, crm, rdf, cdf, air, mcr;
903 bzero(tct, sizeof(tct));
905 /* special case for UBR0 */
907 tct[0] = IDT_TCT_UBR | scd->sram;
908 tct[7] = IDT_TCT_UBR_FLG;
912 switch (vcc->vcc.traffic) {
914 case ATMIO_TRAFFIC_CBR:
915 patm_tst_alloc(sc, vcc);
916 tct[0] = IDT_TCT_CBR | scd->sram;
917 /* must account for what was really allocated */
920 case ATMIO_TRAFFIC_VBR:
921 /* compute parameters for the TCT */
922 scd->init_er = rate2log(sc, vcc->vcc.tparam.pcr);
923 scd->lacr = rate2log(sc, vcc->vcc.tparam.scr);
925 /* get the 16-bit fraction of SCR/PCR
926 * both a 24 bit. Do it the simple way. */
927 token = (uint64_t)(vcc->vcc.tparam.scr << 16) /
930 patm_debug(sc, VCC, "VBR: init_er=%u lacr=%u "
931 "token=0x%04x\n", scd->init_er, scd->lacr, token);
933 tct[0] = IDT_TCT_VBR | scd->sram;
934 tct[2] = IDT_TCT_TSIF;
935 tct[3] = IDT_TCT_IDLE | IDT_TCT_HALT;
936 tct[4] = IDT_TCT_MAXIDLE;
938 if ((mbs = vcc->vcc.tparam.mbs) > 0xff)
940 tct[6] = (mbs << 16) | token;
941 sc->bwrem -= vcc->vcc.tparam.scr;
944 case ATMIO_TRAFFIC_ABR:
945 scd->init_er = rate2log(sc, vcc->vcc.tparam.pcr);
946 scd->lacr = rate2log(sc, vcc->vcc.tparam.icr);
947 mcr = rate2log(sc, vcc->vcc.tparam.mcr);
950 tmp = vcc->vcc.tparam.tbe / vcc->vcc.tparam.nrm;
951 if (tmp * vcc->vcc.tparam.nrm < vcc->vcc.tparam.tbe)
953 for (crm = 1; tmp > (1 << crm); crm++)
958 air = get_air_table(sc, vcc->vcc.tparam.rif,
959 vcc->vcc.tparam.pcr);
961 if ((rdf = vcc->vcc.tparam.rdf) >= patm_rtables_ntab)
962 rdf = patm_rtables_ntab - 1;
963 rdf += patm_rtables_ntab + 4;
965 if ((cdf = vcc->vcc.tparam.cdf) >= patm_rtables_ntab)
966 cdf = patm_rtables_ntab - 1;
967 cdf += patm_rtables_ntab + 4;
969 patm_debug(sc, VCC, "ABR: init_er=%u lacr=%u mcr=%u "
970 "crm=%u air=%u rdf=%u cdf=%u\n", scd->init_er,
971 scd->lacr, mcr, crm, air, rdf, cdf);
973 tct[0] = IDT_TCT_ABR | scd->sram;
974 tct[1] = crm << IDT_TCT_CRM_SHIFT;
975 tct[3] = IDT_TCT_HALT | IDT_TCT_IDLE |
976 (4 << IDT_TCT_NAGE_SHIFT);
977 tct[4] = mcr << IDT_TCT_LMCR_SHIFT;
978 tct[5] = (cdf << IDT_TCT_CDF_SHIFT) |
979 (rdf << IDT_TCT_RDF_SHIFT) |
980 (air << IDT_TCT_AIR_SHIFT);
982 sc->bwrem -= vcc->vcc.tparam.mcr;
987 patm_sram_write4(sc, sram + 0, tct[0], tct[1], tct[2], tct[3]);
988 patm_sram_write4(sc, sram + 4, tct[4], tct[5], tct[6], tct[7]);
990 patm_debug(sc, VCC, "TCT[%u]: %08x %08x %08x %08x %08x %08x %08x %08x",
991 sram / 8, patm_sram_read(sc, sram + 0),
992 patm_sram_read(sc, sram + 1), patm_sram_read(sc, sram + 2),
993 patm_sram_read(sc, sram + 3), patm_sram_read(sc, sram + 4),
994 patm_sram_read(sc, sram + 5), patm_sram_read(sc, sram + 6),
995 patm_sram_read(sc, sram + 7));
1002 patm_tct_start(struct patm_softc *sc, struct patm_vcc *vcc)
1005 patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_UIER(vcc->cid,
1006 vcc->scd->init_er));
1007 patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_SLACR(vcc->cid,
1012 patm_tct_print(struct patm_softc *sc, u_int cid)
1015 u_int sram = cid * 8;
1018 patm_debug(sc, VCC, "TCT[%u]: %08x %08x %08x %08x %08x %08x %08x %08x",
1019 sram / 8, patm_sram_read(sc, sram + 0),
1020 patm_sram_read(sc, sram + 1), patm_sram_read(sc, sram + 2),
1021 patm_sram_read(sc, sram + 3), patm_sram_read(sc, sram + 4),
1022 patm_sram_read(sc, sram + 5), patm_sram_read(sc, sram + 6),
1023 patm_sram_read(sc, sram + 7));
1030 patm_scd_setup(struct patm_softc *sc, struct patm_scd *scd)
1032 patm_sram_write4(sc, scd->sram + 0,
1033 scd->phy, 0, 0xffffffff, 0);
1034 patm_sram_write4(sc, scd->sram + 4,
1037 patm_debug(sc, VCC, "SCD(%x): %08x %08x %08x %08x %08x %08x %08x %08x",
1039 patm_sram_read(sc, scd->sram + 0),
1040 patm_sram_read(sc, scd->sram + 1),
1041 patm_sram_read(sc, scd->sram + 2),
1042 patm_sram_read(sc, scd->sram + 3),
1043 patm_sram_read(sc, scd->sram + 4),
1044 patm_sram_read(sc, scd->sram + 5),
1045 patm_sram_read(sc, scd->sram + 6),
1046 patm_sram_read(sc, scd->sram + 7));
1050 * Grow the TX map table if possible
1053 patm_txmaps_grow(struct patm_softc *sc)
1056 struct patm_txmap *map;
1059 if (sc->tx_nmaps >= sc->tx_maxmaps)
1062 for (i = sc->tx_nmaps; i < sc->tx_nmaps + PATM_CFG_TXMAPS_STEP; i++) {
1063 map = uma_zalloc(sc->tx_mapzone, M_NOWAIT);
1064 err = bus_dmamap_create(sc->tx_tag, 0, &map->map);
1066 uma_zfree(sc->tx_mapzone, map);
1069 SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
1076 * Allocate a transmission map
1078 static struct patm_txmap *
1079 patm_txmap_get(struct patm_softc *sc)
1081 struct patm_txmap *map;
1083 if ((map = SLIST_FIRST(&sc->tx_maps_free)) == NULL) {
1084 patm_txmaps_grow(sc);
1085 if ((map = SLIST_FIRST(&sc->tx_maps_free)) == NULL)
1088 SLIST_REMOVE_HEAD(&sc->tx_maps_free, link);
1093 * Look whether we are in the process of updating the TST on the chip.
1094 * If we are set the flag that we need another update.
1095 * If we are not start the update.
1097 static __inline void
1098 patm_tst_start(struct patm_softc *sc)
1101 if (!(sc->tst_state & TST_PENDING)) {
1102 sc->tst_state |= TST_PENDING;
1103 if (!(sc->tst_state & TST_WAIT)) {
1104 /* timer not running */
1105 patm_tst_update(sc);
1111 * Allocate TST entries to a CBR connection
1114 patm_tst_alloc(struct patm_softc *sc, struct patm_vcc *vcc)
1121 mtx_lock(&sc->tst_lock);
1123 /* compute the number of slots we need, make sure to get at least
1124 * the specified PCR */
1125 slots = cbr2slots(sc, vcc);
1126 vcc->scd->slots = slots;
1127 sc->bwrem -= slots2cr(sc, slots);
1129 patm_debug(sc, TST, "tst_alloc: cbr=%u link=%u tst=%u slots=%u",
1130 vcc->vcc.tparam.pcr, IFP2IFATM(sc->ifp)->mib.pcr, sc->mmap->tst_size, slots);
1132 qmax = sc->mmap->tst_size - 1;
1135 pspc = pmax / slots;
1137 pptr = pspc >> 1; /* starting point */
1145 if (sc->tst_soft[qptr] != IDT_TST_VBR) {
1146 /* used - try next */
1150 patm_debug(sc, TST, "slot[%u] = %u.%u diff=%d", qptr,
1151 vcc->vcc.vpi, vcc->vcc.vci, (int)qptr - (int)last);
1154 sc->tst_soft[qptr] = IDT_TST_CBR | vcc->cid | TST_BOTH;
1157 if ((pptr += pspc) >= pmax)
1164 mtx_unlock(&sc->tst_lock);
1168 * Free a CBR connection's TST entries
1171 patm_tst_free(struct patm_softc *sc, struct patm_vcc *vcc)
1175 mtx_lock(&sc->tst_lock);
1176 for (i = 0; i < sc->mmap->tst_size - 1; i++) {
1177 if ((sc->tst_soft[i] & IDT_TST_MASK) == vcc->cid) {
1178 sc->tst_soft[i] = IDT_TST_VBR | TST_BOTH;
1182 sc->bwrem += slots2cr(sc, vcc->scd->slots);
1184 mtx_unlock(&sc->tst_lock);
1188 * Write the soft TST into the idle incore TST and start the wait timer.
1189 * We assume that we hold the tst lock.
1192 patm_tst_update(struct patm_softc *sc)
1194 u_int flag; /* flag to clear from soft TST */
1195 u_int idle; /* the idle TST */
1196 u_int act; /* the active TST */
1199 if (sc->tst_state & TST_ACT1) {
1208 /* update the idle one */
1209 for (i = 0; i < sc->mmap->tst_size - 1; i++)
1210 if (sc->tst_soft[i] & flag) {
1211 patm_sram_write(sc, sc->tst_base[idle] + i,
1212 sc->tst_soft[i] & ~TST_BOTH);
1213 sc->tst_soft[i] &= ~flag;
1215 /* the used one jump to the idle one */
1216 patm_sram_write(sc, sc->tst_jump[act],
1217 IDT_TST_BR | (sc->tst_base[idle] << 2));
1219 /* wait for the chip to jump */
1220 sc->tst_state &= ~TST_PENDING;
1221 sc->tst_state |= TST_WAIT;
1223 callout_reset(&sc->tst_callout, 1, patm_tst_timer, sc);
1227 * Timer for TST updates
1230 patm_tst_timer(void *p)
1232 struct patm_softc *sc = p;
1233 u_int act; /* active TST */
1234 u_int now; /* current place in TST */
1236 mtx_lock(&sc->tst_lock);
1238 if (sc->tst_state & TST_WAIT) {
1239 /* ignore the PENDING state while we are waiting for
1240 * the chip to switch tables. Once the switch is done,
1241 * we will again lock at PENDING */
1242 act = (sc->tst_state & TST_ACT1) ? 1 : 0;
1243 now = patm_nor_read(sc, IDT_NOR_NOW) >> 2;
1244 if (now >= sc->tst_base[act] && now <= sc->tst_jump[act]) {
1246 callout_reset(&sc->tst_callout, 1, patm_tst_timer, sc);
1249 sc->tst_state &= ~TST_WAIT;
1250 /* change back jump */
1251 patm_sram_write(sc, sc->tst_jump[act],
1252 IDT_TST_BR | (sc->tst_base[act] << 2));
1255 sc->tst_state ^= TST_ACT1;
1258 if (sc->tst_state & TST_PENDING)
1259 /* we got another update request while the timer was running. */
1260 patm_tst_update(sc);
1263 mtx_unlock(&sc->tst_lock);
1267 dump_scd(struct patm_softc *sc, struct patm_scd *scd)
1271 for (i = 0; i < IDT_TSQE_TAG_SPACE; i++)
1272 printf("on_card[%u] = %p\n", i, scd->on_card[i]);
1273 printf("space=%u tag=%u num_on_card=%u last_tag=%u\n",
1274 scd->space, scd->tag, scd->num_on_card, scd->last_tag);