Annotation of XNU/iokit/Families/IOATABus/IOATADevice.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:  * IOATADevice.cpp
                     25:  *
                     26:  */
                     27: 
                     28: #include <IOKit/IOSyncer.h>
                     29: #include <IOKit/ata/IOATA.h>
                     30: #include <IOKit/ata/IOATAController.h>
                     31: #include "ATAPrivate.h"
                     32: 
                     33: #undef  super
                     34: #define super IOService
                     35: 
                     36: OSDefineMetaClassAndStructors( IOATADevice, IOService );
                     37: 
                     38: extern EndianTable             AppleIdentifyEndianTable[];
                     39: 
                     40: extern UInt32                  AppleNumPIOModes;
                     41: extern ATAModeTable            ApplePIOModes[];
                     42: extern UInt32                  AppleNumDMAModes;
                     43: extern ATAModeTable            AppleDMAModes[];
                     44: extern UInt32                  AppleNumUltraModes;
                     45: extern ATAModeTable            AppleUltraModes[];
                     46: 
                     47: /*
                     48:  *
                     49:  *
                     50:  */
                     51: bool IOATADevice::probeDevice()
                     52: {
                     53:     OSDictionary               *propTable = 0;
                     54: 
                     55:     if ( open( this ) != true )
                     56:     {
                     57:         goto probeDevice_error;
                     58:     }
                     59: 
                     60:     if ( doIdentify( (void **)&identifyData ) != ataReturnNoError )
                     61:     {
                     62:         goto probeDevice_error;
                     63:     }
                     64: 
                     65:     if ( deviceType == ataDeviceATA )
                     66:     {
                     67:         doSpinUp();
                     68:     }
                     69: 
                     70:     else if ( deviceType == ataDeviceATAPI )
                     71:     {
                     72:         atapiPktInt = ((identifyData->generalConfiguration & atapiPktProtocolIntDRQ) != 0);
                     73:       
                     74:         if ( doInquiry( (void **)&inquiryData ) != ataReturnNoError )
                     75:         {
                     76:             goto probeDevice_error;
                     77:         }
                     78: 
                     79:         reqSenseCmd = allocCommand();
                     80:     }      
                     81: 
                     82:     if ( getATATimings() != true )
                     83:     {
                     84:         goto probeDevice_error;
                     85:     }
                     86:     
                     87:     propTable = createProperties();
                     88:     if ( !propTable )
                     89:     {
                     90:         goto probeDevice_error;
                     91:     }
                     92:     
                     93:     setPropertyTable( propTable );
                     94: 
                     95:     propTable->release();
                     96:  
                     97:     close( this );
                     98: 
                     99:     return true; 
                    100: 
                    101: probeDevice_error: ;
                    102:     close( this );
                    103:     return false;
                    104: }
                    105: 
                    106: /*
                    107:  *
                    108:  *
                    109:  *
                    110:  */
                    111: ATADeviceType IOATADevice::probeDeviceType()
                    112: {
                    113:     ATATaskfile         taskfile;
                    114:     ATAResults          results;
                    115: 
                    116:     bzero( (void *)&taskfile, sizeof(taskfile) );
                    117: 
                    118:     taskfile.protocol     = ataProtocolSetRegs;
                    119:     taskfile.regmask      = ATARegtoMask(ataRegDriveHead);  
                    120: 
                    121:     taskfile.resultmask   = ATARegtoMask(ataRegSectorCount)
                    122:                           | ATARegtoMask(ataRegSectorNumber)
                    123:                           | ATARegtoMask(ataRegCylinderLow)
                    124:                           | ATARegtoMask(ataRegCylinderHigh)
                    125:                           | ATARegtoMask(ataRegStatus);
                    126: 
                    127:     taskfile.ataRegs[ataRegDriveHead] = ataModeLBA | (getUnit() << 4);
                    128: 
                    129:     utilCmd->setTaskfile( &taskfile );
                    130:     utilCmd->execute();
                    131: 
                    132:     if ( utilCmd->getResults( &results ) != ataReturnNoError )     
                    133:     {
                    134:         return (deviceType = ataDeviceNone);
                    135:     }
                    136:  
                    137:     if ( results.ataRegs[ataRegSectorCount] == ataSignatureSectorCount
                    138:           && results.ataRegs[ataRegSectorNumber] == ataSignatureSectorNumber
                    139:              && results.ataRegs[ataRegCylinderLow] == ataSignatureCylinderLow
                    140:                 && results.ataRegs[ataRegCylinderHigh] == ataSignatureCylinderHigh )
                    141:     { 
                    142:         if ( !(results.ataRegs[ataRegStatus] & ataStatusBSY)  
                    143:                  && (results.ataRegs[ataRegStatus] & ataStatusDRDY) )
                    144:         {
                    145:             return (deviceType = ataDeviceATA);
                    146:         }
                    147:     }
                    148:             
                    149:     if ( results.ataRegs[ataRegCylinderLow] == atapiSignatureCylinderLow
                    150:                 && results.ataRegs[ataRegCylinderHigh] == atapiSignatureCylinderHigh )
                    151:     {
                    152:         return (deviceType = ataDeviceATAPI);
                    153:     }       
                    154:   
                    155:     return (deviceType = ataDeviceNone);
                    156: }
                    157: 
                    158: 
                    159: /*
                    160:  *
                    161:  *
                    162:  *
                    163:  */
                    164: ATAReturnCode IOATADevice::doSpinUp()
                    165: {
                    166:     void               *buffer = NULL;
                    167:     ATAReturnCode      rc;
                    168: 
                    169:     rc = doSectorCommand( ataCommandReadSector, 0, 1, &buffer );
                    170: 
                    171:     if ( rc != ataReturnNoError )
                    172:     {
                    173:         return rc;
                    174:     }
                    175: 
                    176:     IOFree( buffer, 512 );
                    177: 
                    178:     return rc ; 
                    179: }    
                    180: 
                    181: /*
                    182:  *
                    183:  *
                    184:  *
                    185:  */
                    186: ATAReturnCode IOATADevice::doIdentify( void **dataPtr )
                    187: {   
                    188:     ATACommand         ataCmd;
                    189:     ATAReturnCode      rc;
                    190:  
                    191:     ataCmd = (deviceType == ataDeviceATA) ? ataCommandIdentify : atapiCommandIdentify;
                    192: 
                    193:     rc = doSectorCommand( ataCmd, 0, 1, dataPtr );
                    194: 
                    195:     if ( rc != ataReturnNoError )
                    196:     {
                    197:         return rc;
                    198:     }
                    199:  
                    200:     endianConvertData( *dataPtr, AppleIdentifyEndianTable );
                    201: 
                    202:     return rc;
                    203: }
                    204: 
                    205: 
                    206: 
                    207: /*
                    208:  *
                    209:  *
                    210:  *
                    211:  */
                    212: ATAReturnCode IOATADevice::doSectorCommand( ATACommand ataCmd, UInt32 ataLBA, UInt32 ataCount, void **dataPtr )
                    213: {
                    214:     ATATaskfile                        taskfile;
                    215:     ATAResults                 result;
                    216:     IOMemoryDescriptor         *desc;
                    217:     UInt32                     size;
                    218:     void                       *data;
                    219:     UInt32                     i;
                    220:     ATAReturnCode              rc;
                    221: 
                    222:     *dataPtr = NULL;
                    223: 
                    224:     size = ataCount * 512;
                    225: 
                    226:     if ( !(data = (void *)IOMalloc(size)) )
                    227:     {
                    228:         return ataReturnNoResource;
                    229:     }
                    230: 
                    231:     bzero( &taskfile, sizeof(taskfile) );
                    232: 
                    233:     desc = IOMemoryDescriptor::withAddress( data, size, kIODirectionIn );
                    234:     if ( desc == NULL )
                    235:     {
                    236:         rc = ataReturnNoResource;
                    237:         goto doSectorCommand_error;
                    238:     }
                    239: 
                    240:     
                    241:     taskfile.protocol                  = ataProtocolPIO;
                    242:     taskfile.regmask                   = ATARegtoMask(ataRegDriveHead)
                    243:                                        | ATARegtoMask(ataRegSectorCount)
                    244:                                        | ATARegtoMask(ataRegSectorNumber)
                    245:                                        | ATARegtoMask(ataRegCylinderLow)
                    246:                                        | ATARegtoMask(ataRegCylinderHigh)
                    247:                                        | ATARegtoMask(ataRegFeatures)
                    248:                                        | ATARegtoMask(ataRegCommand);
                    249: 
                    250: 
                    251:     taskfile.resultmask                        = ATARegtoMask(ataRegError) 
                    252:                                         | ATARegtoMask(ataRegStatus);
                    253: 
                    254:     taskfile.ataRegs[ataRegSectorCount]   = ataCount;
                    255:     taskfile.ataRegs[ataRegSectorNumber]  = ataLBA         & 0xff;
                    256:     taskfile.ataRegs[ataRegCylinderLow]   = (ataLBA >> 8)  & 0xff;
                    257:     taskfile.ataRegs[ataRegCylinderHigh]  = (ataLBA >> 16) & 0xff;
                    258:     taskfile.ataRegs[ataRegDriveHead]     = (ataLBA >> 24) & 0x0f;
                    259: 
                    260:     taskfile.ataRegs[ataRegDriveHead]   |= ataModeLBA | (getUnit() << 4);
                    261:     taskfile.ataRegs[ataRegCommand]      = ataCmd;
                    262: 
                    263:     for ( i = 0; i < 2; i++ )
                    264:     { 
                    265:         utilCmd->setTimeout( 25000 );
                    266:         utilCmd->setTaskfile( &taskfile );
                    267:         utilCmd->setPointers( desc, size, false ); 
                    268:         submitCommand( utilCmd );
                    269:     
                    270:         rc  = utilCmd->getResults( &result );
                    271:         if ( rc == ataReturnNoError )
                    272:         {
                    273:             break;
                    274:         }
                    275:     }
                    276: 
                    277: 
                    278: doSectorCommand_error: ;
                    279: 
                    280:     desc->release();
                    281: 
                    282:     if ( rc != ataReturnNoError )
                    283:     {
                    284:         IOFree( data, size );
                    285:         return result.returnCode;
                    286:     }
                    287: 
                    288:     *dataPtr = data;
                    289: 
                    290:     return ataReturnNoError;
                    291: }
                    292: 
                    293: 
                    294: /*
                    295:  *
                    296:  *
                    297:  */
                    298: ATAReturnCode IOATADevice::doInquiry( void **dataPtr )
                    299: {
                    300:     ATATaskfile                        taskfile;
                    301:     ATAPICmd                   atapiCmd;
                    302:     ATAResults                 result;
                    303:     void                        *data;
                    304:     IOMemoryDescriptor         *desc;
                    305:     UInt32                     size = sizeof(ATAPIInquiry);
                    306: 
                    307:     *dataPtr = 0;
                    308: 
                    309:     if ( !(data = (void *)IOMalloc(size)) )
                    310:     {
                    311:         return ataReturnNoResource;;
                    312:     }
                    313: 
                    314:     bzero( &taskfile, sizeof(taskfile) );
                    315:     bzero( &atapiCmd, sizeof(atapiCmd) );
                    316: 
                    317:     desc = IOMemoryDescriptor::withAddress( data, size, kIODirectionIn );
                    318:     
                    319:     taskfile.protocol                  = atapiProtocolPIO;
                    320:     taskfile.regmask                   = ATARegtoMask(atapiRegDeviceSelect) 
                    321:                                        | ATARegtoMask(atapiRegCommand)
                    322:                                         | ATARegtoMask(atapiRegByteCountLow)
                    323:                                         | ATARegtoMask(atapiRegByteCountHigh)
                    324:                                         | ATARegtoMask(atapiRegFeatures);
                    325:     taskfile.ataRegs[atapiRegDeviceSelect]  = ataModeLBA | (getUnit() << 4);
                    326:     taskfile.ataRegs[atapiRegCommand]       = atapiCommandPacket;
                    327:     taskfile.ataRegs[atapiRegFeatures]      = 0;
                    328:     taskfile.ataRegs[atapiRegByteCountLow]  = 0xfe;
                    329:     taskfile.ataRegs[atapiRegByteCountHigh] = 0xff;
                    330: 
                    331:     atapiCmd.cdbLength = 12;  // Fix 16 byte cmdpkts??
                    332:     atapiCmd.cdb[0]    = 0x12;
                    333:     atapiCmd.cdb[4]    = size;
                    334: 
                    335:     utilCmd->setATAPICmd( &atapiCmd, 0, 0 );
                    336:     utilCmd->setTaskfile( &taskfile );
                    337:     utilCmd->setPointers( desc, size, false );
                    338:     utilCmd->setTimeout( 5000 ); 
                    339:     submitCommand( utilCmd );
                    340:  
                    341:     if ( utilCmd->getResults(&result) == ataReturnNoError )
                    342:     {
                    343:         *dataPtr = data;
                    344:     }
                    345:     else
                    346:     {
                    347:         IOFree( data, size );
                    348:     }
                    349: 
                    350:     desc->release();
                    351: 
                    352:     return result.returnCode;
                    353: }
                    354: 
                    355: /*
                    356:  *
                    357:  *
                    358:  */
                    359: bool IOATADevice::getDeviceCapacity( UInt32 *blockMax, UInt32 *blockSize )
                    360: {
                    361:     UInt32             i;
                    362:     UInt32             data[2];
                    363: 
                    364:     if ( deviceType == ataDeviceATA )
                    365:     {
                    366:         if ( identifyData != NULL )
                    367:         {
                    368:             *blockMax = *(UInt32 *)identifyData->userAddressableSectors - 1;
                    369:             *blockSize  = 512;
                    370:             return true;
                    371:         }
                    372:     }
                    373:     
                    374:     if ( deviceType == ataDeviceATAPI )
                    375:     {
                    376:         for ( i=0; i < 8; i++ )
                    377:         {
                    378:             if ( doTestUnitReady() == ataReturnNoError )
                    379:             {
                    380:                 break;
                    381:             }
                    382:         }
                    383: 
                    384:         if ( doReadCapacity( data ) == ataReturnNoError )
                    385:         {
                    386:             *blockMax   = OSSwapBigToHostInt32( data[0] );
                    387:             *blockSize  = OSSwapBigToHostInt32( data[1] );
                    388:             return true;
                    389:         }      
                    390:     }
                    391: 
                    392:     return false;
                    393: }
                    394: 
                    395: 
                    396: ATAReturnCode IOATADevice::doTestUnitReady()
                    397: {
                    398:     ATATaskfile                        taskfile;
                    399:     ATAPICmd                   atapiCmd;
                    400:     ATAResults                 result;
                    401: 
                    402:     bzero( &taskfile, sizeof(taskfile) );
                    403:     bzero( &atapiCmd, sizeof(atapiCmd) );
                    404: 
                    405:     taskfile.protocol                  = atapiProtocolPIO;
                    406: 
                    407:     taskfile.regmask                   = ATARegtoMask(atapiRegDeviceSelect) 
                    408:                                        | ATARegtoMask(atapiRegCommand)
                    409:                                         | ATARegtoMask(atapiRegByteCountLow)
                    410:                                         | ATARegtoMask(atapiRegByteCountHigh)
                    411:                                         | ATARegtoMask(atapiRegFeatures);
                    412: 
                    413:     taskfile.ataRegs[atapiRegDeviceSelect]  = ataModeLBA | (getUnit() << 4);
                    414:     taskfile.ataRegs[atapiRegCommand]       = atapiCommandPacket;
                    415:     taskfile.ataRegs[atapiRegFeatures]      = 0;
                    416:     taskfile.ataRegs[atapiRegByteCountLow]  = 0xfe;
                    417:     taskfile.ataRegs[atapiRegByteCountHigh] = 0xff;
                    418: 
                    419:     atapiCmd.cdbLength = 12;  // Fix 16 byte cmdpkts??
                    420:     atapiCmd.cdb[0]    = 0x00;
                    421: 
                    422:     utilCmd->setATAPICmd( &atapiCmd );
                    423:     utilCmd->setTaskfile( &taskfile );
                    424:     utilCmd->setPointers( (IOMemoryDescriptor *)NULL, 0, false ); 
                    425:     utilCmd->setTimeout( 5000 );
                    426:     submitCommand( utilCmd );
                    427:     utilCmd->getResults(&result);
                    428:  
                    429:     return result.returnCode;
                    430: }
                    431: 
                    432: 
                    433: /*
                    434:  *
                    435:  *
                    436:  */
                    437: ATAReturnCode IOATADevice::doReadCapacity( void *data )
                    438: {
                    439:     ATATaskfile                        taskfile;
                    440:     ATAPICmd                   atapiCmd;
                    441:     ATAResults                 result;
                    442:     IOMemoryDescriptor         *dataDesc;
                    443:     UInt32                     size = 8;
                    444: 
                    445: 
                    446:     bzero( &taskfile, sizeof(taskfile) );
                    447:     bzero( &atapiCmd, sizeof(atapiCmd) );
                    448: 
                    449:     dataDesc = IOMemoryDescriptor::withAddress( data, size, kIODirectionIn );
                    450:     if ( dataDesc == NULL )
                    451:     {
                    452:         return ataReturnNoResource;
                    453:     }
                    454:     
                    455:     taskfile.protocol                  = atapiProtocolPIO;
                    456:     taskfile.regmask                   = ATARegtoMask(atapiRegDeviceSelect) 
                    457:                                        | ATARegtoMask(atapiRegCommand)
                    458:                                         | ATARegtoMask(atapiRegByteCountLow)
                    459:                                         | ATARegtoMask(atapiRegByteCountHigh)
                    460:                                         | ATARegtoMask(atapiRegFeatures);
                    461:     taskfile.ataRegs[atapiRegDeviceSelect]  = ataModeLBA | (getUnit() << 4);
                    462:     taskfile.ataRegs[atapiRegCommand]       = atapiCommandPacket;
                    463:     taskfile.ataRegs[atapiRegFeatures]      = 0;
                    464:     taskfile.ataRegs[atapiRegByteCountLow]  = 0xfe;
                    465:     taskfile.ataRegs[atapiRegByteCountHigh] = 0xff;
                    466: 
                    467:     atapiCmd.cdbLength = 12;  // Fix 16 byte cmdpkts??
                    468:     atapiCmd.cdb[0]    = 0x25;
                    469: 
                    470:     utilCmd->setATAPICmd( &atapiCmd );
                    471:     utilCmd->setTaskfile( &taskfile );
                    472:     utilCmd->setPointers( dataDesc, size, false ); 
                    473:     utilCmd->setTimeout( 5000 );
                    474:     submitCommand( utilCmd );
                    475:     
                    476:     utilCmd->getResults(&result);
                    477: 
                    478:     dataDesc->release();
                    479:  
                    480:     return result.returnCode;
                    481: }
                    482: 
                    483: 
                    484: /*
                    485:  *
                    486:  *
                    487:  */
                    488: IOATACommand *IOATADevice::makeRequestSense( IOATACommand *origCmd )
                    489: {
                    490:     ATATaskfile                        taskfile;
                    491:     ATAPICmd                   atapiCmd;
                    492: 
                    493:     if ( reqSenseCmd == NULL )
                    494:     {
                    495:         return NULL;
                    496:     }
                    497: 
                    498:     bzero( &taskfile, sizeof(taskfile) );
                    499:     bzero( &atapiCmd, sizeof(atapiCmd) );
                    500: 
                    501:     taskfile.protocol                  = atapiProtocolPIO;
                    502:  
                    503:     taskfile.regmask                   = ATARegtoMask(atapiRegDeviceSelect) 
                    504:                                        | ATARegtoMask(atapiRegCommand)
                    505:                                         | ATARegtoMask(atapiRegByteCountLow)
                    506:                                         | ATARegtoMask(atapiRegByteCountHigh)
                    507:                                         | ATARegtoMask(atapiRegFeatures);
                    508: 
                    509:     taskfile.ataRegs[atapiRegDeviceSelect]  = ataModeLBA | (getUnit() << 4);
                    510:     taskfile.ataRegs[atapiRegCommand]       = atapiCommandPacket;
                    511:     taskfile.ataRegs[atapiRegFeatures]      = 0;
                    512:     taskfile.ataRegs[atapiRegByteCountLow]  = origCmd->senseLength & 0xff;
                    513:     taskfile.ataRegs[atapiRegByteCountHigh] = 0;
                    514: 
                    515:     atapiCmd.cdbLength   = 12;  // Fix 16 byte cmdpkts??
                    516:     atapiCmd.cdb[0]      = 0x03;
                    517:     atapiCmd.cdb[4]      = origCmd->senseLength;
                    518: 
                    519:     reqSenseCmd->setATAPICmd( &atapiCmd, 0, 0 );
                    520:     reqSenseCmd->setTaskfile( &taskfile );
                    521:     reqSenseCmd->setPointers( origCmd->senseData, origCmd->senseLength, false ); 
                    522: 
                    523:     return reqSenseCmd;
                    524: }
                    525: 
                    526: /*
                    527:  *
                    528:  *
                    529:  */
                    530: bool IOATADevice::completeRequestSense( IOATACommand *origCmd, IOATACommand  *reqSense )
                    531: {
                    532:     ATAResults         result;
                    533: 
                    534:     if ( reqSense->getResults(&result) != ataReturnNoError )
                    535:     {
                    536:         return false;
                    537:     }
                    538:     
                    539:     origCmd->results.senseLength = result.bytesTransferred;
                    540:     return true;
                    541: }
                    542: 
                    543: 
                    544: /*
                    545:  *
                    546:  *
                    547:  */ 
                    548: bool IOATADevice::getTimingsSupported( ATATimingProtocol *timingsSupported )
                    549: {
                    550:     UInt32                     i;
                    551: 
                    552:     *(UInt32 *)timingsSupported = 0;
                    553:  
                    554:     for ( i=0; i < numTimings; i++ )
                    555:     {
                    556:         *(UInt32 *) timingsSupported |= (UInt32)ataTimings[i].timingProtocol; 
                    557:     }
                    558: 
                    559:     return true;
                    560: }
                    561: 
                    562: /*
                    563:  *
                    564:  *
                    565:  */ 
                    566: bool IOATADevice::getTiming( ATATimingProtocol *timingProtocol, ATATiming *timing )
                    567: {
                    568:     UInt32                     i;
                    569: 
                    570:     for ( i=0; i < numTimings; i++ )
                    571:     {
                    572:         if ( ataTimings[i].timingProtocol == *timingProtocol )
                    573:         {
                    574:             bcopy( &ataTimings[i], timing, sizeof(ATATiming) );
                    575:             return true;
                    576:         }
                    577:     }
                    578: 
                    579:     return false;
                    580: }
                    581: 
                    582: 
                    583: /*
                    584:  *
                    585:  *
                    586:  */ 
                    587: bool IOATADevice::selectTiming( ATATimingProtocol timingProtocol )
                    588: {
                    589:     ATATaskfile                        taskfile;
                    590:     ATAResults                 result;
                    591:     bool                       rc = false;
                    592:     UInt32                     i;
                    593: 
                    594:     for ( i=0; i < numTimings; i++ )
                    595:     {
                    596:         if ( ataTimings[i].timingProtocol == timingProtocol )
                    597:         {
                    598:             rc = true;
                    599:             break;
                    600:         }
                    601:     }
                    602: 
                    603:     if ( rc == false ) return rc;
                    604:     
                    605:     if ( controller->selectTiming( getUnit(), timingProtocol ) == false )
                    606:     {
                    607:         return false;
                    608:     }
                    609:      
                    610:     bzero( &taskfile, sizeof(taskfile) );
                    611:     bzero( &result, sizeof(result) );
                    612: 
                    613:     taskfile.protocol                  = ataProtocolPIO;
                    614:     taskfile.regmask                   = ATARegtoMask(ataRegFeatures) 
                    615:                                        | ATARegtoMask(ataRegSectorCount) 
                    616:                                        | ATARegtoMask(ataRegDriveHead) 
                    617:                                        | ATARegtoMask(ataRegCommand);
                    618:  
                    619:     taskfile.ataRegs[ataRegSectorCount]  = ataTimings[i].featureSetting;
                    620:     taskfile.ataRegs[ataRegFeatures]     = ataFeatureTransferMode;
                    621:     taskfile.ataRegs[ataRegDriveHead]    = ataModeLBA | (getUnit() << 4);
                    622:     taskfile.ataRegs[ataRegCommand]      = ataCommandSetFeatures;
                    623: 
                    624:     utilCmd->setTaskfile( &taskfile );
                    625:     utilCmd->setPointers( (IOMemoryDescriptor *)NULL, 0, false );
                    626:     utilCmd->setTimeout( 5000 );
                    627:     utilCmd->setCallback(); 
                    628:     submitCommand( utilCmd );
                    629:  
                    630:     if ( utilCmd->getResults( &result ) != ataReturnNoError )
                    631:     {
                    632:         rc = false;
                    633:     }
                    634:     return rc;
                    635: }
                    636:     
                    637: 
                    638: /*
                    639:  *
                    640:  *
                    641:  */ 
                    642: bool IOATADevice::getATATimings()
                    643: {
                    644:     int                        i, n;
                    645:     UInt32             mode            = 0;
                    646:     UInt32                     cycleTime       = 0;
                    647: 
                    648:     ATATiming          *pTimings;
                    649: 
                    650:     pTimings = ataTimings;
                    651: 
                    652:     /*
                    653:      *  PIO Cycle timing......  
                    654:      *
                    655:      *  1. Try to match Word 51 (pioCycleTime) with cycle timings
                    656:      *     in our pioModes table to get mode/CycleTime. (Valid for Modes 0-2)
                    657:      *  2. If Words 64-68 are supported and Mode 3 or 4 supported check, 
                    658:      *     update CycleTime with Word 68 (CycleTimeWithIORDY).
                    659:      */
                    660: 
                    661:     cycleTime = identifyData->pioMode;
                    662: 
                    663:     if ( cycleTime > 2 )
                    664:     {
                    665:         for ( i=AppleNumPIOModes-1; i != -1; i-- )
                    666:         {
                    667:             if ( cycleTime <= ApplePIOModes[i].minDataCycle )
                    668:             {
                    669:                 mode = i;
                    670:                 break;
                    671:             }
                    672:          }
                    673: 
                    674:          if ( i == -1 )
                    675:          {
                    676:              cycleTime = ApplePIOModes[mode].minDataCycle;
                    677:          }
                    678:     }
                    679:     else
                    680:     {
                    681:         mode      = cycleTime;
                    682:         cycleTime = ApplePIOModes[mode].minDataCycle;
                    683:     }
                    684: 
                    685: 
                    686:     if ( identifyData->validFields & identifyWords_64to70_Valid ) 
                    687:     {
                    688:        if (identifyData->advancedPIOModes & advPIOModes_Mode4_Supported)
                    689:             mode = 4;
                    690:        else if (identifyData->advancedPIOModes & advPIOModes_Mode3_Supported)
                    691:             mode = 3;
                    692: 
                    693:         if ( (mode >= 3) && identifyData->minPIOCyclcTimeIORDY )
                    694:         {
                    695:             cycleTime = identifyData->minPIOCyclcTimeIORDY;
                    696:         }
                    697:     }
                    698:     
                    699:     pTimings->timingProtocol = ataTimingPIO;
                    700:     pTimings->mode           = mode;
                    701:     pTimings->featureSetting  = mode | ataTransferModePIOwFC;
                    702:     pTimings->minDataCycle    = cycleTime;
                    703:     pTimings->minDataAccess   = ApplePIOModes[mode].minDataAccess;
                    704: 
                    705:     if ( controller->calculateTiming( getUnit(), pTimings ) == false )
                    706:     {
                    707:         IOLog("IOATADevice::%s() - Controller driver must support PIO timings\n\r", __FUNCTION__);
                    708:         return false;
                    709:     }
                    710: 
                    711:     pTimings++;
                    712:     numTimings++;
                    713: 
                    714:     /* 
                    715:      *  Multiword DMA timing.....
                    716:      *
                    717:      *  1. Check Word 63(7:0) (Multiword DMA Modes Supported). Lookup
                    718:      *     CycleTime for highest mode we support.
                    719:      *  2. If Words 64-68 supported, update CycleTime from Word 66
                    720:      *     (RecommendedMultiWordCycleTime) if specified.
                    721:      */                                                                
                    722: 
                    723:     n = identifyData->dmaModes & dmaModes_Supported;
                    724:     if ( n )
                    725:     {
                    726:         for ( i=0; n; i++, n>>=1 )
                    727:           ;
                    728: 
                    729:         mode = i - 1;
                    730:         if ( mode > AppleNumDMAModes-1 )
                    731:         {
                    732:             mode = AppleNumDMAModes-1;
                    733:         }
                    734:         cycleTime = AppleDMAModes[mode].minDataCycle;
                    735: 
                    736:         if (identifyData->validFields & identifyWords_64to70_Valid) 
                    737:         {
                    738:             if ( identifyData->recDMACycleTime )
                    739:             {
                    740:                 cycleTime = identifyData->recDMACycleTime;
                    741:             }
                    742:         }
                    743:         pTimings->timingProtocol = ataTimingDMA;
                    744:         pTimings->mode          = mode;
                    745:         pTimings->featureSetting = mode | ataTransferModeDMA;
                    746:         pTimings->minDataCycle   = cycleTime;
                    747:         pTimings->minDataAccess  = AppleDMAModes[mode].minDataAccess;
                    748: 
                    749:         if ( controller->calculateTiming( getUnit(), pTimings ) == true )
                    750:         {
                    751:             pTimings++;
                    752:             numTimings++;
                    753:         }
                    754:     }
                    755: 
                    756:     /* 
                    757:      *  Ultra DMA timing.....
                    758:      *
                    759:      */                                                                
                    760:     if ( identifyData->validFields & identifyWords_88to88_Valid ) 
                    761:     {
                    762:         n = identifyData->ultraDMAModes & ultraDMAModes_Supported;
                    763:         if ( n )
                    764:         {
                    765:             for ( i=0; n; i++, n>>=1 )
                    766:               ;
                    767: 
                    768:             mode = i - 1;
                    769:             if ( mode > AppleNumUltraModes-1 )
                    770:             {
                    771:                 mode = AppleNumUltraModes-1;
                    772:             }
                    773: 
                    774:             /*
                    775:              * Build a separate timing entry for Ultra DMA/33 (mode <= 2) and Ultra DMA/66
                    776:              */
                    777:             while ( 1 )
                    778:             { 
                    779:                 cycleTime = AppleUltraModes[mode].minDataCycle;
                    780: 
                    781:                 pTimings->timingProtocol = (mode > 2) ? ataTimingUltraDMA66 : ataTimingUltraDMA33;
                    782:                 pTimings->mode          = mode;
                    783:                 pTimings->featureSetting = mode | ataTransferModeUltraDMA33;
                    784:                 pTimings->minDataCycle   = cycleTime;
                    785:                 pTimings->minDataAccess  = AppleUltraModes[mode].minDataAccess;
                    786:   
                    787:                 if ( controller->calculateTiming( getUnit(), pTimings ) == true )
                    788:                 {
                    789:                     pTimings++;
                    790:                     numTimings++;
                    791:                 }
                    792:                 
                    793:                 if ( mode < 3 ) break; 
                    794:            
                    795:                 mode = 2;
                    796:             }
                    797:         }
                    798:     }
                    799: 
                    800:     return true;            
                    801: }
                    802: 
                    803: /*
                    804:  *
                    805:  *
                    806:  */
                    807: void IOATADevice::submitCommand( IOATACommand *cmd )
                    808: {
                    809:     cmd->execute();
                    810:     IOWriteLock( resetSem );
                    811:     IORWUnlock( resetSem );
                    812: }
                    813: 
                    814: /*
                    815:  *
                    816:  *
                    817:  */
                    818: bool IOATADevice::executeCommand( IOATACommand *cmd )
                    819: {
                    820:     bool               isSync;
                    821: 
                    822:     isSync = !(cmd->flags & IOATACommand::atacmdCallbackValid);
                    823: 
                    824:     if ( isSync )
                    825:     {
                    826:         cmd->completionInfo.sync.syncer = IOSyncer::create();
                    827:     }
                    828: 
                    829:     cmd->deviceQueue = deviceQueue;
                    830: 
                    831:     controller->executeCommand( cmd );
                    832:     
                    833:     if ( isSync )
                    834:     {
                    835:         cmd->completionInfo.sync.syncer->wait();
                    836:     }
                    837: 
                    838:     return true;
                    839: }
                    840: 
                    841: /*
                    842:  *
                    843:  *
                    844:  */
                    845: void IOATADevice::completeCommand( IOATACommand *cmd )
                    846: {
                    847:     ATATaskfile                tf;
                    848:     ATAResults         res;
                    849:     UInt32             i;
                    850: 
                    851:     cmd->getTaskfile(&tf);
                    852:     cmd->getResults(&res);
                    853: 
                    854: #if 0
                    855:     IOLog("ATA command = %02x, RegMask = %04x ResultMask = %04x ReturnCode = %04x\n\r", 
                    856:            tf.protocol, (int)tf.regmask, (int)tf.resultmask, (int)res.returnCode );
                    857: 
                    858:     IOLog("ATA command regs:      ");
                    859: 
                    860:     for (i=0; i < MAX_ATA_REGS; i++ )
                    861:     {
                    862:         IOLog("%04x ", tf.ataRegs[i]);
                    863:     }
                    864: 
                    865:     IOLog("\n\rATA result regs:       ");
                    866: 
                    867:     for (i=0; i < MAX_ATA_REGS; i++ )
                    868:     {
                    869:         IOLog("%04x ", res.ataRegs[i]);
                    870:     }
                    871:     IOLog("\n\r");
                    872: #endif
                    873: 
                    874:     if ( cmd->flags & IOATACommand::atacmdCallbackValid )
                    875:     {
                    876:         (*cmd->completionInfo.async.ataDoneFn)(              cmd->completionInfo.async.target, 
                    877:                                                 (IOService *)this, 
                    878:                                                              cmd, 
                    879:                                                              cmd->completionInfo.async.refcon );
                    880:     }
                    881:     else
                    882:     {
                    883:         cmd->completionInfo.sync.syncer->signal();
                    884:     }
                    885: }
                    886: 
                    887: /*
                    888:  *
                    889:  *
                    890:  */
                    891: IOReturn IOATADevice::message( UInt32 p0, IOService *p1, void *p2 )
                    892: {
                    893:     UInt32                     msgId;
                    894:     IOATADevice                        *ataDev;    
                    895: 
                    896:     msgId  = (UInt32) p0;
                    897:     ataDev = (IOATADevice *)p1;
                    898: 
                    899:     switch ( msgId )
                    900:     {
                    901:         case ataMessageResetStarted:
                    902:             lock_init( resetSem, true, NULL, NULL );
                    903:             IORWLockWrite( resetSem );
                    904:             break;
                    905:         
                    906:         case ataMessageResetComplete:
                    907:             IORWLockUnlock( resetSem );
                    908:             break;
                    909:  
                    910:         default:
                    911:             ;
                    912:     }
                    913: 
                    914:     return kIOReturnSuccess;
                    915: }
                    916: 
                    917: /*
                    918:  *
                    919:  *
                    920:  */
                    921: UInt32 IOATADevice::getUnit()
                    922: {
                    923:     return unit;
                    924: }
                    925: 
                    926: /*
                    927:  *
                    928:  *
                    929:  */
                    930: IOCommandQueue  *IOATADevice::getDeviceQueue()
                    931: {
                    932:     return deviceQueue;
                    933: }
                    934: 
                    935: 
                    936: /*
                    937:  *
                    938:  *
                    939:  */
                    940: ATADeviceType IOATADevice::getDeviceType()
                    941: {
                    942:     return deviceType;
                    943: }
                    944: 
                    945: /*
                    946:  *
                    947:  *
                    948:  */
                    949: bool IOATADevice::getATAPIPktInt()
                    950: {
                    951:     return atapiPktInt;
                    952: }
                    953: 
                    954: /*
                    955:  *
                    956:  *
                    957:  */
                    958: bool IOATADevice::getIdentifyData( ATAIdentify *identifyBuffer )
                    959: {
                    960:     if ( identifyData == NULL )
                    961:     {
                    962:         bzero( identifyBuffer, sizeof(ATAIdentify) );
                    963:         return false;
                    964:     }
                    965: 
                    966:     bcopy( identifyData, identifyBuffer, sizeof(ATAIdentify) );
                    967:     return true;
                    968: }
                    969: 
                    970: /*
                    971:  *
                    972:  *
                    973:  */
                    974: bool IOATADevice::getInquiryData( UInt32 inquiryBufLength, ATAPIInquiry *inquiryBuffer )
                    975: {        
                    976:     bzero( inquiryBuffer, inquiryBufLength );
                    977: 
                    978:     if ( inquiryData == NULL )
                    979:     {
                    980:         return false;
                    981:     }
                    982: 
                    983:     bcopy( inquiryData, inquiryBuffer, inquiryBufLength );
                    984: 
                    985:     return true;
                    986: }
                    987: 
                    988: /*
                    989:  *
                    990:  *
                    991:  */
                    992: bool IOATADevice::init( UInt32 unitNum, IOATAController *ctlr )
                    993: {
                    994:     controller = ctlr;
                    995:     unit       = unitNum;
                    996: 
                    997:     if ( super::init() != true )
                    998:     {
                    999:         return false;
                   1000:     }
                   1001: 
                   1002:     deviceQueue = controller->createDeviceQueue( this ); 
                   1003:     if ( deviceQueue == NULL )
                   1004:     {
                   1005:         return false;
                   1006:     }
                   1007: 
                   1008:     utilCmd = allocCommand();
                   1009:     if ( utilCmd == NULL )
                   1010:     {
                   1011:         return false;
                   1012:     }
                   1013: 
                   1014:     resetSem = IORWLockAlloc();
                   1015:     if ( resetSem == NULL )
                   1016:     {
                   1017:         return false;
                   1018:     }
                   1019: 
                   1020:     return true;
                   1021: }
                   1022: 
                   1023: 
                   1024: /*
                   1025:  *
                   1026:  *
                   1027:  */
                   1028: OSDictionary *IOATADevice::createProperties()
                   1029: {
                   1030:     OSDictionary       *propTable = 0;
                   1031:     OSObject           *regObj;
                   1032:     char               tmpbuf[81];
                   1033:     char               *s, *d;
                   1034:    
                   1035: 
                   1036:     propTable = OSDictionary::withCapacity(ATAMaxProperties);
                   1037:     if ( propTable == NULL )
                   1038:     {
                   1039:         return NULL;
                   1040:     }
                   1041: 
                   1042:     s = (deviceType == ataDeviceATA) ? ATAPropertyProtocolATA : ATAPropertyProtocolATAPI;
                   1043:     regObj = (OSObject *)OSString::withCString( s );
                   1044:     if ( addToRegistry( propTable, regObj, ATAPropertyProtocol ) != true )
                   1045:     {
                   1046:         goto createprop_error;
                   1047:     }
                   1048: 
                   1049:     regObj = (OSObject *)OSNumber::withNumber(unit,32);
                   1050:     if ( addToRegistry( propTable, regObj, ATAPropertyDeviceNumber ) != true )
                   1051:     {
                   1052:         goto createprop_error;
                   1053:     }
                   1054: 
                   1055:     regObj = (OSObject *)OSNumber::withNumber(unit,32);
                   1056:     if ( addToRegistry( propTable, regObj, ATAPropertyLocation ) != true )
                   1057:     {
                   1058:         goto createprop_error;
                   1059:     }
                   1060: 
                   1061:     d = tmpbuf;
                   1062:     stripBlanks( d, identifyData->modelNumber, sizeof(identifyData->modelNumber));
                   1063:     regObj = (OSObject *)OSString::withCString( d );
                   1064:     if ( addToRegistry( propTable, regObj, ATAPropertyModelNumber ) != true )
                   1065:     {
                   1066:         goto createprop_error;
                   1067:     }
                   1068: 
                   1069:     d = tmpbuf;
                   1070:     stripBlanks( d, identifyData->firmwareRevision, sizeof(identifyData->firmwareRevision));
                   1071:     regObj = (OSObject *)OSString::withCString( d );
                   1072:     if ( addToRegistry( propTable, regObj, ATAPropertyFirmwareRev ) != true )
                   1073:     {
                   1074:         goto createprop_error;
                   1075:     }
                   1076: 
                   1077:     if ( inquiryData )
                   1078:     {
                   1079:         stripBlanks( d, inquiryData->vendorName, sizeof(inquiryData->vendorName) );
                   1080:         regObj = (OSObject *)OSString::withCString( d );
                   1081:         if ( addToRegistry( propTable, regObj, ATAPropertyVendorName ) != true )
                   1082:         {
                   1083:             goto createprop_error;
                   1084:         }
                   1085: 
                   1086:         stripBlanks( d, inquiryData->productName, sizeof(inquiryData->productName) );
                   1087:         regObj = (OSObject *)OSString::withCString( d );
                   1088:         if ( addToRegistry( propTable, regObj, ATAPropertyProductName ) != true )
                   1089:         {
                   1090:             goto createprop_error;
                   1091:         }
                   1092: 
                   1093:         stripBlanks( d, inquiryData->productRevision, sizeof(inquiryData->productRevision) );
                   1094:         regObj = (OSObject *)OSString::withCString( d );
                   1095:         if ( addToRegistry( propTable, regObj, ATAPropertyProductRevision ) != true )
                   1096:         {
                   1097:             goto createprop_error;
                   1098:         }
                   1099:     }
                   1100:     return propTable;
                   1101: 
                   1102: createprop_error: ;
                   1103:     propTable->release();
                   1104:     return NULL;
                   1105: }
                   1106: 
                   1107: /*
                   1108:  *
                   1109:  *
                   1110:  */
                   1111: 
                   1112: bool IOATADevice::matchPropertyTable( OSDictionary * table )
                   1113: {
                   1114:   return( controller->matchNubWithPropertyTable( this, table ));
                   1115: }
                   1116: 
                   1117: IOService *IOATADevice::matchLocation( IOService * )
                   1118: {
                   1119: //    IOLog( "IOATADevice::%s - called\n\r", __FUNCTION__ );
                   1120: 
                   1121:     return this;
                   1122: }
                   1123: 
                   1124: /*
                   1125:  *
                   1126:  *
                   1127:  */
                   1128: bool IOATADevice::open( IOService *customer )
                   1129: {
                   1130:     bool               rc;
                   1131: 
                   1132:     rc = super::open( customer );
                   1133:     
                   1134:     if ( rc == true )
                   1135:     {
                   1136:         client = customer;
                   1137:     }
                   1138:     
                   1139:     return rc;
                   1140: }
                   1141: 
                   1142: 
                   1143: /*
                   1144:  *
                   1145:  *
                   1146:  */
                   1147: void IOATADevice::close( IOService *customer )
                   1148: {
                   1149:     super::close( customer );
                   1150:     client = NULL;
                   1151: }
                   1152: 
                   1153: 
                   1154: /*
                   1155:  *
                   1156:  *
                   1157:  */
                   1158: void IOATADevice::free()
                   1159: {
                   1160:     if ( identifyData ) IOFree( identifyData, sizeof(*identifyData) );
                   1161:     if ( inquiryData  ) IOFree( inquiryData,  sizeof(*inquiryData)  );
                   1162:     if ( utilCmd )      utilCmd->release();
                   1163:     if ( reqSenseCmd )  reqSenseCmd->release();
                   1164:     if ( deviceQueue )  deviceQueue->release();
                   1165:     if ( resetSem )    IORWLockFree( resetSem );
                   1166: 
                   1167:     super::free();
                   1168: }
                   1169:     
                   1170: /*
                   1171:  *
                   1172:  *
                   1173:  */
                   1174: IOService *IOATADevice::getClient()
                   1175: {
                   1176:     return client;
                   1177: }
                   1178: 
                   1179: 
                   1180: /*
                   1181:  *
                   1182:  *
                   1183:  */
                   1184: IOATACommand *IOATADevice::allocCommand( UInt32 clientDataSize )
                   1185: {
                   1186:     IOATACommand       *cmd;
                   1187: 
                   1188:     if ( (cmd = controller->allocCommand( clientDataSize )) )
                   1189:     {
                   1190:         cmd->setDevice( this );
                   1191:     }
                   1192:     return cmd;
                   1193: }
                   1194: 
                   1195: /*
                   1196:  *
                   1197:  *
                   1198:  */
                   1199: bool IOATADevice::addToRegistry( OSDictionary *propTable, OSObject *regObj, char *key )
                   1200: {
                   1201:     bool ret;
                   1202: 
                   1203:     if ( regObj == NULL )
                   1204:     {
                   1205:         return false;
                   1206:     }
                   1207: 
                   1208:     ret = propTable->setObject( key, regObj );
                   1209: 
                   1210:     regObj->release();
                   1211: 
                   1212:     return ret;
                   1213: }
                   1214:            
                   1215: /*
                   1216:  *
                   1217:  *
                   1218:  */
                   1219: void IOATADevice::stripBlanks( char *d, char *s, UInt32 l )
                   1220: {
                   1221:     char       *p, c;
                   1222: 
                   1223:     for ( p = d, c = *s; l && c ; l--)
                   1224:     {
                   1225:         c = (*d++ = *s++);
                   1226:         if ( c != ' ' )
                   1227:         {
                   1228:             p = d;
                   1229:         }
                   1230:     }
                   1231:     *p = 0;
                   1232: }   
                   1233: 
                   1234: 
                   1235: /*
                   1236:  *
                   1237:  *
                   1238:  */
                   1239: void IOATADevice::endianConvertData( void *data, void *endianTable )
                   1240: {
                   1241:     EndianTable                *t;
                   1242: 
                   1243:     union EndianPtr 
                   1244:     {
                   1245:         void            *voidPtr;
                   1246:         UInt8          *bytePtr;
                   1247:         UInt16         *shortPtr;
                   1248:         UInt32         *longPtr;
                   1249:         UInt64         *longlongPtr;
                   1250:     } p;
                   1251: 
                   1252:     UInt32             i,j;
                   1253: 
                   1254:     p.voidPtr = data;
                   1255: 
                   1256:     t = (EndianTable *)endianTable;
                   1257: 
                   1258:     for ( ; t->type; t++ )
                   1259:     {
                   1260:         i = t->size/t->type;
                   1261: 
                   1262:         switch ( t->type )
                   1263:         {
                   1264:         
                   1265:             /* Note:
                   1266:              *
                   1267:              * The ATA standard defines identify strings as arrays of short ints,
                   1268:              * with the left-most character of the string as the most significant  
                   1269:              * byte of the short int. Strings are not normally affected by the host
                   1270:              * endianess. However, the way ATA defines strings would cause strings
                   1271:              * to appear byte reversed. We do a manditory short int byte-swap here, 
                   1272:              * although strictly speaking this is not an endian issue.
                   1273:              *
                   1274:              */
                   1275:             case sizeof(UInt8):
                   1276:               for ( j = 0; j < i/2; j++ )
                   1277:               {
                   1278:                   *p.shortPtr++ = OSSwapInt16(*p.shortPtr);
                   1279:               }  
                   1280:               
                   1281:               break;
                   1282:         
                   1283:             case sizeof(UInt16):
                   1284:               for ( j = 0; j < i; j++ )
                   1285:               {
                   1286:                   *p.shortPtr++ = OSSwapLittleToHostInt16(*p.shortPtr);
                   1287:               }  
                   1288:               break;
                   1289: 
                   1290:             case sizeof(UInt32):
                   1291:               for ( j = 0; j < i; j++ )
                   1292:               {
                   1293:                   *p.longPtr++ = OSSwapLittleToHostInt32(*p.longPtr);
                   1294:               }  
                   1295:               break;
                   1296: 
                   1297:             case sizeof(UInt64):
                   1298:               for ( j = 0; j < i; j++ )
                   1299:               {
                   1300:                   *p.longlongPtr++ = OSSwapLittleToHostInt64(*p.longlongPtr);
                   1301:               }  
                   1302:               break;
                   1303: 
                   1304:             default:
                   1305:               ;
                   1306:         }
                   1307:     } 
                   1308: }

unix.superglobalmegacorp.com

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