1/* 2 * Copyright (c) 2000-2008 Apple 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 * 25 * IOATADevConfig.cpp 26 * 27 */ 28 29const int configword = 00; 30const int pioModeNumber = 51; 31const int fieldValidity = 53; 32const int mwDMAWord = 63; 33const int pioAdvancedMode = 64; 34const int minimumDMATime = 65; 35const int recommendDMATime = 66; 36const int pioCycleNoFlow = 67; 37const int pioCycleIORDY = 68; 38const int ultraDMAWord = 88; 39 40#include<IOKit/IOTypes.h> 41#include"IOATATypes.h" 42#include"IOATADevConfig.h" 43#include"IOATABusInfo.h" 44 45 46#ifdef DLOG 47#undef DLOG 48#endif 49 50#ifdef ATA_DEBUG 51#define DLOG(fmt, args...) IOLog(fmt, ## args) 52#else 53#define DLOG(fmt, args...) 54#endif 55 56 57//--------------------------------------------------------------------------- 58 59#define super OSObject 60OSDefineMetaClassAndStructors ( IOATADevConfig, OSObject ) 61 OSMetaClassDefineReservedUnused(IOATADevConfig, 0); 62 OSMetaClassDefineReservedUnused(IOATADevConfig, 1); 63 OSMetaClassDefineReservedUnused(IOATADevConfig, 2); 64 OSMetaClassDefineReservedUnused(IOATADevConfig, 3); 65 OSMetaClassDefineReservedUnused(IOATADevConfig, 4); 66 OSMetaClassDefineReservedUnused(IOATADevConfig, 5); 67 OSMetaClassDefineReservedUnused(IOATADevConfig, 6); 68 OSMetaClassDefineReservedUnused(IOATADevConfig, 7); 69 OSMetaClassDefineReservedUnused(IOATADevConfig, 8); 70 OSMetaClassDefineReservedUnused(IOATADevConfig, 9); 71 OSMetaClassDefineReservedUnused(IOATADevConfig, 10); 72 OSMetaClassDefineReservedUnused(IOATADevConfig, 11); 73 OSMetaClassDefineReservedUnused(IOATADevConfig, 12); 74 OSMetaClassDefineReservedUnused(IOATADevConfig, 13); 75 OSMetaClassDefineReservedUnused(IOATADevConfig, 14); 76 OSMetaClassDefineReservedUnused(IOATADevConfig, 15); 77 OSMetaClassDefineReservedUnused(IOATADevConfig, 16); 78 OSMetaClassDefineReservedUnused(IOATADevConfig, 17); 79 OSMetaClassDefineReservedUnused(IOATADevConfig, 18); 80 OSMetaClassDefineReservedUnused(IOATADevConfig, 19); 81 OSMetaClassDefineReservedUnused(IOATADevConfig, 20); 82 83 84IOATADevConfig* 85IOATADevConfig::atadevconfig(void) 86{ 87 88 IOATADevConfig* config = new IOATADevConfig; 89 90 if( !config ) 91 return 0L; 92 93 if( !config->init() ) 94 { 95 96 return 0L; 97 98 } 99 100 101 return config; 102 103} 104 105 106// intialize the data fields to nil values 107 108/*----------------------------------------------------------------------------- 109 * 110 * 111 *-----------------------------------------------------------------------------*/ 112 113bool 114IOATADevConfig::init( ) 115{ 116 117 if( ! super::init() ) 118 return false; 119 120 _atapiIRQForPacket = kATAPIUnknown; 121 122 _ataPIOMode = 0x00; 123 _ataPIOCycleTime = 0; 124 _ataMultiDMAMode = 0x00; 125 _ataMultiCycleTime = 0; 126 _ataUltraDMAMode = 0x00; 127// _ataUltraCycleTime = 0; 128 129 return true; 130} 131 132 133 134/*----------------------------------------------------------------------------- 135 * 136 * 137 *-----------------------------------------------------------------------------*/ 138 139IOReturn 140IOATADevConfig::initWithBestSelection( const UInt16* identifyData, IOATABusInfo* busInfo) 141{ 142 IOReturn err = kATANoErr; 143 144 err = assignFromData( identifyData ); 145 if( err ) 146 return err; 147 148 // AND mask with the modes supported by the bus controller 149 150 _ataPIOMode = _ataPIOMode & busInfo->getPIOModes(); 151 _ataMultiDMAMode = _ataMultiDMAMode & busInfo->getDMAModes(); 152 _ataUltraDMAMode = _ataUltraDMAMode & busInfo->getUltraModes(); 153 154 // select only one kind of DMA mode, preferring UDMA over MWDMA 155 156 if( _ataUltraDMAMode != 0x00 ) 157 { 158 _ataMultiDMAMode = 0x00; 159 } 160 161 // clear all but the most-significant matching bit to indicate the best match between 162 // device and bus. 163 164 _ataPIOMode = _MostSignificantBit(_ataPIOMode); 165 _ataMultiDMAMode = _MostSignificantBit(_ataMultiDMAMode); 166 _ataUltraDMAMode = _MostSignificantBit(_ataUltraDMAMode); 167 168 return kATANoErr; 169 170} 171 172 173//----------------------------------------------------------------------------- 174IOReturn 175IOATADevConfig::assignFromData( const UInt16* identifyData ) 176{ 177 178 if ( ( identifyData[0] & 0xC000 ) == 0xC000 ) 179 { 180 // unknown device type 181 return kATAErrUnknownType; 182 } 183 184 // for atapi devices, figure out the command-to-packet protocol 185 if( ( identifyData[0] & 0x8000 ) ) 186 { 187 188 // Atapi device that uses INTRQ 189 _atapiIRQForPacket = ( atapiConfig )( ( identifyData[0] & 0x0060 ) >> 5 ); 190 191 } 192 193 194 195 _AssignPIOData ( identifyData ); 196 _AssignDMAData ( identifyData ); 197 _AssignUltraData ( identifyData ); 198 199 return kATANoErr; 200 201} 202 203 204 205/*----------------------------------------------------------------------------- 206 * 207 * 208 *-----------------------------------------------------------------------------*/ 209 210IOReturn 211IOATADevConfig::_AssignPIOData( const UInt16* identifyData) 212{ 213 UInt16 advancedPIO = 0x0000; 214 215 // set internal fields to no modes. 216 _ataPIOCycleTime = 0; 217 _ataPIOMode = 0; 218 219 //Check word 53 bit 1 if advanced fields are valid. 220 if( 0x0002 & identifyData[fieldValidity] ) 221 { 222 223 advancedPIO = (identifyData[ pioAdvancedMode ] & 0x03) << 3 ; 224 225 if(advancedPIO != 0x0000) 226 { 227 228 // set ns cycle time. 229 _ataPIOCycleTime = identifyData[ pioCycleIORDY ]; 230 if( _ataPIOCycleTime == 0 ) 231 { 232 // some devices fail to support cycle times. 233 // supply a default setting that equals PIO mode 3 timing 234 _ataPIOCycleTime = 180; 235 236 } 237 238 // set all lower mode bits as per ATA standards 239 _ataPIOMode = advancedPIO | 0x0007; 240 return kATANoErr; 241 } 242 243 // otherwise fall through and use the mode number in word 51. 244 245 } 246 247 248 249 // Otherwise, this is a basic device 250 switch( identifyData[ pioModeNumber] & 0xFF00 ) 251 { 252 case 0x0200: 253 _ataPIOMode = 0x07; // mode 2, 1, 0 254 _ataPIOCycleTime = 240; 255 break; 256 257 case 0x0100: 258 _ataPIOMode = 0x03; // mode 1, 0 259 _ataPIOCycleTime = 383; 260 break; 261 262 default: 263 _ataPIOMode = 0x01; // mode 0 only. 264 _ataPIOCycleTime = 600; 265 break; 266 267 268 } 269 270 return kATANoErr; 271 272} 273 274 275/*----------------------------------------------------------------------------- 276 * 277 * 278 *-----------------------------------------------------------------------------*/ 279 280IOReturn 281IOATADevConfig::_AssignDMAData(const UInt16* identifyData) 282{ 283 284 // set internal fields to no support 285 _ataMultiDMAMode = 0; 286 _ataMultiCycleTime = 0; 287 288 289 //Check word 53 bit 1 if dma fields are valid. 290 if( 0x0002 & identifyData[fieldValidity] ) 291 { 292 _ataMultiDMAMode = identifyData[mwDMAWord] & 0x0007; 293 294 if( identifyData[recommendDMATime] > identifyData[minimumDMATime] ) 295 { 296 _ataMultiCycleTime = identifyData[recommendDMATime]; 297 298 } else { 299 300 _ataMultiCycleTime = identifyData[minimumDMATime]; 301 } 302 303 } 304 305 return kATANoErr; 306 307 308} 309 310 311 312 313/*----------------------------------------------------------------------------- 314 * 315 * 316 *-----------------------------------------------------------------------------*/ 317 318IOReturn 319IOATADevConfig::_AssignUltraData(const UInt16* identifyData) 320{ 321 322 // set internal fields to no support 323 _ataUltraDMAMode = 0; 324 325 326 //Check word 53 bit 2 if ultra fields are valid. 327 if( 0x0004 & identifyData[fieldValidity] ) 328 { 329 _ataUltraDMAMode = identifyData[ultraDMAWord] & 0x00FF; 330 } 331 332 return kATANoErr; 333 334 335 336} 337 338 339 340/*----------------------------------------------------------------------------- 341 * 342 * 343 *-----------------------------------------------------------------------------*/ 344 345void 346IOATADevConfig::setPacketConfig ( atapiConfig packetConfig) 347{ 348 349 _atapiIRQForPacket = packetConfig; 350 351} 352 353 354/*----------------------------------------------------------------------------- 355 * 356 * 357 *-----------------------------------------------------------------------------*/ 358 359atapiConfig 360IOATADevConfig::getPacketConfig( void ) 361{ 362 363 return _atapiIRQForPacket; 364 365} 366 367 368 369 370/*----------------------------------------------------------------------------- 371 * 372 * 373 *-----------------------------------------------------------------------------*/ 374 375void 376IOATADevConfig::setPIOMode( UInt8 inModeBitMap) 377{ 378 379 _ataPIOMode = inModeBitMap; 380 381 382} 383 384 385/*----------------------------------------------------------------------------- 386 * 387 * 388 *-----------------------------------------------------------------------------*/ 389 390UInt8 391IOATADevConfig::getPIOMode( void ) 392{ 393 394 395 return _ataPIOMode; 396 397} 398 399 400/*----------------------------------------------------------------------------- 401 * 402 * 403 *-----------------------------------------------------------------------------*/ 404 405void 406IOATADevConfig::setDMAMode( UInt8 inModeBitMap ) 407{ 408 409 _ataMultiDMAMode = inModeBitMap; 410 411 412} 413 414 415/*----------------------------------------------------------------------------- 416 * 417 * 418 *-----------------------------------------------------------------------------*/ 419 420UInt8 421IOATADevConfig::getDMAMode( void ) 422{ 423 424 return _ataMultiDMAMode; 425 426} 427 428 429/*----------------------------------------------------------------------------- 430 * 431 * 432 *-----------------------------------------------------------------------------*/ 433 434void 435IOATADevConfig::setUltraMode( UInt8 inModeBitMap ) 436{ 437 438 439 _ataUltraDMAMode = inModeBitMap; 440 441} 442 443 444/*----------------------------------------------------------------------------- 445 * 446 * 447 *-----------------------------------------------------------------------------*/ 448 449UInt8 450IOATADevConfig::getUltraMode( void ) 451{ 452 453 454 return _ataUltraDMAMode; 455 456} 457 458 459/*----------------------------------------------------------------------------- 460 * 461 * 462 *-----------------------------------------------------------------------------*/ 463 464void 465IOATADevConfig::setPIOCycleTime( UInt16 inNS ) 466{ 467 468 469 _ataPIOCycleTime = inNS; 470 471} 472 473 474/*----------------------------------------------------------------------------- 475 * 476 * 477 *-----------------------------------------------------------------------------*/ 478 479UInt16 480IOATADevConfig::getPIOCycleTime( void ) 481{ 482 483 return _ataPIOCycleTime; 484 485 486} 487 488 489/*----------------------------------------------------------------------------- 490 * 491 * 492 *-----------------------------------------------------------------------------*/ 493 494void 495IOATADevConfig::setDMACycleTime( UInt16 inNS ) 496{ 497 498 499 _ataMultiCycleTime = inNS; 500 501} 502 503 504/*----------------------------------------------------------------------------- 505 * 506 * 507 *-----------------------------------------------------------------------------*/ 508 509UInt16 510IOATADevConfig::getDMACycleTime( void ) 511{ 512 513 return _ataMultiCycleTime; 514 515 516} 517 518 519/*----------------------------------------------------------------------------- 520 * 521 * 522 *-----------------------------------------------------------------------------*/ 523 524UInt8 525IOATADevConfig::_MostSignificantBit( UInt8 inByte) 526{ 527 // return 0 if input is 0 528 if( inByte == 0) 529 return inByte; 530 531 // start at the top and work down. 532 UInt8 mask = 0x80; 533 534 for( int i = 7; i >0; i--) 535 { 536 // if it masks, return. 537 if( mask & inByte ) 538 { 539 return mask; 540 } 541 542 // shift one right and try again. 543 mask >>= 1; 544 } 545 546 // bit zero is the winner. 547 return 0x01; 548 549} 550 551/***************************************************************************** 552** Function bitSigToNumeric 553** This function converts a bit-significant value into an integer which 554** corresponds to the highest-order bit which is active. For example, 555** 0x0035 is converted to 5, which is the bit-number of the high bit of 0x0035. 556** Input variable binary = zero is technically illegal; the routine does not check 557** explicitly for this value, but rather returns 0xFFFF as a result of no 558** bit being found, and the return value is decemented below zero. The 559** loop terminates when i becomes zero because of binary = 0. 560** Implicit maximum value of binary: 0x00FF. 561** 562** Explicit Inputs: 563** binary - a non-zero binary number (0 has no corresponding bit number) 564** Return Value: 565** integer - the bit-number of the highest bit active in binary. 566** 567******************************************************************************/ 568 569UInt8 570IOATADevConfig::bitSigToNumeric(UInt16 binary) 571{ 572 UInt16 i, integer; 573 574 /* Test all bits from left to right, terminating at the first non-zero bit. */ 575 for (i = 0x0080, integer = 7; ((i & binary) == 0 && i != 0) ; i >>= 1, integer-- ) 576 {;} 577 return (integer); 578} /* end BitSigToNumeric() */ 579 580bool 581IOATADevConfig::sDriveSupports48BitLBA( const UInt16* identifyData ) 582{ 583 584 if( (identifyData[83] & 0x0400) 585 && (identifyData[86] & 0x0400)) 586 { 587 return true; 588 } 589 590 return false; 591} 592 593UInt32 594IOATADevConfig::sDriveExtendedLBASize( UInt32* lbaHi, UInt32* lbaLo, const UInt16* identifyData) 595{ 596 597 UInt32 lowerLBA = 0; 598 UInt32 upperLBA = 0; 599 600 if( IOATADevConfig::sDriveSupports48BitLBA( identifyData ) ) 601 { 602 lowerLBA = identifyData[ 100 ] | ( identifyData[101] << 16 ); 603 upperLBA = identifyData[102] | ( identifyData[103] << 16 ); 604 } 605 606 *lbaLo = lowerLBA; 607 *lbaHi = upperLBA; 608 609 return lowerLBA; 610 611}