Annotation of XNU/iokit/Families/IOSCSIHDDrive/IOSCSIHDDrive.cpp, revision 1.1.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.