]>
Commit | Line | Data |
---|---|---|
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 | ||
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)); | |
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 | } |