Annotation of XNU/iokit/Families/IOHDDrive/IOHDDrive.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: 
        !            23: #include <IOKit/IOLib.h>
        !            24: #include <IOKit/IOReturn.h>
        !            25: #include <IOKit/storage/IOMedia.h>
        !            26: #include <IOKit/assert.h>
        !            27: #include <IOKit/storage/IOHDDrive.h>
        !            28: #include <IOKit/storage/IOHDDriveNub.h>
        !            29: 
        !            30: #define        super   IODrive
        !            31: OSDefineMetaClassAndStructors(IOHDDrive,IODrive)
        !            32: 
        !            33: void
        !            34: gc_glue(IOService *target,void *param,UInt64 actualTransferCount,IOReturn result);
        !            35: 
        !            36: /* Accept a new piece of media, doing whatever's necessary to make it
        !            37:  * show up properly to the system.
        !            38:  */
        !            39: IOReturn
        !            40: IOHDDrive::acceptNewMedia(void)
        !            41: {
        !            42:     IOReturn result;
        !            43:     bool ok;
        !            44:     UInt64 nbytes;
        !            45:     UInt64 nformats;
        !            46:     char name[128];
        !            47:     bool nameSep;
        !            48: 
        !            49:     lockForArbitration();
        !            50: 
        !            51:     /* Since the kernel printf doesn't handle 64-bit integers, we
        !            52:      * simply make an assumption that the block count and size
        !            53:      * will be 32-bit values max.
        !            54:      */
        !            55: 
        !            56: #ifdef moreDebug
        !            57:     IOLog("%s[IOHDDrive]::%s media: %ld blocks, %ld bytes each, write-%s.\n",
        !            58:             getName(),
        !            59:             getDeviceTypeName(),
        !            60:             (UInt32)_maxBlockNumber + 1,(UInt32)getMediaBlockSize(),
        !            61:             (_writeProtected ? "protected" : "enabled"));
        !            62: #else
        !            63:     IOLog("%s media: %ld blocks, %ld bytes each, write-%s.\n",          
        !            64:             getName(),
        !            65:             (UInt32)_maxBlockNumber + 1,(UInt32)getMediaBlockSize(),
        !            66:             (_writeProtected ? "protected" : "enabled"));
        !            67: #endif
        !            68:     
        !            69:     /* Instantiate a media object and attach it to ourselves. */
        !            70: 
        !            71:     nformats = getFormatCapacities(&nbytes,1); /* get byte size of media */
        !            72: 
        !            73:     name[0] = 0;
        !            74:     nameSep = false;
        !            75:     if (_provider->getVendorString()) {
        !            76:         strcat(name, _provider->getVendorString());
        !            77:         nameSep = true;
        !            78:     }
        !            79:     if (_provider->getProductString()) {
        !            80:         if (nameSep == true)  strcat(name, " ");
        !            81:         strcat(name, _provider->getProductString());
        !            82:         nameSep = true;
        !            83:     }
        !            84:     if (nameSep == true)  strcat(name, " ");
        !            85:     strcat(name, "Media");
        !            86: 
        !            87:     result = instantiateMediaObject(&_mediaObject,0,nbytes,_mediaBlockSize,true,name);
        !            88:     
        !            89:     if (result == kIOReturnSuccess) {
        !            90:         _mediaPresent = true;
        !            91:         ok = _mediaObject->attach(this);                       /* attach media object above us */
        !            92:         if (ok) {
        !            93:            // IOLog("IOHDDrive: registering media object\n");
        !            94:             _mediaObject->registerService();           /* enable matching */
        !            95:         }
        !            96:     } else {
        !            97:         IOLog("%s[IOHDDrive]::acceptNewMedia; couldn't instantiate media object.\n",getName());
        !            98:     }
        !            99:     
        !           100:     unlockForArbitration();    
        !           101: 
        !           102:     return(result);
        !           103: }
        !           104: 
        !           105: /* Allocate a new context struct. */
        !           106: struct IOHDDrive::context *
        !           107: IOHDDrive::allocateContext(void)
        !           108: {
        !           109:     struct IOHDDrive::context *cx;
        !           110: 
        !           111:     cx = IONew(struct IOHDDrive::context,1);
        !           112:     if (cx == NULL) {
        !           113:         return(NULL);
        !           114:     }
        !           115: 
        !           116:     bzero(cx,sizeof(struct IOHDDrive::context));
        !           117: 
        !           118:     return(cx);
        !           119: }
        !           120: 
        !           121: IOReturn
        !           122: IOHDDrive::checkForMedia(void)
        !           123: {
        !           124:     IOReturn result;
        !           125:     bool currentState;
        !           126:     bool changed;
        !           127:     
        !           128:     IOTakeLock(_mediaStateLock);    
        !           129: 
        !           130:     result = _provider->reportMediaState(&currentState,&changed);
        !           131:     if (result != kIOReturnSuccess) {          /* the poll operation failed */
        !           132:        IOLog("%s[IOHDDrive]::checkForMedia; err '%s' from reportMediaState\n",
        !           133:                        getName(),stringFromReturn(result));
        !           134: 
        !           135:         IOUnlock(_mediaStateLock);
        !           136:         return(result);
        !           137:     }
        !           138: 
        !           139:     /* The poll succeeded. */
        !           140: 
        !           141:     if (!changed) {                    /* media state hasn't changed */
        !           142:         IOUnlock(_mediaStateLock);
        !           143:         return(kIOReturnSuccess);
        !           144:     }
        !           145: 
        !           146:     /* The media has changed state. See if it's just inserted or removed. */
        !           147: 
        !           148:     if (currentState == true) {                /* media is now present */
        !           149: 
        !           150: //        IOLog("%s[IOHDDrive]::checkForMedia; changed = %s, mediaPresent = %s\n",
        !           151: //                getName(),changed ? "Y" : "N",currentState ? "Y" : "N");
        !           152: 
        !           153:         /* Allow a subclass to decide whether we accept the media. Such a decision
        !           154:          * might be based on things like password-protection, etc.
        !           155:          */
        !           156: 
        !           157:         if (validateNewMedia() == false) {     /* we're told to reject it */
        !           158:             rejectMedia();                     /* so let subclass do whatever it wants */
        !           159:             IOUnlock(_mediaStateLock);
        !           160:             return(kIOReturnSuccess);          /* pretend nothing happened */
        !           161:         }
        !           162: 
        !           163:         result = recordMediaParameters();      /* learn about media */
        !           164:         if (result != kIOReturnSuccess) {      /* couldn't record params */
        !           165:             initMediaStates();         /* deny existence of new media */
        !           166:            IOLog("%s[IOHDDrive]::checkForMedia: err '%s' from recordMediaParameters\n",
        !           167:                        getName(),stringFromReturn(result));
        !           168:             IOUnlock(_mediaStateLock);
        !           169:             return(result);
        !           170:         }
        !           171: 
        !           172:         /* Now we do what's necessary to make the new media
        !           173:          * show up properly in the system.
        !           174:          */
        !           175: 
        !           176:         result = acceptNewMedia();
        !           177:         if (result != kIOReturnSuccess) {
        !           178:             initMediaStates();         /* deny existence of new media */
        !           179:            IOLog("%s[IOHDDrive]::checkForMedia; err '%s' from acceptNewMedia\n",
        !           180:                        getName(),stringFromReturn(result));
        !           181:             IOUnlock(_mediaStateLock);
        !           182:             return(result);
        !           183:         }
        !           184: 
        !           185:         IOUnlock(_mediaStateLock);
        !           186:         return(kIOReturnSuccess);              /* all done, new media is ready */
        !           187: 
        !           188:     } else {                           /* media is now absent */
        !           189: 
        !           190:         result = decommissionMedia(true);      /* force a teardown */
        !           191:         if (result != kIOReturnSuccess && result != kIOReturnNoMedia) {
        !           192:            IOLog("%s[IOHDDrive]::checkForMedia; err '%s' from decommissionNewMedia\n",
        !           193:                        getName(),stringFromReturn(result));
        !           194:             IOUnlock(_mediaStateLock);
        !           195:             return(result);
        !           196:         }
        !           197: 
        !           198:         IOUnlock(_mediaStateLock);
        !           199:         return(kIOReturnSuccess);              /* all done; media is gone */
        !           200:     }
        !           201: }
        !           202: 
        !           203: UInt64
        !           204: IOHDDrive::constrainByteCount(UInt64 /* requestedCount */ ,bool isWrite)
        !           205: {
        !           206:     if (isWrite) {
        !           207:         return(_maxWriteByteTransfer);
        !           208:     } else {
        !           209:         return(_maxReadByteTransfer);
        !           210:     }
        !           211: }
        !           212: 
        !           213: OSDictionary *
        !           214: IOHDDrive::constructMediaProperties(void)
        !           215: {
        !           216: #ifdef notyet //xxx
        !           217:     
        !           218:     OSDictionary *propTable;
        !           219:     OSData *prop;
        !           220: 
        !           221:     propTable = OSDictionary::withCapacity(6);
        !           222:     
        !           223:     if (propTable) {
        !           224:         
        !           225:         prop = OSData::withBytes((void *)(&_mediaBlockSize),sizeof(UInt64));
        !           226:         if (prop) {
        !           227:             propTable->setObject(prop,"phys-blocksize");
        !           228:             prop->release(); // XXX -- svail: added.
        !           229:         }
        !           230: 
        !           231:         prop = OSData::withBytes((void *)(&_maxBlockNumber),sizeof(UInt64));
        !           232:         if (prop) {
        !           233:             propTable->setObject(prop,"highest-block");
        !           234:             prop->relase(); // XXX -- svail: added.
        !           235:         }
        !           236: 
        !           237:         prop = OSData::withBytes((void *)(&_writeProtected),sizeof(bool));
        !           238:         if (prop) {
        !           239:             propTable->setObject(prop,"write-protected");
        !           240:             prop->release(); // XXX -- svail: added.
        !           241:         }
        !           242:     }
        !           243: 
        !           244:     return(propTable);
        !           245: 
        !           246: #else
        !           247:     return(0);
        !           248: #endif //xxx
        !           249: }
        !           250: 
        !           251: /* Decommission a piece of media that has become unavailable either due to
        !           252:  * ejection or some outside force (e.g. the Giant Hand of the User).
        !           253:  * (I prefer the term "decommission" rather than "abandon." The former implies
        !           254:  * a well-determined procedure, whereas the latter implies leaving the media
        !           255:  * in an orphaned state.)
        !           256:  */
        !           257: /* Tear down the stack above the specified object. Usually these objects will
        !           258:  * be of type IOMedia, but they could be any IOService.
        !           259:  */
        !           260: IOReturn
        !           261: IOHDDrive::decommissionMedia(bool forcible)
        !           262: {
        !           263:     IOReturn result;
        !           264: 
        !           265:     result = tearDown(_mediaObject);
        !           266: 
        !           267:     /* If this is a forcible decommission (i.e. media is gone), we don't care
        !           268:      * whether the teardown worked; we forget about the media.
        !           269:      */
        !           270:     
        !           271:     if (forcible || (result == kIOReturnSuccess)) {    /* then it tore down successfully */
        !           272:         _mediaObject = 0;
        !           273:         initMediaStates();                     /* deny existence of any media */
        !           274:     }
        !           275: 
        !           276:     return(result);
        !           277: }
        !           278: 
        !           279: void
        !           280: IOHDDrive::deleteContext(struct IOHDDrive::context *cx)
        !           281: {
        !           282:     if (cx->buffer) {
        !           283:         cx->buffer->release();         /* reduce retain count on Memory Descriptor */
        !           284:     }
        !           285:     IODelete(cx,struct IOHDDrive::context,1);
        !           286: }
        !           287: 
        !           288: IOReturn
        !           289: IOHDDrive::ejectMedia(void)
        !           290: {
        !           291:     IOReturn result;
        !           292: 
        !           293:     if (_removable) {
        !           294:         
        !           295:         IOTakeLock(_mediaStateLock);
        !           296: 
        !           297:         result = decommissionMedia(false);     /* try to teardown */
        !           298: 
        !           299:         if (result == kIOReturnSuccess) {      /* eject */
        !           300:             (void)_provider->doEjectMedia();   /* ignore any error */
        !           301:         }
        !           302: 
        !           303:         IOUnlock(_mediaStateLock);
        !           304: 
        !           305:         return(result);
        !           306:             
        !           307:     } else {
        !           308:         return(kIOReturnUnsupported);        
        !           309:     }
        !           310: }
        !           311: 
        !           312: void
        !           313: IOHDDrive::executeRequest(UInt64               byteStart,
        !           314:                           IOMemoryDescriptor * buffer,
        !           315:                           IOStorageCompletion  completion)
        !           316: {
        !           317:     struct IOHDDrive::context *cx;
        !           318:     UInt32 block;
        !           319:     UInt32 nblks;
        !           320:     IOReturn result;
        !           321: 
        !           322:     _stats.clientReceived++;
        !           323:     
        !           324:     if (!_mediaPresent) {              /* no media? you lose */
        !           325:         _stats.clientCompletionsSent++;
        !           326:         complete(completion, kIOReturnNoMedia,0);
        !           327:         _stats.clientCompletionsDone++;
        !           328:         return;
        !           329:     }
        !           330: 
        !           331:     result = buffer->prepare();                          // (prepare the buffer)
        !           332:     if ( result != kIOReturnSuccess )  {
        !           333:         // (wiring or permissions failure?)
        !           334:         _stats.clientCompletionsSent++;
        !           335:         complete(completion, result,0);
        !           336:         _stats.clientCompletionsDone++;
        !           337:         return;
        !           338:     }
        !           339: 
        !           340:     /* We know that we are never called with a request too large,
        !           341:      * nor one that is misaligned with a block.
        !           342:      */
        !           343:     assert((byteStart           % _mediaBlockSize) == 0);
        !           344:     assert((buffer->getLength() % _mediaBlockSize) == 0);
        !           345:     
        !           346:     block = byteStart           / _mediaBlockSize;
        !           347:     nblks = buffer->getLength() / _mediaBlockSize;
        !           348: 
        !           349:     cx = allocateContext();
        !           350:     if (cx == NULL) {
        !           351:         if (buffer) {
        !           352:             buffer->complete();
        !           353:         }
        !           354:         _stats.clientCompletionsSent++;
        !           355:         complete(completion,kIOReturnNoResources,0);
        !           356:         _stats.clientCompletionsDone++;
        !           357:         return;
        !           358:     }
        !           359: 
        !           360:     /* Copy our params to our context. */
        !           361: 
        !           362:     cx->completion     = completion;
        !           363:     cx->buffer         = buffer;
        !           364:     cx->buffer->retain();
        !           365:     cx->byteStart      = byteStart;
        !           366:     cx->byteCount      = buffer->getLength();
        !           367: 
        !           368: /***
        !           369:     if (isWrite) {
        !           370:         assert(buffer->getDirection() == kIODirectionOut);
        !           371:     } else {
        !           372:         assert(buffer->getDirection() == kIODirectionIn);
        !           373:     }
        !           374: ***/
        !           375: /**    
        !           376:     IOLog("%s[IOHDDrive]::executeRequest; blk %d, nblks %d\n",getName(),
        !           377:           (int)block,(int)nblks);
        !           378: **/
        !           379: /* Now the protocol-specific provider implements the actual
        !           380:      * start of the data transfer: */
        !           381: 
        !           382:     _stats.providerSent++;
        !           383:     result = _provider->doAsyncReadWrite(cx->buffer,
        !           384:                                             block,nblks,
        !           385:                                             gc_glue,
        !           386:                                             this,(void *)cx);
        !           387:     
        !           388:     if (result != kIOReturnSuccess) {          /* it failed to start */
        !           389:         _stats.providerReject++;
        !           390:         IOLog("%s[IOHDDrive]; executeRequest: request failed to start!\n",getName());
        !           391:         if (buffer) {
        !           392:             buffer->complete();
        !           393:         }
        !           394:         _stats.clientCompletionsSent++;
        !           395:         complete(completion,result,0);
        !           396:         _stats.clientCompletionsDone++;
        !           397:         deleteContext(cx);
        !           398:         return;
        !           399:     }
        !           400: 
        !           401:     if (showStats()) {
        !           402:         IOLog("%s[IOHDDrive]; executeRequest: cr=%5d,ps=%5d,pr=%5d,pcr=%5d,ccs=%5d,ccd=%5d\n",
        !           403:             getName(),
        !           404:             _stats.clientReceived,
        !           405:             _stats.providerSent,
        !           406:             _stats.providerReject,
        !           407:             _stats.providerCompletionsRcvd,
        !           408:             _stats.clientCompletionsSent,
        !           409:             _stats.clientCompletionsDone);
        !           410:     }
        !           411: }
        !           412: 
        !           413: IOReturn
        !           414: IOHDDrive::formatMedia(UInt64 byteCapacity)
        !           415: {
        !           416:     if (!_mediaPresent) {
        !           417:         return(kIOReturnNoMedia);
        !           418:     }
        !           419: 
        !           420:     return(_provider->doFormatMedia(byteCapacity));
        !           421: }
        !           422: 
        !           423: void
        !           424: IOHDDrive::free(void)
        !           425: {
        !           426:     if (_mediaStateLock) {
        !           427:         IOLockFree(_mediaStateLock);
        !           428:     }
        !           429:     
        !           430:     super::free();
        !           431: }
        !           432: 
        !           433: /* The Callback (C) entry from our provider. We just glue
        !           434:  * right into C++.
        !           435:  */
        !           436: 
        !           437: void
        !           438: gc_glue(IOService *target,void *param,UInt64 actualTransferCount,IOReturn result)
        !           439: {
        !           440:     IOHDDrive *self;
        !           441:     struct IOHDDrive::context *cx;
        !           442: 
        !           443:     self = (IOHDDrive *) target;
        !           444:     cx = (struct IOHDDrive::context *)param;
        !           445:     cx->result = result;
        !           446:     cx->actualTransferCount = actualTransferCount;
        !           447:     
        !           448:     if (cx->result == kIOReturnSuccess) {
        !           449:         assert(cx->byteCount == cx->actualTransferCount);
        !           450:     }
        !           451:     
        !           452:     self->RWCompletion(cx);
        !           453: }
        !           454: 
        !           455: const char *
        !           456: IOHDDrive::getDeviceTypeName(void)
        !           457: {
        !           458:     return(kDeviceTypeHardDisk);
        !           459: }
        !           460: 
        !           461: UInt32
        !           462: IOHDDrive::getFormatCapacities(UInt64 * capacities,
        !           463:                                             UInt32   capacitiesMaxCount) const
        !           464: {
        !           465:     return(_provider->doGetFormatCapacities(capacities,capacitiesMaxCount));
        !           466: }
        !           467: 
        !           468: UInt64
        !           469: IOHDDrive::getMediaBlockSize() const
        !           470: {
        !           471:     return(_mediaBlockSize);
        !           472: }
        !           473: 
        !           474: IODrive::IOMediaState
        !           475: IOHDDrive::getMediaState() const
        !           476: {
        !           477:     if (_mediaPresent) {
        !           478:         return(kMediaOnline);
        !           479:     } else {
        !           480:         return(kMediaOffline);
        !           481:     }
        !           482: }
        !           483: 
        !           484: bool
        !           485: IOHDDrive::handleStart(IOService * provider)
        !           486: {
        !           487:     IOReturn result;
        !           488: 
        !           489:     /* Print device name/type information on the console: */
        !           490:     
        !           491: //    IOLog("%s[IOHDDrive] ",getName());
        !           492:     IOLog("%s drive: %s, %s, rev %s %s.\n",getName(),
        !           493:                 _provider->getVendorString(),
        !           494:                _provider->getProductString(),
        !           495:                _provider->getRevisionString(),
        !           496:                 _provider->getAdditionalDeviceInfoString());
        !           497: 
        !           498:     /*The protocol-specific provider determines whether the media is removable. */
        !           499: 
        !           500:     result = _provider->reportRemovability(&_removable);
        !           501:     if (result != kIOReturnSuccess) {
        !           502:        IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportRemovability\n",
        !           503:                        getName(),stringFromReturn(result));
        !           504:         return(false);
        !           505:     }
        !           506: 
        !           507:     if (_removable) {
        !           508: 
        !           509:         /* The protocol-specific provider determines whether we must poll to detect
        !           510:          * media insertion. Nonremovable devices never need polling.
        !           511:          */
        !           512:         
        !           513:         result = _provider->reportPollRequirements(&_pollIsRequired,&_pollIsExpensive);
        !           514: /**
        !           515:            IOLog("%s[IOHDDrive]::handleStart; pollIsRequired =  %s\n",
        !           516:                        getName(),_pollIsRequired ? "Y" : "N");
        !           517: **/
        !           518:             if (result != kIOReturnSuccess) {
        !           519:            IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportPollRequirements\n",
        !           520:                        getName(),stringFromReturn(result));
        !           521:             return(false);
        !           522:         }
        !           523:         
        !           524:         /* The protocol-specific provider determines whether the media is ejectable
        !           525:          * under software control.
        !           526:          */
        !           527:         result = _provider->reportEjectability(&_ejectable);
        !           528:         if (result != kIOReturnSuccess) {
        !           529:            IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportEjectability\n",
        !           530:                        getName(),stringFromReturn(result));
        !           531:             return(false);
        !           532:         }
        !           533: 
        !           534:         /* The protocol-specific provider determines whether the media is lockable
        !           535:          * under software control.
        !           536:          */
        !           537:         result = _provider->reportLockability(&_lockable);
        !           538:         if (result != kIOReturnSuccess) {
        !           539:            IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportLockability\n",
        !           540:                        getName(),stringFromReturn(result));
        !           541:             return(false);
        !           542:         }
        !           543: 
        !           544:     } else {           /* fixed drive: not ejectable, not lockable */
        !           545:         _ejectable     = false;
        !           546:         _lockable      = false;
        !           547:         _pollIsRequired        = true;         /* polling detects device disappearance */
        !           548:     }
        !           549:     
        !           550:     /* Check for the device being ready with media inserted: */
        !           551: 
        !           552: //    IOLog("%s[IOHDDrive]::handleStart; calling checkForMedia\n",getName());
        !           553: 
        !           554:     result = checkForMedia();
        !           555: 
        !           556:     /* The poll should never fail for nonremovable media: */
        !           557:     
        !           558:     if (result != kIOReturnSuccess && !_removable) {
        !           559:        IOLog("%s[IOHDDrive]::handleStart: err '%s' from checkForMedia\n",
        !           560:                        getName(),stringFromReturn(result));
        !           561:         return(false);
        !           562:     }
        !           563: 
        !           564:     return(true);
        !           565: }
        !           566: 
        !           567: /* The driver has been instructed to stop. If the media is writable, issue a
        !           568:  * Synchronize Cache command to ensure that all blocks have been written to
        !           569:  * the media. Then attempt to eject it.
        !           570:  */
        !           571: void
        !           572: IOHDDrive::handleStop(IOService * provider)
        !           573: {
        !           574:     if (_mediaPresent) {
        !           575:         if (!_writeProtected) {
        !           576:             (void)_provider->doSynchronizeCache();     /* ignore any error */
        !           577:         }
        !           578:         (void)ejectMedia();            /* eject media if it's removable */
        !           579:     }
        !           580: 
        !           581:     super::detach(provider);
        !           582: }
        !           583: 
        !           584: bool
        !           585: IOHDDrive::init(OSDictionary * properties)
        !           586: {
        !           587:     /* Do minimal initialization: */
        !           588: 
        !           589:     initMediaStates();
        !           590:     
        !           591:     _removable         = false;
        !           592:     _ejectable         = false;
        !           593:     _lockable          = false;
        !           594:     _pollIsExpensive   = false;
        !           595:     _pollIsRequired    = false;
        !           596:     
        !           597:     _mediaBlockSize            = 0;
        !           598:     _maxBlockNumber            = 0;
        !           599:     _maxReadByteTransfer       = 0;
        !           600:     _maxWriteByteTransfer      = 0;
        !           601: 
        !           602:     bzero(&_stats,sizeof(struct stats));
        !           603: 
        !           604:     _mediaStateLock = IOLockAlloc();
        !           605:     if (_mediaStateLock == 0)  {
        !           606:         return false;
        !           607:     }
        !           608:     IOLockInit(_mediaStateLock);
        !           609: 
        !           610:     return(super::init(properties));
        !           611: }
        !           612: 
        !           613: void
        !           614: IOHDDrive::initMediaStates(void)
        !           615: {
        !           616:     _mediaPresent      = false;
        !           617:     _writeProtected            = false;
        !           618: }
        !           619: 
        !           620: IOMedia *
        !           621: IOHDDrive::instantiateDesiredMediaObject(void)
        !           622: {
        !           623:     return(new IOMedia);
        !           624: }
        !           625: 
        !           626: IOReturn
        !           627: IOHDDrive::instantiateMediaObject(IOMedia **media,UInt64 base,UInt64 byteSize,UInt32 blockSize,
        !           628:                                         bool isWholeMedia,char *mediaName)
        !           629: {
        !           630:     IOMedia *m;
        !           631:     bool result;
        !           632: 
        !           633:     *media = NULL;                             /* just for safety */
        !           634:     
        !           635:     m = instantiateDesiredMediaObject();
        !           636:     if (m == NULL) {
        !           637:         return(kIOReturnNoMemory);
        !           638:     }
        !           639: 
        !           640:     result = m->init(   base,                  /* base byte offset */
        !           641:                         byteSize,              /* byte size */
        !           642:                         blockSize,             /* preferred block size */
        !           643:                        _ejectable,             /* TRUE if ejectable */
        !           644:                         isWholeMedia,          /* TRUE if whole physical media */
        !           645:                         !_writeProtected,      /* TRUE if writable */
        !           646:                        "");                    /* content hint */
        !           647: 
        !           648:     if (result) {
        !           649:         *media = m;
        !           650:         m->setName(mediaName);
        !           651:         return(kIOReturnSuccess);
        !           652:         
        !           653:     } else {                                   /* some init error */
        !           654:         m->release();
        !           655:         return(kIOReturnBadArgument);          /* beats me...call it this error */
        !           656:     }
        !           657: }
        !           658: 
        !           659: bool
        !           660: IOHDDrive::isMediaEjectable(void) const
        !           661: {
        !           662:     return(_ejectable);
        !           663: }
        !           664: 
        !           665: bool
        !           666: IOHDDrive::isMediaPollExpensive(void) const
        !           667: {
        !           668:     return(_pollIsExpensive);
        !           669: }
        !           670: 
        !           671: bool
        !           672: IOHDDrive::isMediaPollRequired(void) const
        !           673: {
        !           674:     return(_pollIsRequired);
        !           675: }
        !           676: 
        !           677: IOReturn
        !           678: IOHDDrive::lockMedia(bool locked)
        !           679: {
        !           680:     if (_lockable) {
        !           681:         return(_provider->doLockUnlockMedia(locked));
        !           682:     } else {
        !           683:         return(kIOReturnUnsupported);        
        !           684:     }
        !           685: }
        !           686: 
        !           687: IOReturn
        !           688: IOHDDrive::pollMedia(void)
        !           689: {
        !           690:     if (!_pollIsRequired) {                    /* shouldn't poll; it's an error */
        !           691:         
        !           692:         return(kIOReturnUnsupported);
        !           693:         
        !           694:     } else {                                   /* poll is required...do it */
        !           695: 
        !           696:         return(checkForMedia());
        !           697:         
        !           698:     }
        !           699: }
        !           700: 
        !           701: IOService *
        !           702: IOHDDrive::probe(IOService * provider,SInt32 * score)
        !           703: {
        !           704:     OSObject *object;
        !           705:     OSString *prop;
        !           706:     const char *string;
        !           707:     
        !           708:     if (!super::probe(provider,score)) {
        !           709:         return(NULL);
        !           710:     }
        !           711: 
        !           712:     /* Make sure the device type is what we expect. We can't simply use
        !           713:      * the class type because many nubs are subclasses of the same superclass.
        !           714:      */
        !           715: 
        !           716:     object = provider->getProperty(kDeviceTypeProperty);
        !           717:     if (object == NULL) {
        !           718:         IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' has no device-type property\n",
        !           719:             getName(),provider->getName());
        !           720:         return(NULL);
        !           721:     }
        !           722:     
        !           723:     prop = OSDynamicCast(OSString,provider->getProperty(kDeviceTypeProperty));
        !           724:     
        !           725:     if (prop == NULL) {                /* the property doesn't exist */
        !           726:         IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' device-type property is wrong type\n",
        !           727:             getName(),provider->getName());
        !           728:         return(NULL);
        !           729:         
        !           730:     } else {                   /* we got the property */
        !           731:         string = prop->getCStringNoCopy();
        !           732: /**
        !           733:         IOLog("%s[IOHDDrive]:;probe; provider '%s' device-type property is '%s'\n",
        !           734:               getName(),provider->getName(),string);
        !           735: **/
        !           736:         if (strcmp(string,getDeviceTypeName()) != 0) { /* the value isn't what we want */
        !           737: /***
        !           738:             IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' device type '%s' is wrong\n",
        !           739:               getName(),provider->getName(),string);
        !           740: ***/
        !           741:             return(NULL);
        !           742:         }
        !           743: 
        !           744:     /* The device type is right; now make sure the class is. */
        !           745:         
        !           746:         if (setProvider(provider)) {           /* the provider's class is what we expect */
        !           747: //            IOLog("%s[IOHDDrive]:;probe; matching provider '%s'\n",getName(),_provider->getName());
        !           748:             return(this);
        !           749:         } else {                               /* the provider's class is wrong, ignore it */
        !           750:             IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' is wrong class\n",
        !           751:                   getName(),provider->getName());
        !           752:             return(NULL);
        !           753:         }
        !           754:     }
        !           755: }
        !           756: 
        !           757: IOReturn
        !           758: IOHDDrive::recordAdditionalMediaParameters(void)
        !           759: {
        !           760:     return(kIOReturnSuccess);                  /* default does nothing */
        !           761: }
        !           762:     
        !           763: IOReturn
        !           764: IOHDDrive::recordMediaParameters(void)
        !           765: {
        !           766:     IOReturn result;
        !           767:     OSDictionary *propTable;
        !           768: 
        !           769:     /* Determine the device's block size and max block number.
        !           770:      * What should an unformatted device report? All zeroes, or an error?
        !           771:      */
        !           772: 
        !           773:     result = _provider->reportBlockSize(&_mediaBlockSize);    
        !           774:     if (result != kIOReturnSuccess) {
        !           775:         goto err;
        !           776:     }
        !           777: 
        !           778:     result = _provider->reportMaxValidBlock(&_maxBlockNumber);    
        !           779:     if (result != kIOReturnSuccess) {
        !           780:         goto err;
        !           781:     }
        !           782: 
        !           783:     /* Calculate the maximum allowed byte transfers for reads and writes. */
        !           784: 
        !           785:     result = _provider->reportMaxReadTransfer(_mediaBlockSize,&_maxReadByteTransfer);
        !           786:     if (result != kIOReturnSuccess) {
        !           787:         goto err;
        !           788:     }
        !           789: 
        !           790:     result = _provider->reportMaxWriteTransfer(_mediaBlockSize,&_maxWriteByteTransfer);
        !           791:     if (result != kIOReturnSuccess) {
        !           792:         goto err;
        !           793:     }
        !           794: 
        !           795:     /* Is the media write-protected? */
        !           796: 
        !           797:     result = _provider->reportWriteProtection(&_writeProtected);
        !           798:     if (result != kIOReturnSuccess) {
        !           799:         goto err;
        !           800:     }
        !           801: 
        !           802:     /* Create media-related properties: */
        !           803: 
        !           804:     propTable = constructMediaProperties();
        !           805:     
        !           806:    // xxx what to do with propTable? xxx
        !           807:         
        !           808:     /* Record additional media-related information,
        !           809:      * and perhaps create properties.
        !           810:      */
        !           811: 
        !           812:     result = recordAdditionalMediaParameters();
        !           813:     if (result != kIOReturnSuccess) {
        !           814:         goto err;
        !           815:     }
        !           816: 
        !           817:     return(kIOReturnSuccess);          /* everything was successful */
        !           818: 
        !           819:     /* If we fall thru to here, we had some kind of error. Set everything to
        !           820:      * a reasonable state since we haven't got any real information.
        !           821:      */
        !           822: 
        !           823: err:;
        !           824:     _mediaPresent = false;
        !           825:     _writeProtected = true;
        !           826: 
        !           827:     return(result);
        !           828: }
        !           829: 
        !           830: void
        !           831: IOHDDrive::rejectMedia(void)
        !           832: {
        !           833:     (void)_provider->doEjectMedia();   /* eject it, ignoring any error */
        !           834:     initMediaStates();                 /* deny existence of new media */
        !           835: }
        !           836: 
        !           837: void                    
        !           838: IOHDDrive::RWCompletion(struct IOHDDrive::context *cx)   
        !           839: {
        !           840:     bool isWrite;
        !           841: 
        !           842:     _stats.providerCompletionsRcvd++;
        !           843:     
        !           844:     if (cx->result == kIOReturnSuccess) {
        !           845:         assert(cx->byteCount == cx->actualTransferCount);
        !           846:     } else {
        !           847:         IOLog("%s[IOHDDrive]::RWCompletion; result = %s, req=%d, actual=%d\n",
        !           848:               getName(),stringFromReturn(cx->result),(int)cx->byteCount,
        !           849:               (int)cx->actualTransferCount);
        !           850:     }
        !           851:     
        !           852:     if (cx->buffer->getDirection() == kIODirectionOut) {
        !           853:         isWrite = true;
        !           854:     } else {
        !           855:         isWrite = false;
        !           856:     }
        !           857: 
        !           858:     addToBytesTransferred(cx->actualTransferCount,0,0,isWrite);
        !           859:     if (cx->result != kIOReturnSuccess) {
        !           860:         incrementErrors(isWrite);
        !           861:     }   
        !           862: 
        !           863:     if (cx->buffer) {
        !           864:         cx->buffer->complete();
        !           865:     }
        !           866: 
        !           867:     /* Complete the client request, which was issued at executeRequest: */
        !           868: 
        !           869:     assert(cx->completion.action);
        !           870: 
        !           871:     _stats.clientCompletionsSent++;
        !           872:     complete(cx->completion,cx->result,cx->actualTransferCount);
        !           873:     _stats.clientCompletionsDone++;
        !           874: 
        !           875:     if (showStats()) {
        !           876:         IOLog("%s[IOHDDrive]; RWCompletion:   cr=%5d,ps=%5d,pr=%5d,pcr=%5d,ccs=%5d,ccd=%5d\n",
        !           877:             getName(),
        !           878:             _stats.clientReceived,
        !           879:             _stats.providerSent,
        !           880:             _stats.providerReject,
        !           881:             _stats.providerCompletionsRcvd,
        !           882:             _stats.clientCompletionsSent,
        !           883:             _stats.clientCompletionsDone);
        !           884:     }
        !           885:     deleteContext(cx);
        !           886: }   
        !           887: 
        !           888: bool
        !           889: IOHDDrive::setProvider(IOService * provider)
        !           890: {
        !           891:     _provider = OSDynamicCast(IOHDDriveNub,provider);
        !           892: 
        !           893:     if (_provider == NULL) {
        !           894:         return(false);
        !           895:     } else {
        !           896:         return(true);
        !           897:     }
        !           898: }
        !           899: 
        !           900: bool
        !           901: IOHDDrive::showStats(void)
        !           902: {
        !           903:     return(false);
        !           904: }
        !           905: 
        !           906: /* Tear down the stack above the specified object. Usually these objects will
        !           907:  * be of type IOMedia, but they could be any IOService.
        !           908:  */
        !           909: IOReturn
        !           910: IOHDDrive::tearDown(IOService *media)
        !           911: {
        !           912:     IOReturn result;
        !           913: 
        !           914:     lockForArbitration();
        !           915: 
        !           916:     if (media) {
        !           917:         if (media->terminate()) {
        !           918:             media->release();
        !           919: 
        !           920:             initMediaStates();        /* clear all knowledge of the media */
        !           921:             result = kIOReturnSuccess;
        !           922: 
        !           923:         } else {
        !           924:             result = kIOReturnBusy;
        !           925:         }
        !           926:     } else {
        !           927:         result = kIOReturnNoMedia;
        !           928:     }
        !           929: 
        !           930:     unlockForArbitration();
        !           931: 
        !           932:     return(result);
        !           933: }
        !           934: 
        !           935: bool
        !           936: IOHDDrive::validateNewMedia(void)
        !           937: {
        !           938:     return(true);
        !           939: }

unix.superglobalmegacorp.com

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