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
|