Annotation of driverkit/Examples/IOStub/IOStub.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: /*     IOStub.m        1.0     01/29/91        (c) 1991 NeXT   
                     25:  *
                     26:  * IOStub.m - Implementation for trivial I/O device subclass.
                     27:  *
                     28:  * HISTORY
                     29:  * 29-Jan-91    Doug Mitchell at NeXT
                     30:  *      Created. 
                     31:  */
                     32:  
                     33: #import <bsd/sys/types.h>
                     34: #import <mach/mach.h>
                     35: #import <mach/vm_param.h>
                     36: #import <mach/mach_error.h>
                     37: #import <bsd/libc.h>
                     38: #import <driverkit/return.h>
                     39: #import <driverkit/IODevice.h>
                     40: #import "IOStub.h"
                     41: #import "IOStubThread.h"
                     42: #import "IOStubDevice.h"
                     43: #import "IOStubUxpr.h"
                     44: #import <machkit/NXLock.h>
                     45: 
                     46: @implementation IOStub
                     47: 
                     48: /*
                     49:  * Initialize current instance. Returns non-zero on error.
                     50:  */
                     51: - initStub : (int)unitNum
                     52: {
                     53:        int data_size;
                     54:        int i;
                     55:        char *cp;
                     56:        kern_return_t krtn;
                     57:        u_int block_size, dev_size;
                     58:        
                     59:        xpr_stub("IOStub : init: unitNum %d\n", unitNum, 2,3,4,5);
                     60:        
                     61: 
                     62:        [self setUnit:unitNum];
                     63:        if(unitNum == 0) {
                     64:                /*
                     65:                 * read/write.
                     66:                 */
                     67:                block_size = 0x20;
                     68:                dev_size = 0x1000;
                     69:                [self setName : "IOStub0"];
                     70:                [self setWriteProtected:NO];
                     71:        }
                     72:        else {
                     73:                /*
                     74:                 * Make this one read-only, non-queuing.
                     75:                 */
                     76:                block_size = 0x40;
                     77:                dev_size = 0x800;
                     78:                [self setName : "IOStub1"];
                     79:                [self setWriteProtected:YES];
                     80:        }
                     81:        [self setDeviceKind:"Stub Device"];
                     82:        [self setLocation:NULL];
                     83:        [self setDiskSize:dev_size];
                     84:        [self setBlockSize:block_size];
                     85:        [self setFormattedInternal:1];
                     86:        
                     87:        /* 
                     88:         * allocate and initialize data for writing and reading.
                     89:         */
                     90:        data_size = block_size * dev_size;
                     91:        krtn = vm_allocate(task_self(),
                     92:                (vm_address_t *)&stub_data,
                     93:                (vm_size_t)round_page(data_size), 
                     94:                YES);
                     95:        if(krtn != KERN_SUCCESS) {
                     96:                mach_error("***IOStub init: vm_allocate", krtn);
                     97:                return(self);
                     98:        }
                     99:        
                    100:        /*
                    101:         * initial data: incrementing bytes for unit 0, decrementing
                    102:         * bytes for others.
                    103:         */
                    104:        cp = (char *)stub_data;
                    105:        for(i=0; i<data_size; i++) {
                    106:                if(unitNum)
                    107:                        *cp++ = 0 - (char)i;
                    108:                else
                    109:                        *cp++ = i;
                    110:        }
                    111:         
                    112:        /*
                    113:         * Set up our instance's IOQueue.
                    114:         */
                    115:        ioQLock = [NXConditionLock alloc];
                    116:        [ioQLock initWith:NO_WORK_AVAILABLE];
                    117:        queue_init(&ioQueue);
                    118: 
                    119:        /*
                    120:         * Start up an I/O thread to perform the actual work of this device.
                    121:         */
                    122:        IOForkThread((IOThreadFunc)IOStub_thread, self);
                    123:                        
                    124:        [self registerDevice];
                    125:        
                    126:        /*
                    127:         * Let superclass take care of initializing inherited instance
                    128:         * variables.
                    129:         */
                    130:        [super init];
                    131:        return self;
                    132: }
                    133: 
                    134: /*
                    135:  * Free resources consumed by this instance. 
                    136:  */
                    137: - free
                    138: {
                    139:        int data_size;
                    140:        kern_return_t krtn;
                    141:        u_int block_size, dev_size;
                    142:        IOBuf_t *IOBuf;
                    143:                
                    144:        /*
                    145:         * Kill the I/O thread.
                    146:         */
                    147:        IOBuf            = IOMalloc(sizeof(*IOBuf));
                    148:        IOBuf->cmd       = STUB_ABORT;
                    149:        IOBuf->pending   = 0;
                    150:        IOBuf->waitLock  = [NXConditionLock alloc];
                    151:        [IOBuf->waitLock initWith:NO];
                    152:        [self enqueueIoBuf:IOBuf];
                    153:        
                    154:        /*
                    155:         * Wait for I/O complete.
                    156:         */
                    157:        [IOBuf->waitLock lockWhen:YES];
                    158:        [IOBuf->waitLock unlock];
                    159:        [IOBuf->waitLock free];
                    160:        IOFree(IOBuf, sizeof(IOBuf_t));
                    161:        
                    162:        /*
                    163:         *  Free up our VM.
                    164:         */
                    165:        block_size = [self blockSize];
                    166:        dev_size = [self diskSize];
                    167:        data_size = block_size * dev_size;
                    168:        krtn = vm_deallocate(task_self(),
                    169:                (vm_address_t)stub_data,
                    170:                (vm_size_t)round_page(data_size));
                    171:        if(krtn != KERN_SUCCESS) {
                    172:                mach_error("***IOStub free: vm_deallocate", krtn);
                    173:        }
                    174:        return([super free]);
                    175: }
                    176: 
                    177: /*
                    178:  * These override the superclass's methods which are no-op stubs.
                    179:  */
                    180:  
                    181: - (int)deviceOpen:(u_int)intentions
                    182: {
                    183:        xpr_stub("IOStub deviceOpen: unit %d\n", [self unit], 2,3,4,5);
                    184:        return(IO_R_SUCCESS);
                    185: }
                    186: 
                    187: - (void)deviceClose
                    188: {
                    189:        xpr_stub("IOStub deviceClose: unit %d\n", [self unit], 2,3,4,5);
                    190: }
                    191: 
                    192: /* 
                    193:  * These are the exported I/O methods, from the 
                    194:  * IODiskDeviceReadingAndWriting category. Their main task is:
                    195:  * 
                    196:  * -- verify valid input parameters.
                    197:  * -- set up and enqueue an IOBuf for servicing by the I/O thread.
                    198:  * -- Wait for I/O complete if synchronous request.
                    199:  */
                    200: 
                    201: - (IOReturn) readAt            : (unsigned)offset 
                    202:                                  length : (unsigned)length 
                    203:                                  buffer : (unsigned char *)buffer
                    204:                                  actualLength : (unsigned *)actualLength
                    205: {
                    206:        IOReturn mrtn;
                    207:        char *source;
                    208:        IOBuf_t *IOBuf;
                    209:        u_int block_size;
                    210:        u_int dev_size;
                    211:        
                    212:        xpr_stub("IOStub read: unit %d  offset 0x%x  length 0x%x\n",
                    213:                [self unit], offset, length, 4,5);
                    214:                
                    215:        block_size = [self blockSize];
                    216:        dev_size = [self diskSize];
                    217: 
                    218:        /*
                    219:         * Verify legal parameters.
                    220:         */
                    221:        source = stub_data + offset * block_size;
                    222:        if((source + length) > (stub_data + (block_size * dev_size))) {
                    223:           
                    224:                xpr_stub("IOStub read: invalid offset/byte count\n", 
                    225:                        1,2,3,4,5);
                    226:                return(IO_R_INVALID_ARG);
                    227:        }
                    228: 
                    229:        /*
                    230:         * OK, queue up an IOBuf.
                    231:         */
                    232:        IOBuf            = IOMalloc(sizeof(*IOBuf));
                    233:        IOBuf->cmd       = STUB_READ;
                    234:        IOBuf->offset    = offset;
                    235:        IOBuf->bytesReq  = length;
                    236:        IOBuf->buf       = buffer;
                    237:        IOBuf->bytesXfr  = actualLength;
                    238:        IOBuf->status    = IO_R_INVALID;
                    239:        IOBuf->pending   = 0;
                    240:        IOBuf->waitLock  = [NXConditionLock alloc];
                    241:        [IOBuf->waitLock initWith:NO];
                    242:        IOBuf->dirRead   = 1;
                    243:        [self enqueueIoBuf:IOBuf];
                    244:        
                    245:        /*
                    246:         * Wait for I/O complete.
                    247:         */
                    248:        [IOBuf->waitLock lockWhen:YES];
                    249:        [IOBuf->waitLock unlock];
                    250:        xpr_stub("stub read: DONE\n", 1,2,3,4,5);
                    251:        mrtn = IOBuf->status;
                    252:        [IOBuf->waitLock free];
                    253:        IOFree(IOBuf, sizeof(*IOBuf));
                    254:        return(mrtn);
                    255: }
                    256: 
                    257: - (IOReturn) readAsyncAt       : (unsigned)offset 
                    258:                                  length : (unsigned)length 
                    259:                                  buffer : (unsigned char *)buffer
                    260:                                  pending : (void *)pending
                    261: {
                    262:        char *source;
                    263:        IOBuf_t *IOBuf;
                    264:        unsigned block_size;
                    265:        unsigned dev_size;
                    266:        
                    267:        xpr_stub("IOStub readAsync: unit %d  offset 0x%x  length 0x%x\n",
                    268:                [self unit], offset, length, 4,5);
                    269:                
                    270:        block_size = [self blockSize];
                    271:        dev_size = [self diskSize];
                    272: 
                    273:        /*
                    274:         * Verify legal parameters.
                    275:         */
                    276:        source = stub_data + offset * block_size;
                    277:        if((source + length) > (stub_data + (block_size * dev_size))) {
                    278:           
                    279:                xpr_stub("IOStub read: invalid offset/byte count\n",
                    280:                        1,2,3,4,5);
                    281:                return(IO_R_INVALID_ARG);
                    282:        }
                    283: 
                    284:        /*
                    285:         * Just queue up an IOBuf.
                    286:         */
                    287:        IOBuf            = IOMalloc(sizeof(*IOBuf));
                    288:        IOBuf->cmd       = STUB_READ;
                    289:        IOBuf->offset    = offset;
                    290:        IOBuf->bytesReq  = length;
                    291:        IOBuf->buf       = buffer;
                    292:        IOBuf->status    = IO_R_INVALID;        /* must be filled in by
                    293:                                                 * I/O thread */
                    294:        IOBuf->pending   = pending;
                    295:        IOBuf->dirRead   = 1;
                    296:        [self enqueueIoBuf:IOBuf];
                    297:        
                    298:        xpr_stub("stub readAsync: DONE\n", 1,2,3,4,5);
                    299:        return(IO_R_SUCCESS);
                    300: }
                    301: 
                    302: - (IOReturn) writeAt           : (unsigned)offset 
                    303:                                  length : (unsigned)length 
                    304:                                  buffer : (unsigned char *)buffer
                    305:                                  actualLength : (unsigned *)actualLength
                    306: {
                    307:        IOReturn mrtn;
                    308:        char *dest;
                    309:        IOBuf_t *IOBuf;
                    310:        unsigned block_size;
                    311:        unsigned dev_size;
                    312:        
                    313:        xpr_stub("IOStub write: unit %d  offset 0x%x  length 0x%x\n",
                    314:                [self unit], offset, length, 4,5);
                    315:                
                    316:        block_size = [self blockSize];
                    317:        dev_size = [self diskSize];
                    318: 
                    319:        /*
                    320:         * Verify legal parameters.
                    321:         */
                    322:        if([self isWriteProtected]) {
                    323:                return IO_R_NOT_WRITABLE;
                    324:        }
                    325:        dest = stub_data + offset * block_size;
                    326:        if((dest + length) > (stub_data + (block_size * dev_size))) {
                    327:           
                    328:                xpr_stub("IOStub dest: invalid offset/byte count\n",
                    329:                        1,2,3,4,5);
                    330:                return(IO_R_INVALID_ARG);
                    331:        }
                    332: 
                    333:        /*
                    334:         * OK, queue up an IOBuf.
                    335:         */
                    336:        IOBuf            = IOMalloc(sizeof(*IOBuf));
                    337:        IOBuf->cmd       = STUB_WRITE;
                    338:        IOBuf->offset    = offset;
                    339:        IOBuf->bytesReq  = length;
                    340:        IOBuf->buf       = buffer;
                    341:        IOBuf->bytesXfr  = actualLength;
                    342:        IOBuf->status    = IO_R_INVALID;
                    343:        IOBuf->pending   = 0;
                    344:        IOBuf->waitLock  = [NXConditionLock alloc];
                    345:        [IOBuf->waitLock initWith:NO];
                    346:        IOBuf->dirRead   = 0;
                    347:        [self enqueueIoBuf:IOBuf];
                    348:        
                    349:        /*
                    350:         * Wait for I/O complete.
                    351:         */
                    352:        [IOBuf->waitLock lockWhen:YES];
                    353:        [IOBuf->waitLock unlock];
                    354:        xpr_stub("stub write: DONE\n", 1,2,3,4,5);
                    355:        mrtn = IOBuf->status;
                    356:        [IOBuf->waitLock free];
                    357:        IOFree(IOBuf, sizeof(*IOBuf));
                    358:        return(mrtn);
                    359: }
                    360: 
                    361: - (IOReturn) writeAsyncAt      : (unsigned)offset 
                    362:                                  length : (unsigned)length 
                    363:                                  buffer : (unsigned char *)buffer
                    364:                                  pending : (void *)pending;
                    365: {
                    366:        char *source;
                    367:        IOBuf_t *IOBuf;
                    368:        unsigned block_size;
                    369:        unsigned dev_size;
                    370:        
                    371:        xpr_stub("IOStub writeAsync: unit %d  offset 0x%x  length 0x%x\n",
                    372:                [self unit], offset, length, 4,5);
                    373:                
                    374:        block_size = [self blockSize];
                    375:        dev_size = [self diskSize];
                    376: 
                    377:        /*
                    378:         * Verify legal parameters.
                    379:         */
                    380:        if([self isWriteProtected]) {
                    381:                return IO_R_NOT_WRITABLE;
                    382:        }
                    383:        source = stub_data + offset * block_size;
                    384:        if((source + length) > (stub_data + (block_size * dev_size))) {
                    385:           
                    386:                xpr_stub("IOStub write: invalid offset/byte count\n",
                    387:                        1,2,3,4,5);
                    388:                return(IO_R_INVALID_ARG);
                    389:        }
                    390: 
                    391:        /*
                    392:         * Just queue up an IOBuf.
                    393:         */
                    394:        IOBuf            = IOMalloc(sizeof(*IOBuf));
                    395:        IOBuf->cmd       = STUB_WRITE;
                    396:        IOBuf->offset    = offset;
                    397:        IOBuf->bytesReq  = length;
                    398:        IOBuf->buf       = buffer;
                    399:        IOBuf->status    = IO_R_INVALID;        /* must be filled in by
                    400:                                                 * I/O thread */
                    401:        IOBuf->pending   = pending;
                    402:        IOBuf->dirRead   = 0;
                    403:        [self enqueueIoBuf:IOBuf];
                    404:        
                    405:        xpr_stub("stub writeAsync: DONE\n", 1,2,3,4,5);
                    406:        return(IO_R_SUCCESS);
                    407: }
                    408: 
                    409: /*
                    410:  * Distributed Objects R/W protocol.
                    411:  */
                    412: - (IOReturn) readAt            : (unsigned)offset              // in blocks
                    413:                                  length : (unsigned)length     // in bytes
                    414:                                  data : (out IOData **)data
                    415:                                  actualLength : (out unsigned *)actualLength
                    416: {
                    417:        IOReturn rtn;
                    418:        IOData *ldata = [[IOData alloc] initWithSize:length];
                    419:        
                    420:        /*
                    421:         * FIXME - when freeFlag is set to YES (which is what we really 
                    422:         * want), this method crashes with the following error messages
                    423:         * when run with the DiskTest app:
                    424:         *
                    425:         *   finishEncoding: send error -101:invalid memory
                    426:         *   uncaught exception : 11001
                    427:         *   objc: FREED(id): message free sent to freed object=0x9c01c
                    428:         * 
                    429:         * When run with the test programs in ../tests, everything works 
                    430:         * OK...
                    431:         *
                    432:         * When we set freeFlag to NO, everything works, but the IOStub
                    433:         * server leaks memory.
                    434:         *
                    435:         * Update 15-Oct-92 - this error only happens when moving at least
                    436:         * one entire page of data. Moving less than a page is OK.
                    437:         */
                    438:        [ldata setFreeFlag:YES];
                    439:        rtn = [self readAt:offset
                    440:                length:length
                    441:                buffer:[ldata data]
                    442:                actualLength:actualLength];
                    443:        if(*actualLength) {
                    444:                *data = ldata;
                    445:        }
                    446:        
                    447:        /*
                    448:         * FIXME - when does the IOData get deallocated??
                    449:         */
                    450:        return rtn;
                    451: }
                    452: 
                    453: /*
                    454:  * DiskRwDistributed protocol.
                    455:  */
                    456: - (IOData *)rreadAt            : (unsigned)offset
                    457:                                  length : (unsigned)length
                    458:                                  rtn : (out IOReturn *)rtn
                    459:                                  actualLength : (out unsigned *)actualLength
                    460: {
                    461:        IOReturn lrtn;
                    462:        IOData *ldata = [[IOData alloc] initWithSize:length];
                    463:        
                    464:        [ldata setFreeFlag:YES];
                    465:        lrtn = [self readAt:offset
                    466:                length:length
                    467:                buffer:[ldata data]
                    468:                actualLength:actualLength];
                    469:        *rtn = lrtn;
                    470:        return ldata;
                    471: }
                    472:        
                    473: - (IOReturn) readAsyncAt       : (unsigned)offset
                    474:                                  length : (unsigned)length
                    475:                                  ioKey : (unsigned)ioKey
                    476:                                  caller : (id)caller
                    477: {
                    478:        /* TBD */
                    479:        return IO_R_UNSUPPORTED;
                    480: }
                    481:                                  
                    482:                          
                    483: - (IOReturn) writeAt           : (unsigned)offset              // in blocks
                    484:                                  length : (unsigned)length     // in bytes
                    485:                                  data : (in IOData *)data
                    486:                                  actualLength : (out unsigned *)actualLength
                    487: {
                    488:        IOReturn rtn;
                    489:        
                    490:        if([data size] < length) {
                    491:                IOLog("%s writeAt: insufficient memory in IOData\n",
                    492:                        [self name]);
                    493:        }
                    494:        rtn = [self writeAt:offset
                    495:                        length:length
                    496:                        buffer:[data data]
                    497:                        actualLength:actualLength];
                    498:        [data free]; 
                    499:        return rtn;
                    500: }
                    501: 
                    502: - (IOReturn)writeAsyncAt       : (unsigned)offset              // in blocks
                    503:                                  length : (unsigned)length     // in bytes
                    504:                                  data : (in IOData *)data
                    505:                                  ioKey : (unsigned)ioKey
                    506:                                  caller : (id)caller
                    507: {
                    508:        return IO_R_UNSUPPORTED;
                    509: }
                    510: @end
                    511: 

unix.superglobalmegacorp.com

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