Home | History | Annotate | Line # | Download | only in dmover
swdmover.c revision 1.8
      1  1.8    perry /*	$NetBSD: swdmover.c,v 1.8 2005/02/27 00:26:59 perry 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.8    perry __KERNEL_RCSID(0, "$NetBSD: swdmover.c,v 1.8 2005/02/27 00:26:59 perry 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.7   briggs 		len = OUTBUF_L.l_len;
    295  1.6   briggs 		for (i = 0 ; i < ninputs ; i++) {
    296  1.6   briggs 			if (len != INBUF_L(i).l_len) {
    297  1.6   briggs 				/* XXXLOCK */
    298  1.6   briggs 				dreq->dreq_error = EINVAL;
    299  1.6   briggs 				dreq->dreq_flags |= DMOVER_REQ_ERROR;
    300  1.6   briggs 				/* XXXUNLOCK */
    301  1.6   briggs 				break;
    302  1.6   briggs 			}
    303  1.6   briggs 			if ((ulong) INBUF_L(i).l_addr & 0x3)
    304  1.6   briggs 				aligned = 0;
    305  1.6   briggs 		}
    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.8    perry 
    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