The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/hatm/if_hatm_rx.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2001-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  * Author: Hartmut Brandt <harti@freebsd.org>
   28  *
   29  * ForeHE driver.
   30  *
   31  * Receive.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include "opt_inet.h"
   38 #include "opt_natm.h"
   39 
   40 #include <sys/types.h>
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/bus.h>
   45 #include <sys/errno.h>
   46 #include <sys/conf.h>
   47 #include <sys/module.h>
   48 #include <sys/queue.h>
   49 #include <sys/syslog.h>
   50 #include <sys/condvar.h>
   51 #include <sys/sysctl.h>
   52 #include <vm/uma.h>
   53 
   54 #include <sys/sockio.h>
   55 #include <sys/mbuf.h>
   56 #include <sys/socket.h>
   57 
   58 #include <net/if.h>
   59 #include <net/if_media.h>
   60 #include <net/if_atm.h>
   61 #include <net/route.h>
   62 #ifdef ENABLE_BPF
   63 #include <net/bpf.h>
   64 #endif
   65 #include <netinet/in.h>
   66 #include <netinet/if_atm.h>
   67 
   68 #include <machine/bus.h>
   69 #include <machine/resource.h>
   70 #include <sys/bus.h>
   71 #include <sys/rman.h>
   72 #include <dev/pci/pcireg.h>
   73 #include <dev/pci/pcivar.h>
   74 
   75 #include <dev/utopia/utopia.h>
   76 #include <dev/hatm/if_hatmconf.h>
   77 #include <dev/hatm/if_hatmreg.h>
   78 #include <dev/hatm/if_hatmvar.h>
   79 
   80 void
   81 hatm_rx(struct hatm_softc *sc, u_int cid, u_int flags, struct mbuf *m0,
   82     u_int len)
   83 {
   84         struct hevcc *vcc;
   85         struct atm_pseudohdr aph;
   86         struct mbuf *m, *m1;
   87         u_int vpi, vci;
   88         u_char *ptr;
   89 
   90         DBG(sc, RX, ("cid=%#x flags=%#x len=%u mbuf=%p", cid, flags, len, m0));
   91 
   92         vcc = sc->vccs[cid];
   93         if (vcc == NULL)
   94                 goto drop;
   95 
   96         if (flags & HE_REGM_RBRQ_CON_CLOSED) {
   97                 if (vcc->vflags & HE_VCC_RX_CLOSING) {
   98                         vcc->vflags &= ~HE_VCC_RX_CLOSING;
   99                         if (vcc->param.flags & ATMIO_FLAG_ASYNC) {
  100                                 if (!(vcc->vflags & HE_VCC_OPEN))
  101                                         hatm_vcc_closed(sc, cid);
  102                         } else
  103                                 cv_signal(&sc->vcc_cv);
  104                 }
  105                 goto drop;
  106         }
  107 
  108         if (!(vcc->vflags & HE_VCC_RX_OPEN))
  109                 goto drop;
  110 
  111         if (flags & HE_REGM_RBRQ_HBUF_ERROR) {
  112                 sc->istats.hbuf_error++;
  113                 if (vcc->chain != NULL) {
  114                         m_freem(vcc->chain);
  115                         vcc->chain = vcc->last = NULL;
  116                 }
  117                 goto drop;
  118         }
  119         if (m0 == NULL) {
  120                 sc->istats.no_rcv_mbuf++;
  121                 return;
  122         }
  123 
  124         if ((m0->m_len = len) == 0) {
  125                 sc->istats.empty_hbuf++;
  126                 m_free(m0);
  127 
  128         } else if (vcc->chain == NULL) {
  129                 sc->istats.rx_seg++;
  130                 vcc->chain = vcc->last = m0;
  131                 vcc->last->m_next = NULL;
  132                 vcc->chain->m_pkthdr.len = m0->m_len;
  133                 vcc->chain->m_pkthdr.rcvif = sc->ifp;
  134 
  135         } else {
  136                 sc->istats.rx_seg++;
  137                 vcc->last->m_next = m0;
  138                 vcc->last = m0;
  139                 vcc->last->m_next = NULL;
  140                 vcc->chain->m_pkthdr.len += m0->m_len;
  141         }
  142 
  143         if (!(flags & HE_REGM_RBRQ_END_PDU))
  144                 return;
  145 
  146         if (flags & HE_REGM_RBRQ_CRC_ERROR) {
  147                 if (vcc->chain)
  148                         m_freem(vcc->chain);
  149                 vcc->chain = vcc->last = NULL;
  150                 sc->istats.crc_error++;
  151                 sc->ifp->if_ierrors++;
  152                 return;
  153         }
  154         if (flags & HE_REGM_RBRQ_LEN_ERROR) {
  155                 if (vcc->chain)
  156                         m_freem(vcc->chain);
  157                 vcc->chain = vcc->last = NULL;
  158                 sc->istats.len_error++;
  159                 sc->ifp->if_ierrors++;
  160                 return;
  161         }
  162 
  163 #ifdef HATM_DEBUG
  164         if (sc->debug & DBG_DUMP) {
  165                 struct mbuf *tmp;
  166 
  167                 for (tmp = vcc->chain; tmp != NULL; tmp = tmp->m_next) {
  168                         printf("mbuf %p: len=%u\n", tmp, tmp->m_len);
  169                         for (ptr = mtod(tmp, u_char *);
  170                             ptr < mtod(tmp, u_char *) + tmp->m_len; ptr++)
  171                                 printf("%02x ", *ptr);
  172                         printf("\n");
  173                 }
  174         }
  175 #endif
  176 
  177         if (vcc->param.aal == ATMIO_AAL_5) {
  178                 /*
  179                  * Need to remove padding and the trailer. The trailer
  180                  * may be split accross buffers according to 2.10.1.2
  181                  * Assume that mbufs sizes are even (buffer sizes and cell
  182                  * payload sizes are) and that there are no empty mbufs.
  183                  */
  184                 m = vcc->last;
  185                 if (m->m_len == 2) {
  186                         /* Ah, oh, only part of CRC */
  187                         if (m == vcc->chain) {
  188                                 /* ups */
  189                                 sc->istats.short_aal5++;
  190                                 m_freem(vcc->chain);
  191                                 vcc->chain = vcc->last = NULL;
  192                                 return;
  193                         }
  194                         for (m1 = vcc->chain; m1->m_next != m; m1 = m1->m_next)
  195                                 ;
  196                         ptr = (u_char *)m1->m_data + m1->m_len - 4;
  197 
  198                 } else if (m->m_len == 4) {
  199                         /* Ah, oh, only CRC */
  200                         if (m == vcc->chain) {
  201                                 /* ups */
  202                                 sc->istats.short_aal5++;
  203                                 m_freem(vcc->chain);
  204                                 vcc->chain = vcc->last = NULL;
  205                                 return;
  206                         }
  207                         for (m1 = vcc->chain; m1->m_next != m; m1 = m1->m_next)
  208                                 ;
  209                         ptr = (u_char *)m1->m_data + m1->m_len - 2;
  210 
  211                 } else if (m->m_len >= 6) {
  212                         ptr = (u_char *)m->m_data + m->m_len - 6;
  213                 } else
  214                         panic("hatm_rx: bad mbuf len %d", m->m_len);
  215 
  216                 len = (ptr[0] << 8) + ptr[1];
  217                 if (len > (u_int)vcc->chain->m_pkthdr.len - 4) {
  218                         sc->istats.badlen_aal5++;
  219                         m_freem(vcc->chain);
  220                         vcc->chain = vcc->last = NULL;
  221                         return;
  222                 }
  223                 m_adj(vcc->chain, -(vcc->chain->m_pkthdr.len - len));
  224         }
  225         m = vcc->chain;
  226         vcc->chain = vcc->last = NULL;
  227 
  228 #ifdef ENABLE_BPF
  229         if (!(vcc->param.flags & ATMIO_FLAG_NG) &&
  230             (vcc->param.aal == ATMIO_AAL_5) &&
  231             (vcc->param.flags & ATM_PH_LLCSNAP))
  232                 BPF_MTAP(sc->ifp, m);
  233 #endif
  234 
  235         vpi = HE_VPI(cid);
  236         vci = HE_VCI(cid);
  237 
  238         ATM_PH_FLAGS(&aph) = vcc->param.flags & 0xff;
  239         ATM_PH_VPI(&aph) = vpi;
  240         ATM_PH_SETVCI(&aph, vci);
  241 
  242         sc->ifp->if_ipackets++;
  243         /* this is in if_atmsubr.c */
  244         /* sc->ifp->if_ibytes += len; */
  245 
  246         vcc->ibytes += len;
  247         vcc->ipackets++;
  248 
  249 #if 0
  250         {
  251                 struct mbuf *tmp;
  252 
  253                 for (tmp = m; tmp != NULL; tmp = tmp->m_next) {
  254                         printf("mbuf %p: len=%u\n", tmp, tmp->m_len);
  255                         for (ptr = mtod(tmp, u_char *);
  256                             ptr < mtod(tmp, u_char *) + tmp->m_len; ptr++)
  257                                 printf("%02x ", *ptr);
  258                         printf("\n");
  259                 }
  260         }
  261 #endif
  262 
  263         atm_input(sc->ifp, &aph, m, vcc->rxhand);
  264 
  265         return;
  266 
  267   drop:
  268         if (m0 != NULL)
  269                 m_free(m0);
  270 }
  271 
  272 void
  273 hatm_rx_vcc_open(struct hatm_softc *sc, u_int cid)
  274 {
  275         struct hevcc *vcc = sc->vccs[cid];
  276         uint32_t rsr0, rsr1, rsr4;
  277 
  278         rsr0 = rsr1 = rsr4 = 0;
  279 
  280         if (vcc->param.traffic == ATMIO_TRAFFIC_ABR) {
  281                 rsr1 |= HE_REGM_RSR1_AQI;
  282                 rsr4 |= HE_REGM_RSR4_AQI;
  283         }
  284 
  285         if (vcc->param.aal == ATMIO_AAL_5) {
  286                 rsr0 |= HE_REGM_RSR0_STARTPDU | HE_REGM_RSR0_AAL_5;
  287         } else if (vcc->param.aal == ATMIO_AAL_0) {
  288                 rsr0 |= HE_REGM_RSR0_AAL_0;
  289         } else {
  290                 if (sc->rbp_s1.size != 0) {
  291                         rsr1 |= (1 << HE_REGS_RSR1_GROUP);
  292                         rsr4 |= (1 << HE_REGS_RSR4_GROUP);
  293                 }
  294                 rsr0 |= HE_REGM_RSR0_AAL_RAW | HE_REGM_RSR0_PTI7 |
  295                     HE_REGM_RSR0_RM | HE_REGM_RSR0_F5OAM;
  296         }
  297         rsr0 |= HE_REGM_RSR0_OPEN;
  298 
  299         WRITE_RSR(sc, cid, 0, 0xf, rsr0);
  300         WRITE_RSR(sc, cid, 1, 0xf, rsr1);
  301         WRITE_RSR(sc, cid, 4, 0xf, rsr4);
  302 
  303         vcc->vflags |= HE_VCC_RX_OPEN;
  304 }
  305 
  306 /*
  307  * Close the RX side of a VCC.
  308  */
  309 void
  310 hatm_rx_vcc_close(struct hatm_softc *sc, u_int cid)
  311 {
  312         struct hevcc *vcc = sc->vccs[cid];
  313         uint32_t v;
  314 
  315         vcc->vflags |= HE_VCC_RX_CLOSING;
  316         WRITE_RSR(sc, cid, 0, 0xf, 0);
  317 
  318         v = READ4(sc, HE_REGO_RCCSTAT);
  319         while ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) &&
  320                (READ4(sc, HE_REGO_RCCSTAT) & HE_REGM_RCCSTAT_PROG))
  321                 cv_timedwait(&sc->cv_rcclose, &sc->mtx, 1);
  322 
  323         if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING))
  324                 return;
  325 
  326         WRITE_MBOX4(sc, HE_REGO_RCON_CLOSE, cid);
  327 
  328         vcc->vflags |= HE_VCC_RX_CLOSING;
  329         vcc->vflags &= ~HE_VCC_RX_OPEN;
  330 }

Cache object: 0a280b1b876ef1d5cb295015a3d3624a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.