1/* $NetBSD: criov.c,v 1.9 2018/09/03 16:29:37 riastradh Exp $ */ 2/* $OpenBSD: criov.c,v 1.11 2002/06/10 19:36:43 espie Exp $ */ 3 4/* 5 * Copyright (c) 1999 Theo de Raadt 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> 32__KERNEL_RCSID(0, "$NetBSD: criov.c,v 1.9 2018/09/03 16:29:37 riastradh Exp $"); 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/proc.h> 37#include <sys/errno.h> 38#include <sys/malloc.h> 39#include <sys/kernel.h> 40#include <sys/mbuf.h> 41 42#include <uvm/uvm_extern.h> 43 44#include <opencrypto/cryptodev.h> 45int cuio_getindx(struct uio *uio, int loc, int *off); 46 47 48void 49cuio_copydata(struct uio *uio, int off, int len, void *cp) 50{ 51 struct iovec *iov = uio->uio_iov; 52 int iol = uio->uio_iovcnt; 53 unsigned count; 54 55 if (off < 0) 56 panic("cuio_copydata: off %d < 0", off); 57 if (len < 0) 58 panic("cuio_copydata: len %d < 0", len); 59 while (off > 0) { 60 if (iol == 0) 61 panic("iov_copydata: empty in skip"); 62 if (off < iov->iov_len) 63 break; 64 off -= iov->iov_len; 65 iol--; 66 iov++; 67 } 68 while (len > 0) { 69 if (iol == 0) 70 panic("cuio_copydata: empty"); 71 count = uimin(iov->iov_len - off, len); 72 memcpy(cp, (char *)iov->iov_base + off, count); 73 len -= count; 74 cp = (char *)cp + count; 75 off = 0; 76 iol--; 77 iov++; 78 } 79} 80 81void 82cuio_copyback(struct uio *uio, int off, int len, void *cp) 83{ 84 struct iovec *iov = uio->uio_iov; 85 int iol = uio->uio_iovcnt; 86 unsigned count; 87 88 if (off < 0) 89 panic("cuio_copyback: off %d < 0", off); 90 if (len < 0) 91 panic("cuio_copyback: len %d < 0", len); 92 while (off > 0) { 93 if (iol == 0) { 94#ifdef DEBUG 95 printf("cuio_copyback: empty in skip\n"); 96#endif 97 return; 98 } 99 if (off < iov->iov_len) 100 break; 101 off -= iov->iov_len; 102 iol--; 103 iov++; 104 } 105 while (len > 0) { 106 if (iol == 0) { 107#ifdef DEBUG 108 printf("uio_copyback: empty\n"); 109#endif 110 return; 111 } 112 count = uimin(iov->iov_len - off, len); 113 memcpy((char *)iov->iov_base + off, cp, count); 114 len -= count; 115 cp = (char *)cp + count; 116 off = 0; 117 iol--; 118 iov++; 119 } 120} 121 122/* 123 * Return a pointer to iov/offset of location in iovec list. 124 */ 125 126int 127cuio_getptr(struct uio *uio, int loc, int *off) 128{ 129 int ind, len; 130 131 ind = 0; 132 while (loc >= 0 && ind < uio->uio_iovcnt) { 133 len = uio->uio_iov[ind].iov_len; 134 if (len > loc) { 135 *off = loc; 136 return (ind); 137 } 138 loc -= len; 139 ind++; 140 } 141 142 if (ind > 0 && loc == 0) { 143 ind--; 144 *off = uio->uio_iov[ind].iov_len; 145 return (ind); 146 } 147 148 return (-1); 149} 150 151int 152cuio_apply(struct uio *uio, int off, int len, 153 int (*f)(void *, void *, unsigned int), void *fstate) 154{ 155 int rval, ind, uiolen; 156 unsigned int count; 157 158 if (len < 0) 159 panic("%s: len %d < 0", __func__, len); 160 if (off < 0) 161 panic("%s: off %d < 0", __func__, off); 162 163 ind = 0; 164 while (off > 0) { 165 if (ind >= uio->uio_iovcnt) 166 panic("cuio_apply: out of ivecs before data in uio"); 167 uiolen = uio->uio_iov[ind].iov_len; 168 if (off < uiolen) 169 break; 170 off -= uiolen; 171 ind++; 172 } 173 while (len > 0) { 174 if (ind >= uio->uio_iovcnt) 175 panic("cuio_apply: out of ivecs when processing uio"); 176 count = uimin(uio->uio_iov[ind].iov_len - off, len); 177 178 rval = f(fstate, 179 ((char *)uio->uio_iov[ind].iov_base + off), count); 180 if (rval) 181 return (rval); 182 183 len -= count; 184 off = 0; 185 ind++; 186 } 187 188 return (0); 189} 190