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>
33 #define super IOSCSIDevice
36 #define MIN(a,b) ((a <= b) ? a : b)
39 OSDefineMetaClassAndAbstractStructors( IOCDBDevice
, IOService
)
40 OSDefineMetaClassAndAbstractStructors( IOSCSIDevice
, IOCDBDevice
)
41 OSDefineMetaClassAndStructors( IOSCSIParallelDevice
, IOSCSIDevice
)
48 bool IOSCSIParallelDevice::init( IOSCSIParallelController
*forController
, SCSITargetLun forTargetLun
)
52 controller
= forController
;
53 targetLun
= forTargetLun
;
55 target
= &controller
->targets
[targetLun
.target
];
57 queue_init( &deviceList
);
58 queue_init( &bypassList
);
59 queue_init( &activeList
);
60 queue_init( &abortList
);
61 queue_init( &cancelList
);
63 clientSem
= IORWLockAlloc();
69 if ( super::init() == false )
74 if ( controller
->controllerInfo
.lunPrivateDataSize
!= 0 )
76 devicePrivateData
= IOMallocContiguous( controller
->controllerInfo
.lunPrivateDataSize
, 16, 0 );
77 if ( devicePrivateData
== 0 )
83 bzero( &scsiCDB
, sizeof(scsiCDB
) );
85 abortCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
90 abortCmd
->setTimeout( kSCSIAbortTimeoutmS
);
92 cancelCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
97 cancelCmd
->setTimeout( 0 );
98 cancelCmd
->cmdType
= kSCSICommandCancel
;
100 reqSenseCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
101 if ( reqSenseCmd
== 0 )
105 scsiCDB
.cdbLength
= 6;
106 scsiCDB
.cdb
[0] = kSCSICmdRequestSense
;
107 scsiCDB
.cdb
[1] = targetLun
.lun
<< 4;
108 scsiCDB
.cdbTag
= (UInt32
) -1;
110 reqSenseCmd
->setTimeout( kSCSIReqSenseTimeoutmS
);
111 reqSenseCmd
->cmdType
= kSCSICommandReqSense
;
112 reqSenseCmd
->setCDB( &scsiCDB
);
114 if ( controller
->controllerInfo
.tagAllocationMethod
== kTagAllocationPerLun
)
116 tagArray
= (UInt32
*)IOMalloc( controller
->tagArraySize
);
117 bzero( tagArray
, controller
->tagArraySize
);
120 deviceGate
= IOCommandGate::commandGate( this, (IOCommandGate::Action
) &IOSCSIParallelDevice::receiveCommand
);
121 if ( deviceGate
== 0 )
126 if ( controller
->workLoop
->addEventSource( deviceGate
) != kIOReturnSuccess
)
131 commandLimitSave
= commandLimit
= controller
->controllerInfo
.maxCommandsPerLun
;
133 idleNotifyActive
= false;
146 IOReturn
IOSCSIParallelDevice::probeTargetLun()
151 IOMemoryDescriptor
*desc
= 0;
152 SCSIInquiry
*inqData
= 0;
154 OSDictionary
*propTable
;
156 probeCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
160 rc
= kIOReturnNoMemory
;
164 size
= kDefaultInquirySize
;
166 if ( !(inqData
= (SCSIInquiry
*)IOMalloc(size
)) )
168 rc
= kIOReturnNoMemory
;
172 desc
= IOMemoryDescriptor::withAddress( (void *)inqData
, size
, kIODirectionIn
);
175 rc
= kIOReturnNoMemory
;
179 if ( open( this ) == false )
185 bzero( (void *)&cdb
, sizeof(cdb
) );
188 cdb
.cdb
[0] = kSCSICmdInquiry
;
190 probeCmd
->setCDB( &cdb
);
192 probeCmd
->setPointers( desc
, size
, false );
194 probeCmd
->setTimeout( kSCSIProbeTimeoutmS
);
195 probeCmd
->setCallback();
199 rc
= probeCmd
->getResults( &result
);
203 case kIOReturnSuccess
:
206 case kIOReturnUnderrun
:
207 rc
= kIOReturnSuccess
;
214 if ( result
.bytesTransferred
<= (UInt32
)(&inqData
->flags
- &inqData
->devType
) )
216 rc
= kIOReturnDeviceError
;
220 switch ( inqData
->devType
& kSCSIDevTypeQualifierMask
)
222 case kSCSIDevTypeQualifierConnected
:
223 case kSCSIDevTypeQualifierNotConnected
:
225 case kSCSIDevTypeQualifierReserved
:
226 case kSCSIDevTypeQualifierMissing
:
227 rc
= kIOReturnNotAttached
;
233 if ( rc
!= kIOReturnSuccess
)
238 inquiryData
= inqData
;
239 inquiryDataSize
= result
.bytesTransferred
;
241 propTable
= createProperties();
242 if ( !propTable
) goto probeError
;
244 setPropertyTable( propTable
);
246 propTable
->release();
257 if ( rc
!= kIOReturnSuccess
)
259 IOFree( inqData
, size
);
271 void IOSCSIParallelDevice::setupTarget()
273 SCSITargetParms targetParms
;
274 UInt32 transferWidth
;
276 if ( targetLun
.lun
!= 0 )
282 getTargetParms( &targetParms
);
284 if ( ((inquiryData
->flags
& kSCSIDevCapCmdQue
) != 0) && (checkCmdQueEnabled() == true) )
286 targetParms
.enableTagQueuing
= true;
289 if ( inquiryData
->flags
& kSCSIDevCapSync
)
291 targetParms
.transferPeriodpS
= controller
->controllerInfo
.minTransferPeriodpS
;
292 targetParms
.transferOffset
= controller
->controllerInfo
.maxTransferOffset
;
295 if ( inquiryData
->flags
& kSCSIDevCapWBus32
)
299 else if ( inquiryData
->flags
& kSCSIDevCapWBus16
)
308 targetParms
.transferWidth
= MIN( transferWidth
, controller
->controllerInfo
.maxTransferWidth
);
310 if ( ((inquiryData
->version
& 0x07) >= kSCSIInqVersionSCSI3
)
311 && (inquiryDataSize
> (UInt32
)(&inquiryData
->scsi3Options
- &inquiryData
->devType
)) )
313 if ( inquiryData
->scsi3Options
& kSCSI3InqOptionClockDT
)
315 targetParms
.transferOptions
|= kSCSITransferOptionClockDT
;
317 /* If it's a SCSI-3 target that handles DT clocking,
318 * assume the HBA can try using the PPR message.
320 targetParms
.transferOptions
|= kSCSITransferOptionPPR
;
322 if ( inquiryData
->scsi3Options
& kSCSI3InqOptionIUS
)
324 targetParms
.transferOptions
|= kSCSITransferOptionIUS
;
326 if ( inquiryData
->scsi3Options
& kSCSI3InqOptionQAS
)
328 targetParms
.transferOptions
|= kSCSITransferOptionQAS
;
334 setTargetParms( &targetParms
);
344 bool IOSCSIParallelDevice::checkCmdQueEnabled()
347 SCSIResults scsiResult
;
348 IOMemoryDescriptor
*desc
;
350 UInt8 controlModePage
[32];
354 bzero( (void *)&scsiCDB
, sizeof(scsiCDB
) );
356 size
= sizeof(controlModePage
);
358 scsiCDB
.cdbLength
= 6;
359 scsiCDB
.cdb
[0] = kSCSICmdModeSense6
;
360 scsiCDB
.cdb
[1] = 0x08;
361 scsiCDB
.cdb
[2] = 0x0a; // Control Mode Page
362 scsiCDB
.cdb
[4] = size
;
364 probeCmd
->setCDB( &scsiCDB
);
366 desc
= IOMemoryDescriptor::withAddress( (void *)controlModePage
, size
, kIODirectionIn
);
372 probeCmd
->setPointers( desc
, size
, false );
374 probeCmd
->setTimeout( kSCSIProbeTimeoutmS
);
375 probeCmd
->setCallback();
379 cmdRc
= probeCmd
->getResults( &scsiResult
);
381 if ( (cmdRc
== kIOReturnUnderrun
) && (scsiResult
.bytesTransferred
> 7) )
383 cmdRc
= kIOReturnSuccess
;
386 /* Check DQue bit on ControlMode Page (0x0A) */
387 if ( (cmdRc
== kIOReturnSuccess
) && ((controlModePage
[7] & 0x01) == 0) )
402 void IOSCSIParallelDevice::getInquiryData( void *clientBuf
, UInt32 clientBufSize
, UInt32
*clientDataSize
)
406 bzero( clientBuf
, clientBufSize
);
408 len
= MIN( clientBufSize
, inquiryDataSize
);
410 bcopy( inquiryData
, clientBuf
, len
);
412 *clientDataSize
= len
;
420 void IOSCSIParallelDevice::abort()
422 submitCommand( kSCSICommandAbortAll
, 0 );
430 void IOSCSIParallelDevice::reset()
432 submitCommand( kSCSICommandDeviceReset
, 0 );
440 void IOSCSIParallelDevice::holdQueue( UInt32 queueType
)
442 if ( getWorkLoop()->inGate() == false )
444 IOPanic( "IOSCSIParallelDevice::holdQueue() - must be called from workloop!!\n\r");
447 if ( queueType
== kQTypeBypassQ
)
451 else if ( queueType
== kQTypeNormalQ
)
462 void IOSCSIParallelDevice::releaseQueue( UInt32 queueType
)
464 if ( getWorkLoop()->inGate() == false )
466 IOPanic( "IOSCSIParallelDevice::releaseQueue() - must be called from workloop!!\n\r");
469 if ( queueType
== kQTypeBypassQ
)
473 else if ( queueType
== kQTypeNormalQ
)
486 void IOSCSIParallelDevice::notifyIdle( void *target
= 0, CallbackFn callback
= 0, void *refcon
= 0 )
488 if ( getWorkLoop()->inGate() == false )
490 IOPanic( "IOSCSIParallelDevice:::notifyIdle() - must be called from workloop!!\n\r");
495 idleNotifyActive
= false;
499 if ( idleNotifyActive
== true )
501 IOPanic( "IOSCSIParallelDevice:::notifyIdle() - only one idle notify may be active\n\r");
504 idleNotifyActive
= true;
505 idleNotifyTarget
= target
;
506 idleNotifyCallback
= callback
;
507 idleNotifyRefcon
= refcon
;
518 void IOSCSIParallelDevice::submitCommand( UInt32 cmdType
, IOSCSIParallelCommand
*scsiCmd
, UInt32 cmdSequenceNumber
)
520 deviceGate
->runCommand( (void *)cmdType
, (void *)scsiCmd
, (void *) cmdSequenceNumber
, (void *) 0 );
528 void IOSCSIParallelDevice::receiveCommand( UInt32 cmdType
, IOSCSIParallelCommand
*scsiCmd
, UInt32 cmdSequenceNumber
, void *p3
)
534 case kSCSICommandExecute
:
535 scsiCmd
->cmdType
= (SCSICommandType
) cmdType
;
537 scsiCmd
->scsiCmd
.cdbFlags
&= (kCDBFNoDisconnect
);
539 queue
= (scsiCmd
->queueType
== kQTypeBypassQ
) ? &bypassList
: &deviceList
;
541 if ( scsiCmd
->queuePosition
== kQPositionHead
)
543 stackCommand( queue
, scsiCmd
);
547 addCommand( queue
, scsiCmd
);
553 case kSCSICommandAbortAll
:
554 abortAllCommands( kSCSICommandAbortAll
);
557 case kSCSICommandAbort
:
558 abortCommand( scsiCmd
, cmdSequenceNumber
);
561 case kSCSICommandDeviceReset
:
562 abortAllCommands( kSCSICommandDeviceReset
);
576 void IOSCSIParallelDevice::abortCommand( IOSCSIParallelCommand
*scsiCmd
, UInt32 sequenceNumber
)
578 if ( scsiCmd
->list
== (queue_head_t
*)deviceGate
)
580 if ( scsiCmd
->sequenceNumber
!= sequenceNumber
)
584 scsiCmd
->results
.returnCode
= kIOReturnAborted
;
586 else if ( scsiCmd
->list
== &deviceList
)
588 if ( scsiCmd
->sequenceNumber
!= sequenceNumber
)
593 deleteCommand( &deviceList
, scsiCmd
);
594 scsiCmd
->results
.returnCode
= kIOReturnAborted
;
595 finishCommand( scsiCmd
);
597 else if ( scsiCmd
->list
== &activeList
)
599 if ( scsiCmd
->sequenceNumber
!= sequenceNumber
)
604 moveCommand( &activeList
, &abortList
, scsiCmd
);
616 void IOSCSIParallelDevice::abortAllCommands( SCSICommandType cmdType
)
618 IOSCSIParallelDevice
*abortDev
;
620 abortCmdPending
= cmdType
;
622 if ( abortCmdPending
== kSCSICommandAbortAll
)
626 client
->message( kSCSIClientMsgDeviceAbort
, this );
629 else if ( abortCmdPending
== kSCSICommandDeviceReset
)
631 queue_iterate( &target
->deviceList
, abortDev
, IOSCSIParallelDevice
*, nextDevice
)
633 if ( abortDev
->client
!= 0 )
635 abortDev
->client
->message( kSCSIClientMsgDeviceReset
, abortDev
);
648 void IOSCSIParallelDevice::resetOccurred( SCSIClientMessage clientMsg
)
650 if ( client
!= 0 && clientMsg
!= kSCSIClientMsgNone
)
652 client
->message( clientMsg
, this );
655 moveAllCommands( &activeList
, &cancelList
, kIOReturnAborted
);
656 moveAllCommands( &abortList
, &cancelList
, kIOReturnAborted
);
658 abortState
= kStateIdle
;
659 reqSenseState
= kStateIdle
;
660 commandLimit
= commandLimitSave
;
661 negotiateState
= kStateIdle
;
666 void IOSCSIParallelDevice::resetComplete()
670 client
->message( kSCSIClientMsgBusReset
| kSCSIClientMsgDone
, this );
680 bool IOSCSIParallelDevice::checkAbortQueue()
682 IOSCSIParallelCommand
*origCmd
;
684 if ( abortState
== kStateActive
)
689 if ( abortCmdPending
!= kSCSICommandNone
)
691 abortCmd
->origCommand
= 0;
693 abortCmd
->scsiCmd
.cdbTagMsg
= 0;
694 abortCmd
->scsiCmd
.cdbTag
= (UInt32
) -1;
697 abortCmd
->cmdType
= abortCmdPending
;
698 abortCmd
->scsiCmd
.cdbAbortMsg
= (abortCmdPending
== kSCSICommandAbortAll
)
699 ? kSCSIMsgAbort
: kSCSIMsgBusDeviceReset
;
701 if ( disableDisconnect
== true )
703 abortCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNoDisconnect
;
707 abortCmd
->scsiCmd
.cdbFlags
&= ~kCDBFlagsNoDisconnect
;
711 abortCmd
->timer
= ( abortCmd
->timeout
!= 0 ) ?
712 abortCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
714 bzero( &abortCmd
->results
, sizeof(SCSIResults
) );
716 abortCmdPending
= kSCSICommandNone
;
717 abortState
= kStateActive
;
719 addCommand( &activeList
, abortCmd
);
720 controller
->executeCommand( abortCmd
);
722 else if ( queue_empty( &abortList
) == false )
724 origCmd
= (IOSCSIParallelCommand
*)queue_first( &abortList
);
725 abortCmd
->origCommand
= origCmd
;
727 abortCmd
->cmdType
= kSCSICommandAbort
;
728 abortCmd
->scsiCmd
.cdbTagMsg
= origCmd
->scsiCmd
.cdbTagMsg
;
729 abortCmd
->scsiCmd
.cdbTag
= origCmd
->scsiCmd
.cdbTag
;
730 abortCmd
->scsiCmd
.cdbAbortMsg
= (abortCmd
->scsiCmd
.cdbTagMsg
!= 0)
731 ? kSCSIMsgAbortTag
: kSCSIMsgAbort
;
733 abortCmd
->timer
= ( abortCmd
->timeout
!= 0 ) ?
734 abortCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
736 bzero( &abortCmd
->results
, sizeof(SCSIResults
) );
738 abortState
= kStateActive
;
740 addCommand( &activeList
, abortCmd
);
741 controller
->executeCommand( abortCmd
);
756 void IOSCSIParallelDevice::checkCancelQueue()
758 if ( cancelState
!= kStateIdle
)
763 if ( queue_empty( &cancelList
) == true )
768 if ( controller
->controllerInfo
.disableCancelCommands
== true )
773 cancelCmd
->origCommand
= (IOSCSIParallelCommand
*)queue_first( &cancelList
);
774 bzero( &cancelCmd
->results
, sizeof(SCSIResults
) );
776 cancelState
= kStateActive
;
777 controller
->cancelCommand( cancelCmd
);
785 bool IOSCSIParallelDevice::checkReqSense()
787 IOMemoryDescriptor
*senseData
;
789 SCSITargetParms
*tpCur
;
791 if ( target
->reqSenseState
== kStateActive
)
796 if ( reqSenseState
== kStateIssue
)
798 reqSenseCmd
->origCommand
= reqSenseOrigCmd
;
799 bzero( &reqSenseCmd
->results
, sizeof(SCSIResults
) );
801 reqSenseOrigCmd
->getPointers( &senseData
, &senseLength
, 0, true );
802 reqSenseCmd
->setPointers( senseData
, senseLength
, false );
804 reqSenseCmd
->scsiCmd
.cdbFlags
= 0;
806 if ( disableDisconnect
== true )
808 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNoDisconnect
;
812 reqSenseCmd
->scsiCmd
.cdbFlags
&= ~kCDBFlagsNoDisconnect
;
815 tpCur
= &target
->targetParmsCurrent
;
817 if ( tpCur
->transferWidth
!= 1 )
819 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateWDTR
;
820 if (tpCur
->transferOptions
& kSCSITransferOptionPPR
) {
821 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiatePPR
;
825 if ( tpCur
->transferOffset
!= 0 )
827 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateSDTR
;
828 if (tpCur
->transferOptions
& kSCSITransferOptionPPR
) {
829 reqSenseCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiatePPR
;
834 reqSenseCmd
->timer
= ( reqSenseCmd
->timeout
!= 0 ) ?
835 reqSenseCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
837 reqSenseCmd
->scsiCmd
.cdb
[3] = (senseLength
>> 8) & 0xff;
838 reqSenseCmd
->scsiCmd
.cdb
[4] = senseLength
& 0xff;
840 reqSenseState
= kStatePending
;
843 if ( reqSenseState
== kStatePending
)
845 target
->reqSenseState
= reqSenseState
= kStateActive
;
847 addCommand( &activeList
, reqSenseCmd
);
850 controller
->commandCount
++;
852 controller
->executeCommand( reqSenseCmd
);
855 return (target
->reqSenseCount
> 0);
864 bool IOSCSIParallelDevice::checkDeviceQueue( UInt32
*dispatchAction
)
866 IOSCSIParallelCommand
*scsiCmd
= 0;
874 if ( controller
->commandCount
>= controller
->commandLimit
)
876 *dispatchAction
= kDispatchStop
;
880 if ( target
->commandCount
>= target
->commandLimit
)
882 *dispatchAction
= kDispatchNextTarget
;
886 *dispatchAction
= kDispatchNextLun
;
888 if ( commandCount
>= commandLimit
)
893 for ( i
=0; i
< 2; i
++ )
895 queueHeld
= (i
== 0) ? bypassQHeld
: normalQHeld
;
896 queue
= (i
== 0) ? &bypassList
: &deviceList
;
898 if ( queueHeld
== true )
903 scsiCmd
= checkCommand( queue
);
906 *dispatchAction
= kDispatchNextCommand
;
917 if ( disableDisconnect
== true || (scsiCmd
->scsiCmd
.cdbFlags
& kCDBFNoDisconnect
) )
919 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNoDisconnect
;
921 if ( controller
->commandCount
!= 0 )
923 *dispatchAction
= kDispatchNextLun
;
927 controller
->noDisconnectCmd
= scsiCmd
;
928 controller
->commandLimitSave
= controller
->commandLimit
;
929 controller
->commandLimit
= 1;
932 else if ( checkTag( scsiCmd
) == false )
934 switch ( controller
->controllerInfo
.tagAllocationMethod
)
936 case kTagAllocationPerTarget
:
937 *dispatchAction
= kDispatchNextTarget
;
939 case kTagAllocationPerController
:
940 *dispatchAction
= kDispatchStop
;
942 case kTagAllocationPerLun
:
945 *dispatchAction
= kDispatchNextLun
;
952 checkNegotiate( scsiCmd
);
954 scsiCmd
->timer
= ( scsiCmd
->timeout
!= 0 ) ? scsiCmd
->timeout
/ kSCSITimerIntervalmS
+ 1 : 0;
957 target
->commandCount
++;
958 controller
->commandCount
++;
960 addCommand( &activeList
, scsiCmd
);
962 controller
->executeCommand( scsiCmd
);
974 void IOSCSIParallelDevice::rescheduleCommand( IOSCSIParallelCommand
*scsiCmd
)
976 if ( scsiCmd
->list
!= &activeList
)
978 IOLog( "IOSCSIParallelController::rescheduleCommand() - Command not active. Cmd = %08x\n\r", (int)scsiCmd
);
982 deleteCommand( &activeList
, scsiCmd
);
984 switch ( scsiCmd
->cmdType
)
986 case kSCSICommandExecute
:
987 if ( scsiCmd
->scsiCmd
.cdbTagMsg
!= 0 )
989 freeTag( scsiCmd
->scsiCmd
.cdbTag
);
990 scsiCmd
->scsiCmd
.cdbTag
= (UInt32
) -1;
993 stackCommand( &deviceList
, scsiCmd
);
995 if ( scsiCmd
->scsiCmd
.cdbFlags
& kCDBFlagsNoDisconnect
)
997 controller
->commandLimit
= controller
->commandLimitSave
;
998 controller
->noDisconnectCmd
= 0;
1001 controller
->commandCount
--;
1002 target
->commandCount
--;
1006 case kSCSICommandReqSense
:
1007 reqSenseState
= kStatePending
;
1008 target
->reqSenseState
= kStateIdle
;
1010 controller
->commandCount
--;
1013 case kSCSICommandAbortAll
:
1014 case kSCSICommandDeviceReset
:
1015 abortCmdPending
= scsiCmd
->cmdType
;
1017 case kSCSICommandAbort
:
1018 abortState
= kStateIdle
;
1034 bool IOSCSIParallelDevice::setTargetParms( SCSITargetParms
*targetParms
)
1036 IOSCSIParallelCommand
*scsiCmd
;
1037 SCSICDBInfo scsiCDB
;
1041 IOMemoryDescriptor
*senseDesc
;
1042 UInt8 senseBuffer
[14];
1045 if ( getWorkLoop()->inGate() == true )
1047 IOPanic( "IOSCSIParallelDevice:::setTargetParms() - must not be called from workloop!!\n\r");
1050 IOWriteLock( target
->clientSem
);
1051 IOWriteLock( target
->targetSem
);
1053 while ( target
->negotiateState
== kStateActive
)
1058 target
->targetParmsNew
= *targetParms
;
1060 if ( targetParms
->transferPeriodpS
< controller
->controllerInfo
.minTransferPeriodpS
)
1062 target
->targetParmsNew
.transferPeriodpS
= controller
->controllerInfo
.minTransferPeriodpS
;
1065 if ( target
->targetParmsNew
.transferPeriodpS
== 0
1066 || target
->targetParmsNew
.transferOffset
== 0
1067 || controller
->controllerInfo
.minTransferPeriodpS
== 0 )
1069 target
->targetParmsNew
.transferPeriodpS
= 0;
1070 target
->targetParmsNew
.transferOffset
= 0;
1073 target
->commandLimit
= 1;
1075 fTagEnable
= (targetParms
->enableTagQueuing
== true)
1076 && (controller
->controllerInfo
.tagAllocationMethod
!= kTagAllocationNone
)
1077 && (controller
->controllerInfo
.maxTags
!= 0);
1079 regObjCmdQueue
->setValue( (UInt32
)fTagEnable
);
1081 if ( fTagEnable
== true )
1083 target
->commandLimitSave
= controller
->controllerInfo
.maxCommandsPerTarget
;
1087 target
->commandLimitSave
= 1;
1088 target
->targetParmsNew
.enableTagQueuing
= false;
1091 scsiCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
1093 bzero( &scsiCDB
, sizeof( SCSICDBInfo
) );
1095 scsiCDB
.cdbLength
= 6;
1096 scsiCDB
.cdb
[0] = kSCSICmdTestUnitReady
;
1097 scsiCDB
.cdb
[1] = targetLun
.lun
<< 4;
1098 scsiCmd
->setCDB( &scsiCDB
);
1100 senseDesc
= IOMemoryDescriptor::withAddress(senseBuffer
, sizeof(senseBuffer
), kIODirectionIn
);
1101 if ( senseDesc
== 0 ) return false;
1102 scsiCmd
->setPointers( senseDesc
, sizeof(senseBuffer
), false, true );
1104 target
->negotiateState
= kStateIssue
;
1108 IOWriteLock( target
->targetSem
);
1109 IORWUnlock( target
->targetSem
);
1112 senseDesc
->release();
1114 rc
= (target
->negotiationResult
.returnCode
== kIOReturnSuccess
);
1116 IORWUnlock( target
->clientSem
);
1126 void IOSCSIParallelDevice::getTargetParms( SCSITargetParms
*targetParms
)
1128 *targetParms
= target
->targetParmsCurrent
;
1136 bool IOSCSIParallelDevice::setLunParms( SCSILunParms
*lunParms
)
1138 IOSCSIParallelCommand
*scsiCmd
;
1139 SCSICDBInfo scsiCDB
;
1141 IOMemoryDescriptor
*senseDesc
;
1142 UInt8 senseBuffer
[14];
1144 if ( getWorkLoop()->inGate() == true )
1146 IOPanic( "IOSCSIParallelDevice:::setLunParms() - must not be called from workloop!!\n\r");
1149 IOWriteLock( clientSem
);
1151 lunParmsNew
= *lunParms
;
1152 commandLimitSave
= commandLimit
;
1155 scsiCmd
= allocCommand(kIOSCSIParallelDevice
, 0);
1157 bzero( &scsiCDB
, sizeof( SCSICDBInfo
) );
1159 scsiCDB
.cdbLength
= 6;
1160 scsiCDB
.cdb
[0] = kSCSICmdTestUnitReady
;
1161 scsiCDB
.cdb
[1] = targetLun
.lun
<< 4;
1162 scsiCmd
->setCDB( &scsiCDB
);
1164 senseDesc
= IOMemoryDescriptor::withAddress(senseBuffer
, sizeof(senseBuffer
), kIODirectionIn
);
1165 if ( senseDesc
== 0 ) return false;
1166 scsiCmd
->setPointers( senseDesc
, sizeof(senseBuffer
), false, true );
1168 negotiateState
= kStateIssue
;
1173 senseDesc
->release();
1175 while ( negotiateState
!= kStateIdle
)
1180 IORWUnlock( clientSem
);
1190 void IOSCSIParallelDevice::getLunParms( SCSILunParms
*lunParms
)
1192 lunParms
->disableDisconnect
= disableDisconnect
;
1200 void IOSCSIParallelDevice::checkNegotiate( IOSCSIParallelCommand
*scsiCmd
)
1202 SCSITargetParms
*tpCur
, *tpNew
;
1204 if ( target
->negotiateState
== kStateIssue
)
1206 if ( target
->commandCount
== 0 )
1208 target
->negotiateState
= kStateActive
;
1210 tpNew
= &target
->targetParmsNew
;
1211 tpCur
= &target
->targetParmsCurrent
;
1213 target
->negotiationResult
.returnCode
= kIOReturnError
;
1215 if ((tpCur
->transferPeriodpS
!= tpNew
->transferPeriodpS
) ||
1216 (tpCur
->transferOffset
!= tpNew
->transferOffset
) ||
1217 ((tpCur
->transferOptions
^ tpNew
->transferOptions
) & kSCSITransferOptionsSCSI3
) )
1219 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateSDTR
;
1221 if (tpNew
->transferOptions
& kSCSITransferOptionPPR
) {
1222 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiatePPR
;
1226 if ( tpCur
->transferWidth
!= tpNew
->transferWidth
)
1228 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsNegotiateWDTR
;
1231 if ( tpCur
->enableTagQueuing
!= tpNew
->enableTagQueuing
)
1233 scsiCmd
->scsiCmd
.cdbFlags
|= kCDBFlagsEnableTagQueuing
;
1236 if ( (scsiCmd
->scsiCmd
.cdbFlags
&
1237 (kCDBFlagsNegotiateSDTR
|
1238 kCDBFlagsNegotiateWDTR
|
1239 kCDBFlagsNegotiatePPR
|
1240 kCDBFlagsEnableTagQueuing
)) == 0 )
1242 IORWUnlock( target
->targetSem
);
1243 target
->negotiateState
= kStateIdle
;
1244 target
->commandLimit
= target
->commandLimitSave
;
1251 if ( negotiateState
== kStateIssue
)
1253 if ( commandCount
== 0 )
1255 disableDisconnect
= lunParmsNew
.disableDisconnect
;
1256 negotiateState
= kStateIdle
;
1266 void IOSCSIParallelDevice::negotiationComplete()
1268 SCSITargetParms
*tpCur
, *tpNew
;
1270 tpNew
= &target
->targetParmsNew
;
1271 tpCur
= &target
->targetParmsCurrent
;
1273 if ( target
->negotiationResult
.returnCode
== kIOReturnSuccess
)
1275 tpCur
->transferPeriodpS
= tpNew
->transferPeriodpS
= target
->negotiationResult
.transferPeriodpS
;
1276 tpCur
->transferOffset
= tpNew
->transferOffset
= target
->negotiationResult
.transferOffset
;
1277 tpCur
->transferWidth
= tpNew
->transferWidth
= target
->negotiationResult
.transferWidth
;
1278 tpCur
->transferOptions
= tpNew
->transferOptions
= target
->negotiationResult
.transferOptions
;
1280 target
->commandLimit
= target
->commandLimitSave
;
1284 tpNew
->transferPeriodpS
= 0;
1285 tpNew
->transferOffset
= 0;
1286 tpNew
->transferWidth
= 1;
1289 target
->regObjTransferPeriod
->setValue( tpNew
->transferPeriodpS
);
1290 target
->regObjTransferOffset
->setValue( tpNew
->transferOffset
);
1291 target
->regObjTransferWidth
->setValue( tpNew
->transferWidth
);
1292 target
->regObjTransferOptions
->setValue( tpNew
->transferOptions
);
1294 target
->negotiateState
= kStateIdle
;
1302 bool IOSCSIParallelDevice::checkTag( IOSCSIParallelCommand
*scsiCmd
)
1304 SCSICDBInfo scsiCDB
;
1307 scsiCmd
->getCDB( &scsiCDB
);
1309 scsiCDB
.cdbTagMsg
= 0;
1310 scsiCDB
.cdbTag
= (UInt32
)-1;
1314 if ( scsiCmd
->device
->target
->targetParmsCurrent
.enableTagQueuing
== false )
1319 if ( allocTag( &scsiCDB
.cdbTag
) == false )
1325 if ( scsiCDB
.cdbTagMsg
== 0 )
1327 scsiCDB
.cdbTagMsg
= kSCSIMsgSimpleQueueTag
;
1332 scsiCmd
->setCDB( &scsiCDB
);
1342 bool IOSCSIParallelDevice::allocTag( UInt32
*tagId
)
1349 switch ( controller
->controllerInfo
.tagAllocationMethod
)
1351 case kTagAllocationPerLun
:
1354 case kTagAllocationPerTarget
:
1355 tags
= target
->tagArray
;
1357 case kTagAllocationPerController
:
1358 tags
= controller
->tagArray
;
1364 if ( tags
== 0 ) return false;
1366 for ( i
= 0; i
< controller
->controllerInfo
.maxTags
; i
++ )
1369 tagMask
= 1 << (i
% 32);
1370 if ( !(tags
[tagIndex
] & tagMask
) )
1372 tags
[tagIndex
] |= tagMask
;
1385 void IOSCSIParallelDevice::freeTag( UInt32 tagId
)
1389 switch ( controller
->controllerInfo
.tagAllocationMethod
)
1391 case kTagAllocationPerLun
:
1394 case kTagAllocationPerTarget
:
1395 tags
= target
->tagArray
;
1397 case kTagAllocationPerController
:
1398 tags
= controller
->tagArray
;
1404 if ( tags
== 0 ) return;
1406 tags
[tagId
/32] &= ~(1 << (tagId
% 32));
1414 IOSCSIParallelCommand
*IOSCSIParallelDevice::findCommandWithNexus( UInt32 tagValue
)
1416 IOSCSIParallelCommand
*scsiCmd
;
1418 queue_iterate( &activeList
, scsiCmd
, IOSCSIParallelCommand
*, nextCommand
)
1420 switch ( scsiCmd
->cmdType
)
1422 case kSCSICommandExecute
:
1423 case kSCSICommandReqSense
:
1424 if ( scsiCmd
->scsiCmd
.cdbTag
== tagValue
)
1434 queue_iterate( &abortList
, scsiCmd
, IOSCSIParallelCommand
*, nextCommand
)
1436 switch ( scsiCmd
->cmdType
)
1438 case kSCSICommandExecute
:
1439 case kSCSICommandReqSense
:
1440 if ( scsiCmd
->scsiCmd
.cdbTag
== tagValue
)
1458 void IOSCSIParallelDevice::timer()
1460 IOSCSIParallelCommand
*scsiCmd
, *tmp
= 0;
1461 SCSITargetLun scsiTargetLun
;
1463 queue_iterate( &activeList
, scsiCmd
, IOSCSIParallelCommand
*, nextCommand
)
1465 tmp
= (IOSCSIParallelCommand
*)queue_prev( &scsiCmd
->nextCommand
);
1467 if ( scsiCmd
->timer
)
1469 if ( !--scsiCmd
->timer
)
1471 scsiCmd
->getTargetLun( &scsiTargetLun
);
1472 IOLog("Timeout: T/L = %d:%d Cmd = %08x Cmd Type = %d\n\r",
1473 scsiTargetLun
.target
, scsiTargetLun
.lun
, (int)scsiCmd
, scsiCmd
->cmdType
);
1475 switch ( scsiCmd
->cmdType
)
1477 case kSCSICommandExecute
:
1478 moveCommand( &activeList
, &abortList
, scsiCmd
, kIOReturnTimeout
);
1482 case kSCSICommandReqSense
:
1483 reqSenseState
= kStateIdle
;
1484 moveCommand( &activeList
, &abortList
, scsiCmd
, kIOReturnTimeout
);
1488 case kSCSICommandAbort
:
1489 case kSCSICommandAbortAll
:
1490 case kSCSICommandDeviceReset
:
1491 controller
->busResetState
= kStateIssue
;
1502 if ( queue_end( &activeList
, (queue_head_t
*)scsiCmd
) == true )
1514 void IOSCSIParallelDevice::dispatchRequest()
1516 target
->state
= kStateActive
;
1517 controller
->dispatchRequest();
1525 bool IOSCSIParallelDevice::dispatch( UInt32
*dispatchAction
)
1531 if ( controller
->checkBusReset() == true )
1533 *dispatchAction
= kDispatchStop
;
1537 if ( (rc
= controller
->commandDisable
) == true )
1539 *dispatchAction
= kDispatchNextTarget
;
1543 if ( checkAbortQueue() == true )
1545 *dispatchAction
= kDispatchNextTarget
;
1551 if ( (rc
= controller
->commandDisable
) == true )
1553 *dispatchAction
= kDispatchStop
;
1557 if ( (rc
= checkReqSense()) == true )
1559 *dispatchAction
= kDispatchNextTarget
;
1563 rc
= checkDeviceQueue( dispatchAction
);
1565 } while ( *dispatchAction
== kDispatchNextCommand
);
1576 void IOSCSIParallelDevice::completeCommand( IOSCSIParallelCommand
*scsiCmd
)
1578 SCSICommandType cmdType
;
1580 cmdType
= scsiCmd
->cmdType
;
1583 case kSCSICommandExecute
:
1584 executeCommandDone( scsiCmd
);
1587 case kSCSICommandReqSense
:
1588 executeReqSenseDone( scsiCmd
);
1591 case kSCSICommandAbort
:
1592 case kSCSICommandAbortAll
:
1593 case kSCSICommandDeviceReset
:
1594 abortCommandDone( scsiCmd
);
1597 case kSCSICommandCancel
:
1598 cancelCommandDone( scsiCmd
);
1615 void IOSCSIParallelDevice::checkIdleNotify()
1617 if ( idleNotifyActive
== false )
1622 if ( (queue_empty( &activeList
) == true)
1623 && (queue_empty( &abortList
) == true)
1624 && (queue_empty( &cancelList
) == true)
1625 && (target
->reqSenseCount
== 0) )
1627 idleNotifyActive
= false;
1628 (idleNotifyCallback
)( idleNotifyTarget
, idleNotifyRefcon
);
1637 void IOSCSIParallelDevice::flushQueue( UInt32 queueType
, IOReturn rc
)
1639 queue_head_t
*queue
;
1641 queue
= (queueType
== kQTypeBypassQ
) ? &bypassList
: &deviceList
;
1642 purgeAllCommands( queue
, rc
);
1650 void IOSCSIParallelDevice::executeCommandDone( IOSCSIParallelCommand
*scsiCmd
)
1652 deleteCommand( scsiCmd
->list
, scsiCmd
);
1655 controller
->commandCount
--;
1656 target
->commandCount
--;
1658 if ( scsiCmd
->scsiCmd
.cdbTagMsg
!= 0 )
1660 freeTag( scsiCmd
->scsiCmd
.cdbTag
);
1661 scsiCmd
->scsiCmd
.cdbTag
= (UInt32
) -1;
1664 if ( scsiCmd
->scsiCmd
.cdbFlags
& (kCDBFlagsNegotiateSDTR
|
1665 kCDBFlagsNegotiateWDTR
|
1666 kCDBFlagsNegotiatePPR
|
1667 kCDBFlagsEnableTagQueuing
) )
1669 if ( scsiCmd
->scsiCmd
.cdbFlags
& (kCDBFlagsNegotiateSDTR
|
1670 kCDBFlagsNegotiateWDTR
|
1671 kCDBFlagsNegotiatePPR
) )
1673 negotiationComplete();
1677 target
->negotiationResult
.returnCode
= kIOReturnSuccess
;
1680 IORWUnlock( target
->targetSem
);
1683 if ( scsiCmd
->scsiCmd
.cdbFlags
& kCDBFlagsNoDisconnect
)
1685 controller
->commandLimit
= controller
->commandLimitSave
;
1686 controller
->noDisconnectCmd
= 0;
1689 if ( scsiCmd
->results
.scsiStatus
== kSCSIStatusCheckCondition
1690 && scsiCmd
->results
.requestSenseDone
== false
1691 && scsiCmd
->senseData
!= 0 )
1693 reqSenseOrigCmd
= scsiCmd
;
1694 reqSenseState
= kStateIssue
;
1695 target
->reqSenseCount
++;
1699 if ( scsiCmd
->results
.scsiStatus
== kSCSIStatusQueueFull
)
1701 if ( commandCount
> 4 )
1703 // IOLog( "IOSCSI: Q-full - commandCount = %d commandLimit = %d\n\r", commandCount, commandLimit );
1704 commandLimit
= commandCount
;
1707 stackCommand( &deviceList
, scsiCmd
);
1711 finishCommand( scsiCmd
);
1719 void IOSCSIParallelDevice::executeReqSenseDone( IOSCSIParallelCommand
*scsiCmd
)
1721 IOSCSIParallelCommand
*origCommand
;
1723 deleteCommand( scsiCmd
->list
, scsiCmd
);
1725 target
->reqSenseState
= reqSenseState
= kStateIdle
;
1726 target
->reqSenseCount
--;
1729 controller
->commandCount
--;
1731 reqSenseOrigCmd
= 0;
1733 origCommand
= scsiCmd
->origCommand
;
1735 if ( (scsiCmd
->results
.returnCode
== kIOReturnSuccess
) || (scsiCmd
->results
.returnCode
== kIOReturnUnderrun
) )
1737 origCommand
->results
.requestSenseDone
= true;
1738 origCommand
->results
.requestSenseLength
= scsiCmd
->results
.bytesTransferred
;
1742 origCommand
->results
.requestSenseDone
= false;
1743 origCommand
->results
.requestSenseLength
= 0;
1746 finishCommand( scsiCmd
->origCommand
);
1754 void IOSCSIParallelDevice::abortCommandDone( IOSCSIParallelCommand
*scsiCmd
)
1756 IOSCSIParallelCommand
*origSCSICmd
;
1757 IOSCSIParallelDevice
*abortDev
;
1759 deleteCommand( scsiCmd
->list
, scsiCmd
);
1761 abortState
= kStateIdle
;
1763 if ( scsiCmd
->cmdType
== kSCSICommandAbortAll
)
1765 moveAllCommands( &activeList
, &cancelList
, kIOReturnAborted
);
1766 moveAllCommands( &abortList
, &cancelList
, kIOReturnAborted
);
1770 client
->message( kSCSIClientMsgDeviceAbort
| kSCSIClientMsgDone
, this );
1773 if ( scsiCmd
->cmdType
== kSCSICommandDeviceReset
)
1775 target
->commandLimit
= target
->commandLimitSave
;
1776 target
->reqSenseCount
= 0;
1777 target
->reqSenseState
= kStateIdle
;
1778 target
->negotiateState
= kStateIssue
;
1780 target
->targetParmsCurrent
.transferPeriodpS
= 0;
1781 target
->targetParmsCurrent
.transferOffset
= 0;
1782 target
->targetParmsCurrent
.transferWidth
= 1;
1784 queue_iterate( &target
->deviceList
, abortDev
, IOSCSIParallelDevice
*, nextDevice
)
1786 abortDev
->resetOccurred( (SCSIClientMessage
)(kSCSIClientMsgDeviceReset
| kSCSIClientMsgDone
) );
1789 else if ( scsiCmd
->cmdType
== kSCSICommandAbort
)
1791 origSCSICmd
= scsiCmd
->origCommand
;
1793 if ( findCommand( &abortList
, origSCSICmd
) == true )
1795 moveCommand( &abortList
, &cancelList
, origSCSICmd
, kIOReturnAborted
);
1807 void IOSCSIParallelDevice::cancelCommandDone( IOSCSIParallelCommand
*scsiCmd
)
1809 IOSCSIParallelCommand
*origSCSICmd
;
1811 cancelState
= kStateIdle
;
1813 origSCSICmd
= scsiCmd
->origCommand
;
1815 if ( findCommand( &cancelList
, origSCSICmd
) == true )
1817 IOLog( "IOSCSIParallelDevice::cancelCommandDone - Cancelled command not completed - scsiCmd = %08x\n\r", (int)origSCSICmd
);
1818 deleteCommand( &cancelList
, origSCSICmd
);
1827 void IOSCSIParallelDevice::finishCommand( IOSCSIParallelCommand
*scsiCmd
)
1829 if ( scsiCmd
->completionInfo
.async
.callback
)
1831 (*scsiCmd
->completionInfo
.async
.callback
)( scsiCmd
->completionInfo
.async
.target
,
1832 scsiCmd
->completionInfo
.async
.refcon
);
1836 scsiCmd
->completionInfo
.sync
.lock
->signal();
1845 OSDictionary
*IOSCSIParallelDevice::createProperties()
1847 OSDictionary
*propTable
= 0;
1852 propTable
= OSDictionary::withCapacity(kSCSIMaxProperties
);
1853 if ( propTable
== NULL
)
1858 regObj
= (OSObject
*)OSNumber::withNumber(targetLun
.target
,32);
1859 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTarget
) != true )
1861 goto createprop_error
;
1864 regObj
= (OSObject
*)OSNumber::withNumber(targetLun
.target
,32);
1865 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyIOUnit
) != true )
1867 goto createprop_error
;
1870 regObj
= (OSObject
*)OSNumber::withNumber(targetLun
.lun
,32);
1871 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyLun
) != true )
1873 goto createprop_error
;
1878 stripBlanks( d
, (char *)inquiryData
->vendorName
, sizeof(inquiryData
->vendorName
) );
1879 regObj
= (OSObject
*)OSString::withCString( d
);
1880 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyVendorName
) != true )
1882 goto createprop_error
;
1885 stripBlanks( d
, (char *)inquiryData
->productName
, sizeof(inquiryData
->productName
) );
1886 regObj
= (OSObject
*)OSString::withCString( d
);
1887 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyProductName
) != true )
1889 goto createprop_error
;
1892 stripBlanks( d
, (char *)inquiryData
->productRevision
, sizeof(inquiryData
->productRevision
) );
1893 regObj
= (OSObject
*)OSString::withCString( d
);
1894 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyProductRevision
) != true )
1896 goto createprop_error
;
1899 regObj
= (OSObject
*)OSBoolean::withBoolean( (inquiryData
->devTypeMod
& kSCSIDevTypeModRemovable
) != 0 );
1900 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyRemovableMedia
) != true )
1902 goto createprop_error
;
1905 regObj
= (OSObject
*)OSNumber::withNumber( inquiryData
->devType
& kSCSIDevTypeMask
, 32 );
1906 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyDeviceTypeID
) != true )
1908 goto createprop_error
;
1911 regObj
= (OSObject
*)target
->regObjTransferPeriod
;
1912 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferPeriod
, false ) != true )
1914 goto createprop_error
;
1916 regObjTransferPeriod
= (OSNumber
*)regObj
;
1918 regObj
= (OSObject
*)target
->regObjTransferOffset
;
1919 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferOffset
, false ) != true )
1921 goto createprop_error
;
1923 regObjTransferOffset
= (OSNumber
*)regObj
;
1926 regObj
= (OSObject
*)target
->regObjTransferWidth
;
1927 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferWidth
, false ) != true )
1929 goto createprop_error
;
1931 regObjTransferWidth
= (OSNumber
*)regObj
;
1933 regObj
= (OSObject
*)target
->regObjTransferOptions
;
1934 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyTransferOptions
, false ) != true )
1936 goto createprop_error
;
1938 regObjTransferOptions
= (OSNumber
*)regObj
;
1940 regObj
= (OSObject
*)target
->regObjCmdQueue
;
1941 if ( addToRegistry( propTable
, regObj
, kSCSIPropertyCmdQueue
, false ) != true )
1943 goto createprop_error
;
1945 regObjCmdQueue
= (OSNumber
*)regObj
;
1950 propTable
->release();
1959 bool IOSCSIParallelDevice::addToRegistry( OSDictionary
*propTable
, OSObject
*regObj
, char *key
,
1960 bool doRelease
= true )
1964 if ( regObj
== NULL
)
1969 rc
= propTable
->setObject( key
, regObj
);
1973 // If 'doRelease' is true, then a reference count is consumed.
1986 bool IOSCSIParallelDevice::matchPropertyTable(OSDictionary
* table
)
1990 match
= compareProperty( table
, kSCSIPropertyIOUnit
) &&
1991 compareProperty( table
, kSCSIPropertyDeviceTypeID
) &&
1992 compareProperty( table
, kSCSIPropertyRemovableMedia
) &&
1993 compareProperty( table
, kSCSIPropertyVendorName
) &&
1994 compareProperty( table
, kSCSIPropertyProductName
) &&
1995 compareProperty( table
, kSCSIPropertyProductRevision
);
1997 if ( match
== true )
1999 match
= super::matchPropertyTable(table
);
2011 IOService
*IOSCSIParallelDevice::matchLocation(IOService
* client
)
2022 void IOSCSIParallelDevice::stripBlanks( char *d
, char *s
, UInt32 l
)
2026 for ( p
= d
, c
= *s
; l
&& c
; l
--)
2042 IOSCSICommand
*IOSCSIParallelDevice::allocCommand( IOSCSIDevice
*, UInt32 clientDataSize
)
2045 return (IOSCSICommand
*) allocCommand( kIOSCSIParallelDevice
, clientDataSize
);
2048 IOSCSIParallelCommand
*IOSCSIParallelDevice::allocCommand( IOSCSIParallelDevice
*, UInt32 clientDataSize
)
2050 IOSCSIParallelCommand
*cmd
;
2052 if ( (cmd
= controller
->allocCommand( clientDataSize
)) )
2059 IOCDBCommand
*IOSCSIParallelDevice::allocCommand( IOCDBDevice
*, UInt32 clientDataSize
)
2061 return (IOCDBCommand
*) allocCommand( kIOSCSIDevice
, clientDataSize
);
2069 IOWorkLoop
*IOSCSIParallelDevice::getWorkLoop() const
2071 return controller
->workLoop
;
2080 bool IOSCSIParallelDevice::open( IOService
*forClient
, IOOptionBits options
, void *arg
)
2082 if ( client
!= 0 ) return false;
2086 return super::open( forClient
, options
, arg
);
2094 void IOSCSIParallelDevice::close( IOService
*forClient
, IOOptionBits options
)
2098 return super::close( forClient
, options
);
2106 IOReturn
IOSCSIParallelDevice::message( UInt32 forMsg
, IOService
*forProvider
, void *forArg
)
2108 IOReturn rc
= kIOReturnSuccess
;
2109 SCSIClientMessage clientMsg
;
2111 clientMsg
= (SCSIClientMessage
) forMsg
;
2113 // IOLog( "IOSCSIParallelDevice::message() - clientMsg = %08x\n\r", clientMsg );
2117 case kSCSIClientMsgBusReset
:
2118 holdQueue( kQTypeNormalQ
);
2120 case kSCSIClientMsgBusReset
| kSCSIClientMsgDone
:
2121 releaseQueue( kQTypeNormalQ
);
2124 rc
= super::message( clientMsg
, forProvider
, forArg
);
2135 void IOSCSIParallelDevice::free()
2137 if ( deviceGate
!= 0 )
2139 controller
->workLoop
->removeEventSource( deviceGate
);
2140 deviceGate
->release();
2143 if ( reqSenseCmd
!= 0 ) reqSenseCmd
->release();
2144 if ( abortCmd
!= 0 ) abortCmd
->release();
2145 if ( cancelCmd
!= 0 ) cancelCmd
->release();
2146 if ( probeCmd
!= 0 ) probeCmd
->release();
2148 if ( tagArray
!= 0 ) IOFree( tagArray
, controller
->tagArraySize
);
2149 if ( inquiryData
!= 0 ) IOFree( inquiryData
, inquiryDataSize
);
2150 if ( devicePrivateData
!= 0 ) IOFreeContiguous( devicePrivateData
, controller
->controllerInfo
.lunPrivateDataSize
);
2151 if ( clientSem
!= 0 ) IORWLockFree( clientSem
);