]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOSCSIParallel/IOSCSIParallelCommand.cpp
bff8be4bc30e7ec3429e370a8a7450c63f3979fc
[apple/xnu.git] / iokit / Families / IOSCSIParallel / IOSCSIParallelCommand.cpp
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
35 OSDefineMetaClassAndStructors( IOSCSIParallelCommand, IOSCSICommand )
36 OSDefineMetaClassAndAbstractStructors( IOSCSICommand, IOCDBCommand )
37 OSDefineMetaClassAndAbstractStructors( IOCDBCommand, IOCommand )
38
39 static struct adapterReturnCodes
40 {
41 SCSIAdapterStatus adapterStatus;
42 IOReturn ioReturnCode;
43 }
44 adapterReturnCodes[] =
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
56 static struct statusReturnCodes
57 {
58 UInt32 scsiStatus;
59 IOReturn ioReturnCode;
60 }
61 statusReturnCodes[] =
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
77 IOSCSIDevice *IOSCSIParallelCommand::getDevice(IOSCSIDevice *)
78 {
79 return (IOSCSIDevice *)getDevice(kIOSCSIParallelDevice);
80 }
81
82 IOSCSIParallelDevice *IOSCSIParallelCommand::getDevice(IOSCSIParallelDevice *)
83 {
84 return device;
85 }
86
87
88 void *IOSCSIParallelCommand::getClientData()
89 {
90 return clientData;
91 }
92
93 void *IOSCSIParallelCommand::getCommandData()
94 {
95 return commandPrivateData;
96 }
97
98 UInt32 IOSCSIParallelCommand::getCmdType()
99 {
100 return cmdType;
101 }
102
103 IOSCSIParallelCommand *IOSCSIParallelCommand::getOriginalCmd()
104 {
105 return origCommand;
106 }
107
108 UInt32 IOSCSIParallelCommand::getSequenceNumber()
109 {
110 return sequenceNumber;
111 }
112
113 void 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
127 void IOSCSIParallelCommand::setTimeout( UInt32 timeoutMS )
128 {
129 timeout = timeoutMS;
130 }
131
132 UInt32 IOSCSIParallelCommand::getTimeout()
133 {
134 return timeout;
135 }
136
137 void IOSCSIParallelCommand::setResults( SCSIResults *srcResults )
138 {
139 setResults( srcResults, (SCSINegotiationResults *)0 );
140 }
141
142 void 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
201 IOReturn 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
215 IOReturn 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
229 IOReturn IOSCSIParallelCommand::getResults( SCSIResults *dstResults )
230 {
231 if ( dstResults != 0 )
232 {
233 *dstResults = results;
234 }
235
236 return results.returnCode;
237 }
238
239 void IOSCSIParallelCommand::setQueueInfo( UInt32 forQueueType, UInt32 forQueuePosition )
240 {
241 queueType = forQueueType;
242 queuePosition = forQueuePosition;
243 }
244
245 void IOSCSIParallelCommand::getQueueInfo( UInt32 *forQueueType, UInt32 *forQueuePosition = 0 )
246 {
247 if ( forQueueType != 0 ) *forQueueType = queueType;
248 if ( forQueuePosition != 0 ) *forQueuePosition = queuePosition;
249 }
250
251 void 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
266 void 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
284 void IOSCSIParallelCommand::setCDB( SCSICDBInfo *clientSCSICmd )
285 {
286 scsiCmd = *clientSCSICmd;
287 }
288
289 void IOSCSIParallelCommand::getCDB( SCSICDBInfo *clientSCSICmd )
290 {
291 *clientSCSICmd = scsiCmd;
292 }
293
294 void 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
301 bool 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
336 void IOSCSIParallelCommand::abort( UInt32 sequenceNumber )
337 {
338 device->submitCommand( kSCSICommandAbort, this, sequenceNumber );
339 }
340
341 void 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
355 void 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
366 void 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
377 IOReturn 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
398 IOCDBDevice *IOSCSIParallelCommand::getDevice( IOCDBDevice * )
399 {
400 return (IOCDBDevice *)device;
401 }
402
403
404 void 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));
424 if (dataArea && dataSize)
425 bzero( dataArea, dataSize );
426 // commandPrivateData = <same-as-before>;
427 // clientData = <same-as-before>;
428 sequenceNumber = 0;
429 }