if_patm_rx.c revision 243857
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: head/sys/dev/patm/if_patm_rx.c 243857 2012-12-04 09:32:43Z glebius $"); 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#ifdef ENABLE_BPF 64117632Sharti#include <net/bpf.h> 65117632Sharti#endif 66117632Sharti#include <netinet/in.h> 67117632Sharti#include <netinet/if_atm.h> 68117632Sharti 69117632Sharti#include <machine/bus.h> 70117632Sharti#include <machine/resource.h> 71117632Sharti#include <sys/bus.h> 72117632Sharti#include <sys/rman.h> 73117632Sharti#include <sys/mbpool.h> 74117632Sharti 75117632Sharti#include <dev/utopia/utopia.h> 76117632Sharti#include <dev/patm/idt77252reg.h> 77117632Sharti#include <dev/patm/if_patmvar.h> 78117632Sharti 79117632Shartistatic void *patm_rcv_handle(struct patm_softc *sc, u_int handle); 80117632Shartistatic void patm_rcv_free(struct patm_softc *, void *, u_int handle); 81117632Shartistatic struct mbuf *patm_rcv_mbuf(struct patm_softc *, void *, u_int, int); 82117632Sharti 83117632Shartistatic __inline void 84117632Shartirct_write(struct patm_softc *sc, u_int cid, u_int w, u_int val) 85117632Sharti{ 86117632Sharti patm_sram_write(sc, sc->mmap->rct + cid * IDT_RCT_ENTRY_SIZE + w, val); 87117632Sharti} 88117632Shartistatic __inline u_int 89117632Shartirct_read(struct patm_softc *sc, u_int cid, u_int w) 90117632Sharti{ 91117632Sharti return (patm_sram_read(sc, sc->mmap->rct + 92117632Sharti cid * IDT_RCT_ENTRY_SIZE + w)); 93117632Sharti} 94117632Sharti 95117632Sharti/* check if we can open this one */ 96117632Shartiint 97117632Shartipatm_rx_vcc_can_open(struct patm_softc *sc, struct patm_vcc *vcc) 98117632Sharti{ 99117632Sharti return (0); 100117632Sharti} 101117632Sharti 102117632Sharti/* 103117632Sharti * open the VCC 104117632Sharti */ 105117632Shartivoid 106117632Shartipatm_rx_vcc_open(struct patm_softc *sc, struct patm_vcc *vcc) 107117632Sharti{ 108117632Sharti uint32_t w1 = IDT_RCT_OPEN; 109117632Sharti 110117632Sharti patm_debug(sc, VCC, "%u.%u RX opening", vcc->vcc.vpi, vcc->vcc.vci); 111117632Sharti 112117632Sharti switch (vcc->vcc.aal) { 113117632Sharti case ATMIO_AAL_0: 114117632Sharti w1 |= IDT_RCT_AAL0 | IDT_RCT_FBP2 | IDT_RCT_RCI; 115117632Sharti break; 116117632Sharti case ATMIO_AAL_34: 117117632Sharti w1 |= IDT_RCT_AAL34; 118117632Sharti break; 119117632Sharti case ATMIO_AAL_5: 120117632Sharti w1 |= IDT_RCT_AAL5; 121117632Sharti break; 122117632Sharti case ATMIO_AAL_RAW: 123117632Sharti w1 |= IDT_RCT_AALRAW | IDT_RCT_RCI; 124117632Sharti break; 125117632Sharti } 126117632Sharti 127117632Sharti if (vcc->cid != 0) 128118061Sharti patm_sram_write4(sc, sc->mmap->rct + vcc->cid * 129118061Sharti IDT_RCT_ENTRY_SIZE, w1, 0, 0, 0xffffffff); 130117632Sharti else { 131117632Sharti /* switch the interface into promiscuous mode */ 132117632Sharti patm_nor_write(sc, IDT_NOR_CFG, patm_nor_read(sc, IDT_NOR_CFG) | 133117632Sharti IDT_CFG_ICAPT | IDT_CFG_VPECA); 134117632Sharti } 135117632Sharti 136117632Sharti vcc->vflags |= PATM_VCC_RX_OPEN; 137117632Sharti} 138117632Sharti 139117632Sharti/* close the given vcc for transmission */ 140117632Shartivoid 141117632Shartipatm_rx_vcc_close(struct patm_softc *sc, struct patm_vcc *vcc) 142117632Sharti{ 143117632Sharti u_int w1; 144117632Sharti 145117632Sharti patm_debug(sc, VCC, "%u.%u RX closing", vcc->vcc.vpi, vcc->vcc.vci); 146117632Sharti 147117632Sharti if (vcc->cid == 0) { 148117632Sharti /* switch off promiscuous mode */ 149117632Sharti patm_nor_write(sc, IDT_NOR_CFG, patm_nor_read(sc, IDT_NOR_CFG) & 150117632Sharti ~(IDT_CFG_ICAPT | IDT_CFG_VPECA)); 151117632Sharti vcc->vflags &= ~PATM_VCC_RX_OPEN; 152117632Sharti return; 153117632Sharti } 154117632Sharti 155117632Sharti /* close the connection but keep state */ 156117632Sharti w1 = rct_read(sc, vcc->cid, 0); 157117632Sharti w1 &= ~IDT_RCT_OPEN; 158117632Sharti rct_write(sc, vcc->cid, 0, w1); 159117632Sharti 160117632Sharti /* minimum idle count */ 161117632Sharti w1 = (w1 & ~IDT_RCT_IACT_CNT_MASK) | (1 << IDT_RCT_IACT_CNT_SHIFT); 162117632Sharti rct_write(sc, vcc->cid, 0, w1); 163117632Sharti 164117632Sharti /* initialize scan */ 165117632Sharti patm_nor_write(sc, IDT_NOR_IRCP, vcc->cid); 166117632Sharti 167117632Sharti vcc->vflags &= ~PATM_VCC_RX_OPEN; 168117632Sharti vcc->vflags |= PATM_VCC_RX_CLOSING; 169117632Sharti 170117632Sharti /* 171117632Sharti * check the RSQ 172117632Sharti * This is a hack. The problem is, that although an entry is written 173117632Sharti * to the RSQ, no interrupt is generated. Also we must wait 1 cell 174117632Sharti * time for the SAR to process the scan of our connection. 175117632Sharti */ 176117632Sharti DELAY(1); 177117632Sharti patm_intr_rsq(sc); 178117632Sharti} 179117632Sharti 180117632Sharti/* transmission side finally closed */ 181117632Shartivoid 182117632Shartipatm_rx_vcc_closed(struct patm_softc *sc, struct patm_vcc *vcc) 183117632Sharti{ 184117632Sharti patm_debug(sc, VCC, "%u.%u RX finally closed", 185117632Sharti vcc->vcc.vpi, vcc->vcc.vci); 186117632Sharti} 187117632Sharti 188117632Sharti/* 189117632Sharti * Handle the given receive status queue entry 190117632Sharti */ 191117632Shartivoid 192117632Shartipatm_rx(struct patm_softc *sc, struct idt_rsqe *rsqe) 193117632Sharti{ 194117632Sharti struct mbuf *m; 195117632Sharti void *buf; 196117632Sharti u_int stat, cid, w, cells, len, h; 197117632Sharti struct patm_vcc *vcc; 198117632Sharti struct atm_pseudohdr aph; 199117632Sharti u_char *trail; 200117632Sharti 201117632Sharti cid = le32toh(rsqe->cid); 202117632Sharti stat = le32toh(rsqe->stat); 203117632Sharti h = le32toh(rsqe->handle); 204117632Sharti 205117632Sharti cid = PATM_CID(sc, IDT_RSQE_VPI(cid), IDT_RSQE_VCI(cid)); 206117632Sharti vcc = sc->vccs[cid]; 207117632Sharti 208117632Sharti if (IDT_RSQE_TYPE(stat) == IDT_RSQE_IDLE) { 209117632Sharti /* connection has gone idle */ 210117632Sharti if (stat & IDT_RSQE_BUF) 211117632Sharti patm_rcv_free(sc, patm_rcv_handle(sc, h), h); 212117632Sharti 213117632Sharti w = rct_read(sc, cid, 0); 214117632Sharti if (w != 0 && !(w & IDT_RCT_OPEN)) 215117632Sharti rct_write(sc, cid, 0, 0); 216117632Sharti if (vcc != NULL && (vcc->vflags & PATM_VCC_RX_CLOSING)) { 217117632Sharti patm_debug(sc, VCC, "%u.%u RX closed", vcc->vcc.vpi, 218117632Sharti vcc->vcc.vci); 219117632Sharti vcc->vflags &= ~PATM_VCC_RX_CLOSING; 220118539Sharti if (vcc->vcc.flags & ATMIO_FLAG_ASYNC) { 221117632Sharti patm_rx_vcc_closed(sc, vcc); 222117632Sharti if (!(vcc->vflags & PATM_VCC_OPEN)) 223117632Sharti patm_vcc_closed(sc, vcc); 224117632Sharti } else 225117632Sharti cv_signal(&sc->vcc_cv); 226117632Sharti } 227117632Sharti return; 228117632Sharti } 229117632Sharti 230117632Sharti buf = patm_rcv_handle(sc, h); 231117632Sharti 232117632Sharti if (vcc == NULL || (vcc->vflags & PATM_VCC_RX_OPEN) == 0) { 233117632Sharti patm_rcv_free(sc, buf, h); 234117632Sharti return; 235117632Sharti } 236117632Sharti 237117632Sharti cells = IDT_RSQE_CNT(stat); 238117632Sharti KASSERT(cells > 0, ("zero cell count")); 239117632Sharti 240117632Sharti if (vcc->vcc.aal == ATMIO_AAL_0) { 241117632Sharti /* deliver this packet as it is */ 242117632Sharti if ((m = patm_rcv_mbuf(sc, buf, h, 1)) == NULL) 243117632Sharti return; 244117632Sharti 245117632Sharti m->m_len = cells * 48; 246117632Sharti m->m_pkthdr.len = m->m_len; 247147256Sbrooks m->m_pkthdr.rcvif = sc->ifp; 248117632Sharti 249117632Sharti } else if (vcc->vcc.aal == ATMIO_AAL_34) { 250117632Sharti /* XXX AAL3/4 */ 251117632Sharti patm_rcv_free(sc, buf, h); 252117632Sharti return; 253117632Sharti 254117632Sharti } else if (vcc->vcc.aal == ATMIO_AAL_5) { 255117632Sharti if (stat & IDT_RSQE_CRC) { 256147256Sbrooks sc->ifp->if_ierrors++; 257117632Sharti if (vcc->chain != NULL) { 258117632Sharti m_freem(vcc->chain); 259117632Sharti vcc->chain = vcc->last = NULL; 260117632Sharti } 261117632Sharti return; 262117632Sharti } 263117632Sharti 264117632Sharti /* append to current chain */ 265117632Sharti if (vcc->chain == NULL) { 266117632Sharti if ((m = patm_rcv_mbuf(sc, buf, h, 1)) == NULL) 267117632Sharti return; 268117632Sharti m->m_len = cells * 48; 269117632Sharti m->m_pkthdr.len = m->m_len; 270147256Sbrooks m->m_pkthdr.rcvif = sc->ifp; 271117632Sharti vcc->chain = vcc->last = m; 272117632Sharti } else { 273117632Sharti if ((m = patm_rcv_mbuf(sc, buf, h, 0)) == NULL) 274117632Sharti return; 275117632Sharti m->m_len = cells * 48; 276117632Sharti vcc->last->m_next = m; 277117632Sharti vcc->last = m; 278117632Sharti vcc->chain->m_pkthdr.len += m->m_len; 279117632Sharti } 280117632Sharti 281117632Sharti if (!(stat & IDT_RSQE_EPDU)) 282117632Sharti return; 283117632Sharti 284117632Sharti trail = mtod(m, u_char *) + m->m_len - 6; 285117632Sharti len = (trail[0] << 8) + trail[1]; 286117632Sharti 287117632Sharti if ((u_int)vcc->chain->m_pkthdr.len < len + 8) { 288117632Sharti patm_printf(sc, "%s: bad aal5 lengths %u %u\n", 289117632Sharti __func__, (u_int)m->m_pkthdr.len, len); 290117632Sharti m_freem(vcc->chain); 291117632Sharti vcc->chain = vcc->last = NULL; 292117632Sharti return; 293117632Sharti } 294117632Sharti m->m_len -= vcc->chain->m_pkthdr.len - len; 295117632Sharti KASSERT(m->m_len >= 0, ("bad last mbuf")); 296117632Sharti 297117632Sharti m = vcc->chain; 298117632Sharti vcc->chain = vcc->last = NULL; 299117632Sharti m->m_pkthdr.len = len; 300117632Sharti } else 301117632Sharti panic("bad aal"); 302117632Sharti 303117632Sharti#if 0 304117632Sharti { 305117632Sharti u_int i; 306117632Sharti 307117632Sharti for (i = 0; i < m->m_len; i++) { 308117632Sharti printf("%02x ", mtod(m, u_char *)[i]); 309117632Sharti } 310117632Sharti printf("\n"); 311117632Sharti } 312117632Sharti#endif 313117632Sharti 314147256Sbrooks sc->ifp->if_ipackets++; 315117632Sharti /* this is in if_atmsubr.c */ 316147256Sbrooks /* sc->ifp->if_ibytes += m->m_pkthdr.len; */ 317117632Sharti 318117632Sharti vcc->ibytes += m->m_pkthdr.len; 319117632Sharti vcc->ipackets++; 320117632Sharti 321117632Sharti ATM_PH_FLAGS(&aph) = vcc->vcc.flags & 0xff; 322117632Sharti ATM_PH_VPI(&aph) = IDT_RSQE_VPI(cid); 323117632Sharti ATM_PH_SETVCI(&aph, IDT_RSQE_VCI(cid)); 324117632Sharti 325117632Sharti#ifdef ENABLE_BPF 326117632Sharti if (!(vcc->vcc.flags & ATMIO_FLAG_NG) && 327118539Sharti (vcc->vcc.aal == ATMIO_AAL_5) && 328117632Sharti (vcc->vcc.flags & ATM_PH_LLCSNAP)) 329147256Sbrooks BPF_MTAP(sc->ifp, m); 330117632Sharti#endif 331117632Sharti 332147256Sbrooks atm_input(sc->ifp, &aph, m, vcc->rxhand); 333117632Sharti} 334117632Sharti 335117632Sharti/* 336117632Sharti * Get the buffer for a receive handle. This is either an mbuf for 337117632Sharti * a large handle or a pool buffer for the others. 338117632Sharti */ 339117632Shartistatic void * 340117632Shartipatm_rcv_handle(struct patm_softc *sc, u_int handle) 341117632Sharti{ 342117632Sharti void *buf; 343117632Sharti u_int c; 344117632Sharti 345117632Sharti if ((handle & ~MBUF_HMASK) == LMBUF_HANDLE) { 346117632Sharti struct lmbuf *b; 347117632Sharti 348117632Sharti c = handle & MBUF_HMASK; 349117632Sharti b = &sc->lbufs[c]; 350117632Sharti 351117632Sharti buf = b->m; 352117632Sharti b->m = NULL; 353117632Sharti 354117632Sharti bus_dmamap_sync(sc->lbuf_tag, b->map, BUS_DMASYNC_POSTREAD); 355117632Sharti patm_lbuf_free(sc, b); 356117632Sharti 357117632Sharti } else if ((handle & ~MBUF_HMASK) == MBUF_VHANDLE) { 358117632Sharti mbp_sync(sc->vbuf_pool, handle, 359117632Sharti 0, VMBUF_SIZE, BUS_DMASYNC_POSTREAD); 360117632Sharti buf = mbp_get(sc->vbuf_pool, handle); 361117632Sharti 362117632Sharti } else { 363117632Sharti mbp_sync(sc->sbuf_pool, handle, 364117632Sharti 0, SMBUF_SIZE, BUS_DMASYNC_POSTREAD); 365117632Sharti buf = mbp_get(sc->sbuf_pool, handle); 366117632Sharti } 367117632Sharti 368117632Sharti return (buf); 369117632Sharti} 370117632Sharti 371117632Sharti/* 372117632Sharti * Free a buffer. 373117632Sharti */ 374117632Shartistatic void 375117632Shartipatm_rcv_free(struct patm_softc *sc, void *p, u_int handle) 376117632Sharti{ 377117632Sharti if ((handle & ~MBUF_HMASK) == LMBUF_HANDLE) 378117632Sharti m_free((struct mbuf *)p); 379117632Sharti 380117632Sharti else if ((handle & ~MBUF_HMASK) == MBUF_VHANDLE) 381117632Sharti mbp_free(sc->vbuf_pool, p); 382117632Sharti 383117632Sharti else 384117632Sharti mbp_free(sc->sbuf_pool, p); 385117632Sharti} 386117632Sharti 387117632Sharti/* 388117632Sharti * Make an mbuf around the buffer 389117632Sharti */ 390117632Shartistatic struct mbuf * 391117632Shartipatm_rcv_mbuf(struct patm_softc *sc, void *buf, u_int h, int hdr) 392117632Sharti{ 393117632Sharti struct mbuf *m; 394117632Sharti 395117632Sharti if ((h & ~MBUF_HMASK) == MBUF_LHANDLE) 396117632Sharti return ((struct mbuf *)buf); 397117632Sharti 398117632Sharti if (hdr) 399243857Sglebius MGETHDR(m, M_NOWAIT, MT_DATA); 400117632Sharti else 401243857Sglebius MGET(m, M_NOWAIT, MT_DATA); 402117632Sharti if (m == NULL) { 403117632Sharti patm_rcv_free(sc, buf, h); 404117632Sharti return (NULL); 405117632Sharti } 406117632Sharti 407117632Sharti if ((h & ~MBUF_HMASK) == MBUF_VHANDLE) { 408150347Sandre MEXTADD(m, (caddr_t)buf, VMBUF_SIZE, mbp_ext_free, 409175872Sphk buf, sc->vbuf_pool, M_PKTHDR, EXT_NET_DRV); 410117632Sharti m->m_data += VMBUF_OFFSET; 411117632Sharti } else { 412150347Sandre MEXTADD(m, (caddr_t)buf, SMBUF_SIZE, mbp_ext_free, 413175872Sphk buf, sc->sbuf_pool, M_PKTHDR, EXT_NET_DRV); 414117632Sharti m->m_data += SMBUF_OFFSET; 415117632Sharti } 416117632Sharti 417117632Sharti if (!(m->m_flags & M_EXT)) { 418117632Sharti patm_rcv_free(sc, buf, h); 419117632Sharti m_free(m); 420117632Sharti return (NULL); 421117632Sharti } 422117632Sharti return (m); 423117632Sharti} 424117632Sharti 425117632Sharti/* 426117632Sharti * Process the raw cell at the given address. 427117632Sharti */ 428117632Shartivoid 429117632Shartipatm_rx_raw(struct patm_softc *sc, u_char *cell) 430117632Sharti{ 431117632Sharti u_int vpi, vci, cid; 432117632Sharti struct patm_vcc *vcc; 433117632Sharti struct mbuf *m; 434117632Sharti u_char *dst; 435117632Sharti struct timespec ts; 436117632Sharti struct atm_pseudohdr aph; 437117632Sharti uint64_t cts; 438117632Sharti 439117632Sharti sc->stats.raw_cells++; 440117632Sharti 441117632Sharti /* 442117632Sharti * For some non-appearant reason the cell header 443117632Sharti * is in the wrong endian. 444117632Sharti */ 445117632Sharti *(uint32_t *)cell = bswap32(*(uint32_t *)cell); 446117632Sharti 447117632Sharti vpi = ((cell[0] & 0xf) << 4) | ((cell[1] & 0xf0) >> 4); 448117632Sharti vci = ((cell[1] & 0xf) << 12) | (cell[2] << 4) | ((cell[3] & 0xf0) >> 4); 449117632Sharti cid = PATM_CID(sc, vpi, vci); 450117632Sharti 451117632Sharti vcc = sc->vccs[cid]; 452117632Sharti if (vcc == NULL || !(vcc->vflags & PATM_VCC_RX_OPEN) || 453117632Sharti vcc->vcc.aal != ATMIO_AAL_RAW) { 454117632Sharti vcc = sc->vccs[0]; 455117632Sharti if (vcc == NULL || !(vcc->vflags & PATM_VCC_RX_OPEN)) { 456117632Sharti sc->stats.raw_no_vcc++; 457117632Sharti return; 458117632Sharti } 459117632Sharti } 460117632Sharti 461243857Sglebius MGETHDR(m, M_NOWAIT, MT_DATA); 462117632Sharti if (m == NULL) { 463117632Sharti sc->stats.raw_no_buf++; 464117632Sharti return; 465117632Sharti } 466147256Sbrooks m->m_pkthdr.rcvif = sc->ifp; 467117632Sharti 468117632Sharti switch (vcc->vflags & PATM_RAW_FORMAT) { 469117632Sharti 470117632Sharti default: 471117632Sharti case PATM_RAW_CELL: 472117632Sharti m->m_len = m->m_pkthdr.len = 53; 473117632Sharti MH_ALIGN(m, 53); 474117632Sharti dst = mtod(m, u_char *); 475117632Sharti *dst++ = *cell++; 476117632Sharti *dst++ = *cell++; 477117632Sharti *dst++ = *cell++; 478117632Sharti *dst++ = *cell++; 479117632Sharti *dst++ = 0; /* HEC */ 480117632Sharti bcopy(cell + 12, dst, 48); 481117632Sharti break; 482117632Sharti 483117632Sharti case PATM_RAW_NOHEC: 484117632Sharti m->m_len = m->m_pkthdr.len = 52; 485117632Sharti MH_ALIGN(m, 52); 486117632Sharti dst = mtod(m, u_char *); 487117632Sharti *dst++ = *cell++; 488117632Sharti *dst++ = *cell++; 489117632Sharti *dst++ = *cell++; 490117632Sharti *dst++ = *cell++; 491117632Sharti bcopy(cell + 12, dst, 48); 492117632Sharti break; 493117632Sharti 494117632Sharti case PATM_RAW_CS: 495117632Sharti m->m_len = m->m_pkthdr.len = 64; 496117632Sharti MH_ALIGN(m, 64); 497117632Sharti dst = mtod(m, u_char *); 498117632Sharti *dst++ = *cell++; 499117632Sharti *dst++ = *cell++; 500117632Sharti *dst++ = *cell++; 501117632Sharti *dst++ = *cell++; 502117632Sharti *dst++ = 0; /* HEC */ 503117632Sharti *dst++ = 0; /* flags */ 504117632Sharti *dst++ = 0; /* reserved */ 505117632Sharti *dst++ = 0; /* reserved */ 506117632Sharti nanotime(&ts); 507117632Sharti cts = ts.tv_sec * 1000000000ULL + ts.tv_nsec; 508117632Sharti bcopy(dst, &cts, 8); 509117632Sharti bcopy(cell + 12, dst + 8, 48); 510117632Sharti break; 511117632Sharti } 512117632Sharti 513147256Sbrooks sc->ifp->if_ipackets++; 514117632Sharti /* this is in if_atmsubr.c */ 515147256Sbrooks /* sc->ifp->if_ibytes += m->m_pkthdr.len; */ 516117632Sharti 517117632Sharti vcc->ibytes += m->m_pkthdr.len; 518117632Sharti vcc->ipackets++; 519117632Sharti 520117632Sharti ATM_PH_FLAGS(&aph) = vcc->vcc.flags & 0xff; 521117632Sharti ATM_PH_VPI(&aph) = vcc->vcc.vpi; 522117632Sharti ATM_PH_SETVCI(&aph, vcc->vcc.vci); 523117632Sharti 524147256Sbrooks atm_input(sc->ifp, &aph, m, vcc->rxhand); 525117632Sharti} 526