]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOATAStandard/IOATAStandardCommand.cpp
xnu-201.42.3.tar.gz
[apple/xnu.git] / iokit / Families / IOATAStandard / IOATAStandardCommand.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 * 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 }