Annotation of XNU/iokit/Families/IOSCSIParallel/IOSCSIParallelDevice.cpp, revision 1.1

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