]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOATAStandard/IOATAStandardController.cpp
3374fbbdd2ff391c8beb891f2b659480118b292d
[apple/xnu.git] / iokit / Families / IOATAStandard / IOATAStandardController.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 * IOATAStandardController.cpp
24 *
25 */
26
27 #include <IOKit/ata/IOATAStandardInterface.h>
28 #include <IOKit/IOSyncer.h>
29
30 #undef super
31 #define super IOService
32
33 OSDefineMetaClass( IOATAStandardController, IOService )
34 OSDefineAbstractStructors( IOATAStandardController, IOService );
35
36 #define round(x,y) (((int)(x) + (y) - 1) & ~((y)-1))
37
38 /*
39 *
40 *
41 */
42 bool IOATAStandardController::start( IOService *forProvider )
43 {
44 provider = forProvider;
45
46 // IOSleep( 15000 );
47
48 if ( provider->open( this ) != true )
49 {
50 return false;
51 }
52
53 if ( createWorkLoop() != true )
54 {
55 return false;
56 }
57
58 if ( configureController() != true )
59 {
60 provider->close( this );
61 return false;
62 }
63
64 if ( scanATABus() != true )
65 {
66 provider->close( this );
67 return false;
68 }
69
70 return true;
71 }
72
73 /*
74 *
75 *
76 *
77 */
78 bool IOATAStandardController::scanATABus()
79 {
80 if ( createDeviceNubs() != true )
81 {
82 return false;
83 }
84
85 timer( timerEvent );
86
87 if ( initTimings() == false )
88 {
89 return false;
90 }
91
92 disableControllerInterrupts();
93
94 if ( reset() != kIOReturnSuccess )
95 {
96 return false;
97 }
98
99 enableControllerInterrupts();
100
101 if ( probeDeviceNubs() != true )
102 {
103 return false;
104 }
105
106 if ( registerDeviceNubs() != true )
107 {
108 return false;
109 }
110
111 return true;
112 }
113
114
115 /*
116 *
117 *
118 *
119 */
120 bool IOATAStandardController::createDeviceNubs()
121 {
122 UInt32 i;
123 IOATAStandardDevice *ataDev;
124
125 for (i = 0; i < controllerInfo.maxDevicesSupported; i++ )
126 {
127 ataDev = targets[i].device = new IOATAStandardDevice;
128
129 if ( ataDev->init( this, i ) != true )
130 {
131 ataDev->release();
132 targets[i].device = NULL;
133 }
134 }
135
136 resetCmd = allocCommand( 0 );
137 resetCmd->cmdType = kATACommandBusReset;
138 resetCmd->setTimeout( kATAResetTimeoutmS );
139 resetCmd->setPointers( 0, 0, false );
140
141 return true;
142 }
143
144 /*
145 *
146 *
147 *
148 */
149 bool IOATAStandardController::probeDeviceNubs()
150 {
151 UInt32 i;
152 IOATAStandardDevice *ataDev;
153
154 for (i = 0; i < controllerInfo.maxDevicesSupported; i++ )
155 {
156 ataDev = targets[i].device;
157 if ( ataDev->probeDeviceType() == kATADeviceNone )
158 {
159 ataDev->release();
160 targets[i].device = NULL;
161 }
162 }
163
164 for (i = 0; i < controllerInfo.maxDevicesSupported; i++ )
165 {
166 ataDev = targets[i].device;
167 if ( ataDev == NULL )
168 {
169 continue;
170 }
171
172 if ( ataDev->probeDevice() != true )
173 {
174 ataDev->release();
175 targets[i].device = NULL;
176 }
177 }
178
179 return true;
180 }
181
182
183 /*
184 *
185 *
186 *
187 */
188 bool IOATAStandardController::registerDeviceNubs()
189 {
190 UInt32 i;
191 IOATAStandardDevice *ataDev;
192
193 for (i = 0; i < controllerInfo.maxDevicesSupported; i++ )
194 {
195 ataDev = targets[i].device;
196 if ( ataDev != NULL )
197 {
198 ataDev->attach( this );
199 ataDev->registerService();
200 }
201 }
202
203 return true;
204 }
205
206 /*
207 *
208 *
209 *
210 */
211 bool IOATAStandardController::initTimings()
212 {
213 ATATiming initPIOTiming;
214
215 initPIOTiming.timingProtocol = kATATimingPIO;
216 initPIOTiming.featureSetting = 0;
217 initPIOTiming.mode = 0;
218 initPIOTiming.minDataAccess = 165;
219 initPIOTiming.minDataCycle = 600;
220 initPIOTiming.minCmdAccess = 290;
221 initPIOTiming.minCmdCycle = 600;
222
223 if ( calculateTiming( 0, &initPIOTiming ) != true )
224 {
225 return false;
226 }
227
228 if ( calculateTiming( 1, &initPIOTiming ) != true )
229 {
230 return false;
231 }
232
233 return true;
234 }
235
236 /*
237 *
238 *
239 *
240 */
241 bool IOATAStandardController::matchNubWithPropertyTable( IOService *nub, OSDictionary *table )
242 {
243 bool rc;
244
245 rc = nub->compareProperty( table, kATAPropertyLocation );
246
247 return rc;
248 }
249
250
251
252 /*
253 *
254 *
255 *
256 */
257 void IOATAStandardController::releaseDevice( IOATAStandardDevice *device )
258 {
259 workLoopRequest( kWorkLoopReleaseDevice, (UInt32) device );
260
261 device->release();
262 }
263
264 /*
265 *
266 *
267 *
268 */
269 bool IOATAStandardController::workLoopRequest( WorkLoopReqType type, UInt32 p1, UInt32 p2, UInt32 p3 )
270 {
271 WorkLoopRequest workLoopReq;
272
273 bzero( &workLoopReq, sizeof(WorkLoopRequest) );
274 workLoopReq.type = type;
275 workLoopReq.sync = IOSyncer::create();
276
277 workLoopReqGate->runCommand( &workLoopReq, (void *)p1, (void *)p2, (void *)p3 );
278
279 workLoopReq.sync->wait();
280
281 return( workLoopReq.rc );
282 }
283
284
285 /*
286 *
287 *
288 *
289 */
290 void IOATAStandardController::workLoopProcessRequest( WorkLoopRequest *workLoopReq, void *p1, void *p2, void *p3 )
291 {
292 bool rc = true;
293 IOATAStandardDevice *device;
294
295 switch ( workLoopReq->type )
296 {
297
298 case kWorkLoopInitDevice:
299 device = (IOATAStandardDevice *) p1;
300 addDevice( device );
301 rc = allocateDevice( device->unit );
302 break;
303
304 case kWorkLoopReleaseDevice:
305 device = (IOATAStandardDevice *) p1;
306 deleteDevice( device );
307 break;
308 }
309
310 workLoopReq->rc = rc;
311 workLoopReq->sync->signal();
312 }
313
314 /*
315 *
316 *
317 *
318 */
319 void IOATAStandardController::addDevice( IOATAStandardDevice *forDevice )
320 {
321 ATAUnit unit;
322
323 unit = forDevice->unit;
324
325 forDevice->target = &targets[unit];
326 targets[unit].device = forDevice;
327 }
328
329 /*
330 *
331 *
332 *
333 */
334 void IOATAStandardController::deleteDevice( IOATAStandardDevice *forDevice )
335 {
336 ATAUnit unit;
337
338 unit = forDevice->unit;
339 targets[unit].device = 0;
340 }
341
342
343 /*
344 *
345 *
346 *
347 */
348 bool IOATAStandardController::allocateDevice( ATAUnit unit )
349 {
350 return true;
351 }
352
353 /*
354 *
355 *
356 *
357 */
358 void IOATAStandardController::deallocateDevice( ATAUnit unit )
359 {
360 }
361
362
363 /*
364 *
365 *
366 *
367 */
368 void *IOATAStandardController::getDeviceData( ATAUnit unit )
369 {
370 IOATAStandardDevice *device;
371
372 device = targets[unit].device;
373
374 if ( device == 0 ) return 0;
375
376 return device->devicePrivateData;
377 }
378
379
380 /*
381 *
382 *
383 *
384 */
385 IOReturn IOATAStandardController::reset()
386 {
387 if ( busResetState != kStateIdle )
388 {
389 return kIOReturnNoResources;
390 }
391
392 busResetState = kStateIssue;
393 dispatchRequest();
394
395 while ( busResetState != kStateIdle )
396 {
397 IOSleep( 100 );
398 }
399
400 return resetCmd->getResults( (ATAResults *)0 );
401 }
402
403 /*
404 *
405 *
406 *
407 */
408 void IOATAStandardController::resetATABus()
409 {
410 if ( busResetState != kStateIssue )
411 {
412 return;
413 }
414
415 busResetState = kStateActive;
416
417 resetStarted();
418
419 resetCommand( resetCmd );
420 }
421
422 /*
423 *
424 *
425 *
426 */
427 void IOATAStandardController::resetStarted()
428 {
429 IOATAStandardDevice *device;
430 UInt32 i;
431
432 for (i=0; i < controllerInfo.maxDevicesSupported; i++ )
433 {
434 device = targets[i].device;
435
436 if ( (device != 0) && (device->client != 0) && (device->abortCmdPending != kATACommandDeviceReset) )
437 {
438 device->client->message( kATAClientMsgBusReset, device );
439 }
440 }
441 }
442
443
444 /*
445 *
446 *
447 *
448 */
449 bool IOATAStandardController::checkBusReset()
450 {
451 if ( busResetState == kStateIdle )
452 {
453 return false;
454 }
455 if ( busResetState == kStateIssue )
456 {
457 resetATABus();
458 }
459 return true;
460 }
461
462
463 /*
464 *
465 *
466 */
467 void IOATAStandardController::timer( IOTimerEventSource * /* timer */ )
468 {
469 UInt32 i;
470 IOATAStandardDevice *device;
471
472
473 if ( disableTimer )
474 {
475 if ( !--disableTimer )
476 {
477 disableTimeoutOccurred();
478 }
479 }
480
481 for (i=0; i < controllerInfo.maxDevicesSupported; i++ )
482 {
483 device = targets[i].device;
484 if ( device != 0 )
485 {
486 device->timer();
487 }
488 }
489
490 timerEvent->setTimeoutMS(kATATimerIntervalmS);
491 }
492
493
494 /*
495 *
496 *
497 *
498 */
499 void IOATAStandardController::completeCommand( IOATAStandardCommand *ataCmd )
500 {
501 switch ( ataCmd->cmdType )
502 {
503 case kATACommandBusReset:
504 busResetState = kStateIdle;
505 resetOccurred();
506 break;
507 default:
508 ;
509 }
510 }
511
512 /*
513 *
514 *
515 *
516 */
517 void IOATAStandardController::resetOccurred()
518 {
519 UInt32 i;
520 IOATAStandardDevice *device;
521
522 for (i=0; i < controllerInfo.maxDevicesSupported; i++ )
523 {
524 device = targets[i].device;
525
526 if ( device == 0 ) continue;
527
528 if ( device->abortCmdPending != kATACommandDeviceReset )
529 {
530 device->resetOccurred( (ATAClientMessage) (kATAClientMsgBusReset | kATAClientMsgDone) );
531 }
532 }
533 }
534
535 /*
536 *
537 *
538 *
539 */
540 bool IOATAStandardController::createWorkLoop()
541 {
542 workLoop = getWorkLoop();
543 if ( workLoop == 0 )
544 {
545 workLoop = new IOWorkLoop;
546 if ( workLoop == 0 )
547 {
548 return false;
549 }
550 }
551
552 if ( workLoop->init() != true )
553 {
554 return false;
555 }
556
557 timerEvent = IOTimerEventSource::timerEventSource( this, (IOTimerEventSource::Action) &IOATAStandardController::timer );
558 if ( timerEvent == NULL )
559 {
560 return false;
561 }
562
563 if ( workLoop->addEventSource( timerEvent ) != kIOReturnSuccess )
564 {
565 return false;
566 }
567
568 timer( timerEvent );
569
570
571 dispatchEvent = IOInterruptEventSource::interruptEventSource( this,
572 (IOInterruptEventAction) &IOATAStandardController::dispatch,
573 0 );
574 if ( dispatchEvent == 0 )
575 {
576 return false;
577 }
578
579 if ( workLoop->addEventSource( dispatchEvent ) != kIOReturnSuccess )
580 {
581 return false;
582 }
583
584 workLoopReqGate = IOCommandGate::commandGate( this, (IOCommandGate::Action) &IOATAStandardController::workLoopProcessRequest );
585 if ( workLoopReqGate == NULL )
586 {
587 return false;
588 }
589
590 if ( workLoop->addEventSource( workLoopReqGate ) != kIOReturnSuccess )
591 {
592 return false;
593 }
594
595
596 return true;
597 }
598
599 /*
600 *
601 *
602 *
603 */
604 IOATAStandardCommand *IOATAStandardController::findCommandWithNexus( IOATAStandardDevice *device, UInt32 tagValue = (UInt32)-1 )
605 {
606 return ((IOATAStandardDevice *)device)->findCommandWithNexus( tagValue );
607 }
608
609 /*
610 *
611 *
612 *
613 */
614 bool IOATAStandardController::configureController()
615 {
616 UInt32 targetsSize;
617
618 if ( configure( provider, &controllerInfo ) == false )
619 {
620 return false;
621 }
622
623 controllerInfo.commandPrivateDataSize = round( controllerInfo.commandPrivateDataSize, 16 );
624
625 targetsSize = controllerInfo.maxDevicesSupported * sizeof(ATATarget);
626 targets = (ATATarget *)IOMalloc( targetsSize );
627 bzero( targets, targetsSize );
628
629 commandLimit = commandLimitSave = (UInt32)-1;
630
631 return true;
632 }
633
634 /*
635 *
636 *
637 *
638 */
639 void IOATAStandardController::setCommandLimit( IOATAStandardDevice *device, UInt32 newCommandLimit )
640 {
641 ((IOATAStandardDevice *)device)->commandLimit = newCommandLimit;
642 }
643
644
645 /*
646 *
647 *
648 *
649 */
650 void IOATAStandardController::disableControllerInterrupts()
651 {
652 workLoop->disableAllInterrupts();
653 }
654
655 /*
656 *
657 *
658 *
659 */
660 void IOATAStandardController::enableControllerInterrupts()
661 {
662 workLoop->enableAllInterrupts();
663 }
664
665
666 /*
667 *
668 *
669 *
670 */
671 IOWorkLoop *IOATAStandardController::getWorkLoop() const
672 {
673 return workLoop;
674 }
675
676 /*
677 *
678 *
679 *
680 */
681 void IOATAStandardController::disableCommands( UInt32 disableTimeoutmS )
682 {
683 commandDisable = true;
684
685 disableTimer = ( disableTimeoutmS != 0 ) ? (disableTimeoutmS / kATATimerIntervalmS + 1) : 0;
686 }
687
688
689 /*
690 *
691 *
692 *
693 */
694 void IOATAStandardController::disableCommands()
695 {
696 UInt32 disableTimeout;
697
698 commandDisable = true;
699
700 disableTimeout = kATADisableTimeoutmS;
701
702 if ( noDisconnectCmd != 0 )
703 {
704 disableTimeout = noDisconnectCmd->getTimeout();
705 if ( disableTimeout != 0 ) disableTimeout += kATADisableTimeoutmS;
706 }
707
708 disableTimer = ( disableTimeout != 0 ) ? (disableTimeout / kATATimerIntervalmS + 1) : 0;
709 }
710
711 /*
712 *
713 *
714 *
715 */
716 void IOATAStandardController::disableTimeoutOccurred()
717 {
718 busResetState = kStateIssue;
719 dispatchRequest();
720 }
721
722
723 /*
724 *
725 *
726 *
727 */
728 UInt32 IOATAStandardController::getCommandCount()
729 {
730 return commandCount;
731 }
732
733 /*
734 *
735 *
736 *
737 */
738 void IOATAStandardController::suspendDevice( IOATAStandardDevice *device )
739 {
740 ((IOATAStandardDevice *)device)->suspend();
741 }
742
743 /*
744 *
745 *
746 *
747 */
748 void IOATAStandardController::resumeDevice( IOATAStandardDevice *device )
749 {
750 ((IOATAStandardDevice *)device)->resume();
751 }
752
753 /*
754 *
755 *
756 *
757 */
758 IOATAStandardDevice *IOATAStandardController::selectDevice()
759 {
760 IOATAStandardDevice *ataDev;
761 IOATAStandardDevice *selectedDevice = 0;
762 AbsoluteTime maxSuspendTime;
763 UInt32 i;
764
765 AbsoluteTime_to_scalar(&maxSuspendTime) = 0;
766
767 for (i = 0; i < controllerInfo.maxDevicesSupported; i++ )
768 {
769 ataDev = targets[i].device;
770 if ( ataDev != NULL )
771 {
772 if ( ataDev->isSuspended == true )
773 {
774 if ( CMP_ABSOLUTETIME(&ataDev->suspendTime, &maxSuspendTime) > 0 )
775 {
776 selectedDevice = ataDev;
777 AbsoluteTime_to_scalar( &maxSuspendTime ) = AbsoluteTime_to_scalar( &ataDev->suspendTime );
778 }
779 }
780 }
781 }
782
783 return (IOATAStandardDevice *) selectedDevice;
784 }
785
786
787 /*
788 *
789 *
790 *
791 */
792 void IOATAStandardController::rescheduleCommand( IOATAStandardCommand *forATACmd )
793 {
794 forATACmd->getDevice(kIOATAStandardDevice)->rescheduleCommand( forATACmd );
795 }
796
797 /*
798 *
799 *
800 *
801 */
802 void IOATAStandardController::enableCommands()
803 {
804 commandDisable = false;
805
806 disableTimer = 0;
807
808 dispatchRequest();
809 }
810
811 /*
812 *
813 *
814 *
815 */
816 void IOATAStandardController::dispatchRequest()
817 {
818 dispatchEvent->interruptOccurred(0, 0, 0);
819 }
820
821
822 /*
823 *
824 *
825 *
826 */
827 void IOATAStandardController::dispatch()
828 {
829 ATATarget *target;
830 IOATAStandardDevice *device;
831 UInt32 dispatchAction;
832 UInt32 i;
833
834 if ( checkBusReset() == true )
835 {
836 goto dispatch_Exit;
837 }
838
839 for ( i = 0; i < controllerInfo.maxDevicesSupported; i++ )
840 {
841 target = &targets[i];
842
843 device = target->device;
844 if ( device == 0 ) continue;
845
846 if ( target->state == kStateActive )
847 {
848 if ( device->dispatch( &dispatchAction ) == false )
849 {
850 target->state = kStateIdle;
851 }
852
853 switch ( dispatchAction )
854 {
855 case kDispatchNextDevice:
856 break;
857 case kDispatchStop:
858 goto dispatch_Exit;
859 }
860 }
861 }
862
863 dispatch_Exit:
864 ;
865 }
866
867 /*
868 *
869 *
870 *
871 */
872 IOATAStandardCommand *IOATAStandardController::allocCommand(UInt32 clientDataSize )
873 {
874 IOATAStandardCommand *cmd;
875 UInt32 size;
876
877 size = controllerInfo.commandPrivateDataSize + round(clientDataSize, 16);
878
879 cmd = new IOATAStandardCommand;
880 if ( !cmd )
881 {
882 return 0;
883 }
884 cmd->init();
885
886 if ( size )
887 {
888 cmd->dataArea = (void *)IOMallocContiguous( (vm_size_t)size, 16, 0 );
889 if ( !cmd->dataArea )
890 {
891 cmd->release();
892 return 0;
893 }
894
895 bzero( cmd->dataArea, size );
896
897 cmd->dataSize = size;
898
899 if ( controllerInfo.commandPrivateDataSize )
900 {
901 cmd->commandPrivateData = cmd->dataArea;
902 }
903 if ( clientDataSize )
904 {
905 cmd->clientData = (void *)((UInt8 *)cmd->dataArea + controllerInfo.commandPrivateDataSize);
906 }
907 }
908
909 cmd->controller = this;
910
911 return cmd;
912 }
913
914 /*
915 *
916 *
917 *
918 */
919 void IOATAStandardController::free()
920 {
921 UInt32 targetsSize;
922
923 if ( timerEvent != 0 ) timerEvent->release();
924
925 if ( workLoopReqGate != 0 ) workLoopReqGate->release();
926
927 if ( dispatchEvent != 0 ) dispatchEvent->release();
928
929 if ( resetCmd != 0 ) resetCmd->release();
930
931 if ( workLoop != 0 ) workLoop->release();
932
933 if ( targets != 0 )
934 {
935 targetsSize = controllerInfo.maxDevicesSupported * sizeof(ATATarget);
936 IOFree( targets, targetsSize );
937 }
938
939 super::free();
940 }
941
942 /*
943 *
944 *
945 *
946 */
947 void IOATAStandardCommand::free()
948 {
949 if ( dataArea )
950 {
951 IOFreeContiguous( dataArea, dataSize );
952 }
953
954 OSObject::free();
955 }
956