1139749Simp/*- 2117632Sharti * Copyright (c) 2003 3117632Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4117632Sharti * All rights reserved. 5117632Sharti * 6117632Sharti * Redistribution and use in source and binary forms, with or without 7117632Sharti * modification, are permitted provided that the following conditions 8117632Sharti * are met: 9117632Sharti * 1. Redistributions of source code must retain the above copyright 10117632Sharti * notice, this list of conditions and the following disclaimer. 11117632Sharti * 2. Redistributions in binary form must reproduce the above copyright 12117632Sharti * notice, this list of conditions and the following disclaimer in the 13117632Sharti * documentation and/or other materials provided with the distribution. 14117632Sharti * 15117632Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16117632Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17117632Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18117632Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19117632Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20117632Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21117632Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22117632Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23117632Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24117632Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25117632Sharti * SUCH DAMAGE. 26117632Sharti * 27117632Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28117632Sharti * 29117632Sharti * Driver for IDT77252 based cards like ProSum's. 30117632Sharti */ 31119418Sobrien 32117632Sharti#include <sys/cdefs.h> 33117632Sharti__FBSDID("$FreeBSD$"); 34117632Sharti 35117632Sharti#include "opt_inet.h" 36117632Sharti#include "opt_natm.h" 37117632Sharti 38117632Sharti#include <sys/types.h> 39117632Sharti#include <sys/param.h> 40117632Sharti#include <sys/systm.h> 41117632Sharti#include <sys/malloc.h> 42117632Sharti#include <sys/kernel.h> 43117632Sharti#include <sys/bus.h> 44117632Sharti#include <sys/errno.h> 45117632Sharti#include <sys/conf.h> 46117632Sharti#include <sys/module.h> 47117632Sharti#include <sys/lock.h> 48117632Sharti#include <sys/mutex.h> 49117632Sharti#include <sys/sysctl.h> 50117632Sharti#include <sys/queue.h> 51117632Sharti#include <sys/condvar.h> 52117632Sharti#include <sys/endian.h> 53117632Sharti#include <vm/uma.h> 54117632Sharti 55117632Sharti#include <sys/sockio.h> 56117632Sharti#include <sys/mbuf.h> 57117632Sharti#include <sys/socket.h> 58117632Sharti 59117632Sharti#include <net/if.h> 60117632Sharti#include <net/if_media.h> 61117632Sharti#include <net/if_atm.h> 62117632Sharti#include <net/route.h> 63117632Sharti#include <netinet/in.h> 64117632Sharti#include <netinet/if_atm.h> 65117632Sharti 66117632Sharti#include <machine/bus.h> 67117632Sharti#include <machine/resource.h> 68117632Sharti#include <sys/bus.h> 69117632Sharti#include <sys/rman.h> 70117632Sharti#include <sys/mbpool.h> 71117632Sharti 72117632Sharti#include <dev/utopia/utopia.h> 73117632Sharti#include <dev/patm/idt77252reg.h> 74117632Sharti#include <dev/patm/if_patmvar.h> 75117632Sharti 76117632Shartistatic void patm_feed_sbufs(struct patm_softc *sc); 77117632Shartistatic void patm_feed_lbufs(struct patm_softc *sc); 78117632Shartistatic void patm_feed_vbufs(struct patm_softc *sc); 79117632Shartistatic void patm_intr_tsif(struct patm_softc *sc); 80117632Shartistatic void patm_intr_raw(struct patm_softc *sc); 81117632Sharti 82117632Sharti#ifdef PATM_DEBUG 83117632Shartistatic int patm_mbuf_cnt(u_int unit) __unused; 84117632Sharti#endif 85117632Sharti 86117632Sharti/* 87117632Sharti * Write free buf Q 88117632Sharti */ 89117632Shartistatic __inline void 90117632Shartipatm_fbq_write(struct patm_softc *sc, u_int queue, uint32_t h0, 91117632Sharti uint32_t p0, uint32_t h1, uint32_t p1) 92117632Sharti{ 93117632Sharti patm_debug(sc, FREEQ, "supplying(%u,%#x,%#x,%#x,%#x)", 94117632Sharti queue, h0, p0, h1, p1); 95117632Sharti patm_nor_write(sc, IDT_NOR_D0, h0); 96117632Sharti patm_nor_write(sc, IDT_NOR_D1, p0); 97117632Sharti patm_nor_write(sc, IDT_NOR_D2, h1); 98117632Sharti patm_nor_write(sc, IDT_NOR_D3, p1); 99117632Sharti patm_cmd_exec(sc, IDT_CMD_WFBQ | queue); 100117632Sharti} 101117632Sharti 102117632Sharti/* 103117632Sharti * Interrupt 104117632Sharti */ 105117632Shartivoid 106117632Shartipatm_intr(void *p) 107117632Sharti{ 108117632Sharti struct patm_softc *sc = p; 109117632Sharti uint32_t stat, cfg; 110117632Sharti u_int cnt; 111117632Sharti const uint32_t ints = IDT_STAT_TSIF | IDT_STAT_TXICP | IDT_STAT_TSQF | 112117632Sharti IDT_STAT_TMROF | IDT_STAT_PHYI | IDT_STAT_RSQF | IDT_STAT_EPDU | 113117632Sharti IDT_STAT_RAWCF | IDT_STAT_RSQAF; 114117632Sharti const uint32_t fbqa = IDT_STAT_FBQ3A | IDT_STAT_FBQ2A | 115117632Sharti IDT_STAT_FBQ1A | IDT_STAT_FBQ0A; 116117632Sharti 117117632Sharti mtx_lock(&sc->mtx); 118117632Sharti 119117632Sharti stat = patm_nor_read(sc, IDT_NOR_STAT); 120117632Sharti patm_nor_write(sc, IDT_NOR_STAT, stat & (ints | fbqa)); 121117632Sharti 122148887Srwatson if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) { 123117632Sharti /* if we are stopped ack all interrupts and handle PHYI */ 124117632Sharti if (stat & IDT_STAT_PHYI) { 125117632Sharti patm_debug(sc, INTR, "PHYI (stopped)"); 126117632Sharti utopia_intr(&sc->utopia); 127117632Sharti } 128117632Sharti mtx_unlock(&sc->mtx); 129117632Sharti return; 130117632Sharti } 131117632Sharti 132117632Sharti patm_debug(sc, INTR, "stat=%08x", stat); 133117632Sharti 134117632Sharti /* 135117632Sharti * If the buffer queues are empty try to fill them. If this fails 136117632Sharti * disable the interrupt. Otherwise enable the interrupt. 137117632Sharti */ 138117632Sharti if (stat & fbqa) { 139117632Sharti cfg = patm_nor_read(sc, IDT_NOR_CFG); 140117632Sharti if (stat & IDT_STAT_FBQ0A) 141117632Sharti patm_feed_sbufs(sc); 142117632Sharti if (stat & IDT_STAT_FBQ1A) 143117632Sharti patm_feed_lbufs(sc); 144117632Sharti if (stat & IDT_STAT_FBQ2A) { 145117632Sharti /* 146117632Sharti * Workaround for missing interrupt on AAL0. Check the 147117632Sharti * receive status queue if the FBQ2 is not full. 148117632Sharti */ 149117632Sharti patm_intr_rsq(sc); 150117632Sharti patm_feed_vbufs(sc); 151117632Sharti } 152117632Sharti if ((patm_nor_read(sc, IDT_NOR_STAT) & fbqa) && 153117632Sharti (cfg & IDT_CFG_FBIE)) { 154117632Sharti /* failed */ 155117632Sharti patm_nor_write(sc, IDT_NOR_CFG, cfg & ~IDT_CFG_FBIE); 156117632Sharti patm_printf(sc, "out of buffers -- intr disabled\n"); 157117632Sharti } else if (!(cfg & IDT_CFG_FBIE)) { 158117632Sharti patm_printf(sc, "bufQ intr re-enabled\n"); 159117632Sharti patm_nor_write(sc, IDT_NOR_CFG, cfg | IDT_CFG_FBIE); 160117632Sharti } 161117632Sharti patm_nor_write(sc, IDT_NOR_STAT, fbqa); 162117632Sharti } 163117632Sharti 164117632Sharti cnt = 0; 165117632Sharti while ((stat & ints) != 0) { 166117632Sharti if (++cnt == 200) { 167117632Sharti patm_printf(sc, "%s: excessive interrupts\n", __func__); 168117632Sharti patm_stop(sc); 169117632Sharti break; 170117632Sharti } 171117632Sharti if (stat & IDT_STAT_TSIF) { 172117632Sharti patm_debug(sc, INTR, "TSIF"); 173117632Sharti patm_intr_tsif(sc); 174117632Sharti } 175117632Sharti if (stat & IDT_STAT_TXICP) { 176117632Sharti patm_printf(sc, "incomplete PDU transmitted\n"); 177117632Sharti } 178117632Sharti if (stat & IDT_STAT_TSQF) { 179117632Sharti patm_printf(sc, "TSQF\n"); 180117632Sharti patm_intr_tsif(sc); 181117632Sharti } 182117632Sharti if (stat & IDT_STAT_TMROF) { 183117632Sharti patm_debug(sc, INTR, "TMROF"); 184117632Sharti patm_intr_tsif(sc); 185117632Sharti } 186117632Sharti if (stat & IDT_STAT_PHYI) { 187117632Sharti patm_debug(sc, INTR, "PHYI"); 188117632Sharti utopia_intr(&sc->utopia); 189117632Sharti } 190117632Sharti if (stat & IDT_STAT_RSQF) { 191117632Sharti patm_printf(sc, "RSQF\n"); 192117632Sharti patm_intr_rsq(sc); 193117632Sharti } 194117632Sharti if (stat & IDT_STAT_EPDU) { 195117632Sharti patm_debug(sc, INTR, "EPDU"); 196117632Sharti patm_intr_rsq(sc); 197117632Sharti } 198117632Sharti if (stat & IDT_STAT_RAWCF) { 199117632Sharti patm_debug(sc, INTR, "RAWCF"); 200117632Sharti patm_intr_raw(sc); 201117632Sharti } 202117632Sharti if (stat & IDT_STAT_RSQAF) { 203117632Sharti patm_debug(sc, INTR, "RSQAF"); 204117632Sharti patm_intr_rsq(sc); 205117632Sharti } else if (IDT_STAT_FRAC2(stat) != 0xf) { 206117632Sharti /* 207117632Sharti * Workaround for missing interrupt on AAL0. Check the 208117632Sharti * receive status queue if the FBQ2 is not full. 209117632Sharti */ 210117632Sharti patm_intr_rsq(sc); 211117632Sharti } 212117632Sharti 213117632Sharti stat = patm_nor_read(sc, IDT_NOR_STAT); 214117632Sharti patm_nor_write(sc, IDT_NOR_STAT, ints & stat); 215117632Sharti patm_debug(sc, INTR, "stat=%08x", stat); 216117632Sharti } 217117632Sharti 218117632Sharti mtx_unlock(&sc->mtx); 219117632Sharti 220117632Sharti patm_debug(sc, INTR, "... exit"); 221117632Sharti} 222117632Sharti 223117632Sharti/* 224117632Sharti * Compute the amount of buffers to feed into a given free buffer queue 225117632Sharti * 226117632Sharti * Feeding buffers is actually not so easy as it seems. We cannot use the 227117632Sharti * fraction fields in the status registers, because they round down, i.e. 228117632Sharti * if we have 34 buffers in the queue, it will show 1. If we now feed 229160964Syar * 512 - 1 * 32 buffers, we lose two buffers. The only reliable way to know 230117632Sharti * how many buffers are in the queue are the FBQP registers. 231117632Sharti */ 232117632Shartistatic u_int 233117632Shartipatm_feed_cnt(struct patm_softc *sc, u_int q) 234117632Sharti{ 235117632Sharti u_int w, r, reg; 236117632Sharti u_int feed; 237117632Sharti int free; 238117632Sharti 239117632Sharti /* get the FBQ read and write pointers */ 240117632Sharti reg = patm_nor_read(sc, IDT_NOR_FBQP0 + 4 * q); 241117632Sharti r = (reg & 0x7ff) >> 1; 242117632Sharti w = ((reg >> 16) & 0x7ff) >> 1; 243117632Sharti /* compute amount of free buffers */ 244117632Sharti if ((free = w - r) < 0) 245117632Sharti free += 0x400; 246117632Sharti KASSERT(free <= 512, ("bad FBQP 0x%x", reg)); 247117632Sharti feed = 512 - free; 248117632Sharti 249117632Sharti /* can only feed pairs of buffers */ 250117632Sharti feed &= ~1; 251117632Sharti 252117632Sharti if (feed > 0) 253117632Sharti feed -= 2; 254117632Sharti 255117632Sharti patm_debug(sc, FREEQ, "feeding %u buffers into queue %u", feed, q); 256117632Sharti 257117632Sharti return (feed); 258117632Sharti} 259117632Sharti 260117632Sharti/* 261117632Sharti * Feed small buffers into buffer queue 0 262117632Sharti * 263117632Sharti */ 264117632Shartistatic void 265117632Shartipatm_feed_sbufs(struct patm_softc *sc) 266117632Sharti{ 267117632Sharti u_int feed; 268117632Sharti bus_addr_t p0, p1; 269185336Sganbold void *v0; 270117632Sharti uint32_t h0, h1; 271117632Sharti 272117632Sharti feed = patm_feed_cnt(sc, 0); 273117632Sharti 274117632Sharti while (feed > 0) { 275117632Sharti if ((v0 = mbp_alloc(sc->sbuf_pool, &p0, &h0)) == NULL) 276117632Sharti break; 277185336Sganbold if (mbp_alloc(sc->sbuf_pool, &p1, &h1) == NULL) { 278117632Sharti mbp_free(sc->sbuf_pool, v0); 279117632Sharti break; 280117632Sharti } 281117632Sharti patm_fbq_write(sc, 0, 282117632Sharti h0 | MBUF_SHANDLE, (p0 + SMBUF_OFFSET), 283117632Sharti h1 | MBUF_SHANDLE, (p1 + SMBUF_OFFSET)); 284117632Sharti 285117632Sharti feed -= 2; 286117632Sharti } 287117632Sharti} 288117632Sharti 289117632Sharti/* 290117632Sharti * Feed small buffers into buffer queue 0 291117632Sharti */ 292117632Shartistatic void 293117632Shartipatm_feed_vbufs(struct patm_softc *sc) 294117632Sharti{ 295117632Sharti u_int feed; 296117632Sharti bus_addr_t p0, p1; 297185336Sganbold void *v0; 298117632Sharti uint32_t h0, h1; 299117632Sharti 300117632Sharti feed = patm_feed_cnt(sc, 2); 301117632Sharti 302117632Sharti while (feed > 0) { 303117632Sharti if ((v0 = mbp_alloc(sc->vbuf_pool, &p0, &h0)) == NULL) 304117632Sharti break; 305185336Sganbold if (mbp_alloc(sc->vbuf_pool, &p1, &h1) == NULL) { 306117632Sharti mbp_free(sc->vbuf_pool, v0); 307117632Sharti break; 308117632Sharti } 309117632Sharti patm_fbq_write(sc, 2, 310117632Sharti h0 | MBUF_VHANDLE, (p0 + VMBUF_OFFSET), 311117632Sharti h1 | MBUF_VHANDLE, (p1 + VMBUF_OFFSET)); 312117632Sharti 313117632Sharti feed -= 2; 314117632Sharti } 315117632Sharti} 316117632Sharti 317117632Sharti/* 318117632Sharti * Allocate a large buffer 319117632Sharti */ 320117632Shartistatic struct lmbuf * 321117632Shartipatm_lmbuf_alloc(struct patm_softc *sc) 322117632Sharti{ 323117632Sharti int error; 324117632Sharti struct mbuf *m; 325117632Sharti struct lmbuf *b; 326117632Sharti 327248078Smarius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 328117632Sharti if (m == NULL) 329117632Sharti return (NULL); 330117632Sharti m->m_data += LMBUF_OFFSET; 331117632Sharti 332117632Sharti if ((b = SLIST_FIRST(&sc->lbuf_free_list)) == NULL) { 333117632Sharti m_freem(m); 334117632Sharti return (NULL); 335117632Sharti } 336117632Sharti 337117632Sharti b->phy = 0; /* alignment */ 338117632Sharti error = bus_dmamap_load(sc->lbuf_tag, b->map, m->m_data, LMBUF_SIZE, 339117632Sharti patm_load_callback, &b->phy, BUS_DMA_NOWAIT); 340117632Sharti if (error) { 341117632Sharti patm_printf(sc, "%s -- bus_dmamap_load: %d\n", __func__, error); 342117632Sharti m_free(m); 343117632Sharti return (NULL); 344117632Sharti } 345117632Sharti 346117632Sharti SLIST_REMOVE_HEAD(&sc->lbuf_free_list, link); 347117632Sharti b->m = m; 348117632Sharti 349117632Sharti return (b); 350117632Sharti} 351117632Sharti 352117632Sharti/* 353117632Sharti * Feed large buffers into buffer queue 1 354117632Sharti */ 355117632Shartistatic void 356117632Shartipatm_feed_lbufs(struct patm_softc *sc) 357117632Sharti{ 358117632Sharti u_int feed; 359117632Sharti struct lmbuf *b0, *b1; 360117632Sharti 361117632Sharti feed = patm_feed_cnt(sc, 1); 362117632Sharti 363117632Sharti while (feed > 0) { 364117632Sharti if ((b0 = patm_lmbuf_alloc(sc)) == NULL) 365117632Sharti break; 366117632Sharti if ((b1 = patm_lmbuf_alloc(sc)) == NULL) { 367117632Sharti patm_lbuf_free(sc, b0); 368117632Sharti break; 369117632Sharti } 370117632Sharti patm_fbq_write(sc, 1, 371117632Sharti LMBUF_HANDLE | b0->handle, b0->phy, 372117632Sharti LMBUF_HANDLE | b1->handle, b1->phy); 373117632Sharti 374117632Sharti feed -= 2; 375117632Sharti } 376117632Sharti} 377117632Sharti 378117632Sharti/* 379117632Sharti * Handle transmit status interrupt 380117632Sharti */ 381117632Shartistatic void 382117632Shartipatm_intr_tsif(struct patm_softc *sc) 383117632Sharti{ 384201758Smbr struct idt_tsqe *tsqe = sc->tsq_next; 385117632Sharti struct idt_tsqe *prev = NULL; 386117632Sharti uint32_t stamp; 387117632Sharti 388117632Sharti stamp = le32toh(tsqe->stamp); 389117632Sharti if (stamp & IDT_TSQE_EMPTY) 390117632Sharti return; 391117632Sharti 392117632Sharti do { 393117632Sharti switch (IDT_TSQE_TYPE(stamp)) { 394117632Sharti 395117632Sharti case IDT_TSQE_TBD: 396117632Sharti patm_tx(sc, stamp, le32toh(tsqe->stat)); 397117632Sharti break; 398117632Sharti 399117632Sharti case IDT_TSQE_IDLE: 400117632Sharti patm_tx_idle(sc, le32toh(tsqe->stat)); 401117632Sharti break; 402117632Sharti } 403117632Sharti 404117632Sharti /* recycle */ 405117632Sharti tsqe->stat = 0; 406117632Sharti tsqe->stamp = htole32(IDT_TSQE_EMPTY); 407117632Sharti 408117632Sharti /* save pointer to this entry and advance */ 409117632Sharti prev = tsqe; 410117632Sharti if (++tsqe == &sc->tsq[IDT_TSQ_SIZE]) 411117632Sharti tsqe = &sc->tsq[0]; 412117632Sharti 413117632Sharti stamp = le32toh(tsqe->stamp); 414117632Sharti } while (!(stamp & IDT_TSQE_EMPTY)); 415117632Sharti 416117632Sharti sc->tsq_next = tsqe; 417117632Sharti patm_nor_write(sc, IDT_NOR_TSQH, ((prev - sc->tsq) << IDT_TSQE_SHIFT)); 418117632Sharti} 419117632Sharti 420117632Sharti/* 421117632Sharti * Handle receive interrupt 422117632Sharti */ 423117632Shartivoid 424117632Shartipatm_intr_rsq(struct patm_softc *sc) 425117632Sharti{ 426117632Sharti struct idt_rsqe *rsqe; 427117632Sharti u_int stat; 428117632Sharti 429117632Sharti if (sc->rsq_last + 1 == PATM_RSQ_SIZE) 430117632Sharti rsqe = &sc->rsq[0]; 431117632Sharti else 432117632Sharti rsqe = &sc->rsq[sc->rsq_last + 1]; 433117632Sharti stat = le32toh(rsqe->stat); 434117632Sharti if (!(stat & IDT_RSQE_VALID)) 435117632Sharti return; 436117632Sharti 437117632Sharti while (stat & IDT_RSQE_VALID) { 438117632Sharti patm_rx(sc, rsqe); 439117632Sharti 440117632Sharti /* recycle RSQE */ 441117632Sharti rsqe->cid = 0; 442117632Sharti rsqe->handle = 0; 443117632Sharti rsqe->crc = 0; 444117632Sharti rsqe->stat = 0; 445117632Sharti 446117632Sharti /* save pointer to this entry and advance */ 447117632Sharti if (++sc->rsq_last == PATM_RSQ_SIZE) 448117632Sharti sc->rsq_last = 0; 449117632Sharti if (++rsqe == &sc->rsq[PATM_RSQ_SIZE]) 450117632Sharti rsqe = sc->rsq; 451117632Sharti 452117632Sharti stat = le32toh(rsqe->stat); 453117632Sharti } 454117632Sharti 455117632Sharti patm_nor_write(sc, IDT_NOR_RSQH, sc->rsq_phy | (sc->rsq_last << 2)); 456117632Sharti 457117632Sharti patm_feed_sbufs(sc); 458117632Sharti patm_feed_lbufs(sc); 459117632Sharti patm_feed_vbufs(sc); 460117632Sharti} 461117632Sharti 462117632Sharti/* 463117632Sharti * Handle raw cell receive. 464117632Sharti * 465117632Sharti * Note that the description on page 3-8 is wrong. The RAWHND contains not 466117632Sharti * the same value as RAWCT. RAWCT points to the next address the chip is 467117632Sharti * going to write to whike RAWHND points to the last cell's address the chip 468117632Sharti * has written to. 469117632Sharti */ 470117632Shartistatic void 471117632Shartipatm_intr_raw(struct patm_softc *sc) 472117632Sharti{ 473117632Sharti uint32_t tail; 474117632Sharti uint32_t h, *cell; 475117632Sharti 476117632Sharti#ifdef notyet 477117632Sharti bus_dma_sync_size(sc->sq_tag, sc->sq_map, IDT_TSQ_SIZE * IDT_TSQE_SIZE + 478117632Sharti PATM_RSQ_SIZE * IDT_RSQE_SIZE, sizeof(*sc->rawhnd), 479117632Sharti BUS_DMASYNC_POSTREAD); 480117632Sharti#endif 481117632Sharti /* first turn */ 482117632Sharti if (sc->rawh == NULL) { 483117632Sharti sc->rawh = &sc->lbufs[le32toh(sc->rawhnd->handle) & MBUF_HMASK]; 484117632Sharti } 485117632Sharti tail = le32toh(sc->rawhnd->tail); 486117632Sharti if (tail == sc->rawh->phy) 487117632Sharti /* not really a raw interrupt */ 488117632Sharti return; 489117632Sharti 490117632Sharti while (tail + 64 != sc->rawh->phy + sc->rawi * 64) { 491117632Sharti#ifdef notyet 492117632Sharti bus_dmamap_sync_size(sc->lbuf_tag, sc->rawh->map, 493117632Sharti sc->rawi * 64, 64, BUS_DMASYNC_POSTREAD); 494117632Sharti#endif 495117632Sharti cell = (uint32_t *)(mtod(sc->rawh->m, u_char *) + 496117632Sharti sc->rawi * 64); 497117632Sharti if (sc->rawi == (LMBUF_SIZE / 64) - 1) { 498117632Sharti /* chain */ 499117632Sharti h = le32toh(cell[1]); 500117632Sharti patm_lbuf_free(sc, sc->rawh); 501117632Sharti sc->rawh = &sc->lbufs[h & MBUF_HMASK]; 502117632Sharti sc->rawi = 0; 503117632Sharti continue; 504117632Sharti } 505117632Sharti 506117632Sharti patm_rx_raw(sc, (u_char *)cell); 507117632Sharti sc->rawi++; 508117632Sharti } 509117632Sharti} 510117632Sharti 511117632Sharti/* 512117632Sharti * Free a large mbuf. This is called by us. 513117632Sharti */ 514117632Shartivoid 515117632Shartipatm_lbuf_free(struct patm_softc *sc, struct lmbuf *b) 516117632Sharti{ 517117632Sharti 518117632Sharti bus_dmamap_unload(sc->lbuf_tag, b->map); 519117632Sharti if (b->m != NULL) { 520117632Sharti m_free(b->m); 521117632Sharti b->m = NULL; 522117632Sharti } 523117632Sharti SLIST_INSERT_HEAD(&sc->lbuf_free_list, b, link); 524117632Sharti} 525117632Sharti 526117632Sharti#ifdef PATM_DEBUG 527117632Shartistatic int 528117632Shartipatm_mbuf_cnt(u_int unit) 529117632Sharti{ 530117632Sharti devclass_t dc; 531117632Sharti struct patm_softc *sc; 532117632Sharti u_int used, card, free; 533117632Sharti 534117632Sharti dc = devclass_find("patm"); 535117632Sharti if (dc == NULL) { 536117632Sharti printf("%s: can't find devclass\n", __func__); 537117632Sharti return (0); 538117632Sharti } 539117632Sharti sc = devclass_get_softc(dc, unit); 540117632Sharti if (sc == NULL) { 541117632Sharti printf("%s: invalid unit number: %d\n", __func__, unit); 542117632Sharti return (0); 543117632Sharti } 544117632Sharti 545117632Sharti mbp_count(sc->sbuf_pool, &used, &card, &free); 546117632Sharti printf("sbufs: %u on card, %u used, %u free\n", card, used, free); 547117632Sharti 548117632Sharti mbp_count(sc->vbuf_pool, &used, &card, &free); 549117632Sharti printf("aal0 bufs: %u on card, %u used, %u free\n", card, used, free); 550117632Sharti 551117632Sharti return (0); 552117632Sharti} 553117632Sharti#endif 554