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@
24 * IOSCSIParallelCommand.cpp
28 #include <IOKit/IOSyncer.h>
29 #include <IOKit/scsi/IOSCSIParallelInterface.h>
30 #include <libkern/OSAtomic.h>
33 #define super IOSCSICommand
35 OSDefineMetaClassAndStructors( IOSCSIParallelCommand
, IOSCSICommand
)
36 OSDefineMetaClassAndAbstractStructors( IOSCSICommand
, IOCDBCommand
)
37 OSDefineMetaClassAndAbstractStructors( IOCDBCommand
, IOCommand
)
39 static struct adapterReturnCodes
41 SCSIAdapterStatus adapterStatus
;
42 IOReturn ioReturnCode
;
44 adapterReturnCodes
[] =
46 { kSCSIAdapterStatusSuccess
, kIOReturnSuccess
},
47 { kSCSIAdapterStatusProtocolError
, kIOReturnDeviceError
},
48 { kSCSIAdapterStatusSelectionTimeout
, kIOReturnNotResponding
},
49 { kSCSIAdapterStatusMsgReject
, kIOReturnUnsupported
},
50 { kSCSIAdapterStatusParityError
, kIOReturnIOError
},
51 { kSCSIAdapterStatusOverrun
, kIOReturnOverrun
}
54 #define kNumAdapterReturnCodes (sizeof(adapterReturnCodes)/sizeof(adapterReturnCodes[0]))
56 static struct statusReturnCodes
59 IOReturn ioReturnCode
;
63 { kSCSIStatusGood
, kIOReturnSuccess
},
64 { kSCSIStatusCheckCondition
, kIOReturnIOError
},
65 { kSCSIStatusConditionMet
, kIOReturnSuccess
},
66 { kSCSIStatusBusy
, kIOReturnBusy
},
67 { kSCSIStatusIntermediate
, kIOReturnSuccess
},
68 { kSCSIStatusIntermediateMet
, kIOReturnSuccess
},
69 { kSCSIStatusReservationConfict
, kIOReturnAborted
},
70 { kSCSIStatusCommandTerminated
, kIOReturnAborted
},
71 { kSCSIStatusQueueFull
, kIOReturnIOError
}
74 #define kNumStatusReturnCodes (sizeof(statusReturnCodes)/sizeof(statusReturnCodes[0]))
77 IOSCSIDevice
*IOSCSIParallelCommand::getDevice(IOSCSIDevice
*)
79 return (IOSCSIDevice
*)getDevice(kIOSCSIParallelDevice
);
82 IOSCSIParallelDevice
*IOSCSIParallelCommand::getDevice(IOSCSIParallelDevice
*)
88 void *IOSCSIParallelCommand::getClientData()
93 void *IOSCSIParallelCommand::getCommandData()
95 return commandPrivateData
;
98 UInt32
IOSCSIParallelCommand::getCmdType()
103 IOSCSIParallelCommand
*IOSCSIParallelCommand::getOriginalCmd()
108 UInt32
IOSCSIParallelCommand::getSequenceNumber()
110 return sequenceNumber
;
113 void IOSCSIParallelCommand::getTargetLun( SCSITargetLun
*forTargetLun
)
117 *forTargetLun
= device
->targetLun
;
121 bzero( forTargetLun
, sizeof( SCSITargetLun
) );
127 void IOSCSIParallelCommand::setTimeout( UInt32 timeoutMS
)
132 UInt32
IOSCSIParallelCommand::getTimeout()
137 void IOSCSIParallelCommand::setResults( SCSIResults
*srcResults
)
139 setResults( srcResults
, (SCSINegotiationResults
*)0 );
142 void IOSCSIParallelCommand::setResults( SCSIResults
*srcResults
, SCSINegotiationResults
*negotiationResult
)
144 SCSICommandType cmdType
;
146 if ( srcResults
!= 0 )
148 results
= *srcResults
;
150 cmdType
= (SCSICommandType
) getCmdType();
152 while ( results
.returnCode
== kIOReturnSuccess
)
156 case kSCSICommandExecute
:
157 case kSCSICommandReqSense
:
158 case kSCSICommandAbort
:
159 case kSCSICommandAbortAll
:
160 case kSCSICommandDeviceReset
:
161 if ( results
.adapterStatus
!= kSCSIAdapterStatusSuccess
)
163 results
.returnCode
= adapterStatusToIOReturnCode( results
.adapterStatus
);
171 if ( results
.returnCode
!= kIOReturnSuccess
) break;
175 case kSCSICommandExecute
:
176 case kSCSICommandReqSense
:
177 results
.returnCode
= scsiStatusToIOReturnCode( results
.scsiStatus
);
179 if ( results
.returnCode
!= kIOReturnSuccess
) break;
181 if ( results
.bytesTransferred
< xferCount
)
183 results
.returnCode
= kIOReturnUnderrun
;
195 if ( negotiationResult
!= 0 )
197 device
->target
->negotiationResult
= *negotiationResult
;
201 IOReturn
IOSCSIParallelCommand::adapterStatusToIOReturnCode( SCSIAdapterStatus adapterStatus
)
205 for ( i
=0; i
< kNumAdapterReturnCodes
; i
++ )
207 if ( adapterReturnCodes
[i
].adapterStatus
== adapterStatus
)
209 return adapterReturnCodes
[i
].ioReturnCode
;
212 return kIOReturnError
;
215 IOReturn
IOSCSIParallelCommand::scsiStatusToIOReturnCode( UInt8 scsiStatus
)
219 for ( i
=0; i
< kNumStatusReturnCodes
; i
++ )
221 if ( statusReturnCodes
[i
].scsiStatus
== scsiStatus
)
223 return statusReturnCodes
[i
].ioReturnCode
;
226 return kIOReturnError
;
229 IOReturn
IOSCSIParallelCommand::getResults( SCSIResults
*dstResults
)
231 if ( dstResults
!= 0 )
233 *dstResults
= results
;
236 return results
.returnCode
;
239 void IOSCSIParallelCommand::setQueueInfo( UInt32 forQueueType
, UInt32 forQueuePosition
)
241 queueType
= forQueueType
;
242 queuePosition
= forQueuePosition
;
245 void IOSCSIParallelCommand::getQueueInfo( UInt32
*forQueueType
, UInt32
*forQueuePosition
= 0 )
247 if ( forQueueType
!= 0 ) *forQueueType
= queueType
;
248 if ( forQueuePosition
!= 0 ) *forQueuePosition
= queuePosition
;
251 void IOSCSIParallelCommand::setPointers( IOMemoryDescriptor
*clientDesc
, UInt32 transferCount
, bool isWrite
, bool isSense
= false )
253 if ( isSense
== false )
255 xferDesc
= clientDesc
;
256 xferCount
= transferCount
;
257 xferDirection
= isWrite
;
261 senseData
= clientDesc
;
262 senseLength
= transferCount
;
266 void IOSCSIParallelCommand::getPointers( IOMemoryDescriptor
**clientDesc
, UInt32
*transferCount
, bool *isWrite
, bool isSense
= false )
268 if ( clientDesc
!= NULL
)
270 *clientDesc
= (isSense
== false) ? xferDesc
: senseData
;
273 if ( transferCount
!= NULL
)
275 *transferCount
= (isSense
== false) ? xferCount
: senseLength
;
278 if ( isWrite
!= NULL
)
280 *isWrite
= (isSense
== false) ? xferDirection
: false;
284 void IOSCSIParallelCommand::setCDB( SCSICDBInfo
*clientSCSICmd
)
286 scsiCmd
= *clientSCSICmd
;
289 void IOSCSIParallelCommand::getCDB( SCSICDBInfo
*clientSCSICmd
)
291 *clientSCSICmd
= scsiCmd
;
294 void IOSCSIParallelCommand::setCallback( void *clientTarget
, CallbackFn clientSCSIDoneFn
, void *clientRefcon
)
296 completionInfo
.async
.target
= clientTarget
;
297 completionInfo
.async
.callback
= clientSCSIDoneFn
;
298 completionInfo
.async
.refcon
= clientRefcon
;
301 bool IOSCSIParallelCommand::execute( UInt32
*cmdSequenceNumber
)
307 sequenceNumber
= OSIncrementAtomic( (SInt32
*)&controller
->sequenceNumber
);
309 while ( sequenceNumber
== 0 );
311 if ( cmdSequenceNumber
!= 0 )
313 *cmdSequenceNumber
= sequenceNumber
;
316 list
= (queue_head_t
*)device
->deviceGate
;
318 isSync
= (completionInfo
.async
.callback
== 0);
322 completionInfo
.sync
.lock
= IOSyncer::create();
325 device
->submitCommand( kSCSICommandExecute
, this );
329 completionInfo
.sync
.lock
->wait();
336 void IOSCSIParallelCommand::abort( UInt32 sequenceNumber
)
338 device
->submitCommand( kSCSICommandAbort
, this, sequenceNumber
);
341 void IOSCSIParallelCommand::complete()
345 device
->completeCommand( this );
349 controller
->completeCommand( this );
353 /*------------------- Generic CDB Interface -----------------------------------------------*/
355 void IOSCSIParallelCommand::getCDB( CDBInfo
*cdbInfo
)
357 SCSICDBInfo scsiCDBInfo
;
359 bzero( cdbInfo
, sizeof(CDBInfo
) );
361 getCDB( &scsiCDBInfo
);
362 cdbInfo
->cdb
= scsiCDBInfo
.cdb
;
363 cdbInfo
->cdbLength
= scsiCDBInfo
.cdbLength
;
366 void IOSCSIParallelCommand::setCDB( CDBInfo
*cdbInfo
)
368 SCSICDBInfo scsiCDBInfo
;
370 bzero( &scsiCDBInfo
, sizeof(SCSICDBInfo
) );
372 scsiCDBInfo
.cdbLength
= cdbInfo
->cdbLength
;
373 scsiCDBInfo
.cdb
= cdbInfo
->cdb
;
374 setCDB( &scsiCDBInfo
);
377 IOReturn
IOSCSIParallelCommand::getResults( CDBResults
*cdbResults
)
379 SCSIResults scsiResults
;
382 rc
= getResults( &scsiResults
);
384 if ( cdbResults
!= 0 )
386 bzero( cdbResults
, sizeof(CDBResults
) );
388 cdbResults
->returnCode
= scsiResults
.returnCode
;
389 cdbResults
->bytesTransferred
= scsiResults
.bytesTransferred
;
390 cdbResults
->requestSenseDone
= scsiResults
.requestSenseDone
;
391 cdbResults
->requestSenseLength
= scsiResults
.requestSenseLength
;
398 IOCDBDevice
*IOSCSIParallelCommand::getDevice( IOCDBDevice
* )
400 return (IOCDBDevice
*)device
;
404 void IOSCSIParallelCommand::zeroCommand()
406 cmdType
= kSCSICommandNone
;
407 // controller = <same-as-before>;
408 // device = <same-as-before>;
410 bzero(&nextCommand
, sizeof(nextCommand
));
411 bzero(&scsiCmd
, sizeof(scsiCmd
));
412 bzero(&results
, sizeof(results
));
423 bzero(&completionInfo
, sizeof(completionInfo
));
424 if (dataArea
&& dataSize
)
425 bzero( dataArea
, dataSize
);
426 // commandPrivateData = <same-as-before>;
427 // clientData = <same-as-before>;