Annotation of driverkit/libDriver/IODiskPartition.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:  * IODiskPartition.m - implementation of NeXT-style logical disk.
                     27:  *
                     28:  * HISTORY
                     29:  * 22-Jan-98   radar 1669467 - ISO 9660 CD support - jwc
                     30:  * 15-Dec-92   Sam Streeper (sam) at NeXT
                     31:  *     Added support for a NeXT disk on a MS-DOS partition
                     32:  * 01-May-91    Doug Mitchell at NeXT
                     33:  *      Created.
                     34:  */
                     35: 
                     36: #define DRIVER_PRIVATE 1
                     37: 
                     38: #import <driverkit/return.h>
                     39: #import <driverkit/IODiskPartition.h>
                     40: #import <driverkit/generalFuncs.h>
                     41: #import <bsd/dev/disk_label.h>
                     42: #import <bsd/sys/disktab.h>
                     43: #ifdef KERNEL
                     44: #import <kernserv/prototypes.h>
                     45: #import <driverkit/kernelDiskMethods.h>
                     46: #import <driverkit/kernelDiskMethodsPrivate.h>
                     47: #import <driverkit/kernelDriver.h>
                     48: #import <machkit/NXLock.h>
                     49: #else  KERNEL
                     50: #import <bsd/libc.h>
                     51: #endif KERNEL
                     52: #import <kern/time_stamp.h>
                     53: #import <driverkit/Device_ddm.h>
                     54: #import <mach/vm_param.h>
                     55: #import <driverkit/disk_label.h>
                     56: #import <driverkit/diskstruct.h>
                     57: #ifdef i386
                     58: #import <bsd/dev/i386/disk.h>
                     59: #endif i386
                     60: #import <architecture/byte_order.h>
                     61: #import "label_subr.h"
                     62: #import <driverkit/IODeviceDescription.h>
                     63: #import <bsd/dev/voldev.h>
                     64: #ifdef ppc
                     65: #import <bsd/dev/ppc/disk.h>
                     66: #endif
                     67: 
                     68: /* Define GROK_DOS if scsi driver is to understand MS-DOS partitions.
                     69:  * It only finds the partition with the NeXT name.  Live partition is
                     70:  * not affected.  -sam
                     71:  *
                     72:  * define GROK_APPLE if we want to look to a Rhapsody partition on a
                     73:  * Apple Partitioned disk
                     74:  */
                     75: #ifdef i386
                     76: #define        GROK_DOS
                     77: #endif
                     78: 
                     79: #ifdef ppc
                     80: #define GROK_APPLE 1
                     81: #endif
                     82: 
                     83: // seconds to wait for disk ready at probe time
                     84: #define DELAY_AT_PROBE 0
                     85: 
                     86: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                     87: 
                     88: #define HFS_PART_TYPE "Apple_HFS"
                     89: 
                     90: #endif //bknight - 12/3/97 - Radar #2004660
                     91: 
                     92: 
                     93: @interface IODiskPartition(Private)
                     94: 
                     95: /*
                     96:  * Private methods.
                     97:  */                              
                     98: /*
                     99:  * Examine a known good label, initialize LogicalDisk parameters for the
                    100:  * raw device (on which this method is invoked) and create block devices
                    101:  * as appropriate.
                    102:  *
                    103:  * Invoked by LogicalDisk +probe, upon disk insertion, and when a new label
                    104:  * is written.
                    105:  */
                    106: - (void) _probeLabel           : (disk_label_t *)labelp;
                    107: 
                    108: /*
                    109:  * Assign logical disk parameters for a partition instance.
                    110:  */
                    111: - (void)_initPartition         : (int)partNum
                    112:               physicalPartition : (int)physNum 
                    113:                         disktab : (struct disktab *)dtp;
                    114:                                  
                    115: /*
                    116:  * Free all partition instances other than partition 0.
                    117:  */
                    118: - (IOReturn)_freePartitions;
                    119: 
                    120: /*
                    121:  * Determine if any block devices in the logicalDisk chain are open.
                    122:  */
                    123: - (BOOL)isAnyBlockDevOpen;
                    124: 
                    125: /*
                    126:  * Verify that it's safe to do an operation which will result in a call
                    127:  * to _freePartitions.
                    128:  */
                    129: - (IOReturn)checkSafeConfig    : (const char *)op;
                    130: 
                    131: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    132: 
                    133: /*
                    134:  * IODiskPartition knows how to
                    135:  * Create HFS Devices From Apple Partition Map.
                    136:  */
                    137: + (void)CreateHFSDevicesFromApplePartitionMap : (id)physicalDisk;
                    138: 
                    139: /*
                    140:  * Assign logical disk parameters for a partition instance.
                    141:  */
                    142: 
                    143: - (void)       _initHFSPartition : (int) partitionNum
                    144:                        physicalPartNum : (int) physNum
                    145:                        diskSize : (int) diskSize
                    146:                        partitionBase : (int) partitionBase;
                    147: 
                    148: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    149:                                  
                    150: @end
                    151: 
                    152: 
                    153: @implementation IODiskPartition
                    154: 
                    155: + (IODeviceStyle)deviceStyle
                    156: {
                    157:        return IO_IndirectDevice;
                    158: }
                    159: 
                    160: /*
                    161:  * The protocol we need as an indirect device.
                    162:  */
                    163: static Protocol *protocols[] = {
                    164:        @protocol(IOPhysicalDiskMethods),
                    165:        @protocol(IODiskReadingAndWriting),
                    166:        nil
                    167: };
                    168: 
                    169: + (Protocol **)requiredProtocols
                    170: {
                    171:        return protocols;
                    172: }
                    173: 
                    174: /*
                    175:  * Attempt to read label of physical device. If valid label, create an 
                    176:  * instance of LogicalDisk for each valid partition as well as for the 
                    177:  * Unix raw device. Returns YES if any instances were created. 
                    178:  */
                    179: + (BOOL)probe : deviceDescription
                    180: {
                    181:        id              physDisk = [deviceDescription directDevice];
                    182:        int             try;
                    183:        IODiskReadyState        ready;
                    184:        IOReturn        rtn;
                    185:        disk_label_t    *labelp = NULL;
                    186:        IODiskPartition *part0p;
                    187:        BOOL            frtn = YES;     // when would this be NO?
                    188:        char            name[30];
                    189:        id              ld;
                    190:        const char      *physName = [physDisk name];
                    191:        unsigned        physBlockSize = 0;
                    192:        unsigned        physDiskSize = 0;
                    193:        unsigned        formattedFlag;
                    194:        BOOL            logParams = NO;
                    195:        BOOL            logLabel = NO;
                    196:        IODiskReadyState        oldReady;
                    197:        
                    198:        xpr_disk("IODiskPartition probe\n", 1,2,3,4,5);
                    199:        /*
                    200:         * First of all, we're only interested in physical disks.
                    201:         * (Shouldn't this be covered by our requiredProtocols values?)
                    202:         */
                    203:        if(![physDisk isPhysical]) {
                    204:                return NO;
                    205:        }
                    206:        
                    207:        /*
                    208:         * Create a partition 0 instance if there isn't already one; attach 
                    209:         * it to physDisk. There will already be a partition 0 instance if 
                    210:         * this probe is in response to a disk insertion as opposed to 
                    211:         * initial device configuration.
                    212:         */
                    213:        ld = [physDisk nextLogicalDisk];
                    214:        if(ld != nil) {
                    215:                part0p = (IODiskPartition *)ld;
                    216:                
                    217:                /*
                    218:                 * Update physical parameters.
                    219:                 */
                    220:                [part0p connectToPhysicalDisk:physDisk];
                    221:                part0p->_labelValid = 0;    
                    222:                part0p->_physicalPartition = 0;
                    223: 
                    224: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    225:                part0p->_hfsValid = 0;    
                    226: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    227:                part0p->_blockDeviceOpen = 0;
                    228:                part0p->_rawDeviceOpen = 0;
                    229:                IOLog("\n");
                    230:        }
                    231:        else {
                    232:                part0p = [IODiskPartition new];
                    233:                sprintf(name, "%sa", physName);
                    234:                [part0p setName:name];
                    235:                [part0p setDeviceKind:"IODiskPartition"];
                    236:                [part0p setDriveName:"IODiskPartition Partition"]; 
                    237:                [part0p setLocation:NULL];
                    238:                 part0p->_partitionWaitLock = [[NXConditionLock alloc] init];
                    239:                IOGetTimestamp( &part0p->_probeTime);
                    240:                [part0p init];
                    241:                [part0p connectToPhysicalDisk:physDisk];
                    242:                 [part0p setDeviceDescription:deviceDescription];
                    243:                [physDisk setLogicalDisk:part0p];
                    244:                part0p->_labelValid = 0;    
                    245: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    246:                part0p->_hfsValid = 0;    
                    247: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    248:                part0p->_blockDeviceOpen = 0;
                    249:                part0p->_rawDeviceOpen = 0;
                    250:        
                    251: #ifdef KERNEL
                    252:                /*
                    253:                 * Register both physDisk and partition 0 with Unix 
                    254:                 * level owner.
                    255:                 */
                    256:                [physDisk registerUnixDisk:0];
                    257:                [part0p registerUnixDisk:0];
                    258: #endif KERNEL
                    259:        }
                    260:        
                    261:        /*
                    262:         * Give the drive a chance to spin up.
                    263:         */
                    264:        oldReady = [physDisk lastReadyState];
                    265: 
                    266: #if DELAY_AT_PROBE
                    267:        if( (physName[0] == 'f') && (physName[1] == 'd'))
                    268:            ready = [physDisk updateReadyState];
                    269:        else {
                    270:            for(try = 0; try < DELAY_AT_PROBE; try++) {
                    271:                ready = [physDisk updateReadyState];
                    272:                switch(ready) {
                    273:                    case IO_Ready:      
                    274:                        goto goOn;              /* go for it */
                    275:                    case IO_NotReady:
                    276:                        break;                  /* try again */
                    277:                    case IO_NoDisk:
                    278:                        if (try > 0)
                    279:                            IOLog("\n");
                    280:                        goto done;              /* forget it */
                    281:                    case IO_Ejecting:   
                    282:                        break;                  /* try again */
                    283:                }
                    284:                if(try == 0)
                    285:                        IOLog("%s: Waiting for drive to come ready", physName);
                    286:                else
                    287:                        IOLog(".");
                    288:                IOSleep(1000);
                    289:            }
                    290:          goOn:
                    291:            if (try > 0)
                    292:                IOLog("\n");
                    293:        }
                    294: #else
                    295:         ready = [physDisk updateReadyState];
                    296: #endif
                    297:        [physDisk setLastReadyState:ready];
                    298:        if(ready != IO_Ready) {
                    299:                IOLog("%s: Disk Not Ready\n", physName);
                    300:                xpr_disk("IODiskPartition probe: Disk Not Ready\n", 1,2,3,4,5);
                    301:                goto done;
                    302:        }
                    303: 
                    304:        /*
                    305:         * If the disk just came ready, have driver update its physical 
                    306:         * parameters.
                    307:         */
                    308:        if(oldReady != IO_Ready) {
                    309:                [physDisk updatePhysicalParameters];
                    310:        }
                    311:                
                    312:        /*
                    313:         * If disk is not formatted, forget the rest of this.
                    314:         */
                    315:        formattedFlag = [physDisk isFormatted];
                    316:        if(!formattedFlag) {
                    317:                IOLog("%s: Disk Unformatted\n", physName);
                    318:                xpr_disk("IODiskPartitionProbe: physDisk %s not formatted\n", 
                    319:                        physName, 2,3,4,5);
                    320:                goto done;
                    321:        }
                    322: 
                    323:        physDiskSize = [physDisk diskSize];
                    324:        physBlockSize = [physDisk blockSize];
                    325: 
                    326:        [part0p setPhysicalBlockSize:physBlockSize];
                    327: 
                    328:        logParams = YES;
                    329: 
                    330:        /*
                    331:         * Try to read a label.
                    332:         */
                    333:        labelp = IOMalloc(sizeof(disk_label_t));
                    334:        rtn = [part0p readLabel:labelp];
                    335:        if(rtn) {               
                    336:                xpr_disk("IODiskPartition probe: No Label\n", 1,2,3,4,5);
                    337:                IOLog("%s: No Valid Disk Label\n", physName);
                    338:                
                    339:                /*
                    340:                 * Set up blockSize and diskSize of partition A
                    341:                 * to be the same as our physicalDisk's for now.
                    342:                 */
                    343:                [part0p setBlockSize:physBlockSize];
                    344:                [part0p setDiskSize:[physDisk diskSize]];
                    345: 
                    346:                /* Remember to reset the partition base to zero,
                    347:                 * since we don't yet have any recognizable
                    348:                 * partitioning information.
                    349:                 */
                    350:                [part0p setPartitionBase:0];
                    351:        }
                    352:        else {
                    353:                logLabel = YES;
                    354:        
                    355:                /*
                    356:                 * Initialize remaining device parameters and create 
                    357:                 * additional partition instances as appropriate.
                    358:                 */
                    359:                [part0p _probeLabel:labelp];
                    360:        }
                    361: 
                    362: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    363: 
                    364:        [self CreateHFSDevicesFromApplePartitionMap:deviceDescription];
                    365: 
                    366: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    367: 
                    368:        if( part0p->_partitionWaitLock) {
                    369:             [part0p->_partitionWaitLock lock];
                    370:             [part0p->_partitionWaitLock unlockWith:YES];
                    371:        }
                    372: done:
                    373:        if(logParams) {
                    374:                unsigned kbytes;
                    375:                
                    376:                IOLog("%s: Device Block Size: %u bytes\n",
                    377:                        physName, physBlockSize);
                    378:                kbytes = (physDiskSize / 1024) * physBlockSize;
                    379:                if(kbytes > (10 * 1024)) {
                    380:                        IOLog("%s: Device Capacity:   %u MB\n", 
                    381:                                physName, kbytes / 1024);
                    382:                }
                    383:                else {
                    384:                        IOLog("%s: Device Capacity:   %u KB\n", 
                    385:                                physName, physDiskSize * physBlockSize / 
                    386:                                1024);
                    387:                }
                    388:        }
                    389:        if(logLabel) {
                    390:                IOLog("%s: Disk Label:        %s\n", 
                    391:                        physName, labelp->dl_label);
                    392:        }
                    393:        if(labelp != NULL) {
                    394:                IOFree(labelp, sizeof(disk_label_t));
                    395:        }
                    396: 
                    397:        if(ld == nil)
                    398:                [part0p registerDevice];
                    399: 
                    400:        return(frtn);
                    401: }
                    402: 
                    403: #ifdef GROK_DOS
                    404: /* returns the offset to the NeXT partition of an MSDOS partitioned
                    405:  * hard disk (0 if it isn't a DOS disk), or a (negative) IOReturn.  
                    406:  */
                    407: - (int) NeXTpartitionOffset
                    408: {
                    409:        IOReturn                frtn = 0;
                    410:        IOReturn                rtn;
                    411:        unsigned                bytesXfr;
                    412:        id                      physDisk = [self physicalDisk];
                    413:        /*
                    414:         * Force page alignment...
                    415:         */
                    416:        unsigned char           *blk= IOMalloc(PAGE_SIZE);
                    417:        struct disk_blk0        *blk0;
                    418:        struct fdisk_part       *fd;
                    419:        int                     n;
                    420:        BOOL                    validPart = NO;
                    421:        
                    422:        if ([self physicalBlockSize] != DISK_BLK0SZ) {
                    423:                frtn = 0;
                    424:                goto out;
                    425:        }
                    426:        // fixme - can I really transfer to unwired, unaligned buffer?
                    427:         rtn = [[super class] commonReadWrite
                    428:                    : physDisk
                    429:                    : YES                       /* read */
                    430:                    : (unsigned long long)DISK_BLK0 * [physDisk blockSize]
                    431:                    : DISK_BLK0SZ       /* bytes */
                    432:                    : blk
                    433:                    : IOVmTaskSelf()
                    434:                    : (void *)NULL
                    435:                    : &bytesXfr];
                    436: 
                    437:        if (rtn) {
                    438:                frtn = IO_R_NO_BLOCK_ZERO;
                    439:                goto out;
                    440:        }
                    441: 
                    442:        // Check for a valid DOS boot block.
                    443:        blk0 = (struct disk_blk0 *)blk;
                    444:        if (blk0->signature != DISK_SIGNATURE) {
                    445:                goto out;
                    446:        }
                    447: 
                    448:        // Check to see if the disk has been partitioned with FDISK
                    449:        // to allow DOS and ufs filesystems to exist on the same disk
                    450:        fd = (struct fdisk_part *)blk0->parts;    
                    451:        for (n = 0; n < FDISK_NPART; n++, fd++) {
                    452:                switch(fd->systid) {
                    453:                    case 0:
                    454:                        /*
                    455:                         * Not valid partition, meaningless.
                    456:                         */
                    457:                        break;
                    458:                    case FDISK_NEXTNAME:
                    459:                        /*
                    460:                         * Valid NeXT partition.
                    461:                         */
                    462:                        frtn = fd->relsect;
                    463:                         _physicalPartition = n;
                    464:                        goto out;
                    465:                    default:
                    466:                        /*
                    467:                         * Not what we're looking for, but this means that
                    468:                         * we can't use partition 0.
                    469:                         */
                    470:                        validPart = YES;
                    471:                        break;
                    472:                }
                    473:        }
                    474:        if(validPart) {
                    475:                frtn = IO_R_NO_NEXT_PART;
                    476:        }
                    477:        else {
                    478:                /*
                    479:                 * No valid partitions; treat same as "no valid block 0".
                    480:                 */
                    481:        }
                    482: out:
                    483:        IOFree(blk, PAGE_SIZE);
                    484:        return frtn;
                    485: }
                    486: #endif GROK_DOS
                    487: 
                    488: #ifdef GROK_APPLE
                    489: /*
                    490:  * Check for an apple partition:
                    491:  *
                    492:  */
                    493: #define BLOCKSIZE_512_BYTES    512
                    494: 
                    495: - (int) NeXTpartitionOffset
                    496: {
                    497:        unsigned char *         blk;
                    498:        Block0 *                blk0;
                    499:        unsigned long           blocksize = [self physicalBlockSize];
                    500:        unsigned                bytesXfr;
                    501:        IOReturn                frtn = 0;
                    502:        id                      physDisk = [self physicalDisk];
                    503:        IOReturn                rtn;
                    504: 
                    505:        blk = IOMalloc(PAGE_SIZE); /* force page alignment */
                    506:        blk0 = (Block0 *)blk;
                    507: 
                    508:        /* check block 0 for valid Apple partition signature */
                    509: 
                    510:         rtn = [[super class] commonReadWrite
                    511:                                : physDisk
                    512:                                : YES                   /* read */
                    513:                                : (unsigned long long)0 /* byte offset */
                    514:                                : PAGE_SIZE     /* bytes */
                    515:                                : blk
                    516:                                : IOVmTaskSelf()
                    517:                                : (void *)NULL
                    518:                                : &bytesXfr];
                    519:         
                    520:         /* scan for the rhapsody apple ufs partition */
                    521:        if (rtn)
                    522:            frtn = IO_R_NO_BLOCK_ZERO;
                    523:        else {
                    524:            unsigned int                block = 1;
                    525:            unsigned int                entry_within_block = 0;
                    526:            int                         n;
                    527:            unsigned int                nentries_per_block = 1;
                    528:            unsigned int                numPartBlocks;
                    529:            DPME *                      partEntry;
                    530:            int                         physNum;
                    531: 
                    532:            /* check if there is a valid map at 512 offset */
                    533:            partEntry = (DPME *)(blk + BLOCKSIZE_512_BYTES);
                    534:            if (blocksize > BLOCKSIZE_512_BYTES) {
                    535:                if (NXSwapBigShortToHost(partEntry->dpme_signature) 
                    536:                    == DPME_SIGNATURE) {
                    537:                    /* there is a valid map, and the device blocksize
                    538:                     * is > 512, which means we probably have a CDROM
                    539:                     * using 2K, but having valid 512 map
                    540:                     */
                    541:                    block = 0;
                    542:                    nentries_per_block = blocksize / BLOCKSIZE_512_BYTES;
                    543:                    entry_within_block = 1;
                    544:                }
                    545:                else
                    546:                    partEntry = (DPME *)(blk + blocksize);
                    547:            }
                    548:          if (NXSwapBigShortToHost(partEntry->dpme_signature) == DPME_SIGNATURE) {
                    549:            numPartBlocks = NXSwapBigLongToHost(partEntry->dpme_map_entries);
                    550: #ifdef PRINT_APT
                    551:            IOLog("Apple Partition table (%d entries)...\n", numPartBlocks);
                    552: #endif PRINT_APT
                    553: 
                    554:             physNum = 1;
                    555:            for (n = 0; n < numPartBlocks; n++) {
                    556:                int ufs_partition_set = 0;
                    557: 
                    558:                if (NXSwapBigShortToHost(partEntry->dpme_signature) 
                    559:                    != DPME_SIGNATURE) {
                    560:                    break;
                    561:                }
                    562:                if (strcmp(partEntry->dpme_type, RHAPSODY_PART_TYPE) == 0
                    563:                    && ufs_partition_set == 0) {
                    564:                    unsigned long part_offset;
                    565: 
                    566:                    part_offset 
                    567:                        = NXSwapBigLongToHost(partEntry->dpme_pblock_start);
                    568:                    if ((part_offset / nentries_per_block * nentries_per_block)
                    569:                        != part_offset) {
                    570:                        IOLog("IODiskPartition: " RHAPSODY_PART_TYPE
                    571:                              " partition base (%ld x 512) is not"
                    572:                              " a multiple of the devblksize %ld\n",
                    573:                              part_offset, blocksize);
                    574:                        frtn = IO_R_NO_NEXT_PART;
                    575:                        break;
                    576:                    }
                    577:        
                    578:                    part_offset = part_offset / nentries_per_block;
                    579: #ifdef PRINT_APT
                    580:                    IOLog("%s: UFS partition at offset %ld\n",
                    581:                          [physDisk name], part_offset);
                    582: #endif PRINT_APT
                    583:                    frtn = (IOReturn)part_offset;
                    584:                    ufs_partition_set = 1;
                    585:                     _physicalPartition = physNum;
                    586:                }
                    587: #ifdef PRINT_APT
                    588:                IOLog("Apple Partition entry %d:\n", n + 1);
                    589:                IOLog("  Name: %s, Type %s, size: %d\n", 
                    590:                       partEntry->dpme_name, partEntry->dpme_type,
                    591:                       partEntry->dpme_pblocks);
                    592:                IOLog("block %d entry %d (of %d) blocksize %d\n", 
                    593:                       block, entry_within_block + 1,
                    594:                       nentries_per_block, blocksize);
                    595: #endif PRINT_APT
                    596:                partEntry++;
                    597:                 physNum++;
                    598:                if (++entry_within_block == nentries_per_block) {
                    599:                    block++;
                    600:                    entry_within_block = 0;
                    601:                    partEntry = (DPME *)blk;
                    602: 
                    603:                    rtn = [[super class] commonReadWrite
                    604:                                : physDisk
                    605:                                : YES                   /* read */
                    606:                    : (unsigned long long)block * blocksize /* byte offset */
                    607:                                : blocksize     /* bytes */
                    608:                                : blk
                    609:                                : IOVmTaskSelf()
                    610:                                : (void *)NULL
                    611:                                : &bytesXfr];
                    612:                    
                    613:                    if (rtn) {
                    614:                        frtn = IO_R_NO_NEXT_PART;
                    615:                        break;
                    616:                    }
                    617:                }
                    618:            }
                    619:          } /* DPME signature validation */
                    620:        } /* scan for Apple rhapsody ufs partitions */
                    621:        IOFree(blk, PAGE_SIZE);
                    622:        return frtn;
                    623: }
                    624: 
                    625: - getDevicePath:(char *)path maxLength:(int)maxLen useAlias:(BOOL)doAlias
                    626: {
                    627:     if( [[self physicalDisk] 
                    628:        getDevicePath:path maxLength:maxLen useAlias:doAlias]) {
                    629: 
                    630:        char partStr[ 12 ];
                    631: 
                    632:        sprintf( partStr, ":%x", _physicalPartition);
                    633:        strcat( path, partStr);
                    634:        return( self);
                    635:     }
                    636:     return( nil);
                    637: }
                    638: 
                    639: #endif GROK_APPLE
                    640: 
                    641: /*
                    642:  * Read disk label. label_p must does not have to be aligned; we do a
                    643:  * page-aligned read to satisfy any possible DMA requirements.
                    644:  *
                    645:  * This is only invoked on the raw device. This can be invoked on a 
                    646:  * drive with no disk present; we'll do a 'isDiskReady:YES" to get a 
                    647:  * disk if necessary.
                    648:  *
                    649:  * This reads labels as raw m68k disk_label_t's. On successful return,
                    650:  * *label_p contains a label which is valid for the current architecture;
                    651:  * the transformation is performed per the API in <driverkit/disk_label.h>.
                    652:  */
                    653: 
                    654: - (IOReturn) readLabel : (disk_label_t *)label_p
                    655: {
                    656:        int                     label_num;
                    657:        IOReturn                rtn;
                    658:        int                     found = 0;
                    659:        int                     blocksInLabel;
                    660:        int                     bytesInLabel;
                    661:        unsigned                bytesXfr;
                    662:        char                    *raw_label;
                    663:        int                     labelBufSize;
                    664:        id                      physDisk = [self physicalDisk];
                    665:        unsigned                physBlockSize = [self physicalBlockSize];
                    666:        unsigned                physFormatted;
                    667:         unsigned               blocksize;
                    668:        const char              *disk_name = [self name];
                    669:        /* offset of NeXT disk on dos or Apple partition */
                    670:        int                     part_offset = 0;
                    671:        
                    672:        xpr_disk("IODiskPartition readLabel\n", 1,2,3,4,5);
                    673:        
                    674:        /*
                    675:         * Note we have to 'fault in' a possible non-present disk in 
                    676:         * order to get its physical parameters...
                    677:         */
                    678:        rtn = [physDisk isDiskReady:YES];
                    679:        switch(rtn) {
                    680:            case IO_R_SUCCESS:
                    681:                break;
                    682:            case IO_R_NO_DISK:
                    683:                xpr_err("%s readLabel: disk not present\n", disk_name, 
                    684:                        2,3,4,5);
                    685:                return(rtn);
                    686:            default:
                    687:                IOLog("%s readLabel: bogus return from isDiskReady (%s)\n",
                    688:                        disk_name, [self stringFromReturn:rtn]);
                    689:                return(rtn);
                    690:        }
                    691:        
                    692:        physFormatted = [physDisk isFormatted];
                    693:        if((physBlockSize == 0) || !physFormatted) {
                    694:                xpr_err("%s readLabel: physDisk UNFORMATTED\n", 
                    695:                        disk_name, 2,3,4,5);
                    696:                return(IO_R_UNFORMATTED);
                    697:        }
                    698:        
                    699: #if defined(GROK_DOS) || defined(GROK_APPLE)
                    700:        part_offset = [self NeXTpartitionOffset];
                    701:        if (part_offset < 0) {
                    702:                return part_offset;
                    703:        }
                    704: #ifdef DEBUG
                    705:        if (part_offset > 0) {
                    706:                printf("found NeXT disk partition at offset"
                    707:                        ", offset = %d sectors\n", part_offset);
                    708:        }
                    709: #endif DEBUG
                    710: #endif defined(GROK_DOS) || defined(GROK_APPLE)
                    711: 
                    712:        /*
                    713:         * Careful, we're reading in an m68k-style label...
                    714:         */
                    715:        blocksInLabel = howmany(SIZEOF_DISK_LABEL_T, physBlockSize);
                    716:        bytesInLabel = blocksInLabel * physBlockSize;
                    717:        labelBufSize = round_page(bytesInLabel);
                    718:        
                    719:        /*
                    720:         * This assumes that the memory allocator used by IOMalloc will 
                    721:         * return one physically contiguous page if we ask it for one
                    722:         * page...should be OK, right?
                    723:         * This used to be vm_allocate(), but can't DMA to IOTask's
                    724:         * virtual memory.
                    725:         */
                    726:        raw_label = IOMalloc(labelBufSize);
                    727:        for(label_num=0; label_num<NLABELS; label_num++) {
                    728: 
                    729:        /* To read a disk label, we *should* use the blocksize of the
                    730:         * enclosing partition, but we don't know what that is.
                    731:         *
                    732:         * As a workaround, we can use the *physical* blocksize. By
                    733:         * doing so, we will always compute the proper offset for
                    734:         * fixed disks using Mac, FDISK, or *no* partitioning scheme,
                    735:         * since all these schemes assume a 512 byte blocksize.
                    736:         * (It is possible for a Mac partition map to imply a non-512
                    737:         * blocksize, but in practice this is rare).
                    738:         *
                    739:         * Using the physical blocksize would not iterate properly
                    740:         * through all four labels on a Mac-partitioned CD-ROM, because
                    741:         * we'd be using 2K blocks instead of the Mac partition's 512.
                    742:         * This, however, *still* luckily works because the first label
                    743:         * is at offset zero: offset zero is always the same no matter
                    744:         * what you're multiplying by to get that zero!
                    745:         *
                    746:         * Once we find a valid label (often the one at offset zero),
                    747:         * we immediately reset our logical blocksize, so after that
                    748:         * point things work normally.
                    749:         */
                    750: 
                    751:        blocksize = [physDisk blockSize];
                    752: 
                    753:                        rtn = [[super class] commonReadWrite
                    754:                                : physDisk
                    755:                                : YES                   /* read */
                    756:                                : ((unsigned long long)part_offset + 
                    757:                                        (label_num * blocksInLabel))
                    758:                                            * blocksize /* byte offset */
                    759:                                : bytesInLabel  /* bytes */
                    760:                                : raw_label
                    761:                                : IOVmTaskSelf()
                    762:                                : (void *)NULL
                    763:                                : &bytesXfr];
                    764:             if((rtn == IO_R_SUCCESS) &&
                    765:                   (bytesXfr == bytesInLabel)) {
                    766:                        
                    767:                        /*
                    768:                         * Is it a valid disk label?
                    769:                         */
                    770:                        const char *rtn;
                    771:                        
                    772:                        rtn = check_label(raw_label, 
                    773:                                part_offset + (label_num*blocksInLabel));
                    774:                        if(rtn == NULL) {
                    775:                                found++;
                    776:                                break;
                    777:                        }
                    778: #ifdef DEBUG
                    779:                        else {
                    780:                                IOLog("%s\n", rtn);
                    781:                        }
                    782: #endif DEBUG
                    783:                }
                    784:                
                    785:                /*
                    786:                 * there is one fatal error here - disk not present.
                    787:                 */
                    788:                if(rtn == IO_R_NO_DISK)
                    789:                        break;
                    790:        }
                    791: 
                    792:        if(found) {
                    793:                /*
                    794:                 * Success. 
                    795:                 */
                    796:                xpr_disk("readLabel: Valid Label\n", 1,2,3,4,5);
                    797:                _labelValid = 1;
                    798: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    799:                _hfsValid = 0;                  // bek - 12/14/97 - Is this redundant?
                    800: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    801:                get_disk_label(raw_label, label_p);
                    802:                rtn = IO_R_SUCCESS;
                    803:        }
                    804:        else {
                    805:                xpr_disk("readLabel: NO LABEL\n", 1,2,3,4,5);
                    806:                if(rtn != IO_R_NO_DISK)
                    807:                        rtn = IO_R_NO_LABEL;
                    808:        }
                    809:        IOFree(raw_label, labelBufSize);
                    810:        return(rtn);
                    811: }
                    812: 
                    813: /*
                    814:  * Write disk label. Label is passed in as an actual native label per 
                    815:  * current architecture and is written as an m68k-style label.
                    816:  */
                    817: 
                    818: static inline void put_short(unsigned short s, void *dest)
                    819: {
                    820:        *((unsigned short *)dest) = NXSwapHostShortToBig(s);
                    821: }
                    822: 
                    823: - (IOReturn) writeLabel : (disk_label_t *)label_p
                    824: {
                    825:        unsigned                size;
                    826:        unsigned short          *cksum_p;
                    827:        unsigned short          cksum;
                    828:        ns_time_t               timestamp;
                    829:        int                     label_num;
                    830:        unsigned                bytesXfr;
                    831:        int                     goodLabel = 0;
                    832:        IOReturn                rtn;
                    833:        int                     blocksInLabel;
                    834:        int                     bytesInLabel;
                    835:        id                      physDisk = [self physicalDisk];
                    836:        unsigned                physBlockSize = [self physicalBlockSize];
                    837:        char                    *raw_label = NULL;
                    838:        int                     labelBufSize = 0;       /* compiler quirk */
                    839:        unsigned                formattedFlag = 0;
                    840:        const char              *lrtn;
                    841:        int                     cksum_offset;
                    842:        /* offset of NeXT disk on dos or Apple partition */
                    843:        int                     part_offset = 0;
                    844: #ifdef i386
                    845:        /*
                    846:         * Avoid writing first label over block 0.
                    847:         */
                    848:        int                     firstLabel = 1;
                    849: #else  i386
                    850:        int                     firstLabel = 0;
                    851: #endif i386
                    852: 
                    853:        xpr_disk("IODiskPartition writeLabel\n", 1,2,3,4,5);
                    854:        
                    855:        /*
                    856:         * We can't do this if any block devices, or any other logical disk, 
                    857:         * are currently open. Also, we can only do this on partition 0
                    858:         * because we're going to blow away all IODiskPartitions other than the
                    859:         * one for partition 0 before we're thru.
                    860:         */
                    861:        rtn = [self checkSafeConfig:"writeLabel"];
                    862:        if(rtn) {
                    863:                return rtn;
                    864:        }
                    865: 
                    866:        /*
                    867:         * Lock out similar destructive actions...
                    868:         */
                    869:        [physDisk lockLogicalDisks];
                    870:        
                    871:        formattedFlag = [physDisk isFormatted];
                    872:        if(!formattedFlag) {
                    873:                xpr_disk("IODiskPartition writeLabel: UNFORMATTED DISK\n",
                    874:                        1,2,3,4,5);
                    875:                rtn = IO_R_IO;
                    876:                goto done;
                    877:        }
                    878:        
                    879:        /*
                    880:         * OK, here we go. All other partitions are now invalid. Let's
                    881:         * get rid of them.
                    882:         */
                    883:        [self _freePartitions];
                    884:        _labelValid = 0;                        // until we're thru
                    885: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    886:        _hfsValid = 0;                  // until we're thru
                    887: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    888:        
                    889:        if(label_p->dl_version == DL_V1 || label_p->dl_version == DL_V2) {
                    890:                size = SIZEOF_DISK_LABEL_T;
                    891:                cksum_p = &label_p->dl_checksum;
                    892:                cksum_offset = DISK_LABEL_DL_CHECKSUM;
                    893:        } else if(label_p->dl_version == DL_V3) {
                    894:                size = SIZEOF_DISK_LABEL_T - SIZEOF_DL_UN_T;
                    895:                cksum_p = &label_p->dl_v3_checksum;
                    896:                cksum_offset = DISK_LABEL_DL_UN;
                    897:        }
                    898:        else {
                    899:                IOLog("%s writeLabel: BAD LABEL\n", [self name]);
                    900:                rtn = IO_R_INVALID_ARG;
                    901:                goto done;
                    902:        }
                    903:                
                    904:        /*
                    905:         * tag label with time.
                    906:         */
                    907:        IOGetTimestamp(&timestamp);
                    908:        label_p->dl_tag = (unsigned)timestamp;
                    909:        
                    910:        /*
                    911:         * prepare to validate (before converting to m68k-style label).
                    912:         */
                    913:        label_p->dl_label_blkno = 0;
                    914:        *cksum_p = 0;
                    915:        
                    916:        /*
                    917:         * Get an m68k-style label for validation (and which we'll eventually
                    918:         * write to disk). We do page alignment here to satisfy the most 
                    919:         * stringent DMA requirements downstream.
                    920:         */
                    921:        blocksInLabel = howmany(SIZEOF_DISK_LABEL_T, physBlockSize);
                    922:        bytesInLabel = blocksInLabel * physBlockSize;
                    923:        labelBufSize = round_page(bytesInLabel);
                    924:        raw_label = IOMalloc(labelBufSize);
                    925:        put_disk_label(label_p, raw_label);
                    926: 
                    927:        /*
                    928:         * Get checksum and validate. Careful, put the checksum in the 
                    929:         * raw m68k-style label in a machine-independent manner...
                    930:         */
                    931:        cksum = checksum16((unsigned short *)raw_label, size >> 1);
                    932:        put_short(cksum, raw_label + cksum_offset);
                    933:        if(lrtn = check_label(raw_label, 0)) {
                    934:                IOLog("%s writeLabel: BAD LABEL : %s\n", 
                    935:                        [self name], lrtn);
                    936:                rtn = IO_R_INVALID_ARG;
                    937:                goto done;
                    938:        }
                    939:                
                    940: #if defined(GROK_DOS) || defined(GROK_APPLE)
                    941:        part_offset = [self NeXTpartitionOffset];
                    942:        if (part_offset < 0) {
                    943:                rtn = part_offset;
                    944:                goto done;
                    945:        }
                    946: #endif defined(GROK_DOS) || defined(GROK_APPLE)
                    947: 
                    948:        /*
                    949:         * OK, the caller gave us a good label. Write NLABEL copies.
                    950:         */
                    951:        for(label_num=firstLabel; label_num<NLABELS; label_num++) {
                    952:                *(int *)(raw_label + DISK_LABEL_DL_LABEL_BLKNO ) = 
                    953:                        NXSwapHostIntToBig(part_offset + 
                    954:                                (label_num * blocksInLabel));
                    955: 
                    956:                        rtn = [[super class] commonReadWrite
                    957:                                : physDisk
                    958:                                : NO                    /* write */
                    959:                                : ((unsigned long long)part_offset + 
                    960:                                        (label_num * blocksInLabel))
                    961:                                            * physBlockSize /* byte offset */
                    962:                                : bytesInLabel  /* bytes */
                    963:                                : raw_label
                    964:                                : IOVmTaskSelf()
                    965:                                : (void *)NULL
                    966:                                : &bytesXfr];
                    967: 
                    968:             if((rtn == IO_R_SUCCESS) && (bytesXfr == bytesInLabel)) {
                    969:                        goodLabel++;
                    970:                }
                    971:                /*
                    972:                 * there is one fatal error here - disk not present.
                    973:                 */
                    974:                if(rtn == IO_R_NO_DISK)
                    975:                        break;
                    976:        }
                    977:        if(goodLabel) {
                    978:                _labelValid = 1;
                    979: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    980:                _hfsValid = 0;                  // bek - 12/14/97 - Is this redundant?
                    981: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                    982:                rtn = IO_R_SUCCESS;
                    983:        }
                    984:        else {
                    985:                xpr_disk("IODiskPartition writeLabel: Couldn\'t write label\n",
                    986:                        1,2,3,4,5);
                    987:                if(rtn != IO_R_NO_DISK)
                    988:                        rtn = IO_R_IO;
                    989:                goto done;
                    990:        }
                    991:        
                    992:        /*
                    993:         * One more thing - update our own parameters and see if we
                    994:         * need to create any block devices.
                    995:         */
                    996:        [self _probeLabel: label_p];
                    997: done:
                    998:        [physDisk unlockLogicalDisks];
                    999:        if(raw_label) {
                   1000:                IOFree(raw_label, labelBufSize);
                   1001:        }
                   1002:        return(rtn);
                   1003: }
                   1004: 
                   1005: 
                   1006: /*
                   1007:  * Before we die, tell owner about this. LogicalDisk takes care of freeing
                   1008:  * chained logicalDisks.
                   1009:  */
                   1010: - free
                   1011: {
                   1012: #ifdef KERNEL
                   1013:        [self unregisterUnixDisk: _partition];
                   1014: #endif KERNEL
                   1015: 
                   1016:        if( _partitionWaitLock) {
                   1017:            [_partitionWaitLock free];
                   1018:            _partitionWaitLock = nil;
                   1019:        }
                   1020:        return([super free]);
                   1021: }
                   1022:                  
                   1023: /*
                   1024:  * Handle Disk Eject request. Overrides IODisk's method of same name. 
                   1025:  * Invoked upon the partition 0 instance by DiskObject's eject. This 
                   1026:  * will be rejected at the DiskObject level if any block devices are open. 
                   1027:  * We require this to be done only on partition 0 since we're going to blow
                   1028:  * away all of the other partitions.
                   1029:  */
                   1030: - (IOReturn)eject
                   1031: {
                   1032:        IOReturn rtn;
                   1033:        id phys = [self physicalDisk];
                   1034:        
                   1035:        xpr_disk("IODiskPartition eject\n", 1,2,3,4,5);
                   1036: 
                   1037:        /*
                   1038:         * We can't do this if any block devices, or any other logical disk, 
                   1039:         * are currently open. Also, we can only do this on partition 0
                   1040:         * because we're going to blow away all IODiskPartitions other than the
                   1041:         * one for partition 0 before we're thru.
                   1042:         */
                   1043:        rtn = [self checkSafeConfig:"eject"];
                   1044:        if(rtn) {
                   1045:                return rtn;
                   1046:        }
                   1047: 
                   1048:        /*
                   1049:         * Kill all other partitions. Have IODisk clear our
                   1050:         * "formatted" flag.
                   1051:         */
                   1052:        [self _freePartitions];
                   1053:        _labelValid = 0;
                   1054: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1055:        _hfsValid = 0;
                   1056: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1057:        [super setFormattedInternal:0];
                   1058: 
                   1059:        /*
                   1060:         * Cancel possible outstanding "manual poll" request. This covers
                   1061:         * the case in which the open() performed immediately preceeding
                   1062:         * this eject command did an implied vol_check_set_poll() in the
                   1063:         * driver's open() routine.
                   1064:         */
                   1065:        if([phys needsManualPolling]) {
                   1066:                vol_check_manual_poll();
                   1067:        }
                   1068:        
                   1069:        /*
                   1070:         * Pass this down to physDisk using the internal versions to avoid
                   1071:         * getting callbacks.
                   1072:         */
                   1073:        return([phys ejectPhysical]);
                   1074: }
                   1075: 
                   1076: - (IOReturn) requestRelease
                   1077: {
                   1078:        IOReturn rtn;
                   1079:        
                   1080:        /*
                   1081:         * We can't do this if any block devices, or any other logical disk, 
                   1082:         * are currently open. Also, we can only do this on partition 0
                   1083:         * because we're going to blow away all IODiskPartitions other than the
                   1084:         * one for partition 0 before we're thru.
                   1085:         */
                   1086: 
                   1087:        rtn = [self checkSafeConfig:"disown"];
                   1088:        if(rtn) {
                   1089:                return rtn;
                   1090:        }
                   1091: 
                   1092:        /*
                   1093:         * Kill all other partitions. Have IODisk clear our
                   1094:         * "formatted" flag.
                   1095:         */
                   1096:        [self _freePartitions];
                   1097:        _labelValid = 0;
                   1098: #ifdef GROK_APPLE
                   1099:        _hfsValid = 0;
                   1100: #endif GROK_APPLE
                   1101:        [super setFormattedInternal:0];
                   1102: 
                   1103:        return(rtn);
                   1104: }
                   1105: 
                   1106: /*
                   1107:  * read/write methods. These are illegal if _labelValid is false, otherwise
                   1108:  * they're just passed up to LogicalDisk.
                   1109:  */
                   1110: #ifdef KERNEL
                   1111: - (IOReturn) readAt            : (unsigned)offset 
                   1112:                                  length : (unsigned)length 
                   1113:                                  buffer : (unsigned char *)buffer
                   1114:                                  actualLength : (out unsigned *)actualLength
                   1115:                                  client : (vm_task_t)client
                   1116: {
                   1117:        xpr_disk("IODiskPartition read\n", 1,2,3,4,5);
                   1118:        
                   1119: #if 0 // radar 1669467 - ISO 9660 CD support
                   1120: // Read is NOT illegal if _labelValid is false - ISO 9660 CDs do not have 
                   1121: // standard disk label.  In order to get read-only ISO 9660 CDROM support
                   1122: // working, we have disabled the check for a valid label on the read path 
                   1123: // only.  However, the ISO 9660 file system will not attempt to write to 
                   1124: // the device and no other client should be able to open the device for 
                   1125: // writing while the file system has it open, so the above scenario should 
                   1126: // not occur.  bknight.
                   1127: //
                   1128: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1129:        if( ! ( _labelValid || _hfsValid ) ) {
                   1130: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1131:        if( ! _labelValid ) {
                   1132: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1133:                IOLog("%s: Read attempt with no valid label\n", 
                   1134:                        [self name]);
                   1135:                return(IO_R_INVALID_ARG);
                   1136:        }
                   1137: #endif // radar 1669467 - ISO 9660 CD support
                   1138: 
                   1139:        return([super readAt : offset 
                   1140:                      length : length 
                   1141:                      buffer : buffer
                   1142:                      actualLength : actualLength
                   1143:                      client : client]);
                   1144: }
                   1145:                                  
                   1146: - (IOReturn) readAsyncAt       : (unsigned)offset 
                   1147:                                  length : (unsigned)length 
                   1148:                                  buffer : (unsigned char *)buffer
                   1149:                                  pending : (void *)pending
                   1150:                                  client : (vm_task_t)client
                   1151: {
                   1152:        xpr_disk("IODiskPartition readAsync\n", 1,2,3,4,5);
                   1153: #if 0 // radar 1669467 - ISO 9660 CD support
                   1154: // Read is NOT illegal if _labelValid is false - ISO 9660 CDs do not have 
                   1155: // standard disk label.  In order to get read-only ISO 9660 CDROM support
                   1156: // working, we have disabled the check for a valid label on the read path 
                   1157: // only.  However, the ISO 9660 file system will not attempt to write to 
                   1158: // the device and no other client should be able to open the device for 
                   1159: // writing while the file system has it open, so the above scenario should 
                   1160: // not occur.  bknight.
                   1161: //
                   1162: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1163:        if( ! ( _labelValid || _hfsValid ) ) {
                   1164: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1165:        if( ! _labelValid ) {
                   1166: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1167:                IOLog("%s: Read attempt with no valid label\n", 
                   1168:                        [self name]);
                   1169:                return(IO_R_INVALID_ARG);
                   1170:        }
                   1171: #endif // radar 1669467 - ISO 9660 CD support
                   1172: 
                   1173:        return([super readAsyncAt : offset 
                   1174:                      length : length 
                   1175:                      buffer : buffer
                   1176:                      pending: pending
                   1177:                      client : client]);
                   1178: }
                   1179:                                  
                   1180: - (IOReturn) writeAt           : (unsigned)offset 
                   1181:                                  length : (unsigned)length 
                   1182:                                  buffer : (unsigned char *)buffer
                   1183:                                  actualLength : (out unsigned *)actualLength
                   1184:                                  client : (vm_task_t)client
                   1185: {
                   1186:        xpr_disk("IODiskPartition writeAt\n", 1,2,3,4,5);
                   1187: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1188:        if( ! ( _labelValid || _hfsValid ) ) {
                   1189: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1190:        if( ! _labelValid ) {
                   1191: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1192:                IOLog("%s: Write attempt with no valid label\n", 
                   1193:                        [self name]);
                   1194:                return(IO_R_INVALID_ARG);
                   1195:        }
                   1196:        return([super writeAt : offset 
                   1197:                      length : length 
                   1198:                      buffer : buffer
                   1199:                      actualLength : actualLength
                   1200:                      client : client]);
                   1201: }
                   1202:                                        
                   1203: - (IOReturn) writeAsyncAt      : (unsigned)offset 
                   1204:                                  length : (unsigned)length 
                   1205:                                  buffer : (unsigned char *)buffer
                   1206:                                  pending : (void *)pending
                   1207:                                  client : (vm_task_t)client
                   1208: {
                   1209:        xpr_disk("IODiskPartition writeAsync\n", 1,2,3,4,5);
                   1210: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1211:        if( ! ( _labelValid || _hfsValid ) ) {
                   1212: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1213:        if( ! _labelValid ) {
                   1214: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1215:                IOLog("%s: Write attempt with no valid label\n", 
                   1216:                        [self name]);
                   1217:                return(IO_R_INVALID_ARG);
                   1218:        }
                   1219:        return([super writeAsyncAt : offset 
                   1220:                      length : length 
                   1221:                      buffer : buffer
                   1222:                      pending: pending
                   1223:                      client : client]);
                   1224: }
                   1225: 
                   1226: #else  KERNEL
                   1227: 
                   1228: - (IOReturn) readAt            : (unsigned)offset 
                   1229:                                  length : (unsigned)length 
                   1230:                                  buffer : (unsigned char *)buffer
                   1231:                                  actualLength : (out unsigned *)actualLength
                   1232: {
                   1233:        xpr_disk("IODiskPartition read\n", 1,2,3,4,5);
                   1234: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1235:        if( ! ( _labelValid || _hfsValid ) ) {
                   1236: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1237:        if( ! _labelValid ) {
                   1238: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1239:                IOLog("%s: Read attempt with no valid label\n", 
                   1240:                        [self name]);
                   1241:                return(IO_R_INVALID_ARG);
                   1242:        }
                   1243:        return([super readAt : offset 
                   1244:                      length : length 
                   1245:                      buffer : buffer
                   1246:                      actualLength : actualLength]);
                   1247: }
                   1248:                                  
                   1249: - (IOReturn) readAsyncAt       : (unsigned)offset 
                   1250:                                  length : (unsigned)length 
                   1251:                                  buffer : (unsigned char *)buffer
                   1252:                                  pending : (void *)pending
                   1253: {
                   1254:        xpr_disk("IODiskPartition readAsync\n", 1,2,3,4,5);
                   1255: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1256:        if( ! ( _labelValid || _hfsValid ) ) {
                   1257: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1258:        if( ! _labelValid ) {
                   1259: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1260:                IOLog("%s: Read attempt with no valid label\n", 
                   1261:                        [self name]);
                   1262:                return(IO_R_INVALID_ARG);
                   1263:        }
                   1264:        return([super readAsyncAt : offset 
                   1265:                      length : length 
                   1266:                      buffer : buffer
                   1267:                      pending: pending]);
                   1268: }
                   1269:                                  
                   1270: - (IOReturn) writeAt           : (unsigned)offset 
                   1271:                                  length : (unsigned)length 
                   1272:                                  buffer : (unsigned char *)buffer
                   1273:                                  actualLength : (unsigned *)actualLength
                   1274: {
                   1275:        xpr_disk("IODiskPartition writeAt\n", 1,2,3,4,5);
                   1276: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1277:        if( ! ( _labelValid || _hfsValid ) ) {
                   1278: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1279:        if( ! _labelValid ) {
                   1280: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1281:                IOLog("%s: Write attempt with no valid label\n", 
                   1282:                        [self name]);
                   1283:                return(IO_R_INVALID_ARG);
                   1284:        }
                   1285:        return([super writeAt : offset 
                   1286:                      length : length 
                   1287:                      buffer : buffer
                   1288:                      actualLength : actualLength]);
                   1289: }
                   1290:                                        
                   1291: - (IOReturn) writeAsyncAt      : (unsigned)offset 
                   1292:                                  length : (unsigned)length 
                   1293:                                  buffer : (unsigned char *)buffer
                   1294:                                  pending : (void *)pending
                   1295: {
                   1296:        xpr_disk("IODiskPartition writeAsync\n", 1,2,3,4,5);
                   1297: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1298:        if( ! ( _labelValid || _hfsValid ) ) {
                   1299: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1300:        if( ! _labelValid ) {
                   1301: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1302:                IOLog("%s: Write attempt with no valid label\n", 
                   1303:                        [self name]);
                   1304:                return(IO_R_INVALID_ARG);
                   1305:        }
                   1306:        return([super writeAsyncAt : offset 
                   1307:                      length : length 
                   1308:                      buffer : buffer
                   1309:                      pending: pending]);
                   1310: }
                   1311: #endif KERNEL
                   1312: 
                   1313: /*
                   1314:  * Public setFormatted, overrides the same method in IODisk.
                   1315:  * This is the normal way a setFormatted operation is done in a 
                   1316:  * Unix environment.
                   1317:  */
                   1318: - (IOReturn)setFormatted : (BOOL)formattedFlag
                   1319: {
                   1320:        id physDisk;
                   1321:        IOReturn rtn;
                   1322:        
                   1323:        /*
                   1324:         * We can't do this if any block devices, or any other logical disk, 
                   1325:         * are currently open. Also, we can only do this on partition 0
                   1326:         * because we're going to blow away all IODiskPartitions other than the
                   1327:         * one for partition 0 before we're thru.
                   1328:         */
                   1329:        rtn = [self checkSafeConfig:"setFormatted"];
                   1330:        if(rtn) {
                   1331:                return rtn;
                   1332:        }
                   1333: 
                   1334:        /*
                   1335:         * Pass this down to physDisk using the internal versions to avoid
                   1336:         * getting callbacks.
                   1337:         */
                   1338:        physDisk = [self physicalDisk];
                   1339:        [physDisk setFormattedInternal:formattedFlag];
                   1340:        if(formattedFlag) {
                   1341:                /*
                   1342:                 * Going to a newly formatted state; have physical
                   1343:                 * device update block size and so forth.
                   1344:                 */
                   1345:                [physDisk updatePhysicalParameters];
                   1346:        }
                   1347:        
                   1348:        /*
                   1349:         * Strange, but we'll set the internal formatted flag again in case 
                   1350:         * physical device driver disagrees with what our caller is saying.
                   1351:         * The caller wins in this case.
                   1352:         */
                   1353:        [physDisk setFormattedInternal:formattedFlag];
                   1354:        [self setFormattedInternal:formattedFlag];
                   1355:        return IO_R_SUCCESS;
                   1356: }
                   1357: 
                   1358: /*
                   1359:  * internal setFormatted - avoids logical disk interaction. Called by
                   1360:  * the exported setFormatted method both here (for normal Unix use) and
                   1361:  * from physicalDisk.
                   1362:  */
                   1363: - (void)setFormattedInternal:(BOOL)formattedFlag
                   1364: {
                   1365:        xpr_disk("%s: setFormattedInternal %d\n", [self name], 
                   1366:                formattedFlag, 3,4,5);
                   1367:        [self _freePartitions];
                   1368:        _labelValid = 0;
                   1369: 
                   1370:        /*
                   1371:         * Finally, the low-impact "just set the flag" method in
                   1372:         * IODisk...
                   1373:         */
                   1374:        [super setFormattedInternal:formattedFlag];
                   1375: }
                   1376: 
                   1377: 
                   1378: /*
                   1379:  * Get/set "device open" flags.
                   1380:  */
                   1381: - (BOOL)isBlockDeviceOpen
                   1382: {
                   1383:        return _blockDeviceOpen;
                   1384: }
                   1385: 
                   1386: - (void)setBlockDeviceOpen             : (BOOL)openFlag
                   1387: {
                   1388:         _blockDeviceOpen = openFlag ? YES : NO;
                   1389:        [self setInstanceOpen: (_blockDeviceOpen || _rawDeviceOpen)];
                   1390: }
                   1391: 
                   1392: - (BOOL)isRawDeviceOpen
                   1393: {
                   1394:        return _rawDeviceOpen;
                   1395: }
                   1396: 
                   1397: - (void)setRawDeviceOpen               : (BOOL)openFlag
                   1398: {
                   1399:        _rawDeviceOpen = openFlag ? YES : NO;
                   1400:        [self setInstanceOpen: (_blockDeviceOpen || _rawDeviceOpen)];
                   1401: }
                   1402: 
                   1403: - waitForProbe:(int) seconds
                   1404: {
                   1405:     int                attempts;
                   1406:     BOOL       ready;
                   1407:     ns_time_t  now;
                   1408: 
                   1409:     if( nil == _partitionWaitLock)
                   1410:        return( nil);
                   1411: 
                   1412:     [_partitionWaitLock lock];
                   1413:     ready = [_partitionWaitLock condition];
                   1414:     [_partitionWaitLock unlock];
                   1415: 
                   1416:     if( NO == ready) do {
                   1417:         IOGetTimestamp( &now);
                   1418:         attempts = seconds - (int)((now - _probeTime) / 1000 / 1000 / 1000);
                   1419:         if( attempts <= 0)
                   1420:            continue;
                   1421: 
                   1422:         IOLog( "%s: Waiting for drive to come ready", [self name]);
                   1423:         for( ; (NO == ready) && attempts; attempts--) {
                   1424:             IOLog( ".");
                   1425:             IOSleep( 1000);
                   1426:             [_partitionWaitLock lock];
                   1427:             ready = [_partitionWaitLock condition];
                   1428:             [_partitionWaitLock unlock];
                   1429:         }
                   1430:         IOLog( "\n");
                   1431:         if( NO == ready)
                   1432:             IOLog( "%s: Disk Not Ready\n", [self name]);
                   1433: 
                   1434:     } while( NO);
                   1435: 
                   1436:     return( ready ? self : nil);
                   1437: }
                   1438: 
                   1439: @end
                   1440: 
                   1441: @implementation IODiskPartition(Private)
                   1442: 
                   1443: 
                   1444: /*
                   1445:  * Examine a known good label, initialize LogicalDisk parameters for the
                   1446:  * partition '0' instance (on which this method is invoked) and create 
                   1447:  * additional partition instances as appropriate.
                   1448:  *
                   1449:  * Invoked by LogicalDisk +probe, upon disk insertion, and when a new label
                   1450:  * is written.
                   1451:  */
                   1452: - (void) _probeLabel : (disk_label_t *)labelp
                   1453: {
                   1454:        IODiskPartition *partInst;
                   1455:        int part;
                   1456:        struct partition *partition_p;
                   1457:        id physDisk = [self physicalDisk];
                   1458:        id lastIODiskPartition = self;
                   1459:        
                   1460:        xpr_disk("IODiskPartition  _probeLabel\n", 1,2,3,4,5);
                   1461:        
                   1462:        if(_partition != 0) {
                   1463:                IOLog("%s:  _probeLabel on partition != 0\n", 
                   1464:                        [self name]);
                   1465:                return;
                   1466:        }
                   1467:        
                   1468:        /*
                   1469:         * Update internal state for partition 0.
                   1470:         */
                   1471:        [self   _initPartition:0 
                   1472:                physicalPartition:_physicalPartition
                   1473:                disktab:&labelp->dl_dt];
                   1474:        
                   1475:        /*
                   1476:         * Create & init an additional IODiskPartition instance per valid 
                   1477:         * partition. Partition NPART-1 is never used by convention (it's 
                   1478:         * the live partition).
                   1479:         */
                   1480:        for(part=1; part<NPART-1; part++) {
                   1481:                partition_p = &labelp->dl_dt.d_partitions[part];
                   1482:                if(partition_p->p_size > 0) {
                   1483:                
                   1484:                        /*
                   1485:                         * A valid logical disk partition.
                   1486:                         */
                   1487:                        partInst = [IODiskPartition new];
                   1488:                        [partInst connectToPhysicalDisk:physDisk];
                   1489:                        [partInst _initPartition : part
                   1490:                                physicalPartition: _physicalPartition
                   1491:                                disktab : &labelp->dl_dt];
                   1492:                        [partInst init];
                   1493:                        [partInst registerDevice];
                   1494:                                
                   1495:                        /*
                   1496:                         * Link to logical disk chain, and notify 
                   1497:                         * physDisk as well.
                   1498:                         */
                   1499:                        [lastIODiskPartition setLogicalDisk:partInst];
                   1500:                        [[self physicalDisk] setLogicalDisk:partInst];
                   1501:                        lastIODiskPartition = partInst;
                   1502:                }
                   1503:        }
                   1504:        return;
                   1505: }
                   1506: 
                   1507: /*
                   1508:  * Assign logical disk parameters for an IODiskPartition instance based on
                   1509:  * specified partition number on disktab. Caller must have already 
                   1510:  * done a connectToPhysicalDisk on this instance, and specified partition
                   1511:  * is known to be valid.
                   1512:  */
                   1513: - (void)_initPartition         : (int)partNum
                   1514:               physicalPartition : (int)physNum 
                   1515:                         disktab : (struct disktab *)dtp;
                   1516: {
                   1517:        struct partition *pp = &dtp->d_partitions[partNum];
                   1518:        int partBase;
                   1519:        char name[30];
                   1520:        id physDisk = [self physicalDisk];
                   1521: 
                   1522:        /*
                   1523:         * Set IODevice-class instance variables.
                   1524:         */
                   1525:        sprintf(name, "%s%c", [physDisk name], 'a' + partNum);
                   1526:        [self setName:name];
                   1527:        [self setDriveName:"IODiskPartition Partition"];
                   1528:        [self setLocation:NULL];
                   1529:        xpr_disk("%s: _initPartition\n", IOCopyString(name), 2,3,4,5);
                   1530:        [self setDiskSize:pp->p_size];
                   1531:        [self setBlockSize:dtp->d_secsize];
                   1532:        [self setUnit:[physDisk unit]];         // probably unnecessary
                   1533: 
                   1534:        // Ensure partition 0 always has the correct value
                   1535:        // for this instance variable, since connectToPhysicalDisk
                   1536:        // is only called once for that partition.
                   1537:        [self setWriteProtected:[physDisk isWriteProtected]];
                   1538: 
                   1539:        /*
                   1540:         * LogicalDisk instance variables are taken care of in
                   1541:         * connectToPhysicalDisk.
                   1542:         * Set up local instance variables.
                   1543:         *
                   1544:         * Careful, partitionBase is not necessarily in physical blocksize;
                   1545:         * for old disks, it's in d_secsize (usually DEV_BSIZE) from 
                   1546:         * disktab...
                   1547:         */
                   1548:        partBase = pp->p_base + dtp->d_front;
                   1549:        partBase *= dtp->d_secsize / [self physicalBlockSize];
                   1550:        [self setPartitionBase:partBase];
                   1551:        _partition =  partNum;
                   1552:        _physicalPartition = physNum;
                   1553:        
                   1554:        /*
                   1555:         * The low-impact "just set the flag" method in IODisk...Our
                   1556:         * override of this method frees partitions.
                   1557:         */
                   1558:        [super setFormattedInternal:1];
                   1559:        _labelValid = 1;
                   1560: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1561:        _hfsValid = 0;                  // bek - 12/14/97 - Is this redundant?
                   1562: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1563:        
                   1564: #ifdef KERNEL
                   1565:        /*
                   1566:         * Let Unix layer know about us.
                   1567:         */
                   1568:        [self registerUnixDisk : partNum];
                   1569: #endif KERNEL
                   1570:        return;
                   1571: }                                
                   1572:                
                   1573: /*
                   1574:  * Free all partition instances other than partition 0. The others must
                   1575:  * not be open, and this must be invoked on partition 0.
                   1576:  */
                   1577: - (IOReturn)_freePartitions;
                   1578: {
                   1579:        id nextPart = [self nextLogicalDisk];
                   1580:        
                   1581:        if(_partition != 0) {
                   1582:                IOLog("%s: _freePartitions on partition != 0\n",
                   1583:                        [self name]);
                   1584:                return IO_R_BUSY;       
                   1585:        }       
                   1586:        if(nextPart == nil)
                   1587:                return IO_R_SUCCESS;
                   1588:        if([nextPart isOpen]) {
                   1589:                /* 
                   1590:                 * this shouldn't happen - this was already checked
                   1591:                 * in checkSafeConfig.
                   1592:                 */
                   1593:                IOLog("%s: _freePartitions with open partitions\n",
                   1594:                        [self name]);
                   1595:                return IO_R_BUSY;
                   1596:        }
                   1597:        [nextPart free];
                   1598:        [self setLogicalDisk:nil];
                   1599:        return IO_R_SUCCESS;
                   1600: }
                   1601: 
                   1602: /*
                   1603:  * Determine if any block devices in the logicalDisk chain are open.
                   1604:  */
                   1605: - (BOOL)isAnyBlockDevOpen
                   1606: {
                   1607:        id logDisk = [[self physicalDisk] nextLogicalDisk];
                   1608:        
                   1609:        while(logDisk) {
                   1610:                if([logDisk isBlockDeviceOpen]) {
                   1611:                        return YES;
                   1612:                }
                   1613:                logDisk = [logDisk nextLogicalDisk];
                   1614:        }
                   1615:        return NO;
                   1616: }
                   1617: 
                   1618: 
                   1619: /*
                   1620:  * Verify that it's safe to do an operation which will result in a call
                   1621:  * to _freePartitions.
                   1622:  */
                   1623: - (IOReturn)checkSafeConfig    : (const char *)op
                   1624: {
                   1625:        if(_partition != 0) {
                   1626:                return IO_R_BUSY;
                   1627:        }
                   1628:        if([self isAnyBlockDevOpen]) {
                   1629:                return IO_R_BUSY;
                   1630:        }
                   1631:        if([self isAnyOtherOpen]) {
                   1632:                return IO_R_BUSY;
                   1633:        }
                   1634:        return IO_R_SUCCESS;
                   1635: }
                   1636: 
                   1637: 
                   1638: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1639: 
                   1640: /*
                   1641:  * Check for an apple partition:
                   1642:  *
                   1643:  */
                   1644: #define BLOCKSIZE_512_BYTES    512
                   1645: 
                   1646: + (void)CreateHFSDevicesFromApplePartitionMap: (id) devDesc
                   1647: {
                   1648:        id                      physicalDisk = [devDesc directDevice];
                   1649:        unsigned char   *       blk;
                   1650:        Block0                  *       blk0;
                   1651:        unsigned long           blocksize;
                   1652:        unsigned                        bytesXfr;
                   1653:        IOReturn                        rtn;
                   1654:        
                   1655:     unsigned int               block = 1;
                   1656:     unsigned int               entry_within_block = 0;
                   1657:     int                                        n;
                   1658:     unsigned int               nentries_per_block = 1;
                   1659:     unsigned int               numPartBlocks;
                   1660:     DPME                       *       partEntry;
                   1661:     int                                physNum;
                   1662: 
                   1663:        IODiskPartition *       partitionInstance;
                   1664:        IODiskPartition *       lastIODiskPartition = nil; // mandatory initialization
                   1665:        unsigned                        part = 0;
                   1666: 
                   1667:        blocksize = 512;
                   1668: 
                   1669:        blk = IOMalloc(PAGE_SIZE); /* force page alignment */
                   1670:        blk0 = (Block0 *)blk;
                   1671: 
                   1672:        /* check block 0 for valid Apple partition signature */
                   1673: 
                   1674:        rtn = [[super class] commonReadWrite
                   1675:                                : physicalDisk
                   1676:                                : YES                   /* read */
                   1677:                                : (unsigned long long)0 /* byte offset */
                   1678:                                : PAGE_SIZE     /* bytes */
                   1679:                                : blk
                   1680:                                : IOVmTaskSelf()
                   1681:                                : (void *)NULL
                   1682:                                : &bytesXfr];
                   1683: 
                   1684:         if (rtn)
                   1685:        {
                   1686:            goto Return;
                   1687:        }
                   1688:        
                   1689:        /* scan for apple hfs partitions */
                   1690: 
                   1691:     /* check if there is a valid map at 512 offset */
                   1692: 
                   1693:     partEntry = (DPME *)(blk + BLOCKSIZE_512_BYTES);
                   1694: 
                   1695:     if (blocksize > BLOCKSIZE_512_BYTES)
                   1696:     {
                   1697:                if (NXSwapBigShortToHost(partEntry->dpme_signature) == DPME_SIGNATURE)
                   1698:                {
                   1699:                    /* there is a valid map, and the device blocksize
                   1700:                     * is > 512, which means we probably have a CDROM
                   1701:                     * using 2K, but having valid 512 map
                   1702:                     */
                   1703:                    block = 0;
                   1704:                    nentries_per_block = blocksize / BLOCKSIZE_512_BYTES;
                   1705:                    entry_within_block = 1;
                   1706:                }
                   1707:                else
                   1708:                {
                   1709:                    partEntry = (DPME *)(blk + blocksize);
                   1710:                }
                   1711:     }
                   1712: 
                   1713:     if (NXSwapBigShortToHost(partEntry->dpme_signature) != DPME_SIGNATURE)
                   1714:     {
                   1715: #if 1 // bknight - 7/2/98 - Radar #2240631
                   1716:        /* Make a single giant "_hfs_a" partition to support floppies, DOS disks, ISO9660 CDs. */
                   1717: 
                   1718:        partitionInstance = [IODiskPartition new];
                   1719:        [partitionInstance connectToPhysicalDisk: physicalDisk];
                   1720:        [partitionInstance setDeviceDescription: devDesc];
                   1721:        [partitionInstance _initHFSPartition: 0
                   1722:                physicalPartNum: 0 // bknight - intentionally illegal phys part num
                   1723:                diskSize: ( [physicalDisk diskSize] * ([physicalDisk blockSize] / BLOCKSIZE_512_BYTES) )
                   1724:                partitionBase: 0];
                   1725:        [partitionInstance init]; //bknight - [super init] all the way up to Object
                   1726:        [partitionInstance registerDevice]; //bknight - doesn't do anything since (!_isPhysical)
                   1727:                        
                   1728:        /* No need to link onto the end of nonexistent chain of logical partitions.
                   1729:           Just notify the physical disk. */
                   1730:                 
                   1731:        [physicalDisk setLogicalDisk: partitionInstance]; //bknight - doesn't override if already set
                   1732: #endif // bknight - 7/2/98 - Radar #2240631
                   1733:        goto Return;
                   1734:     }
                   1735: 
                   1736:     numPartBlocks = NXSwapBigLongToHost(partEntry->dpme_map_entries);
                   1737:     physNum = 1;
                   1738:     for (n = 0; n < numPartBlocks; n++)
                   1739:     {
                   1740:                if (NXSwapBigShortToHost(partEntry->dpme_signature) != DPME_SIGNATURE)
                   1741:                {
                   1742:                    break;
                   1743:                }
                   1744: 
                   1745:                if ( strcmp(partEntry->dpme_type, HFS_PART_TYPE) == 0 )
                   1746:                {
                   1747:                    /*
                   1748:                     * Mount HFS volume only if this isn't "MOSX_OF3_Booter" partition.
                   1749:                     */
                   1750:                    if ( strcmp(partEntry->dpme_name, "MOSX_OF3_Booter") != 0 )
                   1751:                    {
                   1752:                            unsigned long part_offset;
                   1753:        
                   1754:                            part_offset = NXSwapBigLongToHost(partEntry->dpme_pblock_start);
                   1755:                            if ((part_offset / nentries_per_block * nentries_per_block) != part_offset)
                   1756:                            {
                   1757:                                        IOLog("IODiskPartition: " HFS_PART_TYPE
                   1758:                                              " partition base (%ld x 512) is not"
                   1759:                                              " a multiple of the devblksize %ld\n",
                   1760:                                              part_offset, blocksize);
                   1761:                                        break;
                   1762:                            }
                   1763:        
                   1764:                    part_offset = part_offset / nentries_per_block;
                   1765: 
                   1766:                        /* A valid logical disk partition. */
                   1767: 
                   1768:                        partitionInstance = [IODiskPartition new];
                   1769:                        [partitionInstance connectToPhysicalDisk: physicalDisk];
                   1770:                        [partitionInstance setDeviceDescription:devDesc];
                   1771:                        [partitionInstance
                   1772:                                _initHFSPartition: part
                   1773:                                physicalPartNum: physNum
                   1774:                                diskSize: partEntry->dpme_pblocks
                   1775:                                partitionBase: partEntry->dpme_pblock_start];
                   1776:                        [partitionInstance init]; //bknight - [super init] all the way up to Object
                   1777:                        [partitionInstance registerDevice]; //bknight - doesn't do anything since (!_isPhysical)
                   1778:                                
                   1779:                        /* Link to logical disk chain, and notify the physicalDisk. */
                   1780:                         
                   1781:                        if ( lastIODiskPartition != nil )
                   1782:                        {
                   1783:                                [lastIODiskPartition setLogicalDisk: partitionInstance];
                   1784:                        }
                   1785:                        lastIODiskPartition = partitionInstance;
                   1786:                        [physicalDisk setLogicalDisk: partitionInstance]; //bknight - doesn't override if already set
                   1787:                        
                   1788:                        /* Increment our partition counter. */
                   1789:                        
                   1790:                        part++;
                   1791:                    } // if not "MOSX_OF3_Booter" partition flag set
                   1792:                } // if HFS_PART_TYPE
                   1793: 
                   1794:                 physNum++;
                   1795:                partEntry++;
                   1796:                if (++entry_within_block == nentries_per_block)
                   1797:                {
                   1798:                    block++;
                   1799:                    entry_within_block = 0;
                   1800:                    partEntry = (DPME *)blk;
                   1801:                            rtn = [[super class] commonReadWrite
                   1802:                                : physicalDisk
                   1803:                                : YES                   /* read */
                   1804:                    : (unsigned long long)block * blocksize /* byte offset */
                   1805:                                : blocksize     /* bytes */
                   1806:                                : blk
                   1807:                                : IOVmTaskSelf()
                   1808:                                : (void *)NULL
                   1809:                                : &bytesXfr];
                   1810:                     if (rtn)
                   1811:                    {
                   1812:                                break;
                   1813:                    }
                   1814: 
                   1815:                } // if
                   1816: 
                   1817:     } // for
                   1818: 
                   1819: Return:
                   1820: 
                   1821:        IOFree(blk, PAGE_SIZE);
                   1822:        return;
                   1823: 
                   1824: } // CreateHFSDevicesFromApplePartitionMap
                   1825: 
                   1826: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1827: 
                   1828: #if GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1829: 
                   1830: /*
                   1831:  * Assign logical disk parameters for an IODiskPartition instance based on
                   1832:  * specified partition number on disktab. Caller must have already 
                   1833:  * done a connectToPhysicalDisk on this instance, and specified partition
                   1834:  * is known to be valid.
                   1835:  */
                   1836: - (void)       _initHFSPartition       : (int) partitionNum
                   1837:                        physicalPartNum : (int) physNum
                   1838:                        diskSize        : (int) diskSize
                   1839:                        partitionBase : (int) partitionBase;
                   1840: {
                   1841:        int                                             hfsPartitionNum = partitionNum + NPART;
                   1842:        char                                    name[30]; //bknight - hardcoded
                   1843:        id                                              physicalDisk = [self physicalDisk];
                   1844: 
                   1845:        /* IODevice initialization */
                   1846: 
                   1847:        sprintf(name, "%s_hfs_%c", [physicalDisk name], 'a' + partitionNum);
                   1848:        [self setUnit: [physicalDisk unit]]; // IODevice //bknight - probably unnecessary ???
                   1849:        [self setName: name];
                   1850:        [self setLocation: NULL];
                   1851: 
                   1852:        /* IODisk initialization */
                   1853: 
                   1854:        [self setDriveName: "IODiskPartition Partition"];
                   1855: 
                   1856:        // always measured in 512-byte blocks, regardless of the device block size
                   1857: 
                   1858:        [self setDiskSize: diskSize]; //bknight - in 512-byte blocks
                   1859: 
                   1860:        // hardcoded per Radar #2211264
                   1861: 
                   1862:        [self setBlockSize: 512]; 
                   1863: 
                   1864:        /* bknight - WHAT DOES THIS COMMENT / LINE MEAN ??? */
                   1865: 
                   1866:        // Ensure partition 0 always has the correct value
                   1867:        // for this instance variable, since connectToPhysicalDisk
                   1868:        // is only called once for that partition.
                   1869:        [self setWriteProtected:[physicalDisk isWriteProtected]];
                   1870: 
                   1871:        /*
                   1872:         * IOLogicalDisk instance variables are taken care of in connectToPhysicalDisk.
                   1873:         * Set up IODiskPartition instance variables.
                   1874:         *
                   1875:         */
                   1876:        [self setPartitionBase: partitionBase];
                   1877:        _partition = hfsPartitionNum;
                   1878:         _physicalPartition = physNum;
                   1879: 
                   1880:        /*
                   1881:         * The low-impact "just set the flag" method in IODisk...Our
                   1882:         * override of this method frees partitions.
                   1883:         */
                   1884:        [super setFormattedInternal:1];
                   1885:        _hfsValid = 1;
                   1886:        _labelValid = 0;
                   1887:        
                   1888: #ifdef KERNEL
                   1889:        /*
                   1890:         * Let Unix layer know about us.
                   1891:         */
                   1892:        [self registerUnixDisk: hfsPartitionNum];
                   1893: #endif KERNEL
                   1894: 
                   1895: Return:
                   1896: 
                   1897:        return;
                   1898: 
                   1899: } // _initHFSPartition
                   1900:                
                   1901: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
                   1902: 
                   1903: - property_IODeviceType:(char *)types length:(unsigned int *)maxLen
                   1904: {
                   1905: #if GROK_APPLE
                   1906:     if( _hfsValid)
                   1907:         strcat( types, " "IOTypeHFS);
                   1908:     else
                   1909: #endif GROK_APPLE
                   1910:         strcat( types, " "IOTypeUFS);
                   1911:     return( self);
                   1912: }
                   1913: 
                   1914: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
                   1915: {
                   1916:     [super property_IODeviceClass:classes length:maxLen];
                   1917:     strcat( classes, " "IOClassDiskPartition);
                   1918:     return( self);
                   1919: }
                   1920: 
                   1921: - property_IOPartitionNumber:(char *)result length:(unsigned int *)maxLen
                   1922: {
                   1923:     sprintf( result, "0x%x", _physicalPartition);
                   1924:     return( self);
                   1925: }
                   1926: 
                   1927: - registerLoudly
                   1928: {
                   1929:     return( nil);
                   1930: }
                   1931: 
                   1932: @end
                   1933: 
                   1934: #ifndef        KERNEL
                   1935: /*
                   1936:  * Ripped off from kernel's next/checksum16.c
                   1937:  */
                   1938: #define        ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
                   1939: #define        REDUCE {                                \
                   1940:        l_util.l = sum;                         \
                   1941:        sum = l_util.s[0] + l_util.s[1];        \
                   1942:        ADDCARRY(sum);                          \
                   1943: }
                   1944: 
                   1945: u_short checksum_16(u_short *wp, int num_shorts)
                   1946: {
                   1947:        int sum = 0;
                   1948:        union {
                   1949:                u_short s[2];
                   1950:                long    l;
                   1951:        } l_util;
                   1952: 
                   1953:        while (num_shorts--)
                   1954:                sum += *wp++;
                   1955:        REDUCE;
                   1956:        return (sum);
                   1957: }
                   1958: #endif KERNEL

unix.superglobalmegacorp.com

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