Annotation of XNU/iokit/Families/IOATABus/IOATAController.cpp, revision 1.1.1.1

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( &currentTime );
                    448:         SUB_MACH_TIMESPEC( &currentTime, &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( &currentTime );
                    644:         SUB_MACH_TIMESPEC( &currentTime, &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:    

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.