Annotation of driverkit/libDriver/IOLogicalDisk.m, revision 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: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
        !            25:  *
        !            26:  * IOLogicalDisk.m
        !            27:  *
        !            28:  * HISTORY
        !            29:  * 05-Mar-91    Doug Mitchell at NeXT
        !            30:  *      Created.
        !            31:  */
        !            32: 
        !            33: #import <driverkit/return.h>
        !            34: #import <driverkit/IODisk.h>
        !            35: #ifdef KERNEL
        !            36: #import <kernserv/prototypes.h>
        !            37: #import <mach/mach_interface.h>
        !            38: #import <driverkit/kernelDiskMethods.h>
        !            39: #else  KERNEL
        !            40: #import <mach/mach.h>
        !            41: #import <bsd/libc.h>
        !            42: #endif KERNEL
        !            43: #import <driverkit/IOLogicalDisk.h>
        !            44: #import <driverkit/Device_ddm.h>
        !            45: #import <driverkit/generalFuncs.h>
        !            46: #import <driverkit/SCSIDisk.h>
        !            47: 
        !            48: @interface IOLogicalDisk(private)
        !            49: - (IOReturn)_diskParamCommon   :(u_int)logicalOffset
        !            50:                                  length : (u_int)bytesReq
        !            51:                                  deviceOffset : (unsigned *)deviceOffset       
        !            52:                                  bytesToMove : (u_int *)bytesToMove;
        !            53: 
        !            54: - (IOReturn)computePartition   :(u_int)logicalOffset
        !            55:                                 length : (u_int)bytesReq
        !            56:                                 byteOffset : (unsigned long long *)byteOffset  
        !            57:                                 bytesToMove : (u_int *)bytesToMove;
        !            58: 
        !            59: /* This must be a class method since it's called by
        !            60:  * a class method in DiskPartition.
        !            61:  */
        !            62: 
        !            63: + (IOReturn) reblock           : (id)physicalDisk
        !            64:                                : (BOOL)read
        !            65:                                : (unsigned long long)offset    /* bytes */
        !            66:                                : (unsigned)length              /* bytes */
        !            67:                                : (unsigned char *)buffer
        !            68:                                : (vm_task_t)client
        !            69:                                : (void *)pending
        !            70:                                : (unsigned)physsize;   /* phys blocksize */
        !            71: @end
        !            72: 
        !            73: @implementation IOLogicalDisk
        !            74: 
        !            75: /*
        !            76:  * Standard IODiskDeviceReadingAndWriting methods. We translate into raw device 
        !            77:  * parameters and pass along to _physicalDisk.
        !            78:  */
        !            79: #ifdef KERNEL
        !            80: 
        !            81: - (IOReturn) readAt            : (unsigned)offset 
        !            82:                                  length : (unsigned)length 
        !            83:                                  buffer : (unsigned char *)buffer
        !            84:                                  actualLength : (unsigned *)actualLength
        !            85:                                  client : (vm_task_t)client
        !            86: {
        !            87:     IOReturn rtn;
        !            88:     unsigned bytesToMove;
        !            89:     unsigned long long byteposition;
        !            90:     
        !            91:     rtn = [self computePartition:offset 
        !            92:                            length : length
        !            93:                        byteOffset : &byteposition
        !            94:                        bytesToMove:&bytesToMove];
        !            95: 
        !            96:     if (rtn) {
        !            97:        return(rtn);
        !            98:     }
        !            99: 
        !           100:     /* If the request is aligned with the physical block size, we
        !           101:      * send it directly to the driver. If not, we have to use the
        !           102:      * (synchronous) reblocking IO function to handle size and/or
        !           103:      * alignment mismatches.
        !           104:      */
        !           105: 
        !           106:     if (byteposition % _physicalBlockSize || length % _physicalBlockSize) {
        !           107:     
        !           108:        return([[self class] commonReadWrite
        !           109:                            : _physicalDisk
        !           110:                            : YES                       /* it's a read */
        !           111:                            : byteposition               /* byte offset */
        !           112:                            : (unsigned)bytesToMove     /* bytes */
        !           113:                            : (unsigned char *)buffer
        !           114:                            : (vm_task_t)client
        !           115:                            : (void *)NULL
        !           116:                            : (u_int *)actualLength]);
        !           117: 
        !           118:     } else {                   /* neatly aligned */
        !           119: 
        !           120:        return([_physicalDisk readAt:(byteposition / _physicalBlockSize)
        !           121:                    length:bytesToMove
        !           122:                    buffer:buffer
        !           123:                    actualLength:actualLength
        !           124:                    client:client]);
        !           125:     }
        !           126: }
        !           127:                                  
        !           128: - (IOReturn) readAsyncAt       : (unsigned)offset 
        !           129:                                  length : (unsigned)length 
        !           130:                                  buffer : (unsigned char *)buffer
        !           131:                                  pending : (void *)pending
        !           132:                                  client : (vm_task_t)client
        !           133: {
        !           134:     IOReturn rtn;
        !           135:     unsigned bytesToMove;
        !           136:     unsigned long long byteposition;
        !           137: 
        !           138:     rtn = [self computePartition:offset 
        !           139:                            length : length
        !           140:                        byteOffset : &byteposition
        !           141:                        bytesToMove:&bytesToMove];
        !           142: 
        !           143:        if (rtn) {
        !           144:            return(rtn);        
        !           145:        }
        !           146: 
        !           147:     /* If the request is aligned with the physical block size, we
        !           148:      * send it directly to the driver. If not, we have to use the
        !           149:      * (synchronous) reblocking IO function to handle size and/or
        !           150:      * alignment mismatches.
        !           151:      */
        !           152: 
        !           153:     if (byteposition % _physicalBlockSize || length % _physicalBlockSize) {
        !           154:     
        !           155:        return([[self class] commonReadWrite
        !           156:                            : _physicalDisk
        !           157:                            : YES
        !           158:                            : byteposition              /* byte offset */
        !           159:                            : (unsigned)bytesToMove     /* bytes */
        !           160:                            : (unsigned char *)buffer
        !           161:                            : (vm_task_t)client
        !           162:                            : (void *)pending
        !           163:                            : (u_int *)NULL]);
        !           164: 
        !           165:     } else {                           /* neatly aligned */
        !           166:        return([_physicalDisk readAsyncAt:(byteposition / _physicalBlockSize)
        !           167:                length:bytesToMove
        !           168:                buffer:buffer
        !           169:                pending:pending
        !           170:                client:client]);
        !           171:     }
        !           172: }
        !           173:                                  
        !           174: - (IOReturn) writeAt           : (unsigned)offset 
        !           175:                                  length : (unsigned)length 
        !           176:                                  buffer : (unsigned char *)buffer
        !           177:                                  actualLength : (unsigned *)actualLength
        !           178:                                  client : (vm_task_t)client
        !           179: {
        !           180:     unsigned deviceBlock;
        !           181:     IOReturn rtn;
        !           182:     unsigned bytesToMove;
        !           183:     unsigned long long byteposition;
        !           184:     
        !           185:     if ([self isWriteProtected]) {
        !           186:            return IO_R_NOT_WRITABLE;
        !           187:     }
        !           188: 
        !           189:     rtn = [self computePartition:offset 
        !           190:                            length : length
        !           191:                        byteOffset : &byteposition
        !           192:                        bytesToMove:&bytesToMove];
        !           193: 
        !           194:     if (rtn) {
        !           195:        return(rtn);
        !           196:     }
        !           197: 
        !           198:     /* If the request is aligned with the physical block size, we
        !           199:      * send it directly to the driver. If not, we have to use the
        !           200:      * (synchronous) reblocking IO function to handle size and/or
        !           201:      * alignment mismatches.
        !           202:      */
        !           203: 
        !           204:     if (byteposition % _physicalBlockSize || length % _physicalBlockSize) {
        !           205:     
        !           206:        return([[self class] commonReadWrite
        !           207:                            : _physicalDisk
        !           208:                            : NO                        /* it's a write */
        !           209:                            : byteposition               /* byte offset */
        !           210:                            : (unsigned)bytesToMove     /* bytes */
        !           211:                            : (unsigned char *)buffer
        !           212:                            : (vm_task_t)client
        !           213:                            : (void *)NULL
        !           214:                            : (u_int *)actualLength]);
        !           215: 
        !           216:     } else {                   /* neatly aligned */
        !           217: 
        !           218:        return([_physicalDisk writeAt:(byteposition / _physicalBlockSize)
        !           219:                    length:bytesToMove
        !           220:                    buffer:buffer
        !           221:                    actualLength:actualLength
        !           222:                    client:client]);
        !           223:     }
        !           224: }
        !           225:                                        
        !           226: - (IOReturn) writeAsyncAt      : (unsigned)offset 
        !           227:                                  length : (unsigned)length 
        !           228:                                  buffer : (unsigned char *)buffer
        !           229:                                  pending : (void *)pending
        !           230:                                  client : (vm_task_t)client
        !           231: {
        !           232:     unsigned deviceBlock;
        !           233:     IOReturn rtn;
        !           234:     unsigned bytesToMove;
        !           235:     unsigned long long byteposition;
        !           236: 
        !           237:     if ([self isWriteProtected]) {
        !           238:        return IO_R_NOT_WRITABLE;
        !           239:     }
        !           240: 
        !           241:     rtn = [self computePartition:offset 
        !           242:                            length : length
        !           243:                        byteOffset : &byteposition
        !           244:                        bytesToMove:&bytesToMove];
        !           245: 
        !           246:     if (rtn) {
        !           247:        return(rtn);    
        !           248:     }
        !           249: 
        !           250:     /* If the request is aligned with the physical block size, we
        !           251:      * send it directly to the driver. If not, we have to use the
        !           252:      * (synchronous) reblocking IO function to handle size and/or
        !           253:      * alignment mismatches.
        !           254:      */
        !           255: 
        !           256:     if (byteposition % _physicalBlockSize || length % _physicalBlockSize) {
        !           257:     
        !           258:        return([[self class] commonReadWrite
        !           259:                            : _physicalDisk
        !           260:                            : NO
        !           261:                            : byteposition              /* byte offset */
        !           262:                            : (unsigned)bytesToMove     /* bytes */
        !           263:                            : (unsigned char *)buffer
        !           264:                            : (vm_task_t)client
        !           265:                            : (void *)pending
        !           266:                            : (u_int *)NULL]);
        !           267: 
        !           268:     } else {                           /* neatly aligned */
        !           269: 
        !           270:        return([_physicalDisk writeAsyncAt:(byteposition / _physicalBlockSize)
        !           271:                length:bytesToMove
        !           272:                buffer:buffer
        !           273:                pending:pending
        !           274:                client:client]);
        !           275:     }
        !           276: }
        !           277: 
        !           278: #else  KERNEL
        !           279: 
        !           280: //xxxxx These copies of the routines have not been updated for reblocking.
        !           281: // They aren't used.
        !           282: 
        !           283: - (IOReturn) readAt            : (unsigned)offset 
        !           284:                                  length : (unsigned)length 
        !           285:                                  buffer : (unsigned char *)buffer
        !           286:                                  actualLength : (unsigned *)actualLength
        !           287: {
        !           288:        unsigned deviceBlock;
        !           289:        IOReturn rtn;
        !           290:        unsigned bytesToMove;
        !           291:        
        !           292:        if(rtn = [self _diskParamCommon:offset 
        !           293:            length : length
        !           294:            deviceOffset : &deviceBlock
        !           295:            bytesToMove:&bytesToMove])
        !           296:                return(rtn);    
        !           297:        return([_physicalDisk readAt:deviceBlock
        !           298:                length:bytesToMove
        !           299:                buffer:buffer
        !           300:                actualLength:actualLength]);
        !           301: }
        !           302:                                  
        !           303: - (IOReturn) readAsyncAt       : (unsigned)offset 
        !           304:                                  length : (unsigned)length 
        !           305:                                  buffer : (unsigned char *)buffer
        !           306:                                  pending : (void *)pending
        !           307: {
        !           308:        unsigned deviceBlock;
        !           309:        IOReturn rtn;
        !           310:        unsigned bytesToMove;
        !           311:        
        !           312:        if(rtn = [self _diskParamCommon:offset 
        !           313:            length : length
        !           314:            deviceOffset : &deviceBlock
        !           315:            bytesToMove:&bytesToMove])
        !           316:                return(rtn);    
        !           317:        return([_physicalDisk readAsyncAt:deviceBlock
        !           318:                length:bytesToMove
        !           319:                buffer:buffer
        !           320:                pending:pending]);
        !           321: }
        !           322:                                  
        !           323: - (IOReturn) writeAt           : (unsigned)offset 
        !           324:                                  length : (unsigned)length 
        !           325:                                  buffer : (unsigned char *)buffer
        !           326:                                  actualLength : (unsigned *)actualLength
        !           327: {
        !           328:        unsigned deviceBlock;
        !           329:        IOReturn rtn;
        !           330:        unsigned bytesToMove;
        !           331:        
        !           332:        if ([self isWriteProtected])
        !           333:                return IO_R_NOT_WRITABLE;
        !           334:        if(rtn = [self _diskParamCommon:offset 
        !           335:            length : length
        !           336:            deviceOffset : &deviceBlock
        !           337:            bytesToMove:&bytesToMove])
        !           338:                return(rtn);    
        !           339:        return([_physicalDisk writeAt:deviceBlock
        !           340:                length:bytesToMove
        !           341:                buffer:buffer
        !           342:                actualLength:actualLength]);
        !           343: }                                
        !           344:                                        
        !           345: - (IOReturn) writeAsyncAt      : (unsigned)offset 
        !           346:                                  length : (unsigned)length 
        !           347:                                  buffer : (unsigned char *)buffer
        !           348:                                  pending : (void *)pending
        !           349: {
        !           350:        unsigned deviceBlock;
        !           351:        IOReturn rtn;
        !           352:        unsigned bytesToMove;
        !           353:        
        !           354:        if ([self isWriteProtected])
        !           355:                return IO_R_NOT_WRITABLE;
        !           356:        if(rtn = [self _diskParamCommon:offset 
        !           357:            length : length
        !           358:            deviceOffset : &deviceBlock
        !           359:            bytesToMove:&bytesToMove])
        !           360:                return(rtn);
        !           361:        return([_physicalDisk writeAsyncAt:deviceBlock
        !           362:                length:bytesToMove
        !           363:                buffer:buffer
        !           364:                pending:pending]);
        !           365: }                              
        !           366: 
        !           367: #endif KERNEL
        !           368: 
        !           369: - (IODiskReadyState)updateReadyState
        !           370: {
        !           371:        return [_physicalDisk updateReadyState];
        !           372: }
        !           373: 
        !           374: /*
        !           375:  * Open a connection to physDevice. FIXME: when do we close??
        !           376:  */
        !           377: - (IOReturn)connectToPhysicalDisk : physicalDisk
        !           378: {
        !           379:        IOReturn rtn = IO_R_SUCCESS;
        !           380:        
        !           381:        xpr_disk("connectToPhysicalDiskice\n", 1,2,3,4,5);
        !           382:        _physicalDisk = physicalDisk;
        !           383:        [self setIsPhysical:0];
        !           384:        
        !           385:        /*
        !           386:         * Get some instance variables which must be the same as the
        !           387:         * physDevice's.
        !           388:         */
        !           389:        _physicalBlockSize = [physicalDisk blockSize];
        !           390:        [self setRemovable:[physicalDisk isRemovable]];
        !           391:        [self setFormattedInternal:[physicalDisk isFormatted]];
        !           392:        [self setWriteProtected:[physicalDisk isWriteProtected]];
        !           393:        [self setLogicalDisk:nil];
        !           394: #ifdef KERNEL
        !           395:        [self setDevAndIdInfo:[physicalDisk devAndIdInfo]];
        !           396: #endif KERNEL
        !           397:        return(rtn);
        !           398: }
        !           399: 
        !           400: - (void)setPartitionBase       : (unsigned)partBase
        !           401: {
        !           402:        _partitionBase = partBase;
        !           403: }
        !           404: 
        !           405: 
        !           406: /*
        !           407:  * Determine if this LogicalDisk (or any other LogicalDisks in the
        !           408:  * logicalDisk list) are currently open. Returns NO if none open, else
        !           409:  * YES.
        !           410:  */
        !           411: - (BOOL)isOpen
        !           412: {
        !           413:        if([self isInstanceOpen])
        !           414:                return(YES);
        !           415:        else if([self nextLogicalDisk])
        !           416:                return([[self nextLogicalDisk] isOpen]);
        !           417:        else
        !           418:                return(NO);
        !           419: }
        !           420: 
        !           421: /*
        !           422:  * Free self and any objects in logicalDisk chain.
        !           423:  */
        !           424: - free
        !           425: {
        !           426:        id nextLd;
        !           427:        
        !           428:        nextLd = [self nextLogicalDisk];
        !           429:        if(nextLd) {
        !           430:                [nextLd free];
        !           431:        }
        !           432:        return([super free]);
        !           433: }
        !           434: 
        !           435: - physicalDisk
        !           436: {
        !           437:        return(_physicalDisk);
        !           438: }
        !           439: 
        !           440: - (unsigned)physicalBlockSize
        !           441: {
        !           442:        return(_physicalBlockSize);
        !           443: }
        !           444: 
        !           445: - (void)setPhysicalBlockSize : (unsigned)size
        !           446: {
        !           447:        _physicalBlockSize = size;
        !           448: }
        !           449: 
        !           450: /*
        !           451:  * Pass this on to _physicalDisk.
        !           452:  */
        !           453: - (IOReturn)isDiskReady        : (BOOL)prompt
        !           454: {
        !           455:        return [_physicalDisk isDiskReady:prompt];
        !           456: }
        !           457: 
        !           458: /*
        !           459:  * Determine if any logical disks in the _logicalDisk chain except
        !           460:  * for self are open.
        !           461:  */
        !           462: - (BOOL)isAnyOtherOpen
        !           463: {
        !           464:        id logDisk = [_physicalDisk nextLogicalDisk];
        !           465:        while(logDisk) {
        !           466:                if((logDisk != self) && [logDisk isInstanceOpen]) {
        !           467:                        return YES;
        !           468:                }
        !           469:                logDisk = [logDisk nextLogicalDisk];
        !           470:        }
        !           471:        return NO;
        !           472: }
        !           473: 
        !           474: - (BOOL)isInstanceOpen
        !           475: {
        !           476:        return _instanceOpen;
        !           477: }
        !           478: 
        !           479: - (void)setInstanceOpen : (BOOL)isOpen
        !           480: {
        !           481:        _instanceOpen = (isOpen ? YES : NO);
        !           482: }
        !           483: 
        !           484: /*-----------------------------------------*/
        !           485: 
        !           486: /* Common read/write function; handles reblocking of misaligned requests. */
        !           487: 
        !           488: + (IOReturn) commonReadWrite   : (id)physicalDisk
        !           489:                                : (BOOL)read
        !           490:                                : (unsigned long long)byteposition
        !           491:                                : (unsigned)length              /* bytes */
        !           492:                                : (unsigned char *)buffer
        !           493:                                : (vm_task_t)client
        !           494:                                : (void *)pending
        !           495:                                : (u_int *)actualLength
        !           496: {
        !           497:     IOReturn rtn = IO_R_SUCCESS;
        !           498:     unsigned long aligncount;          /* bytes */
        !           499:     unsigned long integralblocks;
        !           500:     unsigned long integralbytes;
        !           501:     unsigned long transfer;
        !           502:     unsigned long originallength;
        !           503:     unsigned long physsize;                    /* physical blocksize */
        !           504:    // unsigned char *origbuf;
        !           505:     u_int tempactual;
        !           506: 
        !           507:     //origbuf = buffer;
        !           508:     originallength = length;
        !           509:     tempactual = 0;
        !           510:     physsize = [physicalDisk blockSize];
        !           511:     
        !           512:     /* If the beginning of the request is not properly aligned
        !           513:      * with the device block size, or it's less than a block,
        !           514:      * we have to reblock it here to get ourselves aligned.
        !           515:      */
        !           516: 
        !           517:     if ((byteposition % physsize) || (length < physsize)) {
        !           518: 
        !           519:        /* Compute the number of bytes needed
        !           520:         * to bring us into sync with the real size.
        !           521:         */
        !           522:        aligncount = physsize - (byteposition % physsize);
        !           523:        if (aligncount > length) { /* a short read of less than a real block */
        !           524:            aligncount = length;
        !           525:        }
        !           526: 
        !           527:        rtn = [[IOLogicalDisk class] reblock
        !           528:                : physicalDisk
        !           529:                : read                          /* read or write */
        !           530:                : byteposition                  /* start byte position */
        !           531:                : aligncount                    /* byte count */
        !           532:                : buffer
        !           533:                : client
        !           534:                : pending
        !           535:                : physsize];
        !           536:        length          -= aligncount;          /* update length (bytes) */
        !           537:        byteposition    += aligncount;          /* update start byte position */
        !           538:        buffer          += aligncount;          /* update buffer */
        !           539:     }
        !           540:     
        !           541:     /* Now we're aligned. Transfer any integral-block "middle" part
        !           542:      * of the request. The integer divide below excludes any "odd" bytes
        !           543:      * at the end of the request which aren't part of an integral number
        !           544:      * of device blocks.
        !           545:      */
        !           546: 
        !           547:     if (length > 0 && (rtn == IO_R_SUCCESS)) { /* there's more left to do */
        !           548: 
        !           549:        integralblocks = length / physsize;     /* zero if no full blocks */
        !           550: 
        !           551:        if (integralblocks) {           /* transfer this many aligned blocks */
        !           552:            integralbytes = integralblocks * physsize;
        !           553: 
        !           554:            if (read) {
        !           555:                rtn = [physicalDisk readAt:(byteposition / physsize)
        !           556:                    length:integralbytes
        !           557:                    buffer:buffer
        !           558:                    actualLength:&tempactual
        !           559:                    client:client];
        !           560:            } else {
        !           561:                rtn = [physicalDisk writeAt:(byteposition / physsize)
        !           562:                    length:integralbytes
        !           563:                    buffer:buffer
        !           564:                    actualLength:&tempactual
        !           565:                    client:client];
        !           566:            }
        !           567: 
        !           568:            length       -= integralbytes;      /* update length (bytes) */
        !           569:            byteposition += integralbytes;      /* update start block */
        !           570:            buffer       += integralbytes;      /* update buffer */
        !           571:        }
        !           572:     }
        !           573: 
        !           574:     /* If there are any "odd" bytes at the end of the request,
        !           575:      * transfer these now via reblocking.
        !           576:      */
        !           577: 
        !           578:     if (length > 0 && (rtn == IO_R_SUCCESS)) { /* there's more to do */
        !           579: 
        !           580:        rtn = [[IOLogicalDisk class] reblock
        !           581:                        : physicalDisk
        !           582:                        : read
        !           583:                        : byteposition
        !           584:                        : length
        !           585:                        : buffer
        !           586:                        : client
        !           587:                        : pending
        !           588:                        : physsize];
        !           589:     }    
        !           590: 
        !           591:     /* We only remember the actual length if the transfer succeeds. */
        !           592: 
        !           593:     if (rtn == IO_R_SUCCESS) {
        !           594:        tempactual = originallength;
        !           595:     }
        !           596: 
        !           597:     /* Since we've been doing sync IOs here, we have to force a
        !           598:      * completion if the caller's request was async. Done here,
        !           599:      * this is ugly, but we have little choice with the current design.
        !           600:      */
        !           601: 
        !           602:     if (pending) {             /* async: force an I/O completion (ugly) */
        !           603:        [physicalDisk completeTransfer
        !           604:                        : pending
        !           605:            withStatus  : rtn
        !           606:            actualLength : tempactual];
        !           607:     } else {                   /* sync */
        !           608:        *actualLength = tempactual;
        !           609:     }
        !           610: 
        !           611:     return(rtn);
        !           612: }
        !           613: @end
        !           614: 
        !           615: /*
        !           616:  * Generate device-specific parameters from logical parameters.
        !           617:  */
        !           618: @implementation IOLogicalDisk(private)
        !           619: 
        !           620: - (IOReturn)_diskParamCommon   :(unsigned)logicalOffset
        !           621:                                  length : (unsigned)length
        !           622:                 deviceOffset : (unsigned*)deviceOffset 
        !           623:                                  bytesToMove : (unsigned *)bytesToMove
        !           624: {
        !           625:         unsigned ratio = 0;    // bogus compiler warning
        !           626:        int deviceBlocks;
        !           627:        int logicalBlocks;
        !           628:         unsigned block_size;
        !           629:        unsigned dev_size;
        !           630:         IOReturn rtn;
        !           631:         const char *name = [self name];
        !           632: 
        !           633:         /*
        !           634:          * Note we have to 'fault in' a possible non-present physical disk in
        !           635:          * order to get its physical parameters...
        !           636:          */
        !           637:         rtn = [_physicalDisk isDiskReady:YES];
        !           638:         switch(rtn) {
        !           639:             case IO_R_SUCCESS:
        !           640:                 break;
        !           641:             case IO_R_NO_DISK:
        !           642:                 xpr_err("%s diskParamCommon: disk not present\n",
        !           643:                         name, 2,3,4,5);
        !           644:                 return(rtn);
        !           645:             default:
        !           646:                 IOLog("%s deviceRwCommon: bogus return from isDiskReady "
        !           647:                         "(%s)\n",
        !           648:                         name, [self stringFromReturn:rtn]);
        !           649:                 return(rtn);
        !           650:         }
        !           651: 
        !           652:         block_size = [self blockSize];
        !           653:         dev_size = [self diskSize];
        !           654: 
        !           655:         if(length % block_size) {
        !           656:                 IOLog("%s: Bytes requested not multiple of block size\n",
        !           657:                         name);
        !           658:                 return(IO_R_INVALID_ARG);
        !           659:         }
        !           660:         logicalBlocks = length / block_size;
        !           661:         if((logicalOffset + logicalBlocks) > dev_size) {
        !           662:                 if(logicalOffset >= dev_size)
        !           663:                         return(IO_R_INVALID_ARG);
        !           664: 
        !           665:                 /*
        !           666:                  * Truncate.
        !           667:                  */
        !           668:                 logicalBlocks = dev_size - logicalOffset;
        !           669:         }
        !           670:         ratio = block_size / _physicalBlockSize;
        !           671:         deviceBlocks = logicalBlocks * ratio;
        !           672:         *deviceOffset = (logicalOffset * ratio) + _partitionBase;
        !           673:         *bytesToMove = deviceBlocks * _physicalBlockSize;
        !           674:         return(IO_R_SUCCESS);
        !           675: }
        !           676: 
        !           677: - (IOReturn)computePartition   :(unsigned)logicalOffset
        !           678:                                 length : (unsigned)length
        !           679:                                 byteOffset : (unsigned long long *)byteOffset  
        !           680:                                 bytesToMove : (unsigned *)bytesToMove
        !           681: {
        !           682:     unsigned physicalBlocksize;
        !           683:     unsigned logicalBlocksize;
        !           684:     IOReturn rtn;
        !           685:     const char *name = [self name];
        !           686: 
        !           687:     unsigned long long partbase;
        !           688:     unsigned long long partsize;
        !           689:     unsigned long long partend;
        !           690:     unsigned long long reqbase;
        !           691:     
        !           692:     /*
        !           693:      * Note we have to 'fault in' a possible non-present physical disk in 
        !           694:      * order to get its physical parameters...
        !           695:      */
        !           696:     rtn = [_physicalDisk isDiskReady:YES];
        !           697:     switch(rtn) {
        !           698:        case IO_R_SUCCESS:
        !           699:            break;
        !           700:        case IO_R_NO_DISK:
        !           701:            xpr_err("%s diskParamCommon: disk not present\n",
        !           702:                    name, 2,3,4,5);
        !           703:            return(rtn);
        !           704:        default:
        !           705:            IOLog("%s deviceRwCommon: bogus return from isDiskReady "
        !           706:                    "(%s)\n",
        !           707:                    name, [self stringFromReturn:rtn]);
        !           708:            return(rtn);
        !           709:     }
        !           710: 
        !           711:     /* We compute partition information here based on the notion of
        !           712:      * block size, but for better results these boundaries should
        !           713:      * have been set up in bytes from the start.
        !           714:      */
        !           715:     physicalBlocksize = [_physicalDisk blockSize];
        !           716:     logicalBlocksize  = [self blockSize];
        !           717: 
        !           718:     /* If we don't (yet) know our logical block size, we have to
        !           719:      * default to the physical block size.
        !           720:      */
        !           721:     if (logicalBlocksize == 0) {       /* we don't know (yet)*/
        !           722:        logicalBlocksize = physicalBlocksize;
        !           723:     }
        !           724: 
        !           725:     /* The partition base is usually in physical blocks, except when
        !           726:      * we are reblocking HFS on CD-ROM. In that case, all computations
        !           727:      * are done in 512-byte logical blocks.
        !           728:      *
        !           729:      * Is there a better way to detect that we're an HFS partition?
        !           730:      */
        !           731:     if (logicalBlocksize != physicalBlocksize &&
        !           732:        logicalBlocksize == 512) {                      /* must be HFS */
        !           733:        partbase = (unsigned long long)_partitionBase * 
        !           734:                        (unsigned long long)logicalBlocksize;
        !           735:     } else {
        !           736:        partbase = (unsigned long long)_partitionBase *
        !           737:                        (unsigned long long)physicalBlocksize;
        !           738:     }
        !           739:     partsize = (unsigned long long)[self diskSize] *
        !           740:                    (unsigned long long)logicalBlocksize;
        !           741:     partend  = partbase + partsize;
        !           742: 
        !           743:     /* The caller's block offset is in units expressed by the
        !           744:      * partitioning scheme. NeXT labeled disks are usually 1024 bytes,
        !           745:      * HFS is always 512.)
        !           746:      */
        !           747:     reqbase = ((unsigned long long)logicalOffset *
        !           748:                    (unsigned long long)logicalBlocksize) + partbase;
        !           749:     
        !           750:     if (reqbase < partbase || reqbase > partend) {
        !           751:        return(IO_R_INVALID_ARG);
        !           752:     }
        !           753: 
        !           754:     if ((reqbase + length) > partend) {
        !           755:        length = partend - reqbase;     /* truncate the request */
        !           756:     }
        !           757: 
        !           758:     *byteOffset = reqbase;
        !           759:     *bytesToMove = length;
        !           760:     return(IO_R_SUCCESS);
        !           761: }
        !           762: 
        !           763: /* Copy data to (write) or from (read) a misaligned part of a physical block: */
        !           764: 
        !           765: #define MAX_REBLOCK_SIZE 2048
        !           766: 
        !           767: + (IOReturn) reblock           : (id)physicalDisk
        !           768:                                : (BOOL)read
        !           769:                                : (unsigned long long)offset    /* bytes */
        !           770:                                : (unsigned)length              /* bytes */
        !           771:                                : (unsigned char *)buffer
        !           772:                                : (vm_task_t)client
        !           773:                                : (void *)pending
        !           774:                                : (unsigned)physsize    /* phys blocksize */
        !           775: {
        !           776:     IOReturn rtn;
        !           777:     unsigned long physblock;
        !           778:     int bufoffset;
        !           779:     u_int tempactual;
        !           780:     id controller;
        !           781:     char *reblockbuf;
        !           782:     void *freePtr;
        !           783:     unsigned freeCnt;
        !           784: 
        !           785:     /* Allocate a buffer to hold the (larger) device block. This isn't
        !           786:      * efficient since we allocate and free the buffer each time through,
        !           787:      * but we're just trying to make the thing work for now.
        !           788:      */
        !           789: 
        !           790:     controller = [physicalDisk controller];
        !           791:     reblockbuf = (char *)[controller allocateBufferOfLength:MAX_REBLOCK_SIZE
        !           792:                            actualStart:&freePtr
        !           793:                            actualLength:&freeCnt];
        !           794: 
        !           795:     bzero(reblockbuf,MAX_REBLOCK_SIZE);
        !           796: 
        !           797:     /* Figure out which physical block we need, and load it: */
        !           798: 
        !           799:     physblock = offset / physsize;
        !           800: 
        !           801:     rtn = [physicalDisk readAt
        !           802:                    :physblock
        !           803:            length:physsize
        !           804:            buffer:reblockbuf
        !           805:            actualLength:&tempactual
        !           806:            client:client];
        !           807: 
        !           808:     if (rtn != IO_R_SUCCESS) {
        !           809:        return(rtn);
        !           810:     }
        !           811:     
        !           812:     /* Now copy what the client wants, in the direction specified: */
        !           813: 
        !           814:     bufoffset = offset % physsize;
        !           815: 
        !           816:     if (read) {
        !           817:        bcopy(&reblockbuf[bufoffset],buffer,length); /* read : buf to client */
        !           818:     } else {
        !           819:        bcopy(buffer,&reblockbuf[bufoffset],length); /* write: client to buf */
        !           820:            
        !           821:        /* If writing, flush the buffer to the device: */
        !           822:        rtn = [physicalDisk writeAt:physblock
        !           823:                    length:physsize
        !           824:                    buffer:reblockbuf
        !           825:                    actualLength:&tempactual
        !           826:                    client:client];
        !           827:     }
        !           828: 
        !           829:     IOFree(freePtr,freeCnt);
        !           830:     return(IO_R_SUCCESS);
        !           831: }
        !           832: 
        !           833: @end

unix.superglobalmegacorp.com

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