|
|
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: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * IOATAHDDrive.cpp - Generic ATA disk driver. ! 26: * ! 27: * HISTORY ! 28: * Aug 27, 1999 jliu - Ported from AppleATADrive. ! 29: */ ! 30: ! 31: #include <IOKit/assert.h> ! 32: #include <IOKit/storage/ata/IOATAHDDrive.h> ! 33: #include <IOKit/storage/ata/IOATAHDDriveNub.h> ! 34: ! 35: #define super IOService ! 36: OSDefineMetaClassAndStructors( IOATAHDDrive, IOService ) ! 37: ! 38: // -------------------------------------------------------------------------- ! 39: // init() method. ! 40: ! 41: bool ! 42: IOATAHDDrive::init(OSDictionary * properties) ! 43: { ! 44: _ataDevice = 0; // provider (nub). ! 45: _workloop = 0; // workloop to service command retries. ! 46: _evSource = 0; // signals workloop that work is available. ! 47: _retryQueue = 0; // queue object to store retry commands. ! 48: ! 49: return (super::init(properties)); ! 50: } ! 51: ! 52: // -------------------------------------------------------------------------- ! 53: // Override probe() method inherited from IOService. ! 54: ! 55: IOService * ! 56: IOATAHDDrive::probe(IOService * provider, SInt32 * score) ! 57: { ! 58: if (!super::probe(provider, score)) ! 59: return 0; ! 60: ! 61: // Our provider must be a IOATADevice nub, most likely created ! 62: // by an IOATAController instance. ! 63: // ! 64: IOATADevice * device = OSDynamicCast(IOATADevice, provider); ! 65: if (!device) ! 66: return 0; // IOATADevice nub not found. ! 67: ! 68: // Do ATA device type matching. ! 69: // ! 70: if (device->getDeviceType() != reportATADeviceType()) ! 71: return 0; // error, type mismatch. ! 72: ! 73: return this; // probe successful. ! 74: } ! 75: ! 76: // -------------------------------------------------------------------------- ! 77: // Starts up the driver and spawn a nub. ! 78: ! 79: bool ! 80: IOATAHDDrive::start(IOService * provider) ! 81: { ! 82: // First call start() in our superclass. ! 83: // ! 84: if (!super::start(provider)) ! 85: return false; ! 86: ! 87: // Cache our provider. ! 88: // ! 89: _ataDevice = OSDynamicCast(IOATADevice, provider); ! 90: if (!_ataDevice) ! 91: return false; ! 92: ! 93: // Open our provider. ! 94: // ! 95: _ataDevice->retain(); ! 96: _ataDevice->open(this); ! 97: ! 98: // Inspect the provider. ! 99: // ! 100: inspectDevice(_ataDevice); ! 101: ! 102: // Cache the drive unit number (master/slave assignment). ! 103: // ! 104: _unit = _ataDevice->getUnit(); ! 105: ! 106: // Allocate a workloop which is solely responsible for performing ! 107: // command retries. It is otherwise not involved in the data path. ! 108: // ! 109: _workloop = IOWorkLoop::workLoop(); ! 110: if (!_workloop) ! 111: return false; ! 112: ! 113: // Create an event source to trigger the workloop when a command ! 114: // needs to be retried. ! 115: // ! 116: _evSource = IOInterruptEventSource::interruptEventSource( ! 117: this, ! 118: (IOInterruptEventAction) &IOATAHDDrive::dequeueCommands, ! 119: 0); ! 120: ! 121: if (!_evSource || ! 122: (_workloop->addEventSource(_evSource) != kIOReturnSuccess)) ! 123: return false; ! 124: ! 125: // Initialize _retryQueue to store sync and retry command objects. ! 126: // ! 127: _retryQueue = IOATACommandQueue::commmandQueue(); ! 128: if (!_retryQueue) ! 129: return false; ! 130: ! 131: // Select ATA timing. ! 132: // ! 133: if (!selectTimingProtocol()) ! 134: return false; ! 135: ! 136: // Enable retry queue. ! 137: // ! 138: _retryQueue->setEnabled(true); ! 139: ! 140: return (createNub(provider)); ! 141: } ! 142: ! 143: // -------------------------------------------------------------------------- ! 144: // Release allocated resources. ! 145: ! 146: void ! 147: IOATAHDDrive::free() ! 148: { ! 149: if (_evSource) ! 150: _evSource->release(); ! 151: if (_workloop) ! 152: _workloop->release(); ! 153: if (_ataDevice) ! 154: _ataDevice->release(); ! 155: if (_retryQueue) ! 156: _retryQueue->release(); ! 157: ! 158: super::free(); ! 159: } ! 160: ! 161: // -------------------------------------------------------------------------- ! 162: // Fetch information about the ATA device nub. ! 163: ! 164: void ! 165: IOATAHDDrive::inspectDevice(IOService * provider) ! 166: { ! 167: OSString * string; ! 168: IOATADevice * ataDevice = OSDynamicCast(IOATADevice, provider); ! 169: if (!ataDevice) ! 170: return; ! 171: ! 172: // Fetch ATA device information from the nub. ! 173: // ! 174: string = OSDynamicCast(OSString, ! 175: ataDevice->getProperty(ATAPropertyModelNumber)); ! 176: if (string) { ! 177: strncpy(_model, string->getCStringNoCopy(), 40); ! 178: _model[40] = '\0'; ! 179: } ! 180: ! 181: string = OSDynamicCast(OSString, ! 182: ataDevice->getProperty(ATAPropertyFirmwareRev)); ! 183: if (string) { ! 184: strncpy(_revision, string->getCStringNoCopy(), 8); ! 185: _revision[8] = '\0'; ! 186: } ! 187: } ! 188: ! 189: // -------------------------------------------------------------------------- ! 190: // Report the type of ATA device (ATA vs. ATAPI). ! 191: ! 192: ATADeviceType ! 193: IOATAHDDrive::reportATADeviceType() const ! 194: { ! 195: return ataDeviceATA; ! 196: } ! 197: ! 198: // -------------------------------------------------------------------------- ! 199: // Returns the device type. ! 200: ! 201: const char * ! 202: IOATAHDDrive::getDeviceTypeName() ! 203: { ! 204: return kDeviceTypeHardDisk; ! 205: } ! 206: ! 207: // -------------------------------------------------------------------------- ! 208: // Instantiate an ATA specific subclass of IOHDDriveNub. ! 209: ! 210: IOService * IOATAHDDrive::instantiateNub() ! 211: { ! 212: IOService * nub = new IOATAHDDriveNub; ! 213: return nub; ! 214: } ! 215: ! 216: // -------------------------------------------------------------------------- ! 217: // Returns an IOATAHDDriveNub. ! 218: ! 219: bool IOATAHDDrive::createNub(IOService * provider) ! 220: { ! 221: IOService * nub; ! 222: ! 223: // Instantiate a generic hard disk nub so a generic driver ! 224: // can match above us. ! 225: // ! 226: nub = instantiateNub(); ! 227: ! 228: if (nub == 0) { ! 229: IOLog("%s: instantiateNub() failed\n", getName()); ! 230: return false; ! 231: } ! 232: ! 233: nub->init(); ! 234: ! 235: if (!nub->attach(this)) ! 236: IOPanic("IOATAHDDrive::createNub; couldn't attach IOATAHDDriveNub"); ! 237: ! 238: nub->registerService(); ! 239: ! 240: return true; ! 241: } ! 242: ! 243: // -------------------------------------------------------------------------- ! 244: // Handles read/write requests. ! 245: ! 246: IOReturn IOATAHDDrive::doAsyncReadWrite(IOMemoryDescriptor * buffer, ! 247: UInt32 block, ! 248: UInt32 nblks, ! 249: gdCompletionFunction action, ! 250: IOService * target, ! 251: void * param) ! 252: { ! 253: IOReturn ret; ! 254: IOATACommand * cmd = ataCommandReadWrite(buffer, block, nblks); ! 255: if (!cmd) ! 256: return kIOReturnNoMemory; ! 257: ! 258: ret = getIOReturn(asyncExecute(cmd, target, action, param)); ! 259: ! 260: cmd->release(); ! 261: ! 262: return ret; ! 263: } ! 264: ! 265: // -------------------------------------------------------------------------- ! 266: // Eject the media in the drive. ! 267: ! 268: IOReturn IOATAHDDrive::doEjectMedia() ! 269: { ! 270: return kIOReturnUnsupported; // No support for removable ATA devices. ! 271: } ! 272: ! 273: // -------------------------------------------------------------------------- ! 274: // Format the media in the drive. ! 275: // ATA devices does not support low level formatting. ! 276: ! 277: IOReturn IOATAHDDrive::doFormatMedia(UInt64 byteCapacity) ! 278: { ! 279: return kIOReturnUnsupported; ! 280: } ! 281: ! 282: // -------------------------------------------------------------------------- ! 283: // Returns disk capacity. ! 284: ! 285: UInt32 IOATAHDDrive::doGetFormatCapacities(UInt64 * capacities, ! 286: UInt32 capacitiesMaxCount) const ! 287: { ! 288: UInt32 blockCount = 0; ! 289: UInt32 blockSize = 0; ! 290: ! 291: assert(_ataDevice); ! 292: ! 293: if (_ataDevice->getDeviceCapacity(&blockCount, &blockSize) && ! 294: (capacities != NULL) && (capacitiesMaxCount > 0)) { ! 295: UInt64 count = blockCount; ! 296: UInt64 size = blockSize; ! 297: ! 298: *capacities = size * (count + 1); ! 299: ! 300: return 1; ! 301: } ! 302: ! 303: return 0; ! 304: } ! 305: ! 306: // -------------------------------------------------------------------------- ! 307: // Lock the media and prevent a user-initiated eject. ! 308: ! 309: IOReturn IOATAHDDrive::doLockUnlockMedia(bool doLock) ! 310: { ! 311: return kIOReturnUnsupported; // No removable ATA device support. ! 312: } ! 313: ! 314: // -------------------------------------------------------------------------- ! 315: // Flush the write-cache to the physical media. ! 316: ! 317: IOReturn IOATAHDDrive::doSynchronizeCache() ! 318: { ! 319: // FIXME - A lie, need implementation. ! 320: // ! 321: return kIOReturnSuccess; ! 322: } ! 323: ! 324: // -------------------------------------------------------------------------- ! 325: // Handle a Start Unit command. ! 326: ! 327: IOReturn ! 328: IOATAHDDrive::doStart() ! 329: { ! 330: return kIOReturnSuccess; ! 331: } ! 332: ! 333: // -------------------------------------------------------------------------- ! 334: // Handle a Stop Unit command. ! 335: ! 336: IOReturn ! 337: IOATAHDDrive::doStop() ! 338: { ! 339: return kIOReturnSuccess; ! 340: } ! 341: ! 342: // -------------------------------------------------------------------------- ! 343: // Return device identification strings. ! 344: ! 345: char * IOATAHDDrive::getAdditionalDeviceInfoString() ! 346: { ! 347: return ("[ATA]"); ! 348: } ! 349: ! 350: char * IOATAHDDrive::getProductString() ! 351: { ! 352: return _model; ! 353: } ! 354: ! 355: char * IOATAHDDrive::getRevisionString() ! 356: { ! 357: return _revision; ! 358: } ! 359: ! 360: char * IOATAHDDrive::getVendorString() ! 361: { ! 362: return NULL; ! 363: } ! 364: ! 365: // -------------------------------------------------------------------------- ! 366: // Report the device block size in bytes. We ask the device nub for the ! 367: // block size. We expect this to be 512-bytes. ! 368: ! 369: IOReturn IOATAHDDrive::reportBlockSize(UInt64 * blockSize) ! 370: { ! 371: UInt32 blkCount = 0; ! 372: UInt32 blkSize = 0; ! 373: ! 374: assert(_ataDevice); ! 375: ! 376: if (!_ataDevice->getDeviceCapacity(&blkCount, &blkSize)) ! 377: return kIOReturnNoDevice; ! 378: ! 379: *blockSize = blkSize; ! 380: return kIOReturnSuccess; ! 381: } ! 382: ! 383: // -------------------------------------------------------------------------- ! 384: // Report the media in the ATA device as non-ejectable. ! 385: ! 386: IOReturn IOATAHDDrive::reportEjectability(bool * isEjectable) ! 387: { ! 388: *isEjectable = false; ! 389: return kIOReturnSuccess; ! 390: } ! 391: ! 392: // -------------------------------------------------------------------------- ! 393: // Fixed media, locking is invalid. ! 394: ! 395: IOReturn IOATAHDDrive::reportLockability(bool * isLockable) ! 396: { ! 397: *isLockable = false; ! 398: return kIOReturnSuccess; ! 399: } ! 400: ! 401: // -------------------------------------------------------------------------- ! 402: // Report the polling requirements for a removable media. ! 403: ! 404: IOReturn IOATAHDDrive::reportPollRequirements(bool * pollRequired, ! 405: bool * pollIsExpensive) ! 406: { ! 407: *pollIsExpensive = false; ! 408: *pollRequired = false; ! 409: ! 410: return kIOReturnSuccess; ! 411: } ! 412: ! 413: // -------------------------------------------------------------------------- ! 414: // Report the max number of bytes transferred for an ATA read command. ! 415: ! 416: IOReturn IOATAHDDrive::reportMaxReadTransfer(UInt64 blocksize, UInt64 * max) ! 417: { ! 418: *max = blocksize * kIOATAMaxBlocksPerXfer; ! 419: return kIOReturnSuccess; ! 420: } ! 421: ! 422: // -------------------------------------------------------------------------- ! 423: // Report the max number of bytes transferred for an ATA write command. ! 424: ! 425: IOReturn IOATAHDDrive::reportMaxWriteTransfer(UInt64 blocksize, UInt64 * max) ! 426: { ! 427: // Same as read transfer limits. ! 428: // ! 429: return reportMaxReadTransfer(blocksize, max); ! 430: } ! 431: ! 432: // -------------------------------------------------------------------------- ! 433: // Returns the maximum addressable sector number. ! 434: ! 435: IOReturn IOATAHDDrive::reportMaxValidBlock(UInt64 * maxBlock) ! 436: { ! 437: UInt32 blockCount = 0; ! 438: UInt32 blockSize = 0; ! 439: ! 440: assert(_ataDevice && maxBlock); ! 441: ! 442: if (!_ataDevice->getDeviceCapacity(&blockCount, &blockSize)) ! 443: return kIOReturnNoDevice; ! 444: ! 445: *maxBlock = blockCount; ! 446: ! 447: return kIOReturnSuccess; ! 448: } ! 449: ! 450: // -------------------------------------------------------------------------- ! 451: // Report whether the media is currently present, and whether a media ! 452: // change has been registered since the last reporting. ! 453: ! 454: IOReturn IOATAHDDrive::reportMediaState(bool * mediaPresent, bool * changed) ! 455: { ! 456: *mediaPresent = true; ! 457: *changed = true; ! 458: ! 459: return kIOReturnSuccess; ! 460: } ! 461: ! 462: // -------------------------------------------------------------------------- ! 463: // Report whether the media is removable. ! 464: ! 465: IOReturn IOATAHDDrive::reportRemovability(bool * isRemovable) ! 466: { ! 467: *isRemovable = false; ! 468: return kIOReturnSuccess; ! 469: } ! 470: ! 471: // -------------------------------------------------------------------------- ! 472: // Report if the media is write-protected. ! 473: ! 474: IOReturn IOATAHDDrive::reportWriteProtection(bool * isWriteProtected) ! 475: { ! 476: *isWriteProtected = false; ! 477: return kIOReturnSuccess; ! 478: } ! 479: ! 480: // -------------------------------------------------------------------------- ! 481: // Handles messages from our provider. ! 482: ! 483: IOReturn ! 484: IOATAHDDrive::message(UInt32 type, IOService * provider, void * argument) ! 485: { ! 486: IOReturn ret = kIOReturnSuccess; ! 487: ! 488: switch (type) ! 489: { ! 490: case ataMessageInitDevice: ! 491: if (!selectTimingProtocol(_timingProtocol)) ! 492: ret = kIOReturnIOError; ! 493: break; ! 494: ! 495: case ataMessageResetStarted: ! 496: // ! 497: // Freeze the sync/retry queue. ! 498: // What about async commands? ! 499: // ! 500: _retryQueue->setEnabled(false); ! 501: break; ! 502: ! 503: case ataMessageResetComplete: ! 504: // ! 505: // Re-enable the sync/retry queue. ! 506: // ! 507: _retryQueue->setEnabled(true); ! 508: _evSource->interruptOccurred(0, 0, 0); ! 509: break; ! 510: ! 511: default: ! 512: ret = super::message(type, provider, argument); ! 513: break; ! 514: } ! 515: ! 516: return ret; ! 517: } ! 518: ! 519: // -------------------------------------------------------------------------- ! 520: // Perform translation from ATAReturnCode to IOReturn codes. ! 521: ! 522: static inline IOReturn ! 523: getIOReturnFunc(ATAReturnCode code) ! 524: { ! 525: switch (code) { ! 526: case ataReturnNoError: ! 527: return kIOReturnSuccess; ! 528: ! 529: case ataReturnNotSupported: ! 530: return kIOReturnUnsupported; ! 531: ! 532: case ataReturnNoResource: ! 533: return kIOReturnNoResources; ! 534: ! 535: case ataReturnErrorBusy: ! 536: return kIOReturnBusy; ! 537: ! 538: case ataReturnErrorInterruptTimeout: ! 539: return kIOReturnTimeout; ! 540: ! 541: case ataReturnErrorRetryPIO: ! 542: case ataReturnErrorStatus: ! 543: case ataReturnErrorProtocol: ! 544: default: ! 545: return kIOReturnIOError; ! 546: } ! 547: } ! 548: ! 549: IOReturn ! 550: IOATAHDDrive::getIOReturn(ATAResults * result) ! 551: { ! 552: // Translate the return code in an ATAResult structure. ! 553: // ! 554: return getIOReturnFunc(result->returnCode); ! 555: } ! 556: ! 557: IOReturn ! 558: IOATAHDDrive::getIOReturn(ATAReturnCode code) ! 559: { ! 560: return getIOReturnFunc(code); ! 561: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.