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