swdmover.c revision 1.9.30.2 1 /* $NetBSD: swdmover.c,v 1.9.30.2 2007/07/15 13:21:10 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.9.30.2 2007/07/15 13:21:10 ad 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 lwp *swdmover_lwp;
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 int error;
416
417 /* XXX Currently, both buffers must be of same type. */
418 if (dreq->dreq_inbuf_type != dreq->dreq_outbuf_type) {
419 /* XXXLOCK */
420 dreq->dreq_error = EINVAL;
421 dreq->dreq_flags |= DMOVER_REQ_ERROR;
422 /* XXXUNLOCK */
423 goto done;
424 }
425
426 switch (dreq->dreq_outbuf_type) {
427 case DMOVER_BUF_LINEAR:
428 if (dreq->dreq_outbuf.dmbuf_linear.l_len !=
429 dreq->dreq_inbuf[0].dmbuf_linear.l_len) {
430 /* XXXLOCK */
431 dreq->dreq_error = EINVAL;
432 dreq->dreq_flags |= DMOVER_REQ_ERROR;
433 /* XXXUNLOCK */
434 break;
435 }
436 memcpy(dreq->dreq_outbuf.dmbuf_linear.l_addr,
437 dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
438 dreq->dreq_outbuf.dmbuf_linear.l_len);
439 break;
440
441 case DMOVER_BUF_UIO:
442 {
443 struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio;
444 struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
445 char *cp;
446 size_t count, buflen;
447 int error;
448
449 if (uio_in->uio_rw != UIO_WRITE ||
450 uio_out->uio_rw != UIO_READ ||
451 uio_in->uio_resid != uio_out->uio_resid) {
452 /* XXXLOCK */
453 dreq->dreq_error = EINVAL;
454 dreq->dreq_flags |= DMOVER_REQ_ERROR;
455 /* XXXUNLOCK */
456 break;
457 }
458
459 buflen = uio_in->uio_resid;
460 if (buflen > 1024)
461 buflen = 1024;
462 cp = alloca(buflen);
463
464 while ((count = uio_in->uio_resid) != 0) {
465 if (count > buflen)
466 count = buflen;
467 error = uiomove(cp, count, uio_in);
468 if (error == 0)
469 error = uiomove(cp, count, uio_out);
470 if (error) {
471 /* XXXLOCK */
472 dreq->dreq_error = error;
473 dreq->dreq_flags |= DMOVER_REQ_ERROR;
474 /* XXXUNLOCK */
475 break;
476 }
477 }
478 break;
479 }
480
481 default:
482 /* XXXLOCK */
483 dreq->dreq_error = EINVAL;
484 dreq->dreq_flags |= DMOVER_REQ_ERROR;
485 /* XXXUNLOCK */
486 }
487
488 done:
489 dmover_done(dreq);
490 }
491
492 static const uint32_t iscsi_crc32c_table[256] = {
493 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
494 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
495 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
496 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
497 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
498 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
499 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
500 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
501 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
502 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
503 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
504 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
505 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
506 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
507 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
508 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
509 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
510 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
511 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
512 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
513 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
514 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
515 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
516 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
517 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
518 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
519 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
520 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
521 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
522 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
523 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
524 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
525 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
526 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
527 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
528 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
529 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
530 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
531 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
532 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
533 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
534 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
535 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
536 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
537 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
538 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
539 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
540 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
541 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
542 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
543 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
544 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
545 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
546 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
547 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
548 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
549 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
550 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
551 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
552 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
553 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
554 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
555 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
556 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
557 };
558
559 static uint32_t
560 iscsi_crc32c(const uint8_t *buf, size_t len, uint32_t last)
561 {
562 uint32_t crc = 0xffffffffU ^ last;
563
564 while (len--)
565 crc = iscsi_crc32c_table[(crc ^ *buf++) & 0xff] ^ (crc >> 8);
566
567 return (crc ^ 0xffffffffU);
568 }
569
570 /*
571 * swdmover_func_iscsi_crc32c_process:
572 *
573 * Processing routine for the "iscsi-crc32c" function.
574 */
575 static void
576 swdmover_func_iscsi_crc32c_process(struct dmover_request *dreq)
577 {
578 uint32_t result;
579
580 /* No output buffer; we use the immediate only. */
581 if (dreq->dreq_outbuf_type != DMOVER_BUF_NONE) {
582 /* XXXLOCK */
583 dreq->dreq_error = EINVAL;
584 dreq->dreq_flags |= DMOVER_REQ_ERROR;
585 /* XXXUNLOCK */
586 goto done;
587 }
588
589 memcpy(&result, dreq->dreq_immediate, sizeof(result));
590
591 switch (dreq->dreq_inbuf_type) {
592 case DMOVER_BUF_LINEAR:
593 result = iscsi_crc32c(dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
594 dreq->dreq_inbuf[0].dmbuf_linear.l_len, result);
595 break;
596
597 case DMOVER_BUF_UIO:
598 {
599 struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
600 uint8_t *cp;
601 size_t count, buflen;
602 int error;
603
604 if (uio_in->uio_rw != UIO_WRITE) {
605 /* XXXLOCK */
606 dreq->dreq_error = EINVAL;
607 dreq->dreq_flags |= DMOVER_REQ_ERROR;
608 /* XXXUNLOCK */
609 goto done;
610 }
611
612 buflen = uio_in->uio_resid;
613 if (buflen > 1024)
614 buflen = 1024;
615 cp = alloca(buflen);
616
617 while ((count = uio_in->uio_resid) != 0) {
618 if (count > buflen)
619 count = buflen;
620 error = uiomove(cp, count, uio_in);
621 if (error) {
622 /* XXXLOCK */
623 dreq->dreq_error = error;
624 dreq->dreq_flags |= DMOVER_REQ_ERROR;
625 /* XXXUNLOCK */
626 goto done;
627 } else
628 result = iscsi_crc32c(cp, count, result);
629 }
630 break;
631 }
632
633 default:
634 /* XXXLOCK */
635 dreq->dreq_error = EINVAL;
636 dreq->dreq_flags |= DMOVER_REQ_ERROR;
637 /* XXXUNLOCK */
638 goto done;
639 }
640
641 memcpy(dreq->dreq_immediate, &result, sizeof(result));
642 done:
643 dmover_done(dreq);
644 }
645
646 static struct swdmover_function swdmover_func_zero = {
647 swdmover_func_zero_process
648 };
649
650 static struct swdmover_function swdmover_func_fill8 = {
651 swdmover_func_fill8_process
652 };
653
654 static struct swdmover_function swdmover_func_copy = {
655 swdmover_func_copy_process
656 };
657
658 static struct swdmover_function swdmover_func_xor = {
659 swdmover_func_xor_process
660 };
661
662 static struct swdmover_function swdmover_func_iscsi_crc32c = {
663 swdmover_func_iscsi_crc32c_process
664 };
665
666 const struct dmover_algdesc swdmover_algdescs[] = {
667 {
668 DMOVER_FUNC_XOR2,
669 &swdmover_func_xor,
670 2
671 },
672 {
673 DMOVER_FUNC_XOR3,
674 &swdmover_func_xor,
675 3
676 },
677 {
678 DMOVER_FUNC_XOR4,
679 &swdmover_func_xor,
680 4
681 },
682 {
683 DMOVER_FUNC_XOR5,
684 &swdmover_func_xor,
685 5
686 },
687 {
688 DMOVER_FUNC_XOR6,
689 &swdmover_func_xor,
690 6
691 },
692 {
693 DMOVER_FUNC_XOR7,
694 &swdmover_func_xor,
695 7
696 },
697 {
698 DMOVER_FUNC_XOR8,
699 &swdmover_func_xor,
700 8
701 },
702 {
703 DMOVER_FUNC_ZERO,
704 &swdmover_func_zero,
705 0
706 },
707 {
708 DMOVER_FUNC_FILL8,
709 &swdmover_func_fill8,
710 0
711 },
712 {
713 DMOVER_FUNC_COPY,
714 &swdmover_func_copy,
715 1
716 },
717 {
718 DMOVER_FUNC_ISCSI_CRC32C,
719 &swdmover_func_iscsi_crc32c,
720 1,
721 },
722 };
723 #define SWDMOVER_ALGDESC_COUNT \
724 (sizeof(swdmover_algdescs) / sizeof(swdmover_algdescs[0]))
725
726 /*
727 * swdmoverattach:
728 *
729 * Pesudo-device attach routine.
730 */
731 void
732 swdmoverattach(int count)
733 {
734 int error;
735
736 swdmover_backend.dmb_name = "swdmover";
737 swdmover_backend.dmb_speed = 1; /* XXX */
738 swdmover_backend.dmb_cookie = NULL;
739 swdmover_backend.dmb_algdescs = swdmover_algdescs;
740 swdmover_backend.dmb_nalgdescs = SWDMOVER_ALGDESC_COUNT;
741 swdmover_backend.dmb_process = swdmover_process;
742
743 error = kthread_create(PRI_NONE, 0, NULL, swdmover_thread,
744 arg, &swdmover_proc, "swdmover");
745 if (error)
746 printf("WARNING: unable to create swdmover thread, "
747 "error = %d\n", error);
748
749 /* XXX Should only register this when kthread creation succeeds. */
750 dmover_backend_register(&swdmover_backend);
751 }
752