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

Cache object: 297a902095a71ce84002d060feac84fd


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