Annotation of driverkit/libDriver/IOLogicalDisk.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: /*     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.