Annotation of driverkit/Examples/UnixDisk/unixDiskPrivate.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*     unixDiskPrivate.m       1.0     02/07/91        (c) 1991 NeXT   
                     25:  *
                     26:  * unixDiskPrivate.m - unixDisk Private methods.
                     27:  *
                     28:  * HISTORY
                     29:  * 07-Feb-91    Doug Mitchell at NeXT
                     30:  *      Created.
                     31:  */
                     32: 
                     33: #import <bsd/sys/types.h>
                     34: #import <mach/cthreads.h>
                     35: #import <bsd/libc.h>
                     36: #import <bsd/sys/file.h>
                     37: #import <driverkit/IODevice.h>
                     38: #import "unixDisk.h"
                     39: #import "unixThread.h"
                     40: #import "unixDiskPrivate.h"
                     41: #import <bsd/dev/disk.h>
                     42: #import "unixDiskUxpr.h"
                     43: #import <errno.h>
                     44: #import <driverkit/generalFuncs.h>
                     45: #import <machkit/NXLock.h>
                     46: 
                     47: @implementation unixDisk(Private)
                     48: 
                     49: /*
                     50:  * readCommon: and writeCommon: are invoked by the exported flavors of
                     51:  * read: and write:. 
                     52:  */
                     53: - (IOReturn) readCommon : (u_int)block 
                     54:                length : (u_int)length 
                     55:                buffer : (void *)bufp
                     56:                actualLength : (u_int *)actualLength            /* returned */
                     57:                pending : (void *)pending
                     58:                caller : (id)caller
                     59:                IOBufRtn : (IOBuf_t **)IOBufRtn
                     60: {
                     61:        IOReturn mrtn;
                     62:        IOBuf_t *IOBuf;
                     63:        u_int block_size, dev_size;
                     64:        
                     65:        /*
                     66:         * We have to 'fault in' a possible non-present disk in 
                     67:         * order to get its physical parameters...
                     68:         */
                     69:        mrtn = [self isDiskReady:TRUE];
                     70:        switch(mrtn) {
                     71:            case IO_R_SUCCESS:
                     72:                break;
                     73:            case IO_R_NO_DISK:
                     74:                xpr_err("%s readCommon: disk not present\n", 
                     75:                        [self name], 2,3,4,5);
                     76:                return(mrtn);
                     77:            default:
                     78:                IOLog("%s readCommon: bogus return from isDiskReady"
                     79:                        " (%s)\n",
                     80:                        [self name], [self stringFromReturn:mrtn]);
                     81:                return(mrtn);
                     82:        }
                     83:        if(![self isFormatted])
                     84:                return(IO_R_UNFORMATTED);
                     85: 
                     86:        /*
                     87:         * Verify legal parameters.
                     88:         */
                     89:        block_size = [self blockSize];
                     90:        dev_size = [self diskSize];
                     91:        if(block >= dev_size) {
                     92:                xpr_ud("unixDisk readCommon: invalid "
                     93:                        "deviceBlock/byte count\n", 1,2,3,4,5);
                     94:                return(IO_R_INVALID_ARG);
                     95:        }
                     96: 
                     97:        if(length % block_size) {
                     98:                xpr_ud("unixDisk readCommon: byteCount not block_size "
                     99:                        "multiple\n", 1,2,3,4,5);
                    100:                return(IO_R_INVALID_ARG); 
                    101:        }
                    102:        
                    103:        /*
                    104:         * Queue up an IOBuf.
                    105:         */
                    106:        IOBuf            = [self allocIOBuf];
                    107:        IOBuf->command   = @selector(unixDeviceRead:threadNum:);
                    108:        IOBuf->offset    = block;
                    109:        IOBuf->bytesReq  = length;
                    110:        IOBuf->buf       = bufp;
                    111:        IOBuf->bytesXfr  = actualLength;
                    112:        IOBuf->status    = IO_R_INVALID;        /* must be filled in by
                    113:                                                 * I/O thread */
                    114:        IOBuf->pending   = pending;
                    115:        IOBuf->caller    = caller;
                    116:        IOBuf->device    = self;
                    117:        IOBuf->dirRead   = 1;
                    118:        *IOBufRtn        = IOBuf;
                    119:        if(!pending) {
                    120:                IOBuf->wait_lock = [NXConditionLock alloc];
                    121:                [IOBuf->wait_lock initWith:FALSE];
                    122:        }
                    123:        else {
                    124:                IOBuf->wait_lock = nil;
                    125:        }
                    126:        [self enqueueIoBuf:IOBuf needs_disk:TRUE];
                    127:        return(IO_R_SUCCESS);
                    128: }
                    129: 
                    130: - (IOReturn) writeCommon : (u_int)block 
                    131:                length : (u_int)length 
                    132:                buffer : (void *)bufp
                    133:                actualLength : (u_int *)actualLength            /* returned */
                    134:                pending : (void *)pending
                    135:                caller : (id)caller                     // for DO only
                    136:                IOBufRtn : (IOBuf_t **)IOBufRtn
                    137: {
                    138:        IOReturn mrtn;
                    139:        IOBuf_t *IOBuf;
                    140:        u_int block_size, dev_size;
                    141:        
                    142:        /*
                    143:         * We have to 'fault in' a possible non-present disk in 
                    144:         * order to get its physical parameters...
                    145:         */
                    146:        mrtn = [self isDiskReady:TRUE];
                    147:        switch(mrtn) {
                    148:            case IO_R_SUCCESS:
                    149:                break;
                    150:            case IO_R_NO_DISK:
                    151:                xpr_err("%s writeCommon: disk not present\n", 
                    152:                        [self name], 2,3,4,5);
                    153:                return(mrtn);
                    154:            default:
                    155:                IOLog("%s writeCommon: bogus return from isDiskReady"
                    156:                        " (%s)\n",
                    157:                        [self name], [self stringFromReturn:mrtn]);
                    158:                return(mrtn);
                    159:        }
                    160: 
                    161:        /*
                    162:         * Verify access and legal parameters.
                    163:         */
                    164:        if([self isWriteProtected]) {
                    165:                return IO_R_NOT_WRITABLE;
                    166:        }
                    167:        block_size = [self blockSize];
                    168:        dev_size = [self diskSize];
                    169:        if(block >= dev_size) {
                    170:                xpr_ud("unixDisk writeCommon: invalid "
                    171:                        "deviceBlock/byte count\n", 1,2,3,4,5);
                    172:                return(IO_R_INVALID_ARG);
                    173:        }
                    174:        if(length % block_size) {
                    175:                xpr_ud("unixDisk writeCommon: byteCount not block_size "
                    176:                        "multiple\n", 1,2,3,4,5);
                    177:                return(IO_R_INVALID_ARG);
                    178:        }
                    179: 
                    180:        /*
                    181:         * Queue up an IOBuf.
                    182:         */
                    183:        IOBuf            = [self allocIOBuf];
                    184:        IOBuf->command   = @selector(unixDeviceWrite:threadNum:);
                    185:        IOBuf->offset    = block;
                    186:        IOBuf->bytesReq  = length;
                    187:        IOBuf->buf       = bufp;
                    188:        IOBuf->bytesXfr  = actualLength;
                    189:        IOBuf->status    = IO_R_INVALID;        /* must be filled in by
                    190:                                                 * I/O thread */
                    191:        IOBuf->pending   = pending;
                    192:        IOBuf->caller    = caller;
                    193:        IOBuf->device    = self;
                    194:        IOBuf->dirRead   = 1;
                    195:        *IOBufRtn        = IOBuf;
                    196:        if(!pending) {
                    197:                IOBuf->wait_lock = [NXConditionLock alloc];
                    198:                [IOBuf->wait_lock initWith:FALSE];
                    199:        }
                    200:        else {
                    201:                IOBuf->wait_lock = nil;
                    202:        }
                    203:        [self enqueueIoBuf:IOBuf needs_disk:TRUE];
                    204:        return(IO_R_SUCCESS);
                    205: }
                    206: 
                    207: - (IOBuf_t *)allocIOBuf
                    208: {
                    209:        return(IOMalloc(sizeof(IOBuf_t)));
                    210: }
                    211: 
                    212: - (void)freeIOBuf:(IOBuf_t *)IOBuf
                    213: {
                    214:        if(IOBuf->wait_lock != nil) {
                    215:                /* 
                    216:                 * This was used for async I/O; free these resources...
                    217:                 */
                    218:                [IOBuf->wait_lock free];
                    219:        }
                    220:        IOFree(IOBuf, sizeof(*IOBuf));
                    221: }
                    222: 
                    223: /*
                    224:  * Wakeup thread waiting on IOBuf.
                    225:  */
                    226: - (void)IOBufDone : (IOBuf_t *)IOBuf
                    227:                    status : (IOReturn)status
                    228: {
                    229:        [IOBuf->wait_lock lock];
                    230:        IOBuf->status = status;
                    231:        [IOBuf->wait_lock unlockWith:TRUE];
                    232: }      
                    233: 
                    234: /*
                    235:  * These methods are invoked by a unix_thread; they do the actual work of
                    236:  * reading and writing.
                    237:  */
                    238: - (void)unixDeviceRead : (IOBuf_t *)IOBuf
                    239:        threadNum:(int)threadNum
                    240: {
                    241:        int rtn;
                    242:        int position;
                    243:        IOReturn status;
                    244:        u_int block_size;
                    245:        
                    246:        xpr_uth("unix deviceRead: thread %d offset %d\n", 
                    247:                threadNum, IOBuf->offset, 3,4,5);
                    248:        
                    249:        /*
                    250:         * lseek to appropriate place.
                    251:         */
                    252:        block_size = [self blockSize];
                    253:        position = IOBuf->offset * block_size;
                    254:        rtn = lseek(unix_fd[threadNum], position, L_SET);
                    255:        if(rtn != position) {
                    256:                xpr_uth("unixDisk deviceRead lseek(): errno %d\n", errno,
                    257:                        2,3,4,5);
                    258:                status = errno_to_mio(errno);
                    259:                goto done;
                    260:        }
                    261: 
                    262:        /* 
                    263:         * Go for it.
                    264:         */
                    265:        xpr_uth("unix deviceRead read(): thread %d offset %d\n", 
                    266:                threadNum, IOBuf->offset, 3,4,5);
                    267:        rtn = read(unix_fd[threadNum], IOBuf->buf, IOBuf->bytesReq);
                    268:        if(rtn > 0) {
                    269:                *IOBuf->bytesXfr = rtn;
                    270:                status = IO_R_SUCCESS;
                    271:        }
                    272:        else 
                    273:                status = errno_to_mio(errno);
                    274: done:
                    275:        /*
                    276:         * Any time we successfully complete a read or a write, we go to 
                    277:         * "formatted" state.
                    278:         */
                    279:        if(status == IO_R_SUCCESS)
                    280:                [self setFormattedInternal:1];
                    281:        if(IOBuf->pending) {
                    282:                /*
                    283:                 * Async I/O. Notify client.
                    284:                 */
                    285:                IOData *rdata = [[IOData alloc] initWithData:IOBuf->buf
                    286:                        size:*IOBuf->bytesXfr
                    287:                        dealloc:NO];
                    288:                
                    289:                [rdata setFreeFlag:NO];
                    290:                [IOBuf->caller readIoComplete:(unsigned)IOBuf->pending  
                    291:                                        // ioKey
                    292:                        device:self
                    293:                        data:rdata
                    294:                        status:IOBuf->status];
                    295:                [rdata free];
                    296:                [self freeIOBuf:IOBuf];
                    297:        }
                    298:        else {
                    299:                /*
                    300:                 * Synchronous I/O. Notify sleeping thread.
                    301:                 */
                    302:                [self IOBufDone:IOBuf status:status];
                    303:        }
                    304:        xpr_uth("unixDeviceRead thread %d: DONE, status %s\n",
                    305:                threadNum, [self stringFromReturn:IOBuf->status], 3,4,5);
                    306: }
                    307: 
                    308: - (void)unixDeviceWrite : (IOBuf_t *)IOBuf
                    309:        threadNum:(int)threadNum
                    310: {
                    311:        int rtn;
                    312:        int position;
                    313:        IOReturn status;
                    314:        u_int block_size;
                    315:        
                    316:        xpr_uth("unix deviceWrite: thread %d offset %d\n", 
                    317:                threadNum, IOBuf->offset, 3,4,5);
                    318: 
                    319:        /*
                    320:         * lseek to appropriate place.
                    321:         */
                    322:        block_size = [self blockSize];
                    323:        position = IOBuf->offset * block_size;
                    324:        rtn = lseek(unix_fd[threadNum], position, L_SET);
                    325:        if(rtn != position) {
                    326:                xpr_uth("unixDisk deviceWrite lseek(): errno %d\n", errno,
                    327:                        2,3,4,5);
                    328:                status = errno_to_mio(errno);
                    329:                goto done;
                    330:        }
                    331:        
                    332:        /*
                    333:         * Go for it.
                    334:         */
                    335:        rtn = write(unix_fd[threadNum], IOBuf->buf, IOBuf->bytesReq);
                    336:        if(rtn > 0) {
                    337:                *IOBuf->bytesXfr = rtn;
                    338:                status = IO_R_SUCCESS;
                    339:        }
                    340:        else 
                    341:                status = errno_to_mio(errno);
                    342: done:
                    343:        /*
                    344:         * Any time we successfully complete a read or a write, we go to 
                    345:         * "formatted" state.
                    346:         */
                    347:        if(status == IO_R_SUCCESS)
                    348:                [self setFormattedInternal:1];
                    349:        if(IOBuf->pending) {
                    350:                /*
                    351:                 * Async I/O. Notify client.
                    352:                 */
                    353:                [IOBuf->caller writeIoComplete:(unsigned)IOBuf->pending
                    354:                        device:self
                    355:                        actualLength:*IOBuf->bytesXfr
                    356:                        status:IOBuf->status];
                    357:                [self freeIOBuf:IOBuf];
                    358:        }
                    359:        else {
                    360:                /*
                    361:                 * Synchronous I/O. Notify sleeping thread.
                    362:                 */
                    363:                [self IOBufDone:IOBuf status:status];
                    364:        }               
                    365:        xpr_uth("unixDeviceWrite thread %d: DONE, status %s\n",
                    366:                threadNum, [self stringFromReturn:IOBuf->status], 3,4,5);
                    367: }
                    368: 
                    369: - (void)deviceEject    : (IOBuf_t *)IOBuf
                    370:                           threadNum:(int)threadNum
                    371: {
                    372:        int rtn;
                    373:        IOReturn status;
                    374:        
                    375:        xpr_uth("unixDisk deviceEject: thread %d\n", threadNum, 2,3,4,5);
                    376:        
                    377:        /*
                    378:         * Wait until we're the only thread doing disk access.
                    379:         */
                    380:        [IOQueue.ejectLock lockWhen:1];
                    381:        [IOQueue.ejectLock unlock];
                    382:        
                    383:        rtn = ioctl(unix_fd[threadNum], DKIOCEJECT, NULL);
                    384:        if(rtn)
                    385:                status = errno_to_mio(errno);
                    386:        else
                    387:                status = IO_R_SUCCESS;
                    388:        
                    389:        /*
                    390:         * We go to unformatted state until we successfully complete a 
                    391:         * read or a write.
                    392:         */
                    393:        [self setFormattedInternal:0];
                    394:        IOQueue.ejectPending = FALSE;
                    395:        [self IOBufDone:IOBuf status:status];
                    396:        xpr_uth("unixDeviceEject thread %d: DONE, status %s\n",
                    397:                threadNum, [self stringFromReturn:IOBuf->status], 3,4,5);
                    398: }
                    399: 
                    400: /*
                    401:  * Requested disk is not available. ioComplete everything in this
                    402:  * device's q_disk queue with IO_R_NO_DISK status.
                    403:  */
                    404: - (void)unixDeviceAbort : (IOBuf_t *)IOBuf
                    405: {
                    406:        IOBuf_t *abortBuf;
                    407:        queue_head_t *q = &IOQueue.q_disk;
                    408:        
                    409:        xpr_uth("unixDeviceAbort\n", 1,2,3,4,5);
                    410:        [IOQueue.qlock lock];
                    411:        while(!queue_empty(q)) {
                    412:                abortBuf = (IOBuf_t *)queue_first(q);
                    413:                queue_remove(q, abortBuf, IOBuf_t *, ioChain);
                    414:                
                    415:                /*
                    416:                 * Note we don't change condition variable of qlock...
                    417:                 */
                    418:                [IOQueue.qlock unlock];
                    419:                xpr_uth("unixDeviceAbort: ABORTING IOBuf 0x%x\n", abortBuf,
                    420:                        2,3,4,5);
                    421:                [self IOBufDone:abortBuf status:IO_R_NO_DISK];
                    422:                [IOQueue.qlock lock];
                    423:        }
                    424:        [IOQueue.qlock unlock];
                    425:        
                    426:        /* 
                    427:         * One more thing - I/O complete the abort command itself.
                    428:         */
                    429:        [self IOBufDone:IOBuf status:IO_R_SUCCESS];
                    430: }
                    431: 
                    432: /*
                    433:  * See if disk is present. If we got this far, it is; otherwise this request
                    434:  * would have been ioComplete'd in unixDeviceAbort:.
                    435:  */
                    436: - (void)deviceProbe    : (IOBuf_t *)IOBuf
                    437: {
                    438:        [self IOBufDone:IOBuf status:IO_R_SUCCESS];
                    439: }
                    440: 
                    441: /*
                    442:  * Test ready. We do this by trying to do a new open , with O_NDELAY. If that
                    443:  * succeeds, it's ready.
                    444:  */
                    445: - (void)deviceCheckReady : (IOBuf_t *)IOBuf
                    446:                           threadNum:(int)threadNum
                    447: {
                    448:        int newfd;
                    449:        IODiskReadyState *readyState = (IODiskReadyState *)IOBuf->buf;
                    450:        
                    451:        newfd = open(unix_name, O_RDONLY|O_NDELAY, 0);
                    452:        if(newfd <=0) {
                    453:                *readyState = IO_NotReady;
                    454:                xpr_uth("deviceCheckReady: NOT READY\n", 1,2,3,4,5);
                    455:        }
                    456:        else {
                    457:                *readyState = IO_Ready;
                    458:                close(newfd);
                    459:                xpr_uth("deviceCheckReady: READY\n", 1,2,3,4,5);
                    460:        }
                    461:        [self IOBufDone:IOBuf status:IO_R_SUCCESS];
                    462: }
                    463: 
                    464: @end

unix.superglobalmegacorp.com

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