xref: /netbsd-src/sys/dev/dmover/swdmover.c (revision 863d66edc3ea671ca6913490957025b4bce9d757)
1*863d66edSchristos /*	$NetBSD: swdmover.c,v 1.14 2017/01/07 21:11:14 christos Exp $	*/
25d06c0e8Sthorpej 
35d06c0e8Sthorpej /*
4b41675bcSthorpej  * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
55d06c0e8Sthorpej  * All rights reserved.
65d06c0e8Sthorpej  *
75d06c0e8Sthorpej  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
85d06c0e8Sthorpej  *
95d06c0e8Sthorpej  * Redistribution and use in source and binary forms, with or without
105d06c0e8Sthorpej  * modification, are permitted provided that the following conditions
115d06c0e8Sthorpej  * are met:
125d06c0e8Sthorpej  * 1. Redistributions of source code must retain the above copyright
135d06c0e8Sthorpej  *    notice, this list of conditions and the following disclaimer.
145d06c0e8Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
155d06c0e8Sthorpej  *    notice, this list of conditions and the following disclaimer in the
165d06c0e8Sthorpej  *    documentation and/or other materials provided with the distribution.
175d06c0e8Sthorpej  * 3. All advertising materials mentioning features or use of this software
185d06c0e8Sthorpej  *    must display the following acknowledgement:
195d06c0e8Sthorpej  *	This product includes software developed for the NetBSD Project by
205d06c0e8Sthorpej  *	Wasabi Systems, Inc.
215d06c0e8Sthorpej  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
225d06c0e8Sthorpej  *    or promote products derived from this software without specific prior
235d06c0e8Sthorpej  *    written permission.
245d06c0e8Sthorpej  *
255d06c0e8Sthorpej  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
265d06c0e8Sthorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
275d06c0e8Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
285d06c0e8Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
295d06c0e8Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
305d06c0e8Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
315d06c0e8Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
325d06c0e8Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
335d06c0e8Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
345d06c0e8Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
355d06c0e8Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
365d06c0e8Sthorpej  */
375d06c0e8Sthorpej 
385d06c0e8Sthorpej /*
395d06c0e8Sthorpej  * swdmover.c: Software back-end providing the dmover functions
405d06c0e8Sthorpej  * mentioned in dmover(9).
415d06c0e8Sthorpej  *
425d06c0e8Sthorpej  * This module provides a fallback for cases where no hardware
435d06c0e8Sthorpej  * data movers are present in a system, and also serves an an
445d06c0e8Sthorpej  * example of how to write a dmover back-end.
455d06c0e8Sthorpej  *
465d06c0e8Sthorpej  * Note that even through the software dmover doesn't require
475d06c0e8Sthorpej  * interrupts to be blocked, we block them anyway to demonstrate
485d06c0e8Sthorpej  * the locking protocol.
495d06c0e8Sthorpej  */
505d06c0e8Sthorpej 
515d06c0e8Sthorpej #include <sys/cdefs.h>
52*863d66edSchristos __KERNEL_RCSID(0, "$NetBSD: swdmover.c,v 1.14 2017/01/07 21:11:14 christos Exp $");
535d06c0e8Sthorpej 
545d06c0e8Sthorpej #include <sys/param.h>
555d06c0e8Sthorpej #include <sys/kthread.h>
565d06c0e8Sthorpej #include <sys/systm.h>
575d06c0e8Sthorpej #include <sys/uio.h>
585d06c0e8Sthorpej 
595d06c0e8Sthorpej #include <dev/dmover/dmovervar.h>
605d06c0e8Sthorpej 
61e7ae23fdSchristos #include "ioconf.h"
62e7ae23fdSchristos 
635d06c0e8Sthorpej struct swdmover_function {
645d06c0e8Sthorpej 	void	(*sdf_process)(struct dmover_request *);
655d06c0e8Sthorpej };
665d06c0e8Sthorpej 
675d06c0e8Sthorpej static struct dmover_backend swdmover_backend;
68cdcf88b0She static struct lwp *swdmover_lwp;
695d06c0e8Sthorpej static int swdmover_cv;
705d06c0e8Sthorpej 
715d06c0e8Sthorpej /*
725d06c0e8Sthorpej  * swdmover_process:
735d06c0e8Sthorpej  *
745d06c0e8Sthorpej  *	Dmover back-end entry point.
755d06c0e8Sthorpej  */
765d06c0e8Sthorpej static void
swdmover_process(struct dmover_backend * dmb)775d06c0e8Sthorpej swdmover_process(struct dmover_backend *dmb)
785d06c0e8Sthorpej {
795d06c0e8Sthorpej 	int s;
805d06c0e8Sthorpej 
815d06c0e8Sthorpej 	/*
825d06c0e8Sthorpej 	 * Just wake up the processing thread.  This will allow
835d06c0e8Sthorpej 	 * requests to linger on the middle-end's queue so that
845d06c0e8Sthorpej 	 * they can be cancelled, if need-be.
855d06c0e8Sthorpej 	 */
865d06c0e8Sthorpej 	s = splbio();
875d06c0e8Sthorpej 	/* XXXLOCK */
885d06c0e8Sthorpej 	if (TAILQ_EMPTY(&dmb->dmb_pendreqs) == 0)
895d06c0e8Sthorpej 		wakeup(&swdmover_cv);
905d06c0e8Sthorpej 	/* XXXUNLOCK */
915d06c0e8Sthorpej 	splx(s);
925d06c0e8Sthorpej }
935d06c0e8Sthorpej 
945d06c0e8Sthorpej /*
955d06c0e8Sthorpej  * swdmover_thread:
965d06c0e8Sthorpej  *
975d06c0e8Sthorpej  *	Request processing thread.
985d06c0e8Sthorpej  */
995d06c0e8Sthorpej static void
swdmover_thread(void * arg)1005d06c0e8Sthorpej swdmover_thread(void *arg)
1015d06c0e8Sthorpej {
1025d06c0e8Sthorpej 	struct dmover_backend *dmb = arg;
1035d06c0e8Sthorpej 	struct dmover_request *dreq;
1045d06c0e8Sthorpej 	struct swdmover_function *sdf;
1055d06c0e8Sthorpej 	int s;
1065d06c0e8Sthorpej 
1075d06c0e8Sthorpej 	s = splbio();
1085d06c0e8Sthorpej 	/* XXXLOCK */
1095d06c0e8Sthorpej 
1105d06c0e8Sthorpej 	for (;;) {
1115d06c0e8Sthorpej 		dreq = TAILQ_FIRST(&dmb->dmb_pendreqs);
1125d06c0e8Sthorpej 		if (dreq == NULL) {
1135d06c0e8Sthorpej 			/* XXXUNLOCK */
1145d06c0e8Sthorpej 			(void) tsleep(&swdmover_cv, PRIBIO, "swdmvr", 0);
1155d06c0e8Sthorpej 			continue;
1165d06c0e8Sthorpej 		}
1175d06c0e8Sthorpej 
1185d06c0e8Sthorpej 		dmover_backend_remque(dmb, dreq);
1195d06c0e8Sthorpej 		dreq->dreq_flags |= DMOVER_REQ_RUNNING;
1205d06c0e8Sthorpej 
1215d06c0e8Sthorpej 		/* XXXUNLOCK */
1225d06c0e8Sthorpej 		splx(s);
1235d06c0e8Sthorpej 
1245d06c0e8Sthorpej 		sdf = dreq->dreq_assignment->das_algdesc->dad_data;
1255d06c0e8Sthorpej 		(*sdf->sdf_process)(dreq);
1265d06c0e8Sthorpej 
1275d06c0e8Sthorpej 		s = splbio();
1285d06c0e8Sthorpej 		/* XXXLOCK */
1295d06c0e8Sthorpej 	}
1305d06c0e8Sthorpej }
1315d06c0e8Sthorpej 
1325d06c0e8Sthorpej /*
1335d06c0e8Sthorpej  * swdmover_func_zero_process:
1345d06c0e8Sthorpej  *
1355d06c0e8Sthorpej  *	Processing routine for the "zero" function.
1365d06c0e8Sthorpej  */
1375d06c0e8Sthorpej static void
swdmover_func_zero_process(struct dmover_request * dreq)1385d06c0e8Sthorpej swdmover_func_zero_process(struct dmover_request *dreq)
1395d06c0e8Sthorpej {
1405d06c0e8Sthorpej 
1415d06c0e8Sthorpej 	switch (dreq->dreq_outbuf_type) {
1425d06c0e8Sthorpej 	case DMOVER_BUF_LINEAR:
1435d06c0e8Sthorpej 		memset(dreq->dreq_outbuf.dmbuf_linear.l_addr, 0,
1445d06c0e8Sthorpej 		    dreq->dreq_outbuf.dmbuf_linear.l_len);
1455d06c0e8Sthorpej 		break;
1465d06c0e8Sthorpej 
1475d06c0e8Sthorpej 	case DMOVER_BUF_UIO:
1485d06c0e8Sthorpej 	    {
1495d06c0e8Sthorpej 		struct uio *uio = dreq->dreq_outbuf.dmbuf_uio;
150*863d66edSchristos 		char cp[1024];
1515d06c0e8Sthorpej 		size_t count, buflen;
1525d06c0e8Sthorpej 		int error;
1535d06c0e8Sthorpej 
1545d06c0e8Sthorpej 		if (uio->uio_rw != UIO_READ) {
1555d06c0e8Sthorpej 			/* XXXLOCK */
1565d06c0e8Sthorpej 			dreq->dreq_error = EINVAL;
1575d06c0e8Sthorpej 			dreq->dreq_flags |= DMOVER_REQ_ERROR;
1585d06c0e8Sthorpej 			/* XXXUNLOCK */
1595d06c0e8Sthorpej 			break;
1605d06c0e8Sthorpej 		}
1615d06c0e8Sthorpej 
1625d06c0e8Sthorpej 		buflen = uio->uio_resid;
163*863d66edSchristos 		if (buflen > sizeof(cp))
164*863d66edSchristos 			buflen = sizeof(cp);
1655d06c0e8Sthorpej 		memset(cp, 0, buflen);
1665d06c0e8Sthorpej 
1675d06c0e8Sthorpej 		while ((count = uio->uio_resid) != 0) {
1685d06c0e8Sthorpej 			if (count > buflen)
1695d06c0e8Sthorpej 				count = buflen;
1705d06c0e8Sthorpej 			error = uiomove(cp, count, uio);
1715d06c0e8Sthorpej 			if (error) {
1725d06c0e8Sthorpej 				/* XXXLOCK */
1735d06c0e8Sthorpej 				dreq->dreq_error = error;
1745d06c0e8Sthorpej 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
1755d06c0e8Sthorpej 				/* XXXUNLOCK */
1765d06c0e8Sthorpej 				break;
1775d06c0e8Sthorpej 			}
1785d06c0e8Sthorpej 		}
1795d06c0e8Sthorpej 		break;
1805d06c0e8Sthorpej 	    }
18190044065Sthorpej 
18290044065Sthorpej 	default:
18390044065Sthorpej 		/* XXXLOCK */
18490044065Sthorpej 		dreq->dreq_error = EINVAL;
18590044065Sthorpej 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
18690044065Sthorpej 		/* XXXUNLOCK */
1875d06c0e8Sthorpej 	}
1885d06c0e8Sthorpej 
1895d06c0e8Sthorpej 	dmover_done(dreq);
1905d06c0e8Sthorpej }
1915d06c0e8Sthorpej 
1925d06c0e8Sthorpej /*
1935d06c0e8Sthorpej  * swdmover_func_fill8_process:
1945d06c0e8Sthorpej  *
1955d06c0e8Sthorpej  *	Processing routine for the "fill8" function.
1965d06c0e8Sthorpej  */
1975d06c0e8Sthorpej static void
swdmover_func_fill8_process(struct dmover_request * dreq)1985d06c0e8Sthorpej swdmover_func_fill8_process(struct dmover_request *dreq)
1995d06c0e8Sthorpej {
2005d06c0e8Sthorpej 
2015d06c0e8Sthorpej 	switch (dreq->dreq_outbuf_type) {
2025d06c0e8Sthorpej 	case DMOVER_BUF_LINEAR:
2035d06c0e8Sthorpej 		memset(dreq->dreq_outbuf.dmbuf_linear.l_addr,
2045d06c0e8Sthorpej 		    dreq->dreq_immediate[0],
2055d06c0e8Sthorpej 		    dreq->dreq_outbuf.dmbuf_linear.l_len);
2065d06c0e8Sthorpej 		break;
2075d06c0e8Sthorpej 
2085d06c0e8Sthorpej 	case DMOVER_BUF_UIO:
2095d06c0e8Sthorpej 	    {
2105d06c0e8Sthorpej 		struct uio *uio = dreq->dreq_outbuf.dmbuf_uio;
211*863d66edSchristos 		char cp[1024];
2125d06c0e8Sthorpej 		size_t count, buflen;
2135d06c0e8Sthorpej 		int error;
2145d06c0e8Sthorpej 
2155d06c0e8Sthorpej 		if (uio->uio_rw != UIO_READ) {
2165d06c0e8Sthorpej 			/* XXXLOCK */
2175d06c0e8Sthorpej 			dreq->dreq_error = EINVAL;
2185d06c0e8Sthorpej 			dreq->dreq_flags |= DMOVER_REQ_ERROR;
2195d06c0e8Sthorpej 			/* XXXUNLOCK */
2205d06c0e8Sthorpej 			break;
2215d06c0e8Sthorpej 		}
2225d06c0e8Sthorpej 
2235d06c0e8Sthorpej 		buflen = uio->uio_resid;
224*863d66edSchristos 		if (buflen > sizeof(cp))
225*863d66edSchristos 			buflen = sizeof(cp);
2265d06c0e8Sthorpej 		memset(cp, dreq->dreq_immediate[0], buflen);
2275d06c0e8Sthorpej 
2285d06c0e8Sthorpej 		while ((count = uio->uio_resid) != 0) {
2295d06c0e8Sthorpej 			if (count > buflen)
2305d06c0e8Sthorpej 				count = buflen;
2315d06c0e8Sthorpej 			error = uiomove(cp, count, uio);
2325d06c0e8Sthorpej 			if (error) {
2335d06c0e8Sthorpej 				/* XXXLOCK */
2345d06c0e8Sthorpej 				dreq->dreq_error = error;
2355d06c0e8Sthorpej 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
2365d06c0e8Sthorpej 				/* XXXUNLOCK */
2375d06c0e8Sthorpej 				break;
2385d06c0e8Sthorpej 			}
2395d06c0e8Sthorpej 		}
2405d06c0e8Sthorpej 		break;
2415d06c0e8Sthorpej 	    }
24290044065Sthorpej 
24390044065Sthorpej 	default:
24490044065Sthorpej 		/* XXXLOCK */
24590044065Sthorpej 		dreq->dreq_error = EINVAL;
24690044065Sthorpej 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
24790044065Sthorpej 		/* XXXUNLOCK */
2485d06c0e8Sthorpej 	}
2495d06c0e8Sthorpej 
2505d06c0e8Sthorpej 	dmover_done(dreq);
2515d06c0e8Sthorpej }
2525d06c0e8Sthorpej 
2536d7027eeSbriggs static void
xor2(uint8_t * dst,uint8_t * src1,uint8_t * src2,int cnt)2546d7027eeSbriggs xor2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int cnt)
2556d7027eeSbriggs {
2566d7027eeSbriggs 
2576d7027eeSbriggs 	while (cnt--)
2586d7027eeSbriggs 		*dst++ = *src1++ ^ *src2++;
2596d7027eeSbriggs }
2606d7027eeSbriggs 
2616d7027eeSbriggs /*
2626d7027eeSbriggs  * swdmover_func_xor_process:
2636d7027eeSbriggs  *
2646d7027eeSbriggs  *	Processing routine for the "xor" function.
2656d7027eeSbriggs  */
2666d7027eeSbriggs static void
swdmover_func_xor_process(struct dmover_request * dreq)2676d7027eeSbriggs swdmover_func_xor_process(struct dmover_request *dreq)
2686d7027eeSbriggs {
2696d7027eeSbriggs #define INBUF_L(x)	dreq->dreq_inbuf[(x)].dmbuf_linear
2706d7027eeSbriggs #define OUTBUF_L	dreq->dreq_outbuf.dmbuf_linear
2716d7027eeSbriggs 
2726d7027eeSbriggs 	uint32_t *dst32, *src32;
2736d7027eeSbriggs 	uint8_t *dst8, *src8;
2746d7027eeSbriggs 	int	i, ninputs = dreq->dreq_assignment->das_algdesc->dad_ninputs;
2756d7027eeSbriggs 	int	aligned, len, nwords;
2766d7027eeSbriggs 
2776d7027eeSbriggs 	/* XXX Currently, both buffers must be of same type. */
2786d7027eeSbriggs 	if (dreq->dreq_inbuf_type != dreq->dreq_outbuf_type) {
2796d7027eeSbriggs 		/* XXXLOCK */
2806d7027eeSbriggs 		dreq->dreq_error = EINVAL;
2816d7027eeSbriggs 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
2826d7027eeSbriggs 		/* XXXUNLOCK */
2836d7027eeSbriggs 		goto done;
2846d7027eeSbriggs 	}
2856d7027eeSbriggs 
2866d7027eeSbriggs 	switch (dreq->dreq_outbuf_type) {
2876d7027eeSbriggs 	case DMOVER_BUF_LINEAR:
2886d7027eeSbriggs 		aligned = 1;
2896d7027eeSbriggs 		if ((ulong) OUTBUF_L.l_addr & 0x3)
2906d7027eeSbriggs 			aligned = 0;
291cad1dd99Sbriggs 		len = OUTBUF_L.l_len;
2926d7027eeSbriggs 		for (i = 0 ; i < ninputs ; i++) {
2936d7027eeSbriggs 			if (len != INBUF_L(i).l_len) {
2946d7027eeSbriggs 				/* XXXLOCK */
2956d7027eeSbriggs 				dreq->dreq_error = EINVAL;
2966d7027eeSbriggs 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
2976d7027eeSbriggs 				/* XXXUNLOCK */
2986d7027eeSbriggs 				break;
2996d7027eeSbriggs 			}
3006d7027eeSbriggs 			if ((ulong) INBUF_L(i).l_addr & 0x3)
3016d7027eeSbriggs 				aligned = 0;
3026d7027eeSbriggs 		}
3036d7027eeSbriggs 		if (aligned) {
3046d7027eeSbriggs 			dst32 = (uint32_t *) OUTBUF_L.l_addr;
3056d7027eeSbriggs 			nwords = len / 4;
3066d7027eeSbriggs 			while (nwords--) {
3076d7027eeSbriggs 				*dst32 = 0;
3086d7027eeSbriggs 				for (i = 0 ; i < ninputs ; i++) {
3096d7027eeSbriggs 					src32 = (uint32_t *) INBUF_L(i).l_addr;
3106d7027eeSbriggs 					*dst32 ^= *src32;
3116d7027eeSbriggs 				}
3126d7027eeSbriggs 				dst32++;
3136d7027eeSbriggs 				len -= 4;
3146d7027eeSbriggs 			}
3156d7027eeSbriggs 		}
3166d7027eeSbriggs 		if (len) {
3176d7027eeSbriggs 			dst8 = (uint8_t *) OUTBUF_L.l_addr;
3186d7027eeSbriggs 			while (len--) {
3196d7027eeSbriggs 				*dst8 = 0;
3206d7027eeSbriggs 				for (i = 0 ; i < ninputs ; i++) {
3216d7027eeSbriggs 					src8 = (uint8_t *) INBUF_L(i).l_addr;
3226d7027eeSbriggs 					*dst8 ^= *src8;
3236d7027eeSbriggs 				}
3246d7027eeSbriggs 				dst8++;
3256d7027eeSbriggs 			}
3266d7027eeSbriggs 		}
3276d7027eeSbriggs 
3286d7027eeSbriggs 		break;
3296d7027eeSbriggs 
3306d7027eeSbriggs 	case DMOVER_BUF_UIO:
3316d7027eeSbriggs 	    {
3326d7027eeSbriggs 		struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio;
3336d7027eeSbriggs 		struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
3346d7027eeSbriggs 		struct uio *uio;
335*863d66edSchristos 		char cp[1024], dst[1024];
3366d7027eeSbriggs 		size_t count, buflen;
3376d7027eeSbriggs 		int error;
3386d7027eeSbriggs 
3396d7027eeSbriggs 		if (uio_in->uio_rw != UIO_WRITE ||
3406d7027eeSbriggs 		    uio_out->uio_rw != UIO_READ ||
3416d7027eeSbriggs 		    uio_in->uio_resid != uio_out->uio_resid) {
3426d7027eeSbriggs 			/* XXXLOCK */
3436d7027eeSbriggs 			dreq->dreq_error = EINVAL;
3446d7027eeSbriggs 			dreq->dreq_flags |= DMOVER_REQ_ERROR;
3456d7027eeSbriggs 			/* XXXUNLOCK */
3466d7027eeSbriggs 			break;
3476d7027eeSbriggs 		}
3486d7027eeSbriggs 
3496d7027eeSbriggs 		buflen = uio_in->uio_resid;
350*863d66edSchristos 		if (buflen > sizeof(cp))
351*863d66edSchristos 			buflen = sizeof(cp);
3526d7027eeSbriggs 
3536d7027eeSbriggs 		/*
3546d7027eeSbriggs 		 * For each block, copy first input buffer into the destination
3556d7027eeSbriggs 		 * buffer and then read the rest, one by one, into a temporary
3566d7027eeSbriggs 		 * buffer and xor into the destination buffer.  After all of
3576d7027eeSbriggs 		 * the inputs have been xor'd in, move the destination buffer
3586d7027eeSbriggs 		 * out and loop.
3596d7027eeSbriggs 		 */
3606d7027eeSbriggs 		while ((count = uio_in->uio_resid) != 0) {
3616d7027eeSbriggs 			if (count > buflen)
3626d7027eeSbriggs 				count = buflen;
3636d7027eeSbriggs 			error = uiomove(dst, count, uio_in);
3646d7027eeSbriggs 			if (error) {
3656d7027eeSbriggs 				/* XXXLOCK */
3666d7027eeSbriggs 				dreq->dreq_error = error;
3676d7027eeSbriggs 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
3686d7027eeSbriggs 				/* XXXUNLOCK */
3696d7027eeSbriggs 				break;
3706d7027eeSbriggs 			}
3716d7027eeSbriggs 			for (i=1 ; (i < ninputs) && (error == 0) ; i++) {
3726d7027eeSbriggs 				uio = dreq->dreq_inbuf[i].dmbuf_uio;
3736d7027eeSbriggs 				error = uiomove(cp, count, uio);
3746d7027eeSbriggs 				if (error == 0) {
3756d7027eeSbriggs 					xor2(dst, dst, cp, count);
3766d7027eeSbriggs 				}
3776d7027eeSbriggs 			}
3786d7027eeSbriggs 			if (error == 0) {
3796d7027eeSbriggs 				error = uiomove(dst, count, uio_out);
3806d7027eeSbriggs 			} else {
3816d7027eeSbriggs 				/* XXXLOCK */
3826d7027eeSbriggs 				dreq->dreq_error = error;
3836d7027eeSbriggs 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
3846d7027eeSbriggs 				/* XXXUNLOCK */
3856d7027eeSbriggs 				break;
3866d7027eeSbriggs 			}
3876d7027eeSbriggs 		}
3886d7027eeSbriggs 		break;
3896d7027eeSbriggs 	    }
3906d7027eeSbriggs 
3916d7027eeSbriggs 	default:
3926d7027eeSbriggs 		/* XXXLOCK */
3936d7027eeSbriggs 		dreq->dreq_error = EINVAL;
3946d7027eeSbriggs 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
3956d7027eeSbriggs 		/* XXXUNLOCK */
3966d7027eeSbriggs 	}
3976d7027eeSbriggs 
3986d7027eeSbriggs  done:
3996d7027eeSbriggs 	dmover_done(dreq);
4006d7027eeSbriggs }
4016d7027eeSbriggs 
4025d06c0e8Sthorpej /*
4035d06c0e8Sthorpej  * swdmover_func_copy_process:
4045d06c0e8Sthorpej  *
4055d06c0e8Sthorpej  *	Processing routine for the "copy" function.
4065d06c0e8Sthorpej  */
4075d06c0e8Sthorpej static void
swdmover_func_copy_process(struct dmover_request * dreq)4085d06c0e8Sthorpej swdmover_func_copy_process(struct dmover_request *dreq)
4095d06c0e8Sthorpej {
4105d06c0e8Sthorpej 
411a5722408Sthorpej 	/* XXX Currently, both buffers must be of same type. */
412a5722408Sthorpej 	if (dreq->dreq_inbuf_type != dreq->dreq_outbuf_type) {
413a5722408Sthorpej 		/* XXXLOCK */
414a5722408Sthorpej 		dreq->dreq_error = EINVAL;
415a5722408Sthorpej 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
416a5722408Sthorpej 		/* XXXUNLOCK */
417a5722408Sthorpej 		goto done;
418a5722408Sthorpej 	}
419a5722408Sthorpej 
4205d06c0e8Sthorpej 	switch (dreq->dreq_outbuf_type) {
4215d06c0e8Sthorpej 	case DMOVER_BUF_LINEAR:
4225d06c0e8Sthorpej 		if (dreq->dreq_outbuf.dmbuf_linear.l_len !=
4235d06c0e8Sthorpej 		    dreq->dreq_inbuf[0].dmbuf_linear.l_len) {
4245d06c0e8Sthorpej 			/* XXXLOCK */
4255d06c0e8Sthorpej 			dreq->dreq_error = EINVAL;
4265d06c0e8Sthorpej 			dreq->dreq_flags |= DMOVER_REQ_ERROR;
4275d06c0e8Sthorpej 			/* XXXUNLOCK */
4285d06c0e8Sthorpej 			break;
4295d06c0e8Sthorpej 		}
4305d06c0e8Sthorpej 		memcpy(dreq->dreq_outbuf.dmbuf_linear.l_addr,
4315d06c0e8Sthorpej 		    dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
4325d06c0e8Sthorpej 		    dreq->dreq_outbuf.dmbuf_linear.l_len);
4335d06c0e8Sthorpej 		break;
4345d06c0e8Sthorpej 
4355d06c0e8Sthorpej 	case DMOVER_BUF_UIO:
4365d06c0e8Sthorpej 	    {
4375d06c0e8Sthorpej 		struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio;
4385d06c0e8Sthorpej 		struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
439*863d66edSchristos 		char cp[1024];
4405d06c0e8Sthorpej 		size_t count, buflen;
4415d06c0e8Sthorpej 		int error;
4425d06c0e8Sthorpej 
4435d06c0e8Sthorpej 		if (uio_in->uio_rw != UIO_WRITE ||
4445d06c0e8Sthorpej 		    uio_out->uio_rw != UIO_READ ||
4455d06c0e8Sthorpej 		    uio_in->uio_resid != uio_out->uio_resid) {
4465d06c0e8Sthorpej 			/* XXXLOCK */
4475d06c0e8Sthorpej 			dreq->dreq_error = EINVAL;
4485d06c0e8Sthorpej 			dreq->dreq_flags |= DMOVER_REQ_ERROR;
4495d06c0e8Sthorpej 			/* XXXUNLOCK */
4505d06c0e8Sthorpej 			break;
4515d06c0e8Sthorpej 		}
4525d06c0e8Sthorpej 
4535d06c0e8Sthorpej 		buflen = uio_in->uio_resid;
454*863d66edSchristos 		if (buflen > sizeof(cp))
455*863d66edSchristos 			buflen = sizeof(cp);
4565d06c0e8Sthorpej 
4575d06c0e8Sthorpej 		while ((count = uio_in->uio_resid) != 0) {
4585d06c0e8Sthorpej 			if (count > buflen)
4595d06c0e8Sthorpej 				count = buflen;
4605d06c0e8Sthorpej 			error = uiomove(cp, count, uio_in);
4615d06c0e8Sthorpej 			if (error == 0)
4625d06c0e8Sthorpej 				error = uiomove(cp, count, uio_out);
4635d06c0e8Sthorpej 			if (error) {
4645d06c0e8Sthorpej 				/* XXXLOCK */
4655d06c0e8Sthorpej 				dreq->dreq_error = error;
4665d06c0e8Sthorpej 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
4675d06c0e8Sthorpej 				/* XXXUNLOCK */
4685d06c0e8Sthorpej 				break;
4695d06c0e8Sthorpej 			}
4705d06c0e8Sthorpej 		}
4715d06c0e8Sthorpej 		break;
4725d06c0e8Sthorpej 	    }
47390044065Sthorpej 
47490044065Sthorpej 	default:
47590044065Sthorpej 		/* XXXLOCK */
47690044065Sthorpej 		dreq->dreq_error = EINVAL;
47790044065Sthorpej 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
47890044065Sthorpej 		/* XXXUNLOCK */
4795d06c0e8Sthorpej 	}
4805d06c0e8Sthorpej 
481a5722408Sthorpej  done:
4825d06c0e8Sthorpej 	dmover_done(dreq);
4835d06c0e8Sthorpej }
4845d06c0e8Sthorpej 
485b41675bcSthorpej static const uint32_t iscsi_crc32c_table[256] = {
486b41675bcSthorpej 	0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
487b41675bcSthorpej 	0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
488b41675bcSthorpej 	0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
489b41675bcSthorpej 	0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
490b41675bcSthorpej 	0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
491b41675bcSthorpej 	0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
492b41675bcSthorpej 	0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
493b41675bcSthorpej 	0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
494b41675bcSthorpej 	0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
495b41675bcSthorpej 	0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
496b41675bcSthorpej 	0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
497b41675bcSthorpej 	0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
498b41675bcSthorpej 	0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
499b41675bcSthorpej 	0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
500b41675bcSthorpej 	0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
501b41675bcSthorpej 	0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
502b41675bcSthorpej 	0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
503b41675bcSthorpej 	0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
504b41675bcSthorpej 	0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
505b41675bcSthorpej 	0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
506b41675bcSthorpej 	0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
507b41675bcSthorpej 	0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
508b41675bcSthorpej 	0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
509b41675bcSthorpej 	0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
510b41675bcSthorpej 	0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
511b41675bcSthorpej 	0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
512b41675bcSthorpej 	0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
513b41675bcSthorpej 	0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
514b41675bcSthorpej 	0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
515b41675bcSthorpej 	0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
516b41675bcSthorpej 	0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
517b41675bcSthorpej 	0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
518b41675bcSthorpej 	0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
519b41675bcSthorpej 	0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
520b41675bcSthorpej 	0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
521b41675bcSthorpej 	0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
522b41675bcSthorpej 	0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
523b41675bcSthorpej 	0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
524b41675bcSthorpej 	0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
525b41675bcSthorpej 	0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
526b41675bcSthorpej 	0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
527b41675bcSthorpej 	0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
528b41675bcSthorpej 	0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
529b41675bcSthorpej 	0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
530b41675bcSthorpej 	0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
531b41675bcSthorpej 	0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
532b41675bcSthorpej 	0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
533b41675bcSthorpej 	0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
534b41675bcSthorpej 	0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
535b41675bcSthorpej 	0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
536b41675bcSthorpej 	0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
537b41675bcSthorpej 	0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
538b41675bcSthorpej 	0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
539b41675bcSthorpej 	0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
540b41675bcSthorpej 	0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
541b41675bcSthorpej 	0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
542b41675bcSthorpej 	0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
543b41675bcSthorpej 	0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
544b41675bcSthorpej 	0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
545b41675bcSthorpej 	0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
546b41675bcSthorpej 	0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
547b41675bcSthorpej 	0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
548b41675bcSthorpej 	0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
549b41675bcSthorpej 	0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
550b41675bcSthorpej };
551b41675bcSthorpej 
552b41675bcSthorpej static uint32_t
iscsi_crc32c(const uint8_t * buf,size_t len,uint32_t last)553b41675bcSthorpej iscsi_crc32c(const uint8_t *buf, size_t len, uint32_t last)
554b41675bcSthorpej {
555b41675bcSthorpej 	uint32_t crc = 0xffffffffU ^ last;
556b41675bcSthorpej 
557b41675bcSthorpej 	while (len--)
558b41675bcSthorpej 		crc = iscsi_crc32c_table[(crc ^ *buf++) & 0xff] ^ (crc >> 8);
559b41675bcSthorpej 
560b41675bcSthorpej 	return (crc ^ 0xffffffffU);
561b41675bcSthorpej }
562b41675bcSthorpej 
563b41675bcSthorpej /*
564b41675bcSthorpej  * swdmover_func_iscsi_crc32c_process:
565b41675bcSthorpej  *
566b41675bcSthorpej  *	Processing routine for the "iscsi-crc32c" function.
567b41675bcSthorpej  */
568b41675bcSthorpej static void
swdmover_func_iscsi_crc32c_process(struct dmover_request * dreq)569b41675bcSthorpej swdmover_func_iscsi_crc32c_process(struct dmover_request *dreq)
570b41675bcSthorpej {
571b41675bcSthorpej 	uint32_t result;
572b41675bcSthorpej 
573b41675bcSthorpej 	/* No output buffer; we use the immediate only. */
574b41675bcSthorpej 	if (dreq->dreq_outbuf_type != DMOVER_BUF_NONE) {
575b41675bcSthorpej 		/* XXXLOCK */
576b41675bcSthorpej 		dreq->dreq_error = EINVAL;
577b41675bcSthorpej 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
578b41675bcSthorpej 		/* XXXUNLOCK */
579b41675bcSthorpej 		goto done;
580b41675bcSthorpej 	}
581b41675bcSthorpej 
582b41675bcSthorpej 	memcpy(&result, dreq->dreq_immediate, sizeof(result));
583b41675bcSthorpej 
584b41675bcSthorpej 	switch (dreq->dreq_inbuf_type) {
585b41675bcSthorpej 	case DMOVER_BUF_LINEAR:
586b41675bcSthorpej 		result = iscsi_crc32c(dreq->dreq_inbuf[0].dmbuf_linear.l_addr,
587b41675bcSthorpej 		    dreq->dreq_inbuf[0].dmbuf_linear.l_len, result);
588b41675bcSthorpej 		break;
589b41675bcSthorpej 
590b41675bcSthorpej 	case DMOVER_BUF_UIO:
591b41675bcSthorpej 	    {
592b41675bcSthorpej 		struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio;
593*863d66edSchristos 		uint8_t cp[1024];
594b41675bcSthorpej 		size_t count, buflen;
595b41675bcSthorpej 		int error;
596b41675bcSthorpej 
597b41675bcSthorpej 		if (uio_in->uio_rw != UIO_WRITE) {
598b41675bcSthorpej 			/* XXXLOCK */
599b41675bcSthorpej 			dreq->dreq_error = EINVAL;
600b41675bcSthorpej 			dreq->dreq_flags |= DMOVER_REQ_ERROR;
601b41675bcSthorpej 			/* XXXUNLOCK */
602b41675bcSthorpej 			goto done;
603b41675bcSthorpej 		}
604b41675bcSthorpej 
605b41675bcSthorpej 		buflen = uio_in->uio_resid;
606*863d66edSchristos 		if (buflen > sizeof(cp))
607*863d66edSchristos 			buflen = sizeof(cp);
608b41675bcSthorpej 
609b41675bcSthorpej 		while ((count = uio_in->uio_resid) != 0) {
610b41675bcSthorpej 			if (count > buflen)
611b41675bcSthorpej 				count = buflen;
612b41675bcSthorpej 			error = uiomove(cp, count, uio_in);
613b41675bcSthorpej 			if (error) {
614b41675bcSthorpej 				/* XXXLOCK */
615b41675bcSthorpej 				dreq->dreq_error = error;
616b41675bcSthorpej 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
617b41675bcSthorpej 				/* XXXUNLOCK */
618b41675bcSthorpej 				goto done;
619b41675bcSthorpej 			} else
620b41675bcSthorpej 				result = iscsi_crc32c(cp, count, result);
621b41675bcSthorpej 		}
622b41675bcSthorpej 		break;
623b41675bcSthorpej 	    }
624b41675bcSthorpej 
625b41675bcSthorpej 	default:
626b41675bcSthorpej 		/* XXXLOCK */
627b41675bcSthorpej 		dreq->dreq_error = EINVAL;
628b41675bcSthorpej 		dreq->dreq_flags |= DMOVER_REQ_ERROR;
629b41675bcSthorpej 		/* XXXUNLOCK */
630b41675bcSthorpej 		goto done;
631b41675bcSthorpej 	}
632b41675bcSthorpej 
633b41675bcSthorpej 	memcpy(dreq->dreq_immediate, &result, sizeof(result));
634b41675bcSthorpej  done:
635b41675bcSthorpej 	dmover_done(dreq);
636b41675bcSthorpej }
637b41675bcSthorpej 
6385d06c0e8Sthorpej static struct swdmover_function swdmover_func_zero = {
6395d06c0e8Sthorpej 	swdmover_func_zero_process
6405d06c0e8Sthorpej };
6415d06c0e8Sthorpej 
6425d06c0e8Sthorpej static struct swdmover_function swdmover_func_fill8 = {
6435d06c0e8Sthorpej 	swdmover_func_fill8_process
6445d06c0e8Sthorpej };
6455d06c0e8Sthorpej 
646b41675bcSthorpej static struct swdmover_function swdmover_func_copy = {
6475d06c0e8Sthorpej 	swdmover_func_copy_process
6485d06c0e8Sthorpej };
6495d06c0e8Sthorpej 
6506d7027eeSbriggs static struct swdmover_function swdmover_func_xor = {
6516d7027eeSbriggs 	swdmover_func_xor_process
6526d7027eeSbriggs };
6536d7027eeSbriggs 
654b41675bcSthorpej static struct swdmover_function swdmover_func_iscsi_crc32c = {
655b41675bcSthorpej 	swdmover_func_iscsi_crc32c_process
656b41675bcSthorpej };
657b41675bcSthorpej 
6585d06c0e8Sthorpej const struct dmover_algdesc swdmover_algdescs[] = {
6595d06c0e8Sthorpej 	{
6606d7027eeSbriggs 	  DMOVER_FUNC_XOR2,
6616d7027eeSbriggs 	  &swdmover_func_xor,
6626d7027eeSbriggs 	  2
6636d7027eeSbriggs 	},
6646d7027eeSbriggs 	{
6656d7027eeSbriggs 	  DMOVER_FUNC_XOR3,
6666d7027eeSbriggs 	  &swdmover_func_xor,
6676d7027eeSbriggs 	  3
6686d7027eeSbriggs 	},
6696d7027eeSbriggs 	{
6706d7027eeSbriggs 	  DMOVER_FUNC_XOR4,
6716d7027eeSbriggs 	  &swdmover_func_xor,
6726d7027eeSbriggs 	  4
6736d7027eeSbriggs 	},
6746d7027eeSbriggs 	{
6756d7027eeSbriggs 	  DMOVER_FUNC_XOR5,
6766d7027eeSbriggs 	  &swdmover_func_xor,
6776d7027eeSbriggs 	  5
6786d7027eeSbriggs 	},
6796d7027eeSbriggs 	{
6806d7027eeSbriggs 	  DMOVER_FUNC_XOR6,
6816d7027eeSbriggs 	  &swdmover_func_xor,
6826d7027eeSbriggs 	  6
6836d7027eeSbriggs 	},
6846d7027eeSbriggs 	{
6856d7027eeSbriggs 	  DMOVER_FUNC_XOR7,
6866d7027eeSbriggs 	  &swdmover_func_xor,
6876d7027eeSbriggs 	  7
6886d7027eeSbriggs 	},
6896d7027eeSbriggs 	{
6906d7027eeSbriggs 	  DMOVER_FUNC_XOR8,
6916d7027eeSbriggs 	  &swdmover_func_xor,
6926d7027eeSbriggs 	  8
6936d7027eeSbriggs 	},
6946d7027eeSbriggs 	{
6955d06c0e8Sthorpej 	  DMOVER_FUNC_ZERO,
6965d06c0e8Sthorpej 	  &swdmover_func_zero,
6975d06c0e8Sthorpej 	  0
6985d06c0e8Sthorpej 	},
6995d06c0e8Sthorpej 	{
7005d06c0e8Sthorpej 	  DMOVER_FUNC_FILL8,
7015d06c0e8Sthorpej 	  &swdmover_func_fill8,
7025d06c0e8Sthorpej 	  0
7035d06c0e8Sthorpej 	},
7045d06c0e8Sthorpej 	{
7055d06c0e8Sthorpej 	  DMOVER_FUNC_COPY,
7065d06c0e8Sthorpej 	  &swdmover_func_copy,
7075d06c0e8Sthorpej 	  1
7085d06c0e8Sthorpej 	},
709b41675bcSthorpej 	{
710b41675bcSthorpej 	  DMOVER_FUNC_ISCSI_CRC32C,
711b41675bcSthorpej 	  &swdmover_func_iscsi_crc32c,
712b41675bcSthorpej 	  1,
713b41675bcSthorpej 	},
7145d06c0e8Sthorpej };
7155d06c0e8Sthorpej #define	SWDMOVER_ALGDESC_COUNT \
7165d06c0e8Sthorpej 	(sizeof(swdmover_algdescs) / sizeof(swdmover_algdescs[0]))
7175d06c0e8Sthorpej 
7185d06c0e8Sthorpej /*
7195d06c0e8Sthorpej  * swdmoverattach:
7205d06c0e8Sthorpej  *
7215d06c0e8Sthorpej  *	Pesudo-device attach routine.
7225d06c0e8Sthorpej  */
7235d06c0e8Sthorpej void
swdmoverattach(int count)7245d06c0e8Sthorpej swdmoverattach(int count)
7255d06c0e8Sthorpej {
72688ab7da9Sad 	int error;
7275d06c0e8Sthorpej 
7285d06c0e8Sthorpej 	swdmover_backend.dmb_name = "swdmover";
7295d06c0e8Sthorpej 	swdmover_backend.dmb_speed = 1;		/* XXX */
7305d06c0e8Sthorpej 	swdmover_backend.dmb_cookie = NULL;
7315d06c0e8Sthorpej 	swdmover_backend.dmb_algdescs = swdmover_algdescs;
7325d06c0e8Sthorpej 	swdmover_backend.dmb_nalgdescs = SWDMOVER_ALGDESC_COUNT;
7335d06c0e8Sthorpej 	swdmover_backend.dmb_process = swdmover_process;
7345d06c0e8Sthorpej 
73588ab7da9Sad 	error = kthread_create(PRI_NONE, 0, NULL, swdmover_thread,
736cdcf88b0She 	    &swdmover_backend, &swdmover_lwp, "swdmover");
73788ab7da9Sad 	if (error)
73888ab7da9Sad 		printf("WARNING: unable to create swdmover thread, "
73988ab7da9Sad 		    "error = %d\n", error);
7405d06c0e8Sthorpej 
7415d06c0e8Sthorpej 	/* XXX Should only register this when kthread creation succeeds. */
7425d06c0e8Sthorpej 	dmover_backend_register(&swdmover_backend);
7435d06c0e8Sthorpej }
744