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