Annotation of XNU/iokit/Families/IOSCSIHDDrive/IOSCSIHDDrive.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/scsi/IOSCSIDeviceInterface.h>
        !            26: #include <IOKit/storage/scsi/IOSCSIHDDrive.h>
        !            27: #include <IOKit/storage/scsi/IOSCSIHDDriveNub.h>
        !            28: 
        !            29: 
        !            30: /* Device types that we intend to handle. */
        !            31: 
        !            32: const UInt8    DT_DIRACCESS    = 0x00;         /* direct access disk */
        !            33: 
        !            34: #define        super   IOBasicSCSI
        !            35: OSDefineMetaClassAndStructors(IOSCSIHDDrive,IOBasicSCSI)
        !            36: 
        !            37: IOReturn
        !            38: IOSCSIHDDrive::allocateFormatBuffer(UInt8 **buf,UInt32 *len)
        !            39: {
        !            40:     /* The default implementation uses no buffer. */
        !            41: 
        !            42:     *buf = 0;
        !            43:     *len = 0;
        !            44:     return(kIOReturnSuccess);
        !            45: }
        !            46: 
        !            47: UInt8
        !            48: IOSCSIHDDrive::composeFormatBuffer(UInt8 * /* buf */,UInt32 /* buflen */)
        !            49: {
        !            50:     return(0);                 /* default: no fmtdata buffer to transfer */
        !            51: }
        !            52: 
        !            53: OSDictionary *
        !            54: IOSCSIHDDrive::constructDeviceProperties(void)
        !            55: {
        !            56:     OSDictionary *propTable;
        !            57:     OSData *prop;
        !            58:     char *typeString;
        !            59: 
        !            60:     propTable = OSDictionary::withCapacity(6);
        !            61:     
        !            62:     if (propTable) {
        !            63:         
        !            64:         prop = OSData::withBytes((void *)(&_vendor),strlen(_vendor));
        !            65:         if (prop) {
        !            66:             propTable->setObject("vendor", prop);
        !            67:         }
        !            68: 
        !            69:         prop = OSData::withBytes((void *)(&_product),strlen(_product));
        !            70:         if (prop) {
        !            71:             propTable->setObject("product", prop);
        !            72:         }
        !            73: 
        !            74:         prop = OSData::withBytes((void *)(&_rev),strlen(_rev));
        !            75:         if (prop) {
        !            76:             propTable->setObject("revision", prop);
        !            77:         }
        !            78: 
        !            79:         typeString = (char *)getDeviceTypeName();
        !            80:         prop = OSData::withBytes((void *)(typeString),strlen(typeString));
        !            81:         if (prop) {
        !            82:             propTable->setObject("device-type", prop);            
        !            83:         }
        !            84: 
        !            85: #ifdef xxx
        !            86:         prop = OSData::withBytes((void *)(&_removable),sizeof(bool));
        !            87:         if (prop) {
        !            88:             propTable->setObject("removable", prop);
        !            89:         }
        !            90: 
        !            91:         prop = OSData::withBytes((void *)(&_ejectable),sizeof(bool));
        !            92:         if (prop) {
        !            93:             propTable->setObject("ejectable", prop);
        !            94:         }   
        !            95: #endif //xxx
        !            96: 
        !            97:     }
        !            98:     
        !            99:     return(propTable);
        !           100: }
        !           101: 
        !           102: UInt32
        !           103: IOSCSIHDDrive::createFormatCdb(UInt64 /* byteCapacity */,
        !           104:                             UInt8 *cdb,UInt32 *cdbLength,
        !           105:                             UInt8 buf[],UInt32 bufLen,
        !           106:                             UInt32 *maxAutoSenseLength,UInt32 *timeoutSeconds)
        !           107: {
        !           108:     struct IOFormatcdb *c;
        !           109:     UInt8 formatControls;              /* CmpLst & Defect List Format bits */
        !           110: 
        !           111:     c = (struct IOFormatcdb *)cdb;
        !           112:     
        !           113:     c->opcode = SOP_FORMAT;
        !           114:     c->lunbits = 0;
        !           115:     c->vendor = 0;
        !           116:     c->interleave_msb = 0;
        !           117:     c->interleave_lsb = 0;
        !           118:     c->ctlbyte = 0;
        !           119: 
        !           120:     *cdbLength = 6;
        !           121: 
        !           122:     /* If we are to use a format buffer, set it up: */
        !           123:     
        !           124:     if (buf != NULL) {
        !           125:         formatControls = composeFormatBuffer(buf,bufLen);
        !           126:         c->lunbits |= (formatControls | 0x10); /* data transfer will occur */
        !           127:     }
        !           128:     
        !           129:     *maxAutoSenseLength = sizeof(SCSISenseData);       /* do the sense */
        !           130:     *timeoutSeconds = 15 * 60;                 /* a nice long time */
        !           131: 
        !           132:     return(0);
        !           133: }
        !           134: 
        !           135: IOService *
        !           136: IOSCSIHDDrive::createNub(void)
        !           137: {
        !           138:     IOService *nub;
        !           139: 
        !           140: //    IOLog("%s[IOSCSIHDDrive]::createNub\n",getName());
        !           141:     
        !           142:     /* Instantiate a nub so a generic driver can match above us. */
        !           143: 
        !           144:     nub = instantiateNub();
        !           145:     if (nub == NULL) {
        !           146:         IOLog("%s[IOSCSIHDDrive]::createNub; nub didn't instantiate\n",getName());
        !           147:         return(NULL);
        !           148:     }
        !           149: 
        !           150:     nub->init();
        !           151:     
        !           152:     if (!nub->attach(this)) {
        !           153:         IOPanic("IOSCSIHDDrive::createNub; couldn't attach IOSCSIHDDriveNub");
        !           154:     }
        !           155:     
        !           156:     nub->registerService();
        !           157:         
        !           158:     return(nub);
        !           159: }
        !           160: 
        !           161: void
        !           162: IOSCSIHDDrive::deleteFormatBuffer(UInt8 * /* buf */, UInt32 /* buflen */)
        !           163: {
        !           164:     /* The default implementation has no buffer to free. */
        !           165: }
        !           166: 
        !           167: bool
        !           168: IOSCSIHDDrive::deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen)
        !           169: {
        !           170:     if ((_inqBuf[0] & 0x1f) == DT_DIRACCESS) {
        !           171:         return(true);
        !           172:     } else {
        !           173:         return(false);                 /* we don't handle other devices */        
        !           174:     }
        !           175: }
        !           176: 
        !           177: IOReturn
        !           178: IOSCSIHDDrive::doAsyncReadWrite(IOMemoryDescriptor *buffer,
        !           179:                                             UInt32 block,UInt32 nblks,
        !           180:                                             gdCompletionFunction action,
        !           181:                                             IOService *target,void *param)
        !           182: {
        !           183: /**
        !           184:     IOLog("IOSCSIHDDrive::doAsyncReadWrite: target=%08x,action=%08x,param=%08x\n",
        !           185:           (int)target,(int)action,(int)param);
        !           186: **/    
        !           187:     return(standardAsyncReadWrite(buffer,block,nblks,action,target,param));
        !           188: }
        !           189: 
        !           190: IOReturn
        !           191: IOSCSIHDDrive::doEjectMedia(void)
        !           192: {
        !           193:     /* Spin down, eject, and leave power alone: */
        !           194:     
        !           195:     return(doStartStop(false,true,IOStartStopcdb::P_NOCHANGE));
        !           196: }
        !           197: 
        !           198: IOReturn
        !           199: IOSCSIHDDrive::doFormatMedia(UInt64 byteCapacity)
        !           200: {
        !           201:     struct context *cx;
        !           202:     UInt8 *fmtbuf;
        !           203:     IOReturn result;
        !           204:     IOSCSICommand *req;
        !           205:     SCSICDBInfo        scsiCDB;
        !           206:     UInt32 transferLength;
        !           207:     UInt32 senseLength;
        !           208:     UInt32 timeoutSeconds;
        !           209:     
        !           210:     cx = allocateContext();
        !           211:     if (cx == NULL) {
        !           212:         return(kIOReturnNoMemory);
        !           213:     }
        !           214:     
        !           215:     req = cx->scsireq;
        !           216:     
        !           217:     /* Allow a subclass to construct the cdb and return an optional
        !           218:      * memory buffer address for defect lists, etc.
        !           219:      */
        !           220: 
        !           221:     result = allocateFormatBuffer(&fmtbuf,&transferLength);
        !           222:     if (result != kIOReturnSuccess) {
        !           223:         return(result);
        !           224:     }
        !           225:     
        !           226:     bzero( &scsiCDB, sizeof(scsiCDB) );
        !           227: 
        !           228:     scsiCDB.cdbFlags |= createFormatCdb(byteCapacity,(UInt8 *)&scsiCDB.cdb,&scsiCDB.cdbLength,
        !           229:                                fmtbuf,transferLength,
        !           230:                                &senseLength,
        !           231:                                &timeoutSeconds);
        !           232: 
        !           233:     req->setCDB( &scsiCDB );
        !           234:     req->setPointers( cx->senseDataDesc, senseLength, false, true );
        !           235:     req->setTimeout( timeoutSeconds * 1000 );  
        !           236: 
        !           237:     /* If we have a buffer to transfer, create a Memory Descriptor for it: */
        !           238: 
        !           239:     if ((fmtbuf != NULL) && (transferLength != 0)) {
        !           240:         cx->memory = IOMemoryDescriptor::withAddress((void *)fmtbuf,
        !           241:                                                      transferLength,
        !           242:                                                      kIODirectionOut);
        !           243:     }
        !           244:     
        !           245:     req->setPointers( cx->memory, transferLength, true ); 
        !           246:     queueCommand(cx,kSync,getFormatMediaPowerState()); /* queue the operation, sleep awaiting power */
        !           247: 
        !           248:     result = simpleSynchIO(cx);                /* issue a simple command */
        !           249:     
        !           250:     /* Free the format buffer, if any: */
        !           251:     
        !           252:     deleteFormatBuffer(fmtbuf,transferLength);
        !           253:     
        !           254:     deleteContext(cx);
        !           255: 
        !           256:     return(result);
        !           257: }
        !           258: 
        !           259: UInt32
        !           260: IOSCSIHDDrive::doGetFormatCapacities(UInt64 * capacities,
        !           261:                                             UInt32   capacitiesMaxCount) const
        !           262: {
        !           263:     if ((capacities != NULL) && (capacitiesMaxCount > 0)) {
        !           264:         *capacities = _blockSize * (_maxBlock + 1);
        !           265:         return(1);
        !           266:     } else {
        !           267:         return(0);        
        !           268:     }
        !           269: }
        !           270: 
        !           271: /* We issue a simple Prevent/Allow command to lock or unlock the media: */
        !           272: IOReturn
        !           273: IOSCSIHDDrive::doLockUnlockMedia(bool doLock)
        !           274: {
        !           275:     struct context *cx;
        !           276:     struct IOPrevAllowcdb *c;
        !           277:     IOSCSICommand *req;
        !           278:     SCSICDBInfo   scsiCDB;
        !           279:     IOReturn result;
        !           280: 
        !           281:     cx = allocateContext();
        !           282:     if (cx == NULL) {
        !           283:         return(kIOReturnNoMemory);
        !           284:     }
        !           285:     
        !           286:     req = cx->scsireq;
        !           287:     
        !           288:     bzero( &scsiCDB, sizeof(scsiCDB) );
        !           289: 
        !           290:     c = (struct IOPrevAllowcdb *)&scsiCDB.cdb;
        !           291: 
        !           292:     c->opcode = SOP_PREVALLOW;
        !           293:     c->lunbits = 0;
        !           294:     c->reserved1 = 0;
        !           295:     c->reserved2 = 0;
        !           296:     
        !           297:     if (doLock) {
        !           298:         c->prevent = 0x01;             /* prevent removal from device */
        !           299:     } else {
        !           300:         c->prevent = 0x00;             /* allow   removal from device */      
        !           301:     }
        !           302: 
        !           303:     c->ctlbyte = 0;
        !           304: 
        !           305:     scsiCDB.cdbLength = 6;
        !           306: 
        !           307:     req->setCDB( &scsiCDB );    
        !           308: 
        !           309:     cx->memory = 0;
        !           310:     
        !           311:     req->setPointers( cx->memory, 0, false );
        !           312:     
        !           313:     queueCommand(cx,kSync,getLockUnlockMediaPowerState());     /* queue the operation, sleep awaiting power */
        !           314: 
        !           315:     result = simpleSynchIO(cx);
        !           316: 
        !           317:     deleteContext(cx);
        !           318: 
        !           319:     return(result);
        !           320: }
        !           321: 
        !           322: IOReturn
        !           323: IOSCSIHDDrive::doStart(void)
        !           324: {
        !           325:     return(doStartStop(true,false,IOStartStopcdb::P_ACTIVE));
        !           326: }
        !           327: 
        !           328: IOReturn
        !           329: IOSCSIHDDrive::doStop(void)
        !           330: {
        !           331:     return(doStartStop(false,false,IOStartStopcdb::P_NOCHANGE));
        !           332: }
        !           333: 
        !           334: IOReturn
        !           335: IOSCSIHDDrive::doStartStop(bool start,bool loadEject,UInt8 powerCondition)
        !           336: {
        !           337:     struct context *cx;
        !           338:     struct IOStartStopcdb *c;
        !           339:     IOSCSICommand *req;
        !           340:     SCSICDBInfo scsiCDB;
        !           341:     IOReturn result;
        !           342:     UInt32 powerLevel;                 /* what power level we need to be in */
        !           343: 
        !           344:     /* Issue a Start/Stop Unit command. */
        !           345: 
        !           346:     cx = allocateContext();
        !           347:     if (cx == NULL) {
        !           348:         return(kIOReturnNoMemory);
        !           349:     }
        !           350: 
        !           351:     powerLevel = getStopPowerState();          /* assume we're spinning down */
        !           352:     req = cx->scsireq;
        !           353:     
        !           354:     bzero( &scsiCDB, sizeof(SCSICDBInfo) );
        !           355: 
        !           356:     c = (struct IOStartStopcdb *)&scsiCDB.cdb;
        !           357:     c->opcode = SOP_STARTSTOP;
        !           358:     c->lunImmed = 0;
        !           359:     c->reserved1 = 0;
        !           360:     c->reserved2 = 0;
        !           361:     c->controls = powerCondition;
        !           362:     c->controls = 0;                   /* xxx powerCondition is a SCSI-3 thing */
        !           363:     if (loadEject) {
        !           364:         c->controls |= IOStartStopcdb::C_LOEJ;
        !           365:         powerLevel = getEjectPowerState();     /* let subclass decide what we need */
        !           366:     };
        !           367:     if (start) {
        !           368:         c->controls |= IOStartStopcdb::C_SPINUP;
        !           369:         powerLevel = getStartPowerState();
        !           370:     }
        !           371:     c->ctlbyte = 0;
        !           372: 
        !           373:     scsiCDB.cdbLength = 6;
        !           374: 
        !           375:     req->setCDB( &scsiCDB );
        !           376:     req->setTimeout( 10000 );
        !           377: 
        !           378:     cx->memory = 0;
        !           379:     
        !           380:     req->setPointers( cx->memory, 0, false );
        !           381:     
        !           382:     queueCommand(cx,kSync,powerLevel); /* queue the operation, sleep awaiting power */
        !           383: 
        !           384:     result = simpleSynchIO(cx);
        !           385: 
        !           386:     deleteContext(cx);
        !           387:     return(result);
        !           388: }
        !           389: 
        !           390: IOReturn
        !           391: IOSCSIHDDrive::doSynchronizeCache(void)
        !           392: {
        !           393:     struct context *cx;
        !           394:     struct IOSyncCachecdb *c;
        !           395:     IOSCSICommand *req;
        !           396:     SCSICDBInfo scsiCDB;
        !           397:     IOReturn result;
        !           398:     
        !           399:     cx = allocateContext();
        !           400:     if (cx == NULL) {
        !           401:         return(kIOReturnNoMemory);
        !           402:     }
        !           403: 
        !           404:     req = cx->scsireq;
        !           405:     bzero( &scsiCDB, sizeof(scsiCDB) );    
        !           406: 
        !           407:     c = (struct IOSyncCachecdb *)&scsiCDB.cdb;
        !           408: 
        !           409:     c->opcode = SOP_SYNCCACHE;
        !           410:     c->lunbits = 0;
        !           411:     c->lba_3 = 0;                      /* if zero, start at block zero */
        !           412:     c->lba_2 = 0;
        !           413:     c->lba_1 = 0;
        !           414:     c->lba_0 = 0;
        !           415:     c->reserved = 0;
        !           416:     c->nblks_msb = 0;                  /* if zero, do all blocks */
        !           417:     c->nblks_lsb = 0;
        !           418:     c->ctlbyte = 0;
        !           419:     
        !           420:     scsiCDB.cdbLength = 10;
        !           421: 
        !           422:     req->setCDB( &scsiCDB );
        !           423: 
        !           424:     cx->memory = 0;
        !           425: 
        !           426:     req->setPointers( cx->memory, 0, false );
        !           427: 
        !           428:     /* We assume there will be some data in the drive's cache, so we force the
        !           429:      * drive to be running before we issue this command.
        !           430:      */
        !           431: 
        !           432:     queueCommand(cx,kSync,getSynchronizeCachePowerState());    /* queue the operation, sleep awaiting power */
        !           433:     
        !           434:     result = simpleSynchIO(cx);
        !           435: 
        !           436:     deleteContext(cx);
        !           437: 
        !           438:     return(result);    
        !           439: }
        !           440: 
        !           441: IOReturn
        !           442: IOSCSIHDDrive::doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks)
        !           443: {
        !           444:     return(standardSyncReadWrite(buffer,block,nblks));
        !           445: }
        !           446: 
        !           447: const char *
        !           448: IOSCSIHDDrive::getDeviceTypeName(void)
        !           449: {
        !           450:     return(kDeviceTypeHardDisk);
        !           451: }
        !           452: 
        !           453: UInt32
        !           454: IOSCSIHDDrive::getEjectPowerState(void)
        !           455: {
        !           456:     return(kElectronicsOn);
        !           457: }
        !           458: 
        !           459: UInt32
        !           460: IOSCSIHDDrive::getExecuteCDBPowerState(void)
        !           461: {
        !           462:     return(kAllOn);
        !           463: }
        !           464: 
        !           465: UInt32
        !           466: IOSCSIHDDrive::getFormatMediaPowerState(void)
        !           467: {
        !           468:     return(kAllOn);
        !           469: }
        !           470: 
        !           471: UInt32
        !           472: IOSCSIHDDrive::getInitialPowerState(void)
        !           473: {
        !           474:     return(kAllOn);
        !           475: }
        !           476: 
        !           477: UInt32
        !           478: IOSCSIHDDrive::getInquiryPowerState(void)
        !           479: {
        !           480:     return(kElectronicsOn);
        !           481: }
        !           482: 
        !           483: UInt32
        !           484: IOSCSIHDDrive::getLockUnlockMediaPowerState(void)
        !           485: {
        !           486:     return(kElectronicsOn);
        !           487: }
        !           488: 
        !           489: UInt32
        !           490: IOSCSIHDDrive::getReadCapacityPowerState(void)
        !           491: {
        !           492:     return(kElectronicsOn);
        !           493: }
        !           494: 
        !           495: UInt32
        !           496: IOSCSIHDDrive::getReadWritePowerState(void)
        !           497: {
        !           498:     return(kAllOn);
        !           499: }
        !           500: 
        !           501: UInt32
        !           502: IOSCSIHDDrive::getReportWriteProtectionPowerState(void)
        !           503: {
        !           504:     return(kElectronicsOn);
        !           505: }
        !           506: 
        !           507: UInt32
        !           508: IOSCSIHDDrive::getStartPowerState(void)
        !           509: {
        !           510:     return(kElectronicsOn);
        !           511: }
        !           512: 
        !           513: UInt32
        !           514: IOSCSIHDDrive::getStopPowerState(void)
        !           515: {
        !           516:     return(kElectronicsOn);            /* we don't have to be spinning to spin down */
        !           517: }
        !           518: 
        !           519: UInt32
        !           520: IOSCSIHDDrive::getSynchronizeCachePowerState(void)
        !           521: {
        !           522:     return(kAllOn);
        !           523: }
        !           524: 
        !           525: UInt32
        !           526: IOSCSIHDDrive::getTestUnitReadyPowerState(void)
        !           527: {
        !           528:     return(kElectronicsOn);
        !           529: }
        !           530: 
        !           531: bool
        !           532: IOSCSIHDDrive::init(OSDictionary * properties)
        !           533: {
        !           534:     _mediaPresent      = false;
        !           535:     _startStopDisabled = false;
        !           536:     
        !           537:     return(super::init(properties));
        !           538: }
        !           539: 
        !           540: IOService *
        !           541: IOSCSIHDDrive::instantiateNub(void)
        !           542: {
        !           543:     IOService *nub;
        !           544: 
        !           545:     /* Instantiate a nub so a generic driver can match above us. */
        !           546:     
        !           547:     nub = new IOSCSIHDDriveNub;
        !           548:     return(nub);
        !           549: }
        !           550: 
        !           551: bool
        !           552: IOSCSIHDDrive::powerTickle(UInt32 desiredState)
        !           553: {
        !           554:     return(activityTickle(kIOPMSuperclassPolicy1,desiredState));
        !           555: }
        !           556: 
        !           557: IOReturn
        !           558: IOSCSIHDDrive::reportMediaState(bool *mediaPresent,bool *changed)
        !           559: {
        !           560:     struct context *cx;
        !           561:     struct IOTURcdb *c;
        !           562:     IOSCSICommand *req;
        !           563:     SCSICDBInfo scsiCDB;
        !           564:     SCSIResults scsiResults;
        !           565:     IOReturn result;
        !           566:     UInt8 status;
        !           567:     UInt8 senseKey;
        !           568:     
        !           569:     cx = allocateContext();
        !           570:     if (cx == NULL) {
        !           571:         return(kIOReturnNoMemory);
        !           572:     }
        !           573:     
        !           574:     req = cx->scsireq;
        !           575:     
        !           576:     bzero( &scsiCDB, sizeof(scsiCDB) );
        !           577: 
        !           578:     c = (struct IOTURcdb *)&scsiCDB.cdb;
        !           579:     c->opcode = SOP_TUR;
        !           580:     c->lunbits = 0;
        !           581:     c->reserved1 = 0;
        !           582:     c->reserved2 = 0;
        !           583:     c->reserved3 = 0;
        !           584:     c->ctlbyte = 0;
        !           585: 
        !           586:     scsiCDB.cdbLength = 6;
        !           587: 
        !           588:     req->setCDB( &scsiCDB );
        !           589:     req->setPointers( cx->senseDataDesc, 255, false, true );
        !           590: 
        !           591:     req->setTimeout( 2000 );
        !           592: 
        !           593:     cx->memory = 0;
        !           594: 
        !           595:     req->setPointers( cx->memory, 0, false );
        !           596: 
        !           597: /**
        !           598:     IOLog("IOSCSIHDDrive::reportMediaState: mp=%08x,ch=%08x\n",
        !           599:           (int)mediaPresent,(int)changed);
        !           600:     IOLog("IOSCSIHDDrive::reportMediaState: doing TUR\n");
        !           601: **/
        !           602: 
        !           603:     queueCommand(cx,kSync,getTestUnitReadyPowerState());
        !           604:     result = simpleSynchIO(cx);
        !           605:   
        !           606:     req->getResults( &scsiResults );
        !           607:     
        !           608:     status = scsiResults.scsiStatus;
        !           609: 
        !           610: /**
        !           611:     IOLog("%s[IOSCSIHDDrive]::reportMediaState; result=%s, status=%02x,sense=%02x\n",
        !           612:           getName(),stringFromReturn(result),status,cx->senseData->senseKey
        !           613:           );
        !           614: **/
        !           615:     
        !           616:     if (result == kIOReturnSuccess) {          /* TUR succeeded; device is ready */
        !           617:         
        !           618:         *mediaPresent = true;
        !           619:         *changed = (*mediaPresent != _mediaPresent); /* report if it's changed */
        !           620:         _mediaPresent = true;                  /* remember current state */
        !           621:         result = kIOReturnSuccess;
        !           622: 
        !           623:     } else {                                   /* TUR failed; check sense key */
        !           624: 
        !           625:         if ( scsiResults.requestSenseDone == true ) {
        !           626:             senseKey = cx->senseData->senseKey;
        !           627: 
        !           628:             if (senseKey == 0x02) {                    /* device says "not ready" */
        !           629:                 *mediaPresent = false;
        !           630:                 *changed = (*mediaPresent != _mediaPresent); /* report if it's changed */
        !           631:                 _mediaPresent = false;                 /* remember current state */
        !           632:                 result = kIOReturnSuccess;
        !           633: 
        !           634:             } else {                           /* funky sense key? forget it. */
        !           635: 
        !           636:                 *mediaPresent = false;
        !           637:                 *changed = (*mediaPresent != _mediaPresent); /* report if it's changed */
        !           638:                 _mediaPresent = false;                 /* remember current state */
        !           639:                 result = kIOReturnIOError;
        !           640:             }
        !           641:         }
        !           642:     }
        !           643: 
        !           644:     deleteContext(cx);
        !           645: 
        !           646: #ifndef DISKPM
        !           647:     if (*changed && *mediaPresent)
        !           648:         doStart();
        !           649: #endif
        !           650: 
        !           651:     return(result);
        !           652: }
        !           653: 
        !           654: IOReturn
        !           655: IOSCSIHDDrive::restoreElectronicsState(void)
        !           656: {
        !           657:     return(kIOReturnSuccess);
        !           658: }
        !           659: 
        !           660: /* The standard completion for a doAsyncReadWrite operation. We fire it
        !           661:  * up to our target, the generic driver.
        !           662:  */
        !           663: void
        !           664: IOSCSIHDDrive::RWCompletion(struct context *cx)
        !           665: {
        !           666:     SCSIResults scsiResults;
        !           667: 
        !           668:     /**    IOLog("IOSCSIHDDrive::RWCompletion: cx=%08x,target=%08x,action=%08x,param=%08x\n",
        !           669:           (int)cx,(int)cx->completion.target,(int)cx->completion.action,(int)cx->completion.param);
        !           670: **/
        !           671:     cx->scsireq->getResults( &scsiResults );
        !           672:     (*cx->completion.action)(cx->completion.target,cx->completion.param,
        !           673:                             scsiResults.bytesTransferred,
        !           674:                             scsiResults.returnCode);
        !           675: 
        !           676: 
        !           677:     /* Attempt to dequeue and execute any waiting commands: */
        !           678: 
        !           679:     dequeueCommands();
        !           680: }
        !           681: 
        !           682: IOReturn
        !           683: IOSCSIHDDrive::saveElectronicsState(void)
        !           684: {
        !           685:     return(kIOReturnSuccess);
        !           686: }
        !           687: 
        !           688: static IOPMPowerState ourPowerStates[kNumberOfPowerStates] = {
        !           689:     {1,IOPMNotAttainable,0,0,0,0,0,0,0,0,0,0},         /* state 00 kAllOff */
        !           690:     {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0},               /* state 01 kElectronicsOn */
        !           691:     {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}                        /* state 02 kAllOn */
        !           692: };
        !           693: 
        !           694: 
        !           695: bool
        !           696: IOSCSIHDDrive::start(IOService *provider)
        !           697: {
        !           698:     IOService *nub;
        !           699: 
        !           700:     if (!super::start(provider)) {
        !           701:         return(false);
        !           702:     }
        !           703: 
        !           704: //    IOLog("%s[IOSCSIHDDrive]::start\n",getName());
        !           705: 
        !           706:     /* Initialize and set up to perform Power Management: */
        !           707:     
        !           708:     PMinit();
        !           709:     _restoreState = false;
        !           710: #ifdef notyet  // don't register for PM yet till we handle queuing requests!
        !           711:     IOPMRegisterDevice(pm_vars->ourName,this); // join the power management tree
        !           712: #endif
        !           713:     registerControllingDriver(this,ourPowerStates,kNumberOfPowerStates);       // export power states
        !           714:     
        !           715:     nub = createNub();
        !           716:     if (nub == NULL) {
        !           717:         return(false);
        !           718:     } else {
        !           719:         return(true);
        !           720:     }
        !           721: }
        !           722: 
        !           723: // **********************************************************************************
        !           724: // maxCapabilityForDomainState
        !           725: //
        !           726: // This simple device needs only power.  If the power domain is supplying
        !           727: // power, the disk can go to its highest state.  If there is no power
        !           728: // it can only be in its lowest state, which is off.
        !           729: // **********************************************************************************
        !           730: 
        !           731: unsigned long
        !           732: IOSCSIHDDrive::maxCapabilityForDomainState(IOPMPowerFlags domainState)
        !           733: {
        !           734:     if (domainState &  IOPMPowerOn) {
        !           735:         return(kAllOn);
        !           736:     } else {
        !           737:         return(kAllOff);
        !           738:     }
        !           739: }
        !           740: 
        !           741: // **********************************************************************************
        !           742: // powerStateForDomainState
        !           743: //
        !           744: // The power domain may be changing state. If power is ON in its new
        !           745: // state, we will be on, too. If domain power is OFF, we are off.
        !           746: // **********************************************************************************
        !           747: unsigned long
        !           748: IOSCSIHDDrive::powerStateForDomainState(IOPMPowerFlags domainState)
        !           749: {
        !           750:     if (domainState & IOPMPowerOn) {
        !           751:         return(kAllOn);                /* xxx might be kElectronicsOn if drive not spun up */
        !           752:     } else {
        !           753:         return(kAllOff);
        !           754:     }
        !           755: }
        !           756: 
        !           757: // **********************************************************************************
        !           758: // initialPowerStateForDomainState
        !           759: //
        !           760: // Our parent wants to know what our initial power state is.  If power is ON in the
        !           761: // domain, we are in state kElectronicsOn or kAllOn. If domain power is OFF, we are off.
        !           762: // **********************************************************************************
        !           763: unsigned long
        !           764: IOSCSIHDDrive::initialPowerStateForDomainState(IOPMPowerFlags domainState)
        !           765: {
        !           766:     if (domainState & IOPMPowerOn) {
        !           767:         return(getInitialPowerState());                /* report whether it's spinning on startup */
        !           768:     } else {
        !           769:         return(kAllOff);
        !           770:     }
        !           771: }
        !           772: 
        !           773: // **********************************************************************************
        !           774: // setPowerState
        !           775: //
        !           776: // Someone has decided to change the disk state. We perform the change here.
        !           777: // **********************************************************************************
        !           778: IOReturn
        !           779: IOSCSIHDDrive::setPowerState(unsigned long powerStateOrdinal,IOService *)
        !           780: {
        !           781:     IOReturn result;
        !           782: 
        !           783:     result = kIOReturnSuccess;
        !           784:     
        !           785:     /* All we do in the default implementation is spin up and down. If the drive reports an
        !           786:      * error to a start/stop command, we don't bother attempting to issue those commands again.
        !           787:      *
        !           788:      * xxx Question: What should we return? Success? or an error meaning "we didn't do it!"
        !           789:      */
        !           790:     switch (powerStateOrdinal) {
        !           791: 
        !           792:         case kElectronicsOn :  /* spin down if necessary */
        !           793:                                 if (pm_vars->myCurrentState == kAllOn) {
        !           794:                                     if (!_startStopDisabled) {
        !           795:                                         result = doStop();
        !           796:                                         if (result != kIOReturnSuccess) {
        !           797:                                             _startStopDisabled = true;
        !           798:                                             result = kIOReturnSuccess;
        !           799:                                         }
        !           800:                                     }
        !           801:                                 }
        !           802:                                 break;
        !           803: 
        !           804:         case kAllOn :          /* spin up if necessary */
        !           805:                                 if (pm_vars->myCurrentState == kElectronicsOn) {
        !           806:                                     if (!_startStopDisabled) {
        !           807:                                         result = doStart();
        !           808:                                         if (result != kIOReturnSuccess) {
        !           809:                                             _startStopDisabled = true;
        !           810:                                             result = kIOReturnSuccess;
        !           811:                                         }
        !           812:                                     }
        !           813:                                 }
        !           814:                                 break;
        !           815: 
        !           816:         default:               /* we don't do other states */
        !           817:                                 result = kIOReturnSuccess;
        !           818:                                 break;
        !           819: 
        !           820:     }
        !           821: 
        !           822:     return(result);
        !           823: }
        !           824: 
        !           825: // **********************************************************************************
        !           826: /* We get called here as an advisory that the power state will change. If we are coming up
        !           827:  * from the all-off state, remember to restore the electronics state when we later power up.
        !           828:  * If we are powering-down the electronics, save any required state now.
        !           829:  */
        !           830: IOReturn
        !           831: IOSCSIHDDrive::powerStateWillChangeTo(unsigned long,unsigned long stateOrdinal,IOService *)
        !           832: {
        !           833:     if ((pm_vars->myCurrentState == kAllOff) &&
        !           834:         (stateOrdinal > kAllOff)) {                    /* we're powering up from all-off */
        !           835:         _restoreState = true;
        !           836:     }
        !           837:     
        !           838:     if ((stateOrdinal == kAllOff) &&
        !           839:         (pm_vars->myCurrentState > kAllOff)) {         /* we're powering down to all-off */
        !           840:        saveElectronicsState();
        !           841:     }
        !           842:     
        !           843:     return(IOPMAckImplied);
        !           844: }
        !           845: 
        !           846: // **********************************************************************************
        !           847: /* We get called here when power has successfully changed state. */
        !           848: IOReturn
        !           849: IOSCSIHDDrive::powerStateDidChangeTo(unsigned long,unsigned long stateOrdinal,IOService*)
        !           850: {
        !           851:     IOReturn result;
        !           852:     
        !           853:     /* If we must restore the electronics state, do it now. */
        !           854:     
        !           855:     if (_restoreState) {
        !           856:         result = restoreElectronicsState();
        !           857:         _restoreState = false;
        !           858:     }
        !           859: 
        !           860:     /* If we have powered up into a state that can execute commands, release any queued
        !           861:      * requests that were awaiting the power change.
        !           862:      */
        !           863: 
        !           864:     if (stateOrdinal > kAllOff) {
        !           865:         dequeueCommands();
        !           866:     }
        !           867:     
        !           868:     return IOPMAckImplied;
        !           869: }

unix.superglobalmegacorp.com

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