swdmover.c revision 1.6
1/* $NetBSD: swdmover.c,v 1.6 2003/07/25 13:59:09 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.6 2003/07/25 13:59:09 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 62struct swdmover_function { 63 void (*sdf_process)(struct dmover_request *); 64}; 65 66static struct dmover_backend swdmover_backend; 67static struct proc *swdmover_proc; 68static int swdmover_cv; 69 70void swdmoverattach(int); 71 72/* 73 * swdmover_process: 74 * 75 * Dmover back-end entry point. 76 */ 77static void 78swdmover_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 */ 100static void 101swdmover_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 */ 138static void 139swdmover_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 */ 199static void 200swdmover_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 256static void 257xor2(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 */ 269static void 270swdmover_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 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 len = OUTBUF_L.l_len; 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 */ 412static void 413swdmover_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 491static 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 558static uint32_t 559iscsi_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 */ 574static void 575swdmover_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 645static struct swdmover_function swdmover_func_zero = { 646 swdmover_func_zero_process 647}; 648 649static struct swdmover_function swdmover_func_fill8 = { 650 swdmover_func_fill8_process 651}; 652 653static struct swdmover_function swdmover_func_copy = { 654 swdmover_func_copy_process 655}; 656 657static struct swdmover_function swdmover_func_xor = { 658 swdmover_func_xor_process 659}; 660 661static struct swdmover_function swdmover_func_iscsi_crc32c = { 662 swdmover_func_iscsi_crc32c_process 663}; 664 665const 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 */ 730static void 731swdmover_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 */ 747void 748swdmoverattach(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} 763