]>
Commit | Line | Data |
---|---|---|
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 | * IOATAStandardCommand.cpp | |
25 | * | |
26 | */ | |
27 | ||
28 | #include <IOKit/IOSyncer.h> | |
29 | ||
30 | #include <IOKit/ata/IOATAStandardInterface.h> | |
31 | #include <libkern/OSAtomic.h> | |
32 | ||
33 | #undef super | |
34 | #define super IOATACommand | |
35 | ||
36 | OSDefineMetaClassAndStructors( IOATAStandardCommand, IOATACommand ) | |
37 | OSDefineMetaClassAndAbstractStructors( IOATACommand, IOCDBCommand ) | |
38 | ||
39 | IOATADevice *IOATAStandardCommand::getDevice(IOATADevice *) | |
40 | { | |
41 | return (IOATADevice *)device; | |
42 | } | |
43 | ||
44 | IOATAStandardDevice *IOATAStandardCommand::getDevice(IOATAStandardDevice *) | |
45 | { | |
46 | return device; | |
47 | } | |
48 | ||
49 | void *IOATAStandardCommand::getClientData() | |
50 | { | |
51 | return clientData; | |
52 | } | |
53 | ||
54 | void *IOATAStandardCommand::getCommandData() | |
55 | { | |
56 | return commandPrivateData; | |
57 | } | |
58 | ||
59 | UInt32 IOATAStandardCommand::getCmdType() | |
60 | { | |
61 | return cmdType; | |
62 | } | |
63 | ||
64 | IOATAStandardCommand *IOATAStandardCommand::getOriginalCmd() | |
65 | { | |
66 | return origCommand; | |
67 | } | |
68 | ||
69 | UInt32 IOATAStandardCommand::getSequenceNumber() | |
70 | { | |
71 | return sequenceNumber; | |
72 | } | |
73 | ||
74 | ATAUnit IOATAStandardCommand::getUnit() | |
75 | { | |
76 | return device->unit; | |
77 | } | |
78 | ||
79 | void IOATAStandardCommand::setTaskfile( ATATaskfile *srcTaskfile ) | |
80 | { | |
81 | taskfile = *srcTaskfile; | |
82 | } | |
83 | ||
84 | void IOATAStandardCommand::getTaskfile( ATATaskfile *dstTaskfile ) | |
85 | { | |
86 | *dstTaskfile = taskfile; | |
87 | } | |
88 | ||
89 | UInt32 IOATAStandardCommand::getFlags() | |
90 | { | |
91 | return taskfile.flags; | |
92 | } | |
93 | ||
94 | ATAProtocol IOATAStandardCommand::getProtocol() | |
95 | { | |
96 | return taskfile.protocol; | |
97 | } | |
98 | ||
99 | UInt32 IOATAStandardCommand::getResultMask() | |
100 | { | |
101 | return taskfile.resultmask; | |
102 | } | |
103 | ||
104 | ||
105 | void IOATAStandardCommand::setTimeout( UInt32 timeoutMS ) | |
106 | { | |
107 | timeout = timeoutMS; | |
108 | } | |
109 | ||
110 | UInt32 IOATAStandardCommand::getTimeout() | |
111 | { | |
112 | return timeout; | |
113 | } | |
114 | ||
115 | ||
116 | void IOATAStandardCommand::setResults( ATAResults *srcResults ) | |
117 | { | |
118 | results = *srcResults; | |
119 | ||
120 | if ( getCmdType() == kATACommandExecute ) | |
121 | { | |
122 | if ( results.bytesTransferred < xferCount ) | |
123 | { | |
124 | if ( results.returnCode == kIOReturnSuccess ) | |
125 | { | |
126 | results.returnCode = kIOReturnUnderrun; | |
127 | } | |
128 | } | |
129 | } | |
130 | } | |
131 | ||
132 | IOReturn IOATAStandardCommand::getResults( ATAResults *dstResults ) | |
133 | { | |
134 | if ( dstResults != 0 ) | |
135 | { | |
136 | *dstResults = results; | |
137 | } | |
138 | ||
139 | return results.returnCode; | |
140 | } | |
141 | ||
142 | void IOATAStandardCommand::setQueueInfo( UInt32 forQueueType, UInt32 forQueuePosition ) | |
143 | { | |
144 | queueType = forQueueType; | |
145 | queuePosition = forQueuePosition; | |
146 | } | |
147 | ||
148 | void IOATAStandardCommand::getQueueInfo( UInt32 *forQueueType, UInt32 *forQueuePosition = 0 ) | |
149 | { | |
150 | if ( forQueueType != 0 ) *forQueueType = queueType; | |
151 | if ( forQueuePosition != 0 ) *forQueuePosition = queuePosition; | |
152 | } | |
153 | ||
154 | void IOATAStandardCommand::setPointers( IOMemoryDescriptor *clientDesc, UInt32 transferCount, bool isWrite, bool isSense = false ) | |
155 | { | |
156 | if ( isSense == false ) | |
157 | { | |
158 | xferDesc = clientDesc; | |
159 | xferCount = transferCount; | |
160 | xferDirection = isWrite; | |
161 | } | |
162 | else | |
163 | { | |
164 | senseData = clientDesc; | |
165 | senseLength = transferCount; | |
166 | } | |
167 | } | |
168 | ||
169 | void IOATAStandardCommand::getPointers( IOMemoryDescriptor **clientDesc, UInt32 *transferCount, bool *isWrite, bool isSense = false ) | |
170 | { | |
171 | if ( clientDesc != NULL ) | |
172 | { | |
173 | *clientDesc = (isSense == false) ? xferDesc : senseData; | |
174 | } | |
175 | ||
176 | if ( transferCount != NULL ) | |
177 | { | |
178 | *transferCount = (isSense == false) ? xferCount : senseLength; | |
179 | } | |
180 | ||
181 | if ( isWrite != NULL ) | |
182 | { | |
183 | *isWrite = (isSense == false) ? xferDirection : false; | |
184 | } | |
185 | } | |
186 | ||
187 | void IOATAStandardCommand::setCDB( ATACDBInfo *clientATACmd ) | |
188 | { | |
189 | ataCmd = *clientATACmd; | |
190 | } | |
191 | ||
192 | void IOATAStandardCommand::getCDB( ATACDBInfo *clientATACmd ) | |
193 | { | |
194 | *clientATACmd = ataCmd; | |
195 | } | |
196 | ||
197 | void IOATAStandardCommand::setCallback( void *clientTarget, CallbackFn clientATADoneFn, void *clientRefcon ) | |
198 | { | |
199 | completionInfo.async.target = clientTarget; | |
200 | completionInfo.async.callback = clientATADoneFn; | |
201 | completionInfo.async.refcon = clientRefcon; | |
202 | } | |
203 | ||
204 | bool IOATAStandardCommand::execute( UInt32 *cmdSequenceNumber ) | |
205 | { | |
206 | bool isSync; | |
207 | ||
208 | do | |
209 | { | |
210 | sequenceNumber = OSIncrementAtomic( (SInt32 *)&controller->sequenceNumber ); | |
211 | } | |
212 | while ( sequenceNumber == 0 ); | |
213 | ||
214 | if ( cmdSequenceNumber != 0 ) | |
215 | { | |
216 | *cmdSequenceNumber = sequenceNumber; | |
217 | } | |
218 | ||
219 | list = (queue_head_t *)device->deviceGate; | |
220 | ||
221 | isSync = (completionInfo.async.callback == 0); | |
222 | ||
223 | if ( isSync ) | |
224 | { | |
225 | completionInfo.sync.lock = IOSyncer::create(); | |
226 | } | |
227 | ||
228 | device->submitCommand( kATACommandExecute, this ); | |
229 | ||
230 | if ( isSync ) | |
231 | { | |
232 | completionInfo.sync.lock->wait(); | |
233 | } | |
234 | ||
235 | return true; | |
236 | ||
237 | } | |
238 | ||
239 | void IOATAStandardCommand::abort( UInt32 sequenceNumber ) | |
240 | { | |
241 | device->submitCommand( kATACommandAbort, this, sequenceNumber ); | |
242 | } | |
243 | ||
244 | void IOATAStandardCommand::complete() | |
245 | { | |
246 | if ( device ) | |
247 | { | |
248 | device->completeCommand( this ); | |
249 | } | |
250 | else | |
251 | { | |
252 | controller->completeCommand( this ); | |
253 | } | |
254 | } | |
255 | ||
256 | /*------------------- Generic CDB Interface -----------------------------------------------*/ | |
257 | ||
258 | void IOATAStandardCommand::getCDB( CDBInfo *cdbInfo ) | |
259 | { | |
260 | ATACDBInfo ataCDBInfo; | |
261 | ||
262 | bzero( cdbInfo, sizeof(CDBInfo) ); | |
263 | ||
264 | getCDB( &ataCDBInfo ); | |
265 | cdbInfo->cdb = ataCDBInfo.cdb; | |
266 | cdbInfo->cdbLength = ataCDBInfo.cdbLength; | |
267 | } | |
268 | ||
269 | void IOATAStandardCommand::setCDB( CDBInfo *cdbInfo ) | |
270 | { | |
271 | IOATAStandardDevice *ataDevice; | |
272 | ATATimingProtocol ataTimingProtocol; | |
273 | ATACDBInfo ataCDBInfo; | |
274 | ATATaskfile ataTaskfile; | |
275 | ||
276 | ataDevice = getDevice(kIOATAStandardDevice); | |
277 | ||
278 | if ( ataDevice->getDeviceType() != kATADeviceATAPI ) | |
279 | { | |
280 | return; | |
281 | } | |
282 | ||
283 | bzero( &ataTaskfile, sizeof(ataTaskfile) ); | |
284 | ||
285 | ataDevice->getTimingSelected( &ataTimingProtocol ); | |
286 | ||
287 | ataTaskfile.regmask = ATARegtoMask(kATARegATAPIDeviceSelect) | |
288 | | ATARegtoMask(kATARegATAPICommand) | |
289 | | ATARegtoMask(kATARegATAPIByteCountLow) | |
290 | | ATARegtoMask(kATARegATAPIByteCountHigh) | |
291 | | ATARegtoMask(kATARegATAPIFeatures); | |
292 | ||
293 | ataTaskfile.ataRegs[kATARegATAPICommand] = kATACommandATAPIPacket; | |
294 | ataTaskfile.ataRegs[kATARegATAPIDeviceSelect] = kATAModeLBA | (getUnit() << 4); | |
295 | ||
296 | if ( ataTimingProtocol & ~kATATimingPIO ) | |
297 | { | |
298 | ataTaskfile.protocol = kATAProtocolATAPIDMA; | |
299 | ataTaskfile.ataRegs[kATARegATAPIFeatures] = 0x01; | |
300 | } | |
301 | else | |
302 | { | |
303 | ataTaskfile.protocol = kATAProtocolATAPIPIO; | |
304 | ataTaskfile.ataRegs[kATARegATAPIByteCountLow] = 0xfe; | |
305 | ataTaskfile.ataRegs[kATARegATAPIByteCountHigh] = 0xff; | |
306 | } | |
307 | ||
308 | setTaskfile( &ataTaskfile ); | |
309 | ||
310 | bzero( &ataCDBInfo, sizeof(ATACDBInfo) ); | |
311 | ||
312 | ataCDBInfo.cdbLength = cdbInfo->cdbLength; | |
313 | ataCDBInfo.cdb = cdbInfo->cdb; | |
314 | setCDB( &ataCDBInfo ); | |
315 | ||
316 | setQueueInfo(); | |
317 | } | |
318 | ||
319 | IOReturn IOATAStandardCommand::getResults( CDBResults *cdbResults ) | |
320 | { | |
321 | ATAResults ataResults; | |
322 | IOReturn rc; | |
323 | ||
324 | rc = getResults( &ataResults ); | |
325 | ||
326 | if ( cdbResults != 0 ) | |
327 | { | |
328 | bzero( cdbResults, sizeof(CDBResults) ); | |
329 | ||
330 | cdbResults->returnCode = ataResults.returnCode; | |
331 | cdbResults->bytesTransferred = ataResults.bytesTransferred; | |
332 | cdbResults->requestSenseDone = ataResults.returnCode; | |
333 | cdbResults->requestSenseLength = ataResults.requestSenseLength; | |
334 | } | |
335 | ||
336 | return rc; | |
337 | } | |
338 | ||
339 | ||
340 | IOCDBDevice *IOATAStandardCommand::getDevice( IOCDBDevice * ) | |
341 | { | |
342 | return (IOCDBDevice *)device; | |
343 | } |