Annotation of XNU/iokit/Families/IOSCSIParallel/IOSCSIParallelDevice.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:  *     IOSCSIParallelDevice.cpp
                     24:  *
                     25:  */
                     26: 
                     27: #include <IOKit/IOSyncer.h> 
                     28: #include <IOKit/scsi/IOSCSIParallelInterface.h>
                     29: 
                     30: #undef  super
                     31: #define super IOSCSIDevice
                     32: 
                     33: #ifndef MIN
                     34: #define MIN(a,b) ((a <= b) ? a : b)
                     35: #endif
                     36: 
                     37: OSDefineMetaClassAndAbstractStructors( IOCDBDevice,  IOService )
                     38: OSDefineMetaClassAndAbstractStructors( IOSCSIDevice, IOCDBDevice )
                     39: OSDefineMetaClassAndStructors( IOSCSIParallelDevice, IOSCSIDevice )
                     40: 
                     41: /*
                     42:  *
                     43:  *
                     44:  *
                     45:  */ 
                     46: bool IOSCSIParallelDevice::init( IOSCSIParallelController *forController, SCSITargetLun forTargetLun )
                     47: {
                     48:     SCSICDBInfo                scsiCDB;
                     49: 
                     50:     controller  = forController;     
                     51:     targetLun   = forTargetLun;
                     52: 
                     53:     target      = &controller->targets[targetLun.target];
                     54: 
                     55:     queue_init( &deviceList );     
                     56:     queue_init( &bypassList );       
                     57:     queue_init( &activeList );      
                     58:     queue_init( &abortList  );  
                     59:     queue_init( &cancelList ); 
                     60: 
                     61:     clientSem = IORWLockAlloc();
                     62:     if ( clientSem == 0 )
                     63:     {
                     64:         return false;
                     65:     }
                     66: 
                     67:     if ( super::init() == false )
                     68:     {
                     69:         return false;
                     70:     }
                     71: 
                     72:     if ( controller->controllerInfo.lunPrivateDataSize != 0 )
                     73:     {
                     74:         devicePrivateData = IOMallocContiguous( controller->controllerInfo.lunPrivateDataSize, 16, 0 );
                     75:         if ( devicePrivateData == 0 )
                     76:         {
                     77:             return false;
                     78:         }
                     79:     }
                     80: 
                     81:     bzero( &scsiCDB, sizeof(scsiCDB) );
                     82:     
                     83:     abortCmd = allocCommand(kIOSCSIParallelDevice, 0);
                     84:     if ( abortCmd == 0 )
                     85:     {
                     86:         return false;
                     87:     }
                     88:     abortCmd->setTimeout( kSCSIAbortTimeoutmS );    
                     89:     
                     90:     cancelCmd = allocCommand(kIOSCSIParallelDevice, 0);
                     91:     if ( cancelCmd == 0 )
                     92:     {
                     93:         return false;
                     94:     }
                     95:     cancelCmd->setTimeout( 0 );    
                     96:     cancelCmd->cmdType = kSCSICommandCancel;
                     97: 
                     98:     reqSenseCmd = allocCommand(kIOSCSIParallelDevice, 0);
                     99:     if ( reqSenseCmd == 0 )
                    100:     {
                    101:         return false;
                    102:     }    
                    103:     scsiCDB.cdbLength = 6;
                    104:     scsiCDB.cdb[0]    = kSCSICmdRequestSense;
                    105:     scsiCDB.cdb[1]    = targetLun.lun << 4;
                    106:     scsiCDB.cdbTag     = (UInt32) -1;
                    107: 
                    108:     reqSenseCmd->setTimeout( kSCSIReqSenseTimeoutmS );    
                    109:     reqSenseCmd->cmdType = kSCSICommandReqSense;
                    110:     reqSenseCmd->setCDB( &scsiCDB );
                    111: 
                    112:     if ( controller->controllerInfo.tagAllocationMethod == kTagAllocationPerLun )
                    113:     {
                    114:         tagArray = (UInt32 *)IOMalloc( controller->tagArraySize );
                    115:         bzero( tagArray, controller->tagArraySize );
                    116:     }
                    117: 
                    118:     deviceGate = IOCommandGate::commandGate( this, (IOCommandGate::Action) &IOSCSIParallelDevice::receiveCommand );
                    119:     if ( deviceGate == 0 )
                    120:     {
                    121:         return false;
                    122:     }    
                    123:     
                    124:     if ( controller->workLoop->addEventSource( deviceGate ) != kIOReturnSuccess )
                    125:     {
                    126:         return false;
                    127:     }
                    128: 
                    129:     commandLimitSave = commandLimit = controller->controllerInfo.maxCommandsPerLun;
                    130: 
                    131:     idleNotifyActive = false;
                    132: 
                    133:     normalQHeld      = false;
                    134:     bypassQHeld             = false;
                    135:      
                    136:     return true;
                    137: }
                    138: 
                    139: /*
                    140:  *
                    141:  *
                    142:  *
                    143:  */
                    144: IOReturn IOSCSIParallelDevice::probeTargetLun()
                    145: {
                    146:     SCSICDBInfo                                cdb;
                    147:     SCSIResults                                result;
                    148:     IOReturn                           rc;    
                    149:     IOMemoryDescriptor                         *desc = 0;
                    150:     SCSIInquiry                                *inqData = 0;
                    151:     UInt32                             size = 0;
                    152:     OSDictionary                       *propTable;
                    153: 
                    154:     probeCmd = allocCommand(kIOSCSIParallelDevice, 0);
                    155:      
                    156:     if ( probeCmd == 0 )
                    157:     {
                    158:         rc = kIOReturnNoMemory;
                    159:         goto probeError;
                    160:     }
                    161:     
                    162:     size = kDefaultInquirySize;
                    163:      
                    164:     if ( !(inqData = (SCSIInquiry *)IOMalloc(size)) )
                    165:     {
                    166:         rc = kIOReturnNoMemory;
                    167:         goto probeError;
                    168:     }
                    169: 
                    170:     desc = IOMemoryDescriptor::withAddress( (void *)inqData, size, kIODirectionIn );
                    171:     if ( desc == 0 )
                    172:     {
                    173:         rc = kIOReturnNoMemory;    
                    174:         goto probeError;
                    175:     }
                    176: 
                    177:     if ( open( this ) == false )
                    178:     {
                    179:         rc = kIOReturnError;
                    180:         goto probeError;
                    181:     }
                    182:      
                    183:     bzero( (void *)&cdb, sizeof(cdb) );
                    184:     
                    185:     cdb.cdbLength = 6;
                    186:     cdb.cdb[0] = kSCSICmdInquiry;
                    187:     cdb.cdb[4] = size;
                    188:     probeCmd->setCDB( &cdb );
                    189: 
                    190:     probeCmd->setPointers( desc, size, false );
                    191: 
                    192:     probeCmd->setTimeout( kSCSIProbeTimeoutmS );
                    193:     probeCmd->setCallback();
                    194:     
                    195:     probeCmd->execute();
                    196:     
                    197:     rc = probeCmd->getResults( &result );
                    198: 
                    199:     switch ( rc )
                    200:     {
                    201:         case kIOReturnSuccess:
                    202:             break;
                    203: 
                    204:         case kIOReturnUnderrun:
                    205:             rc = kIOReturnSuccess;
                    206:             break;
                    207:  
                    208:         default:
                    209:             goto probeError;
                    210:     }
                    211: 
                    212:     if ( result.bytesTransferred <= (UInt32)(&inqData->flags - &inqData->devType) )
                    213:     {
                    214:         rc = kIOReturnDeviceError;
                    215:         goto probeError;
                    216:     }
                    217:  
                    218:     switch ( inqData->devType &  kSCSIDevTypeQualifierMask )
                    219:     {
                    220:         case kSCSIDevTypeQualifierConnected:
                    221:         case kSCSIDevTypeQualifierNotConnected:
                    222:             break; 
                    223:         case kSCSIDevTypeQualifierReserved:
                    224:         case kSCSIDevTypeQualifierMissing:  
                    225:             rc = kIOReturnNotAttached;
                    226:             break;
                    227:         default:
                    228:             break;
                    229:     }
                    230: 
                    231:     if ( rc != kIOReturnSuccess )
                    232:     {
                    233:         goto probeError;
                    234:     } 
                    235:  
                    236:     inquiryData     = inqData;
                    237:     inquiryDataSize = result.bytesTransferred;
                    238: 
                    239:     propTable = createProperties();
                    240:     if ( !propTable ) goto probeError;
                    241: 
                    242:     setPropertyTable( propTable );
                    243: 
                    244:     propTable->release();
                    245: 
                    246: probeError: ;
                    247:     
                    248:     if ( desc )
                    249:     {    
                    250:         desc->release();
                    251:     }
                    252:     
                    253:     if ( inqData )
                    254:     {
                    255:         if ( rc != kIOReturnSuccess )
                    256:         {
                    257:             IOFree( inqData, size );
                    258:         }
                    259:     }    
                    260:     
                    261:     return rc;
                    262: }
                    263: 
                    264: /*
                    265:  *
                    266:  *
                    267:  *
                    268:  */
                    269: void IOSCSIParallelDevice::setupTarget()
                    270: {   
                    271:     SCSITargetParms                    targetParms;
                    272:     UInt32                             transferWidth;
                    273: 
                    274:     if ( targetLun.lun != 0 )
                    275:     {
                    276:         close( this );
                    277:         return;
                    278:     }
                    279: 
                    280:     bzero( &targetParms, sizeof(SCSITargetParms) );
                    281: 
                    282:     if ( inquiryData->flags & kSCSIDevCapSync )
                    283:     {
                    284:         targetParms.transferPeriodpS = controller->controllerInfo.minTransferPeriodpS;
                    285:         targetParms.transferOffset   = controller->controllerInfo.maxTransferOffset;
                    286:     }
                    287: 
                    288:     if ( inquiryData->flags & kSCSIDevCapWBus32 )
                    289:     {
                    290:         transferWidth = 4;
                    291:     }
                    292:     else if ( inquiryData->flags & kSCSIDevCapWBus16 )
                    293:     {
                    294:         transferWidth = 2;
                    295:     }
                    296:     else
                    297:     {
                    298:         transferWidth = 1;
                    299:     }
                    300: 
                    301:     targetParms.transferWidth = MIN( transferWidth, controller->controllerInfo.maxTransferWidth );
                    302: 
                    303:     if ( inquiryData->flags & kSCSIDevCapCmdQue )
                    304:     {
                    305:         targetParms.enableTagQueuing = true;
                    306:     }
                    307: 
                    308:     setTargetParms( &targetParms );   
                    309: 
                    310:     close( this );
                    311: }
                    312: 
                    313: /*
                    314:  *
                    315:  *
                    316:  *
                    317:  */
                    318: void IOSCSIParallelDevice::getInquiryData( void *clientBuf, UInt32 clientBufSize, UInt32 *clientDataSize )
                    319: {
                    320:     UInt32             len;
                    321: 
                    322:     bzero( clientBuf, clientBufSize );
                    323: 
                    324:     len = MIN( clientBufSize, inquiryDataSize );
                    325:    
                    326:     bcopy( inquiryData, clientBuf, len );
                    327: 
                    328:     *clientDataSize = len;
                    329: }
                    330: 
                    331: /*
                    332:  *
                    333:  *
                    334:  *
                    335:  */
                    336: void IOSCSIParallelDevice::abort()
                    337: {
                    338:     submitCommand( kSCSICommandAbortAll, 0 );
                    339: }
                    340:  
                    341: /*
                    342:  *
                    343:  *
                    344:  *
                    345:  */
                    346: void IOSCSIParallelDevice::reset()
                    347: {
                    348:     submitCommand( kSCSICommandDeviceReset, 0 );
                    349: }
                    350: 
                    351: /*
                    352:  *
                    353:  *
                    354:  *
                    355:  */
                    356: void IOSCSIParallelDevice::holdQueue( UInt32 queueType )
                    357: {
                    358:     if ( getWorkLoop()->inGate() == false )
                    359:     {
                    360:         IOPanic( "IOSCSIParallelDevice::holdQueue() - must be called from workloop!!\n\r");
                    361:     }
                    362: 
                    363:     if ( queueType == kQTypeBypassQ )
                    364:     {
                    365:         bypassQHeld = true;
                    366:     }
                    367:     else if ( queueType == kQTypeNormalQ )
                    368:     {
                    369:         normalQHeld = true;   
                    370:     }
                    371: }
                    372: 
                    373: /*
                    374:  *
                    375:  *
                    376:  *
                    377:  */
                    378: void IOSCSIParallelDevice::releaseQueue( UInt32 queueType )
                    379: {
                    380:     if ( getWorkLoop()->inGate() == false )
                    381:     {
                    382:         IOPanic( "IOSCSIParallelDevice::releaseQueue() - must be called from workloop!!\n\r");
                    383:     }
                    384: 
                    385:    if ( queueType == kQTypeBypassQ )
                    386:     {
                    387:         bypassQHeld = false;
                    388:     }
                    389:     else if ( queueType == kQTypeNormalQ )
                    390:     {
                    391:         normalQHeld = false;   
                    392:     }
                    393: 
                    394:     dispatchRequest();
                    395: }
                    396: 
                    397: /*
                    398:  *
                    399:  *
                    400:  *
                    401:  */
                    402: void IOSCSIParallelDevice::notifyIdle(  void *target = 0, CallbackFn callback = 0, void *refcon = 0  )
                    403: {
                    404:     if ( getWorkLoop()->inGate() == false )
                    405:     {
                    406:         IOPanic( "IOSCSIParallelDevice:::notifyIdle() - must be called from workloop!!\n\r");
                    407:     }
                    408: 
                    409:     if ( callback == 0 )
                    410:     {
                    411:         idleNotifyActive = false;
                    412:         return;
                    413:     }
                    414: 
                    415:     if ( idleNotifyActive == true )
                    416:     {
                    417:         IOPanic( "IOSCSIParallelDevice:::notifyIdle() - only one idle notify may be active\n\r");
                    418:     }
                    419: 
                    420:     idleNotifyActive   = true;
                    421:     idleNotifyTarget   = target;
                    422:     idleNotifyCallback = callback;
                    423:     idleNotifyRefcon   = refcon;
                    424: 
                    425:     checkIdleNotify();    
                    426: }
                    427: 
                    428:    
                    429: /*
                    430:  *
                    431:  *
                    432:  *
                    433:  */
                    434: void IOSCSIParallelDevice::submitCommand( UInt32 cmdType, IOSCSIParallelCommand *scsiCmd, UInt32 cmdSequenceNumber )
                    435: {
                    436:     deviceGate->runCommand( (void *)cmdType, (void *)scsiCmd, (void *) cmdSequenceNumber, (void *) 0 );
                    437: }
                    438: 
                    439: /*
                    440:  *
                    441:  *
                    442:  *
                    443:  */
                    444: void IOSCSIParallelDevice::receiveCommand( UInt32 cmdType, IOSCSIParallelCommand *scsiCmd, UInt32 cmdSequenceNumber, void *p3 )
                    445: {
                    446:     queue_head_t               *queue;
                    447: 
                    448:     switch ( cmdType )
                    449:     {
                    450:         case kSCSICommandExecute:
                    451:             scsiCmd->cmdType = (SCSICommandType) cmdType;
                    452: 
                    453:             scsiCmd->scsiCmd.cdbFlags &= (kCDBFNoDisconnect);
                    454: 
                    455:             queue = (scsiCmd->queueType == kQTypeBypassQ) ? &bypassList : &deviceList;
                    456: 
                    457:             if ( scsiCmd->queuePosition == kQPositionHead ) 
                    458:             {
                    459:                 stackCommand( queue, scsiCmd );
                    460:             }
                    461:             else
                    462:             { 
                    463:                 addCommand( queue, scsiCmd );
                    464:             }
                    465: 
                    466:             dispatchRequest();
                    467:             break;
                    468:      
                    469:         case kSCSICommandAbortAll:
                    470:             abortAllCommands( kSCSICommandAbortAll );    
                    471:             break;
                    472: 
                    473:         case kSCSICommandAbort:
                    474:             abortCommand( scsiCmd, cmdSequenceNumber );
                    475:             break;
                    476: 
                    477:         case kSCSICommandDeviceReset:
                    478:             abortAllCommands( kSCSICommandDeviceReset );            
                    479:             break;
                    480: 
                    481:         default:
                    482:             /* ??? */
                    483:             break;
                    484:     }    
                    485: }
                    486: 
                    487: /*
                    488:  *
                    489:  *
                    490:  *
                    491:  */
                    492: void IOSCSIParallelDevice::abortCommand( IOSCSIParallelCommand *scsiCmd, UInt32 sequenceNumber )
                    493: {
                    494:     if ( scsiCmd->list == (queue_head_t *)deviceGate )
                    495:     {
                    496:         if ( scsiCmd->sequenceNumber != sequenceNumber )
                    497:         {
                    498:             return;
                    499:         }    
                    500:         scsiCmd->results.returnCode = kIOReturnAborted;
                    501:     }
                    502:     else if ( scsiCmd->list == &deviceList )
                    503:     {
                    504:         if ( scsiCmd->sequenceNumber != sequenceNumber )
                    505:         {
                    506:             return;
                    507:         }    
                    508: 
                    509:         deleteCommand( &deviceList, scsiCmd );
                    510:         scsiCmd->results.returnCode = kIOReturnAborted;
                    511:         finishCommand( scsiCmd );
                    512:     }
                    513:     else if ( scsiCmd->list == &activeList )
                    514:     {
                    515:         if ( scsiCmd->sequenceNumber != sequenceNumber )
                    516:         {
                    517:             return;
                    518:         }    
                    519: 
                    520:         moveCommand( &activeList, &abortList, scsiCmd );
                    521: 
                    522:         dispatchRequest();     
                    523:     }
                    524: }
                    525: 
                    526: 
                    527: /*
                    528:  *
                    529:  *
                    530:  *
                    531:  */
                    532: void IOSCSIParallelDevice::abortAllCommands( SCSICommandType cmdType )
                    533: {
                    534:     IOSCSIParallelDevice               *abortDev;
                    535: 
                    536:     abortCmdPending = cmdType;
                    537: 
                    538:     if ( abortCmdPending == kSCSICommandAbortAll )
                    539:     {
                    540:         if ( client != 0 )
                    541:         {
                    542:             client->message( kSCSIClientMsgDeviceAbort, this );
                    543:         }
                    544:     }
                    545:     else if ( abortCmdPending == kSCSICommandDeviceReset )
                    546:     {
                    547:         queue_iterate( &target->deviceList, abortDev, IOSCSIParallelDevice *, nextDevice )
                    548:         {   
                    549:             if ( abortDev->client != 0 )
                    550:             {
                    551:                 abortDev->client->message( kSCSIClientMsgDeviceReset, abortDev );
                    552:             }
                    553:         }
                    554:     }
                    555: 
                    556:     dispatchRequest();
                    557: }
                    558: 
                    559: /*
                    560:  *
                    561:  *
                    562:  *
                    563:  */
                    564: void IOSCSIParallelDevice::resetOccurred( SCSIClientMessage clientMsg )
                    565: {
                    566:     if ( client != 0 && clientMsg != kSCSIClientMsgNone )
                    567:     {
                    568:         client->message( clientMsg, this );
                    569:     }
                    570:     
                    571:     moveAllCommands( &activeList, &cancelList, kIOReturnAborted );
                    572:     moveAllCommands( &abortList,  &cancelList, kIOReturnAborted );
                    573:     
                    574:     abortState        = kStateIdle;
                    575:     reqSenseState     = kStateIdle;
                    576:     commandLimit      = commandLimitSave;
                    577:     negotiateState    = kStateIdle;
                    578: 
                    579:     dispatchRequest();
                    580: }
                    581: 
                    582: void IOSCSIParallelDevice::resetComplete()
                    583: {
                    584:     if ( client != 0 )
                    585:     {
                    586:         client->message( kSCSIClientMsgBusReset | kSCSIClientMsgDone, this );
                    587:     }
                    588: }
                    589: 
                    590: 
                    591: /*
                    592:  *
                    593:  *
                    594:  *
                    595:  */
                    596: bool IOSCSIParallelDevice::checkAbortQueue()
                    597: {
                    598:     IOSCSIParallelCommand              *origCmd;
                    599: 
                    600:     if ( abortState == kStateActive )
                    601:     {
                    602:         return true;
                    603:     }
                    604:         
                    605:     if ( abortCmdPending != kSCSICommandNone )
                    606:     {
                    607:         abortCmd->origCommand = 0;
                    608: 
                    609:         abortCmd->scsiCmd.cdbTagMsg   = 0;
                    610:         abortCmd->scsiCmd.cdbTag      = (UInt32) -1;
                    611:   
                    612:        
                    613:         abortCmd->cmdType             = abortCmdPending;        
                    614:         abortCmd->scsiCmd.cdbAbortMsg = (abortCmdPending == kSCSICommandAbortAll) 
                    615:                                                       ? kSCSIMsgAbort : kSCSIMsgBusDeviceReset;
                    616: 
                    617:         if ( disableDisconnect == true )
                    618:         {
                    619:             abortCmd->scsiCmd.cdbFlags |= kCDBFlagsNoDisconnect;
                    620:         }
                    621:         else
                    622:         {
                    623:             abortCmd->scsiCmd.cdbFlags &= ~kCDBFlagsNoDisconnect;
                    624:         }
                    625: 
                    626:     
                    627:         abortCmd->timer = ( abortCmd->timeout != 0 ) ?
                    628:                                           abortCmd->timeout / kSCSITimerIntervalmS + 1 : 0; 
                    629: 
                    630:         bzero( &abortCmd->results, sizeof(SCSIResults) );
                    631: 
                    632:         abortCmdPending = kSCSICommandNone;
                    633:         abortState      = kStateActive;
                    634: 
                    635:         addCommand( &activeList, abortCmd ); 
                    636:         controller->executeCommand( abortCmd );
                    637:     }             
                    638:     else if ( queue_empty( &abortList ) == false )
                    639:     {   
                    640:         origCmd = (IOSCSIParallelCommand *)queue_first( &abortList );
                    641:         abortCmd->origCommand = origCmd;
                    642:         
                    643:         abortCmd->cmdType = kSCSICommandAbort;
                    644:         abortCmd->scsiCmd.cdbTagMsg = origCmd->scsiCmd.cdbTagMsg;
                    645:         abortCmd->scsiCmd.cdbTag    = origCmd->scsiCmd.cdbTag;
                    646:         abortCmd->scsiCmd.cdbAbortMsg = (abortCmd->scsiCmd.cdbTagMsg != 0) 
                    647:                                                      ? kSCSIMsgAbortTag : kSCSIMsgAbort;
                    648: 
                    649:         abortCmd->timer = ( abortCmd->timeout != 0 ) ?
                    650:                                           abortCmd->timeout / kSCSITimerIntervalmS + 1 : 0; 
                    651: 
                    652:         bzero( &abortCmd->results, sizeof(SCSIResults) );          
                    653: 
                    654:         abortState = kStateActive;
                    655: 
                    656:         addCommand( &activeList, abortCmd ); 
                    657:         controller->executeCommand( abortCmd );
                    658:     }   
                    659:     else
                    660:     {
                    661:         return false;
                    662:     }     
                    663:     
                    664:     return true;
                    665: }
                    666: 
                    667: /*
                    668:  *
                    669:  *
                    670:  *
                    671:  */
                    672: void IOSCSIParallelDevice::checkCancelQueue()
                    673: {
                    674:     if ( cancelState != kStateIdle )
                    675:     {
                    676:         return;
                    677:     }
                    678:         
                    679:     if ( queue_empty( &cancelList ) == true )
                    680:     {
                    681:          return;
                    682:     }
                    683: 
                    684:     if ( controller->controllerInfo.disableCancelCommands == true )
                    685:     {
                    686:         return;
                    687:     }
                    688: 
                    689:     cancelCmd->origCommand = (IOSCSIParallelCommand *)queue_first( &cancelList );
                    690:     bzero( &cancelCmd->results, sizeof(SCSIResults) );
                    691: 
                    692:     cancelState = kStateActive;
                    693:     controller->cancelCommand( cancelCmd );
                    694: }
                    695: 
                    696: /*
                    697:  *
                    698:  *
                    699:  *
                    700:  */
                    701: bool IOSCSIParallelDevice::checkReqSense()
                    702: {
                    703:     IOMemoryDescriptor         *senseData;
                    704:     UInt32                     senseLength;
                    705:     SCSITargetParms            *tpCur;
                    706:     
                    707:     if ( target->reqSenseState == kStateActive )
                    708:     {
                    709:         return true;
                    710:     }
                    711:                  
                    712:     if ( reqSenseState == kStateIssue )
                    713:     {
                    714:         reqSenseCmd->origCommand = reqSenseOrigCmd;
                    715:         bzero( &reqSenseCmd->results, sizeof(SCSIResults) );
                    716: 
                    717:         reqSenseOrigCmd->getPointers( &senseData, &senseLength, 0, true );
                    718:         reqSenseCmd->setPointers( senseData, senseLength, false );
                    719: 
                    720:         reqSenseCmd->scsiCmd.cdbFlags = 0;
                    721: 
                    722:         if ( disableDisconnect == true )
                    723:         {
                    724:             reqSenseCmd->scsiCmd.cdbFlags |= kCDBFlagsNoDisconnect;
                    725:         }
                    726:         else
                    727:         {
                    728:             reqSenseCmd->scsiCmd.cdbFlags &= ~kCDBFlagsNoDisconnect;
                    729:         }
                    730: 
                    731:         tpCur = &target->targetParmsCurrent;
                    732: 
                    733:         if ( tpCur->transferWidth != 1 )
                    734:         {
                    735:             reqSenseCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateWDTR;
                    736:         }
                    737: 
                    738:         if ( tpCur->transferOffset != 0  )
                    739:         {
                    740:             reqSenseCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateSDTR;
                    741:         }
                    742: 
                    743:         reqSenseCmd->timer = ( reqSenseCmd->timeout != 0 ) ?
                    744:                                           reqSenseCmd->timeout / kSCSITimerIntervalmS + 1 : 0; 
                    745: 
                    746:         reqSenseCmd->scsiCmd.cdb[3] = (senseLength >> 8) & 0xff;
                    747:         reqSenseCmd->scsiCmd.cdb[4] =  senseLength       & 0xff;
                    748:         
                    749:         reqSenseState = kStatePending;
                    750:     }
                    751:     
                    752:     if ( reqSenseState == kStatePending )
                    753:     {        
                    754:         target->reqSenseState = reqSenseState = kStateActive;
                    755: 
                    756:         addCommand( &activeList, reqSenseCmd ); 
                    757: 
                    758:         controller->executeCommand( reqSenseCmd );
                    759:     }  
                    760: 
                    761:     return (target->reqSenseCount > 0);  
                    762: }
                    763: 
                    764: 
                    765: /*
                    766:  *
                    767:  *
                    768:  *
                    769:  */
                    770: bool IOSCSIParallelDevice::checkDeviceQueue( UInt32 *dispatchAction ) 
                    771: {
                    772:     IOSCSIParallelCommand      *scsiCmd = 0;
                    773:     queue_head_t               *queue;
                    774:     UInt32                     i;
                    775:     bool                       rc = true;
                    776:     bool                       queueHeld;
                    777: 
                    778:     do
                    779:     {
                    780:         if ( controller->commandCount >= controller->commandLimit )
                    781:         {
                    782:             *dispatchAction = kDispatchStop;
                    783:             break;
                    784:         }
                    785: 
                    786:         if ( target->commandCount >= target->commandLimit )
                    787:         {
                    788:             *dispatchAction = kDispatchNextTarget;
                    789:             break;
                    790:         }
                    791: 
                    792:         *dispatchAction = kDispatchNextLun;
                    793: 
                    794:         if ( commandCount >= commandLimit )
                    795:         {
                    796:             break;
                    797:         }
                    798: 
                    799:         for ( i=0; i < 2; i++ )
                    800:         {
                    801:             queueHeld = (i == 0) ? bypassQHeld : normalQHeld;
                    802:             queue     = (i == 0) ? &bypassList : &deviceList;
                    803:         
                    804:             if ( queueHeld == true )
                    805:             {
                    806:                 continue;
                    807:             }
                    808: 
                    809:             scsiCmd = checkCommand( queue );
                    810:             if ( scsiCmd != 0 )
                    811:             {
                    812:                 *dispatchAction = kDispatchNextCommand;
                    813:                 break;
                    814:             }
                    815:         }
                    816: 
                    817:         if ( i == 2 )
                    818:         { 
                    819:             rc = false;
                    820:             break;
                    821:         }
                    822: 
                    823:         if ( disableDisconnect == true || (scsiCmd->scsiCmd.cdbFlags & kCDBFNoDisconnect) )
                    824:         {
                    825:             scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsNoDisconnect;
                    826: 
                    827:             if ( controller->commandCount != 0 )
                    828:             {
                    829:                 *dispatchAction = kDispatchNextLun;
                    830:                 break;
                    831:             }
                    832:           
                    833:             controller->noDisconnectCmd  = scsiCmd;
                    834:             controller->commandLimitSave = controller->commandLimit;
                    835:             controller->commandLimit     = 1;
                    836:         }        
                    837: 
                    838:         else if ( checkTag( scsiCmd ) == false )
                    839:         {
                    840:             switch ( controller->controllerInfo.tagAllocationMethod )
                    841:             {
                    842:                 case kTagAllocationPerTarget:
                    843:                     *dispatchAction = kDispatchNextTarget;
                    844:                     break;    
                    845:                 case kTagAllocationPerController:
                    846:                     *dispatchAction = kDispatchStop;
                    847:                     break;
                    848:                 case kTagAllocationPerLun:
                    849:                     ;
                    850:                 default:
                    851:                     *dispatchAction = kDispatchNextLun;
                    852:             }
                    853:             break;
                    854:         }
                    855:              
                    856:         getCommand( queue );
                    857: 
                    858:         checkNegotiate( scsiCmd );         
                    859:    
                    860:         scsiCmd->timer = ( scsiCmd->timeout != 0 ) ? scsiCmd->timeout / kSCSITimerIntervalmS + 1 : 0; 
                    861: 
                    862:         commandCount++;
                    863:         target->commandCount++;
                    864:         controller->commandCount++;        
                    865: 
                    866:         addCommand( &activeList, scsiCmd );
                    867: 
                    868:         controller->executeCommand( scsiCmd );
                    869: 
                    870:     } while ( 0 );
                    871: 
                    872:     return rc;
                    873: }   
                    874: 
                    875: /*
                    876:  *
                    877:  *
                    878:  *
                    879:  */
                    880: void IOSCSIParallelDevice::rescheduleCommand( IOSCSIParallelCommand *scsiCmd )
                    881: {
                    882:     if ( scsiCmd->list != &activeList )
                    883:     {
                    884:         IOLog( "IOSCSIParallelController::rescheduleCommand() - Command not active. Cmd = %08x\n\r", (int)scsiCmd );
                    885:         return;
                    886:     }
                    887: 
                    888:     deleteCommand( &activeList, scsiCmd );
                    889:  
                    890:     switch ( scsiCmd->cmdType )
                    891:     {
                    892:         case kSCSICommandExecute:
                    893:             if ( scsiCmd->scsiCmd.cdbTagMsg != 0 )
                    894:             {
                    895:                 freeTag( scsiCmd->scsiCmd.cdbTag );
                    896:                 scsiCmd->scsiCmd.cdbTag = (UInt32) -1;
                    897:             }
                    898: 
                    899:             stackCommand( &deviceList, scsiCmd );
                    900: 
                    901:             if ( scsiCmd->scsiCmd.cdbFlags & kCDBFlagsNoDisconnect )
                    902:             {
                    903:                 controller->commandLimit    = controller->commandLimitSave;
                    904:                 controller->noDisconnectCmd = 0;
                    905:             }
                    906: 
                    907:             controller->commandCount--;
                    908:             target->commandCount--;
                    909:             commandCount--;
                    910:             break;
                    911: 
                    912:         case kSCSICommandReqSense:
                    913:             reqSenseState         = kStatePending;
                    914:             target->reqSenseState = kStateIdle;
                    915:             break;
                    916: 
                    917:         case kSCSICommandAbortAll:
                    918:         case kSCSICommandDeviceReset:
                    919:             abortCmdPending = scsiCmd->cmdType;
                    920: 
                    921:         case kSCSICommandAbort:
                    922:             abortState = kStateIdle;
                    923:             break;
                    924: 
                    925:         default:
                    926:             ;
                    927:     } 
                    928: 
                    929:     dispatchRequest();
                    930: 
                    931: }    
                    932:  
                    933: /*
                    934:  *
                    935:  *
                    936:  *
                    937:  */
                    938: bool IOSCSIParallelDevice::setTargetParms( SCSITargetParms *targetParms )
                    939: {
                    940:     IOSCSIParallelCommand      *scsiCmd;
                    941:     SCSICDBInfo                scsiCDB;
                    942:     bool               fTagEnable;
                    943:     bool               rc = true;
                    944: 
                    945:     IOMemoryDescriptor *senseDesc;
                    946:     UInt8              senseBuffer[14];
                    947: 
                    948: 
                    949:     if ( getWorkLoop()->inGate() == true )
                    950:     {
                    951:         IOPanic( "IOSCSIParallelDevice:::setTargetParms() - must not be called from workloop!!\n\r");
                    952:     }
                    953: 
                    954:     IOWriteLock( target->clientSem );
                    955: 
                    956:     target->targetParmsNew   = *targetParms;
                    957: 
                    958:     target->commandLimit     = 1;
                    959: 
                    960:     fTagEnable =  (targetParms->enableTagQueuing == true)
                    961:                      && (controller->controllerInfo.tagAllocationMethod != kTagAllocationNone) 
                    962:                            && (controller->controllerInfo.maxTags != 0);
                    963:  
                    964:     if ( fTagEnable == true )
                    965:     {
                    966:         target->commandLimitSave = controller->controllerInfo.maxCommandsPerTarget;
                    967:     }
                    968:     else
                    969:     {
                    970:         target->commandLimitSave                = 1;
                    971:         target->targetParmsNew.enableTagQueuing = false;
                    972:     }
                    973: 
                    974:     scsiCmd = allocCommand(kIOSCSIParallelDevice, 0);
                    975: 
                    976:     bzero( &scsiCDB, sizeof( SCSICDBInfo ) );
                    977:     
                    978:     scsiCDB.cdbLength = 6;
                    979:     scsiCDB.cdb[0]    = kSCSICmdTestUnitReady;
                    980:     scsiCDB.cdb[1]    = targetLun.lun << 4;
                    981:     scsiCmd->setCDB( &scsiCDB );
                    982: 
                    983:     
                    984:     senseDesc = IOMemoryDescriptor::withAddress(senseBuffer, sizeof(senseBuffer), kIODirectionIn);
                    985:     if ( senseDesc == 0 ) return false;
                    986:     scsiCmd->setPointers( senseDesc, sizeof(senseBuffer), false, true );
                    987: 
                    988:     IOWriteLock( target->targetSem );
                    989: 
                    990:     target->negotiateState = kStateIssue;
                    991: 
                    992:     scsiCmd->execute();
                    993: 
                    994:     IOWriteLock( target->targetSem );
                    995:     IORWUnlock( target->targetSem );
                    996: 
                    997:     scsiCmd->release();
                    998:     senseDesc->release();
                    999: 
                   1000:     rc =  (target->negotiateResult == kIOReturnSuccess);
                   1001: 
                   1002:     IORWUnlock( target->clientSem );
                   1003: 
                   1004:     return rc;
                   1005: }
                   1006:  
                   1007: /*
                   1008:  *
                   1009:  *
                   1010:  *
                   1011:  */
                   1012: void IOSCSIParallelDevice::getTargetParms( SCSITargetParms *targetParms )
                   1013: {
                   1014:     *targetParms = target->targetParmsCurrent;
                   1015: }    
                   1016: 
                   1017: /*
                   1018:  *
                   1019:  *
                   1020:  *
                   1021:  */
                   1022: bool IOSCSIParallelDevice::setLunParms( SCSILunParms *lunParms )
                   1023: {
                   1024:     IOSCSIParallelCommand      *scsiCmd;
                   1025:     SCSICDBInfo                scsiCDB;
                   1026: 
                   1027:     IOMemoryDescriptor *senseDesc;
                   1028:     UInt8              senseBuffer[14];
                   1029: 
                   1030:     if ( getWorkLoop()->inGate() == true )
                   1031:     {
                   1032:         IOPanic( "IOSCSIParallelDevice:::setLunParms() - must not be called from workloop!!\n\r");
                   1033:     }
                   1034: 
                   1035:     IOWriteLock( clientSem );
                   1036: 
                   1037:     lunParmsNew      = *lunParms;
                   1038:     commandLimitSave = commandLimit;
                   1039:     commandLimit     = 1;
                   1040: 
                   1041:     scsiCmd = allocCommand(kIOSCSIParallelDevice, 0);
                   1042:     
                   1043:     bzero( &scsiCDB, sizeof( SCSICDBInfo ) );
                   1044: 
                   1045:     scsiCDB.cdbLength = 6;
                   1046:     scsiCDB.cdb[0]    = kSCSICmdTestUnitReady;
                   1047:     scsiCDB.cdb[1]    = targetLun.lun << 4;
                   1048:     scsiCmd->setCDB( &scsiCDB );
                   1049: 
                   1050:     senseDesc = IOMemoryDescriptor::withAddress(senseBuffer, sizeof(senseBuffer), kIODirectionIn);
                   1051:     if ( senseDesc == 0 ) return false;
                   1052:     scsiCmd->setPointers( senseDesc, sizeof(senseBuffer), false, true );
                   1053: 
                   1054:     negotiateState = kStateIssue;
                   1055: 
                   1056:     scsiCmd->execute();
                   1057: 
                   1058:     scsiCmd->release();
                   1059:     senseDesc->release();
                   1060: 
                   1061:     while ( negotiateState != kStateIdle )
                   1062:     {
                   1063:         IOSleep( 100 );
                   1064:     }
                   1065: 
                   1066:     IORWUnlock( clientSem );
                   1067: 
                   1068:     return true;
                   1069: }
                   1070:  
                   1071: /*
                   1072:  *
                   1073:  *
                   1074:  *
                   1075:  */
                   1076: void IOSCSIParallelDevice::getLunParms( SCSILunParms *lunParms )
                   1077: {
                   1078:     lunParms->disableDisconnect = disableDisconnect;
                   1079: }    
                   1080: 
                   1081: /*
                   1082:  *
                   1083:  *
                   1084:  *
                   1085:  */
                   1086: void IOSCSIParallelDevice::checkNegotiate( IOSCSIParallelCommand *scsiCmd )
                   1087: {
                   1088:     SCSITargetParms    *tpCur, *tpNew;
                   1089: 
                   1090:     if ( target->negotiateState == kStateIssue )
                   1091:     {
                   1092:         if ( target->commandCount == 0 )
                   1093:         {
                   1094:             tpNew = &target->targetParmsNew;
                   1095:             tpCur = &target->targetParmsCurrent;
                   1096: 
                   1097:             target->negotiateResult = kIOReturnSuccess;
                   1098: 
                   1099:             if ( tpCur->transferPeriodpS != tpNew->transferPeriodpS || tpCur->transferOffset != tpNew->transferOffset  )
                   1100:             {
                   1101:                 scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateSDTR;
                   1102:                 target->negotiateState = kStateActive;
                   1103:             }
                   1104: 
                   1105:             if ( tpCur->transferWidth != tpNew->transferWidth )
                   1106:             {
                   1107:                 scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateWDTR;
                   1108:                 target->negotiateState = kStateActive;
                   1109:             }
                   1110: 
                   1111:             if ( tpCur->enableTagQueuing != tpNew->enableTagQueuing ) 
                   1112:             {
                   1113:                 scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsEnableTagQueuing;
                   1114:                 target->negotiateState = kStateActive;
                   1115:             }
                   1116:             
                   1117:             if ( target->negotiateState != kStateActive )
                   1118:             {
                   1119:                 IORWUnlock( target->targetSem ); 
                   1120:                 target->negotiateState  = kStateIdle;
                   1121:                 target->commandLimit    = target->commandLimitSave;
                   1122:             }
                   1123: 
                   1124:             *tpCur = *tpNew;
                   1125:         }
                   1126:     }
                   1127: 
                   1128:     if ( negotiateState == kStateIssue )
                   1129:     {
                   1130:         if ( commandCount == 0 )
                   1131:         {
                   1132:             disableDisconnect = lunParmsNew.disableDisconnect;
                   1133:             negotiateState = kStateIdle;
                   1134:         }
                   1135:     }               
                   1136: }    
                   1137: 
                   1138: /*
                   1139:  *
                   1140:  *
                   1141:  *
                   1142:  */
                   1143: bool IOSCSIParallelDevice::checkTag( IOSCSIParallelCommand *scsiCmd )
                   1144: {
                   1145:     SCSICDBInfo                scsiCDB;
                   1146:     bool               rc = true;
                   1147: 
                   1148:     scsiCmd->getCDB( &scsiCDB );
                   1149: 
                   1150:     scsiCDB.cdbTagMsg = 0;
                   1151:     scsiCDB.cdbTag    = (UInt32)-1;
                   1152: 
                   1153:     do 
                   1154:     {
                   1155:         if ( scsiCmd->device->target->targetParmsCurrent.enableTagQueuing == false )
                   1156:         {
                   1157:             break;
                   1158:         }
                   1159:     
                   1160:         if ( allocTag( &scsiCDB.cdbTag ) == false )
                   1161:         {
                   1162:              rc = false;
                   1163:              break;
                   1164:         }
                   1165: 
                   1166:         if ( scsiCDB.cdbTagMsg == 0 )
                   1167:         {
                   1168:             scsiCDB.cdbTagMsg = kSCSIMsgSimpleQueueTag;
                   1169:         }
                   1170:     }
                   1171:     while ( 0 );
                   1172: 
                   1173:     scsiCmd->setCDB( &scsiCDB );
                   1174: 
                   1175:     return rc;
                   1176: }
                   1177: 
                   1178: /*
                   1179:  *
                   1180:  *
                   1181:  *
                   1182:  */
                   1183: bool IOSCSIParallelDevice::allocTag( UInt32 *tagId )
                   1184: {
                   1185:     UInt32             i;
                   1186:     UInt32             tagIndex;
                   1187:     UInt32             tagMask;
                   1188:     UInt32             *tags = 0;
                   1189: 
                   1190:     switch ( controller->controllerInfo.tagAllocationMethod )
                   1191:     {
                   1192:         case kTagAllocationPerLun:
                   1193:             tags = tagArray;
                   1194:             break;
                   1195:         case kTagAllocationPerTarget:
                   1196:             tags = target->tagArray;
                   1197:             break;    
                   1198:         case kTagAllocationPerController:
                   1199:             tags = controller->tagArray;
                   1200:             break;
                   1201:         default:
                   1202:             ;
                   1203:     }
                   1204:     
                   1205:     if ( tags == 0 ) return false;
                   1206: 
                   1207:     for ( i = 0; i < controller->controllerInfo.maxTags; i++ )
                   1208:     {
                   1209:         tagIndex = i / 32; 
                   1210:         tagMask  = 1 << (i % 32);
                   1211:         if ( !(tags[tagIndex] & tagMask) )
                   1212:         {
                   1213:             tags[tagIndex] |= tagMask;
                   1214:             *tagId = i;
                   1215:             return true;
                   1216:         }
                   1217:     }
                   1218:     return false;
                   1219: }
                   1220: 
                   1221: /*
                   1222:  *
                   1223:  *
                   1224:  *
                   1225:  */
                   1226: void IOSCSIParallelDevice::freeTag( UInt32 tagId )
                   1227: {
                   1228:     UInt32             *tags = 0;
                   1229: 
                   1230:     switch ( controller->controllerInfo.tagAllocationMethod )
                   1231:     {
                   1232:         case kTagAllocationPerLun:
                   1233:             tags = tagArray;
                   1234:             break;
                   1235:         case kTagAllocationPerTarget:
                   1236:             tags = target->tagArray;
                   1237:             break;    
                   1238:         case kTagAllocationPerController:
                   1239:             tags = controller->tagArray;
                   1240:             break;
                   1241:         default:
                   1242:             ;
                   1243:     }
                   1244: 
                   1245:     if ( tags == 0 ) return;
                   1246: 
                   1247:     tags[tagId/32] &= ~(1 << (tagId % 32));
                   1248: }
                   1249: 
                   1250: /*
                   1251:  *
                   1252:  *
                   1253:  *
                   1254:  */
                   1255: IOSCSIParallelCommand *IOSCSIParallelDevice::findCommandWithNexus( UInt32 tagValue )
                   1256: {
                   1257:     IOSCSIParallelCommand              *scsiCmd;
                   1258: 
                   1259:     queue_iterate( &activeList, scsiCmd, IOSCSIParallelCommand *, nextCommand )
                   1260:     {
                   1261:         switch ( scsiCmd->cmdType )
                   1262:         {
                   1263:             case kSCSICommandExecute:
                   1264:             case kSCSICommandReqSense:
                   1265:                 if ( scsiCmd->scsiCmd.cdbTag == tagValue )
                   1266:                 {
                   1267:                     return scsiCmd;
                   1268:                 }
                   1269:                 break;
                   1270:             default:
                   1271:                 ;
                   1272:         }
                   1273:     }
                   1274: 
                   1275:     queue_iterate( &abortList, scsiCmd, IOSCSIParallelCommand *, nextCommand )
                   1276:     {
                   1277:         switch ( scsiCmd->cmdType )
                   1278:         {
                   1279:             case kSCSICommandExecute:
                   1280:             case kSCSICommandReqSense:
                   1281:                 if ( scsiCmd->scsiCmd.cdbTag == tagValue )
                   1282:                 {
                   1283:                     return scsiCmd;
                   1284:                 }
                   1285:                 break;
                   1286:             default:
                   1287:                 ;
                   1288:         }
                   1289:     }
                   1290: 
                   1291:     return 0;
                   1292: }
                   1293: 
                   1294: /*
                   1295:  *
                   1296:  *
                   1297:  *
                   1298:  */
                   1299: void IOSCSIParallelDevice::timer()
                   1300: {
                   1301:     IOSCSIParallelCommand              *scsiCmd, *tmp = 0;
                   1302:     SCSITargetLun              scsiTargetLun;
                   1303: 
                   1304:     queue_iterate( &activeList, scsiCmd, IOSCSIParallelCommand *, nextCommand )
                   1305:     {
                   1306:         tmp = (IOSCSIParallelCommand *)queue_prev( &scsiCmd->nextCommand );
                   1307:  
                   1308:         if ( scsiCmd->timer )
                   1309:         {
                   1310:             if ( !--scsiCmd->timer )
                   1311:             {
                   1312:                 scsiCmd->getTargetLun( &scsiTargetLun );
                   1313:                 IOLog("Timeout: T/L = %d:%d Cmd = %08x Cmd Type = %d\n\r", 
                   1314:                             scsiTargetLun.target, scsiTargetLun.lun, (int)scsiCmd, scsiCmd->cmdType );
                   1315: 
                   1316:                 switch ( scsiCmd->cmdType )
                   1317:                 {
                   1318:                     case kSCSICommandExecute:
                   1319:                         moveCommand( &activeList, &abortList, scsiCmd, kIOReturnTimeout );
                   1320:                         scsiCmd = tmp;
                   1321:                         break;
                   1322: 
                   1323:                     case kSCSICommandReqSense:
                   1324:                         reqSenseState = kStateIdle;
                   1325:                         moveCommand( &activeList, &abortList, scsiCmd,  kIOReturnTimeout );
                   1326:                         scsiCmd = tmp;
                   1327:                         break;                         
                   1328: 
                   1329:                     case kSCSICommandAbort:
                   1330:                     case kSCSICommandAbortAll:
                   1331:                    case kSCSICommandDeviceReset:
                   1332:                         controller->busResetState = kStateIssue;
                   1333:                         break;       
                   1334: 
                   1335:                    default:
                   1336:                         ;
                   1337:                 } 
                   1338: 
                   1339:                 dispatchRequest();                                    
                   1340:             } 
                   1341:         }
                   1342: 
                   1343:         if ( queue_end( &activeList, (queue_head_t *)scsiCmd ) == true )
                   1344:         {
                   1345:             break;
                   1346:         }
                   1347:     }
                   1348: }
                   1349: 
                   1350: /*
                   1351:  *
                   1352:  *
                   1353:  *
                   1354:  */
                   1355: void IOSCSIParallelDevice::dispatchRequest()
                   1356: {
                   1357:     target->state = kStateActive;
                   1358:     controller->dispatchRequest();
                   1359: }
                   1360:                         
                   1361: /*
                   1362:  *
                   1363:  *
                   1364:  *
                   1365:  */
                   1366: bool IOSCSIParallelDevice::dispatch( UInt32 *dispatchAction )
                   1367: {
                   1368:     bool               rc;
                   1369: 
                   1370:     checkCancelQueue();
                   1371: 
                   1372:     if ( controller->checkBusReset() == true )
                   1373:     {
                   1374:         *dispatchAction = kDispatchStop;
                   1375:         return true;
                   1376:     }
                   1377: 
                   1378:     if ( (rc = controller->commandDisable) == true )
                   1379:     {
                   1380:         *dispatchAction = kDispatchNextTarget;
                   1381:         return true;
                   1382:     }
                   1383: 
                   1384:     if ( checkAbortQueue() == true )
                   1385:     {
                   1386:         *dispatchAction = kDispatchNextTarget;
                   1387:         return true;
                   1388:     }    
                   1389: 
                   1390:     do
                   1391:     {
                   1392:         if ( (rc = controller->commandDisable) == true )
                   1393:         {
                   1394:             *dispatchAction = kDispatchStop;
                   1395:             break;
                   1396:         }
                   1397: 
                   1398:         if ( (rc = checkReqSense()) == true )
                   1399:         {
                   1400:             *dispatchAction = kDispatchNextTarget;
                   1401:             break;
                   1402:         }    
                   1403: 
                   1404:         rc = checkDeviceQueue( dispatchAction );
                   1405: 
                   1406:     } while ( *dispatchAction == kDispatchNextCommand );
                   1407: 
                   1408:     return rc;                
                   1409: }            
                   1410:             
                   1411:       
                   1412: /*
                   1413:  *
                   1414:  *
                   1415:  *
                   1416:  */
                   1417: void IOSCSIParallelDevice::completeCommand( IOSCSIParallelCommand *scsiCmd )
                   1418: {
                   1419:     SCSICommandType            cmdType;
                   1420: 
                   1421:     cmdType = scsiCmd->cmdType;
                   1422:     switch ( cmdType )
                   1423:     {
                   1424:         case kSCSICommandExecute:
                   1425:             executeCommandDone( scsiCmd );
                   1426:             break;
                   1427: 
                   1428:         case kSCSICommandReqSense:
                   1429:             executeReqSenseDone( scsiCmd );
                   1430:             break;
                   1431:        
                   1432:         case kSCSICommandAbort:
                   1433:         case kSCSICommandAbortAll:
                   1434:         case kSCSICommandDeviceReset:
                   1435:             abortCommandDone( scsiCmd );
                   1436:             break;
                   1437: 
                   1438:         case kSCSICommandCancel:
                   1439:             cancelCommandDone( scsiCmd );
                   1440:             break;
                   1441: 
                   1442:         default:
                   1443:             ;
                   1444:     }
                   1445: 
                   1446:     checkIdleNotify();
                   1447: 
                   1448:     dispatchRequest();
                   1449: }     
                   1450: 
                   1451: /*
                   1452:  *
                   1453:  *
                   1454:  *
                   1455:  */
                   1456: void IOSCSIParallelDevice::checkIdleNotify()
                   1457: {
                   1458:     if ( idleNotifyActive == false )
                   1459:     {
                   1460:         return;
                   1461:     }
                   1462: 
                   1463:     if ( (queue_empty( &activeList ) == true) 
                   1464:             &&  (queue_empty( &abortList ) == true)
                   1465:                &&  (queue_empty( &cancelList ) == true)
                   1466:                   && (target->reqSenseCount == 0) )
                   1467:     {
                   1468:         idleNotifyActive = false;
                   1469:         (idleNotifyCallback)( idleNotifyTarget, idleNotifyRefcon );
                   1470:     }
                   1471: }  
                   1472: 
                   1473: /*
                   1474:  *
                   1475:  *
                   1476:  *
                   1477:  */
                   1478: void IOSCSIParallelDevice::flushQueue( UInt32 queueType, IOReturn rc )
                   1479: {
                   1480:     queue_head_t               *queue;
                   1481: 
                   1482:     queue = (queueType == kQTypeBypassQ) ? &bypassList : &deviceList;
                   1483:     purgeAllCommands( queue, rc );
                   1484: }
                   1485:              
                   1486: /*
                   1487:  *
                   1488:  *
                   1489:  *
                   1490:  */
                   1491: void IOSCSIParallelDevice::executeCommandDone( IOSCSIParallelCommand *scsiCmd )
                   1492: {
                   1493:     deleteCommand( scsiCmd->list, scsiCmd );
                   1494: 
                   1495:     commandCount--;
                   1496:     controller->commandCount--;
                   1497:     target->commandCount--;
                   1498: 
                   1499:     if ( scsiCmd->scsiCmd.cdbTagMsg != 0 )
                   1500:     {
                   1501:         freeTag( scsiCmd->scsiCmd.cdbTag );
                   1502:         scsiCmd->scsiCmd.cdbTag = (UInt32) -1;
                   1503:     }
                   1504: 
                   1505:     if ( scsiCmd->scsiCmd.cdbFlags & (kCDBFlagsNegotiateSDTR | kCDBFlagsNegotiateWDTR | kCDBFlagsEnableTagQueuing) )
                   1506:     {
                   1507:         target->negotiateState  = kStateIdle;
                   1508:         target->commandLimit    = target->commandLimitSave;
                   1509: 
                   1510:         if ( scsiCmd->results.adapterStatus != kSCSIAdapterStatusSuccess )
                   1511:         {
                   1512:             target->negotiateResult = kIOReturnIOError;
                   1513: 
                   1514:             target->targetParmsNew.transferWidth    = 1;
                   1515:             target->targetParmsNew.transferOffset   = 0;
                   1516:             target->targetParmsNew.transferPeriodpS = 0;
                   1517:             target->targetParmsNew.enableTagQueuing = false;
                   1518: 
                   1519:             target->commandLimitSave = target->commandLimit = 1;
                   1520: 
                   1521:             target->negotiateState   = kStateIssue;
                   1522:         }
                   1523: 
                   1524:         IORWUnlock( target->targetSem ); 
                   1525:     }
                   1526: 
                   1527:     if ( scsiCmd->scsiCmd.cdbFlags & kCDBFlagsNoDisconnect )
                   1528:     {
                   1529:         controller->commandLimit = controller->commandLimitSave;
                   1530:         controller->noDisconnectCmd = 0;
                   1531:     }        
                   1532: 
                   1533:     if ( scsiCmd->results.scsiStatus == kSCSIStatusCheckCondition 
                   1534:               && scsiCmd->results.requestSenseDone == false
                   1535:                   && scsiCmd->senseData != 0 ) 
                   1536:     {
                   1537:         reqSenseOrigCmd = scsiCmd;
                   1538:         reqSenseState   = kStateIssue;
                   1539:         target->reqSenseCount++;
                   1540:         return;
                   1541:     }
                   1542: 
                   1543:     if ( scsiCmd->results.scsiStatus == kSCSIStatusQueueFull )
                   1544:     {
                   1545:         if ( commandCount > 4 )
                   1546:         {
                   1547: //            IOLog( "IOSCSI: Q-full - commandCount = %d commandLimit = %d\n\r", commandCount, commandLimit );
                   1548:             commandLimit = commandCount;
                   1549:         }
                   1550: 
                   1551:         stackCommand( &deviceList, scsiCmd );
                   1552:         return;
                   1553:     }       
                   1554: 
                   1555:     finishCommand( scsiCmd );
                   1556: }
                   1557: 
                   1558: /*
                   1559:  *
                   1560:  *
                   1561:  *
                   1562:  */
                   1563: void IOSCSIParallelDevice::executeReqSenseDone( IOSCSIParallelCommand *scsiCmd )
                   1564: {
                   1565:     IOSCSIParallelCommand              *origCommand;
                   1566: 
                   1567:     deleteCommand( scsiCmd->list, scsiCmd );
                   1568: 
                   1569:     target->reqSenseState = reqSenseState = kStateIdle;
                   1570:     target->reqSenseCount--;
                   1571:     
                   1572:     reqSenseOrigCmd = 0;
                   1573:     
                   1574:     origCommand = scsiCmd->origCommand;
                   1575: 
                   1576:     if ( (scsiCmd->results.returnCode == kIOReturnSuccess) || (scsiCmd->results.returnCode == kIOReturnUnderrun) )
                   1577:     {
                   1578:         origCommand->results.requestSenseDone   = true;
                   1579:         origCommand->results.requestSenseLength = scsiCmd->results.bytesTransferred;
                   1580:     }
                   1581:     else
                   1582:     {
                   1583:         origCommand->results.requestSenseDone   = false;
                   1584:         origCommand->results.requestSenseLength = 0;
                   1585:     }
                   1586: 
                   1587:     finishCommand( scsiCmd->origCommand );
                   1588: }
                   1589: 
                   1590: /*
                   1591:  *
                   1592:  *
                   1593:  *
                   1594:  */
                   1595: void IOSCSIParallelDevice::abortCommandDone( IOSCSIParallelCommand *scsiCmd )
                   1596: {
                   1597:     IOSCSIParallelCommand              *origSCSICmd;
                   1598:     IOSCSIParallelDevice               *abortDev;
                   1599: 
                   1600:     deleteCommand( scsiCmd->list, scsiCmd );
                   1601:     
                   1602:     if ( scsiCmd->cmdType == kSCSICommandAbortAll )
                   1603:     {
                   1604:         if ( client != 0 )
                   1605:         {
                   1606:             client->message( kSCSIClientMsgDeviceAbort | kSCSIClientMsgDone, this );
                   1607:         }
                   1608:     }
                   1609:     if ( scsiCmd->cmdType == kSCSICommandDeviceReset )
                   1610:     {
                   1611:         target->commandLimit   = target->commandLimitSave;
                   1612:         target->reqSenseCount  = 0;
                   1613:         target->reqSenseState  = kStateIdle;
                   1614:         target->negotiateState = kStateIssue;
                   1615: 
                   1616:         target->targetParmsCurrent.transferPeriodpS = 0;
                   1617:         target->targetParmsCurrent.transferOffset   = 0;
                   1618:         target->targetParmsCurrent.transferWidth    = 1;
                   1619: 
                   1620:         queue_iterate( &target->deviceList, abortDev, IOSCSIParallelDevice *, nextDevice )
                   1621:         {
                   1622:             abortDev->resetOccurred( (SCSIClientMessage)(kSCSIClientMsgDeviceReset | kSCSIClientMsgDone) );
                   1623:         }
                   1624:     }
                   1625:     else if ( scsiCmd->cmdType == kSCSICommandAbort )
                   1626:     {
                   1627:         origSCSICmd = scsiCmd->origCommand;
                   1628:         
                   1629:         if ( findCommand( &abortList, origSCSICmd ) == true )
                   1630:         {
                   1631:             moveCommand( &abortList, &cancelList, origSCSICmd, kIOReturnAborted );
                   1632:         }
                   1633:         abortState = kStateIdle;
                   1634:     }
                   1635: 
                   1636:     return;
                   1637: }
                   1638: 
                   1639: /*
                   1640:  *
                   1641:  *
                   1642:  *
                   1643:  */
                   1644: void IOSCSIParallelDevice::cancelCommandDone( IOSCSIParallelCommand *scsiCmd )
                   1645: {
                   1646:     IOSCSIParallelCommand              *origSCSICmd;
                   1647: 
                   1648:     cancelState = kStateIdle;
                   1649: 
                   1650:     origSCSICmd = scsiCmd->origCommand;
                   1651:     
                   1652:     if ( findCommand( &cancelList, origSCSICmd ) == true )
                   1653:     {
                   1654:         IOLog( "IOSCSIParallelDevice::cancelCommandDone - Cancelled command not completed - scsiCmd = %08x\n\r", (int)origSCSICmd );
                   1655:         deleteCommand( &cancelList, origSCSICmd );
                   1656:     }    
                   1657: }    
                   1658: 
                   1659: /*
                   1660:  *
                   1661:  *
                   1662:  *
                   1663:  */
                   1664: void IOSCSIParallelDevice::finishCommand( IOSCSIParallelCommand *scsiCmd )
                   1665: {
                   1666:     if ( scsiCmd->completionInfo.async.callback )
                   1667:     {
                   1668:         (*scsiCmd->completionInfo.async.callback)( scsiCmd->completionInfo.async.target, 
                   1669:                                                    scsiCmd->completionInfo.async.refcon );
                   1670:     }
                   1671:     else
                   1672:     {
                   1673:         scsiCmd->completionInfo.sync.lock->signal();
                   1674:     }
                   1675: }
                   1676: 
                   1677:     
                   1678: /*
                   1679:  *
                   1680:  *
                   1681:  */
                   1682: OSDictionary *IOSCSIParallelDevice::createProperties()
                   1683: {
                   1684:     OSDictionary       *propTable = 0;
                   1685:     OSObject           *regObj;
                   1686:     char               tmpbuf[81];
                   1687:     char               *d;
                   1688:    
                   1689: 
                   1690:     propTable = OSDictionary::withCapacity(kSCSIMaxProperties);
                   1691:     if ( propTable == NULL )
                   1692:     {
                   1693:         return NULL;
                   1694:     }
                   1695: 
                   1696:     regObj = (OSObject *)OSNumber::withNumber(targetLun.target,32);
                   1697:     if ( addToRegistry( propTable, regObj, kSCSIPropertyTarget ) != true )
                   1698:     {
                   1699:         goto createprop_error;
                   1700:     }
                   1701: 
                   1702:     regObj = (OSObject *)OSNumber::withNumber(targetLun.target,32);
                   1703:     if ( addToRegistry( propTable, regObj, kSCSIPropertyIOUnit ) != true )
                   1704:     {
                   1705:         goto createprop_error;
                   1706:     }
                   1707: 
                   1708:     regObj = (OSObject *)OSNumber::withNumber(targetLun.lun,32);
                   1709:     if ( addToRegistry( propTable, regObj, kSCSIPropertyLun ) != true )
                   1710:     {
                   1711:         goto createprop_error;
                   1712:     }
                   1713: 
                   1714:     d= tmpbuf;
                   1715:     
                   1716:     stripBlanks( d, (char *)inquiryData->vendorName, sizeof(inquiryData->vendorName) );
                   1717:     regObj = (OSObject *)OSString::withCString( d );
                   1718:     if ( addToRegistry( propTable, regObj, kSCSIPropertyVendorName ) != true )
                   1719:     {
                   1720:         goto createprop_error;
                   1721:     }
                   1722: 
                   1723:     stripBlanks( d, (char *)inquiryData->productName, sizeof(inquiryData->productName) );
                   1724:     regObj = (OSObject *)OSString::withCString( d );
                   1725:     if ( addToRegistry( propTable, regObj, kSCSIPropertyProductName ) != true )
                   1726:     {
                   1727:         goto createprop_error;
                   1728:     }
                   1729: 
                   1730:     stripBlanks( d, (char *)inquiryData->productRevision, sizeof(inquiryData->productRevision) );
                   1731:     regObj = (OSObject *)OSString::withCString( d );
                   1732:     if ( addToRegistry( propTable, regObj, kSCSIPropertyProductRevision ) != true )
                   1733:     {
                   1734:         goto createprop_error;
                   1735:    }
                   1736:         
                   1737:     return propTable;
                   1738: 
                   1739: createprop_error: ;
                   1740:     propTable->release();
                   1741:     return NULL;
                   1742: }
                   1743: 
                   1744: 
                   1745: /*
                   1746:  *
                   1747:  *
                   1748:  */
                   1749: bool IOSCSIParallelDevice::addToRegistry( OSDictionary *propTable, OSObject *regObj, char *key )
                   1750: {
                   1751:     bool                 rc;
                   1752: 
                   1753:     if ( regObj == NULL )
                   1754:     {
                   1755:         return false;
                   1756:     }
                   1757:     
                   1758:     rc  = propTable->setObject( key, regObj );
                   1759: 
                   1760:     return rc;
                   1761: }
                   1762: 
                   1763: 
                   1764: /*
                   1765:  *
                   1766:  *
                   1767:  *
                   1768:  */
                   1769: bool IOSCSIParallelDevice::matchPropertyTable(OSDictionary * table)
                   1770: {
                   1771:     bool match;
                   1772: 
                   1773:     if ( (match = compareProperty(table, kSCSIPropertyIOUnit)) )
                   1774:         match = super::matchPropertyTable(table);
                   1775: 
                   1776:     return match;
                   1777: }
                   1778: 
                   1779: 
                   1780: /*
                   1781:  *
                   1782:  *
                   1783:  *
                   1784:  */
                   1785: IOService *IOSCSIParallelDevice::matchLocation(IOService * client)
                   1786: {
                   1787:     return this;
                   1788: }
                   1789: 
                   1790: 
                   1791: /*
                   1792:  *
                   1793:  *
                   1794:  *
                   1795:  */
                   1796: void IOSCSIParallelDevice::stripBlanks( char *d, char *s, UInt32 l )
                   1797: {
                   1798:     char       *p, c;
                   1799: 
                   1800:     for ( p = d, c = *s; l && c ; l--)
                   1801:     {
                   1802:         c = (*d++ = *s++);
                   1803:         if ( c != ' ' )
                   1804:         {
                   1805:             p = d;
                   1806:         }
                   1807:     }
                   1808:     *p = 0;
                   1809: }   
                   1810: 
                   1811: /*
                   1812:  *
                   1813:  *
                   1814:  *
                   1815:  */
                   1816: IOSCSICommand *IOSCSIParallelDevice::allocCommand( IOSCSIDevice *, UInt32 clientDataSize )
                   1817: {
                   1818:     IOSCSIParallelCommand      *cmd;
                   1819: 
                   1820:     if ( (cmd = controller->allocCommand( clientDataSize )) )
                   1821:     {
                   1822:         cmd->device = this;
                   1823:     }
                   1824:     return (IOSCSICommand *)cmd;
                   1825: }
                   1826: 
                   1827: IOSCSIParallelCommand *IOSCSIParallelDevice::allocCommand( IOSCSIParallelDevice *, UInt32 clientDataSize )
                   1828: {
                   1829:     return (IOSCSIParallelCommand *) allocCommand( kIOSCSIDevice, clientDataSize );
                   1830: }
                   1831: 
                   1832: IOCDBCommand *IOSCSIParallelDevice::allocCommand( IOCDBDevice *, UInt32 clientDataSize )
                   1833: {
                   1834:     return (IOCDBCommand *) allocCommand( kIOSCSIDevice, clientDataSize );
                   1835: }
                   1836: 
                   1837: 
                   1838: /*
                   1839:  *
                   1840:  *
                   1841:  */
                   1842: IOWorkLoop *IOSCSIParallelDevice::getWorkLoop() const
                   1843: {
                   1844:     return controller->workLoop;
                   1845: }
                   1846: 
                   1847: 
                   1848: /*
                   1849:  *
                   1850:  *
                   1851:  *
                   1852:  */
                   1853: bool IOSCSIParallelDevice::open( IOService *forClient, IOOptionBits options, void *arg )
                   1854: {
                   1855:     if ( client != 0 ) return false;
                   1856: 
                   1857:     client = forClient;
                   1858: 
                   1859:     return super::open( forClient, options, arg );
                   1860: }
                   1861: 
                   1862: /*
                   1863:  *
                   1864:  *
                   1865:  *
                   1866:  */
                   1867: void IOSCSIParallelDevice::close( IOService *forClient, IOOptionBits options )
                   1868: {
                   1869:     client = 0;
                   1870: 
                   1871:     return super::close( forClient, options );
                   1872: }
                   1873: 
                   1874: /*
                   1875:  *
                   1876:  *
                   1877:  *
                   1878:  */
                   1879: IOReturn IOSCSIParallelDevice::message( UInt32 forMsg, IOService *forProvider, void *forArg )
                   1880: {
                   1881:     IOReturn           rc = kIOReturnSuccess;
                   1882:     SCSIClientMessage   clientMsg;
                   1883: 
                   1884:     clientMsg = (SCSIClientMessage) forMsg;
                   1885: 
                   1886: //    IOLog( "IOSCSIParallelDevice::message() - clientMsg = %08x\n\r", clientMsg );
                   1887: 
                   1888:     switch( clientMsg )
                   1889:     {
                   1890:         case kSCSIClientMsgBusReset:
                   1891:             holdQueue( kQTypeNormalQ );
                   1892:             break;
                   1893:         case kSCSIClientMsgBusReset | kSCSIClientMsgDone:
                   1894:             releaseQueue( kQTypeNormalQ );
                   1895:             break;
                   1896:         default:
                   1897:             rc = super::message( clientMsg, forProvider, forArg );
                   1898:     }
                   1899: 
                   1900:     return rc;
                   1901: }
                   1902: 
                   1903: /*
                   1904:  *
                   1905:  *
                   1906:  *
                   1907:  */
                   1908: void IOSCSIParallelDevice::free()
                   1909: {    
                   1910:     if ( deviceGate != 0 )
                   1911:     {
                   1912:         controller->workLoop->removeEventSource( deviceGate );
                   1913:         deviceGate->release();
                   1914:     }
                   1915: 
                   1916:     if ( reqSenseCmd != 0 )            reqSenseCmd->release();
                   1917:     if ( abortCmd != 0 )               abortCmd->release();
                   1918:     if ( cancelCmd != 0 )              cancelCmd->release();
                   1919:     if ( probeCmd != 0 )               probeCmd->release();
                   1920: 
                   1921:     if ( tagArray != 0 )               IOFree( tagArray, controller->tagArraySize );
                   1922:     if ( inquiryData != 0 )            IOFree( inquiryData, inquiryDataSize );
                   1923:     if ( devicePrivateData != 0 )      IOFreeContiguous( devicePrivateData, controller->controllerInfo.lunPrivateDataSize );
                   1924:     if ( clientSem != 0 )              IORWLockFree( clientSem );
                   1925: 
                   1926:     super::free();
                   1927: }
                   1928: 
                   1929: 

unix.superglobalmegacorp.com

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