Annotation of coherent/f/etc/conf/streams/src/uio.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.