Annotation of driverkit/libDriver/IODiskPartition.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
        !            25:  *
        !            26:  * 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.