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/dmover/swdmover.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 /*      $NetBSD: swdmover.c,v 1.7 2003/11/07 22:04:13 briggs Exp $      */
    2 
    3 /*
    4  * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
    5  * All rights reserved.
    6  *
    7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed for the NetBSD Project by
   20  *      Wasabi Systems, Inc.
   21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
   22  *    or promote products derived from this software without specific prior
   23  *    written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
   29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35  * POSSIBILITY OF SUCH DAMAGE.
   36  */
   37 
   38 /*
   39  * swdmover.c: Software back-end providing the dmover functions
   40  * mentioned in dmover(9).
   41  *
   42  * This module provides a fallback for cases where no hardware
   43  * data movers are present in a system, and also serves an an
   44  * example of how to write a dmover back-end.
   45  *
   46  * Note that even through the software dmover doesn't require
   47  * interrupts to be blocked, we block them anyway to demonstrate
   48  * the locking protocol.
   49  */
   50 
   51 #include <sys/cdefs.h>
   52 __KERNEL_RCSID(0, "$NetBSD: swdmover.c,v 1.7 2003/11/07 22:04:13 briggs Exp $");
   53 
   54 #include <sys/param.h>
   55 #include <sys/lock.h>
   56 #include <sys/kthread.h>
   57 #include <sys/systm.h>
   58 #include <sys/uio.h>
   59 
   60 #include <dev/dmover/dmovervar.h>
   61 
   62 struct swdmover_function {
   63         void    (*sdf_process)(struct dmover_request *);
   64 };
   65 
   66 static struct dmover_backend swdmover_backend;
   67 static struct proc *swdmover_proc;
   68 static int swdmover_cv;
   69 
   70 void    swdmoverattach(int);
   71 
   72 /*
   73  * swdmover_process:
   74  *
   75  *      Dmover back-end entry point.
   76  */
   77 static void
   78 swdmover_process(struct dmover_backend *dmb)
   79 {
   80         int s;
   81 
   82         /*
   83          * Just wake up the processing thread.  This will allow
   84          * requests to linger on the middle-end's queue so that
   85          * they can be cancelled, if need-be.
   86          */
   87         s = splbio();
   88         /* XXXLOCK */
   89         if (TAILQ_EMPTY(&dmb->dmb_pendreqs) == 0)
   90                 wakeup(&swdmover_cv);
   91         /* XXXUNLOCK */
   92         splx(s);
   93 }
   94 
   95 /*
   96  * swdmover_thread:
   97  *
   98  *      Request processing thread.
   99  */
  100 static void
  101 swdmover_thread(void *arg)
  102 {
  103         struct dmover_backend *dmb = arg;
  104         struct dmover_request *dreq;
  105         struct swdmover_function *sdf;
  106         int s;
  107 
  108         s = splbio();
  109         /* XXXLOCK */
  110 
  111         for (;;) {
  112                 dreq = TAILQ_FIRST(&dmb->dmb_pendreqs);
  113                 if (dreq == NULL) {
  114                         /* XXXUNLOCK */
  115                         (void) tsleep(&swdmover_cv, PRIBIO, "swdmvr", 0);
  116                         continue;
  117                 }
  118 
  119                 dmover_backend_remque(dmb, dreq);
  120                 dreq->dreq_flags |= DMOVER_REQ_RUNNING;
  121 
  122                 /* XXXUNLOCK */
  123                 splx(s);
  124 
  125                 sdf = dreq->dreq_assignment->das_algdesc->dad_data;
  126                 (*sdf->sdf_process)(dreq);
  127 
  128                 s = splbio();
  129                 /* XXXLOCK */
  130         }
  131 }
  132 
  133 /*
  134  * swdmover_func_zero_process:
  135  *
  136  *      Processing routine for the "zero" function.
  137  */
  138 static void
  139 swdmover_func_zero_process(struct dmover_request *dreq)
  140 {
  141 
  142         switch (dreq->dreq_outbuf_type) {
  143         case DMOVER_BUF_LINEAR:
  144                 memset(dreq->dreq_outbuf.dmbuf_linear.l_addr, 0,
  145                     dreq->dreq_outbuf.dmbuf_linear.l_len);
  146                 break;
  147 
  148         case DMOVER_BUF_UIO:
  149             {
  150                 struct uio *uio = dreq->dreq_outbuf.dmbuf_uio;
  151                 char *cp;
  152                 size_t count, buflen;
  153                 int error;
  154 
  155                 if (uio->uio_rw != UIO_READ) {
  156                         /* XXXLOCK */
  157                         dreq->dreq_error = EINVAL;
  158                         dreq->dreq_flags |= DMOVER_REQ_ERROR;
  159                         /* XXXUNLOCK */
  160                         break;
  161                 }
  162 
  163                 buflen = uio->uio_resid;
  164                 if (buflen > 1024)
  165                         buflen = 1024;
  166                 cp = alloca(buflen);
  167                 memset(cp, 0, buflen);
  168 
  169                 while ((count = uio->uio_resid) != 0) {
  170                         if (count > buflen)
  171                                 count = buflen;
  172                         error = uiomove(cp, count, uio);
  173                         if (error) {
  174                                 /* XXXLOCK */
  175                                 dreq->dreq_error = error;
  176                                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  177                                 /* XXXUNLOCK */
  178                                 break;
  179                         }
  180                 }
  181                 break;
  182             }
  183 
  184         default:
  185                 /* XXXLOCK */
  186                 dreq->dreq_error = EINVAL;
  187                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  188                 /* XXXUNLOCK */
  189         }
  190 
  191         dmover_done(dreq);
  192 }
  193 
  194 /*
  195  * swdmover_func_fill8_process:
  196  *
  197  *      Processing routine for the "fill8" function.
  198  */
  199 static void
  200 swdmover_func_fill8_process(struct dmover_request *dreq)
  201 {
  202 
  203         switch (dreq->dreq_outbuf_type) {
  204         case DMOVER_BUF_LINEAR:
  205                 memset(dreq->dreq_outbuf.dmbuf_linear.l_addr,
  206                     dreq->dreq_immediate[0],
  207                     dreq->dreq_outbuf.dmbuf_linear.l_len);
  208                 break;
  209 
  210         case DMOVER_BUF_UIO:
  211             {
  212                 struct uio *uio = dreq->dreq_outbuf.dmbuf_uio;
  213                 char *cp;
  214                 size_t count, buflen;
  215                 int error;
  216 
  217                 if (uio->uio_rw != UIO_READ) {
  218                         /* XXXLOCK */
  219                         dreq->dreq_error = EINVAL;
  220                         dreq->dreq_flags |= DMOVER_REQ_ERROR;
  221                         /* XXXUNLOCK */
  222                         break;
  223                 }
  224 
  225                 buflen = uio->uio_resid;
  226                 if (buflen > 1024)
  227                         buflen = 1024;
  228                 cp = alloca(buflen);
  229                 memset(cp, dreq->dreq_immediate[0], buflen);
  230 
  231                 while ((count = uio->uio_resid) != 0) {
  232                         if (count > buflen)
  233                                 count = buflen;
  234                         error = uiomove(cp, count, uio);
  235                         if (error) {
  236                                 /* XXXLOCK */
  237                                 dreq->dreq_error = error;
  238                                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  239                                 /* XXXUNLOCK */
  240                                 break;
  241                         }
  242                 }
  243                 break;
  244             }
  245 
  246         default:
  247                 /* XXXLOCK */
  248                 dreq->dreq_error = EINVAL;
  249                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  250                 /* XXXUNLOCK */
  251         }
  252 
  253         dmover_done(dreq);
  254 }
  255 
  256 static void
  257 xor2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int cnt)
  258 {
  259 
  260         while (cnt--)
  261                 *dst++ = *src1++ ^ *src2++;
  262 }
  263 
  264 /*
  265  * swdmover_func_xor_process:
  266  *
  267  *      Processing routine for the "xor" function.
  268  */
  269 static void
  270 swdmover_func_xor_process(struct dmover_request *dreq)
  271 {
  272 #define INBUF_L(x)      dreq->dreq_inbuf[(x)].dmbuf_linear
  273 #define OUTBUF_L        dreq->dreq_outbuf.dmbuf_linear
  274 
  275         uint32_t *dst32, *src32;
  276         uint8_t *dst8, *src8;
  277         int     i, ninputs = dreq->dreq_assignment->das_algdesc->dad_ninputs;
  278         int     aligned, len, nwords;
  279 
  280         /* XXX Currently, both buffers must be of same type. */
  281         if (dreq->dreq_inbuf_type != dreq->dreq_outbuf_type) {
  282                 /* XXXLOCK */
  283                 dreq->dreq_error = EINVAL;
  284                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  285                 /* XXXUNLOCK */
  286                 goto done;
  287         }
  288 
  289         switch (dreq->dreq_outbuf_type) {
  290         case DMOVER_BUF_LINEAR:
  291                 aligned = 1;
  292                 if ((ulong) OUTBUF_L.l_addr & 0x3)
  293                         aligned = 0;
  294                 len = OUTBUF_L.l_len;
  295                 for (i = 0 ; i < ninputs ; i++) {
  296                         if (len != INBUF_L(i).l_len) {
  297                                 /* XXXLOCK */
  298                                 dreq->dreq_error = EINVAL;
  299                                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  300                                 /* XXXUNLOCK */
  301                                 break;
  302                         }
  303                         if ((ulong) INBUF_L(i).l_addr & 0x3)
  304                                 aligned = 0;
  305                 }
  306                 if (aligned) {
  307                         dst32 = (uint32_t *) OUTBUF_L.l_addr;
  308                         nwords = len / 4;
  309                         while (nwords--) {
  310                                 *dst32 = 0;
  311                                 for (i = 0 ; i < ninputs ; i++) {
  312                                         src32 = (uint32_t *) INBUF_L(i).l_addr;
  313                                         *dst32 ^= *src32;
  314                                 }
  315                                 dst32++;
  316                                 len -= 4;
  317                         }
  318                 }
  319                 if (len) {
  320                         dst8 = (uint8_t *) OUTBUF_L.l_addr;
  321                         while (len--) {
  322                                 *dst8 = 0;
  323                                 for (i = 0 ; i < ninputs ; i++) {
  324                                         src8 = (uint8_t *) INBUF_L(i).l_addr;
  325                                         *dst8 ^= *src8;
  326                                 }
  327                                 dst8++;
  328                         }
  329                 }
  330                 
  331                 break;
  332 
  333         case DMOVER_BUF_UIO:
  334             {
  335                 struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio;
  336                 struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
  337                 struct uio *uio;
  338                 char *cp, *dst;
  339                 size_t count, buflen;
  340                 int error;
  341 
  342                 if (uio_in->uio_rw != UIO_WRITE ||
  343                     uio_out->uio_rw != UIO_READ ||
  344                     uio_in->uio_resid != uio_out->uio_resid) {
  345                         /* XXXLOCK */
  346                         dreq->dreq_error = EINVAL;
  347                         dreq->dreq_flags |= DMOVER_REQ_ERROR;
  348                         /* XXXUNLOCK */
  349                         break;
  350                 }
  351 
  352                 buflen = uio_in->uio_resid;
  353                 if (buflen > 1024)
  354                         buflen = 1024;
  355                 cp = alloca(buflen);
  356                 dst = alloca(buflen);
  357 
  358                 /*
  359                  * For each block, copy first input buffer into the destination
  360                  * buffer and then read the rest, one by one, into a temporary
  361                  * buffer and xor into the destination buffer.  After all of
  362                  * the inputs have been xor'd in, move the destination buffer
  363                  * out and loop.
  364                  */
  365                 while ((count = uio_in->uio_resid) != 0) {
  366                         if (count > buflen)
  367                                 count = buflen;
  368                         error = uiomove(dst, count, uio_in);
  369                         if (error) {
  370                                 /* XXXLOCK */
  371                                 dreq->dreq_error = error;
  372                                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  373                                 /* XXXUNLOCK */
  374                                 break;
  375                         }
  376                         for (i=1 ; (i < ninputs) && (error == 0) ; i++) {
  377                                 uio = dreq->dreq_inbuf[i].dmbuf_uio;
  378                                 error = uiomove(cp, count, uio);
  379                                 if (error == 0) {
  380                                         xor2(dst, dst, cp, count);
  381                                 }
  382                         }
  383                         if (error == 0) {
  384                                 error = uiomove(dst, count, uio_out);
  385                         } else {
  386                                 /* XXXLOCK */
  387                                 dreq->dreq_error = error;
  388                                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  389                                 /* XXXUNLOCK */
  390                                 break;
  391                         }
  392                 }
  393                 break;
  394             }
  395 
  396         default:
  397                 /* XXXLOCK */
  398                 dreq->dreq_error = EINVAL;
  399                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  400                 /* XXXUNLOCK */
  401         }
  402 
  403  done:
  404         dmover_done(dreq);
  405 }
  406 
  407 /*
  408  * swdmover_func_copy_process:
  409  *
  410  *      Processing routine for the "copy" function.
  411  */
  412 static void
  413 swdmover_func_copy_process(struct dmover_request *dreq)
  414 {
  415 
  416         /* XXX Currently, both buffers must be of same type. */
  417         if (dreq->dreq_inbuf_type != dreq->dreq_outbuf_type) {
  418                 /* XXXLOCK */
  419                 dreq->dreq_error = EINVAL;
  420                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  421                 /* XXXUNLOCK */
  422                 goto done;
  423         }
  424 
  425         switch (dreq->dreq_outbuf_type) {
  426         case DMOVER_BUF_LINEAR:
  427                 if (dreq->dreq_outbuf.dmbuf_linear.l_len !=
  428                     dreq->dreq_inbuf[0].dmbuf_linear.l_len) {
  429                         /* XXXLOCK */
  430                         dreq->dreq_error = EINVAL;
  431                         dreq->dreq_flags |= DMOVER_REQ_ERROR;
  432                         /* XXXUNLOCK */
  433                         break;
  434                 }
  435                 memcpy(dreq->dreq_outbuf.dmbuf_linear.l_addr,
  436                     dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
  437                     dreq->dreq_outbuf.dmbuf_linear.l_len);
  438                 break;
  439 
  440         case DMOVER_BUF_UIO:
  441             {
  442                 struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio;
  443                 struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
  444                 char *cp;
  445                 size_t count, buflen;
  446                 int error;
  447 
  448                 if (uio_in->uio_rw != UIO_WRITE ||
  449                     uio_out->uio_rw != UIO_READ ||
  450                     uio_in->uio_resid != uio_out->uio_resid) {
  451                         /* XXXLOCK */
  452                         dreq->dreq_error = EINVAL;
  453                         dreq->dreq_flags |= DMOVER_REQ_ERROR;
  454                         /* XXXUNLOCK */
  455                         break;
  456                 }
  457 
  458                 buflen = uio_in->uio_resid;
  459                 if (buflen > 1024)
  460                         buflen = 1024;
  461                 cp = alloca(buflen);
  462 
  463                 while ((count = uio_in->uio_resid) != 0) {
  464                         if (count > buflen)
  465                                 count = buflen;
  466                         error = uiomove(cp, count, uio_in);
  467                         if (error == 0)
  468                                 error = uiomove(cp, count, uio_out);
  469                         if (error) {
  470                                 /* XXXLOCK */
  471                                 dreq->dreq_error = error;
  472                                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  473                                 /* XXXUNLOCK */
  474                                 break;
  475                         }
  476                 }
  477                 break;
  478             }
  479 
  480         default:
  481                 /* XXXLOCK */
  482                 dreq->dreq_error = EINVAL;
  483                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  484                 /* XXXUNLOCK */
  485         }
  486 
  487  done:
  488         dmover_done(dreq);
  489 }
  490 
  491 static const uint32_t iscsi_crc32c_table[256] = {
  492         0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
  493         0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
  494         0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
  495         0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
  496         0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
  497         0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
  498         0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
  499         0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
  500         0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
  501         0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
  502         0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
  503         0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
  504         0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
  505         0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
  506         0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
  507         0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
  508         0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
  509         0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
  510         0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
  511         0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
  512         0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
  513         0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
  514         0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
  515         0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
  516         0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
  517         0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
  518         0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
  519         0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
  520         0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
  521         0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
  522         0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
  523         0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
  524         0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
  525         0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
  526         0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
  527         0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
  528         0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
  529         0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
  530         0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
  531         0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
  532         0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
  533         0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
  534         0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
  535         0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
  536         0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
  537         0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
  538         0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
  539         0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
  540         0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
  541         0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
  542         0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
  543         0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
  544         0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
  545         0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
  546         0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
  547         0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
  548         0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
  549         0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
  550         0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
  551         0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
  552         0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
  553         0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
  554         0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
  555         0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
  556 };
  557 
  558 static uint32_t
  559 iscsi_crc32c(const uint8_t *buf, size_t len, uint32_t last)
  560 {
  561         uint32_t crc = 0xffffffffU ^ last;
  562 
  563         while (len--)
  564                 crc = iscsi_crc32c_table[(crc ^ *buf++) & 0xff] ^ (crc >> 8);
  565 
  566         return (crc ^ 0xffffffffU);
  567 }
  568 
  569 /*
  570  * swdmover_func_iscsi_crc32c_process:
  571  *
  572  *      Processing routine for the "iscsi-crc32c" function.
  573  */
  574 static void
  575 swdmover_func_iscsi_crc32c_process(struct dmover_request *dreq)
  576 {
  577         uint32_t result;
  578 
  579         /* No output buffer; we use the immediate only. */
  580         if (dreq->dreq_outbuf_type != DMOVER_BUF_NONE) {
  581                 /* XXXLOCK */
  582                 dreq->dreq_error = EINVAL;
  583                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  584                 /* XXXUNLOCK */
  585                 goto done;
  586         }
  587 
  588         memcpy(&result, dreq->dreq_immediate, sizeof(result));
  589 
  590         switch (dreq->dreq_inbuf_type) {
  591         case DMOVER_BUF_LINEAR:
  592                 result = iscsi_crc32c(dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
  593                     dreq->dreq_inbuf[0].dmbuf_linear.l_len, result);
  594                 break;
  595 
  596         case DMOVER_BUF_UIO:
  597             {
  598                 struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
  599                 uint8_t *cp;
  600                 size_t count, buflen;
  601                 int error;
  602 
  603                 if (uio_in->uio_rw != UIO_WRITE) {
  604                         /* XXXLOCK */
  605                         dreq->dreq_error = EINVAL;
  606                         dreq->dreq_flags |= DMOVER_REQ_ERROR;
  607                         /* XXXUNLOCK */
  608                         goto done;
  609                 }
  610 
  611                 buflen = uio_in->uio_resid;
  612                 if (buflen > 1024)
  613                         buflen = 1024;
  614                 cp = alloca(buflen);
  615 
  616                 while ((count = uio_in->uio_resid) != 0) {
  617                         if (count > buflen)
  618                                 count = buflen;
  619                         error = uiomove(cp, count, uio_in);
  620                         if (error) {
  621                                 /* XXXLOCK */
  622                                 dreq->dreq_error = error;
  623                                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  624                                 /* XXXUNLOCK */
  625                                 goto done;
  626                         } else
  627                                 result = iscsi_crc32c(cp, count, result);
  628                 }
  629                 break;
  630             }
  631 
  632         default:
  633                 /* XXXLOCK */
  634                 dreq->dreq_error = EINVAL;
  635                 dreq->dreq_flags |= DMOVER_REQ_ERROR;
  636                 /* XXXUNLOCK */
  637                 goto done;
  638         }
  639 
  640         memcpy(dreq->dreq_immediate, &result, sizeof(result));
  641  done:
  642         dmover_done(dreq);
  643 }
  644 
  645 static struct swdmover_function swdmover_func_zero = {
  646         swdmover_func_zero_process
  647 };
  648 
  649 static struct swdmover_function swdmover_func_fill8 = {
  650         swdmover_func_fill8_process
  651 };
  652 
  653 static struct swdmover_function swdmover_func_copy = {
  654         swdmover_func_copy_process
  655 };
  656 
  657 static struct swdmover_function swdmover_func_xor = {
  658         swdmover_func_xor_process
  659 };
  660 
  661 static struct swdmover_function swdmover_func_iscsi_crc32c = {
  662         swdmover_func_iscsi_crc32c_process
  663 };
  664 
  665 const struct dmover_algdesc swdmover_algdescs[] = {
  666         {
  667           DMOVER_FUNC_XOR2,
  668           &swdmover_func_xor,
  669           2
  670         },
  671         {
  672           DMOVER_FUNC_XOR3,
  673           &swdmover_func_xor,
  674           3
  675         },
  676         {
  677           DMOVER_FUNC_XOR4,
  678           &swdmover_func_xor,
  679           4
  680         },
  681         {
  682           DMOVER_FUNC_XOR5,
  683           &swdmover_func_xor,
  684           5
  685         },
  686         {
  687           DMOVER_FUNC_XOR6,
  688           &swdmover_func_xor,
  689           6
  690         },
  691         {
  692           DMOVER_FUNC_XOR7,
  693           &swdmover_func_xor,
  694           7
  695         },
  696         {
  697           DMOVER_FUNC_XOR8,
  698           &swdmover_func_xor,
  699           8
  700         },
  701         {
  702           DMOVER_FUNC_ZERO,
  703           &swdmover_func_zero,
  704           0
  705         },
  706         {
  707           DMOVER_FUNC_FILL8,
  708           &swdmover_func_fill8,
  709           0
  710         },
  711         {
  712           DMOVER_FUNC_COPY,
  713           &swdmover_func_copy,
  714           1
  715         },
  716         {
  717           DMOVER_FUNC_ISCSI_CRC32C,
  718           &swdmover_func_iscsi_crc32c,
  719           1,
  720         },
  721 };
  722 #define SWDMOVER_ALGDESC_COUNT \
  723         (sizeof(swdmover_algdescs) / sizeof(swdmover_algdescs[0]))
  724 
  725 /*
  726  * swdmover_create_thread:
  727  *
  728  *      Actually create the swdmover processing thread.
  729  */
  730 static void
  731 swdmover_create_thread(void *arg)
  732 {
  733         int error;
  734 
  735         error = kthread_create1(swdmover_thread, arg, &swdmover_proc,
  736             "swdmover");
  737         if (error)
  738                 printf("WARNING: unable to create swdmover thread, "
  739                     "error = %d\n", error);
  740 }
  741 
  742 /*
  743  * swdmoverattach:
  744  *
  745  *      Pesudo-device attach routine.
  746  */
  747 void
  748 swdmoverattach(int count)
  749 {
  750 
  751         swdmover_backend.dmb_name = "swdmover";
  752         swdmover_backend.dmb_speed = 1;         /* XXX */
  753         swdmover_backend.dmb_cookie = NULL;
  754         swdmover_backend.dmb_algdescs = swdmover_algdescs;
  755         swdmover_backend.dmb_nalgdescs = SWDMOVER_ALGDESC_COUNT;
  756         swdmover_backend.dmb_process = swdmover_process;
  757 
  758         kthread_create(swdmover_create_thread, &swdmover_backend);
  759 
  760         /* XXX Should only register this when kthread creation succeeds. */
  761         dmover_backend_register(&swdmover_backend);
  762 }

Cache object: 160637ab0d0cdbbaae3cc4c8d6aeb74a


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