if_patm_tx.c revision 117872
1/*
2 * Copyright (c) 2003
3 *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * 	All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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
25 * SUCH DAMAGE.
26 *
27 * The TST allocation algorithm is from the IDT driver which is:
28 *
29 *	Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
30 *	All rights reserved.
31 *
32 *	Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
33 *	All rights reserved.
34 *
35 * Author: Hartmut Brandt <harti@freebsd.org>
36 *
37 * Driver for IDT77252 based cards like ProSum's.
38 */
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: head/sys/dev/patm/if_patm_tx.c 117872 2003-07-22 08:20:09Z harti $");
41
42#include "opt_inet.h"
43#include "opt_natm.h"
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/malloc.h>
49#include <sys/kernel.h>
50#include <sys/bus.h>
51#include <sys/errno.h>
52#include <sys/conf.h>
53#include <sys/module.h>
54#include <sys/lock.h>
55#include <sys/mutex.h>
56#include <sys/sysctl.h>
57#include <sys/queue.h>
58#include <sys/condvar.h>
59#include <sys/endian.h>
60#include <vm/uma.h>
61
62#include <sys/sockio.h>
63#include <sys/mbuf.h>
64#include <sys/socket.h>
65
66#include <net/if.h>
67#include <net/if_media.h>
68#include <net/if_atm.h>
69#include <net/route.h>
70#ifdef ENABLE_BPF
71#include <net/bpf.h>
72#endif
73#include <netinet/in.h>
74#include <netinet/if_atm.h>
75
76#include <machine/bus.h>
77#include <machine/resource.h>
78#include <sys/bus.h>
79#include <sys/rman.h>
80#include <sys/mbpool.h>
81
82#include <dev/utopia/utopia.h>
83#include <dev/patm/idt77252reg.h>
84#include <dev/patm/if_patmvar.h>
85
86static struct mbuf *patm_tx_pad(struct patm_softc *sc, struct mbuf *m0);
87static void patm_launch(struct patm_softc *sc, struct patm_scd *scd);
88
89static struct patm_txmap *patm_txmap_get(struct patm_softc *);
90static void patm_load_txbuf(void *, bus_dma_segment_t *, int,
91    bus_size_t, int);
92
93static void patm_tst_alloc(struct patm_softc *sc, struct patm_vcc *vcc);
94static void patm_tst_free(struct patm_softc *sc, struct patm_vcc *vcc);
95static void patm_tst_timer(void *p);
96static void patm_tst_update(struct patm_softc *);
97
98static void patm_tct_start(struct patm_softc *sc, struct patm_vcc *);
99
100static const char *dump_scd(struct patm_softc *sc, struct patm_scd *scd)
101    __unused;
102static void patm_tct_print(struct patm_softc *sc, u_int cid) __unused;
103
104/*
105 * Structure for communication with the loader function for transmission
106 */
107struct txarg {
108	struct patm_softc *sc;
109	struct patm_scd	*scd;		/* scheduling channel */
110	struct patm_vcc	*vcc;		/* the VCC of this PDU */
111	struct mbuf	*mbuf;
112	u_int		hdr;		/* cell header */
113};
114
115static __inline u_int
116cbr2slots(struct patm_softc *sc, struct patm_vcc *vcc)
117{
118	/* compute the number of slots we need, make sure to get at least
119	 * the specified PCR */
120	return ((u_int)(((uint64_t)(sc->mmap->tst_size - 1) *
121	    vcc->vcc.tparam.pcr + sc->ifatm.mib.pcr - 1) / sc->ifatm.mib.pcr));
122}
123
124static __inline u_int
125slots2cr(struct patm_softc *sc, u_int slots)
126{
127	return ((slots * sc->ifatm.mib.pcr + sc->mmap->tst_size - 2) /
128	    (sc->mmap->tst_size - 1));
129}
130
131/* check if we can open this one */
132int
133patm_tx_vcc_can_open(struct patm_softc *sc, struct patm_vcc *vcc)
134{
135
136	/* check resources */
137	switch (vcc->vcc.traffic) {
138
139	  case ATMIO_TRAFFIC_CBR:
140	    {
141		u_int slots = cbr2slots(sc, vcc);
142
143		if (slots > sc->tst_free + sc->tst_reserve)
144			return (EINVAL);
145		break;
146	    }
147
148	  case ATMIO_TRAFFIC_VBR:
149		if (vcc->vcc.tparam.scr > sc->bwrem)
150			return (EINVAL);
151		if (vcc->vcc.tparam.pcr > sc->ifatm.mib.pcr)
152			return (EINVAL);
153		if (vcc->vcc.tparam.scr > vcc->vcc.tparam.pcr ||
154		    vcc->vcc.tparam.mbs == 0)
155			return (EINVAL);
156		break;
157
158	  case ATMIO_TRAFFIC_ABR:
159		if (vcc->vcc.tparam.tbe == 0 ||
160		    vcc->vcc.tparam.nrm == 0)
161			/* needed to compute CRM */
162			return (EINVAL);
163		if (vcc->vcc.tparam.pcr > sc->ifatm.mib.pcr ||
164		    vcc->vcc.tparam.icr > vcc->vcc.tparam.pcr ||
165		    vcc->vcc.tparam.mcr > vcc->vcc.tparam.icr)
166			return (EINVAL);
167		if (vcc->vcc.tparam.mcr > sc->bwrem ||
168		    vcc->vcc.tparam.icr > sc->bwrem)
169			return (EINVAL);
170		break;
171	}
172
173	return (0);
174}
175
176#define	NEXT_TAG(T) do {				\
177	(T) = ((T) + 1) % IDT_TSQE_TAG_SPACE;		\
178    } while (0)
179
180/*
181 * open it
182 */
183void
184patm_tx_vcc_open(struct patm_softc *sc, struct patm_vcc *vcc)
185{
186	struct patm_scd *scd;
187
188	if (vcc->vcc.traffic == ATMIO_TRAFFIC_UBR) {
189		/* we use UBR0 */
190		vcc->scd = sc->scd0;
191		vcc->vflags |= PATM_VCC_TX_OPEN;
192		return;
193	}
194
195	/* get an SCD */
196	scd = patm_scd_alloc(sc);
197	if (scd == NULL) {
198		/* should not happen */
199		patm_printf(sc, "out of SCDs\n");
200		return;
201	}
202	vcc->scd = scd;
203	patm_scd_setup(sc, scd);
204	patm_tct_setup(sc, scd, vcc);
205
206	if (vcc->vcc.traffic != ATMIO_TRAFFIC_CBR)
207		patm_tct_start(sc, vcc);
208
209	vcc->vflags |= PATM_VCC_TX_OPEN;
210}
211
212/*
213 * close the given vcc for transmission
214 */
215void
216patm_tx_vcc_close(struct patm_softc *sc, struct patm_vcc *vcc)
217{
218	struct patm_scd *scd;
219	struct mbuf *m;
220
221	vcc->vflags |= PATM_VCC_TX_CLOSING;
222
223	if (vcc->vcc.traffic == ATMIO_TRAFFIC_UBR) {
224		/* let the queue PDUs go out */
225		vcc->scd = NULL;
226		vcc->vflags &= ~(PATM_VCC_TX_OPEN | PATM_VCC_TX_CLOSING);
227		return;
228	}
229	scd = vcc->scd;
230
231	/* empty the waitq */
232	for (;;) {
233		_IF_DEQUEUE(&scd->q, m);
234		if (m == NULL)
235			break;
236		m_freem(m);
237	}
238
239	if (scd->num_on_card == 0) {
240		/* we are idle */
241		vcc->vflags &= ~PATM_VCC_TX_OPEN;
242
243		if (vcc->vcc.traffic == ATMIO_TRAFFIC_CBR)
244			patm_tst_free(sc, vcc);
245
246		patm_sram_write4(sc, scd->sram + 0, 0, 0, 0, 0);
247		patm_sram_write4(sc, scd->sram + 4, 0, 0, 0, 0);
248		patm_scd_free(sc, scd);
249
250		vcc->scd = NULL;
251		vcc->vflags &= ~PATM_VCC_TX_CLOSING;
252
253		return;
254	}
255
256	/* speed up transmission */
257	patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_UIER(vcc->cid, 0xff));
258	patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_ULACR(vcc->cid, 0xff));
259
260	/* wait for the interrupt to drop the number to 0 */
261	patm_debug(sc, VCC, "%u buffers still on card", scd->num_on_card);
262}
263
264/* transmission side finally closed */
265void
266patm_tx_vcc_closed(struct patm_softc *sc, struct patm_vcc *vcc)
267{
268
269	patm_debug(sc, VCC, "%u.%u TX closed", vcc->vcc.vpi, vcc->vcc.vci);
270
271	if (vcc->vcc.traffic == ATMIO_TRAFFIC_VBR)
272		sc->bwrem += vcc->vcc.tparam.scr;
273}
274
275/*
276 * Pull off packets from the interface queue and try to transmit them.
277 * If the transmission fails because of a full transmit channel, we drop
278 * packets for CBR and queue them for other channels up to limit.
279 * This limit should depend on the CDVT for VBR and ABR, but it doesn't.
280 */
281void
282patm_start(struct ifnet *ifp)
283{
284	struct patm_softc *sc = (struct patm_softc *)ifp->if_softc;
285	struct mbuf *m;
286	struct atm_pseudohdr *aph;
287	u_int vpi, vci, cid;
288	struct patm_vcc *vcc;
289
290	mtx_lock(&sc->mtx);
291	if (!(ifp->if_flags & IFF_RUNNING)) {
292		mtx_unlock(&sc->mtx);
293		return;
294	}
295
296	while (1) {
297		/* get a new mbuf */
298		IF_DEQUEUE(&ifp->if_snd, m);
299		if (m == NULL)
300			break;
301
302		/* split of pseudo header */
303		if (m->m_len < sizeof(*aph) &&
304		    (m = m_pullup(m, sizeof(*aph))) == NULL) {
305			sc->ifatm.ifnet.if_oerrors++;
306			continue;
307		}
308
309		aph = mtod(m, struct atm_pseudohdr *);
310		vci = ATM_PH_VCI(aph);
311		vpi = ATM_PH_VPI(aph);
312		m_adj(m, sizeof(*aph));
313
314		/* reject empty packets */
315		if (m->m_pkthdr.len == 0) {
316			m_freem(m);
317			sc->ifatm.ifnet.if_oerrors++;
318			continue;
319		}
320
321		/* check whether this is a legal vcc */
322		if (!LEGAL_VPI(sc, vpi) || !LEGAL_VCI(sc, vci) || vci == 0) {
323			m_freem(m);
324			sc->ifatm.ifnet.if_oerrors++;
325			continue;
326		}
327		cid = PATM_CID(sc, vpi, vci);
328		vcc = sc->vccs[cid];
329		if (vcc == NULL) {
330			m_freem(m);
331			sc->ifatm.ifnet.if_oerrors++;
332			continue;
333		}
334
335		/* must be multiple of 48 if not AAL5 */
336		if (vcc->vcc.aal == ATMIO_AAL_0 ||
337		    vcc->vcc.aal == ATMIO_AAL_34) {
338			/* XXX AAL3/4 format? */
339			if (m->m_pkthdr.len % 48 != 0 &&
340			    (m = patm_tx_pad(sc, m)) == NULL) {
341				sc->ifatm.ifnet.if_oerrors++;
342				continue;
343			}
344		} else if (vcc->vcc.aal == ATMIO_AAL_RAW) {
345			switch (vcc->vflags & PATM_RAW_FORMAT) {
346
347			  default:
348			  case PATM_RAW_CELL:
349				if (m->m_pkthdr.len != 53) {
350					sc->ifatm.ifnet.if_oerrors++;
351					m_freem(m);
352					continue;
353				}
354				break;
355
356			  case PATM_RAW_NOHEC:
357				if (m->m_pkthdr.len != 52) {
358					sc->ifatm.ifnet.if_oerrors++;
359					m_freem(m);
360					continue;
361				}
362				break;
363
364			  case PATM_RAW_CS:
365				if (m->m_pkthdr.len != 64) {
366					sc->ifatm.ifnet.if_oerrors++;
367					m_freem(m);
368					continue;
369				}
370				break;
371			}
372		}
373
374		/* save data */
375		m->m_pkthdr.header = vcc;
376
377		/* try to put it on the channels queue */
378		if (_IF_QFULL(&vcc->scd->q)) {
379			sc->ifatm.ifnet.if_oerrors++;
380			sc->stats.tx_qfull++;
381			m_freem(m);
382			continue;
383		}
384		_IF_ENQUEUE(&vcc->scd->q, m);
385
386#ifdef ENABLE_BPF
387		if (!(vcc->vcc.flags & ATMIO_FLAG_NG) &&
388		    (vcc->vcc.flags & ATM_PH_AAL5) &&
389		    (vcc->vcc.flags & ATM_PH_LLCSNAP))
390		 	BPF_MTAP(ifp, m);
391#endif
392
393		/* kick the channel to life */
394		patm_launch(sc, vcc->scd);
395
396	}
397	mtx_unlock(&sc->mtx);
398}
399
400/*
401 * Pad non-AAL5 packet to a multiple of 48-byte.
402 * We assume AAL0 only. We have still to decide on the format of AAL3/4.
403 */
404static struct mbuf *
405patm_tx_pad(struct patm_softc *sc, struct mbuf *m0)
406{
407	struct mbuf *last, *m;
408	u_int plen, pad, space;
409
410	plen = m_length(m0, &last);
411	if (plen != m0->m_pkthdr.len) {
412		patm_printf(sc, "%s: mbuf length mismatch %d %u\n", __func__,
413		    m0->m_pkthdr.len, plen);
414		m0->m_pkthdr.len = plen;
415		if (plen == 0) {
416			m_freem(m0);
417			sc->ifatm.ifnet.if_oerrors++;
418			return (NULL);
419		}
420		if (plen % 48 == 0)
421			return (m0);
422	}
423	pad = 48 - plen % 48;
424	m0->m_pkthdr.len += pad;
425	if (M_WRITABLE(last)) {
426		if (M_TRAILINGSPACE(last) >= pad) {
427			bzero(last->m_data + last->m_len, pad);
428			last->m_len += pad;
429			return (m0);
430		}
431		space = M_LEADINGSPACE(last);
432		if (space + M_TRAILINGSPACE(last) >= pad) {
433			bcopy(last->m_data, last->m_data + space, last->m_len);
434			last->m_data -= space;
435			bzero(last->m_data + last->m_len, pad);
436			last->m_len += pad;
437			return (m0);
438		}
439	}
440	MGET(m, M_DONTWAIT, MT_DATA);
441	if (m == 0) {
442		m_freem(m0);
443		sc->ifatm.ifnet.if_oerrors++;
444		return (NULL);
445	}
446	bzero(mtod(m, u_char *), pad);
447	m->m_len = pad;
448	last->m_next = m;
449
450	return (m0);
451}
452
453/*
454 * Try to put as many packets from the channels queue onto the channel
455 */
456static void
457patm_launch(struct patm_softc *sc, struct patm_scd *scd)
458{
459	struct txarg a;
460	struct mbuf *m, *tmp;
461	u_int segs;
462	struct patm_txmap *map;
463	int error;
464
465	a.sc = sc;
466	a.scd = scd;
467
468	/* limit the number of outstanding packets to the tag space */
469	while (scd->num_on_card < IDT_TSQE_TAG_SPACE) {
470		/* get the next packet */
471		_IF_DEQUEUE(&scd->q, m);
472		if (m == NULL)
473			break;
474
475		a.vcc = m->m_pkthdr.header;
476
477		/* we must know the number of segments beforehand - count
478		 * this may actually give a wrong number of segments for
479		 * AAL_RAW where we still need to remove the cell header */
480		segs = 0;
481		for (tmp = m; tmp != NULL; tmp = tmp->m_next)
482			if (tmp->m_len != 0)
483				segs++;
484
485		/* check whether there is space in the queue */
486		if (segs >= scd->space) {
487			/* put back */
488			_IF_PREPEND(&scd->q, m);
489			sc->stats.tx_out_of_tbds++;
490			break;
491		}
492
493		/* get a DMA map */
494		if ((map = patm_txmap_get(sc)) == NULL) {
495			_IF_PREPEND(&scd->q, m);
496			sc->stats.tx_out_of_maps++;
497			break;
498		}
499
500		/* load the map */
501		m->m_pkthdr.header = map;
502		a.mbuf = m;
503
504		/* handle AAL_RAW */
505		if (a.vcc->vcc.aal == ATMIO_AAL_RAW) {
506			u_char hdr[4];
507
508			m_copydata(m, 0, 4, hdr);
509			a.hdr = (hdr[0] << 24) | (hdr[1] << 16) |
510			    (hdr[2] << 8) | hdr[3];
511
512			switch (a.vcc->vflags & PATM_RAW_FORMAT) {
513
514			  default:
515			  case PATM_RAW_CELL:
516				m_adj(m, 5);
517				break;
518
519			  case PATM_RAW_NOHEC:
520				m_adj(m, 4);
521				break;
522
523			  case PATM_RAW_CS:
524				m_adj(m, 16);
525				break;
526			}
527		} else
528			a.hdr = IDT_TBD_HDR(a.vcc->vcc.vpi, a.vcc->vcc.vci,
529			    0, 0);
530
531		error = bus_dmamap_load_mbuf(sc->tx_tag, map->map, m,
532		    patm_load_txbuf, &a, BUS_DMA_NOWAIT);
533		if (error == EFBIG) {
534			if ((m = m_defrag(m, M_DONTWAIT)) == NULL) {
535				sc->ifatm.ifnet.if_oerrors++;
536				continue;
537			}
538			error = bus_dmamap_load_mbuf(sc->tx_tag, map->map, m,
539			    patm_load_txbuf, &a, BUS_DMA_NOWAIT);
540		}
541		if (error != 0) {
542			sc->stats.tx_load_err++;
543			sc->ifatm.ifnet.if_oerrors++;
544			SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
545			m_freem(m);
546			continue;
547		}
548
549		sc->ifatm.ifnet.if_opackets++;
550	}
551}
552
553/*
554 * Load the DMA segments into the scheduling channel
555 */
556static void
557patm_load_txbuf(void *uarg, bus_dma_segment_t *segs, int nseg,
558    bus_size_t mapsize, int error)
559{
560	struct txarg *a= uarg;
561	struct patm_scd *scd = a->scd;
562	u_int w1, w3, cnt;
563	struct idt_tbd *tbd = NULL;
564	u_int rest = mapsize;
565
566	if (error != 0)
567		return;
568
569	cnt = 0;
570	while (nseg > 0) {
571		if (segs->ds_len == 0) {
572			/* transmit buffer length must be > 0 */
573			nseg--;
574			segs++;
575			continue;
576		}
577		/* rest after this buffer */
578		rest -= segs->ds_len;
579
580		/* put together status word */
581		w1 = 0;
582		if (rest < 48 /* && a->vcc->vcc.aal != ATMIO_AAL_5 */)
583			/* last cell is in this buffer */
584			w1 |= IDT_TBD_EPDU;
585
586		if (a->vcc->vcc.aal == ATMIO_AAL_5)
587			w1 |= IDT_TBD_AAL5;
588		else if (a->vcc->vcc.aal == ATMIO_AAL_34)
589			w1 |= IDT_TBD_AAL34;
590		else
591			w1 |= IDT_TBD_AAL0;
592
593		w1 |= segs->ds_len;
594
595		/* AAL5 PDU length (unpadded) */
596		if (a->vcc->vcc.aal == ATMIO_AAL_5)
597			w3 = mapsize;
598		else
599			w3 = 0;
600
601		if (rest == 0)
602			w1 |= IDT_TBD_TSIF | IDT_TBD_GTSI |
603			    (scd->tag << IDT_TBD_TAG_SHIFT);
604
605		tbd = &scd->scq[scd->tail];
606
607		tbd->flags = htole32(w1);
608		tbd->addr = htole32(segs->ds_addr);
609		tbd->aal5 = htole32(w3);
610		tbd->hdr = htole32(a->hdr);
611
612		patm_debug(a->sc, TX, "TBD(%u): %08x %08x %08x %08x",
613		    scd->tail, w1, segs->ds_addr, w3, a->hdr);
614
615		/* got to next entry */
616		if (++scd->tail == IDT_SCQ_SIZE)
617			scd->tail = 0;
618		cnt++;
619		nseg--;
620		segs++;
621	}
622	scd->space -= cnt;
623	scd->num_on_card++;
624
625	KASSERT(rest == 0, ("bad mbuf"));
626	KASSERT(cnt > 0, ("no segs"));
627	KASSERT(scd->space > 0, ("scq full"));
628
629	KASSERT(scd->on_card[scd->tag] == NULL,
630	    ("scd on_card wedged %u%s", scd->tag, dump_scd(a->sc, scd)));
631	scd->on_card[scd->tag] = a->mbuf;
632	a->mbuf->m_pkthdr.csum_data = cnt;
633
634	NEXT_TAG(scd->tag);
635
636	patm_debug(a->sc, TX, "SCD tail %u (%lx:%lx)", scd->tail,
637	    (u_long)scd->phy, (u_long)scd->phy + (scd->tail << IDT_TBD_SHIFT));
638	patm_sram_write(a->sc, scd->sram,
639	    scd->phy + (scd->tail << IDT_TBD_SHIFT));
640
641	if (patm_sram_read(a->sc, a->vcc->cid * 8 + 3) & IDT_TCT_IDLE) {
642		/*
643		 * if the connection is idle start it. We cannot rely
644		 * on a flag set by patm_tx_idle() here, because sometimes
645		 * the card seems to place an idle TSI into the TSQ but
646		 * forgets to raise an interrupt.
647		 */
648		patm_nor_write(a->sc, IDT_NOR_TCMDQ,
649		    IDT_TCMDQ_START(a->vcc->cid));
650	}
651}
652
653/*
654 * packet transmitted
655 */
656void
657patm_tx(struct patm_softc *sc, u_int stamp, u_int status)
658{
659	u_int cid, tag, last;
660	struct mbuf *m;
661	struct patm_vcc *vcc;
662	struct patm_scd *scd;
663	struct patm_txmap *map;
664
665	/* get the connection */
666	cid = PATM_CID(sc, IDT_TBD_VPI(status), IDT_TBD_VCI(status));
667	if ((vcc = sc->vccs[cid]) == NULL) {
668		/* closed UBR connection */
669		return;
670	}
671	scd = vcc->scd;
672
673	tag = IDT_TSQE_TAG(stamp);
674
675	last = scd->last_tag;
676	if (tag == last) {
677		patm_printf(sc, "same tag %u\n", tag);
678		return;
679	}
680
681	/* Errata 12 requests us to free all entries up to the one
682	 * with the given tag. */
683	do {
684		/* next tag to try */
685		NEXT_TAG(last);
686
687		m = scd->on_card[last];
688		KASSERT(m != NULL, ("%stag=%u", dump_scd(sc, scd), tag));
689		scd->on_card[last] = NULL;
690		patm_debug(sc, TX, "ok tag=%x", last);
691
692		map = m->m_pkthdr.header;
693		scd->space += m->m_pkthdr.csum_data;
694
695		bus_dmamap_sync(sc->tx_tag, map->map,
696		    BUS_DMASYNC_POSTWRITE);
697		bus_dmamap_unload(sc->tx_tag, map->map);
698		m_freem(m);
699		SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
700		scd->num_on_card--;
701
702		if (vcc->vflags & PATM_VCC_TX_CLOSING) {
703			if (scd->num_on_card == 0) {
704				/* done with this VCC */
705				if (vcc->vcc.traffic == ATMIO_TRAFFIC_CBR)
706					patm_tst_free(sc, vcc);
707
708				patm_sram_write4(sc, scd->sram + 0, 0, 0, 0, 0);
709				patm_sram_write4(sc, scd->sram + 4, 0, 0, 0, 0);
710				patm_scd_free(sc, scd);
711
712				vcc->scd = NULL;
713				vcc->vflags &= ~PATM_VCC_TX_CLOSING;
714
715				if (vcc->vflags & PATM_VCC_ASYNC) {
716					patm_tx_vcc_closed(sc, vcc);
717					if (!(vcc->vflags & PATM_VCC_OPEN))
718						patm_vcc_closed(sc, vcc);
719				} else
720					cv_signal(&sc->vcc_cv);
721				return;
722			}
723			patm_debug(sc, VCC, "%u buffers still on card",
724			    scd->num_on_card);
725
726			if (vcc->vcc.traffic == ATMIO_TRAFFIC_ABR) {
727				/* insist on speeding up transmission for ABR */
728				patm_nor_write(sc, IDT_NOR_TCMDQ,
729				    IDT_TCMDQ_UIER(vcc->cid, 0xff));
730				patm_nor_write(sc, IDT_NOR_TCMDQ,
731				    IDT_TCMDQ_ULACR(vcc->cid, 0xff));
732			}
733		}
734
735	} while (last != tag);
736	scd->last_tag = tag;
737
738	if (vcc->vcc.traffic == ATMIO_TRAFFIC_ABR) {
739		u_int acri, cps;
740
741		acri = (patm_sram_read(sc, 8 * cid + 2) >> IDT_TCT_ACRI_SHIFT)
742		    & 0x3fff;
743		cps = sc->ifatm.mib.pcr * 32 /
744		    ((1 << (acri >> 10)) * (acri & 0x3ff));
745
746		if (cps != vcc->cps) {
747			/* send message */
748			patm_debug(sc, VCC, "ACRI=%04x CPS=%u", acri, cps);
749			vcc->cps = cps;
750		}
751	}
752
753	patm_launch(sc, scd);
754}
755
756/*
757 * VBR/ABR connection went idle
758 * Either restart it or set the idle flag.
759 */
760void
761patm_tx_idle(struct patm_softc *sc, u_int cid)
762{
763	struct patm_vcc *vcc;
764
765	patm_debug(sc, VCC, "idle %u", cid);
766
767	if ((vcc = sc->vccs[cid]) != NULL &&
768	    (vcc->vflags & (PATM_VCC_TX_OPEN | PATM_VCC_TX_CLOSING)) != 0 &&
769	    vcc->scd != NULL && (vcc->scd->num_on_card != 0 ||
770	    _IF_QLEN(&vcc->scd->q) != 0)) {
771		/*
772		 * If there is any packet outstanding in the SCD re-activate
773		 * the channel and kick it.
774		 */
775		patm_nor_write(sc, IDT_NOR_TCMDQ,
776		    IDT_TCMDQ_START(vcc->cid));
777
778		patm_launch(sc, vcc->scd);
779	}
780}
781
782/*
783 * Convert a (24bit) rate to the atm-forum form
784 * Our rate is never larger than 19 bit.
785 */
786static u_int
787cps2atmf(u_int cps)
788{
789	u_int e;
790
791	if (cps == 0)
792		return (0);
793	cps <<= 9;
794	e = 0;
795	while (cps > (1024 - 1)) {
796		e++;
797		cps >>= 1;
798	}
799	return ((1 << 14) | (e << 9) | (cps & 0x1ff));
800}
801
802/*
803 * Do a binary search on the log2rate table to convert the rate
804 * to its log form. This assumes that the ATM-Forum form is monotonically
805 * increasing with the plain cell rate.
806 */
807static u_int
808rate2log(struct patm_softc *sc, u_int rate)
809{
810	const uint32_t *tbl;
811	u_int lower, upper, mid, done, val, afr;
812
813	afr = cps2atmf(rate);
814
815	if (sc->flags & PATM_25M)
816		tbl = patm_rtables25;
817	else
818		tbl = patm_rtables155;
819
820	lower = 0;
821	upper = 255;
822	done = 0;
823	while (!done) {
824		mid = (lower + upper) / 2;
825		val = tbl[mid] >> 17;
826		if (val == afr || upper == lower)
827			break;
828		if (afr > val)
829			lower = mid + 1;
830		else
831			upper = mid - 1;
832	}
833	if (val > afr && mid > 0)
834		mid--;
835	return (mid);
836}
837
838/*
839 * Return the table index for an increase table. The increase table
840 * must be selected not by the RIF itself, but by PCR/2^RIF. Each table
841 * represents an additive increase of a cell rate that can be computed
842 * from the first table entry (the value in this entry will not be clamped
843 * by the link rate).
844 */
845static u_int
846get_air_table(struct patm_softc *sc, u_int rif, u_int pcr)
847{
848	const uint32_t *tbl;
849	u_int increase, base, lair0, ret, t, cps;
850
851#define	GET_ENTRY(TAB, IDX) (0xffff & ((IDX & 1) ?			\
852	(tbl[512 + (IDX / 2) + 128 * (TAB)] >> 16) :			\
853	(tbl[512 + (IDX / 2) + 128 * (TAB)])))
854
855#define	MANT_BITS	10
856#define	FRAC_BITS	16
857
858#define	DIFF_TO_FP(D)	(((D) & ((1 << MANT_BITS) - 1)) << ((D) >> MANT_BITS))
859#define	AFR_TO_INT(A)	((1 << (((A) >> 9) & 0x1f)) * \
860			    (512 + ((A) & 0x1ff)) / 512 * ((A) >> 14))
861
862	if (sc->flags & PATM_25M)
863		tbl = patm_rtables25;
864	else
865		tbl = patm_rtables155;
866	if (rif >= patm_rtables_ntab)
867		rif = patm_rtables_ntab - 1;
868	increase = pcr >> rif;
869
870	ret = 0;
871	for (t = 0; t < patm_rtables_ntab; t++) {
872		/* get base rate of this table */
873		base = GET_ENTRY(t, 0);
874		/* convert this to fixed point */
875		lair0 = DIFF_TO_FP(base) >> FRAC_BITS;
876
877		/* get the CPS from the log2rate table */
878		cps = AFR_TO_INT(tbl[lair0] >> 17) - 10;
879
880		if (increase >= cps)
881			break;
882
883		ret = t;
884	}
885	return (ret + 4);
886}
887
888/*
889 * Setup the TCT
890 */
891void
892patm_tct_setup(struct patm_softc *sc, struct patm_scd *scd,
893    struct patm_vcc *vcc)
894{
895	uint32_t tct[8];
896	u_int sram;
897	u_int mbs, token;
898	u_int tmp, crm, rdf, cdf, air, mcr;
899
900	bzero(tct, sizeof(tct));
901	if (vcc == NULL) {
902		/* special case for UBR0 */
903		sram = 0;
904		tct[0] = IDT_TCT_UBR | scd->sram;
905		tct[7] = IDT_TCT_UBR_FLG;
906
907	} else {
908		sram = vcc->cid * 8;
909		switch (vcc->vcc.traffic) {
910
911		  case ATMIO_TRAFFIC_CBR:
912			patm_tst_alloc(sc, vcc);
913			tct[0] = IDT_TCT_CBR | scd->sram;
914			/* must account for what was really allocated */
915			break;
916
917		  case ATMIO_TRAFFIC_VBR:
918			/* compute parameters for the TCT */
919			scd->init_er = rate2log(sc, vcc->vcc.tparam.pcr);
920			scd->lacr = rate2log(sc, vcc->vcc.tparam.scr);
921
922			/* get the 16-bit fraction of SCR/PCR
923			 * both a 24 bit. Do it the simple way. */
924			token = (uint64_t)(vcc->vcc.tparam.scr << 16) /
925			    vcc->vcc.tparam.pcr;
926
927			patm_debug(sc, VCC, "VBR: init_er=%u lacr=%u "
928			    "token=0x%04x\n", scd->init_er, scd->lacr, token);
929
930			tct[0] = IDT_TCT_VBR | scd->sram;
931			tct[2] = IDT_TCT_TSIF;
932			tct[3] = IDT_TCT_IDLE | IDT_TCT_HALT;
933			tct[4] = IDT_TCT_MAXIDLE;
934			tct[5] = 0x01000000;
935			if ((mbs = vcc->vcc.tparam.mbs) > 0xff)
936				mbs = 0xff;
937			tct[6] = (mbs << 16) | token;
938			sc->bwrem -= vcc->vcc.tparam.scr;
939			break;
940
941		  case ATMIO_TRAFFIC_ABR:
942			scd->init_er = rate2log(sc, vcc->vcc.tparam.pcr);
943			scd->lacr = rate2log(sc, vcc->vcc.tparam.icr);
944			mcr = rate2log(sc, vcc->vcc.tparam.mcr);
945
946			/* compute CRM */
947			tmp = vcc->vcc.tparam.tbe / vcc->vcc.tparam.nrm;
948			if (tmp * vcc->vcc.tparam.nrm < vcc->vcc.tparam.tbe)
949				tmp++;
950			for (crm = 1; tmp > (1 << crm); crm++)
951				;
952			if (crm > 0x7)
953				crm = 7;
954
955			air = get_air_table(sc, vcc->vcc.tparam.rif,
956			    vcc->vcc.tparam.pcr);
957
958			if ((rdf = vcc->vcc.tparam.rdf) >= patm_rtables_ntab)
959				rdf = patm_rtables_ntab - 1;
960			rdf += patm_rtables_ntab + 4;
961
962			if ((cdf = vcc->vcc.tparam.cdf) >= patm_rtables_ntab)
963				cdf = patm_rtables_ntab - 1;
964			cdf += patm_rtables_ntab + 4;
965
966			patm_debug(sc, VCC, "ABR: init_er=%u lacr=%u mcr=%u "
967			    "crm=%u air=%u rdf=%u cdf=%u\n", scd->init_er,
968			    scd->lacr, mcr, crm, air, rdf, cdf);
969
970			tct[0] = IDT_TCT_ABR | scd->sram;
971			tct[1] = crm << IDT_TCT_CRM_SHIFT;
972			tct[3] = IDT_TCT_HALT | IDT_TCT_IDLE |
973			    (4 << IDT_TCT_NAGE_SHIFT);
974			tct[4] = mcr << IDT_TCT_LMCR_SHIFT;
975			tct[5] = (cdf << IDT_TCT_CDF_SHIFT) |
976			    (rdf << IDT_TCT_RDF_SHIFT) |
977			    (air << IDT_TCT_AIR_SHIFT);
978
979			sc->bwrem -= vcc->vcc.tparam.mcr;
980			break;
981		}
982	}
983
984	patm_sram_write4(sc, sram + 0, tct[0], tct[1], tct[2], tct[3]);
985	patm_sram_write4(sc, sram + 4, tct[4], tct[5], tct[6], tct[7]);
986
987	patm_debug(sc, VCC, "TCT[%u]: %08x %08x %08x %08x  %08x %08x %08x %08x",
988	    sram / 8, patm_sram_read(sc, sram + 0),
989	    patm_sram_read(sc, sram + 1), patm_sram_read(sc, sram + 2),
990	    patm_sram_read(sc, sram + 3), patm_sram_read(sc, sram + 4),
991	    patm_sram_read(sc, sram + 5), patm_sram_read(sc, sram + 6),
992	    patm_sram_read(sc, sram + 7));
993}
994
995/*
996 * Start a channel
997 */
998static void
999patm_tct_start(struct patm_softc *sc, struct patm_vcc *vcc)
1000{
1001
1002	patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_UIER(vcc->cid,
1003	    vcc->scd->init_er));
1004	patm_nor_write(sc, IDT_NOR_TCMDQ, IDT_TCMDQ_SLACR(vcc->cid,
1005	    vcc->scd->lacr));
1006}
1007
1008static void
1009patm_tct_print(struct patm_softc *sc, u_int cid)
1010{
1011#ifdef PATM_DEBUG
1012	u_int sram = cid * 8;
1013#endif
1014
1015	patm_debug(sc, VCC, "TCT[%u]: %08x %08x %08x %08x  %08x %08x %08x %08x",
1016	    sram / 8, patm_sram_read(sc, sram + 0),
1017	    patm_sram_read(sc, sram + 1), patm_sram_read(sc, sram + 2),
1018	    patm_sram_read(sc, sram + 3), patm_sram_read(sc, sram + 4),
1019	    patm_sram_read(sc, sram + 5), patm_sram_read(sc, sram + 6),
1020	    patm_sram_read(sc, sram + 7));
1021}
1022
1023/*
1024 * Setup the SCD
1025 */
1026void
1027patm_scd_setup(struct patm_softc *sc, struct patm_scd *scd)
1028{
1029	patm_sram_write4(sc, scd->sram + 0,
1030	    scd->phy, 0, 0xffffffff, 0);
1031	patm_sram_write4(sc, scd->sram + 4,
1032	    0, 0, 0, 0);
1033
1034	patm_debug(sc, VCC, "SCD(%x): %08x %08x %08x %08x %08x %08x %08x %08x",
1035	    scd->sram,
1036	    patm_sram_read(sc, scd->sram + 0),
1037	    patm_sram_read(sc, scd->sram + 1),
1038	    patm_sram_read(sc, scd->sram + 2),
1039	    patm_sram_read(sc, scd->sram + 3),
1040	    patm_sram_read(sc, scd->sram + 4),
1041	    patm_sram_read(sc, scd->sram + 5),
1042	    patm_sram_read(sc, scd->sram + 6),
1043	    patm_sram_read(sc, scd->sram + 7));
1044}
1045
1046/*
1047 * Grow the TX map table if possible
1048 */
1049static void
1050patm_txmaps_grow(struct patm_softc *sc)
1051{
1052	u_int i;
1053	struct patm_txmap *map;
1054	int err;
1055
1056	if (sc->tx_nmaps >= sc->tx_maxmaps)
1057		return;
1058
1059	for (i = sc->tx_nmaps; i < sc->tx_nmaps + PATM_CFG_TXMAPS_STEP; i++) {
1060		map = uma_zalloc(sc->tx_mapzone, M_NOWAIT);
1061		err = bus_dmamap_create(sc->tx_tag, 0, &map->map);
1062		if (err) {
1063			uma_zfree(sc->tx_mapzone, map);
1064			break;
1065		}
1066		SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
1067	}
1068
1069	sc->tx_nmaps = i;
1070}
1071
1072/*
1073 * Allocate a transmission map
1074 */
1075static struct patm_txmap *
1076patm_txmap_get(struct patm_softc *sc)
1077{
1078	struct patm_txmap *map;
1079
1080	if ((map = SLIST_FIRST(&sc->tx_maps_free)) == NULL) {
1081		patm_txmaps_grow(sc);
1082		if ((map = SLIST_FIRST(&sc->tx_maps_free)) == NULL)
1083			return (NULL);
1084	}
1085	SLIST_REMOVE_HEAD(&sc->tx_maps_free, link);
1086	return (map);
1087}
1088
1089/*
1090 * Look whether we are in the process of updating the TST on the chip.
1091 * If we are set the flag that we need another update.
1092 * If we are not start the update.
1093 */
1094static __inline void
1095patm_tst_start(struct patm_softc *sc)
1096{
1097
1098	if (!(sc->tst_state & TST_PENDING)) {
1099		sc->tst_state |= TST_PENDING;
1100		if (!(sc->tst_state & TST_WAIT)) {
1101			/* timer not running */
1102			patm_tst_update(sc);
1103		}
1104	}
1105}
1106
1107/*
1108 * Allocate TST entries to a CBR connection
1109 */
1110static void
1111patm_tst_alloc(struct patm_softc *sc, struct patm_vcc *vcc)
1112{
1113	u_int slots;
1114	u_int qptr, pptr;
1115	u_int qmax, pmax;
1116	u_int pspc, last;
1117
1118	mtx_lock(&sc->tst_lock);
1119
1120	/* compute the number of slots we need, make sure to get at least
1121	 * the specified PCR */
1122	slots = cbr2slots(sc, vcc);
1123	vcc->scd->slots = slots;
1124	sc->bwrem -= slots2cr(sc, slots);
1125
1126	patm_debug(sc, TST, "tst_alloc: cbr=%u link=%u tst=%u slots=%u",
1127	    vcc->vcc.tparam.pcr, sc->ifatm.mib.pcr, sc->mmap->tst_size, slots);
1128
1129	qmax = sc->mmap->tst_size - 1;
1130	pmax = qmax << 8;
1131
1132	pspc = pmax / slots;
1133
1134	pptr = pspc >> 1;	/* starting point */
1135	qptr = pptr >> 8;
1136
1137	last = qptr;
1138
1139	while (slots > 0) {
1140		if (qptr >= qmax)
1141			qptr -= qmax;
1142		if (sc->tst_soft[qptr] != IDT_TST_VBR) {
1143			/* used - try next */
1144			qptr++;
1145			continue;
1146		}
1147		patm_debug(sc, TST, "slot[%u] = %u.%u diff=%d", qptr,
1148		    vcc->vcc.vpi, vcc->vcc.vci, (int)qptr - (int)last);
1149		last = qptr;
1150
1151		sc->tst_soft[qptr] = IDT_TST_CBR | vcc->cid | TST_BOTH;
1152		sc->tst_free--;
1153
1154		if ((pptr += pspc) >= pmax)
1155			pptr -= pmax;
1156		qptr = pptr >> 8;
1157
1158		slots--;
1159	}
1160	patm_tst_start(sc);
1161	mtx_unlock(&sc->tst_lock);
1162}
1163
1164/*
1165 * Free a CBR connection's TST entries
1166 */
1167static void
1168patm_tst_free(struct patm_softc *sc, struct patm_vcc *vcc)
1169{
1170	u_int i;
1171
1172	mtx_lock(&sc->tst_lock);
1173	for (i = 0; i < sc->mmap->tst_size - 1; i++) {
1174		if ((sc->tst_soft[i] & IDT_TST_MASK) == vcc->cid) {
1175			sc->tst_soft[i] = IDT_TST_VBR | TST_BOTH;
1176			sc->tst_free++;
1177		}
1178	}
1179	sc->bwrem += slots2cr(sc, vcc->scd->slots);
1180	patm_tst_start(sc);
1181	mtx_unlock(&sc->tst_lock);
1182}
1183
1184/*
1185 * Write the soft TST into the idle incore TST and start the wait timer.
1186 * We assume that we hold the tst lock.
1187 */
1188static void
1189patm_tst_update(struct patm_softc *sc)
1190{
1191	u_int flag;		/* flag to clear from soft TST */
1192	u_int idle;		/* the idle TST */
1193	u_int act;		/* the active TST */
1194	u_int i;
1195
1196	if (sc->tst_state & TST_ACT1) {
1197		act = 1;
1198		idle = 0;
1199		flag = TST_CH0;
1200	} else {
1201		act = 0;
1202		idle = 1;
1203		flag = TST_CH1;
1204	}
1205	/* update the idle one */
1206	for (i = 0; i < sc->mmap->tst_size - 1; i++)
1207		if (sc->tst_soft[i] & flag) {
1208			patm_sram_write(sc, sc->tst_base[idle] + i,
1209			    sc->tst_soft[i] & ~TST_BOTH);
1210			sc->tst_soft[i] &= ~flag;
1211		}
1212	/* the used one jump to the idle one */
1213	patm_sram_write(sc, sc->tst_jump[act],
1214	    IDT_TST_BR | (sc->tst_base[idle] << 2));
1215
1216	/* wait for the chip to jump */
1217	sc->tst_state &= ~TST_PENDING;
1218	sc->tst_state |= TST_WAIT;
1219
1220	callout_reset(&sc->tst_callout, 1, patm_tst_timer, sc);
1221}
1222
1223/*
1224 * Timer for TST updates
1225 */
1226static void
1227patm_tst_timer(void *p)
1228{
1229	struct patm_softc *sc = p;
1230	u_int act;	/* active TST */
1231	u_int now;	/* current place in TST */
1232
1233	mtx_lock(&sc->tst_lock);
1234
1235	if (sc->tst_state & TST_WAIT) {
1236		/* ignore the PENDING state while we are waiting for
1237		 * the chip to switch tables. Once the switch is done,
1238		 * we will again lock at PENDING */
1239		act = (sc->tst_state & TST_ACT1) ? 1 : 0;
1240		now = patm_nor_read(sc, IDT_NOR_NOW) >> 2;
1241		if (now >= sc->tst_base[act] && now <= sc->tst_jump[act]) {
1242			/* not yet */
1243			callout_reset(&sc->tst_callout, 1, patm_tst_timer, sc);
1244			goto done;
1245		}
1246		sc->tst_state &= ~TST_WAIT;
1247		/* change back jump */
1248		patm_sram_write(sc, sc->tst_jump[act],
1249		    IDT_TST_BR | (sc->tst_base[act] << 2));
1250
1251		/* switch */
1252		sc->tst_state ^= TST_ACT1;
1253	}
1254
1255	if (sc->tst_state & TST_PENDING)
1256		/* we got another update request while the timer was running. */
1257		patm_tst_update(sc);
1258
1259  done:
1260	mtx_unlock(&sc->tst_lock);
1261}
1262
1263static const char *
1264dump_scd(struct patm_softc *sc, struct patm_scd *scd)
1265{
1266	u_int i;
1267
1268	for (i = 0; i < IDT_TSQE_TAG_SPACE; i++)
1269		printf("on_card[%u] = %p\n", i, scd->on_card[i]);
1270	printf("space=%u tag=%u num_on_card=%u last_tag=%u\n",
1271	    scd->space, scd->tag, scd->num_on_card, scd->last_tag);
1272
1273	return ("");
1274}
1275