|
|
1.1 root 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: * IOATAController.cpp
25: *
26: */
27:
28: #include <IOKit/ata/IOATA.h>
29: #include <IOKit/ata/IOATAController.h>
30:
31: #undef super
32: #define super IOService
33:
34: OSDefineMetaClass( IOATAController, IOService );
35: OSDefineAbstractStructors( IOATAController, IOService );
36:
37: #define round(x,y) (((int)(x) + (y) - 1) & ~((y)-1))
38:
39: /*
40: *
41: *
42: */
43: bool IOATAController::start( IOService *provider )
44: {
45:
46: if ( provider->open( this ) != true )
47: {
48: return false;
49: }
50:
51: if ( configure( provider, &controllerDataSize ) != true || scanATABus() != true )
52: {
53: provider->close( this );
54: return false;
55: }
56:
57: controllerDataSize = round( controllerDataSize, 16 );
58:
59: return true;
60: }
61:
62: /*
63: *
64: *
65: *
66: */
67: void IOATAController::completeCommand( IOATACommand *cmd )
68: {
69: }
70:
71: /*
72: *
73: *
74: *
75: */
76: bool IOATAController::scanATABus()
77: {
78: if ( createResetWorker() != true )
79: {
80: return false;
81: }
82:
83: if ( createWorkLoop( &workLoop ) != true )
84: {
85: return false;
86: }
87:
88: if ( createDeviceNubs() != true )
89: {
90: return false;
91: }
92:
93: disableControllerInterrupts();
94:
95: if ( probeController() == false )
96: {
97: return false;
98: }
99:
100: enableControllerInterrupts();
101:
102: if ( resetBus() == false )
103: {
104: return false;
105: }
106:
107: if ( probeDeviceNubs() != true )
108: {
109: return false;
110: }
111:
112: if ( registerDeviceNubs() != true )
113: {
114: return false;
115: }
116:
117:
118: return true;
119: }
120:
121: /*
122: *
123: *
124: *
125: */
126: IOWorkLoop * IOATAController::getWorkLoop() const
127: {
128: return workLoop;
129: }
130:
131: /*
132: *
133: *
134: *
135: */
136: bool IOATAController::createResetWorker()
137: {
138: resetWorkLoop = new IOWorkLoop;
139: if ( resetWorkLoop == NULL )
140: {
141: return false;
142: }
143:
144: if ( resetWorkLoop->init() != true )
145: {
146: return false;
147: }
148:
149: resetCommandQ = IOCommandQueue::commandQueue( this, (IOCommandQueueAction) &IOATAController::resetWorker );
150: if ( resetCommandQ == NULL )
151: {
152: return false;
153: }
154:
155: if ( resetWorkLoop->addEventSource( resetCommandQ ) != kIOReturnSuccess )
156: {
157: resetCommandQ->release();
158: return false;
159: }
160:
161: return true;
162: }
163:
164: /*
165: *
166: *
167: *
168: */
169: bool IOATAController::createWorkLoop( IOWorkLoop **wrkLoop)
170: {
171:
172: *wrkLoop = new IOWorkLoop;
173: if ( *wrkLoop == NULL )
174: {
175: return false;
176: }
177:
178: if ( (*wrkLoop)->init() != true )
179: {
180: return false;
181: }
182: return true;
183: }
184:
185:
186: /*
187: *
188: *
189: *
190: */
191: IOCommandQueue *IOATAController::createDeviceQueue( IOATADevice *ataDev )
192: {
193: IOCommandQueueAction queueHandler;
194: IOCommandQueue *deviceQueue;
195:
196: queueHandler = provideQueueHandler( ataDev );
197: if ( queueHandler == NULL )
198: {
199: IOLog("IOATAController::%s() - Your subclass must provide a device queue handling routine\n\r", __FUNCTION__);
200: return NULL;
201: }
202:
203: deviceQueue = IOCommandQueue::commandQueue( this, (IOCommandQueueAction) queueHandler );
204: if ( deviceQueue == NULL )
205: {
206: return NULL;
207: }
208:
209: if ( workLoop->addEventSource( deviceQueue ) != kIOReturnSuccess )
210: {
211: deviceQueue->release();
212: return NULL;
213: }
214:
215: return deviceQueue;
216: }
217:
218: /*
219: *
220: *
221: */
222: void IOATAController::disableDeviceQueue( IOATADevice *ataDev = NULL )
223: {
224: changeDeviceQueue( ataDev, false );
225: }
226:
227: void IOATAController::enableDeviceQueue( IOATADevice *ataDev = NULL )
228: {
229: changeDeviceQueue( ataDev, true );
230: }
231:
232: void IOATAController::changeDeviceQueue( IOATADevice *ataDev, bool fEnable )
233: {
234: UInt32 i;
235:
236: if ( ataDev == NULL)
237: {
238: for ( i = 0; i < 2; i++ )
239: {
240: ataDev = deviceInfo[i].device;
241: if ( ataDev == NULL )
242: {
243: continue;
244: }
245:
246: if ( fEnable == true )
247: {
248: ataDev->getDeviceQueue()->enable();
249: }
250: else
251: {
252: ataDev->getDeviceQueue()->disable();
253: }
254: }
255: }
256: else
257: {
258: if ( fEnable == true )
259: {
260: ataDev->getDeviceQueue()->enable();
261: }
262: else
263: {
264: ataDev->getDeviceQueue()->disable();
265: }
266: }
267: }
268:
269:
270: /*
271: *
272: *
273: *
274: */
275: IOCommandQueueAction IOATAController::provideQueueHandler( IOATADevice *ataDev )
276: {
277: return NULL;
278: }
279:
280: /*
281: *
282: *
283: *
284: */
285: bool IOATAController::createDeviceNubs()
286: {
287: UInt32 i;
288: IOATADevice *ataDev;
289:
290: for (i = 0; i < 2; i++ )
291: {
292: ataDev = deviceInfo[i].device = new IOATADevice;
293:
294: if ( ataDev->init( i, this ) != true )
295: {
296: ataDev->release();
297: deviceInfo[i].device = NULL;
298: }
299: }
300:
301: return true;
302: }
303:
304: /*
305: *
306: *
307: *
308: */
309: bool IOATAController::probeDeviceNubs()
310: {
311: UInt32 i;
312: IOATADevice *ataDev;
313:
314: for (i = 0; i < 2; i++ )
315: {
316: ataDev = deviceInfo[i].device;
317: if ( ataDev->probeDeviceType() == ataDeviceNone )
318: {
319: ataDev->release();
320: deviceInfo[i].device = NULL;
321: }
322: }
323:
324: for (i = 0; i < 2; i++ )
325: {
326: ataDev = deviceInfo[i].device;
327: if ( ataDev == NULL )
328: {
329: continue;
330: }
331:
332: if ( ataDev->probeDevice() != true )
333: {
334: ataDev->release();
335: deviceInfo[i].device = NULL;
336: }
337: }
338:
339: return true;
340: }
341:
342: /*
343: *
344: *
345: *
346: */
347: bool IOATAController::registerDeviceNubs()
348: {
349: UInt32 i;
350: IOATADevice *ataDev;
351:
352: for (i = 0; i < 2; i++ )
353: {
354: ataDev = deviceInfo[i].device;
355: if ( ataDev != NULL )
356: {
357: ataDev->attach( this );
358: ataDev->registerService();
359: }
360: }
361:
362: return true;
363: }
364:
365: /*
366: *
367: *
368: *
369: */
370: bool IOATAController::matchNubWithPropertyTable( IOService *nub, OSDictionary *table )
371: {
372: bool rc;
373:
374: rc = nub->compareProperty( table, OSString::withCStringNoCopy( ATAPropertyLocation ) );
375:
376: return rc;
377: }
378:
379:
380: /*
381: *
382: *
383: *
384: */
385: bool IOATAController::probeController()
386: {
387: IOATADevice *ataDev;
388: ATATaskfile taskfile;
389: ATAResults results;
390: UInt32 j;
391: bool rc = true;
392: UInt32 status;
393: mach_timespec_t startTime, currentTime;
394: ATATiming initPIOTiming;
395:
396: ataDev = deviceInfo[0].device;
397: if ( ataDev == NULL )
398: {
399: return false;
400: }
401:
402: initPIOTiming.timingProtocol = ataTimingPIO;
403: initPIOTiming.featureSetting = 0;
404: initPIOTiming.mode = 0;
405: initPIOTiming.minDataAccess = 165;
406: initPIOTiming.minDataCycle = 600;
407: initPIOTiming.minCmdAccess = 290;
408: initPIOTiming.minCmdCycle = 600;
409:
410: calculateTiming( 0, &initPIOTiming );
411: calculateTiming( 1, &initPIOTiming );
412:
413: selectTiming( 0, ataTimingPIO );
414: selectTiming( 1, ataTimingPIO );
415:
416: utilCmd = ataDev->allocCommand();
417: if ( utilCmd == NULL )
418: {
419: return false;
420: }
421:
422: bzero( (void *)&taskfile, sizeof(taskfile) );
423:
424: taskfile.protocol = ataProtocolSetRegs;
425:
426: taskfile.regmask = ATARegtoMask(ataRegDriveHead);
427: taskfile.ataRegs[ataRegDriveHead] = ataModeLBA;
428: taskfile.resultmask = 0;
429:
430: utilCmd->setTaskfile( &taskfile );
431: utilCmd->execute();
432:
433: taskfile.regmask = 0;
434: taskfile.resultmask = ATARegtoMask(ataRegStatus);
435: utilCmd->setTaskfile( &taskfile );
436:
437: IOGetTime( &startTime );
438:
439: do
440: {
441: utilCmd->execute();
442: if ( utilCmd->getResults( &results ) != ataReturnNoError )
443: {
444: return false;
445: }
446:
447: IOGetTime( ¤tTime );
448: SUB_MACH_TIMESPEC( ¤tTime, &startTime );
449: if ( currentTime.tv_sec > 25 )
450: {
451: return false;
452: }
453:
454: status = results.ataRegs[ataRegStatus];
455:
456: if ( (status & ataStatusBSY) == 0)
457: {
458: break;
459: }
460: else if ( status & (ataStatusDF | ataStatusECC) )
461: {
462: return false;
463: }
464: IOSleep(20);
465: }
466: while ( 1 );
467:
468:
469: taskfile.regmask = ATARegtoMask(ataRegSectorCount)
470: | ATARegtoMask(ataRegSectorNumber);
471:
472: taskfile.resultmask = ATARegtoMask(ataRegSectorCount)
473: | ATARegtoMask(ataRegSectorNumber);
474:
475: for ( j=0; j < 16; j++ )
476: {
477: taskfile.ataRegs[ataRegSectorCount] = j;
478: taskfile.ataRegs[ataRegSectorNumber] = j << 4;
479:
480: utilCmd->setTaskfile( &taskfile );
481: utilCmd->execute();
482: utilCmd->getResults( &results );
483:
484: if ( results.returnCode != ataReturnNoError
485: || results.ataRegs[ataRegSectorCount] != j
486: || results.ataRegs[ataRegSectorNumber] != (j << 4) )
487: {
488: rc = false;
489: break;
490: }
491: }
492:
493: return rc;
494: }
495:
496: /*
497: *
498: *
499: *
500: */
501: void IOATAController::resetBusRequest()
502: {
503: UInt32 i;
504: IOService *client;
505: IOATADevice *device;
506:
507: for ( i = 0; i < 2; i++ )
508: {
509: device = deviceInfo[i].device;
510: if ( device == NULL ) continue;
511:
512: client = device->getClient();
513: if ( client == NULL ) continue;
514:
515: client->message( ataMessageResetStarted, device );
516: }
517:
518: for ( i = 0; i < 2; i++ )
519: {
520: device = deviceInfo[i].device;
521: if ( device == NULL ) continue;
522:
523: purgeDeviceQueue( device );
524: }
525:
526: resetCommandQ->enqueueCommand();
527: }
528:
529:
530: /*
531: *
532: *
533: *
534: */
535: void IOATAController::purgeDeviceQueue( IOATADevice *device )
536: {
537: enableDeviceQueue( device );
538: device->getDeviceQueue()->performAndFlush( (OSObject *)NULL,
539: (IOCommandQueueAction) &IOATAController::purgeCommand );
540: }
541:
542:
543: /*
544: *
545: *
546: *
547: */
548: void IOATAController::purgeCommand( void *p0, void *p1, void *p2, void *p3 )
549: {
550: IOATACommand *cmd = (IOATACommand *)p1;
551: ATAResults result;
552:
553: bzero( &result, sizeof(result) );
554:
555: result.returnCode = ataReturnBusReset;
556: cmd->setResults( &result );
557:
558: cmd->complete();
559: }
560:
561: /*
562: *
563: *
564: *
565: */
566: void IOATAController::resetWorker( void *, void *, void *, void * )
567: {
568: UInt32 i;
569: IOATADevice *device;
570: IOService *client;
571: bool rc = false;
572:
573: do
574: {
575: rc = resetBus();
576: }
577: while ( rc == false );
578:
579: for ( i = 0; i < 2; i++ )
580: {
581: device = deviceInfo[i].device;
582: if ( device == NULL ) continue;
583:
584: client = device->getClient();
585: if ( client == NULL ) continue;
586:
587: client->message( ataMessageInitDevice, device );
588: }
589:
590: for ( i = 0; i < 2; i++ )
591: {
592: device = deviceInfo[i].device;
593: if ( device == NULL ) continue;
594:
595: client = device->getClient();
596: if ( client == NULL ) continue;
597:
598: client->message( ataMessageResetComplete, device );
599: }
600: }
601:
602:
603: /*
604: *
605: *
606: *
607: */
608: bool IOATAController::resetBus()
609: {
610: ATATaskfile taskfile;
611: ATAResults result;
612: bool rc = true;
613: mach_timespec_t startTime, currentTime;
614:
615: bzero( (void *)&taskfile, sizeof(taskfile) );
616:
617: taskfile.protocol = ataProtocolSetRegs;
618: taskfile.regmask = ATARegtoMask(ataRegDeviceControl);
619: taskfile.resultmask = 0;
620:
621: taskfile.ataRegs[ataRegDeviceControl] = ataDevControlnIEN | ataDevControlSRST;
622:
623: utilCmd->setTaskfile( &taskfile );
624: utilCmd->execute();
625:
626: taskfile.ataRegs[ataRegDeviceControl] &= ~(ataDevControlnIEN | ataDevControlSRST);
627: utilCmd->setTaskfile( &taskfile );
628: utilCmd->execute();
629:
630: taskfile.regmask = 0;
631: taskfile.resultmask = ATARegtoMask(ataRegStatus);
632: utilCmd->setTaskfile( &taskfile );
633:
634: IOSleep(5);
635:
636: IOGetTime( &startTime );
637:
638: do
639: {
640: utilCmd->execute();
641: utilCmd->getResults(&result);
642:
643: IOGetTime( ¤tTime );
644: SUB_MACH_TIMESPEC( ¤tTime, &startTime );
645: if ( currentTime.tv_sec > 25 )
646: {
647: return false;
648: }
649:
650: if ( (result.ataRegs[ataRegStatus] & ataStatusBSY) == 0 )
651: {
652: break;
653: }
654: IOSleep(20);
655: }
656: while ( 1 );
657:
658: return rc;
659: }
660:
661: /*
662: *
663: *
664: *
665: */
666: void IOATAController::enableControllerInterrupts()
667: {
668: }
669:
670: /*
671: *
672: *
673: *
674: */
675: void IOATAController::disableControllerInterrupts()
676: {
677: }
678:
679:
680: /*
681: *
682: *
683: *
684: */
685: IOATACommand *IOATAController::makeRequestSense( IOATACommand *origCmd )
686: {
687: return origCmd->getDevice()->makeRequestSense( origCmd );
688: }
689:
690: /*
691: *
692: *
693: *
694: */
695: bool IOATAController::completeRequestSense( IOATACommand *origCmd, IOATACommand *reqSenseCmd )
696: {
697: return origCmd->getDevice()->completeRequestSense( origCmd, reqSenseCmd );
698: }
699:
700:
701: /*
702: *
703: *
704: *
705: */
706: IOATACommand *IOATAController::allocCommand(UInt32 clientDataSize )
707: {
708: IOATACommand *cmd;
709: UInt32 size;
710:
711: size = controllerDataSize + round(clientDataSize, 16);
712:
713: cmd = new IOATACommand;
714: if ( !cmd )
715: {
716: return 0;
717: }
718: cmd->init();
719:
720: if ( size )
721: {
722: cmd->dataArea = (void *)IOMalloc(size);
723: if ( !cmd->dataArea )
724: {
725: cmd->release();
726: return 0;
727: }
728:
729: bzero( cmd->dataArea, size );
730:
731: cmd->dataSize = size;
732:
733: if ( controllerDataSize )
734: {
735: cmd->controllerData = cmd->dataArea;
736: }
737: if ( clientDataSize )
738: {
739: cmd->clientData = (void *)((UInt8 *)cmd->dataArea + controllerDataSize);
740: }
741: }
742:
743: cmd->setController( this );
744:
745: return cmd;
746: }
747:
748: /*
749: *
750: *
751: *
752: */
753: void IOATAController::free()
754: {
755: if ( workLoop ) workLoop->release();
756: if ( resetCommandQ ) resetCommandQ->release();
757: if ( resetWorkLoop ) resetWorkLoop->release();
758: if ( utilCmd ) utilCmd->release();
759:
760: super::free();
761: }
762:
763: /*
764: *
765: *
766: *
767: */
768: void IOATACommand::free()
769: {
770: if ( dataArea )
771: {
772: IOFree( dataArea, dataSize );
773: }
774:
775: OSObject::free();
776: }
777:
778:
779:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.