swdmover.c revision 1.5 1 1.5 thorpej /* $NetBSD: swdmover.c,v 1.5 2003/07/19 02:05:35 thorpej 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.5 thorpej __KERNEL_RCSID(0, "$NetBSD: swdmover.c,v 1.5 2003/07/19 02:05:35 thorpej 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.1 thorpej /*
257 1.1 thorpej * swdmover_func_copy_process:
258 1.1 thorpej *
259 1.1 thorpej * Processing routine for the "copy" function.
260 1.1 thorpej */
261 1.1 thorpej static void
262 1.1 thorpej swdmover_func_copy_process(struct dmover_request *dreq)
263 1.1 thorpej {
264 1.1 thorpej
265 1.4 thorpej /* XXX Currently, both buffers must be of same type. */
266 1.4 thorpej if (dreq->dreq_inbuf_type != dreq->dreq_outbuf_type) {
267 1.4 thorpej /* XXXLOCK */
268 1.4 thorpej dreq->dreq_error = EINVAL;
269 1.4 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
270 1.4 thorpej /* XXXUNLOCK */
271 1.4 thorpej goto done;
272 1.4 thorpej }
273 1.4 thorpej
274 1.1 thorpej switch (dreq->dreq_outbuf_type) {
275 1.1 thorpej case DMOVER_BUF_LINEAR:
276 1.1 thorpej if (dreq->dreq_outbuf.dmbuf_linear.l_len !=
277 1.1 thorpej dreq->dreq_inbuf[0].dmbuf_linear.l_len) {
278 1.1 thorpej /* XXXLOCK */
279 1.1 thorpej dreq->dreq_error = EINVAL;
280 1.1 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
281 1.1 thorpej /* XXXUNLOCK */
282 1.1 thorpej break;
283 1.1 thorpej }
284 1.1 thorpej memcpy(dreq->dreq_outbuf.dmbuf_linear.l_addr,
285 1.1 thorpej dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
286 1.1 thorpej dreq->dreq_outbuf.dmbuf_linear.l_len);
287 1.1 thorpej break;
288 1.1 thorpej
289 1.1 thorpej case DMOVER_BUF_UIO:
290 1.1 thorpej {
291 1.1 thorpej struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio;
292 1.1 thorpej struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
293 1.1 thorpej char *cp;
294 1.1 thorpej size_t count, buflen;
295 1.1 thorpej int error;
296 1.1 thorpej
297 1.1 thorpej if (uio_in->uio_rw != UIO_WRITE ||
298 1.1 thorpej uio_out->uio_rw != UIO_READ ||
299 1.1 thorpej uio_in->uio_resid != uio_out->uio_resid) {
300 1.1 thorpej /* XXXLOCK */
301 1.1 thorpej dreq->dreq_error = EINVAL;
302 1.1 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
303 1.1 thorpej /* XXXUNLOCK */
304 1.1 thorpej break;
305 1.1 thorpej }
306 1.1 thorpej
307 1.1 thorpej buflen = uio_in->uio_resid;
308 1.1 thorpej if (buflen > 1024)
309 1.1 thorpej buflen = 1024;
310 1.1 thorpej cp = alloca(buflen);
311 1.1 thorpej
312 1.1 thorpej while ((count = uio_in->uio_resid) != 0) {
313 1.1 thorpej if (count > buflen)
314 1.1 thorpej count = buflen;
315 1.1 thorpej error = uiomove(cp, count, uio_in);
316 1.1 thorpej if (error == 0)
317 1.1 thorpej error = uiomove(cp, count, uio_out);
318 1.1 thorpej if (error) {
319 1.1 thorpej /* XXXLOCK */
320 1.1 thorpej dreq->dreq_error = error;
321 1.1 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
322 1.1 thorpej /* XXXUNLOCK */
323 1.1 thorpej break;
324 1.1 thorpej }
325 1.1 thorpej }
326 1.1 thorpej break;
327 1.1 thorpej }
328 1.3 thorpej
329 1.3 thorpej default:
330 1.3 thorpej /* XXXLOCK */
331 1.3 thorpej dreq->dreq_error = EINVAL;
332 1.3 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
333 1.3 thorpej /* XXXUNLOCK */
334 1.1 thorpej }
335 1.1 thorpej
336 1.4 thorpej done:
337 1.1 thorpej dmover_done(dreq);
338 1.1 thorpej }
339 1.1 thorpej
340 1.5 thorpej static const uint32_t iscsi_crc32c_table[256] = {
341 1.5 thorpej 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
342 1.5 thorpej 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
343 1.5 thorpej 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
344 1.5 thorpej 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
345 1.5 thorpej 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
346 1.5 thorpej 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
347 1.5 thorpej 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
348 1.5 thorpej 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
349 1.5 thorpej 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
350 1.5 thorpej 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
351 1.5 thorpej 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
352 1.5 thorpej 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
353 1.5 thorpej 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
354 1.5 thorpej 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
355 1.5 thorpej 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
356 1.5 thorpej 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
357 1.5 thorpej 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
358 1.5 thorpej 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
359 1.5 thorpej 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
360 1.5 thorpej 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
361 1.5 thorpej 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
362 1.5 thorpej 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
363 1.5 thorpej 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
364 1.5 thorpej 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
365 1.5 thorpej 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
366 1.5 thorpej 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
367 1.5 thorpej 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
368 1.5 thorpej 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
369 1.5 thorpej 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
370 1.5 thorpej 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
371 1.5 thorpej 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
372 1.5 thorpej 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
373 1.5 thorpej 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
374 1.5 thorpej 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
375 1.5 thorpej 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
376 1.5 thorpej 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
377 1.5 thorpej 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
378 1.5 thorpej 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
379 1.5 thorpej 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
380 1.5 thorpej 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
381 1.5 thorpej 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
382 1.5 thorpej 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
383 1.5 thorpej 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
384 1.5 thorpej 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
385 1.5 thorpej 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
386 1.5 thorpej 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
387 1.5 thorpej 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
388 1.5 thorpej 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
389 1.5 thorpej 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
390 1.5 thorpej 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
391 1.5 thorpej 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
392 1.5 thorpej 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
393 1.5 thorpej 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
394 1.5 thorpej 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
395 1.5 thorpej 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
396 1.5 thorpej 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
397 1.5 thorpej 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
398 1.5 thorpej 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
399 1.5 thorpej 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
400 1.5 thorpej 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
401 1.5 thorpej 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
402 1.5 thorpej 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
403 1.5 thorpej 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
404 1.5 thorpej 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
405 1.5 thorpej };
406 1.5 thorpej
407 1.5 thorpej static uint32_t
408 1.5 thorpej iscsi_crc32c(const uint8_t *buf, size_t len, uint32_t last)
409 1.5 thorpej {
410 1.5 thorpej uint32_t crc = 0xffffffffU ^ last;
411 1.5 thorpej
412 1.5 thorpej while (len--)
413 1.5 thorpej crc = iscsi_crc32c_table[(crc ^ *buf++) & 0xff] ^ (crc >> 8);
414 1.5 thorpej
415 1.5 thorpej return (crc ^ 0xffffffffU);
416 1.5 thorpej }
417 1.5 thorpej
418 1.5 thorpej /*
419 1.5 thorpej * swdmover_func_iscsi_crc32c_process:
420 1.5 thorpej *
421 1.5 thorpej * Processing routine for the "iscsi-crc32c" function.
422 1.5 thorpej */
423 1.5 thorpej static void
424 1.5 thorpej swdmover_func_iscsi_crc32c_process(struct dmover_request *dreq)
425 1.5 thorpej {
426 1.5 thorpej uint32_t result;
427 1.5 thorpej
428 1.5 thorpej /* No output buffer; we use the immediate only. */
429 1.5 thorpej if (dreq->dreq_outbuf_type != DMOVER_BUF_NONE) {
430 1.5 thorpej /* XXXLOCK */
431 1.5 thorpej dreq->dreq_error = EINVAL;
432 1.5 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
433 1.5 thorpej /* XXXUNLOCK */
434 1.5 thorpej goto done;
435 1.5 thorpej }
436 1.5 thorpej
437 1.5 thorpej memcpy(&result, dreq->dreq_immediate, sizeof(result));
438 1.5 thorpej
439 1.5 thorpej switch (dreq->dreq_inbuf_type) {
440 1.5 thorpej case DMOVER_BUF_LINEAR:
441 1.5 thorpej result = iscsi_crc32c(dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
442 1.5 thorpej dreq->dreq_inbuf[0].dmbuf_linear.l_len, result);
443 1.5 thorpej break;
444 1.5 thorpej
445 1.5 thorpej case DMOVER_BUF_UIO:
446 1.5 thorpej {
447 1.5 thorpej struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
448 1.5 thorpej uint8_t *cp;
449 1.5 thorpej size_t count, buflen;
450 1.5 thorpej int error;
451 1.5 thorpej
452 1.5 thorpej if (uio_in->uio_rw != UIO_WRITE) {
453 1.5 thorpej /* XXXLOCK */
454 1.5 thorpej dreq->dreq_error = EINVAL;
455 1.5 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
456 1.5 thorpej /* XXXUNLOCK */
457 1.5 thorpej goto done;
458 1.5 thorpej }
459 1.5 thorpej
460 1.5 thorpej buflen = uio_in->uio_resid;
461 1.5 thorpej if (buflen > 1024)
462 1.5 thorpej buflen = 1024;
463 1.5 thorpej cp = alloca(buflen);
464 1.5 thorpej
465 1.5 thorpej while ((count = uio_in->uio_resid) != 0) {
466 1.5 thorpej if (count > buflen)
467 1.5 thorpej count = buflen;
468 1.5 thorpej error = uiomove(cp, count, uio_in);
469 1.5 thorpej if (error) {
470 1.5 thorpej /* XXXLOCK */
471 1.5 thorpej dreq->dreq_error = error;
472 1.5 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
473 1.5 thorpej /* XXXUNLOCK */
474 1.5 thorpej goto done;
475 1.5 thorpej } else
476 1.5 thorpej result = iscsi_crc32c(cp, count, result);
477 1.5 thorpej }
478 1.5 thorpej break;
479 1.5 thorpej }
480 1.5 thorpej
481 1.5 thorpej default:
482 1.5 thorpej /* XXXLOCK */
483 1.5 thorpej dreq->dreq_error = EINVAL;
484 1.5 thorpej dreq->dreq_flags |= DMOVER_REQ_ERROR;
485 1.5 thorpej /* XXXUNLOCK */
486 1.5 thorpej goto done;
487 1.5 thorpej }
488 1.5 thorpej
489 1.5 thorpej memcpy(dreq->dreq_immediate, &result, sizeof(result));
490 1.5 thorpej done:
491 1.5 thorpej dmover_done(dreq);
492 1.5 thorpej }
493 1.5 thorpej
494 1.1 thorpej static struct swdmover_function swdmover_func_zero = {
495 1.1 thorpej swdmover_func_zero_process
496 1.1 thorpej };
497 1.1 thorpej
498 1.1 thorpej static struct swdmover_function swdmover_func_fill8 = {
499 1.1 thorpej swdmover_func_fill8_process
500 1.1 thorpej };
501 1.1 thorpej
502 1.5 thorpej static struct swdmover_function swdmover_func_copy = {
503 1.1 thorpej swdmover_func_copy_process
504 1.1 thorpej };
505 1.1 thorpej
506 1.5 thorpej static struct swdmover_function swdmover_func_iscsi_crc32c = {
507 1.5 thorpej swdmover_func_iscsi_crc32c_process
508 1.5 thorpej };
509 1.5 thorpej
510 1.1 thorpej const struct dmover_algdesc swdmover_algdescs[] = {
511 1.1 thorpej {
512 1.1 thorpej DMOVER_FUNC_ZERO,
513 1.1 thorpej &swdmover_func_zero,
514 1.1 thorpej 0
515 1.1 thorpej },
516 1.1 thorpej {
517 1.1 thorpej DMOVER_FUNC_FILL8,
518 1.1 thorpej &swdmover_func_fill8,
519 1.1 thorpej 0
520 1.1 thorpej },
521 1.1 thorpej {
522 1.1 thorpej DMOVER_FUNC_COPY,
523 1.1 thorpej &swdmover_func_copy,
524 1.1 thorpej 1
525 1.5 thorpej },
526 1.5 thorpej {
527 1.5 thorpej DMOVER_FUNC_ISCSI_CRC32C,
528 1.5 thorpej &swdmover_func_iscsi_crc32c,
529 1.5 thorpej 1,
530 1.1 thorpej },
531 1.1 thorpej };
532 1.1 thorpej #define SWDMOVER_ALGDESC_COUNT \
533 1.1 thorpej (sizeof(swdmover_algdescs) / sizeof(swdmover_algdescs[0]))
534 1.1 thorpej
535 1.1 thorpej /*
536 1.1 thorpej * swdmover_create_thread:
537 1.1 thorpej *
538 1.1 thorpej * Actually create the swdmover processing thread.
539 1.1 thorpej */
540 1.1 thorpej static void
541 1.1 thorpej swdmover_create_thread(void *arg)
542 1.1 thorpej {
543 1.1 thorpej int error;
544 1.1 thorpej
545 1.1 thorpej error = kthread_create1(swdmover_thread, arg, &swdmover_proc,
546 1.1 thorpej "swdmover");
547 1.1 thorpej if (error)
548 1.1 thorpej printf("WARNING: unable to create swdmover thread, "
549 1.1 thorpej "error = %d\n", error);
550 1.1 thorpej }
551 1.1 thorpej
552 1.1 thorpej /*
553 1.1 thorpej * swdmoverattach:
554 1.1 thorpej *
555 1.1 thorpej * Pesudo-device attach routine.
556 1.1 thorpej */
557 1.1 thorpej void
558 1.1 thorpej swdmoverattach(int count)
559 1.1 thorpej {
560 1.1 thorpej
561 1.1 thorpej swdmover_backend.dmb_name = "swdmover";
562 1.1 thorpej swdmover_backend.dmb_speed = 1; /* XXX */
563 1.1 thorpej swdmover_backend.dmb_cookie = NULL;
564 1.1 thorpej swdmover_backend.dmb_algdescs = swdmover_algdescs;
565 1.1 thorpej swdmover_backend.dmb_nalgdescs = SWDMOVER_ALGDESC_COUNT;
566 1.1 thorpej swdmover_backend.dmb_process = swdmover_process;
567 1.1 thorpej
568 1.1 thorpej kthread_create(swdmover_create_thread, &swdmover_backend);
569 1.1 thorpej
570 1.1 thorpej /* XXX Should only register this when kthread creation succeeds. */
571 1.1 thorpej dmover_backend_register(&swdmover_backend);
572 1.1 thorpej }
573