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/hfa/fore_command.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  *
    3  * ===================================
    4  * HARP  |  Host ATM Research Platform
    5  * ===================================
    6  *
    7  *
    8  * This Host ATM Research Platform ("HARP") file (the "Software") is
    9  * made available by Network Computing Services, Inc. ("NetworkCS")
   10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
   11  * support of any kind.
   12  *
   13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
   14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
   15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
   16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
   17  * In no event shall NetworkCS be responsible for any damages, including
   18  * but not limited to consequential damages, arising from or relating to
   19  * any use of the Software or related support.
   20  *
   21  * Copyright 1994-1998 Network Computing Services, Inc.
   22  *
   23  * Copies of this Software may be made, however, the above copyright
   24  * notice must be reproduced on all copies.
   25  *
   26  *      @(#) $FreeBSD: releng/5.3/sys/dev/hfa/fore_command.c 126122 2004-02-22 16:27:28Z mux $
   27  *
   28  */
   29 
   30 /*
   31  * FORE Systems 200-Series Adapter Support
   32  * ---------------------------------------
   33  *
   34  * Command queue management
   35  *
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/socket.h>
   41 #include <sys/socketvar.h>
   42 #include <sys/syslog.h>
   43 #include <vm/vm.h>
   44 #include <vm/pmap.h>
   45 #include <net/if.h>
   46 #include <netatm/port.h>
   47 #include <netatm/queue.h>
   48 #include <netatm/atm.h>
   49 #include <netatm/atm_sys.h>
   50 #include <netatm/atm_sap.h>
   51 #include <netatm/atm_cm.h>
   52 #include <netatm/atm_if.h>
   53 #include <netatm/atm_vc.h>
   54 #include <netatm/atm_stack.h>
   55 #include <netatm/atm_pcb.h>
   56 #include <netatm/atm_var.h>
   57 #include <dev/pci/pcivar.h>
   58 #include <dev/hfa/fore.h>
   59 #include <dev/hfa/fore_aali.h>
   60 #include <dev/hfa/fore_slave.h>
   61 #include <dev/hfa/fore_stats.h>
   62 #include <dev/hfa/fore_var.h>
   63 #include <dev/hfa/fore_include.h>
   64 
   65 #ifndef lint
   66 __RCSID("@(#) $FreeBSD: releng/5.3/sys/dev/hfa/fore_command.c 126122 2004-02-22 16:27:28Z mux $");
   67 #endif
   68 
   69 /*
   70  * Local variables
   71  */
   72 static struct t_atm_cause       fore_cause = {
   73         T_ATM_ITU_CODING,
   74         T_ATM_LOC_USER,
   75         T_ATM_CAUSE_TEMPORARY_FAILURE,
   76         {0, 0, 0, 0}
   77 };
   78 
   79 
   80 /*
   81  * Allocate Command Queue Data Structures
   82  *
   83  * Arguments:
   84  *      fup             pointer to device unit structure
   85  *
   86  * Returns:
   87  *      0               allocations successful
   88  *      else            allocation failed
   89  */
   90 int
   91 fore_cmd_allocate(fup)
   92         Fore_unit       *fup;
   93 {
   94         caddr_t         memp;
   95         vm_paddr_t      pmemp;
   96 
   97         /*
   98          * Allocate non-cacheable memory for command status words
   99          */
  100         memp = atm_dev_alloc(sizeof(Q_status) * CMD_QUELEN,
  101                         QSTAT_ALIGN, ATM_DEV_NONCACHE);
  102         if (memp == NULL) {
  103                 return (1);
  104         }
  105         fup->fu_cmd_stat = (Q_status *) memp;
  106 
  107         pmemp = vtophys(fup->fu_cmd_stat);
  108         if (pmemp == 0) {
  109                 return (1);
  110         }
  111         fup->fu_cmd_statd = pmemp;
  112 
  113         /*
  114          * Allocate memory for statistics buffer
  115          */
  116         memp = atm_dev_alloc(sizeof(Fore_stats), FORE_STATS_ALIGN, 0);
  117         if (memp == NULL) {
  118                 return (1);
  119         }
  120         fup->fu_stats = (Fore_stats *) memp;
  121 
  122         /*
  123          * Allocate memory for PROM buffer
  124          */
  125         memp = atm_dev_alloc(sizeof(Fore_prom), FORE_PROM_ALIGN, 0);
  126         if (memp == NULL) {
  127                 return (1);
  128         }
  129         fup->fu_prom = (Fore_prom *) memp;
  130 
  131         return (0);
  132 }
  133 
  134 
  135 /*
  136  * Command Queue Initialization
  137  *
  138  * Allocate and initialize the host-resident command queue structures
  139  * and then initialize the CP-resident queue structures.
  140  * 
  141  * Called at interrupt level.
  142  *
  143  * Arguments:
  144  *      fup             pointer to device unit structure
  145  *
  146  * Returns:
  147  *      none
  148  */
  149 void
  150 fore_cmd_initialize(fup)
  151         Fore_unit       *fup;
  152 {
  153         Aali            *aap = fup->fu_aali;
  154         Cmd_queue       *cqp;
  155         H_cmd_queue     *hcp;
  156         Q_status        *qsp;
  157         vm_paddr_t      qsp_dma;
  158         int             i;
  159 
  160         /*
  161          * Point to CP-resident command queue
  162          */
  163         cqp = (Cmd_queue *)(fup->fu_ram + CP_READ(aap->aali_cmd_q));
  164 
  165         /*
  166          * Point to host-resident command queue structures
  167          */
  168         hcp = fup->fu_cmd_q;
  169         qsp = fup->fu_cmd_stat;
  170         qsp_dma = fup->fu_cmd_statd;
  171 
  172         /*
  173          * Loop thru all queue entries and do whatever needs doing
  174          */
  175         for (i = 0; i < CMD_QUELEN; i++) {
  176 
  177                 /*
  178                  * Set queue status word to free
  179                  */
  180                 *qsp = QSTAT_FREE;
  181 
  182                 /*
  183                  * Set up host queue entry and link into ring
  184                  */
  185                 hcp->hcq_cpelem = cqp;
  186                 hcp->hcq_status = qsp;
  187                 if (i == (CMD_QUELEN - 1))
  188                         hcp->hcq_next = fup->fu_cmd_q;
  189                 else
  190                         hcp->hcq_next = hcp + 1;
  191 
  192                 /*
  193                  * Now let the CP into the game
  194                  */
  195                 cqp->cmdq_status = (CP_dma) CP_WRITE(qsp_dma);
  196 
  197                 /*
  198                  * Bump all queue pointers
  199                  */
  200                 hcp++;
  201                 qsp++;
  202                 qsp_dma += sizeof(Q_status);
  203                 cqp++;
  204         }
  205 
  206         /*
  207          * Initialize queue pointers
  208          */
  209         fup->fu_cmd_head = fup->fu_cmd_tail = fup->fu_cmd_q;
  210 
  211         return;
  212 }
  213 
  214 
  215 /*
  216  * Drain Command Queue
  217  *
  218  * This function will process and free all completed entries at the head 
  219  * of the command queue. 
  220  *
  221  * May be called in interrupt state.  
  222  * Must be called with interrupts locked out.
  223  *
  224  * Arguments:
  225  *      fup             pointer to device unit structure
  226  *
  227  * Returns:
  228  *      none
  229  */
  230 void
  231 fore_cmd_drain(fup)
  232         Fore_unit       *fup;
  233 {
  234         H_cmd_queue     *hcp;
  235         Fore_vcc        *fvp;
  236 
  237         /*
  238          * Process each completed entry
  239          * ForeThought 4 may set QSTAT_ERROR without QSTAT_COMPLETED.
  240          */
  241         while (*fup->fu_cmd_head->hcq_status & (QSTAT_COMPLETED | QSTAT_ERROR)) {
  242 
  243                 hcp = fup->fu_cmd_head;
  244 
  245                 /*
  246                  * Process command completion
  247                  */
  248                 switch (hcp->hcq_code) {
  249 
  250                 case CMD_ACT_VCCIN:
  251                 case CMD_ACT_VCCOUT:
  252                         fvp = hcp->hcq_arg;
  253                         if (*hcp->hcq_status & QSTAT_ERROR) {
  254                                 /*
  255                                  * VCC activation failed - just abort vcc
  256                                  */
  257                                 if (fvp)
  258                                         atm_cm_abort(fvp->fv_connvc,
  259                                                 &fore_cause);
  260                                 fup->fu_pif.pif_cmderrors++;
  261                         } else {
  262                                 /*
  263                                  * Successful VCC activation
  264                                  */
  265                                 if (fvp) {
  266                                         fvp->fv_state = CVS_ACTIVE;
  267                                         fup->fu_open_vcc++;
  268                                 }
  269                         }
  270                         break;
  271 
  272                 case CMD_DACT_VCCIN:
  273                 case CMD_DACT_VCCOUT:
  274                         fvp = hcp->hcq_arg;
  275                         if (*hcp->hcq_status & QSTAT_ERROR) {
  276                                 /*
  277                                  * VCC dactivation failed - whine
  278                                  */
  279                                 log(LOG_ERR, 
  280                                    "fore_cmd_drain: DACT failed, vcc=(%d,%d)\n",
  281                                         fvp->fv_connvc->cvc_vcc->vc_vpi,
  282                                         fvp->fv_connvc->cvc_vcc->vc_vci);
  283                                 fup->fu_pif.pif_cmderrors++;
  284                         } else {
  285                                 /*
  286                                  * Successful VCC dactivation - so what?
  287                                  */
  288                         }
  289                         break;
  290 
  291                 case CMD_GET_STATS:
  292                         if (*hcp->hcq_status & QSTAT_ERROR) {
  293                                 /*
  294                                  * Couldn't get stats
  295                                  */
  296                                 fup->fu_pif.pif_cmderrors++;
  297                                 fup->fu_stats_ret = EIO;
  298                         } else {
  299                                 /*
  300                                  * Stats are now in unit buffer
  301                                  */
  302                                 fup->fu_stats_ret = 0;
  303                         }
  304                         fup->fu_flags &= ~FUF_STATCMD;
  305 
  306                         /*
  307                          * Flush received stats data
  308                          */
  309 #ifdef VAC
  310                         if (vac)
  311                                 vac_pageflush((addr_t)fup->fu_stats);
  312 #endif
  313 
  314 #if BYTE_ORDER == LITTLE_ENDIAN
  315                         /*
  316                          * Little endian machines receives the stats in
  317                          * wrong byte order. Instead of swapping in user
  318                          * land, swap here so that everything going out
  319                          * of the kernel is in correct host order.
  320                          */
  321                         {
  322                                 u_long *bp = (u_long *)fup->fu_stats;
  323                                 int     loop;
  324 
  325                                 for ( loop = 0; loop < sizeof(Fore_cp_stats)/
  326                                     sizeof(long); loop++, bp++ )
  327                                         *bp = ntohl(*bp);
  328                         }
  329 #endif  /* BYTE_ORDER == LITTLE_ENDIAN */
  330 
  331                         /*
  332                          * Poke whoever is waiting on the stats
  333                          */
  334                         wakeup(&fup->fu_stats);
  335                         break;
  336 
  337                 case CMD_GET_PROM:
  338                         if (fup->fu_ft4)
  339                                 goto unknown;
  340                         goto prom;
  341 
  342                 case CMD_GET_PROM4:
  343                         if (!fup->fu_ft4)
  344                                 goto unknown;
  345                 prom:
  346                         if (*hcp->hcq_status & QSTAT_ERROR) {
  347                                 /*
  348                                  * Couldn't get PROM data
  349                                  */
  350                                 fup->fu_pif.pif_cmderrors++;
  351                                 log(LOG_ERR, 
  352                                     "fore_cmd_drain: %s%d: GET_PROM failed\n",
  353                                         fup->fu_pif.pif_name,
  354                                         fup->fu_pif.pif_unit);
  355                         } else {
  356                                 Fore_prom       *fp = fup->fu_prom;
  357 
  358                                 /*
  359                                  * Flush received PROM data
  360                                  */
  361 #ifdef VAC
  362                                 if (vac)
  363                                         vac_pageflush((addr_t)fp);
  364 #endif
  365                                 /*
  366                                  * Copy PROM info into config areas
  367                                  */
  368                                 bcopy(&fp->pr_mac[2],
  369                                         &fup->fu_pif.pif_macaddr,
  370                                         sizeof(struct mac_addr));
  371                                 fup->fu_config.ac_macaddr = 
  372                                         fup->fu_pif.pif_macaddr;
  373                                 snprintf(fup->fu_config.ac_hard_vers,
  374                                     sizeof(fup->fu_config.ac_hard_vers),
  375                                         "%ld.%ld.%ld",
  376                                         (fp->pr_hwver >> 16) & 0xff,
  377                                         (fp->pr_hwver >> 8) & 0xff,
  378                                         fp->pr_hwver & 0xff);
  379                                 fup->fu_config.ac_serial = fp->pr_serno;
  380                         }
  381                         break;
  382 
  383                 default:
  384                 unknown:
  385                         log(LOG_ERR, "fore_cmd_drain: unknown command %ld\n",
  386                                 hcp->hcq_code);
  387                 }
  388 
  389                 /*
  390                  * Mark this entry free for use and bump head pointer
  391                  * to the next entry in the queue
  392                  */
  393                 *hcp->hcq_status = QSTAT_FREE;
  394                 fup->fu_cmd_head = hcp->hcq_next;
  395         }
  396 
  397         return;
  398 }
  399 
  400 
  401 /*
  402  * Free Command Queue Data Structures
  403  *
  404  * Arguments:
  405  *      fup             pointer to device unit structure
  406  *
  407  * Returns:
  408  *      none
  409  */
  410 void
  411 fore_cmd_free(fup)
  412         Fore_unit       *fup;
  413 {
  414         H_cmd_queue     *hcp;
  415 
  416         /*
  417          * Deal with any commands left on the queue
  418          */
  419         if (fup->fu_flags & CUF_INITED) {
  420                 while (*fup->fu_cmd_head->hcq_status != QSTAT_FREE) {
  421                         hcp = fup->fu_cmd_head;
  422 
  423                         switch (hcp->hcq_code) {
  424 
  425                         case CMD_GET_STATS:
  426                                 /*
  427                                  * Just in case someone is sleeping on this
  428                                  */
  429                                 fup->fu_stats_ret = EIO;
  430                                 wakeup(&fup->fu_stats);
  431                                 break;
  432                         }
  433 
  434                         *hcp->hcq_status = QSTAT_FREE;
  435                         fup->fu_cmd_head = hcp->hcq_next;
  436                 }
  437         }
  438 
  439         /*
  440          * Free the statistics buffer
  441          */
  442         if (fup->fu_stats) {
  443                 atm_dev_free(fup->fu_stats);
  444                 fup->fu_stats = NULL;
  445         }
  446 
  447         /*
  448          * Free the PROM buffer
  449          */
  450         if (fup->fu_prom) {
  451                 atm_dev_free(fup->fu_prom);
  452                 fup->fu_prom = NULL;
  453         }
  454 
  455         /*
  456          * Free the status words
  457          */
  458         if (fup->fu_cmd_stat) {
  459                 atm_dev_free((volatile void *)fup->fu_cmd_stat);
  460                 fup->fu_cmd_stat = NULL;
  461                 fup->fu_cmd_statd = 0;
  462         }
  463 
  464         return;
  465 }
  466 

Cache object: efb99a103b4f4b545dd895d9484e1f0f


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