2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * IOSCSIParallelDevice.cpp
27 #include <IOKit/IOSyncer.h>
28 #include <IOKit/scsi/IOSCSIParallelInterface.h>
30 #include <IOKit/IOKitKeys.h>
31 #include <IOKit/system.h>
34 #define super IOSCSIDevice
37 #define MIN(a,b) ((a <= b) ? a : b)
40 OSDefineMetaClassAndAbstractStructors( IOCDBDevice
, IOService
)
41 OSDefineMetaClassAndAbstractStructors( IOSCSIDevice
, IOCDBDevice
)
42 OSDefineMetaClassAndStructors( IOSCSIParallelDevice
, IOSCSIDevice
)
49 bool IOSCSIParallelDevice::init( IOSCSIParallelController
*forController
, SCSITargetLun forTargetLun
)
53 controller
= forController
;
54 targetLun
= forTargetLun
;
56 target
= &controller
->targets
[targetLun
.target
];
58 queue_init( &deviceList
);
59 queue_init( &bypassList
);
60 queue_init( &activeList
);
61 queue_init( &abortList
);
62 queue_init( &cancelList
);
64 clientSem
= IORWLockAlloc();
70 if ( super::init() == false )
75 if ( controller
->controllerInfo
.lunPrivateDataSize
!= 0 )
77 devicePrivateData
= IOMallocContiguous( controller
->controllerInfo
.lunPrivateDataSize
, 16, 0 );
78 if ( devicePrivateData
== 0 )
84 bzero( &scsiCDB
, sizeof(scsiCDB
) );
86 abortCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
91 abortCmd
->setTimeout( kSCSIAbortTimeoutmS
);
93 cancelCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
98 cancelCmd
->setTimeout( 0 );
99 cancelCmd
->cmdType
= kSCSICommandCancel
;
101 reqSenseCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
102 if ( reqSenseCmd
== 0 )
106 scsiCDB
.cdbLength
= 6;
107 scsiCDB
.cdb
[0] = kSCSICmdRequestSense
;
108 scsiCDB
.cdb
[1] = targetLun
.lun
<< 4;
109 scsiCDB
.cdbTag
= (UInt32
) -1;
111 reqSenseCmd
->setTimeout( kSCSIReqSenseTimeoutmS
);
112 reqSenseCmd
->cmdType
= kSCSICommandReqSense
;
113 reqSenseCmd
->setCDB( &scsiCDB
);
115 if ( controller
->controllerInfo
.tagAllocationMethod
== kTagAllocationPerLun
)
117 tagArray
= (UInt32
*)IOMalloc( controller
->tagArraySize
);
118 bzero( tagArray
, controller
->tagArraySize
);
121 deviceGate
= IOCommandGate::commandGate( this, (IOCommandGate::Action
) &IOSCSIParallelDevice::receiveCommand
);
122 if ( deviceGate
== 0 )
127 if ( controller
->workLoop
->addEventSource( deviceGate
) != kIOReturnSuccess
)
132 commandLimitSave
= commandLimit
= controller
->controllerInfo
.maxCommandsPerLun
;
134 idleNotifyActive
= false;
147 IOReturn
IOSCSIParallelDevice::probeTargetLun()
152 IOMemoryDescriptor
*desc
= 0;
153 SCSIInquiry
*inqData
= 0;
155 OSDictionary
*propTable
;
157 probeCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
161 rc
= kIOReturnNoMemory
;
165 size
= sizeof(SCSIInquiry
);
167 if ( !(inqData
= (SCSIInquiry
*)IOMalloc(size
)) )
169 rc
= kIOReturnNoMemory
;
173 desc
= IOMemoryDescriptor::withAddress( (void *)inqData
, size
, kIODirectionIn
);
176 rc
= kIOReturnNoMemory
;
180 if ( open( this ) == false )
186 bzero( (void *)&cdb
, sizeof(cdb
) );
189 cdb
.cdb
[0] = kSCSICmdInquiry
;
191 probeCmd
->setCDB( &cdb
);
193 probeCmd
->setPointers( desc
, size
, false );
195 probeCmd
->setTimeout( kSCSIProbeTimeoutmS
);
196 probeCmd
->setCallback();
200 rc
= probeCmd
->getResults( &result
);
204 case kIOReturnSuccess
:
207 case kIOReturnUnderrun
:
208 rc
= kIOReturnSuccess
;
215 if ( result
.bytesTransferred
<= (UInt32
)(&inqData
->flags
- &inqData
->devType
) )
217 rc
= kIOReturnDeviceError
;
221 switch ( inqData
->devType
& kSCSIDevTypeQualifierMask
)
223 case kSCSIDevTypeQualifierConnected
:
224 case kSCSIDevTypeQualifierNotConnected
:
226 case kSCSIDevTypeQualifierReserved
:
227 case kSCSIDevTypeQualifierMissing
:
228 rc
= kIOReturnNotAttached
;
234 if ( rc
!= kIOReturnSuccess
)
239 inquiryData
= inqData
;
240 inquiryDataSize
= result
.bytesTransferred
;
242 propTable
= createProperties();
243 if ( !propTable
) goto probeError
;
245 setPropertyTable( propTable
);
247 propTable
->release();
258 if ( rc
!= kIOReturnSuccess
)
260 IOFree( inqData
, size
);
272 void IOSCSIParallelDevice::setupTarget()
274 SCSITargetParms targetParms
;
275 UInt32 transferWidth
;
277 if ( targetLun
.lun
!= 0 )
283 getTargetParms( &targetParms
);
285 if ( ((inquiryData
->flags
& kSCSIDevCapCmdQue
) != 0) && (checkCmdQueEnabled() == true) )
287 targetParms
.enableTagQueuing
= true;
290 if ( inquiryData
->flags
& kSCSIDevCapSync
)
292 targetParms
.transferPeriodpS
= controller
->controllerInfo
.minTransferPeriodpS
;
293 targetParms
.transferOffset
= controller
->controllerInfo
.maxTransferOffset
;
296 if ( inquiryData
->flags
& kSCSIDevCapWBus32
)
300 else if ( inquiryData
->flags
& kSCSIDevCapWBus16
)
309 targetParms
.transferWidth
= MIN( transferWidth
, controller
->controllerInfo
.maxTransferWidth
);
311 if ( ((inquiryData
->version
& 0x07) >= kSCSIInqVersionSCSI3
)
312 && (inquiryDataSize
> (UInt32
)(&inquiryData
->scsi3Options
- &inquiryData
->devType
)) )
314 if ( inquiryData
->scsi3Options
& kSCSI3InqOptionClockDT
)
316 targetParms
.transferOptions
|= kSCSITransferOptionClockDT
;
318 /* If it's a SCSI-3 target that handles DT clocking,
319 * assume the HBA can try using the PPR message.
321 targetParms
.transferOptions
|= kSCSITransferOptionPPR
;
323 if ( inquiryData
->scsi3Options
& kSCSI3InqOptionIUS
)
325 targetParms
.transferOptions
|= kSCSITransferOptionIUS
;
327 if ( inquiryData
->scsi3Options
& kSCSI3InqOptionQAS
)
329 targetParms
.transferOptions
|= kSCSITransferOptionQAS
;
335 setTargetParms( &targetParms
);
345 bool IOSCSIParallelDevice::checkCmdQueEnabled()
348 SCSIResults scsiResult
;
349 IOMemoryDescriptor
*desc
;
351 UInt8 controlModePage
[32];
355 bzero( (void *)&scsiCDB
, sizeof(scsiCDB
) );
357 size
= sizeof(controlModePage
);
359 scsiCDB
.cdbLength
= 6;
360 scsiCDB
.cdb
[0] = kSCSICmdModeSense6
;
361 scsiCDB
.cdb
[1] = 0x08;
362 scsiCDB
.cdb
[2] = 0x0a; // Control Mode Page
363 scsiCDB
.cdb
[4] = size
;
365 probeCmd
->setCDB( &scsiCDB
);
367 desc
= IOMemoryDescriptor::withAddress( (void *)controlModePage
, size
, kIODirectionIn
);
373 probeCmd
->setPointers( desc
, size
, false );
375 probeCmd
->setTimeout( kSCSIProbeTimeoutmS
);
376 probeCmd
->setCallback();
380 cmdRc
= probeCmd
->getResults( &scsiResult
);
382 if ( (cmdRc
== kIOReturnUnderrun
) && (scsiResult
.bytesTransferred
> 7) )
384 cmdRc
= kIOReturnSuccess
;
387 /* Check DQue bit on ControlMode Page (0x0A) */
388 if ( (cmdRc
== kIOReturnSuccess
) && ((controlModePage
[7] & 0x01) == 0) )
403 void IOSCSIParallelDevice::getInquiryData( void *clientBuf
, UInt32 clientBufSize
, UInt32
*clientDataSize
)
407 bzero( clientBuf
, clientBufSize
);
409 len
= MIN( clientBufSize
, inquiryDataSize
);
411 bcopy( inquiryData
, clientBuf
, len
);
413 *clientDataSize
= len
;
421 void IOSCSIParallelDevice::abort()
423 submitCommand( kSCSICommandAbortAll
, 0 );
431 void IOSCSIParallelDevice::reset()
433 submitCommand( kSCSICommandDeviceReset
, 0 );
441 void IOSCSIParallelDevice::holdQueue( UInt32 queueType
)
443 if ( getWorkLoop()->inGate() == false )
445 IOPanic( "IOSCSIParallelDevice::holdQueue() - must be called from workloop!!\n\r");
448 if ( queueType
== kQTypeBypassQ
)
452 else if ( queueType
== kQTypeNormalQ
)
463 void IOSCSIParallelDevice::releaseQueue( UInt32 queueType
)
465 if ( getWorkLoop()->inGate() == false )
467 IOPanic( "IOSCSIParallelDevice::releaseQueue() - must be called from workloop!!\n\r");
470 if ( queueType
== kQTypeBypassQ
)
474 else if ( queueType
== kQTypeNormalQ
)
487 void IOSCSIParallelDevice::notifyIdle( void *target
= 0, CallbackFn callback
= 0, void *refcon
= 0 )
489 if ( getWorkLoop()->inGate() == false )
491 IOPanic( "IOSCSIParallelDevice:::notifyIdle() - must be called from workloop!!\n\r");
496 idleNotifyActive
= false;
500 if ( idleNotifyActive
== true )
502 IOPanic( "IOSCSIParallelDevice:::notifyIdle() - only one idle notify may be active\n\r");
505 idleNotifyActive
= true;
506 idleNotifyTarget
= target
;
507 idleNotifyCallback
= callback
;
508 idleNotifyRefcon
= refcon
;
519 void IOSCSIParallelDevice::submitCommand( UInt32 cmdType
, IOSCSIParallelCommand
*scsiCmd
, UInt32 cmdSequenceNumber
)
521 deviceGate
->runCommand( (void *)cmdType
, (void *)scsiCmd
, (void *) cmdSequenceNumber
, (void *) 0 );
529 void IOSCSIParallelDevice::receiveCommand( UInt32 cmdType
, IOSCSIParallelCommand
*scsiCmd
, UInt32 cmdSequenceNumber
, void *p3
)
535 case kSCSICommandExecute
:
536 scsiCmd
->cmdType
= (SCSICommandType
) cmdType
;
538 scsiCmd
->scsiCmd
.cdbFlags
&= (kCDBFNoDisconnect
);
540 queue
= (scsiCmd
->queueType
== kQTypeBypassQ
) ? &bypassList
: &deviceList
;
542 if ( scsiCmd
->queuePosition
== kQPositionHead
)
544 stackCommand( queue
, scsiCmd
);
548 addCommand( queue
, scsiCmd
);
554 case kSCSICommandAbortAll
:
555 abortAllCommands( kSCSICommandAbortAll
);
558 case kSCSICommandAbort
:
559 abortCommand( scsiCmd
, cmdSequenceNumber
);
562 case kSCSICommandDeviceReset
:
563 abortAllCommands( kSCSICommandDeviceReset
);
577 void IOSCSIParallelDevice::abortCommand( IOSCSIParallelCommand
*scsiCmd
, UInt32 sequenceNumber
)
579 if ( scsiCmd
->list
== (queue_head_t
*)deviceGate
)
581 if ( scsiCmd
->sequenceNumber
!= sequenceNumber
)
585 scsiCmd
->results
.returnCode
= kIOReturnAborted
;
587 else if ( scsiCmd
->list
== &deviceList
)
589 if ( scsiCmd
->sequenceNumber
!= sequenceNumber
)
594 deleteCommand( &deviceList
, scsiCmd
);
595 scsiCmd
->results
.returnCode
= kIOReturnAborted
;
596 finishCommand( scsiCmd
);
598 else if ( scsiCmd
->list
== &activeList
)
600 if ( scsiCmd
->sequenceNumber
!= sequenceNumber
)
605 moveCommand( &activeList
, &abortList
, scsiCmd
);
617 void IOSCSIParallelDevice::abortAllCommands( SCSICommandType cmdType
)
619 IOSCSIParallelDevice
*abortDev
;
621 abortCmdPending
= cmdType
;
623 if ( abortCmdPending
== kSCSICommandAbortAll
)
627 client
->message( kSCSIClientMsgDeviceAbort
, this );
630 else if ( abortCmdPending
== kSCSICommandDeviceReset
)
632 queue_iterate( &target
->deviceList
, abortDev
, IOSCSIParallelDevice
*, nextDevice
)
634 if ( abortDev
->client
!= 0 )
636 abortDev
->client
->message( kSCSIClientMsgDeviceReset
, abortDev
);
649 void IOSCSIParallelDevice::resetOccurred( SCSIClientMessage clientMsg
)
651 if ( client
!= 0 && clientMsg
!= kSCSIClientMsgNone
)
653 client
->message( clientMsg
, this );
656 moveAllCommands( &activeList
, &cancelList
, kIOReturnAborted
);
657 moveAllCommands( &abortList
, &cancelList
, kIOReturnAborted
);
659 abortState
= kStateIdle
;
660 reqSenseState
= kStateIdle
;
661 commandLimit
= commandLimitSave
;
662 negotiateState
= kStateIdle
;
667 void IOSCSIParallelDevice::resetComplete()
671 client
->message( kSCSIClientMsgBusReset
| kSCSIClientMsgDone
, this );
681 bool IOSCSIParallelDevice::checkAbortQueue()
683 IOSCSIParallelCommand
*origCmd
;
685 if ( abortState
== kStateActive
)
690 if ( abortCmdPending
!= kSCSICommandNone
)
692 abortCmd
->origCommand
= 0;
694 abortCmd
->scsiCmd
.cdbTagMsg
= 0;
695 abortCmd
->scsiCmd
.cdbTag
= (UInt32
) -1;
698 abortCmd
->cmdType
= abortCmdPending
;
699 abortCmd
->scsiCmd
.cdbAbortMsg
= (abortCmdPending
== kSCSICommandAbortAll
)
700 ? kSCSIMsgAbort
: kSCSIMsgBusDeviceReset
;
702 if ( disableDisconnect
== true )
704 abortCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNoDisconnect
;
708 abortCmd
->scsiCmd
.cdbFlags
&= ~kCDBFlagsNoDisconnect
;
712 abortCmd
->timer
= ( abortCmd
->timeout
!= 0 ) ?
713 abortCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
715 bzero( &abortCmd
->results
, sizeof(SCSIResults
) );
717 abortCmdPending
= kSCSICommandNone
;
718 abortState
= kStateActive
;
720 addCommand( &activeList
, abortCmd
);
721 controller
->executeCommand( abortCmd
);
723 else if ( queue_empty( &abortList
) == false )
725 origCmd
= (IOSCSIParallelCommand
*)queue_first( &abortList
);
726 abortCmd
->origCommand
= origCmd
;
728 abortCmd
->cmdType
= kSCSICommandAbort
;
729 abortCmd
->scsiCmd
.cdbTagMsg
= origCmd
->scsiCmd
.cdbTagMsg
;
730 abortCmd
->scsiCmd
.cdbTag
= origCmd
->scsiCmd
.cdbTag
;
731 abortCmd
->scsiCmd
.cdbAbortMsg
= (abortCmd
->scsiCmd
.cdbTagMsg
!= 0)
732 ? kSCSIMsgAbortTag
: kSCSIMsgAbort
;
734 abortCmd
->timer
= ( abortCmd
->timeout
!= 0 ) ?
735 abortCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
737 bzero( &abortCmd
->results
, sizeof(SCSIResults
) );
739 abortState
= kStateActive
;
741 addCommand( &activeList
, abortCmd
);
742 controller
->executeCommand( abortCmd
);
757 void IOSCSIParallelDevice::checkCancelQueue()
759 if ( cancelState
!= kStateIdle
)
764 if ( queue_empty( &cancelList
) == true )
769 if ( controller
->controllerInfo
.disableCancelCommands
== true )
774 cancelCmd
->origCommand
= (IOSCSIParallelCommand
*)queue_first( &cancelList
);
775 bzero( &cancelCmd
->results
, sizeof(SCSIResults
) );
777 cancelState
= kStateActive
;
778 controller
->cancelCommand( cancelCmd
);
786 bool IOSCSIParallelDevice::checkReqSense()
788 IOMemoryDescriptor
*senseData
;
790 SCSITargetParms
*tpCur
;
792 if ( target
->reqSenseState
== kStateActive
)
797 if ( reqSenseState
== kStateIssue
)
799 reqSenseCmd
->origCommand
= reqSenseOrigCmd
;
800 bzero( &reqSenseCmd
->results
, sizeof(SCSIResults
) );
802 reqSenseOrigCmd
->getPointers( &senseData
, &senseLength
, 0, true );
803 reqSenseCmd
->setPointers( senseData
, senseLength
, false );
805 reqSenseCmd
->scsiCmd
.cdbFlags
= 0;
807 if ( disableDisconnect
== true )
809 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNoDisconnect
;
813 reqSenseCmd
->scsiCmd
.cdbFlags
&= ~kCDBFlagsNoDisconnect
;
816 tpCur
= &target
->targetParmsCurrent
;
818 if ( tpCur
->transferWidth
> 1 )
820 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateWDTR
;
821 if (tpCur
->transferOptions
& kSCSITransferOptionPPR
) {
822 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiatePPR
;
826 if ( tpCur
->transferOffset
!= 0 )
828 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateSDTR
;
829 if (tpCur
->transferOptions
& kSCSITransferOptionPPR
) {
830 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiatePPR
;
835 reqSenseCmd
->timer
= ( reqSenseCmd
->timeout
!= 0 ) ?
836 reqSenseCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
838 reqSenseCmd
->scsiCmd
.cdb
[3] = (senseLength
>> 8) & 0xff;
839 reqSenseCmd
->scsiCmd
.cdb
[4] = senseLength
& 0xff;
841 reqSenseState
= kStatePending
;
844 if ( reqSenseState
== kStatePending
)
846 target
->reqSenseState
= reqSenseState
= kStateActive
;
848 addCommand( &activeList
, reqSenseCmd
);
851 controller
->commandCount
++;
853 controller
->executeCommand( reqSenseCmd
);
856 return (target
->reqSenseCount
> 0);
865 bool IOSCSIParallelDevice::checkDeviceQueue( UInt32
*dispatchAction
)
867 IOSCSIParallelCommand
*scsiCmd
= 0;
875 if ( controller
->commandCount
>= controller
->commandLimit
)
877 *dispatchAction
= kDispatchStop
;
881 if ( target
->commandCount
>= target
->commandLimit
)
883 *dispatchAction
= kDispatchNextTarget
;
887 *dispatchAction
= kDispatchNextLun
;
889 if ( commandCount
>= commandLimit
)
894 for ( i
=0; i
< 2; i
++ )
896 queueHeld
= (i
== 0) ? bypassQHeld
: normalQHeld
;
897 queue
= (i
== 0) ? &bypassList
: &deviceList
;
899 if ( queueHeld
== true )
904 scsiCmd
= checkCommand( queue
);
907 *dispatchAction
= kDispatchNextCommand
;
918 if ( disableDisconnect
== true || (scsiCmd
->scsiCmd
.cdbFlags
& kCDBFNoDisconnect
) )
920 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNoDisconnect
;
922 if ( controller
->commandCount
!= 0 )
924 *dispatchAction
= kDispatchNextLun
;
928 controller
->noDisconnectCmd
= scsiCmd
;
929 controller
->commandLimitSave
= controller
->commandLimit
;
930 controller
->commandLimit
= 1;
933 else if ( checkTag( scsiCmd
) == false )
935 switch ( controller
->controllerInfo
.tagAllocationMethod
)
937 case kTagAllocationPerTarget
:
938 *dispatchAction
= kDispatchNextTarget
;
940 case kTagAllocationPerController
:
941 *dispatchAction
= kDispatchStop
;
943 case kTagAllocationPerLun
:
946 *dispatchAction
= kDispatchNextLun
;
953 checkNegotiate( scsiCmd
);
955 scsiCmd
->timer
= ( scsiCmd
->timeout
!= 0 ) ? scsiCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
958 target
->commandCount
++;
959 controller
->commandCount
++;
961 addCommand( &activeList
, scsiCmd
);
963 controller
->executeCommand( scsiCmd
);
975 void IOSCSIParallelDevice::rescheduleCommand( IOSCSIParallelCommand
*scsiCmd
)
977 if ( scsiCmd
->list
!= &activeList
)
979 IOLog( "IOSCSIParallelController::rescheduleCommand() - Command not active. Cmd = %08x\n\r", (int)scsiCmd
);
983 deleteCommand( &activeList
, scsiCmd
);
985 switch ( scsiCmd
->cmdType
)
987 case kSCSICommandExecute
:
988 if ( scsiCmd
->scsiCmd
.cdbTagMsg
!= 0 )
990 freeTag( scsiCmd
->scsiCmd
.cdbTag
);
991 scsiCmd
->scsiCmd
.cdbTag
= (UInt32
) -1;
994 stackCommand( &deviceList
, scsiCmd
);
996 if ( scsiCmd
->scsiCmd
.cdbFlags
& kCDBFlagsNoDisconnect
)
998 controller
->commandLimit
= controller
->commandLimitSave
;
999 controller
->noDisconnectCmd
= 0;
1002 controller
->commandCount
--;
1003 target
->commandCount
--;
1007 case kSCSICommandReqSense
:
1008 reqSenseState
= kStatePending
;
1009 target
->reqSenseState
= kStateIdle
;
1011 controller
->commandCount
--;
1014 case kSCSICommandAbortAll
:
1015 case kSCSICommandDeviceReset
:
1016 abortCmdPending
= scsiCmd
->cmdType
;
1018 case kSCSICommandAbort
:
1019 abortState
= kStateIdle
;
1035 bool IOSCSIParallelDevice::setTargetParms( SCSITargetParms
*targetParms
)
1037 IOSCSIParallelCommand
*scsiCmd
;
1038 SCSICDBInfo scsiCDB
;
1042 IOMemoryDescriptor
*senseDesc
;
1043 UInt8 senseBuffer
[14];
1046 if ( getWorkLoop()->inGate() == true )
1048 IOPanic( "IOSCSIParallelDevice:::setTargetParms() - must not be called from workloop!!\n\r");
1051 IOWriteLock( target
->clientSem
);
1052 IOWriteLock( target
->targetSem
);
1054 while ( target
->negotiateState
== kStateActive
)
1059 target
->targetParmsNew
= *targetParms
;
1061 if ( targetParms
->transferPeriodpS
< controller
->controllerInfo
.minTransferPeriodpS
)
1063 target
->targetParmsNew
.transferPeriodpS
= controller
->controllerInfo
.minTransferPeriodpS
;
1066 if ( target
->targetParmsNew
.transferPeriodpS
== 0
1067 || target
->targetParmsNew
.transferOffset
== 0
1068 || controller
->controllerInfo
.minTransferPeriodpS
== 0 )
1070 target
->targetParmsNew
.transferPeriodpS
= 0;
1071 target
->targetParmsNew
.transferOffset
= 0;
1074 target
->commandLimit
= 1;
1076 fTagEnable
= (targetParms
->enableTagQueuing
== true)
1077 && (controller
->controllerInfo
.tagAllocationMethod
!= kTagAllocationNone
)
1078 && (controller
->controllerInfo
.maxTags
!= 0);
1080 regObjCmdQueue
->setValue( (UInt32
)fTagEnable
);
1082 if ( fTagEnable
== true )
1084 target
->commandLimitSave
= controller
->controllerInfo
.maxCommandsPerTarget
;
1088 target
->commandLimitSave
= 1;
1089 target
->targetParmsNew
.enableTagQueuing
= false;
1092 scsiCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
1094 bzero( &scsiCDB
, sizeof( SCSICDBInfo
) );
1096 scsiCDB
.cdbLength
= 6;
1097 scsiCDB
.cdb
[0] = kSCSICmdTestUnitReady
;
1098 scsiCDB
.cdb
[1] = targetLun
.lun
<< 4;
1099 scsiCmd
->setCDB( &scsiCDB
);
1101 senseDesc
= IOMemoryDescriptor::withAddress(senseBuffer
, sizeof(senseBuffer
), kIODirectionIn
);
1102 if ( senseDesc
== 0 ) return false;
1103 scsiCmd
->setPointers( senseDesc
, sizeof(senseBuffer
), false, true );
1105 target
->negotiateState
= kStateIssue
;
1109 IOWriteLock( target
->targetSem
);
1110 IORWUnlock( target
->targetSem
);
1113 senseDesc
->release();
1115 rc
= (target
->negotiationResult
.returnCode
== kIOReturnSuccess
);
1117 IORWUnlock( target
->clientSem
);
1127 void IOSCSIParallelDevice::getTargetParms( SCSITargetParms
*targetParms
)
1129 *targetParms
= target
->targetParmsCurrent
;
1137 bool IOSCSIParallelDevice::setLunParms( SCSILunParms
*lunParms
)
1139 IOSCSIParallelCommand
*scsiCmd
;
1140 SCSICDBInfo scsiCDB
;
1142 IOMemoryDescriptor
*senseDesc
;
1143 UInt8 senseBuffer
[14];
1145 if ( getWorkLoop()->inGate() == true )
1147 IOPanic( "IOSCSIParallelDevice:::setLunParms() - must not be called from workloop!!\n\r");
1150 IOWriteLock( clientSem
);
1152 lunParmsNew
= *lunParms
;
1153 commandLimitSave
= commandLimit
;
1156 scsiCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
1158 bzero( &scsiCDB
, sizeof( SCSICDBInfo
) );
1160 scsiCDB
.cdbLength
= 6;
1161 scsiCDB
.cdb
[0] = kSCSICmdTestUnitReady
;
1162 scsiCDB
.cdb
[1] = targetLun
.lun
<< 4;
1163 scsiCmd
->setCDB( &scsiCDB
);
1165 senseDesc
= IOMemoryDescriptor::withAddress(senseBuffer
, sizeof(senseBuffer
), kIODirectionIn
);
1166 if ( senseDesc
== 0 ) return false;
1167 scsiCmd
->setPointers( senseDesc
, sizeof(senseBuffer
), false, true );
1169 negotiateState
= kStateIssue
;
1174 senseDesc
->release();
1176 while ( negotiateState
!= kStateIdle
)
1181 IORWUnlock( clientSem
);
1191 void IOSCSIParallelDevice::getLunParms( SCSILunParms
*lunParms
)
1193 lunParms
->disableDisconnect
= disableDisconnect
;
1201 void IOSCSIParallelDevice::checkNegotiate( IOSCSIParallelCommand
*scsiCmd
)
1203 SCSITargetParms
*tpCur
, *tpNew
;
1205 if ( target
->negotiateState
== kStateIssue
)
1207 if ( target
->commandCount
== 0 )
1209 target
->negotiateState
= kStateActive
;
1211 tpNew
= &target
->targetParmsNew
;
1212 tpCur
= &target
->targetParmsCurrent
;
1214 target
->negotiationResult
.returnCode
= kIOReturnError
;
1216 if ((tpCur
->transferPeriodpS
!= tpNew
->transferPeriodpS
) ||
1217 (tpCur
->transferOffset
!= tpNew
->transferOffset
) ||
1218 ((tpCur
->transferOptions
^ tpNew
->transferOptions
) & kSCSITransferOptionsSCSI3
) )
1220 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateSDTR
;
1222 if (tpNew
->transferOptions
& kSCSITransferOptionPPR
) {
1223 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiatePPR
;
1227 if ( tpCur
->transferWidth
!= tpNew
->transferWidth
)
1229 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateWDTR
;
1232 if ( tpCur
->enableTagQueuing
!= tpNew
->enableTagQueuing
)
1234 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsEnableTagQueuing
;
1237 if ( (scsiCmd
->scsiCmd
.cdbFlags
&
1238 (kCDBFlagsNegotiateSDTR
|
1239 kCDBFlagsNegotiateWDTR
|
1240 kCDBFlagsNegotiatePPR
|
1241 kCDBFlagsEnableTagQueuing
)) == 0 )
1243 IORWUnlock( target
->targetSem
);
1244 target
->negotiateState
= kStateIdle
;
1245 target
->commandLimit
= target
->commandLimitSave
;
1252 if ( negotiateState
== kStateIssue
)
1254 if ( commandCount
== 0 )
1256 disableDisconnect
= lunParmsNew
.disableDisconnect
;
1257 negotiateState
= kStateIdle
;
1267 void IOSCSIParallelDevice::negotiationComplete()
1269 SCSITargetParms
*tpCur
, *tpNew
;
1271 tpNew
= &target
->targetParmsNew
;
1272 tpCur
= &target
->targetParmsCurrent
;
1274 if ( target
->negotiationResult
.returnCode
== kIOReturnSuccess
)
1276 tpCur
->transferPeriodpS
= tpNew
->transferPeriodpS
= target
->negotiationResult
.transferPeriodpS
;
1277 tpCur
->transferOffset
= tpNew
->transferOffset
= target
->negotiationResult
.transferOffset
;
1278 tpCur
->transferWidth
= tpNew
->transferWidth
= target
->negotiationResult
.transferWidth
;
1279 tpCur
->transferOptions
= tpNew
->transferOptions
= target
->negotiationResult
.transferOptions
;
1281 target
->commandLimit
= target
->commandLimitSave
;
1285 tpNew
->transferPeriodpS
= 0;
1286 tpNew
->transferOffset
= 0;
1287 tpNew
->transferWidth
= 1;
1290 target
->regObjTransferPeriod
->setValue( tpNew
->transferPeriodpS
);
1291 target
->regObjTransferOffset
->setValue( tpNew
->transferOffset
);
1292 target
->regObjTransferWidth
->setValue( tpNew
->transferWidth
);
1293 target
->regObjTransferOptions
->setValue( tpNew
->transferOptions
);
1295 target
->negotiateState
= kStateIdle
;
1303 bool IOSCSIParallelDevice::checkTag( IOSCSIParallelCommand
*scsiCmd
)
1305 SCSICDBInfo scsiCDB
;
1308 scsiCmd
->getCDB( &scsiCDB
);
1310 scsiCDB
.cdbTagMsg
= 0;
1311 scsiCDB
.cdbTag
= (UInt32
)-1;
1315 if ( scsiCmd
->device
->target
->targetParmsCurrent
.enableTagQueuing
== false )
1320 /* If the command is untagged, then don't allocate a tag nor
1321 * send the untagged command as a simple-tagged command.
1323 if ( scsiCDB
.cdbTagMsg
== 0 )
1328 if ( allocTag( &scsiCDB
.cdbTag
) == false )
1336 scsiCmd
->setCDB( &scsiCDB
);
1346 bool IOSCSIParallelDevice::allocTag( UInt32
*tagId
)
1353 switch ( controller
->controllerInfo
.tagAllocationMethod
)
1355 case kTagAllocationPerLun
:
1358 case kTagAllocationPerTarget
:
1359 tags
= target
->tagArray
;
1361 case kTagAllocationPerController
:
1362 tags
= controller
->tagArray
;
1368 if ( tags
== 0 ) return false;
1370 for ( i
= 0; i
< controller
->controllerInfo
.maxTags
; i
++ )
1373 tagMask
= 1 << (i
% 32);
1374 if ( !(tags
[tagIndex
] & tagMask
) )
1376 tags
[tagIndex
] |= tagMask
;
1389 void IOSCSIParallelDevice::freeTag( UInt32 tagId
)
1393 switch ( controller
->controllerInfo
.tagAllocationMethod
)
1395 case kTagAllocationPerLun
:
1398 case kTagAllocationPerTarget
:
1399 tags
= target
->tagArray
;
1401 case kTagAllocationPerController
:
1402 tags
= controller
->tagArray
;
1408 if ( tags
== 0 ) return;
1410 tags
[tagId
/32] &= ~(1 << (tagId
% 32));
1418 IOSCSIParallelCommand
*IOSCSIParallelDevice::findCommandWithNexus( UInt32 tagValue
)
1420 IOSCSIParallelCommand
*scsiCmd
;
1422 queue_iterate( &activeList
, scsiCmd
, IOSCSIParallelCommand
*, nextCommand
)
1424 switch ( scsiCmd
->cmdType
)
1426 case kSCSICommandExecute
:
1427 case kSCSICommandReqSense
:
1428 if ( scsiCmd
->scsiCmd
.cdbTag
== tagValue
)
1438 queue_iterate( &abortList
, scsiCmd
, IOSCSIParallelCommand
*, nextCommand
)
1440 switch ( scsiCmd
->cmdType
)
1442 case kSCSICommandExecute
:
1443 case kSCSICommandReqSense
:
1444 if ( scsiCmd
->scsiCmd
.cdbTag
== tagValue
)
1462 void IOSCSIParallelDevice::timer()
1464 IOSCSIParallelCommand
*scsiCmd
, *tmp
= 0;
1465 SCSITargetLun scsiTargetLun
;
1467 queue_iterate( &activeList
, scsiCmd
, IOSCSIParallelCommand
*, nextCommand
)
1469 tmp
= (IOSCSIParallelCommand
*)queue_prev( &scsiCmd
->nextCommand
);
1471 if ( scsiCmd
->timer
)
1473 if ( !--scsiCmd
->timer
)
1475 scsiCmd
->getTargetLun( &scsiTargetLun
);
1476 IOLog("Timeout: T/L = %d:%d Cmd = %08x Cmd Type = %d\n\r",
1477 scsiTargetLun
.target
, scsiTargetLun
.lun
, (int)scsiCmd
, scsiCmd
->cmdType
);
1479 switch ( scsiCmd
->cmdType
)
1481 case kSCSICommandExecute
:
1482 moveCommand( &activeList
, &abortList
, scsiCmd
, kIOReturnTimeout
);
1486 case kSCSICommandReqSense
:
1487 reqSenseState
= kStateIdle
;
1488 moveCommand( &activeList
, &abortList
, scsiCmd
, kIOReturnTimeout
);
1492 case kSCSICommandAbort
:
1493 case kSCSICommandAbortAll
:
1494 case kSCSICommandDeviceReset
:
1495 controller
->busResetState
= kStateIssue
;
1506 if ( queue_end( &activeList
, (queue_head_t
*)scsiCmd
) == true )
1518 void IOSCSIParallelDevice::dispatchRequest()
1520 target
->state
= kStateActive
;
1521 controller
->dispatchRequest();
1529 bool IOSCSIParallelDevice::dispatch( UInt32
*dispatchAction
)
1535 if ( controller
->checkBusReset() == true )
1537 *dispatchAction
= kDispatchStop
;
1541 if ( (rc
= controller
->commandDisable
) == true )
1543 *dispatchAction
= kDispatchNextTarget
;
1547 if ( checkAbortQueue() == true )
1549 *dispatchAction
= kDispatchNextTarget
;
1555 if ( (rc
= controller
->commandDisable
) == true )
1557 *dispatchAction
= kDispatchStop
;
1561 if ( (rc
= checkReqSense()) == true )
1563 *dispatchAction
= kDispatchNextTarget
;
1567 rc
= checkDeviceQueue( dispatchAction
);
1569 } while ( *dispatchAction
== kDispatchNextCommand
);
1580 void IOSCSIParallelDevice::completeCommand( IOSCSIParallelCommand
*scsiCmd
)
1582 SCSICommandType cmdType
;
1584 cmdType
= scsiCmd
->cmdType
;
1587 case kSCSICommandExecute
:
1588 executeCommandDone( scsiCmd
);
1591 case kSCSICommandReqSense
:
1592 executeReqSenseDone( scsiCmd
);
1595 case kSCSICommandAbort
:
1596 case kSCSICommandAbortAll
:
1597 case kSCSICommandDeviceReset
:
1598 abortCommandDone( scsiCmd
);
1601 case kSCSICommandCancel
:
1602 cancelCommandDone( scsiCmd
);
1619 void IOSCSIParallelDevice::checkIdleNotify()
1621 if ( idleNotifyActive
== false )
1626 if ( (queue_empty( &activeList
) == true)
1627 && (queue_empty( &abortList
) == true)
1628 && (queue_empty( &cancelList
) == true)
1629 && (target
->reqSenseCount
== 0) )
1631 idleNotifyActive
= false;
1632 (idleNotifyCallback
)( idleNotifyTarget
, idleNotifyRefcon
);
1641 void IOSCSIParallelDevice::flushQueue( UInt32 queueType
, IOReturn rc
)
1643 queue_head_t
*queue
;
1645 queue
= (queueType
== kQTypeBypassQ
) ? &bypassList
: &deviceList
;
1646 purgeAllCommands( queue
, rc
);
1654 void IOSCSIParallelDevice::executeCommandDone( IOSCSIParallelCommand
*scsiCmd
)
1656 deleteCommand( scsiCmd
->list
, scsiCmd
);
1659 controller
->commandCount
--;
1660 target
->commandCount
--;
1662 if ( scsiCmd
->scsiCmd
.cdbTagMsg
!= 0 )
1664 freeTag( scsiCmd
->scsiCmd
.cdbTag
);
1665 scsiCmd
->scsiCmd
.cdbTag
= (UInt32
) -1;
1668 if ( scsiCmd
->scsiCmd
.cdbFlags
& (kCDBFlagsNegotiateSDTR
|
1669 kCDBFlagsNegotiateWDTR
|
1670 kCDBFlagsNegotiatePPR
|
1671 kCDBFlagsEnableTagQueuing
) )
1673 if ( scsiCmd
->scsiCmd
.cdbFlags
& (kCDBFlagsNegotiateSDTR
|
1674 kCDBFlagsNegotiateWDTR
|
1675 kCDBFlagsNegotiatePPR
) )
1677 negotiationComplete();
1681 target
->negotiationResult
.returnCode
= kIOReturnSuccess
;
1684 IORWUnlock( target
->targetSem
);
1687 if ( scsiCmd
->scsiCmd
.cdbFlags
& kCDBFlagsNoDisconnect
)
1689 controller
->commandLimit
= controller
->commandLimitSave
;
1690 controller
->noDisconnectCmd
= 0;
1693 if ( scsiCmd
->results
.scsiStatus
== kSCSIStatusCheckCondition
1694 && scsiCmd
->results
.requestSenseDone
== false
1695 && scsiCmd
->senseData
!= 0 )
1697 reqSenseOrigCmd
= scsiCmd
;
1698 reqSenseState
= kStateIssue
;
1699 target
->reqSenseCount
++;
1703 if ( scsiCmd
->results
.scsiStatus
== kSCSIStatusQueueFull
)
1705 if ( commandCount
> 4 )
1707 // IOLog( "IOSCSI: Q-full - commandCount = %d commandLimit = %d\n\r", commandCount, commandLimit );
1708 commandLimit
= commandCount
;
1711 stackCommand( &deviceList
, scsiCmd
);
1715 finishCommand( scsiCmd
);
1723 void IOSCSIParallelDevice::executeReqSenseDone( IOSCSIParallelCommand
*scsiCmd
)
1725 IOSCSIParallelCommand
*origCommand
;
1727 deleteCommand( scsiCmd
->list
, scsiCmd
);
1729 target
->reqSenseState
= reqSenseState
= kStateIdle
;
1730 target
->reqSenseCount
--;
1733 controller
->commandCount
--;
1735 reqSenseOrigCmd
= 0;
1737 origCommand
= scsiCmd
->origCommand
;
1739 if ( (scsiCmd
->results
.returnCode
== kIOReturnSuccess
) || (scsiCmd
->results
.returnCode
== kIOReturnUnderrun
) )
1741 origCommand
->results
.requestSenseDone
= true;
1742 origCommand
->results
.requestSenseLength
= scsiCmd
->results
.bytesTransferred
;
1746 origCommand
->results
.requestSenseDone
= false;
1747 origCommand
->results
.requestSenseLength
= 0;
1750 finishCommand( scsiCmd
->origCommand
);
1758 void IOSCSIParallelDevice::abortCommandDone( IOSCSIParallelCommand
*scsiCmd
)
1760 IOSCSIParallelCommand
*origSCSICmd
;
1761 IOSCSIParallelDevice
*abortDev
;
1763 deleteCommand( scsiCmd
->list
, scsiCmd
);
1765 abortState
= kStateIdle
;
1767 if ( scsiCmd
->cmdType
== kSCSICommandAbortAll
)
1769 moveAllCommands( &activeList
, &cancelList
, kIOReturnAborted
);
1770 moveAllCommands( &abortList
, &cancelList
, kIOReturnAborted
);
1774 client
->message( kSCSIClientMsgDeviceAbort
| kSCSIClientMsgDone
, this );
1777 if ( scsiCmd
->cmdType
== kSCSICommandDeviceReset
)
1779 target
->commandLimit
= target
->commandLimitSave
;
1780 target
->reqSenseCount
= 0;
1781 target
->reqSenseState
= kStateIdle
;
1782 target
->negotiateState
= kStateIssue
;
1784 target
->targetParmsCurrent
.transferPeriodpS
= 0;
1785 target
->targetParmsCurrent
.transferOffset
= 0;
1786 target
->targetParmsCurrent
.transferWidth
= 1;
1788 queue_iterate( &target
->deviceList
, abortDev
, IOSCSIParallelDevice
*, nextDevice
)
1790 abortDev
->resetOccurred( (SCSIClientMessage
)(kSCSIClientMsgDeviceReset
| kSCSIClientMsgDone
) );
1793 else if ( scsiCmd
->cmdType
== kSCSICommandAbort
)
1795 origSCSICmd
= scsiCmd
->origCommand
;
1797 if ( findCommand( &abortList
, origSCSICmd
) == true )
1799 moveCommand( &abortList
, &cancelList
, origSCSICmd
, kIOReturnAborted
);
1811 void IOSCSIParallelDevice::cancelCommandDone( IOSCSIParallelCommand
*scsiCmd
)
1813 IOSCSIParallelCommand
*origSCSICmd
;
1815 cancelState
= kStateIdle
;
1817 origSCSICmd
= scsiCmd
->origCommand
;
1819 if ( findCommand( &cancelList
, origSCSICmd
) == true )
1821 IOLog( "IOSCSIParallelDevice::cancelCommandDone - Cancelled command not completed - scsiCmd = %08x\n\r", (int)origSCSICmd
);
1822 deleteCommand( &cancelList
, origSCSICmd
);
1831 void IOSCSIParallelDevice::finishCommand( IOSCSIParallelCommand
*scsiCmd
)
1833 if ( scsiCmd
->completionInfo
.async
.callback
)
1835 (*scsiCmd
->completionInfo
.async
.callback
)( scsiCmd
->completionInfo
.async
.target
,
1836 scsiCmd
->completionInfo
.async
.refcon
);
1840 scsiCmd
->completionInfo
.sync
.lock
->signal();
1849 OSDictionary
*IOSCSIParallelDevice::createProperties()
1851 OSDictionary
*propTable
= 0;
1857 propTable
= OSDictionary::withCapacity(kSCSIMaxProperties
);
1858 if ( propTable
== NULL
)
1863 regObj
= (OSObject
*)OSNumber::withNumber(targetLun
.target
,32);
1864 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTarget
) != true )
1866 goto createprop_error
;
1869 regObj
= (OSObject
*)OSNumber::withNumber(targetLun
.target
,32);
1870 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyIOUnit
) != true )
1872 goto createprop_error
;
1875 sprintf(unit
,"%x",targetLun
.target
);
1878 regObj
= (OSObject
*)OSNumber::withNumber(targetLun
.lun
,32);
1879 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyLun
) != true )
1881 goto createprop_error
;
1886 stripBlanks( d
, (char *)inquiryData
->vendorName
, sizeof(inquiryData
->vendorName
) );
1887 regObj
= (OSObject
*)OSString::withCString( d
);
1888 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyVendorName
) != true )
1890 goto createprop_error
;
1893 stripBlanks( d
, (char *)inquiryData
->productName
, sizeof(inquiryData
->productName
) );
1894 regObj
= (OSObject
*)OSString::withCString( d
);
1895 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyProductName
) != true )
1897 goto createprop_error
;
1900 stripBlanks( d
, (char *)inquiryData
->productRevision
, sizeof(inquiryData
->productRevision
) );
1901 regObj
= (OSObject
*)OSString::withCString( d
);
1902 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyProductRevision
) != true )
1904 goto createprop_error
;
1907 regObj
= (OSObject
*)OSBoolean::withBoolean( (inquiryData
->devTypeMod
& kSCSIDevTypeModRemovable
) != 0 );
1908 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyRemovableMedia
) != true )
1910 goto createprop_error
;
1913 regObj
= (OSObject
*)OSNumber::withNumber( inquiryData
->devType
& kSCSIDevTypeMask
, 32 );
1914 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyDeviceTypeID
) != true )
1916 goto createprop_error
;
1919 regObj
= (OSObject
*)target
->regObjTransferPeriod
;
1920 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferPeriod
, false ) != true )
1922 goto createprop_error
;
1924 regObjTransferPeriod
= (OSNumber
*)regObj
;
1926 regObj
= (OSObject
*)target
->regObjTransferOffset
;
1927 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferOffset
, false ) != true )
1929 goto createprop_error
;
1931 regObjTransferOffset
= (OSNumber
*)regObj
;
1934 regObj
= (OSObject
*)target
->regObjTransferWidth
;
1935 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferWidth
, false ) != true )
1937 goto createprop_error
;
1939 regObjTransferWidth
= (OSNumber
*)regObj
;
1941 regObj
= (OSObject
*)target
->regObjTransferOptions
;
1942 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferOptions
, false ) != true )
1944 goto createprop_error
;
1946 regObjTransferOptions
= (OSNumber
*)regObj
;
1948 regObj
= (OSObject
*)target
->regObjCmdQueue
;
1949 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyCmdQueue
, false ) != true )
1951 goto createprop_error
;
1953 regObjCmdQueue
= (OSNumber
*)regObj
;
1958 propTable
->release();
1967 bool IOSCSIParallelDevice::addToRegistry( OSDictionary
*propTable
, OSObject
*regObj
, char *key
,
1968 bool doRelease
= true )
1972 if ( regObj
== NULL
)
1977 rc
= propTable
->setObject( key
, regObj
);
1981 // If 'doRelease' is true, then a reference count is consumed.
1994 bool IOSCSIParallelDevice::matchPropertyTable(OSDictionary
* table
)
1998 match
= compareProperty( table
, kSCSIPropertyIOUnit
) &&
1999 compareProperty( table
, kSCSIPropertyDeviceTypeID
) &&
2000 compareProperty( table
, kSCSIPropertyRemovableMedia
) &&
2001 compareProperty( table
, kSCSIPropertyVendorName
) &&
2002 compareProperty( table
, kSCSIPropertyProductName
) &&
2003 compareProperty( table
, kSCSIPropertyProductRevision
);
2005 if ( match
== true )
2007 match
= super::matchPropertyTable(table
);
2019 IOService
*IOSCSIParallelDevice::matchLocation(IOService
* client
)
2030 void IOSCSIParallelDevice::stripBlanks( char *d
, char *s
, UInt32 l
)
2034 for ( p
= d
, c
= *s
; l
&& c
; l
--)
2050 IOSCSICommand
*IOSCSIParallelDevice::allocCommand( IOSCSIDevice
*, UInt32 clientDataSize
)
2053 return (IOSCSICommand
*) allocCommand( kIOSCSIParallelDevice
, clientDataSize
);
2056 IOSCSIParallelCommand
*IOSCSIParallelDevice::allocCommand( IOSCSIParallelDevice
*, UInt32 clientDataSize
)
2058 IOSCSIParallelCommand
*cmd
;
2060 if ( (cmd
= controller
->allocCommand( clientDataSize
)) )
2067 IOCDBCommand
*IOSCSIParallelDevice::allocCommand( IOCDBDevice
*, UInt32 clientDataSize
)
2069 return (IOCDBCommand
*) allocCommand( kIOSCSIDevice
, clientDataSize
);
2077 IOWorkLoop
*IOSCSIParallelDevice::getWorkLoop() const
2079 return controller
->workLoop
;
2088 bool IOSCSIParallelDevice::open( IOService
*forClient
, IOOptionBits options
, void *arg
)
2090 if ( client
!= 0 ) return false;
2094 return super::open( forClient
, options
, arg
);
2102 void IOSCSIParallelDevice::close( IOService
*forClient
, IOOptionBits options
)
2106 return super::close( forClient
, options
);
2114 IOReturn
IOSCSIParallelDevice::message( UInt32 forMsg
, IOService
*forProvider
, void *forArg
)
2116 IOReturn rc
= kIOReturnSuccess
;
2117 SCSIClientMessage clientMsg
;
2119 clientMsg
= (SCSIClientMessage
) forMsg
;
2121 // IOLog( "IOSCSIParallelDevice::message() - clientMsg = %08x\n\r", clientMsg );
2125 case kSCSIClientMsgBusReset
:
2126 holdQueue( kQTypeNormalQ
);
2128 case kSCSIClientMsgBusReset
| kSCSIClientMsgDone
:
2129 releaseQueue( kQTypeNormalQ
);
2132 rc
= super::message( clientMsg
, forProvider
, forArg
);
2143 void IOSCSIParallelDevice::free()
2145 if ( deviceGate
!= 0 )
2147 controller
->workLoop
->removeEventSource( deviceGate
);
2148 deviceGate
->release();
2151 if ( reqSenseCmd
!= 0 ) reqSenseCmd
->release();
2152 if ( abortCmd
!= 0 ) abortCmd
->release();
2153 if ( cancelCmd
!= 0 ) cancelCmd
->release();
2154 if ( probeCmd
!= 0 ) probeCmd
->release();
2156 if ( tagArray
!= 0 ) IOFree( tagArray
, controller
->tagArraySize
);
2157 if ( inquiryData
!= 0 ) IOFree( inquiryData
, inquiryDataSize
);
2158 if ( devicePrivateData
!= 0 ) IOFreeContiguous( devicePrivateData
, controller
->controllerInfo
.lunPrivateDataSize
);
2159 if ( clientSem
!= 0 ) IORWLockFree( clientSem
);