]> git.saurik.com Git - apple/xnu.git/blame_incremental - iokit/Families/IOATAStandard/IOATAStandardCommand.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOATAStandard / IOATAStandardCommand.cpp
... / ...
CommitLineData
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
36OSDefineMetaClassAndStructors( IOATAStandardCommand, IOATACommand )
37OSDefineMetaClassAndAbstractStructors( IOATACommand, IOCDBCommand )
38
39IOATADevice *IOATAStandardCommand::getDevice(IOATADevice *)
40{
41 return (IOATADevice *)device;
42}
43
44IOATAStandardDevice *IOATAStandardCommand::getDevice(IOATAStandardDevice *)
45{
46 return device;
47}
48
49void *IOATAStandardCommand::getClientData()
50{
51 return clientData;
52}
53
54void *IOATAStandardCommand::getCommandData()
55{
56 return commandPrivateData;
57}
58
59UInt32 IOATAStandardCommand::getCmdType()
60{
61 return cmdType;
62}
63
64IOATAStandardCommand *IOATAStandardCommand::getOriginalCmd()
65{
66 return origCommand;
67}
68
69UInt32 IOATAStandardCommand::getSequenceNumber()
70{
71 return sequenceNumber;
72}
73
74ATAUnit IOATAStandardCommand::getUnit()
75{
76 return device->unit;
77}
78
79void IOATAStandardCommand::setTaskfile( ATATaskfile *srcTaskfile )
80{
81 taskfile = *srcTaskfile;
82}
83
84void IOATAStandardCommand::getTaskfile( ATATaskfile *dstTaskfile )
85{
86 *dstTaskfile = taskfile;
87}
88
89UInt32 IOATAStandardCommand::getFlags()
90{
91 return taskfile.flags;
92}
93
94ATAProtocol IOATAStandardCommand::getProtocol()
95{
96 return taskfile.protocol;
97}
98
99UInt32 IOATAStandardCommand::getResultMask()
100{
101 return taskfile.resultmask;
102}
103
104
105void IOATAStandardCommand::setTimeout( UInt32 timeoutMS )
106{
107 timeout = timeoutMS;
108}
109
110UInt32 IOATAStandardCommand::getTimeout()
111{
112 return timeout;
113}
114
115
116void 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
132IOReturn IOATAStandardCommand::getResults( ATAResults *dstResults )
133{
134 if ( dstResults != 0 )
135 {
136 *dstResults = results;
137 }
138
139 return results.returnCode;
140}
141
142void IOATAStandardCommand::setQueueInfo( UInt32 forQueueType, UInt32 forQueuePosition )
143{
144 queueType = forQueueType;
145 queuePosition = forQueuePosition;
146}
147
148void IOATAStandardCommand::getQueueInfo( UInt32 *forQueueType, UInt32 *forQueuePosition = 0 )
149{
150 if ( forQueueType != 0 ) *forQueueType = queueType;
151 if ( forQueuePosition != 0 ) *forQueuePosition = queuePosition;
152}
153
154void 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
169void 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
187void IOATAStandardCommand::setCDB( ATACDBInfo *clientATACmd )
188{
189 ataCmd = *clientATACmd;
190}
191
192void IOATAStandardCommand::getCDB( ATACDBInfo *clientATACmd )
193{
194 *clientATACmd = ataCmd;
195}
196
197void 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
204bool 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
239void IOATAStandardCommand::abort( UInt32 sequenceNumber )
240{
241 device->submitCommand( kATACommandAbort, this, sequenceNumber );
242}
243
244void 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
258void 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
269void 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
319IOReturn 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
340IOCDBDevice *IOATAStandardCommand::getDevice( IOCDBDevice * )
341{
342 return (IOCDBDevice *)device;
343}