]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_subr.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / kern / kern_subr.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
8f6c56a5 11 *
6601e61a
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
21 */
22/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23/*
24 * Copyright (c) 1982, 1986, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
61 */
62
63#include <sys/param.h>
64#include <sys/systm.h>
91447636 65#include <sys/proc_internal.h>
1c79356b
A
66#include <sys/malloc.h>
67#include <sys/queue.h>
55e303ae 68#include <vm/pmap.h>
91447636
A
69#include <sys/uio_internal.h>
70#include <kern/kalloc.h>
1c79356b
A
71
72#include <kdebug.h>
73
74#include <sys/kdebug.h>
75#define DBG_UIO_COPYOUT 16
76#define DBG_UIO_COPYIN 17
77
91447636
A
78#if DEBUG
79#include <kern/simple_lock.h>
80
81static int uio_t_count = 0;
82#endif /* DEBUG */
83
de355530 84
1c79356b
A
85int
86uiomove(cp, n, uio)
87 register caddr_t cp;
88 register int n;
91447636 89 register uio_t uio;
55e303ae
A
90{
91 return uiomove64((addr64_t)((unsigned int)cp), n, uio);
92}
93
91447636 94 // LP64todo - fix this! 'n' should be int64_t?
55e303ae 95int
91447636 96uiomove64(addr64_t cp, int n, register struct uio *uio)
1c79356b 97{
91447636
A
98#if LP64KERN
99 register uint64_t acnt;
100#else
101 register u_int acnt;
102#endif
1c79356b
A
103 int error = 0;
104
105#if DIAGNOSTIC
106 if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
107 panic("uiomove: mode");
1c79356b
A
108#endif
109
91447636
A
110#if LP64_DEBUG
111 if (IS_VALID_UIO_SEGFLG(uio->uio_segflg) == 0) {
112 panic("%s :%d - invalid uio_segflg\n", __FILE__, __LINE__);
113 }
114#endif /* LP64_DEBUG */
115
116 while (n > 0 && uio_resid(uio)) {
117 acnt = uio_iov_len(uio);
118 if (acnt == 0) {
119 uio_next_iov(uio);
1c79356b
A
120 uio->uio_iovcnt--;
121 continue;
122 }
91447636
A
123 if (n > 0 && acnt > (uint64_t)n)
124 acnt = n;
125
1c79356b
A
126 switch (uio->uio_segflg) {
127
91447636
A
128 case UIO_USERSPACE64:
129 case UIO_USERISPACE64:
130 // LP64 - 3rd argument in debug code is 64 bit, expected to be 32 bit
131 if (uio->uio_rw == UIO_READ)
132 {
133 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
134 (int)cp, (int)uio->uio_iovs.iov64p->iov_base, acnt, 0,0);
135
136 error = copyout( CAST_DOWN(caddr_t, cp), uio->uio_iovs.iov64p->iov_base, acnt );
137
138 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
139 (int)cp, (int)uio->uio_iovs.iov64p->iov_base, acnt, 0,0);
140 }
141 else
142 {
143 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
144 (int)uio->uio_iovs.iov64p->iov_base, (int)cp, acnt, 0,0);
145
146 error = copyin(uio->uio_iovs.iov64p->iov_base, CAST_DOWN(caddr_t, cp), acnt);
147
148 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
149 (int)uio->uio_iovs.iov64p->iov_base, (int)cp, acnt, 0,0);
150 }
151 if (error)
152 return (error);
153 break;
154
155 case UIO_USERSPACE32:
156 case UIO_USERISPACE32:
1c79356b
A
157 case UIO_USERSPACE:
158 case UIO_USERISPACE:
159 if (uio->uio_rw == UIO_READ)
160 {
161 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
91447636 162 (int)cp, (int)uio->uio_iovs.iov32p->iov_base, acnt, 0,0);
1c79356b 163
91447636 164 error = copyout( CAST_DOWN(caddr_t, cp), CAST_USER_ADDR_T(uio->uio_iovs.iov32p->iov_base), acnt );
1c79356b
A
165
166 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
91447636 167 (int)cp, (int)uio->uio_iovs.iov32p->iov_base, acnt, 0,0);
1c79356b
A
168 }
169 else
170 {
171 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
91447636 172 (int)uio->uio_iovs.iov32p->iov_base, (int)cp, acnt, 0,0);
1c79356b 173
91447636 174 error = copyin(CAST_USER_ADDR_T(uio->uio_iovs.iov32p->iov_base), CAST_DOWN(caddr_t, cp), acnt);
1c79356b
A
175
176 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
91447636 177 (int)uio->uio_iovs.iov32p->iov_base, (int)cp, acnt, 0,0);
1c79356b
A
178 }
179 if (error)
180 return (error);
181 break;
182
91447636 183 case UIO_SYSSPACE32:
1c79356b
A
184 case UIO_SYSSPACE:
185 if (uio->uio_rw == UIO_READ)
91447636
A
186 error = copywithin(CAST_DOWN(caddr_t, cp), (caddr_t)uio->uio_iovs.iov32p->iov_base,
187 acnt);
1c79356b 188 else
91447636
A
189 error = copywithin((caddr_t)uio->uio_iovs.iov32p->iov_base, CAST_DOWN(caddr_t, cp),
190 acnt);
1c79356b 191 break;
9bccf70c 192
91447636
A
193 case UIO_PHYS_USERSPACE64:
194 if (uio->uio_rw == UIO_READ)
195 {
196 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
197 (int)cp, (int)uio->uio_iovs.iov64p->iov_base, acnt, 1,0);
198
199 error = copypv((addr64_t)cp, uio->uio_iovs.iov64p->iov_base, acnt, cppvPsrc | cppvNoRefSrc);
200 if (error) /* Copy physical to virtual */
201 error = EFAULT;
202
203 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
204 (int)cp, (int)uio->uio_iovs.iov64p->iov_base, acnt, 1,0);
205 }
206 else
207 {
208 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
209 (int)uio->uio_iovs.iov64p->iov_base, (int)cp, acnt, 1,0);
210
211 error = copypv(uio->uio_iovs.iov64p->iov_base, (addr64_t)cp, acnt, cppvPsnk | cppvNoRefSrc | cppvNoModSnk);
212 if (error) /* Copy virtual to physical */
213 error = EFAULT;
214
215 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
216 (int)uio->uio_iovs.iov64p->iov_base, (int)cp, acnt, 1,0);
217 }
218 if (error)
219 return (error);
220 break;
221
222 case UIO_PHYS_USERSPACE32:
1c79356b
A
223 case UIO_PHYS_USERSPACE:
224 if (uio->uio_rw == UIO_READ)
225 {
226 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
91447636 227 (int)cp, (int)uio->uio_iovs.iov32p->iov_base, acnt, 1,0);
55e303ae 228
91447636
A
229 error = copypv((addr64_t)cp, (addr64_t)uio->uio_iovs.iov32p->iov_base, acnt, cppvPsrc | cppvNoRefSrc);
230 if (error) /* Copy physical to virtual */
55e303ae
A
231 error = EFAULT;
232
233 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
91447636 234 (int)cp, (int)uio->uio_iovs.iov32p->iov_base, acnt, 1,0);
55e303ae
A
235 }
236 else
237 {
238 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
91447636 239 (int)uio->uio_iovs.iov32p->iov_base, (int)cp, acnt, 1,0);
1c79356b 240
91447636
A
241 error = copypv((addr64_t)uio->uio_iovs.iov32p->iov_base, (addr64_t)cp, acnt, cppvPsnk | cppvNoRefSrc | cppvNoModSnk);
242 if (error) /* Copy virtual to physical */
55e303ae
A
243 error = EFAULT;
244
245 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
91447636 246 (int)uio->uio_iovs.iov32p->iov_base, (int)cp, acnt, 1,0);
55e303ae
A
247 }
248 if (error)
249 return (error);
250 break;
251
91447636 252 case UIO_PHYS_SYSSPACE32:
55e303ae
A
253 case UIO_PHYS_SYSSPACE:
254 if (uio->uio_rw == UIO_READ)
255 {
256 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
91447636 257 (int)cp, (int)uio->uio_iovs.iov32p->iov_base, acnt, 2,0);
de355530 258
91447636
A
259 error = copypv((addr64_t)cp, uio->uio_iovs.iov32p->iov_base, acnt, cppvKmap | cppvPsrc | cppvNoRefSrc);
260 if (error) /* Copy physical to virtual */
55e303ae 261 error = EFAULT;
1c79356b
A
262
263 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
91447636 264 (int)cp, (int)uio->uio_iovs.iov32p->iov_base, acnt, 2,0);
1c79356b
A
265 }
266 else
267 {
268 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
91447636 269 (int)uio->uio_iovs.iov32p->iov_base, (int)cp, acnt, 2,0);
1c79356b 270
91447636
A
271 error = copypv(uio->uio_iovs.iov32p->iov_base, (addr64_t)cp, acnt, cppvKmap | cppvPsnk | cppvNoRefSrc | cppvNoModSnk);
272 if (error) /* Copy virtual to physical */
55e303ae 273 error = EFAULT;
1c79356b
A
274
275 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
91447636 276 (int)uio->uio_iovs.iov32p->iov_base, (int)cp, acnt, 2,0);
1c79356b
A
277 }
278 if (error)
279 return (error);
280 break;
91447636
A
281
282 default:
283 break;
1c79356b 284 }
91447636
A
285 uio_iov_base_add(uio, acnt);
286#if LP64KERN
287 uio_iov_len_add(uio, -((int64_t)acnt));
288 uio_setresid(uio, (uio_resid(uio) - ((int64_t)acnt)));
289#else
290 uio_iov_len_add(uio, -((int)acnt));
291 uio_setresid(uio, (uio_resid(uio) - ((int)acnt)));
292#endif
293 uio->uio_offset += acnt;
294 cp += acnt;
295 n -= acnt;
1c79356b
A
296 }
297 return (error);
298}
299
300/*
301 * Give next character to user as result of read.
302 */
303int
304ureadc(c, uio)
305 register int c;
306 register struct uio *uio;
307{
91447636 308 if (uio_resid(uio) <= 0)
1c79356b
A
309 panic("ureadc: non-positive resid");
310again:
311 if (uio->uio_iovcnt == 0)
312 panic("ureadc: non-positive iovcnt");
91447636 313 if (uio_iov_len(uio) <= 0) {
1c79356b 314 uio->uio_iovcnt--;
91447636 315 uio_next_iov(uio);
1c79356b
A
316 goto again;
317 }
318 switch (uio->uio_segflg) {
319
91447636 320 case UIO_USERSPACE32:
1c79356b 321 case UIO_USERSPACE:
91447636 322 if (subyte(CAST_USER_ADDR_T(uio->uio_iovs.iov32p->iov_base), c) < 0)
1c79356b
A
323 return (EFAULT);
324 break;
325
91447636
A
326 case UIO_USERSPACE64:
327 if (subyte((user_addr_t)uio->uio_iovs.iov64p->iov_base, c) < 0)
328 return (EFAULT);
329 break;
330
331 case UIO_SYSSPACE32:
1c79356b 332 case UIO_SYSSPACE:
91447636 333 *((caddr_t)uio->uio_iovs.iov32p->iov_base) = c;
1c79356b
A
334 break;
335
91447636 336 case UIO_USERISPACE32:
1c79356b 337 case UIO_USERISPACE:
91447636 338 if (suibyte(CAST_USER_ADDR_T(uio->uio_iovs.iov32p->iov_base), c) < 0)
1c79356b
A
339 return (EFAULT);
340 break;
91447636
A
341
342 default:
343 break;
1c79356b 344 }
91447636
A
345 uio_iov_base_add(uio, 1);
346 uio_iov_len_add(uio, -1);
347 uio_setresid(uio, (uio_resid(uio) - 1));
1c79356b
A
348 uio->uio_offset++;
349 return (0);
350}
351
352#if defined(vax) || defined(ppc)
353/* unused except by ct.c, other oddities XXX */
354/*
355 * Get next character written in by user from uio.
356 */
91447636 357int
1c79356b 358uwritec(uio)
91447636 359 uio_t uio;
1c79356b 360{
91447636 361 register int c = 0;
1c79356b 362
91447636 363 if (uio_resid(uio) <= 0)
1c79356b
A
364 return (-1);
365again:
366 if (uio->uio_iovcnt <= 0)
367 panic("uwritec: non-positive iovcnt");
91447636
A
368
369 if (uio_iov_len(uio) == 0) {
370 uio_next_iov(uio);
1c79356b
A
371 if (--uio->uio_iovcnt == 0)
372 return (-1);
373 goto again;
374 }
375 switch (uio->uio_segflg) {
376
91447636 377 case UIO_USERSPACE32:
1c79356b 378 case UIO_USERSPACE:
91447636 379 c = fubyte(CAST_USER_ADDR_T(uio->uio_iovs.iov32p->iov_base));
1c79356b
A
380 break;
381
91447636
A
382 case UIO_USERSPACE64:
383 c = fubyte((user_addr_t)uio->uio_iovs.iov64p->iov_base);
384 break;
385
386 case UIO_SYSSPACE32:
1c79356b 387 case UIO_SYSSPACE:
91447636 388 c = *((caddr_t)uio->uio_iovs.iov32p->iov_base) & 0377;
1c79356b
A
389 break;
390
91447636 391 case UIO_USERISPACE32:
1c79356b 392 case UIO_USERISPACE:
91447636 393 c = fuibyte(CAST_USER_ADDR_T(uio->uio_iovs.iov32p->iov_base));
1c79356b
A
394 break;
395
396 default:
397 c = 0; /* avoid uninitialized variable warning */
398 panic("uwritec: bogus uio_segflg");
399 break;
400 }
401 if (c < 0)
402 return (-1);
91447636
A
403 uio_iov_base_add(uio, 1);
404 uio_iov_len_add(uio, -1);
405 uio_setresid(uio, (uio_resid(uio) - 1));
1c79356b
A
406 uio->uio_offset++;
407 return (c);
408}
409#endif /* vax || ppc */
410
411/*
412 * General routine to allocate a hash table.
413 */
414void *
415hashinit(elements, type, hashmask)
416 int elements, type;
417 u_long *hashmask;
418{
419 long hashsize;
420 LIST_HEAD(generic, generic) *hashtbl;
421 int i;
422
423 if (elements <= 0)
424 panic("hashinit: bad cnt");
425 for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
426 continue;
427 hashsize >>= 1;
428 MALLOC(hashtbl, struct generic *,
91447636
A
429 (u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK|M_ZERO);
430 if (hashtbl != NULL) {
431 for (i = 0; i < hashsize; i++)
432 LIST_INIT(&hashtbl[i]);
433 *hashmask = hashsize - 1;
434 }
1c79356b
A
435 return (hashtbl);
436}
91447636
A
437
438/*
439 * uio_resid - return the residual IO value for the given uio_t
440 */
441user_ssize_t uio_resid( uio_t a_uio )
442{
443#if DEBUG
444 if (a_uio == NULL) {
445 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
446 }
447/* if (IS_VALID_UIO_SEGFLG(a_uio->uio_segflg) == 0) { */
448/* panic("%s :%d - invalid uio_segflg\n", __FILE__, __LINE__); */
449/* } */
450#endif /* DEBUG */
451
452 /* return 0 if there are no active iovecs */
453 if (a_uio == NULL) {
454 return( 0 );
455 }
456
457 if (UIO_IS_64_BIT_SPACE(a_uio)) {
458#if 1 // LP64todo - remove this temp workaround once we go live with uio KPI
459 return( (user_ssize_t)a_uio->uio_resid );
460#else
461 return( a_uio->uio_resid_64 );
462#endif
463 }
464 return( (user_ssize_t)a_uio->uio_resid );
465}
466
467/*
468 * uio_setresid - set the residual IO value for the given uio_t
469 */
470void uio_setresid( uio_t a_uio, user_ssize_t a_value )
471{
472#if DEBUG
473 if (a_uio == NULL) {
474 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
475 }
476/* if (IS_VALID_UIO_SEGFLG(a_uio->uio_segflg) == 0) { */
477/* panic("%s :%d - invalid uio_segflg\n", __FILE__, __LINE__); */
478/* } */
479#endif /* DEBUG */
480
481 if (a_uio == NULL) {
482 return;
483 }
484
485 if (UIO_IS_64_BIT_SPACE(a_uio)) {
486#if 1 // LP64todo - remove this temp workaround once we go live with uio KPI
487 a_uio->uio_resid = (int)a_value;
488#else
489 a_uio->uio_resid_64 = a_value;
490#endif
491 }
492 else {
493 a_uio->uio_resid = (int)a_value;
494 }
495 return;
496}
497
498#if 0 // obsolete
499/*
500 * uio_proc_t - return the proc_t for the given uio_t
501 * WARNING - This call is going away. Find another way to get the proc_t!!
502 */
503__private_extern__ proc_t uio_proc_t( uio_t a_uio )
504{
505#if LP64_DEBUG
506 if (a_uio == NULL) {
507 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
508 }
509#endif /* LP64_DEBUG */
510
511 /* return 0 if there are no active iovecs */
512 if (a_uio == NULL) {
513 return( NULL );
514 }
515 return( a_uio->uio_procp );
516}
517
518/*
519 * uio_setproc_t - set the residual IO value for the given uio_t
520 * WARNING - This call is going away.
521 */
522__private_extern__ void uio_setproc_t( uio_t a_uio, proc_t a_proc_t )
523{
524 if (a_uio == NULL) {
525#if LP64_DEBUG
526 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
527#endif /* LP64_DEBUG */
528 return;
529 }
530
531 a_uio->uio_procp = a_proc_t;
532 return;
533}
534#endif // obsolete
535
536/*
537 * uio_curriovbase - return the base address of the current iovec associated
538 * with the given uio_t. May return 0.
539 */
540user_addr_t uio_curriovbase( uio_t a_uio )
541{
542#if LP64_DEBUG
543 if (a_uio == NULL) {
544 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
545 }
546#endif /* LP64_DEBUG */
547
548 if (a_uio == NULL || a_uio->uio_iovcnt < 1) {
549 return(0);
550 }
551
552 if (UIO_IS_64_BIT_SPACE(a_uio)) {
553 return(a_uio->uio_iovs.uiovp->iov_base);
554 }
555 return((user_addr_t)((uintptr_t)a_uio->uio_iovs.kiovp->iov_base));
556
557}
558
559/*
560 * uio_curriovlen - return the length value of the current iovec associated
561 * with the given uio_t.
562 */
563user_size_t uio_curriovlen( uio_t a_uio )
564{
565#if LP64_DEBUG
566 if (a_uio == NULL) {
567 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
568 }
569#endif /* LP64_DEBUG */
570
571 if (a_uio == NULL || a_uio->uio_iovcnt < 1) {
572 return(0);
573 }
574
575 if (UIO_IS_64_BIT_SPACE(a_uio)) {
576 return(a_uio->uio_iovs.uiovp->iov_len);
577 }
578 return((user_size_t)a_uio->uio_iovs.kiovp->iov_len);
579}
580
581/*
582 * uio_setcurriovlen - set the length value of the current iovec associated
583 * with the given uio_t.
584 */
585__private_extern__ void uio_setcurriovlen( uio_t a_uio, user_size_t a_value )
586{
587#if LP64_DEBUG
588 if (a_uio == NULL) {
589 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
590 }
591#endif /* LP64_DEBUG */
592
593 if (a_uio == NULL) {
594 return;
595 }
596
597 if (UIO_IS_64_BIT_SPACE(a_uio)) {
598 a_uio->uio_iovs.uiovp->iov_len = a_value;
599 }
600 else {
601#if LP64_DEBUG
602 if (a_value > 0xFFFFFFFFull) {
603 panic("%s :%d - invalid a_value\n", __FILE__, __LINE__);
604 }
605#endif /* LP64_DEBUG */
606 a_uio->uio_iovs.kiovp->iov_len = (size_t)a_value;
607 }
608 return;
609}
610
611/*
612 * uio_iovcnt - return count of active iovecs for the given uio_t
613 */
614int uio_iovcnt( uio_t a_uio )
615{
616#if LP64_DEBUG
617 if (a_uio == NULL) {
618 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
619 }
620#endif /* LP64_DEBUG */
621
622 if (a_uio == NULL) {
623 return(0);
624 }
625
626 return( a_uio->uio_iovcnt );
627}
628
629/*
630 * uio_offset - return the current offset value for the given uio_t
631 */
632off_t uio_offset( uio_t a_uio )
633{
634#if LP64_DEBUG
635 if (a_uio == NULL) {
636 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
637 }
638#endif /* LP64_DEBUG */
639
640 if (a_uio == NULL) {
641 return(0);
642 }
643 return( a_uio->uio_offset );
644}
645
646/*
647 * uio_setoffset - set the current offset value for the given uio_t
648 */
649void uio_setoffset( uio_t a_uio, off_t a_offset )
650{
651#if LP64_DEBUG
652 if (a_uio == NULL) {
653 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
654 }
655#endif /* LP64_DEBUG */
656
657 if (a_uio == NULL) {
658 return;
659 }
660 a_uio->uio_offset = a_offset;
661 return;
662}
663
664/*
665 * uio_rw - return the read / write flag for the given uio_t
666 */
667int uio_rw( uio_t a_uio )
668{
669#if LP64_DEBUG
670 if (a_uio == NULL) {
671 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
672 }
673#endif /* LP64_DEBUG */
674
675 if (a_uio == NULL) {
676 return(-1);
677 }
678 return( a_uio->uio_rw );
679}
680
681/*
682 * uio_setrw - set the read / write flag for the given uio_t
683 */
684void uio_setrw( uio_t a_uio, int a_value )
685{
686 if (a_uio == NULL) {
687#if LP64_DEBUG
688 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
689#endif /* LP64_DEBUG */
690 return;
691 }
692
693#if LP64_DEBUG
694 if (!(a_value == UIO_READ || a_value == UIO_WRITE)) {
695 panic("%s :%d - invalid a_value\n", __FILE__, __LINE__);
696 }
697#endif /* LP64_DEBUG */
698
699 if (a_value == UIO_READ || a_value == UIO_WRITE) {
700 a_uio->uio_rw = a_value;
701 }
702 return;
703}
704
705/*
706 * uio_isuserspace - return non zero value if the address space
707 * flag is for a user address space (could be 32 or 64 bit).
708 */
709int uio_isuserspace( uio_t a_uio )
710{
711 if (a_uio == NULL) {
712#if LP64_DEBUG
713 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
714#endif /* LP64_DEBUG */
715 return(0);
716 }
717
718 if (UIO_SEG_IS_USER_SPACE(a_uio->uio_segflg)) {
719 return( 1 );
720 }
721 return( 0 );
722}
723
724
725/*
726 * uio_create - create an uio_t.
727 * Space is allocated to hold up to a_iovcount number of iovecs. The uio_t
728 * is not fully initialized until all iovecs are added using uio_addiov calls.
729 * a_iovcount is the maximum number of iovecs you may add.
730 */
731uio_t uio_create( int a_iovcount, /* number of iovecs */
732 off_t a_offset, /* current offset */
733 int a_spacetype, /* type of address space */
734 int a_iodirection ) /* read or write flag */
735{
736 void * my_buf_p;
737 int my_size;
738 uio_t my_uio;
739
740 my_size = sizeof(struct uio) + (sizeof(struct user_iovec) * a_iovcount);
741 my_buf_p = kalloc(my_size);
742 my_uio = uio_createwithbuffer( a_iovcount,
743 a_offset,
744 a_spacetype,
745 a_iodirection,
746 my_buf_p,
747 my_size );
748 if (my_uio != 0) {
749 /* leave a note that we allocated this uio_t */
750 my_uio->uio_flags |= UIO_FLAGS_WE_ALLOCED;
751#if DEBUG
752 hw_atomic_add(&uio_t_count, 1);
753#endif
754 }
755
756 return( my_uio );
757}
758
759
760/*
761 * uio_createwithbuffer - create an uio_t.
762 * Create a uio_t using the given buffer. The uio_t
763 * is not fully initialized until all iovecs are added using uio_addiov calls.
764 * a_iovcount is the maximum number of iovecs you may add.
765 * This call may fail if the given buffer is not large enough.
766 */
767__private_extern__ uio_t
768 uio_createwithbuffer( int a_iovcount, /* number of iovecs */
769 off_t a_offset, /* current offset */
770 int a_spacetype, /* type of address space */
771 int a_iodirection, /* read or write flag */
772 void *a_buf_p, /* pointer to a uio_t buffer */
773 int a_buffer_size ) /* size of uio_t buffer */
774{
775 uio_t my_uio = (uio_t) a_buf_p;
776 int my_size;
777
778 my_size = sizeof(struct uio) + (sizeof(struct user_iovec) * a_iovcount);
779 if (a_buffer_size < my_size) {
780#if DEBUG
781 panic("%s :%d - a_buffer_size is too small\n", __FILE__, __LINE__);
782#endif /* DEBUG */
783 return( NULL );
784 }
785 my_size = a_buffer_size;
786
787#if DEBUG
788 if (my_uio == 0) {
789 panic("%s :%d - could not allocate uio_t\n", __FILE__, __LINE__);
790 }
791 if (!IS_VALID_UIO_SEGFLG(a_spacetype)) {
792 panic("%s :%d - invalid address space type\n", __FILE__, __LINE__);
793 }
794 if (!(a_iodirection == UIO_READ || a_iodirection == UIO_WRITE)) {
795 panic("%s :%d - invalid IO direction flag\n", __FILE__, __LINE__);
796 }
797 if (a_iovcount > UIO_MAXIOV) {
798 panic("%s :%d - invalid a_iovcount\n", __FILE__, __LINE__);
799 }
800#endif /* DEBUG */
801
802 bzero(my_uio, my_size);
803 my_uio->uio_size = my_size;
804
805 /* we use uio_segflg to indicate if the uio_t is the new format or */
806 /* old (pre LP64 support) legacy format */
807 switch (a_spacetype) {
808 case UIO_USERSPACE:
809 my_uio->uio_segflg = UIO_USERSPACE32;
810 case UIO_SYSSPACE:
811 my_uio->uio_segflg = UIO_SYSSPACE32;
812 case UIO_PHYS_USERSPACE:
813 my_uio->uio_segflg = UIO_PHYS_USERSPACE32;
814 case UIO_PHYS_SYSSPACE:
815 my_uio->uio_segflg = UIO_PHYS_SYSSPACE32;
816 default:
817 my_uio->uio_segflg = a_spacetype;
818 break;
819 }
820
821 if (a_iovcount > 0) {
822 my_uio->uio_iovs.uiovp = (struct user_iovec *)
823 (((uint8_t *)my_uio) + sizeof(struct uio));
824 }
825 else {
826 my_uio->uio_iovs.uiovp = NULL;
827 }
828
829 my_uio->uio_max_iovs = a_iovcount;
830 my_uio->uio_offset = a_offset;
831 my_uio->uio_rw = a_iodirection;
832 my_uio->uio_flags = UIO_FLAGS_INITED;
833
834 return( my_uio );
835}
836
837/*
838 * uio_spacetype - return the address space type for the given uio_t
839 */
840int uio_spacetype( uio_t a_uio )
841{
842 if (a_uio == NULL) {
843#if LP64_DEBUG
844 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
845#endif /* LP64_DEBUG */
846 return(-1);
847 }
848
849 return( a_uio->uio_segflg );
850}
851
852/*
853 * uio_iovsaddr - get the address of the iovec array for the given uio_t.
854 * This returns the location of the iovecs within the uio.
855 * NOTE - for compatibility mode we just return the current value in uio_iovs
856 * which will increase as the IO is completed and is NOT embedded within the
857 * uio, it is a seperate array of one or more iovecs.
858 */
859struct user_iovec * uio_iovsaddr( uio_t a_uio )
860{
861 struct user_iovec * my_addr;
862
863 if (a_uio == NULL) {
864 return(NULL);
865 }
866
867 if (a_uio->uio_segflg == UIO_USERSPACE || a_uio->uio_segflg == UIO_SYSSPACE) {
868 /* we need this for compatibility mode. */
869 my_addr = (struct user_iovec *) a_uio->uio_iovs.iovp;
870 }
871 else {
872 my_addr = (struct user_iovec *) (((uint8_t *)a_uio) + sizeof(struct uio));
873 }
874 return(my_addr);
875}
876
877/*
878 * uio_reset - reset an uio_t.
879 * Reset the given uio_t to initial values. The uio_t is not fully initialized
880 * until all iovecs are added using uio_addiov calls.
881 * The a_iovcount value passed in the uio_create is the maximum number of
882 * iovecs you may add.
883 */
884void uio_reset( uio_t a_uio,
885 off_t a_offset, /* current offset */
886 int a_spacetype, /* type of address space */
887 int a_iodirection ) /* read or write flag */
888{
889 vm_size_t my_size;
890 int my_max_iovs;
891 u_int32_t my_old_flags;
892
893#if LP64_DEBUG
894 if (a_uio == NULL) {
895 panic("%s :%d - could not allocate uio_t\n", __FILE__, __LINE__);
896 }
897 if (!IS_VALID_UIO_SEGFLG(a_spacetype)) {
898 panic("%s :%d - invalid address space type\n", __FILE__, __LINE__);
899 }
900 if (!(a_iodirection == UIO_READ || a_iodirection == UIO_WRITE)) {
901 panic("%s :%d - invalid IO direction flag\n", __FILE__, __LINE__);
902 }
903#endif /* LP64_DEBUG */
904
905 if (a_uio == NULL) {
906 return;
907 }
908
909 my_size = a_uio->uio_size;
910 my_old_flags = a_uio->uio_flags;
911 my_max_iovs = a_uio->uio_max_iovs;
912 bzero(a_uio, my_size);
913 a_uio->uio_size = my_size;
914 a_uio->uio_segflg = a_spacetype;
915 if (my_max_iovs > 0) {
916 a_uio->uio_iovs.uiovp = (struct user_iovec *)
917 (((uint8_t *)a_uio) + sizeof(struct uio));
918 }
919 else {
920 a_uio->uio_iovs.uiovp = NULL;
921 }
922 a_uio->uio_max_iovs = my_max_iovs;
923 a_uio->uio_offset = a_offset;
924 a_uio->uio_rw = a_iodirection;
925 a_uio->uio_flags = my_old_flags;
926
927 return;
928}
929
930/*
931 * uio_free - free a uio_t allocated via uio_init. this also frees all
932 * associated iovecs.
933 */
934void uio_free( uio_t a_uio )
935{
936#if DEBUG
937 if (a_uio == NULL) {
938 panic("%s :%d - passing NULL uio_t\n", __FILE__, __LINE__);
939 }
940#endif /* LP64_DEBUG */
941
942 if (a_uio != NULL && (a_uio->uio_flags & UIO_FLAGS_WE_ALLOCED) != 0) {
943#if DEBUG
944 if ((int)(hw_atomic_sub(&uio_t_count, 1)) < 0) {
945 panic("%s :%d - uio_t_count has gone negative\n", __FILE__, __LINE__);
946 }
947#endif
948 kfree(a_uio, a_uio->uio_size);
949 }
950
951
952}
953
954/*
955 * uio_addiov - add an iovec to the given uio_t. You may call this up to
956 * the a_iovcount number that was passed to uio_create. This call will
957 * increment the residual IO count as iovecs are added to the uio_t.
958 * returns 0 if add was successful else non zero.
959 */
960int uio_addiov( uio_t a_uio, user_addr_t a_baseaddr, user_size_t a_length )
961{
962 int i;
963
964 if (a_uio == NULL) {
965#if DEBUG
966 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
967#endif /* LP64_DEBUG */
968 return(-1);
969 }
970
971 if (UIO_IS_64_BIT_SPACE(a_uio)) {
972 for ( i = 0; i < a_uio->uio_max_iovs; i++ ) {
973 if (a_uio->uio_iovs.uiovp[i].iov_len == 0 && a_uio->uio_iovs.uiovp[i].iov_base == 0) {
974 a_uio->uio_iovs.uiovp[i].iov_len = a_length;
975 a_uio->uio_iovs.uiovp[i].iov_base = a_baseaddr;
976 a_uio->uio_iovcnt++;
977#if 1 // LP64todo - remove this temp workaround once we go live with uio KPI
978 a_uio->uio_resid += a_length;
979#else
980 a_uio->uio_resid_64 += a_length;
981#endif
982 return( 0 );
983 }
984 }
985 }
986 else {
987 for ( i = 0; i < a_uio->uio_max_iovs; i++ ) {
988 if (a_uio->uio_iovs.kiovp[i].iov_len == 0 && a_uio->uio_iovs.kiovp[i].iov_base == 0) {
989 a_uio->uio_iovs.kiovp[i].iov_len = (u_int32_t)a_length;
990 a_uio->uio_iovs.kiovp[i].iov_base = (u_int32_t)((uintptr_t)a_baseaddr);
991 a_uio->uio_iovcnt++;
992 a_uio->uio_resid += a_length;
993 return( 0 );
994 }
995 }
996 }
997
998 return( -1 );
999}
1000
1001/*
1002 * uio_getiov - get iovec data associated with the given uio_t. Use
1003 * a_index to iterate over each iovec (0 to (uio_iovcnt(uio_t) - 1)).
1004 * a_baseaddr_p and a_length_p may be NULL.
1005 * returns -1 when a_index is >= uio_t.uio_iovcnt or invalid uio_t.
1006 * returns 0 when data is returned.
1007 */
1008int uio_getiov( uio_t a_uio,
1009 int a_index,
1010 user_addr_t * a_baseaddr_p,
1011 user_size_t * a_length_p )
1012{
1013 if (a_uio == NULL) {
1014#if DEBUG
1015 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
1016#endif /* DEBUG */
1017 return(-1);
1018 }
1019 if ( a_index < 0 || a_index >= a_uio->uio_iovcnt) {
1020 return(-1);
1021 }
1022
1023 if (UIO_IS_64_BIT_SPACE(a_uio)) {
1024 if (a_baseaddr_p != NULL) {
1025 *a_baseaddr_p = a_uio->uio_iovs.uiovp[a_index].iov_base;
1026 }
1027 if (a_length_p != NULL) {
1028 *a_length_p = a_uio->uio_iovs.uiovp[a_index].iov_len;
1029 }
1030 }
1031 else {
1032 if (a_baseaddr_p != NULL) {
1033 *a_baseaddr_p = a_uio->uio_iovs.kiovp[a_index].iov_base;
1034 }
1035 if (a_length_p != NULL) {
1036 *a_length_p = a_uio->uio_iovs.kiovp[a_index].iov_len;
1037 }
1038 }
1039
1040 return( 0 );
1041}
1042
1043/*
1044 * uio_calculateresid - runs through all iovecs associated with this
1045 * uio_t and calculates (and sets) the residual IO count.
1046 */
1047__private_extern__ void uio_calculateresid( uio_t a_uio )
1048{
1049 int i;
1050
1051 if (a_uio == NULL) {
1052#if LP64_DEBUG
1053 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
1054#endif /* LP64_DEBUG */
1055 return;
1056 }
1057
743b1565 1058 a_uio->uio_iovcnt = a_uio->uio_max_iovs;
91447636
A
1059 if (UIO_IS_64_BIT_SPACE(a_uio)) {
1060#if 1 // LP64todo - remove this temp workaround once we go live with uio KPI
1061 a_uio->uio_resid = 0;
1062#else
1063 a_uio->uio_resid_64 = 0;
1064#endif
1065 for ( i = 0; i < a_uio->uio_max_iovs; i++ ) {
1066 if (a_uio->uio_iovs.uiovp[i].iov_len != 0 && a_uio->uio_iovs.uiovp[i].iov_base != 0) {
91447636
A
1067#if 1 // LP64todo - remove this temp workaround once we go live with uio KPI
1068 a_uio->uio_resid += a_uio->uio_iovs.uiovp[i].iov_len;
1069#else
1070 a_uio->uio_resid_64 += a_uio->uio_iovs.uiovp[i].iov_len;
1071#endif
1072 }
1073 }
743b1565
A
1074
1075 /* position to first non zero length iovec (4235922) */
1076 while (a_uio->uio_iovcnt > 0 && a_uio->uio_iovs.uiovp->iov_len == 0) {
1077 a_uio->uio_iovcnt--;
1078 if (a_uio->uio_iovcnt > 0) {
1079 a_uio->uio_iovs.uiovp++;
1080 }
1081 }
91447636
A
1082 }
1083 else {
1084 a_uio->uio_resid = 0;
1085 for ( i = 0; i < a_uio->uio_max_iovs; i++ ) {
1086 if (a_uio->uio_iovs.kiovp[i].iov_len != 0 && a_uio->uio_iovs.kiovp[i].iov_base != 0) {
91447636
A
1087 a_uio->uio_resid += a_uio->uio_iovs.kiovp[i].iov_len;
1088 }
1089 }
743b1565
A
1090
1091 /* position to first non zero length iovec (4235922) */
1092 while (a_uio->uio_iovcnt > 0 && a_uio->uio_iovs.kiovp->iov_len == 0) {
1093 a_uio->uio_iovcnt--;
1094 if (a_uio->uio_iovcnt > 0) {
1095 a_uio->uio_iovs.kiovp++;
1096 }
1097 }
91447636 1098 }
743b1565 1099
91447636
A
1100 return;
1101}
1102
1103/*
1104 * uio_update - update the given uio_t for a_count of completed IO.
1105 * This call decrements the current iovec length and residual IO value
1106 * and increments the current iovec base address and offset value.
1107 * If the current iovec length is 0 then advance to the next
1108 * iovec (if any).
cc9f6e38
A
1109 * If the a_count passed in is 0, than only do the advancement
1110 * over any 0 length iovec's.
91447636
A
1111 */
1112void uio_update( uio_t a_uio, user_size_t a_count )
1113{
1114#if LP64_DEBUG
1115 if (a_uio == NULL) {
1116 panic("%s :%d - invalid uio_t\n", __FILE__, __LINE__);
1117 }
1118 if (UIO_IS_32_BIT_SPACE(a_uio) && a_count > 0xFFFFFFFFull) {
1119 panic("%s :%d - invalid count value \n", __FILE__, __LINE__);
1120 }
1121#endif /* LP64_DEBUG */
1122
1123 if (a_uio == NULL || a_uio->uio_iovcnt < 1) {
1124 return;
1125 }
1126
1127 if (UIO_IS_64_BIT_SPACE(a_uio)) {
cc9f6e38
A
1128 /*
1129 * if a_count == 0, then we are asking to skip over
1130 * any empty iovs
1131 */
1132 if (a_count) {
1133 if (a_count > a_uio->uio_iovs.uiovp->iov_len) {
1134 a_uio->uio_iovs.uiovp->iov_base += a_uio->uio_iovs.uiovp->iov_len;
1135 a_uio->uio_iovs.uiovp->iov_len = 0;
1136 }
1137 else {
1138 a_uio->uio_iovs.uiovp->iov_base += a_count;
1139 a_uio->uio_iovs.uiovp->iov_len -= a_count;
1140 }
91447636 1141#if 1 // LP64todo - remove this temp workaround once we go live with uio KPI
cc9f6e38
A
1142 if (a_uio->uio_resid < 0) {
1143 a_uio->uio_resid = 0;
1144 }
1145 if (a_count > (user_size_t)a_uio->uio_resid) {
1146 a_uio->uio_offset += a_uio->uio_resid;
1147 a_uio->uio_resid = 0;
1148 }
1149 else {
1150 a_uio->uio_offset += a_count;
1151 a_uio->uio_resid -= a_count;
1152 }
91447636 1153#else
cc9f6e38
A
1154 if (a_uio->uio_resid_64 < 0) {
1155 a_uio->uio_resid_64 = 0;
1156 }
1157 if (a_count > (user_size_t)a_uio->uio_resid_64) {
1158 a_uio->uio_offset += a_uio->uio_resid_64;
1159 a_uio->uio_resid_64 = 0;
1160 }
1161 else {
1162 a_uio->uio_offset += a_count;
1163 a_uio->uio_resid_64 -= a_count;
1164 }
91447636 1165#endif // LP64todo
cc9f6e38
A
1166 }
1167 /*
1168 * advance to next iovec if current one is totally consumed
1169 */
1170 while (a_uio->uio_iovcnt > 0 && a_uio->uio_iovs.uiovp->iov_len == 0) {
91447636
A
1171 a_uio->uio_iovcnt--;
1172 if (a_uio->uio_iovcnt > 0) {
1173 a_uio->uio_iovs.uiovp++;
1174 }
1175 }
1176 }
1177 else {
cc9f6e38
A
1178 /*
1179 * if a_count == 0, then we are asking to skip over
1180 * any empty iovs
1181 */
1182 if (a_count) {
1183 if (a_count > a_uio->uio_iovs.kiovp->iov_len) {
1184 a_uio->uio_iovs.kiovp->iov_base += a_uio->uio_iovs.kiovp->iov_len;
1185 a_uio->uio_iovs.kiovp->iov_len = 0;
1186 }
1187 else {
1188 a_uio->uio_iovs.kiovp->iov_base += a_count;
1189 a_uio->uio_iovs.kiovp->iov_len -= a_count;
1190 }
1191 if (a_uio->uio_resid < 0) {
1192 a_uio->uio_resid = 0;
1193 }
1194 if (a_count > (user_size_t)a_uio->uio_resid) {
1195 a_uio->uio_offset += a_uio->uio_resid;
1196 a_uio->uio_resid = 0;
1197 }
1198 else {
1199 a_uio->uio_offset += a_count;
1200 a_uio->uio_resid -= a_count;
1201 }
91447636 1202 }
cc9f6e38
A
1203 /*
1204 * advance to next iovec if current one is totally consumed
1205 */
1206 while (a_uio->uio_iovcnt > 0 && a_uio->uio_iovs.kiovp->iov_len == 0) {
91447636
A
1207 a_uio->uio_iovcnt--;
1208 if (a_uio->uio_iovcnt > 0) {
1209 a_uio->uio_iovs.kiovp++;
1210 }
1211 }
1212 }
1213 return;
1214}
1215
1216
1217/*
1218 * uio_duplicate - allocate a new uio and make a copy of the given uio_t.
1219 * may return NULL.
1220 */
1221uio_t uio_duplicate( uio_t a_uio )
1222{
1223 uio_t my_uio;
1224 int i;
1225
1226 if (a_uio == NULL) {
1227 return(NULL);
1228 }
1229
1230 my_uio = (uio_t) kalloc(a_uio->uio_size);
1231 if (my_uio == 0) {
1232 panic("%s :%d - allocation failed\n", __FILE__, __LINE__);
1233 }
1234
1235 bcopy((void *)a_uio, (void *)my_uio, a_uio->uio_size);
1236 /* need to set our iovec pointer to point to first active iovec */
1237 if (my_uio->uio_max_iovs > 0) {
1238 my_uio->uio_iovs.uiovp = (struct user_iovec *)
1239 (((uint8_t *)my_uio) + sizeof(struct uio));
1240
1241 /* advance to first nonzero iovec */
1242 if (my_uio->uio_iovcnt > 0) {
1243 for ( i = 0; i < my_uio->uio_max_iovs; i++ ) {
1244 if (UIO_IS_64_BIT_SPACE(a_uio)) {
1245 if (my_uio->uio_iovs.uiovp->iov_len != 0) {
1246 break;
1247 }
1248 my_uio->uio_iovs.uiovp++;
1249 }
1250 else {
1251 if (my_uio->uio_iovs.kiovp->iov_len != 0) {
1252 break;
1253 }
1254 my_uio->uio_iovs.kiovp++;
1255 }
1256 }
1257 }
1258 }
1259
1260 return(my_uio);
1261}
1262