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