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/idt/idt_harp.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) 2000, 2001 Richard Hodges and Matriplex, inc.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *    This product includes software developed by Matriplex, inc.
   16  * 4. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  ******************************************************************************
   32  *
   33  * This driver is derived from the Nicstar driver by Mark Tinguely, and
   34  * some of the original driver still exists here.  Those portions are...
   35  *   Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
   36  *   All rights reserved.
   37  *
   38  ******************************************************************************
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __FBSDID("$FreeBSD$");
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/lock.h>
   48 #include <sys/malloc.h>
   49 #include <sys/socket.h>
   50 #include <sys/socketvar.h>
   51 #include <sys/syslog.h>
   52 
   53 #include <sys/bus.h>
   54 #include <sys/conf.h>
   55 
   56 #include <sys/module.h>
   57 #include <machine/bus_memio.h>
   58 #include <machine/bus.h>
   59 #include <machine/resource.h>
   60 #include <sys/rman.h>
   61 
   62 #include <net/if.h>
   63 #include <net/if_arp.h>
   64 #include <net/netisr.h>
   65 #include <net/if_var.h>
   66 
   67 #include <netatm/port.h>
   68 #include <netatm/queue.h>
   69 #include <netatm/atm.h>
   70 #include <netatm/atm_sys.h>
   71 #include <netatm/atm_sap.h>
   72 #include <netatm/atm_cm.h>
   73 #include <netatm/atm_if.h>
   74 #include <netatm/atm_stack.h>
   75 #include <netatm/atm_pcb.h>
   76 #include <netatm/atm_var.h>
   77 #include <netatm/atm_vc.h>
   78 
   79 #include <dev/idt/idtreg.h>
   80 #include <dev/idt/idtvar.h>
   81 
   82 /******************************************************************************
   83  *
   84  * HARP-specific definitions
   85  *
   86  */
   87 
   88 #define IDT_DEV_NAME    "idt"
   89 
   90 #define IDT_IFF_MTU     9188
   91 #define IDT_MAX_VCI     1023    /* 0 - 1023 */
   92 #define IDT_MAX_VPI     0
   93 
   94 #define iv_next         iv_cmn.cv_next
   95 #define iv_toku         iv_cmn.cv_toku
   96 #define iv_upper        iv_cmn.cv_upper
   97 #define iv_vccb         iv_cmn.cv_connvc        /* HARP 3.0 */
   98 #define iv_state        iv_cmn.cv_state
   99 #define iu_pif          iu_cmn.cu_pif
  100 #define iu_unit         iu_cmn.cu_unit
  101 #define iu_flags        iu_cmn.cu_flags
  102 #define iu_mtu          iu_cmn.cu_mtu
  103 #define iu_open_vcc     iu_cmn.cu_open_vcc
  104 #define iu_instvcc      iu_cmn.cu_instvcc       /* HARP 3.0 */
  105 #define iu_vcc          iu_cmn.cu_vcc
  106 #define iu_vcc_zone     iu_cmn.cu_vcc_zone
  107 #define iu_nif_zone     iu_cmn.cu_nif_zone
  108 #define iu_ioctl        iu_cmn.cu_ioctl
  109 #define iu_openvcc      iu_cmn.cu_openvcc
  110 #define iu_closevcc     iu_cmn.cu_closevcc
  111 #define iu_output       iu_cmn.cu_output
  112 #define iu_config       iu_cmn.cu_config
  113 #define iu_softc        iu_cmn.cu_softc
  114 
  115 /*
  116  * ATM Interface services
  117  */
  118 static struct stack_defn idt_svaal5 = {
  119         NULL,
  120         SAP_CPCS_AAL5,
  121         SDF_TERM,
  122         atm_dev_inst,
  123         atm_dev_lower,
  124         NULL,
  125         0,
  126 };
  127 static struct stack_defn idt_svaal4 = {
  128         &idt_svaal5,
  129         SAP_CPCS_AAL3_4,
  130         SDF_TERM,
  131         atm_dev_inst,
  132         atm_dev_lower,
  133         NULL,
  134         0,
  135 };
  136 static struct stack_defn idt_svaal0 = {
  137         &idt_svaal4,
  138         SAP_ATM,
  139         SDF_TERM,
  140         atm_dev_inst,
  141         atm_dev_lower,
  142         NULL,
  143         0,
  144 };
  145 struct stack_defn *idt_services = &idt_svaal0;
  146 
  147 extern uma_zone_t idt_nif_zone;
  148 extern uma_zone_t idt_vcc_zone;
  149 
  150 static int idt_atm_bearerclass(struct attr_bearer *);
  151 #ifdef T_ATM_BUFQUEUE
  152 static CONNECTION *idt_atm_harpconn(Cmn_unit *, Cmn_vcc *);
  153 #endif
  154 static int idt_atm_ioctl(int, caddr_t, caddr_t);
  155 
  156 static void idt_output(Cmn_unit *, Cmn_vcc *, KBuffer *);
  157 static int idt_openvcc(Cmn_unit *, Cmn_vcc *);
  158 static int idt_closevcc(Cmn_unit *, Cmn_vcc *);
  159 static int idt_instvcc(Cmn_unit *, Cmn_vcc *);
  160 
  161 static void idt_recv_stack(void *, KBuffer *);
  162 
  163 /******************************************************************************
  164  *
  165  *                       HARP GLUE SECTION
  166  *
  167  ******************************************************************************
  168  *
  169  * Handle netatm core service interface ioctl requests
  170  *
  171  * Called at splnet.
  172  *
  173  * Arguments:
  174  *    code       ioctl function (sub)code
  175  *    data       data to/from ioctl
  176  *    arg        optional code-specific argument
  177  *
  178  * Returns:
  179  *    0          request processed successfully
  180  *    error      request failed - reason code
  181  *
  182  */
  183 static int
  184 idt_atm_ioctl(int code, caddr_t addr, caddr_t arg)
  185 {
  186 #ifdef T_ATM_BUFQUEUE
  187         CONNECTION *connection;
  188         TX_QUEUE *txq;
  189         struct mbuf *m;
  190         Cmn_unit *cup;
  191         Cmn_vcc *cvp;
  192         int retval;
  193 #endif
  194 
  195         switch (code) {
  196 
  197 #ifdef T_ATM_BUFQUEUE
  198         case T_ATM_BUFQUEUE:
  199                 cup = (Cmn_unit *) addr;
  200                 cvp = (Cmn_vcc *) arg;
  201                 connection = idt_atm_harpconn(cup, cvp);
  202                 if (connection == NULL)
  203                         return (-1);
  204                 retval = 0;
  205                 txq = connection->queue;
  206                 if (txq == NULL)
  207                         return (-1);
  208                 for (m = txq->mget; m != NULL; m = m->m_nextpkt)
  209                         retval += m->m_pkthdr.len;
  210                 return (retval);
  211 #endif
  212         }
  213 
  214         return (ENOSYS);
  215 }
  216 
  217 #ifdef T_ATM_BUFQUEUE
  218 /*******************************************************************************
  219  *
  220  *  Get connection pointer from Cmn_unit and Cmn_vcc
  221  *
  222  *  in:  Cmn_unit and Cmn_vcc
  223  * out:  connection (NULL=error)
  224  *
  225  *  Date first: 05/31/2001  last: 05/31/2001
  226  */
  227 
  228 static CONNECTION *
  229 idt_atm_harpconn(Cmn_unit * cup, Cmn_vcc * cvp)
  230 {
  231         struct vccb *vccinf;    /* from HARP struct */
  232         IDT *idt;
  233         int vpi;
  234         int vci;
  235 
  236         idt = (IDT *) cup;
  237         if (idt == NULL || cvp == NULL)
  238                 return (NULL);
  239 
  240         if (cvp->cv_connvc == NULL)
  241                 return (NULL);
  242 
  243         vccinf = cvp->cv_connvc->cvc_vcc;
  244 
  245         if (vccinf == NULL)
  246                 return (NULL);
  247 
  248         vpi = vccinf->vc_vpi;
  249         vci = vccinf->vc_vci;
  250 
  251         return (idt_connect_find(idt, vpi, vci));
  252 }
  253 #endif  /* T_ATM_BUFQUEUE */
  254 
  255 /*******************************************************************************
  256  *
  257  *  Get CBR/VBR/UBR class from bearer attribute
  258  *
  259  *  in:
  260  * out:  NICCBR/NICVBR/NICABR/NICUBR
  261  *
  262  *  Date first: 06/12/2001  last: 06/13/2001
  263  */
  264 
  265 static int
  266 idt_atm_bearerclass(struct attr_bearer * bearer)
  267 {
  268         switch (bearer->v.bearer_class) {
  269                 case T_ATM_CLASS_A:return (NICCBR);
  270         case T_ATM_CLASS_C:
  271                 if (idt_sysctl_vbriscbr)
  272                         return (NICCBR);        /* use CBR slots for VBR VC's */
  273                 else
  274                         return (NICVBR);
  275         case T_ATM_CLASS_X:
  276                 if (bearer->v.traffic_type == T_ATM_CBR)
  277                         return (NICCBR);
  278                 if (bearer->v.traffic_type == T_ATM_VBR)
  279                         return (NICVBR);
  280                 return (NICUBR);
  281         }
  282         return (NICUBR);
  283 }
  284 
  285 /*  The flag idt_sysctl_vbriscbr allows us to set up a CBR VC as if it were
  286  *  VBR.  This is primarily to avoid cell loss at a switch that cannot seem
  287  *  to buffer one or two cells of jitter.  This jitter is created when many
  288  *  CBR slots have been taken, and a new CBR VC cannot use the optimally
  289  *  spaced slots, and has to use nearby slots instead.
  290  *
  291  *  In this case, we want to use the VC SCR as the CBR value.  The PCR and MBS
  292  *  is only of interest to the switch.
  293  *
  294  *******************************************************************************
  295  *
  296  *  Initialize HARP service
  297  *  called from device attach
  298  */
  299 
  300 int
  301 idt_harp_init(nicstar_reg_t *idt)
  302 {
  303         long long tsc_val;
  304         u_char idt_mac[6];
  305         int i;
  306         int error;
  307 
  308         error = 0;
  309 
  310         /*
  311          * Start initializing it
  312          */
  313         idt->iu_unit = device_get_unit(idt->dev);
  314         idt->iu_mtu = IDT_IFF_MTU;
  315         idt->iu_ioctl = idt_atm_ioctl;
  316         idt->iu_openvcc = idt_openvcc;
  317         idt->iu_instvcc = idt_instvcc;
  318         idt->iu_closevcc = idt_closevcc;
  319         idt->iu_output = idt_output;
  320         idt->iu_vcc_zone = idt_vcc_zone;
  321         idt->iu_nif_zone = idt_nif_zone;
  322         idt->iu_softc = (void *)idt;
  323 
  324         /*
  325          * Copy serial number into config space
  326          */
  327         idt->iu_config.ac_serial = 0;
  328 
  329         idt->iu_config.ac_vendor = VENDOR_IDT;
  330         idt->iu_config.ac_vendapi = VENDAPI_IDT_1;
  331         idt->iu_config.ac_device = DEV_IDT_155;
  332         idt->iu_config.ac_media = MEDIA_UNKNOWN;
  333         idt->iu_config.ac_bustype = BUS_PCI;
  334 
  335         idt->iu_pif.pif_pcr = idt->cellrate_rmax;       /* ATM_PCR_OC3C; */
  336         idt->iu_pif.pif_maxvpi = idt->conn_maxvpi;
  337         idt->iu_pif.pif_maxvci = idt->conn_maxvci;
  338 
  339         snprintf(idt->iu_config.ac_hard_vers,
  340                  sizeof(idt->iu_config.ac_hard_vers),
  341                  idt->hardware);
  342         snprintf(idt->iu_config.ac_firm_vers,
  343                  sizeof(idt->iu_config.ac_firm_vers),
  344                  IDT_VERSION);
  345         /*
  346          * Save device ram info for user-level programs NOTE: This really
  347          * points to start of EEPROM and includes all the device registers
  348          * in the lower 2 Megabytes.
  349          */
  350         idt->iu_config.ac_ram = 0;
  351         idt->iu_config.ac_ramsize = 0;
  352 
  353         for (i = 0; i < 6; i++) {
  354                 idt_mac[i] = nicstar_eeprom_rd(idt, (0x6c + i));
  355         }
  356 
  357         /* looks like bad MAC */
  358         if ((idt_mac[3] | idt_mac[4] | idt_mac[5]) == 0) {
  359                 GET_RDTSC(tsc_val);     /* 24 bits on 500mhz CPU is about
  360                                          * 30msec */
  361                 idt_mac[0] = 0x00;
  362                 idt_mac[1] = 0x20;
  363                 idt_mac[2] = 0x48;      /* use Fore prefix */
  364                 idt_mac[3] = (tsc_val >> 16) & 0xff;
  365                 idt_mac[4] = (tsc_val >> 8) & 0xff;
  366                 idt_mac[5] = (tsc_val) & 0xff;
  367                 device_printf(idt->dev,
  368                         "Cannot read MAC address from EEPROM, generating it.\n");
  369         }
  370         bcopy(&idt_mac, &idt->iu_pif.pif_macaddr.ma_data, sizeof(idt_mac));
  371 
  372         device_printf(idt->dev, "MAC address %6D, HWrev=%d\n",
  373                 (u_int8_t *)&idt->iu_pif.pif_macaddr.ma_data, ":",
  374                 idt->pci_rev);
  375 
  376         idt->iu_config.ac_macaddr = idt->iu_pif.pif_macaddr;
  377 
  378         /*
  379          * Register this interface with ATM core services
  380          */
  381         error = atm_physif_register(&idt->iu_cmn, IDT_DEV_NAME, idt_services);
  382         if (error != 0) {
  383                 /*
  384                  * Registration failed - back everything out
  385                  */
  386 
  387                 log(LOG_ERR, "%s(): atm_physif_register failed\n", __func__);
  388                 return (error);
  389         }
  390         idt->iu_flags |= CUF_INITED;
  391 
  392 #if BSD >= 199506
  393         /*
  394          * Add hook to out shutdown function at_shutdown (
  395          * (bootlist_fn)idt_pci_shutdown, idt, SHUTDOWN_POST_SYNC );
  396          */
  397 #endif
  398 
  399         return (error);
  400 }
  401 
  402 /*******************************************************************************
  403  *
  404  *  Output data
  405  */
  406 
  407 static void
  408 idt_output(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc, KBuffer * m)
  409 {
  410         struct vccb *vccinf;    /* from HARP struct */
  411         IDT *idt;
  412         int vpi;
  413         int vci;
  414         int flags;
  415 
  416         idt = (IDT *) cmnunit;
  417         flags = 0;
  418 
  419         if (cmnvcc == NULL) {
  420                 device_printf(idt->dev, "idt_output arg error #1\n");
  421                 goto bad;
  422         }
  423         if (cmnvcc->cv_connvc == NULL) {
  424                 device_printf(idt->dev, "idt_output arg error #2\n");
  425                 goto bad;
  426         }
  427         vccinf = cmnvcc->cv_connvc->cvc_vcc;
  428         if (vccinf == NULL) {
  429                 device_printf(idt->dev, "idt_output arg error #3\n");
  430                 goto bad;
  431         }
  432         vpi = vccinf->vc_vpi;
  433         vci = vccinf->vc_vci;
  434 
  435 #ifdef CVF_MPEG2TS              /* option to split bufs into small TS bufs */
  436         if (cmnvcc->cv_flags & CVF_MPEG2TS)
  437                 flags = 1;
  438 #endif
  439 
  440         idt_transmit(idt, m, vpi, vci, flags);
  441 
  442         return;
  443 bad:
  444         m_freem(m);
  445         return;
  446 }
  447 
  448 /*******************************************************************************
  449  *
  450  *  Open VCC
  451  */
  452 
  453 static int
  454 idt_openvcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
  455 {
  456         Atm_attributes *attrib; /* from HARP struct */
  457         struct vccb *vccinf;    /* from HARP struct */
  458         CONNECTION *connection;
  459         IDT *idt;
  460         int vpi;
  461         int vci;
  462         int class;              /* NICCBR, NICVBR, or NICUBR */
  463 
  464         idt = (IDT *) cmnunit;
  465 
  466         if (cmnvcc == NULL || cmnvcc->cv_connvc == NULL) {
  467                 printf("idt_openvcc: bad request #1.\n");
  468                 return (1);
  469         }
  470         attrib = &cmnvcc->cv_connvc->cvc_attr;
  471         vccinf = cmnvcc->cv_connvc->cvc_vcc;
  472 
  473         if (attrib == NULL || vccinf == NULL) {
  474                 printf("idt_openvcc: bad request #2.\n");
  475                 return (1);
  476         }
  477         vpi = vccinf->vc_vpi;
  478         vci = vccinf->vc_vci;
  479 
  480         connection = idt_connect_find(idt, vpi, vci);
  481         if (connection == NULL) {
  482                 printf("idt_openvcc: vpi/vci invalid: %d/%d\n", vpi, vci);
  483                 return (1);
  484         }
  485         if (connection->status) {
  486                 printf("idt_openvcc: connection already open %d/%d\n", vpi, vci);
  487                 return (1);
  488         }
  489         connection->status = 1;
  490         connection->recv = NULL;
  491         connection->rlen = 0;
  492         connection->maxpdu = 20000;
  493         connection->aal = IDTAAL5;
  494         connection->traf_pcr = attrib->traffic.v.forward.PCR_all_traffic;
  495         connection->traf_scr = attrib->traffic.v.forward.SCR_all_traffic;
  496         connection->vccinf = vccinf;    /* 12/15/2000 */
  497 
  498         if (connection->traf_pcr <= 0)
  499                 connection->traf_pcr = connection->traf_scr;
  500         if (connection->traf_scr <= 0)
  501                 connection->traf_scr = connection->traf_pcr;
  502 
  503         class = idt_atm_bearerclass(&attrib->bearer);
  504         if (vpi == 0 && vci == 5)
  505                 class = NICABR; /* higher priority than UBR */
  506         if (vpi == 0 && vci == 16)
  507                 class = NICABR;
  508 
  509         if (connection->traf_pcr < 0) { /* neither PCR nor SCR given */
  510                 connection->traf_pcr = 1;
  511                 connection->traf_scr = 1;
  512                 class = NICUBR; /* so give it lowest priority */
  513         }
  514         connection->class = class;
  515 
  516         if (idt_connect_txopen(idt, connection)) {
  517                 device_printf(idt->dev, "cannot open connection for %d/%d\n",
  518                         vpi, vci);
  519                 return (1);
  520         }
  521         if (idt_sysctl_logvcs)
  522                 printf("idt_openvcc: %d/%d, PCR=%d, SCR=%d\n", vpi, vci,
  523                     connection->traf_pcr, connection->traf_scr);
  524         idt_connect_opencls(idt, connection, 1);        /* open entry in rcv
  525                                                          * connect table */
  526 
  527         return (0);
  528 }
  529 
  530 /*  We really don't handle ABR, but use it as a higher priority UBR.  The
  531  *  idea is that a UBR connection that gives a PCR (like 0/16) should
  532  *  be given preference over a UBR connection that wants "everything else".
  533  *
  534  *  Note that CLASS_X is typically UBR, but the traffic type information
  535  *  element may still specify CBR or VBR.
  536  *
  537  *******************************************************************************
  538  *
  539  *  Close VCC
  540  */
  541 
  542 static int
  543 idt_closevcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
  544 {
  545         CONNECTION *connection;
  546         nicstar_reg_t *idt = (nicstar_reg_t *) cmnunit;
  547         int vpi;
  548         int vci;
  549 
  550         if (cmnvcc && cmnvcc->cv_connvc && cmnvcc->cv_connvc->cvc_vcc) {
  551                 vpi = cmnvcc->cv_connvc->cvc_vcc->vc_vpi;
  552                 vci = cmnvcc->cv_connvc->cvc_vcc->vc_vci;
  553         } else {
  554                 printf("idt_closevcc: bad vcivpi\n");
  555                 return (0);
  556         }
  557         connection = idt_connect_find(idt, vpi, vci);
  558 
  559         if (connection == NULL) {
  560                 printf("idt_closevcc: vpi/vci invalid: %d/%d\n", vpi, vci);
  561                 return (0);
  562         }
  563         idt_connect_opencls(idt, connection, 0);        /* close entry in rcv
  564                                                          * connect table */
  565 
  566         if (connection->status == 0)
  567                 printf("idt_closevcc: close on empty connection %d/%d\n", vpi, vci);
  568         if (connection->recv != NULL)
  569                 m_freem(connection->recv);      /* recycle mbuf of partial PDU */
  570         idt_connect_txclose(idt, connection);
  571         connection->status = 0;
  572         connection->recv = NULL;
  573         connection->rlen = 0;
  574         connection->maxpdu = 0;
  575         connection->aal = 0;
  576         connection->traf_pcr = 0;
  577         connection->traf_scr = 0;
  578 
  579         if (idt_sysctl_logvcs)
  580                 printf("idt_closevcc: vpi=%d vci=%d\n", vpi, vci);
  581 
  582         return (0);
  583 }
  584 
  585 /*
  586  *
  587  * VCC Stack Instantiation
  588  *
  589  * This function is called via the common driver code during a device VCC
  590  * stack instantiation.  The common code has already validated some of
  591  * the request so we just need to check a few more IDT-specific details.
  592  *
  593  * Called at splnet.
  594  *
  595  * Arguments:
  596  *    cup    pointer to device common unit
  597  *    cvp    pointer to common VCC entry
  598  *
  599  * Returns:
  600  *    0    instantiation successful
  601  *    err     instantiation failed - reason indicated
  602  *
  603  */
  604 static int
  605 idt_instvcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
  606 {
  607         Atm_attributes *attrib; /* from HARP struct */
  608         IDT *idt;
  609         int class, pcr, scr;
  610         int slots_vc, slots_cur, slots_max;
  611 
  612         if (cmnvcc == NULL)
  613                 return (EINVAL);
  614         if (cmnvcc->cv_connvc == NULL)
  615                 return (EINVAL);
  616 
  617         idt = (IDT *) cmnunit;
  618         if (idt == NULL)
  619                 return (EINVAL);
  620 
  621         attrib = &cmnvcc->cv_connvc->cvc_attr;
  622 
  623         if (attrib == NULL)
  624                 return (EINVAL);
  625 
  626         pcr = attrib->traffic.v.forward.PCR_all_traffic;
  627         scr = attrib->traffic.v.forward.SCR_all_traffic;
  628 
  629         if (pcr <= 0)
  630                 pcr = scr;      /* if PCR missing, default to SCR */
  631         if (pcr <= 0)
  632                 pcr = 1;
  633         if (scr <= 0)
  634                 scr = pcr;
  635 
  636         class = idt_atm_bearerclass(&attrib->bearer);
  637         if (class == NICCBR) {
  638                 slots_max = idt->txslots_max;
  639                 slots_cur = idt->txslots_cur;
  640                 slots_vc = idt_slots_cbr(idt, scr);     /* 06/13/2001: now using
  641                                                          * SCR */
  642                 if (slots_vc + slots_cur > slots_max) {
  643                         if (idt_sysctl_logvcs)
  644                                 device_printf(idt->dev,
  645                                         "Insufficient bandwidth (vc=%d cur=%d max=%d)\n",
  646                                         slots_vc, slots_cur, slots_max);
  647                         return (EINVAL);
  648                 }
  649         }
  650         /* This part was take from /sys/dev/hfa/fore_vcm.c */
  651 
  652         switch (attrib->aal.type) {
  653         case ATM_AAL0:
  654                 break;
  655         case ATM_AAL3_4:
  656                 if ((attrib->aal.v.aal4.forward_max_SDU_size > IDT_IFF_MTU) ||
  657                     (attrib->aal.v.aal4.backward_max_SDU_size > IDT_IFF_MTU))
  658                         return (EINVAL);
  659                 break;
  660         case ATM_AAL5:
  661                 if ((attrib->aal.v.aal5.forward_max_SDU_size > IDT_IFF_MTU) ||
  662                     (attrib->aal.v.aal5.backward_max_SDU_size > IDT_IFF_MTU))
  663                         return (EINVAL);
  664                 break;
  665         default:
  666                 return (EINVAL);
  667         }
  668         return (0);
  669 }
  670 
  671 /*
  672  * Pass Incoming PDU up Stack
  673  *
  674  * This function is called via the core ATM interrupt queue callback
  675  * set in fore_recv_drain().  It will pass the supplied incoming
  676  * PDU up the incoming VCC's stack.
  677  *
  678  * Called at splnet.
  679  *
  680  * Arguments:
  681  *    tok        token to identify stack instantiation
  682  *    m        pointer to incoming PDU buffer chain
  683  *
  684  * Returns:
  685  *    none
  686  */
  687 static void
  688 idt_recv_stack(void *tok, KBuffer * m)
  689 {
  690         Idt_vcc *ivp = (Idt_vcc *) tok;
  691         int err;
  692 
  693         if ((m->m_flags & M_PKTHDR) == 0) {
  694                 printf("idt_recv_stack: Warning - mbuf chain has no header.\n");
  695                 KB_FREEALL(m);
  696                 return;
  697         }
  698         /*
  699          * Send the data up the stack
  700          */
  701         STACK_CALL(CPCS_UNITDATA_SIG, ivp->iv_upper,
  702             ivp->iv_toku, ivp->iv_vccb, (int)m, 0, err);
  703         if (err)
  704                 KB_FREEALL(m);
  705 
  706         return;
  707 }
  708 
  709 /******************************************************************************
  710  *
  711  *  Enqueue received PDU for HARP to handle
  712  *
  713  *  in:  IDT device, mbuf, vpi, vci
  714  *
  715  * Date last: 12/14/2000
  716  */
  717 
  718 void
  719 idt_receive(nicstar_reg_t * idt, struct mbuf * m, int vpi, int vci)
  720 {
  721         caddr_t cp;
  722         Cmn_vcc *vcc;
  723         int space;
  724 
  725         /*
  726          * The STACK_CALL needs to happen at splnet() in order for the stack
  727          * sequence processing to work.  Schedule an interrupt queue
  728          * callback at splnet() since we are currently at device level.
  729          */
  730 
  731         /*
  732          * Prepend callback function pointer and token value to buffer. We
  733          * have already guaranteed that the space is available in the first
  734          * buffer.
  735          */
  736 
  737         /*
  738          * vcc = atm_dev_vcc_find(&idt->iu_cmn, (vpivci>> 16), vpivci &
  739          * 0xffff, VCC_IN);
  740          */
  741 
  742         vcc = atm_dev_vcc_find(&idt->iu_cmn, vpi, vci, VCC_IN);
  743 
  744         if (vcc == NULL) {      /* harp stack not ready or no vcc */
  745                 printf("idt_receive: no VCC %d/%d\n", vpi, vci);
  746                 KB_FREEALL(m);
  747                 return;
  748         }
  749         space = m->m_data - idt_mbuf_base(m);
  750         if (space < sizeof(atm_intr_func_t) + sizeof(int)) {
  751                 printf("idt_receive: NOT enough buffer space (%d).\n", space);
  752                 KB_FREEALL(m);
  753                 return;
  754         }
  755         KB_HEADADJ(m, sizeof(atm_intr_func_t) + sizeof(int));
  756         KB_DATASTART(m, cp, caddr_t);
  757         *((atm_intr_func_t *) cp) = idt_recv_stack;
  758         cp += sizeof(atm_intr_func_t);
  759 
  760         *((void **)cp) = (void *)vcc;
  761 
  762         /*
  763          * Schedule callback
  764          */
  765         netisr_queue(NETISR_ATM, m);    /* mbuf is free'd on failure. */
  766 }

Cache object: 6a8ef75604ec52db4df8d68e512246ca


[ 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.