]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOATAStandard/IOATAStandardDriver.cpp
054405e67a667bb963a52fea231d02f6b54fa27e
[apple/xnu.git] / iokit / Families / IOATAStandard / IOATAStandardDriver.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 * IOATAStandardDriver.cpp
25 *
26 */
27 #include <IOKit/ata/IOATAStandardInterface.h>
28
29 #undef super
30 #define super IOATAStandardController
31
32 OSDefineMetaClass( IOATAStandardDriver, IOATAStandardController );
33 OSDefineAbstractStructors( IOATAStandardDriver, IOATAStandardController );
34
35 #if 0
36 static UInt32 dropInt=0;
37 #endif
38
39 /*
40 *
41 *
42 */
43 void IOATAStandardDriver::executeCommand( IOATAStandardCommand *cmd )
44 {
45 IOATAStandardDevice *newDevice;
46 ATAProtocol newProtocol;
47 ATATimingProtocol timingProtocol;
48 ATAResults results;
49
50 newDevice = cmd->getDevice(kIOATAStandardDevice);
51 newProtocol = cmd->getProtocol();
52
53 #if 0
54 IOLog("IOATAStandardDriver::%s() - Cmd = %08x Device = %08x Count = %d\n\r",
55 __FUNCTION__, (int) cmd, (int) newDevice, getCommandCount() );
56 #endif
57
58 if ( getCommandCount() > 1 )
59 {
60 if ( currentDevice != newDevice || currentProtocol != newProtocol )
61 {
62 suspendDevice( newDevice );
63 rescheduleCommand( cmd );
64 return;
65 }
66 }
67
68 currentProtocol = newProtocol;
69
70 if ( currentDevice != newDevice )
71 {
72 newDeviceSelected( newDevice );
73 currentDevice = newDevice;
74 }
75
76 if ( (cmd->getFlags() & kATACmdFlagTimingChanged) != 0 )
77 {
78 currentDevice->getTimingSelected( &timingProtocol );
79 selectTiming( currentDevice->getUnit(), timingProtocol );
80 newDeviceSelected( newDevice );
81 }
82
83 bzero( &results, sizeof(ATAResults) );
84 cmd->setResults( &results );
85
86 switch ( currentProtocol )
87 {
88 case kATAProtocolSetRegs:
89 doProtocolSetRegs( cmd );
90 break;
91
92 case kATAProtocolPIO:
93 doATAProtocolPio( cmd );
94 break;
95
96 case kATAProtocolDMA:
97 doATAProtocolDma( cmd );
98 break;
99
100 case kATAProtocolDMAQueued:
101 doATAProtocolDmaQueued( cmd );
102 break;
103
104 case kATAProtocolATAPIPIO:
105 doATAPIProtocolPio( cmd );
106 break;
107
108 case kATAProtocolATAPIDMA:
109 doATAPIProtocolDma( cmd );
110 break;
111
112 default:
113 doProtocolNotSupported( cmd );
114 break;
115 }
116 }
117
118
119 /*
120 *
121 *
122 */
123 void IOATAStandardDriver::resetCommand( IOATAStandardCommand *cmd )
124 {
125
126 resetDma();
127 dmaActive = false;
128
129 currentProtocol = kATAProtocolNone;
130 currentDevice = 0;
131 doATAReset( cmd );
132 }
133
134 /*
135 *
136 *
137 */
138 void IOATAStandardDriver::abortCommand( IOATAStandardCommand *ataCmd )
139 {
140 resetStarted();
141 doATAReset( ataCmd );
142 }
143
144 /*
145 *
146 *
147 */
148 void IOATAStandardDriver::cancelCommand( IOATAStandardCommand *ataCmd )
149 {
150 ATAResults results;
151 IOATAStandardCommand *origCmd;
152
153 origCmd = ataCmd->getOriginalCmd();
154 if ( origCmd != 0 )
155 {
156 completeCmd( origCmd );
157 }
158
159 bzero( &results, sizeof(ATAResults) );
160 ataCmd->setResults( &results );
161 completeCmd( ataCmd );
162 }
163
164
165 /*
166 *
167 *
168 */
169 void IOATAStandardDriver::interruptOccurred()
170 {
171 #if 0
172 if ( dropInt++ > 20 )
173 {
174 UInt32 status;
175
176 IOLog("IOATAStandardDriver::%s() - Dropping interrupt\n\r", __FUNCTION__ );
177 status = readATAReg( kATARegStatus );
178 dropInt = 0;
179 return;
180 }
181 #endif
182
183 if ( currentDevice == 0 )
184 {
185 IOLog( "IOATAStandardDriver::interruptOccurred - Spurious interrupt - ATA Status = %04lx\n\r", readATAReg( kATARegStatus ) );
186 return;
187 }
188
189 switch ( currentProtocol )
190 {
191 case kATAProtocolPIO:
192 processATAPioInt();
193 break;
194
195 case kATAProtocolDMA:
196 processATADmaInt();
197 break;
198
199 case kATAProtocolDMAQueued:
200 processATADmaQueuedInt();
201 break;
202
203 case kATAProtocolATAPIPIO:
204 processATAPIPioInt();
205 break;
206
207 case kATAProtocolATAPIDMA:
208 processATAPIDmaInt();
209 break;
210
211 default:
212 IOLog( "IOATAStandardDriver::interruptOccurred - Spurious interrupt - ATA Status = %04lx\n\r", readATAReg( kATARegStatus ) );
213 }
214 }
215
216
217 /*
218 *
219 *
220 */
221 void IOATAStandardDriver::doProtocolNotSupported( IOATAStandardCommand *cmd )
222 {
223 completeCmd( cmd, kATAReturnNotSupported );
224 }
225
226
227 /*
228 *
229 *
230 */
231 void IOATAStandardDriver::completeCmd( IOATAStandardCommand *cmd, ATAReturnCode returnCode, UInt32 bytesTransferred )
232 {
233 updateCmdStatus( cmd, returnCode, bytesTransferred );
234 completeCmd( cmd );
235 }
236
237 /*
238 *
239 *
240 */
241 void IOATAStandardDriver::updateCmdStatus( IOATAStandardCommand *cmd, ATAReturnCode returnCode, UInt32 bytesTransferred )
242 {
243 UInt32 resultmask;
244 UInt32 i;
245 ATAResults result;
246
247 bzero( &result, sizeof(result) );
248
249 resultmask = cmd->getResultMask();
250
251 if ( cmd->getProtocol() != kATAProtocolSetRegs )
252 {
253 if ( waitForStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
254 {
255 if ( returnCode == kATAReturnSuccess )
256 {
257 kprintf("IOATAStandardDriver::updateCmdStatus is going to return kATAReturnBusyError;\n");
258 returnCode = kATAReturnBusyError;
259 }
260 }
261 }
262
263 for ( i=0; resultmask; i++ )
264 {
265 if ( resultmask & 1 )
266 {
267 result.ataRegs[i] = readATAReg( i );
268 }
269 resultmask >>= 1;
270 }
271
272 result.adapterStatus = returnCode;
273 result.bytesTransferred = bytesTransferred;
274 cmd->setResults( &result );
275 }
276
277 /*
278 *
279 *
280 */
281 void IOATAStandardDriver::completeCmd( IOATAStandardCommand *cmd )
282 {
283 IOATAStandardDevice *device;
284 ATAResults ataResult;
285
286 cmd->getResults( &ataResult );
287 ataResult.returnCode = getIOReturnCode( ataResult.adapterStatus );
288 cmd->setResults( &ataResult );
289
290 if ( getCommandCount() == 1 )
291 {
292 currentProtocol = kATAProtocolNone;
293
294 device = selectDevice();
295 if ( device != 0 )
296 {
297 resumeDevice( device );
298 }
299 }
300
301 cmd->complete();
302 }
303
304 /*
305 *
306 *
307 */
308 IOReturn IOATAStandardDriver::getIOReturnCode( ATAReturnCode code )
309 {
310 switch (code)
311 {
312 case kATAReturnSuccess:
313 return kIOReturnSuccess;
314
315 case kATAReturnNotSupported:
316 return kIOReturnUnsupported;
317
318 case kATAReturnNoResource:
319 return kIOReturnNoResources;
320
321 case kATAReturnBusyError:
322 return kIOReturnBusy;
323
324 case kATAReturnInterruptTimeout:
325 return kIOReturnTimeout;
326
327 case kATAReturnRetryPIO:
328 case kATAReturnStatusError:
329 case kATAReturnProtocolError:
330 default:
331 ;
332 }
333 return kIOReturnIOError;
334 }
335
336 /*
337 *
338 *
339 */
340 void IOATAStandardDriver::newDeviceSelected( IOATAStandardDevice * )
341 {
342 }
343
344
345 /*
346 *
347 *
348 */
349 bool IOATAStandardDriver::programDma( IOATAStandardCommand * )
350 {
351 IOLog( "IOATAStandardDriver::%s - Subclass must implement\n\r", __FUNCTION__ );
352 return false;
353 }
354
355
356 /*
357 *
358 *
359 */
360 bool IOATAStandardDriver::startDma( IOATAStandardCommand * )
361 {
362 IOLog( "IOATAStandardDriver::%s - Subclass must implement\n\r", __FUNCTION__ );
363 return false;
364 }
365
366
367 /*
368 *
369 *
370 */
371 bool IOATAStandardDriver::stopDma( IOATAStandardCommand *, UInt32 * )
372 {
373 IOLog( "IOATAStandardDriver::%s - Subclass must implement\n\r", __FUNCTION__ );
374 return false;
375 }
376
377 /*
378 *
379 *
380 */
381 bool IOATAStandardDriver::checkDmaActive()
382 {
383 IOLog( "IOATAStandardDriver::%s - Subclass must implement\n\r", __FUNCTION__ );
384 return false;
385 }
386
387 /*
388 *
389 *
390 */
391 bool IOATAStandardDriver::resetDma()
392 {
393 return false;
394 }
395
396 /*
397 *
398 *
399 */
400 bool IOATAStandardDriver::getProtocolsSupported( ATAProtocol *forProtocol )
401 {
402 *(UInt32 *) forProtocol = ( kATAProtocolSetRegs
403 | kATAProtocolPIO
404 | kATAProtocolDMA
405 | kATAProtocolDMAQueued
406 | kATAProtocolATAPIPIO
407 | kATAProtocolATAPIDMA );
408
409 return true;
410 }
411
412 /*
413 *
414 *
415 */
416 ATAReturnCode IOATAStandardDriver::waitForDRQ( UInt32 timeoutmS )
417 {
418 AbsoluteTime currentTime, endTime;
419 UInt32 status;
420 ATAReturnCode rc = kATAReturnBusyError;
421
422 clock_interval_to_deadline( timeoutmS, 1000000, &endTime );
423 do
424 {
425 status = readATAReg( kATARegStatus );
426 if ( (status & kATAPIStatusBSY) == 0 )
427 {
428 if ( (status & kATAStatusERR) != 0 )
429 {
430 rc = kATAReturnStatusError;
431 break;
432 }
433 if ( (status & kATAStatusDRQ) != 0 )
434 {
435 rc = kATAReturnSuccess;
436 break;
437 }
438 }
439 clock_get_uptime( &currentTime );
440 }
441 while ( CMP_ABSOLUTETIME( &endTime, &currentTime ) > 0 );
442
443 if (rc == kATAReturnBusyError)
444 kprintf("IOATAStandardDriver::waitForDRQ is going to return kATAReturnBusyError;\n");
445
446 return rc;
447 }
448
449
450 /*
451 *
452 *
453 */
454 bool IOATAStandardDriver::waitForStatus( UInt32 statusBitsOn, UInt32 statusBitsOff, UInt32 timeoutmS )
455 {
456 AbsoluteTime currentTime, endTime;
457 UInt32 status;
458
459 clock_interval_to_deadline( timeoutmS, 1000000, &endTime );
460
461 do
462 {
463 status = readATAReg( kATARegStatus );
464
465 if ( (status & statusBitsOn) == statusBitsOn
466 && (status & statusBitsOff) == 0 )
467 {
468 return true;
469 }
470
471 clock_get_uptime( &currentTime );
472
473 } while ( CMP_ABSOLUTETIME( &endTime, &currentTime ) > 0 );
474
475 return false;
476 }
477
478 /*
479 *
480 *
481 */
482 bool IOATAStandardDriver::waitForAltStatus( UInt32 statusBitsOn, UInt32 statusBitsOff, UInt32 timeoutmS )
483 {
484 AbsoluteTime currentTime, endTime;
485 UInt32 status;
486
487 clock_interval_to_deadline( timeoutmS, 1000000, &endTime );
488
489 do
490 {
491 status = readATAReg( kATARegAltStatus );
492
493 if ( (status & statusBitsOn) == statusBitsOn
494 && (status & statusBitsOff) == 0 )
495 {
496 return true;
497 }
498
499 clock_get_uptime( &currentTime );
500
501 } while ( CMP_ABSOLUTETIME( &endTime, &currentTime ) > 0 );
502
503 return false;
504 }
505
506 /*
507 *
508 *
509 */
510 bool IOATAStandardDriver::start (IOService *provider)
511 {
512
513 PMinit(); // initialize superclass variables
514 provider->joinPMtree(this); // attach into the power management hierarchy
515
516 #define number_of_power_states 2
517
518 static IOPMPowerState ourPowerStates[number_of_power_states] = {
519 {1,0,0,0,0,0,0,0,0,0,0,0},
520 {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0}
521 };
522
523
524 // register ourselves with ourself as policy-maker
525 if (pm_vars != NULL)
526 registerPowerDriver(this, ourPowerStates, number_of_power_states);
527
528
529 // We are starting up, so not waking up:
530 wakingUpFromSleep = false;
531
532 if (!super::start (provider))
533 return false;
534
535 return true;
536 }
537
538 /*
539 *
540 *
541 */
542
543 IOReturn IOATAStandardDriver::setPowerState(unsigned long powerStateOrdinal, IOService* whatDevice)
544 {
545 // Do not do anything if the state is inavalid.
546 if (powerStateOrdinal >= 2)
547 return IOPMNoSuchState;
548
549 if ( powerStateOrdinal == 0 )
550 {
551 kprintf("IOATAStandardDriver would be powered off here\n");
552 wakingUpFromSleep = true;
553
554 // Let's pretend we did something:
555 return IOPMAckImplied;
556 }
557
558 if ( ( powerStateOrdinal == 1 ) && ( wakingUpFromSleep ) )
559 {
560 wakingUpFromSleep = false;
561 disableControllerInterrupts();
562 reset();
563 enableControllerInterrupts();
564 return IOPMAckImplied;
565 }
566
567 return IOPMCannotRaisePower;
568 }
569