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/ppbus/ppb_msq.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) 1998 Nicolas Souchu
    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  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  *
   28  */
   29 #include <machine/stdarg.h>
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 
   35 #include <dev/ppbus/ppbconf.h>
   36 #include <dev/ppbus/ppb_msq.h>
   37 
   38 /* msq index (see PPB_MAX_XFER)
   39  * These are device modes
   40  */
   41 #define COMPAT_MSQ      0x0
   42 #define NIBBLE_MSQ      0x1
   43 #define PS2_MSQ         0x2
   44 #define EPP17_MSQ       0x3
   45 #define EPP19_MSQ       0x4
   46 #define ECP_MSQ         0x5
   47 
   48 /*
   49  * Device mode to submsq conversion
   50  */
   51 static struct ppb_xfer *
   52 mode2xfer(struct ppb_device *dev, int opcode)
   53 {
   54         int index, epp;
   55         struct ppb_xfer *table;
   56 
   57         switch (opcode) {
   58         case MS_OP_GET:
   59                 table = dev->get_xfer;
   60                 break;
   61 
   62         case MS_OP_PUT:
   63                 table = dev->put_xfer;
   64                 break;
   65 
   66         default:
   67                 panic("%s: unknown opcode (%d)", __FUNCTION__, opcode);
   68         }
   69 
   70         /* retrieve the device operating mode */
   71         switch (ppb_get_mode(dev)) {
   72         case PPB_COMPATIBLE:
   73                 index = COMPAT_MSQ;
   74                 break;
   75         case PPB_NIBBLE:
   76                 index = NIBBLE_MSQ;
   77                 break;
   78         case PPB_PS2:
   79                 index = PS2_MSQ;
   80                 break;
   81         case PPB_EPP:
   82                 switch ((epp = ppb_get_epp_protocol(dev))) {
   83                 case EPP_1_7:
   84                         index = EPP17_MSQ;
   85                         break;
   86                 case EPP_1_9:
   87                         index = EPP19_MSQ;
   88                         break;
   89                 default:
   90                         panic("%s: unknown EPP protocol (0x%x)!", __FUNCTION__,
   91                                 epp);
   92                 }
   93                 break;
   94         case PPB_ECP:
   95                 index = ECP_MSQ;
   96                 break;
   97         default:
   98                 panic("%s: unknown mode (%d)", __FUNCTION__, dev->mode);
   99         }
  100 
  101         return (&table[index]);
  102 }
  103 
  104 /*
  105  * ppb_MS_init()
  106  *
  107  * Initialize device dependent submicrosequence of the current mode
  108  *
  109  */
  110 int
  111 ppb_MS_init(struct ppb_device *dev, struct ppb_microseq *loop, int opcode)
  112 {
  113         struct ppb_xfer *xfer = mode2xfer(dev, opcode);
  114 
  115         xfer->loop = loop;
  116 
  117         return (0);
  118 }
  119 
  120 /*
  121  * ppb_MS_exec()
  122  *
  123  * Execute any microsequence opcode - expensive
  124  *
  125  */
  126 int
  127 ppb_MS_exec(struct ppb_device *dev, int opcode, union ppb_insarg param1,
  128                 union ppb_insarg param2, union ppb_insarg param3, int *ret)
  129 {
  130         struct ppb_microseq msq[] = {
  131                   { MS_UNKNOWN, { MS_UNKNOWN, MS_UNKNOWN, MS_UNKNOWN } },
  132                   MS_RET(0)
  133         };
  134 
  135         /* initialize the corresponding microseq */
  136         msq[0].opcode = opcode;
  137         msq[0].arg[0] = param1;
  138         msq[0].arg[1] = param2;
  139         msq[0].arg[2] = param3;
  140 
  141         /* execute the microseq */
  142         return (ppb_MS_microseq(dev, msq, ret));
  143 }
  144 
  145 /*
  146  * ppb_MS_loop()
  147  *
  148  * Execute a microseq loop
  149  *
  150  */
  151 int
  152 ppb_MS_loop(struct ppb_device *dev, struct ppb_microseq *prolog,
  153                 struct ppb_microseq *body, struct ppb_microseq *epilog,
  154                 int iter, int *ret)
  155 {
  156         struct ppb_microseq loop_microseq[] = {
  157                   MS_CALL(NULL),                /* execute prolog */
  158 
  159                   MS_SET(MS_UNKNOWN),           /* set size of transfer */
  160         /* loop: */
  161                   MS_CALL(NULL),                /* execute body */
  162                   MS_DBRA(-1 /* loop: */),
  163 
  164                   MS_CALL(NULL),                /* execute epilog */
  165                   MS_RET(0)
  166         };
  167 
  168         /* initialize the structure */
  169         loop_microseq[0].arg[0].p = (void *)prolog;
  170         loop_microseq[1].arg[0].i = iter;
  171         loop_microseq[2].arg[0].p = (void *)body;
  172         loop_microseq[4].arg[0].p = (void *)epilog;
  173 
  174         /* execute the loop */
  175         return (ppb_MS_microseq(dev, loop_microseq, ret));
  176 }
  177 
  178 /*
  179  * ppb_MS_init_msq()
  180  *
  181  * Initialize a microsequence - see macros in ppb_msq.h
  182  *
  183  */
  184 int
  185 ppb_MS_init_msq(struct ppb_microseq *msq, int nbparam, ...)
  186 {
  187         int i;
  188         int param, ins, arg, type;
  189         va_list p_list = 0;
  190 
  191         va_start(p_list, nbparam);
  192 
  193         for (i=0; i<nbparam; i++) {
  194                 /* retrieve the parameter descriptor */
  195                 param = va_arg(p_list, int);
  196 
  197                 ins  = MS_INS(param);
  198                 arg  = MS_ARG(param);
  199                 type = MS_TYP(param);
  200 
  201                 /* check the instruction position */
  202                 if (arg >= PPB_MS_MAXARGS)
  203                         panic("%s: parameter out of range (0x%x)!",
  204                                 __FUNCTION__, param);
  205 
  206 #if 0
  207                 printf("%s: param = %d, ins = %d, arg = %d, type = %d\n", 
  208                         __FUNCTION__, param, ins, arg, type);
  209 #endif
  210 
  211                 /* properly cast the parameter */
  212                 switch (type) {
  213                 case MS_TYP_INT:
  214                         msq[ins].arg[arg].i = va_arg(p_list, int);
  215                         break;
  216 
  217                 case MS_TYP_CHA:
  218                         msq[ins].arg[arg].i = (int)va_arg(p_list, char);
  219                         break;
  220 
  221                 case MS_TYP_PTR:
  222                         msq[ins].arg[arg].p = va_arg(p_list, void *);
  223                         break;
  224 
  225                 case MS_TYP_FUN:
  226                         msq[ins].arg[arg].f = va_arg(p_list, void *);
  227                         break;
  228 
  229                 default:
  230                         panic("%s: unknown parameter (0x%x)!", __FUNCTION__,
  231                                 param);
  232                 }
  233         }
  234 
  235         return (0);
  236 }
  237 
  238 /*
  239  * ppb_MS_microseq()
  240  *
  241  * Interprete a microsequence. Some microinstructions are executed at adapter
  242  * level to avoid function call overhead between ppbus and the adapter
  243  */
  244 int
  245 ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret)
  246 {
  247         struct ppb_data *ppb = dev->ppb;
  248         struct ppb_microseq *mi;                /* current microinstruction */
  249         int error;
  250 
  251         struct ppb_xfer *xfer;
  252 
  253         /* microsequence executed to initialize the transfer */
  254         struct ppb_microseq initxfer[] = {
  255                 MS_PTR(MS_UNKNOWN),     /* set ptr to buffer */
  256                 MS_SET(MS_UNKNOWN),     /* set transfer size */
  257                 MS_RET(0)
  258         };
  259 
  260         if (ppb->ppb_owner != dev)
  261                 return (EACCES);
  262 
  263 #define INCR_PC (mi ++)
  264 
  265         mi = msq;
  266         for (;;) {
  267                 switch (mi->opcode) {                                           
  268                 case MS_OP_PUT:
  269                 case MS_OP_GET:
  270 
  271                         /* attempt to choose the best mode for the device */
  272                         xfer = mode2xfer(dev, mi->opcode);
  273 
  274                         /* figure out if we should use ieee1284 code */
  275                         if (!xfer->loop) {
  276                                 if (mi->opcode == MS_OP_PUT) {
  277                                         if ((error = ppb->ppb_link->adapter->write(
  278                                                 ppb->ppb_link->adapter_unit,
  279                                                 (char *)mi->arg[0].p,
  280                                                 mi->arg[1].i, 0)))
  281                                                         goto error;
  282 
  283                                         INCR_PC;
  284                                         goto next;
  285                                 } else
  286                                         panic("%s: IEEE1284 read not supported", __FUNCTION__);
  287                         }
  288 
  289                         /* XXX should use ppb_MS_init_msq() */
  290                         initxfer[0].arg[0].p = mi->arg[0].p;
  291                         initxfer[1].arg[0].i = mi->arg[1].i;
  292 
  293                         /* initialize transfer */
  294                         ppb_MS_microseq(dev, initxfer, &error);
  295 
  296                         if (error)
  297                                 goto error;
  298 
  299                         /* the xfer microsequence should not contain any
  300                          * MS_OP_PUT or MS_OP_GET!
  301                          */
  302                         ppb_MS_microseq(dev, xfer->loop, &error);
  303 
  304                         if (error)
  305                                 goto error;
  306 
  307                         INCR_PC;
  308                         break;
  309 
  310                 case MS_OP_RET:
  311                         if (ret)
  312                                 *ret = mi->arg[0].i;    /* return code */
  313                         return (0);
  314                         break;
  315 
  316                 default:
  317                         /* executing microinstructions at ppc level is
  318                          * faster. This is the default if the microinstr
  319                          * is unknown here
  320                          */
  321                         if ((error = ppb->ppb_link->adapter->exec_microseq(
  322                                                 ppb->ppb_link->adapter_unit,
  323                                                 &mi)))
  324                                 goto error;
  325                         break;
  326                 }
  327         next:
  328         }
  329 error:
  330         return (error);
  331 }
  332 

Cache object: 6b16d1af35f81281aa207f5bf54e7a54


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