|
|
1.1 ! root 1: #define _DDI_DKI 1 ! 2: #define _SYSV3 1 ! 3: ! 4: /* ! 5: * Implementations of the functions which manipulate the uio(4) structure ! 6: * under the DDI/DKI. This function runs in _SYSV3 mode to interface with ! 7: * the iBCS2 Coherent kernel. ! 8: */ ! 9: /* ! 10: *-IMPORTS: ! 11: * <common/ccompat.h> ! 12: * __CONST__ ! 13: * __EXTERN_C_BEGIN__ ! 14: * __EXTERN_C_END__ ! 15: * __USE_PROTO__ ! 16: * __ARGS () ! 17: * __PROTO () ! 18: * <sys/debug.h> ! 19: * ASSERT () ! 20: * <sys/types.h> ! 21: * _VOID ! 22: * size_t ! 23: * <sys/errno.h> ! 24: * EFAULT ! 25: * <limits.h> ! 26: * CHAR_BIT ! 27: * UCHAR_MAX ! 28: * <string.h> ! 29: * memcpy () ! 30: */ ! 31: ! 32: #include <common/ccompat.h> ! 33: #include <sys/debug.h> ! 34: #include <sys/types.h> ! 35: #include <sys/errno.h> ! 36: #include <limits.h> ! 37: #include <string.h> ! 38: ! 39: #include <sys/uio.h> ! 40: ! 41: #if __COHERENT__ ! 42: ! 43: #include <sys/coherent.h> ! 44: ! 45: ! 46: /* ! 47: * Routines to perform transfers between the user and kernel address spaces. ! 48: */ ! 49: ! 50: __EXTERN_C_BEGIN__ ! 51: ! 52: int kucopy __PROTO ((__CONST__ caddr_t ker, caddr_t usr, ! 53: size_t n)); ! 54: int ukcopy __PROTO ((__CONST__ caddr_t usr, caddr_t ker, ! 55: size_t n)); ! 56: int getubd __PROTO ((__CONST__ caddr_t usr)); ! 57: void putubd __PROTO ((caddr_t usr, int ch)); ! 58: ! 59: __EXTERN_C_END__ ! 60: ! 61: #define TOUSER(usr,ker,n) kucopy ((caddr_t) ker, (caddr_t) usr, n) ! 62: #define FROMUSER(ker,usr,n) ukcopy ((caddr_t) usr, (caddr_t) ker, n) ! 63: ! 64: #define PUTBYTE(c,usr) (putubd (usr, c), u.u_error) ! 65: #define GETBYTE(usr) ((unsigned char) getubd (usr) - \ ! 66: (u.u_error > 0 ? UCHAR_MAX : 0)) ! 67: ! 68: #else /* if ! defined (COHERENT) */ ! 69: ! 70: ! 71: #define TOUSER(usr,ker,n) (memcpy ((usr), (ker), (n)), (n)) ! 72: #define FROMUSER(ker,usr,n) (memcpy ((ker), (usr), (n)), (n)) ! 73: ! 74: #define PUTBYTE(c,usr) (* (usr) = (c), 0) ! 75: #define GETBYTE(usr) (* (unsigned char *) (usr)) ! 76: ! 77: ! 78: #endif ! 79: ! 80: ! 81: /* ! 82: * For some reason the System V DDI/DKI uses "longs" and "ints" in many cases ! 83: * where a size_t is far more appropriate. We will only work for cases where ! 84: * the request does not exceed the half range of a size_t. ! 85: */ ! 86: ! 87: #define SIZE_T_MAX ((1UL << (sizeof (size_t) * CHAR_BIT - 1)) - 1) ! 88: ! 89: ! 90: /* ! 91: *-STATUS: ! 92: * DDI/DKI ! 93: * ! 94: *-NAME: ! 95: * bcopy Copy data between address locations in the kernel. ! 96: * ! 97: *-SYNOPSIS: ! 98: * #include <sys/types.h> ! 99: * ! 100: * void bcopy (caddr_t from, caddr_t to, size_t bcount); ! 101: * ! 102: *-ARGUMENTS: ! 103: * from Source address from which the copy is made. ! 104: * ! 105: * to Destination address to which the copy is made. ! 106: * ! 107: * bcount Number of bytes to be copied. ! 108: * ! 109: *-DESCRIPTION: ! 110: * bcopy () copies "bcount" bytes from one kernel address to another. It ! 111: * chooses the best algorithm based on address alignment and number of ! 112: * bytes to copy. If the input and output addresses over, the function ! 113: * executes, but the results are undefined. ! 114: * ! 115: *-RETURN VALUE: ! 116: * None. ! 117: * ! 118: *-LEVEL: ! 119: * Base or interrupt. ! 120: * ! 121: *-NOTES: ! 122: * Does not sleep. ! 123: * ! 124: * Driver-defined basic locks, read/write locks, and sleep locks may be ! 125: * held across calls to this function. ! 126: * ! 127: * The source and destination address ranges must both be within the ! 128: * kernel address space and must be memory resident. No range checking is ! 129: * done. Since there is no mechanism by which drivers that conform to the ! 130: * rules of the DDI/DKI can obtain and use a kernel address which is not ! 131: * memory resident (an address which is paged out), DDI/DKI conforming ! 132: * drivers can assume that any address to which they have access is ! 133: * memory resident and therefore a valid argument to bcopy (). Addresses ! 134: * within user space are not valid arguments, and specifying such an ! 135: * address may cause the driver to corrupt the system in an unpredictable ! 136: * way. For copying between kernel and user space, drivers must use an ! 137: * appropriate function defined for that purpose (for example, copyin (), ! 138: * copyout (), uiomove (), ureadc (), or uwritec ()). ! 139: * ! 140: *-SEE ALSO: ! 141: * bzero (), copyin (), copyout (), uiomove (), ureadc (), uwritec () ! 142: */ ! 143: ! 144: #if __USE_PROTO__ ! 145: void (bcopy) (__CONST__ _VOID * from, _VOID * to, size_t bcount) ! 146: #else ! 147: void ! 148: bcopy __ARGS ((from, to, bcount)) ! 149: __CONST__ _VOID ! 150: * from; ! 151: _VOID * to; ! 152: size_t bcount; ! 153: #endif ! 154: { ! 155: ASSERT (to != NULL); ! 156: ! 157: (void) memcpy (to, from, bcount); ! 158: } ! 159: ! 160: ! 161: /* ! 162: *-STATUS: ! 163: * DDI/DKI ! 164: * ! 165: *-NAME: ! 166: * bzero Clear memory for a given number of bytes. ! 167: * ! 168: *-SYNOPSIS: ! 169: * #include <sys/types.h> ! 170: * ! 171: * void bzero (caddr_t addr, size_t bytes); ! 172: * ! 173: *-ARGUMENTS: ! 174: * addr Starting virtual address of memory to be cleared. ! 175: * ! 176: * bytes Number of bytes to clear. ! 177: * ! 178: *-DESCRIPTION: ! 179: * The bzero () function clears a contiguous portion of memory by filling ! 180: * the memory with zeroes. It chooses the best algorithm based on address ! 181: * alignment and number of bytes to clear. ! 182: * ! 183: *-RETURN VALUE: ! 184: * None. ! 185: * ! 186: *-LEVEL: ! 187: * Base or interrupt. ! 188: * ! 189: *-NOTES: ! 190: * Does not sleep. ! 191: * ! 192: * Driver-defined basic locks, read/write locks, and sleep locks may be ! 193: * held across calls to this function. ! 194: * ! 195: * There are no alignment restrictions on "addr", and no length ! 196: * restrictions on "bytes", other than the address range specified must ! 197: * be within the kernel address space and must be memory resident. No ! 198: * range checking is done. Since there is no mechanism by which drivers ! 199: * that conform to the rules of the DDI/DKI can obtain and use a kernel ! 200: * address that is not memory resident (an address that is paged out), ! 201: * DDI/DKI conforming drivers can assume that any address to which they ! 202: * have access is memory resident and therefore a valid argument to ! 203: * bzero (). An address within user space is not a valid argument to ! 204: * bzero (), and specifying such an address may cause the driver to ! 205: * corrupt the system in an unpredictable way. ! 206: * ! 207: *-SEE ALSO: ! 208: * bcopy (), kmem_zalloc () ! 209: */ ! 210: ! 211: #if __USE_PROTO__ ! 212: void (bzero) (_VOID * addr, size_t bytes) ! 213: #else ! 214: void ! 215: bzero __ARGS ((addr, bytes)) ! 216: _VOID * addr; ! 217: size_t bytes; ! 218: #endif ! 219: { ! 220: ASSERT (addr != NULL); ! 221: ! 222: (void) memset (addr, 0, bytes); ! 223: } ! 224: ! 225: ! 226: /* ! 227: *-STATUS: ! 228: * DDI/DKI ! 229: * ! 230: *-NAME: ! 231: * copyin Copy data from a user buffer to a driver buffer. ! 232: * ! 233: *-SYNOPSIS: ! 234: * #include <sys/types.h> ! 235: * ! 236: * int copyin (caddr_t userbuf, caddr_t driverbuf, size_t count); ! 237: * ! 238: *-ARGUMENTS: ! 239: * userbuf User source address from which copy is made. ! 240: * ! 241: * driverbuf Driver destination address to which copy is made. ! 242: * ! 243: * count Number of bytes to copy. ! 244: * ! 245: *-DESCRIPTION: ! 246: * copyin () copies "count" bytes of data from the user virtual address ! 247: * specified by "userbuf" to the kernel virtual address specified by ! 248: * "driverbuf". The driver must ensure that adequate space is allocated ! 249: * for the destination address. ! 250: * ! 251: * copyin () chooses the best algorithm based on address alignment and ! 252: * number of bytes to copy. Although the source and destination addresses ! 253: * are not required to be word aligned, word aligned addresses may result ! 254: * in a more efficient copy. ! 255: * ! 256: *-RETURN VALUE: ! 257: * If the copy is successful, 0 is returned. Otherwise, -1 is returned to ! 258: * indicate the specified user address range is invalid. ! 259: * ! 260: *-LEVEL: ! 261: * Base only. ! 262: * ! 263: *-NOTES: ! 264: * May sleep. ! 265: * ! 266: * Drivers usually convert a return value of -1 to an EFAULT error. ! 267: * ! 268: * Driver-defined basic locks and read/write locks may not be held across ! 269: * calls to this function. ! 270: * ! 271: * Driver-defined sleep locks may be held across calls to this function. ! 272: * ! 273: * When holding sleep locks across calls to this function, drivers must ! 274: * be careful to avoid creating a deadlock. During the data transfer, ! 275: * page fault resolution might result in another I/O to the same device. ! 276: * For example, this could occur if the driver controls the disk drive ! 277: * used as the swap device. ! 278: * ! 279: * The driver destination buffer must be completely within the kernel ! 280: * address space, or the system can panic. ! 281: * ! 282: *-SEE ALSO: ! 283: * copyout (), uiomove (), ureadc (), uwritec () ! 284: */ ! 285: ! 286: #if __USE_PROTO__ ! 287: int (copyin) (_VOID * userbuf, _VOID * driverbuf, size_t count) ! 288: #else ! 289: int ! 290: copyin __ARGS ((userbuf, driverbuf, count)) ! 291: _VOID * userbuf; ! 292: _VOID * driverbuf; ! 293: size_t count; ! 294: #endif ! 295: { ! 296: ASSERT (driverbuf != 0); ! 297: ! 298: return FROMUSER (driverbuf, userbuf, count) != count ? -1 : 0; ! 299: } ! 300: ! 301: ! 302: /* ! 303: *-STATUS: ! 304: * DDI/DKI ! 305: * ! 306: *-NAME: ! 307: * copyout Copy data from a driver buffer to a user buffer. ! 308: * ! 309: *-SYNOPSIS: ! 310: * #include <sys/types.h> ! 311: * ! 312: * int copyout (caddr_t driverbuf, caddr_t userbuf, size_t count); ! 313: * ! 314: *-ARGUMENTS: ! 315: * driverbuf Driver source address from which copy is made. ! 316: * ! 317: * userbuf User destination address to which copy is made. ! 318: * ! 319: * count Number of bytes to copy. ! 320: * ! 321: *-DESCRIPTION: ! 322: * copyout () copies "count" bytes of data from the kernel virtual ! 323: * address specified by "driverbuf" to the user virtual address specified ! 324: * by "userbuf". ! 325: * ! 326: * copyout () chooses the best algorithm based on address alignment and ! 327: * number of bytes to copy. Although the source and destination addresses ! 328: * are not required to be word aligned, word aligned addresses may result ! 329: * in a more efficient copy. ! 330: * ! 331: *-RETURN VALUE: ! 332: * If the copy is successful, 0 is returned. Otherwise, -1 is returned to ! 333: * indicate that the specified user address range is not valid. ! 334: * ! 335: *-LEVEL: ! 336: * Base only. ! 337: * ! 338: *-NOTES: ! 339: * May sleep. ! 340: * ! 341: * Drivers usually convert a return value of -1 into an EFAULT error. ! 342: * ! 343: * Driver-defined basic locks and read/write locks may not be held across ! 344: * calls to this function. ! 345: * ! 346: * Driver-defined sleep locks may be held across calls to this function. ! 347: * ! 348: * When holding sleep locks across calls to this function, drivers must ! 349: * be careful to avoid creating a deadlock. During the data transfer, ! 350: * page fault resolution may result in another I/O to the same device. ! 351: * For example, this could occur if the driver controls the disk drive ! 352: * used as the swap device. ! 353: * ! 354: * The driver source buffer must be completely within the kernel address ! 355: * space, or the system can panic. ! 356: * ! 357: *-SEE ALSO: ! 358: * copyin (), uiomove (), ureadc (), uwritec () ! 359: */ ! 360: ! 361: #if __USE_PROTO__ ! 362: int (copyout) (_VOID * driverbuf, _VOID * userbuf, size_t count) ! 363: #else ! 364: int ! 365: copyout __ARGS ((driverbuf, userbuf, count)) ! 366: _VOID * driverbuf; ! 367: _VOID * userbuf; ! 368: size_t count; ! 369: #endif ! 370: { ! 371: ASSERT (driverbuf != NULL); ! 372: ! 373: return TOUSER (userbuf, driverbuf, count) != count ? -1 : 0; ! 374: } ! 375: ! 376: ! 377: /* ! 378: *-STATUS: ! 379: * DDI/DKI ! 380: * ! 381: *-NAME: ! 382: * uiomove Copy data using uio structure. ! 383: * ! 384: *-SYNOPSIS: ! 385: * #include <sys/types.h> ! 386: * #include <sys/uio.h> ! 387: * ! 388: * int uiomove (caddr_t addr, long nbytes, uio_rw_t rwflag, uio_t * uiop); ! 389: * ! 390: *-ARGUMENTS: ! 391: * addr Source/destination kernel address of the copy. ! 392: * ! 393: * nbytes Number of bytes to copy. ! 394: * ! 395: * rwflag Flag indicating read or write operation. Possible ! 396: * values are UIO_READ and UIO_WRITE. ! 397: * ! 398: * uiop Pointer to the "uio" structure for the copy. ! 399: * ! 400: *-DESCRIPTION: ! 401: * The uiomove () function copies "nbytes" of data between the kernel ! 402: * address "addr" and the space defined by the "uio" structure pointed to ! 403: * by "uiop". If "rwflg" is "UIO_READ", the data is copied from "addr" to ! 404: * the space described by the "uio" structure. If "rwflag" is "UIO_WRITE", ! 405: * the data is copied from the space described by the "uio" structure to ! 406: * "addr". ! 407: * ! 408: * The "uio_segflg" member of the "uio" structure specifies the type of ! 409: * space described by the "uio" structure. If "uio_segflg" is set to ! 410: * "UIO_SYSSPACE" the "uio" structure describes a portion of the kernel ! 411: * address space. If "uio_segflg" is set to "UIO_USERSPACE" the "uio" ! 412: * structure describes a portion of the user address space. ! 413: * ! 414: * If the copy is successful, uiomove () updates the appropriate members ! 415: * of the "uio" and "iovec" structures to reflect the copy ("uio_offset" ! 416: * and "iov_base" and increased by "nbytes" and "uio_resid" and "iov_len" ! 417: * are decreased by "nbytes"). ! 418: * ! 419: *-RETURN VALUE: ! 420: * uiomove () returns 0 on success or an error number on failure. If a ! 421: * partial transfer occurs, the "uio" structure is updated to indicate ! 422: * the amount not transferred and an error is returned. ! 423: * ! 424: *-LEVEL: ! 425: * Base only if "uio_segflg" is set to "UIO_USERSPACE". Base or interrupt ! 426: * if "uio_segflg" is set to "UIO_SYSSPACE". ! 427: * ! 428: *-NOTES: ! 429: * May sleep if "uio_segflg" is set to "UIO_USERSPACE". ! 430: * ! 431: * Driver-defined basic locks and read/write locks may be held across ! 432: * calls to this function if "uio_segflg" is "UIO_SYSSPACE" but may not be ! 433: * held if "uio_segflg" is "UIO_USERSPACE". ! 434: * ! 435: * Driver-defined sleep locks may be held across calls to this function ! 436: * regardless of the value of "uio_segflg". ! 437: * ! 438: * When holding locks across calls to this function, drivers must be ! 439: * careful to avoid creating a deadlock. During the data transfer, page ! 440: * fault resolution might result in another I/O to the same device. For ! 441: * example, this could occur if the driver controls the disk drive used ! 442: * as the swap device. ! 443: * ! 444: * If "addr" specifies an address in user space, or if the value of ! 445: * "uio_segflg" is not consistent with the type of address space ! 446: * described by the "uio" structure, the system can panic. ! 447: * ! 448: *-SEE ALSO: ! 449: * bcopy (), copyin (), copyout (), ureadc (), uwritec (), iovec, uio ! 450: */ ! 451: ! 452: #if __USE_PROTO__ ! 453: int (uiomove) (caddr_t addr, long nbytes, uio_rw_t rwflag, uio_t * uiop) ! 454: #else ! 455: int ! 456: uiomove __ARGS ((addr, nbytes, rwflag, uiop)) ! 457: caddr_t addr; ! 458: long nbytes; ! 459: uio_rw_t rwflag; ! 460: uio_t * uiop; ! 461: #endif ! 462: { ! 463: iovec_t * scan; ! 464: iovec_t * end; ! 465: ! 466: ASSERT (addr != NULL); ! 467: ASSERT (uiop != NULL); ! 468: ASSERT (nbytes > 0); ! 469: ASSERT (nbytes <= SIZE_T_MAX); ! 470: ASSERT (uiop->uio_resid <= SIZE_T_MAX); ! 471: ASSERT (rwflag == UIO_READ || rwflag == UIO_WRITE); ! 472: ASSERT (uiop->uio_segflg == UIO_SYSSPACE || ! 473: uiop->uio_segflg == UIO_USERSPACE); ! 474: ASSERT (uiop->uio_resid > 0); ! 475: ! 476: for (scan = uiop->uio_iov, end = scan + uiop->uio_iovcnt ; ! 477: nbytes > 0 ; scan ++) { ! 478: size_t size; ! 479: ! 480: ! 481: /* ! 482: * Now we are going to move a single block of the scatter/ ! 483: * gather request. We assume that scan->iov_len is ! 484: * less than or equal to uiop->uio_resid! ! 485: */ ! 486: ! 487: ASSERT (scan < end); ! 488: ASSERT (scan->iov_len > 0); ! 489: ASSERT (scan->iov_len <= uiop->uio_resid); ! 490: ! 491: if (nbytes < (size = (size_t) uiop->uio_iov->iov_len)) ! 492: size = (size_t) nbytes; ! 493: ! 494: if (size == 0) ! 495: continue; ! 496: ! 497: ! 498: /* ! 499: * Transfer a segment as indicated. ! 500: */ ! 501: ! 502: if (rwflag == UIO_READ) { ! 503: ! 504: if (uiop->uio_segflg == UIO_USERSPACE) { ! 505: /* ! 506: * Transfers involving user memory may sleep ! 507: * due to paging! ! 508: */ ! 509: ! 510: if (TOUSER (scan->iov_base, addr, ! 511: size) != size) ! 512: break; ! 513: } else ! 514: memcpy (scan->iov_base, addr, size); ! 515: } else { ! 516: ! 517: if (uiop->uio_segflg == UIO_USERSPACE) { ! 518: /* ! 519: * Transfers involving user memory may sleep ! 520: * due to paging! ! 521: */ ! 522: ! 523: ! 524: if (FROMUSER (addr, scan->iov_base, ! 525: size) != size) ! 526: break; ! 527: } else ! 528: memcpy (addr, scan->iov_base, size); ! 529: } ! 530: ! 531: addr += size; ! 532: nbytes -= size; ! 533: ! 534: uiop->uio_resid -= size; ! 535: uiop->uio_offset += size; ! 536: ! 537: scan->iov_len -= size; ! 538: scan->iov_base += size; ! 539: } ! 540: ! 541: return nbytes == 0 ? 0 : EFAULT; ! 542: } ! 543: ! 544: ! 545: /* ! 546: *-STATUS: ! 547: * DDI/DKI ! 548: * ! 549: *-NAME: ! 550: * ureadc Copy a character to space described by a "uio" ! 551: * structure. ! 552: * ! 553: *-SYNOPSIS: ! 554: * #include <sys/uio.h> ! 555: * ! 556: * int ureadc (int c, uio_t * uiop); ! 557: * ! 558: *-ARGUMENTS: ! 559: * c The character to be copied. ! 560: * ! 561: * uiop Pointer to the "uio" structure. ! 562: * ! 563: *-DESCRIPTION: ! 564: * ureadc () copies the character "c" into the space described by the ! 565: * "uio" structure pointed to by "uiop". ! 566: * ! 567: * The "uio_segflg" member of the "uio" structure specifies the type of ! 568: * space to which the copy is made. If "uio_segflg" is set to ! 569: * "UIO_SYSSPACE" the character is copied to a kernel address. If ! 570: * "uio_segflg" is set to "UIO_USERSPACE" the character is copied to a ! 571: * user address. ! 572: * ! 573: * If the character is successfully copied, ureadc () updates the ! 574: * appropriate members of the "uio" and "iovec" structures to reflect ! 575: * the copy ("uio_offset" and "iov_base" are incremented and "uio_resid" ! 576: * and "iov_len" are decremented). ! 577: * ! 578: *-RETURN VALUE: ! 579: * ureadc () returns 0 on success or an error number on failure. ! 580: * ! 581: *-LEVEL: ! 582: * Base only if "uio_segflg" is set to "UIO_USERSPACE". Base or interrupt ! 583: * if "uio_segflg" is set to "UIO_SYSSPACE". ! 584: * ! 585: *-NOTES: ! 586: * May sleep if "uio_segflg" is set to "UIO_USERSPACE". ! 587: * ! 588: * Driver-defined basic locks and read/write locks may be held across ! 589: * calls to this function if "uio_segflg" is set to "UIO_SYSSPACE" but ! 590: * may not be held if "uio_segflg" is set to "UIO_USERSPACE". ! 591: * ! 592: * Driver-defined sleep locks may be held across calls to this function ! 593: * regardless of the value of "uio_segflg". ! 594: * ! 595: * When holding locks across calls to this function, drivers must be ! 596: * careful to avoid creating a deadlock. During the data transfer, page ! 597: * fault resolution might result in another I/O to the same device. For ! 598: * example, this could occur if the driver controls the disk drive used ! 599: * as the swap device. ! 600: * ! 601: *-SEE ALSO: ! 602: * uiomove (), uwritec (), iovec, uio ! 603: */ ! 604: ! 605: #if __USE_PROTO__ ! 606: int (ureadc) (int c, uio_t * uiop) ! 607: #else ! 608: int ! 609: ureadc __ARGS ((c, uiop)) ! 610: int c; ! 611: uio_t * uiop; ! 612: #endif ! 613: { ! 614: iovec_t * scan; ! 615: ! 616: ! 617: ASSERT (uiop != NULL); ! 618: ASSERT (uiop->uio_segflg == UIO_SYSSPACE || ! 619: uiop->uio_segflg == UIO_USERSPACE); ! 620: ASSERT (uiop->uio_segflg == UIO_SYSSPACE || ! 621: uiop->uio_segflg == UIO_USERSPACE); ! 622: ASSERT (uiop->uio_resid > 0); ! 623: ! 624: /* ! 625: * What to do if the structure is empty? As indicated above, I ! 626: * consider that an error worthy of a kernel panic. At a minimum we ! 627: * should make it a recoverable error as the code below does. ! 628: */ ! 629: ! 630: if (uiop->uio_resid <= 0) ! 631: return EFAULT; ! 632: ! 633: ! 634: /* ! 635: * For now, we loop over any initial empty segments. It is not clear ! 636: * to me whether this code can alter "uio_iov" or not, although we ! 637: * definitely are permitted to maintain a separate entry in the ! 638: * structure to the same effect. ! 639: */ ! 640: ! 641: for (scan = uiop->uio_iov ; scan->iov_len == 0 ; scan ++) ! 642: ; ! 643: ! 644: ASSERT (scan < uiop->uio_iov + uiop->uio_iovcnt); ! 645: ! 646: /* ! 647: * Now, write a single character to the space indicated. ! 648: */ ! 649: ! 650: if (uiop->uio_segflg == UIO_USERSPACE) { ! 651: ! 652: if (PUTBYTE (c, scan->iov_base) != 0) ! 653: return EFAULT; ! 654: ! 655: scan->iov_base ++; ! 656: } else ! 657: * scan->iov_base ++ = c; ! 658: ! 659: scan->iov_len ++; ! 660: ! 661: uiop->uio_resid --; ! 662: uiop->uio_offset ++; ! 663: ! 664: return 0; ! 665: } ! 666: ! 667: ! 668: /* ! 669: *-STATUS: ! 670: * DDI/DKI ! 671: * ! 672: *-NAME: ! 673: * uwritec Return a character from space described by a "uio" ! 674: * structure. ! 675: * ! 676: *-SYNOPSIS: ! 677: * #include <sys/uio.h> ! 678: * ! 679: * int uwritec (uio_t * uiop); ! 680: * ! 681: *-ARGUMENTS: ! 682: * uiop Pointer to the "uio" structure. ! 683: * ! 684: *-DESCRIPTION: ! 685: * uwritec () copies a character from the space described by the "uio" ! 686: * structure pointed to by "uiop" and returns the character to the ! 687: * caller. ! 688: * ! 689: * The "uio_segflg" member of the "uio" structure specifies the type of ! 690: * space from which the copy is made. If "uio_segflg" is set to ! 691: * "UIO_SYSSPACE" the character is copied from a kernel address. If ! 692: * "uio_segflg" is set to "UIO_USERSPACE" the character is copied from a ! 693: * user address. ! 694: * ! 695: * If the character is successfully copied, uwritec () updates the ! 696: * appropriate members of the "uio" and "iovec" structures to reflect the ! 697: * copy ("uio_offset" and "iov_base" are incremented and "uio_resid" and ! 698: * "iov_len" are decremented). ! 699: * ! 700: *-RETURN VALUE: ! 701: * If successful, uwritec () returns the character. -1 is returned if the ! 702: * space described by the "uio" structure is empty or if there is an ! 703: * error. ! 704: * ! 705: *-LEVEL: ! 706: * Base only if "uio_segflg" is set to "UIO_USERSPACE". Base or interrupt ! 707: * if "uio_segflg" is set to "UIO_SYSSPACE". ! 708: * ! 709: *-NOTES: ! 710: * May sleep if "uio_segflg" is set to "UIO_USERSPACE". ! 711: * Driver-defined basic locks and read/write locks may be held across ! 712: * calls to this function if "uio_segflg" is "UIO_SYSSPACE" but may not ! 713: * be held if "uio_segflg" is "UIO_USERSPACE". ! 714: * ! 715: * Driver-defined sleep locks may be held across calls to this function ! 716: * regardless of the value of "uio_segflg". ! 717: * ! 718: * When holding locks across calls to this function, drivers must be ! 719: * careful to avoid creating a deadlock. During the data transfer, page ! 720: * fault resolution might result in another I/O to the same device. For ! 721: * example, this could occur if the driver controls the disk drive used ! 722: * as the swap device. ! 723: * ! 724: *-SEE ALSO: ! 725: * uiomove (), ureadc (), iovec, uio ! 726: */ ! 727: ! 728: #if __USE_PROTO__ ! 729: int (uwritec) (uio_t * uiop) ! 730: #else ! 731: int ! 732: uwritec __ARGS ((uiop)) ! 733: uio_t * uiop; ! 734: #endif ! 735: { ! 736: iovec_t * scan; ! 737: int c; ! 738: ! 739: ! 740: ASSERT (uiop != NULL); ! 741: ASSERT (uiop->uio_segflg == UIO_SYSSPACE || ! 742: uiop->uio_segflg == UIO_USERSPACE); ! 743: ASSERT (uiop->uio_segflg == UIO_SYSSPACE || ! 744: uiop->uio_segflg == UIO_USERSPACE); ! 745: ! 746: /* ! 747: * What to do if the structure is empty? Unlike ureadc (), we are ! 748: * allowed to return -1. ! 749: */ ! 750: ! 751: if (uiop->uio_resid <= 0) ! 752: return -1; ! 753: ! 754: ! 755: /* ! 756: * For now, we loop over any initial empty segments. It is not clear ! 757: * to me whether this code can alter "uio_iov" or not, although we ! 758: * definitely are permitted to maintain a separate entry in the ! 759: * structure to the same effect. ! 760: */ ! 761: ! 762: for (scan = uiop->uio_iov ; scan->iov_len == 0 ; scan ++) ! 763: ; ! 764: ! 765: ASSERT (scan < uiop->uio_iov + uiop->uio_iovcnt); ! 766: ! 767: /* ! 768: * Now, read a single character from the space indicated. ! 769: */ ! 770: ! 771: if (uiop->uio_segflg == UIO_USERSPACE) { ! 772: ! 773: if ((c = GETBYTE (scan->iov_base)) < 0) ! 774: return -1; ! 775: ! 776: scan->iov_base ++; ! 777: } else ! 778: c = * scan->iov_base ++; ! 779: ! 780: scan->iov_len --; ! 781: ! 782: uiop->uio_resid --; ! 783: uiop->uio_offset ++; ! 784: ! 785: return c; ! 786: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.