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