]> git.saurik.com Git - apple/xnu.git/blame - iokit/Families/IOSCSIParallel/IOSCSIParallelCommand.cpp
xnu-201.tar.gz
[apple/xnu.git] / iokit / Families / IOSCSIParallel / IOSCSIParallelCommand.cpp
CommitLineData
1c79356b
A
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 *
24 * IOSCSIParallelCommand.cpp
25 *
26 */
27
28#include <IOKit/IOSyncer.h>
29#include <IOKit/scsi/IOSCSIParallelInterface.h>
30#include <libkern/OSAtomic.h>
31
32#undef super
33#define super IOSCSICommand
34
35OSDefineMetaClassAndStructors( IOSCSIParallelCommand, IOSCSICommand )
36OSDefineMetaClassAndAbstractStructors( IOSCSICommand, IOCDBCommand )
37OSDefineMetaClassAndAbstractStructors( IOCDBCommand, IOCommand )
38
39static struct adapterReturnCodes
40{
41 SCSIAdapterStatus adapterStatus;
42 IOReturn ioReturnCode;
43}
44adapterReturnCodes[] =
45{
46 { kSCSIAdapterStatusSuccess, kIOReturnSuccess },
47 { kSCSIAdapterStatusProtocolError, kIOReturnDeviceError },
48 { kSCSIAdapterStatusSelectionTimeout, kIOReturnNotResponding },
49 { kSCSIAdapterStatusMsgReject, kIOReturnUnsupported },
50 { kSCSIAdapterStatusParityError, kIOReturnIOError },
51 { kSCSIAdapterStatusOverrun, kIOReturnOverrun }
52};
53
54#define kNumAdapterReturnCodes (sizeof(adapterReturnCodes)/sizeof(adapterReturnCodes[0]))
55
56static struct statusReturnCodes
57{
58 UInt32 scsiStatus;
59 IOReturn ioReturnCode;
60}
61statusReturnCodes[] =
62{
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 }
72};
73
74#define kNumStatusReturnCodes (sizeof(statusReturnCodes)/sizeof(statusReturnCodes[0]))
75
76
77IOSCSIDevice *IOSCSIParallelCommand::getDevice(IOSCSIDevice *)
78{
79 return (IOSCSIDevice *)getDevice(kIOSCSIParallelDevice);
80}
81
82IOSCSIParallelDevice *IOSCSIParallelCommand::getDevice(IOSCSIParallelDevice *)
83{
84 return device;
85}
86
87
88void *IOSCSIParallelCommand::getClientData()
89{
90 return clientData;
91}
92
93void *IOSCSIParallelCommand::getCommandData()
94{
95 return commandPrivateData;
96}
97
98UInt32 IOSCSIParallelCommand::getCmdType()
99{
100 return cmdType;
101}
102
103IOSCSIParallelCommand *IOSCSIParallelCommand::getOriginalCmd()
104{
105 return origCommand;
106}
107
108UInt32 IOSCSIParallelCommand::getSequenceNumber()
109{
110 return sequenceNumber;
111}
112
113void IOSCSIParallelCommand::getTargetLun( SCSITargetLun *forTargetLun )
114{
115 if ( device )
116 {
117 *forTargetLun = device->targetLun;
118 }
119 else
120 {
121 bzero( forTargetLun, sizeof( SCSITargetLun ) );
122 }
123}
124
125
126
127void IOSCSIParallelCommand::setTimeout( UInt32 timeoutMS )
128{
129 timeout = timeoutMS;
130}
131
132UInt32 IOSCSIParallelCommand::getTimeout()
133{
134 return timeout;
135}
136
137void IOSCSIParallelCommand::setResults( SCSIResults *srcResults )
138{
139 setResults( srcResults, (SCSINegotiationResults *)0 );
140}
141
142void IOSCSIParallelCommand::setResults( SCSIResults *srcResults, SCSINegotiationResults *negotiationResult )
143{
144 SCSICommandType cmdType;
145
146 if ( srcResults != 0 )
147 {
148 results = *srcResults;
149
150 cmdType = (SCSICommandType) getCmdType();
151
152 while ( results.returnCode == kIOReturnSuccess )
153 {
154 switch ( cmdType )
155 {
156 case kSCSICommandExecute:
157 case kSCSICommandReqSense:
158 case kSCSICommandAbort:
159 case kSCSICommandAbortAll:
160 case kSCSICommandDeviceReset:
161 if ( results.adapterStatus != kSCSIAdapterStatusSuccess )
162 {
163 results.returnCode = adapterStatusToIOReturnCode( results.adapterStatus );
164 }
165 break;
166
167 default:
168 ;
169 }
170
171 if ( results.returnCode != kIOReturnSuccess ) break;
172
173 switch ( cmdType )
174 {
175 case kSCSICommandExecute:
176 case kSCSICommandReqSense:
177 results.returnCode = scsiStatusToIOReturnCode( results.scsiStatus );
178
179 if ( results.returnCode != kIOReturnSuccess ) break;
180
181 if ( results.bytesTransferred < xferCount )
182 {
183 results.returnCode = kIOReturnUnderrun;
184 }
185 break;
186
187 default:
188 ;
189 }
190
191 break;
192 }
193 }
194
195 if ( negotiationResult != 0 )
196 {
197 device->target->negotiationResult = *negotiationResult;
198 }
199}
200
201IOReturn IOSCSIParallelCommand::adapterStatusToIOReturnCode( SCSIAdapterStatus adapterStatus )
202{
203 UInt32 i;
204
205 for ( i=0; i < kNumAdapterReturnCodes; i++ )
206 {
207 if ( adapterReturnCodes[i].adapterStatus == adapterStatus )
208 {
209 return adapterReturnCodes[i].ioReturnCode;
210 }
211 }
212 return kIOReturnError;
213}
214
215IOReturn IOSCSIParallelCommand::scsiStatusToIOReturnCode( UInt8 scsiStatus )
216{
217 UInt32 i;
218
219 for ( i=0; i < kNumStatusReturnCodes; i++ )
220 {
221 if ( statusReturnCodes[i].scsiStatus == scsiStatus )
222 {
223 return statusReturnCodes[i].ioReturnCode;
224 }
225 }
226 return kIOReturnError;
227}
228
229IOReturn IOSCSIParallelCommand::getResults( SCSIResults *dstResults )
230{
231 if ( dstResults != 0 )
232 {
233 *dstResults = results;
234 }
235
236 return results.returnCode;
237}
238
239void IOSCSIParallelCommand::setQueueInfo( UInt32 forQueueType, UInt32 forQueuePosition )
240{
241 queueType = forQueueType;
242 queuePosition = forQueuePosition;
243}
244
245void IOSCSIParallelCommand::getQueueInfo( UInt32 *forQueueType, UInt32 *forQueuePosition = 0 )
246{
247 if ( forQueueType != 0 ) *forQueueType = queueType;
248 if ( forQueuePosition != 0 ) *forQueuePosition = queuePosition;
249}
250
251void IOSCSIParallelCommand::setPointers( IOMemoryDescriptor *clientDesc, UInt32 transferCount, bool isWrite, bool isSense = false )
252{
253 if ( isSense == false )
254 {
255 xferDesc = clientDesc;
256 xferCount = transferCount;
257 xferDirection = isWrite;
258 }
259 else
260 {
261 senseData = clientDesc;
262 senseLength = transferCount;
263 }
264}
265
266void IOSCSIParallelCommand::getPointers( IOMemoryDescriptor **clientDesc, UInt32 *transferCount, bool *isWrite, bool isSense = false )
267{
268 if ( clientDesc != NULL )
269 {
270 *clientDesc = (isSense == false) ? xferDesc : senseData;
271 }
272
273 if ( transferCount != NULL )
274 {
275 *transferCount = (isSense == false) ? xferCount : senseLength;
276 }
277
278 if ( isWrite != NULL )
279 {
280 *isWrite = (isSense == false) ? xferDirection : false;
281 }
282}
283
284void IOSCSIParallelCommand::setCDB( SCSICDBInfo *clientSCSICmd )
285{
286 scsiCmd = *clientSCSICmd;
287}
288
289void IOSCSIParallelCommand::getCDB( SCSICDBInfo *clientSCSICmd )
290{
291 *clientSCSICmd = scsiCmd;
292}
293
294void IOSCSIParallelCommand::setCallback( void *clientTarget, CallbackFn clientSCSIDoneFn, void *clientRefcon )
295{
296 completionInfo.async.target = clientTarget;
297 completionInfo.async.callback = clientSCSIDoneFn;
298 completionInfo.async.refcon = clientRefcon;
299}
300
301bool IOSCSIParallelCommand::execute( UInt32 *cmdSequenceNumber )
302{
303 bool isSync;
304
305 do
306 {
307 sequenceNumber = OSIncrementAtomic( (SInt32 *)&controller->sequenceNumber );
308 }
309 while ( sequenceNumber == 0 );
310
311 if ( cmdSequenceNumber != 0 )
312 {
313 *cmdSequenceNumber = sequenceNumber;
314 }
315
316 list = (queue_head_t *)device->deviceGate;
317
318 isSync = (completionInfo.async.callback == 0);
319
320 if ( isSync )
321 {
322 completionInfo.sync.lock = IOSyncer::create();
323 }
324
325 device->submitCommand( kSCSICommandExecute, this );
326
327 if ( isSync )
328 {
329 completionInfo.sync.lock->wait();
330 }
331
332 return true;
333
334}
335
336void IOSCSIParallelCommand::abort( UInt32 sequenceNumber )
337{
338 device->submitCommand( kSCSICommandAbort, this, sequenceNumber );
339}
340
341void IOSCSIParallelCommand::complete()
342{
343 if ( device )
344 {
345 device->completeCommand( this );
346 }
347 else
348 {
349 controller->completeCommand( this );
350 }
351}
352
353/*------------------- Generic CDB Interface -----------------------------------------------*/
354
355void IOSCSIParallelCommand::getCDB( CDBInfo *cdbInfo )
356{
357 SCSICDBInfo scsiCDBInfo;
358
359 bzero( cdbInfo, sizeof(CDBInfo) );
360
361 getCDB( &scsiCDBInfo );
362 cdbInfo->cdb = scsiCDBInfo.cdb;
363 cdbInfo->cdbLength = scsiCDBInfo.cdbLength;
364}
365
366void IOSCSIParallelCommand::setCDB( CDBInfo *cdbInfo )
367{
368 SCSICDBInfo scsiCDBInfo;
369
370 bzero( &scsiCDBInfo, sizeof(SCSICDBInfo) );
371
372 scsiCDBInfo.cdbLength = cdbInfo->cdbLength;
373 scsiCDBInfo.cdb = cdbInfo->cdb;
374 setCDB( &scsiCDBInfo );
375}
376
377IOReturn IOSCSIParallelCommand::getResults( CDBResults *cdbResults )
378{
379 SCSIResults scsiResults;
380 IOReturn rc;
381
382 rc = getResults( &scsiResults );
383
384 if ( cdbResults != 0 )
385 {
386 bzero( cdbResults, sizeof(CDBResults) );
387
388 cdbResults->returnCode = scsiResults.returnCode;
389 cdbResults->bytesTransferred = scsiResults.bytesTransferred;
390 cdbResults->requestSenseDone = scsiResults.requestSenseDone;
391 cdbResults->requestSenseLength = scsiResults.requestSenseLength;
392 }
393
394 return rc;
395}
396
397
398IOCDBDevice *IOSCSIParallelCommand::getDevice( IOCDBDevice * )
399{
400 return (IOCDBDevice *)device;
401}
402
403
404void IOSCSIParallelCommand::zeroCommand()
405{
406 cmdType = kSCSICommandNone;
407// controller = <same-as-before>;
408// device = <same-as-before>;
409 list = 0;
410 bzero(&nextCommand, sizeof(nextCommand));
411 bzero(&scsiCmd, sizeof(scsiCmd));
412 bzero(&results, sizeof(results));
413 timeout = 0;
414 timer = 0;
415 queueType = 0;
416 queuePosition = 0;
417 xferDesc = 0;
418 xferCount = 0;
419 xferDirection = 0;
420 senseLength = 0;
421 senseData = 0;
422 origCommand = 0;
423 bzero(&completionInfo, sizeof(completionInfo));
0b4e3aa0
A
424// if (dataArea && dataSize)
425// bzero( dataArea, dataSize );
1c79356b
A
426// commandPrivateData = <same-as-before>;
427// clientData = <same-as-before>;
428 sequenceNumber = 0;
429}