criov.c revision 158698
1104476Ssam/*      $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $	*/
2104476Ssam
3139825Simp/*-
4104476Ssam * Copyright (c) 1999 Theo de Raadt
5104476Ssam *
6104476Ssam * Redistribution and use in source and binary forms, with or without
7104476Ssam * modification, are permitted provided that the following conditions
8104476Ssam * are met:
9104476Ssam *
10104476Ssam * 1. Redistributions of source code must retain the above copyright
11104476Ssam *   notice, this list of conditions and the following disclaimer.
12104476Ssam * 2. Redistributions in binary form must reproduce the above copyright
13104476Ssam *   notice, this list of conditions and the following disclaimer in the
14104476Ssam *   documentation and/or other materials provided with the distribution.
15104476Ssam * 3. The name of the author may not be used to endorse or promote products
16104476Ssam *   derived from this software without specific prior written permission.
17104476Ssam *
18104476Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19104476Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20104476Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21104476Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22104476Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23104476Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24104476Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25104476Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26104476Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27104476Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28104476Ssam */
29104476Ssam
30116191Sobrien#include <sys/cdefs.h>
31116191Sobrien__FBSDID("$FreeBSD: head/sys/opencrypto/criov.c 158698 2006-05-17 17:56:00Z pjd $");
32116191Sobrien
33104476Ssam#include <sys/param.h>
34104476Ssam#include <sys/systm.h>
35104476Ssam#include <sys/proc.h>
36104476Ssam#include <sys/errno.h>
37104476Ssam#include <sys/malloc.h>
38104476Ssam#include <sys/kernel.h>
39104476Ssam#include <sys/uio.h>
40104476Ssam
41104476Ssam#include <opencrypto/cryptodev.h>
42104476Ssam
43158698Spjd/*
44158698Spjd * This macro is only for avoiding code duplication, as we need to skip
45158698Spjd * given number of bytes in the same way in three functions below.
46158698Spjd */
47158698Spjd#define	CUIO_SKIP()	do {						\
48158698Spjd	KASSERT(off >= 0, ("%s: off %d < 0", __func__, off));		\
49158698Spjd	KASSERT(len >= 0, ("%s: len %d < 0", __func__, len));		\
50158698Spjd	while (off > 0) {						\
51158698Spjd		KASSERT(iol >= 0, ("%s: empty in skip", __func__));	\
52158698Spjd		if (off < iov->iov_len)					\
53158698Spjd			break;						\
54158698Spjd		off -= iov->iov_len;					\
55158698Spjd		iol--;							\
56158698Spjd		iov++;							\
57158698Spjd	}								\
58158698Spjd} while (0)
59158698Spjd
60104476Ssamvoid
61104476Ssamcuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
62104476Ssam{
63104476Ssam	struct iovec *iov = uio->uio_iov;
64104476Ssam	int iol = uio->uio_iovcnt;
65104476Ssam	unsigned count;
66104476Ssam
67158698Spjd	CUIO_SKIP();
68104476Ssam	while (len > 0) {
69158698Spjd		KASSERT(iol >= 0, ("%s: empty", __func__));
70104476Ssam		count = min(iov->iov_len - off, len);
71104476Ssam		bcopy(((caddr_t)iov->iov_base) + off, cp, count);
72104476Ssam		len -= count;
73104476Ssam		cp += count;
74104476Ssam		off = 0;
75104476Ssam		iol--;
76104476Ssam		iov++;
77104476Ssam	}
78104476Ssam}
79104476Ssam
80104476Ssamvoid
81104476Ssamcuio_copyback(struct uio* uio, int off, int len, caddr_t cp)
82104476Ssam{
83104476Ssam	struct iovec *iov = uio->uio_iov;
84104476Ssam	int iol = uio->uio_iovcnt;
85104476Ssam	unsigned count;
86104476Ssam
87158698Spjd	CUIO_SKIP();
88104476Ssam	while (len > 0) {
89158698Spjd		KASSERT(iol >= 0, ("%s: empty", __func__));
90104476Ssam		count = min(iov->iov_len - off, len);
91104476Ssam		bcopy(cp, ((caddr_t)iov->iov_base) + off, count);
92104476Ssam		len -= count;
93104476Ssam		cp += count;
94104476Ssam		off = 0;
95104476Ssam		iol--;
96104476Ssam		iov++;
97104476Ssam	}
98104476Ssam}
99104476Ssam
100104476Ssam/*
101104476Ssam * Return a pointer to iov/offset of location in iovec list.
102104476Ssam */
103104476Ssamstruct iovec *
104104476Ssamcuio_getptr(struct uio *uio, int loc, int *off)
105104476Ssam{
106104476Ssam	struct iovec *iov = uio->uio_iov;
107104476Ssam	int iol = uio->uio_iovcnt;
108104476Ssam
109104476Ssam	while (loc >= 0) {
110104476Ssam		/* Normal end of search */
111104476Ssam		if (loc < iov->iov_len) {
112104476Ssam	    		*off = loc;
113104476Ssam	    		return (iov);
114104476Ssam		}
115104476Ssam
116104476Ssam		loc -= iov->iov_len;
117104476Ssam		if (iol == 0) {
118104476Ssam			if (loc == 0) {
119104476Ssam				/* Point at the end of valid data */
120104476Ssam				*off = iov->iov_len;
121104476Ssam				return (iov);
122104476Ssam			} else
123104476Ssam				return (NULL);
124104476Ssam		} else {
125104476Ssam			iov++, iol--;
126104476Ssam		}
127104476Ssam    	}
128104476Ssam
129104476Ssam	return (NULL);
130104476Ssam}
131158698Spjd
132158698Spjd/*
133158698Spjd * Apply function f to the data in an iovec list starting "off" bytes from
134158698Spjd * the beginning, continuing for "len" bytes.
135158698Spjd */
136158698Spjdint
137158698Spjdcuio_apply(struct uio *uio, int off, int len, int (*f)(void *, void *, u_int),
138158698Spjd    void *arg)
139158698Spjd{
140158698Spjd	struct iovec *iov = uio->uio_iov;
141158698Spjd	int iol = uio->uio_iovcnt;
142158698Spjd	unsigned count;
143158698Spjd	int rval;
144158698Spjd
145158698Spjd	CUIO_SKIP();
146158698Spjd	while (len > 0) {
147158698Spjd		KASSERT(iol >= 0, ("%s: empty", __func__));
148158698Spjd		count = min(iov->iov_len - off, len);
149158698Spjd		rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count);
150158698Spjd		if (rval)
151158698Spjd			return (rval);
152158698Spjd		len -= count;
153158698Spjd		off = 0;
154158698Spjd		iol--;
155158698Spjd		iov++;
156158698Spjd	}
157158698Spjd	return (0);
158158698Spjd}
159