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