|
|
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: * IOATAPIHDDrive.h - Generic ATAPI Direct-Access driver. ! 26: * ! 27: * HISTORY ! 28: * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. ! 29: */ ! 30: ! 31: #include <IOKit/assert.h> ! 32: #include <IOKit/storage/ata/IOATAPIHDDrive.h> ! 33: #include <IOKit/storage/ata/IOATAPIHDDriveNub.h> ! 34: ! 35: #define super IOATAHDDrive ! 36: OSDefineMetaClassAndStructors( IOATAPIHDDrive, IOATAHDDrive ) ! 37: ! 38: // -------------------------------------------------------------------------- ! 39: // Override the init() method in IOATAHDDrive. ! 40: ! 41: bool ! 42: IOATAPIHDDrive::init(OSDictionary * properties) ! 43: { ! 44: _mediaPresent = false; ! 45: _isRemovable = false; ! 46: ! 47: return (super::init(properties)); ! 48: } ! 49: ! 50: // -------------------------------------------------------------------------- ! 51: // Override probe() method inherited from IOATAHDDrive. We need to ! 52: // perform additional matching on ATAPI device type from the Inquiry data. ! 53: ! 54: IOService * ! 55: IOATAPIHDDrive::probe(IOService * provider, SInt32 * score) ! 56: { ! 57: UInt8 deviceType; ! 58: ! 59: // Our provider must be a IOATADevice nub, most likely created ! 60: // by an IOATAController instance. ! 61: // ! 62: IOATADevice * device = OSDynamicCast(IOATADevice, provider); ! 63: if (!device) ! 64: return 0; // IOATADevice nub not found. ! 65: ! 66: // Let superclass have a go at probe first. ! 67: // ! 68: if (!super::probe(provider, score)) ! 69: return 0; ! 70: ! 71: // Perform ATAPI type matching, CD-ROM, Direct-Access, Tape, etc. ! 72: // ! 73: if (!device->getInquiryData(1, (ATAPIInquiry *) &deviceType) || ! 74: !matchATAPIDeviceType(deviceType & 0x1f)) ! 75: return 0; ! 76: ! 77: return this; // probe successful. ! 78: } ! 79: ! 80: // -------------------------------------------------------------------------- ! 81: // Report as an ATAPI device. ! 82: ! 83: ATADeviceType ! 84: IOATAPIHDDrive::reportATADeviceType() const ! 85: { ! 86: return ataDeviceATAPI; ! 87: } ! 88: ! 89: // -------------------------------------------------------------------------- ! 90: // Looks for an ATAPI device which is a direct-access device. ! 91: ! 92: bool ! 93: IOATAPIHDDrive::matchATAPIDeviceType(UInt8 type) ! 94: { ! 95: if (type == kIOATAPIDeviceTypeDirectAccess) ! 96: return true; ! 97: return false; ! 98: } ! 99: ! 100: // -------------------------------------------------------------------------- ! 101: // Gather information about the ATAPI device nub. ! 102: ! 103: void ! 104: IOATAPIHDDrive::inspectDevice(IOService * provider) ! 105: { ! 106: OSString * string; ! 107: IOATADevice * ataDevice = OSDynamicCast(IOATADevice, provider); ! 108: if (!ataDevice) ! 109: return; ! 110: ! 111: // Fetch ATAPI device information from the nub. ! 112: // ! 113: string = OSDynamicCast(OSString, ! 114: ataDevice->getProperty(ATAPropertyVendorName)); ! 115: if (string) { ! 116: strncpy(_vendor, string->getCStringNoCopy(), 8); ! 117: _vendor[8] = '\0'; ! 118: } ! 119: ! 120: string = OSDynamicCast(OSString, ! 121: ataDevice->getProperty(ATAPropertyProductName)); ! 122: if (string) { ! 123: strncpy(_product, string->getCStringNoCopy(), 16); ! 124: _product[16] = '\0'; ! 125: } ! 126: ! 127: string = OSDynamicCast(OSString, ! 128: ataDevice->getProperty(ATAPropertyProductRevision)); ! 129: if (string) { ! 130: strncpy(_revision, string->getCStringNoCopy(), 4); ! 131: _revision[4] = '\0'; ! 132: } ! 133: } ! 134: ! 135: // -------------------------------------------------------------------------- ! 136: // Handles read/write requests. ! 137: ! 138: IOReturn IOATAPIHDDrive::doAsyncReadWrite(IOMemoryDescriptor * buffer, ! 139: UInt32 block, ! 140: UInt32 nblks, ! 141: gdCompletionFunction action, ! 142: IOService * target, ! 143: void * param) ! 144: { ! 145: IOReturn ret; ! 146: IOATACommand * cmd = atapiCommandReadWrite(buffer, block, nblks); ! 147: if (!cmd) ! 148: return kIOReturnNoMemory; ! 149: ! 150: ret = getIOReturn(asyncExecute(cmd, target, action, param)); ! 151: ! 152: cmd->release(); ! 153: ! 154: return ret; ! 155: } ! 156: ! 157: // -------------------------------------------------------------------------- ! 158: // Eject the media in the removable drive. ! 159: ! 160: IOReturn ! 161: IOATAPIHDDrive::doEjectMedia() ! 162: { ! 163: IOReturn ret; ! 164: IOATACommand * cmd = atapiCommandStartStopUnit(0, /* senseData */ ! 165: false, /* start unit */ ! 166: true, /* Load/Eject */ ! 167: false); /* Immediate */ ! 168: ! 169: if (!cmd) ! 170: return kIOReturnNoMemory; ! 171: ! 172: ret = getIOReturn(syncExecute(cmd)); ! 173: ! 174: cmd->release(); ! 175: ! 176: return ret; ! 177: } ! 178: ! 179: // -------------------------------------------------------------------------- ! 180: // Format the media in the drive. ! 181: ! 182: IOReturn ! 183: IOATAPIHDDrive::doFormatMedia(UInt64 /* byteCapacity */) ! 184: { ! 185: return kIOReturnUnsupported; ! 186: } ! 187: ! 188: // -------------------------------------------------------------------------- ! 189: // Lock/unlock the media in the removable drive. ! 190: ! 191: IOReturn ! 192: IOATAPIHDDrive::doLockUnlockMedia(bool doLock) ! 193: { ! 194: IOReturn ret; ! 195: IOATACommand * cmd = atapiCommandPreventAllowRemoval(doLock); ! 196: if (!cmd) ! 197: return kIOReturnNoMemory; ! 198: ! 199: ret = getIOReturn(syncExecute(cmd)); ! 200: ! 201: cmd->release(); ! 202: ! 203: return ret; ! 204: } ! 205: ! 206: // -------------------------------------------------------------------------- ! 207: // Sync the write cache. ! 208: ! 209: IOReturn ! 210: IOATAPIHDDrive::doSynchronizeCache() ! 211: { ! 212: return kIOReturnSuccess; ! 213: } ! 214: ! 215: // -------------------------------------------------------------------------- ! 216: // Start up the drive. ! 217: ! 218: IOReturn ! 219: IOATAPIHDDrive::doStart() ! 220: { ! 221: return doStartStop(true); ! 222: } ! 223: ! 224: // -------------------------------------------------------------------------- ! 225: // Stop the drive. ! 226: ! 227: IOReturn ! 228: IOATAPIHDDrive::doStop() ! 229: { ! 230: return doStartStop(false); ! 231: } ! 232: ! 233: // -------------------------------------------------------------------------- ! 234: // Issue a START/STOP Unit command. ! 235: ! 236: IOReturn ! 237: IOATAPIHDDrive::doStartStop(bool doStart) ! 238: { ! 239: IOReturn ret; ! 240: IOATACommand * cmd; ! 241: ! 242: cmd = atapiCommandStartStopUnit(0, /* senseData */ ! 243: doStart, /* start unit */ ! 244: false, /* Load/Eject */ ! 245: false); /* Immediate operation */ ! 246: ! 247: if (!cmd) return kIOReturnNoMemory; ! 248: ! 249: ret = getIOReturn(syncExecute(cmd)); ! 250: ! 251: cmd->release(); ! 252: ! 253: return ret; ! 254: } ! 255: ! 256: // -------------------------------------------------------------------------- ! 257: // Return device identification strings ! 258: ! 259: char * IOATAPIHDDrive::getVendorString() ! 260: { ! 261: return _vendor; ! 262: } ! 263: ! 264: char * IOATAPIHDDrive::getProductString() ! 265: { ! 266: return _product; ! 267: } ! 268: ! 269: char * IOATAPIHDDrive::getRevisionString() ! 270: { ! 271: return _revision; ! 272: } ! 273: ! 274: char * IOATAPIHDDrive::getAdditionalDeviceInfoString() ! 275: { ! 276: return ("[ATAPI]"); ! 277: } ! 278: ! 279: // -------------------------------------------------------------------------- ! 280: // Report whether the media in the drive is ejectable. ! 281: ! 282: IOReturn ! 283: IOATAPIHDDrive::reportEjectability(bool * isEjectable) ! 284: { ! 285: *isEjectable = true; /* default: if it's removable, it's ejectable */ ! 286: return kIOReturnSuccess; ! 287: } ! 288: ! 289: // -------------------------------------------------------------------------- ! 290: // Report whether the drive can prevent user-initiated ejects by locking ! 291: // the media in the drive. ! 292: ! 293: IOReturn ! 294: IOATAPIHDDrive::reportLockability(bool * isLockable) ! 295: { ! 296: *isLockable = true; /* default: if it's removable, it's lockable */ ! 297: return kIOReturnSuccess; ! 298: } ! 299: ! 300: // -------------------------------------------------------------------------- ! 301: // Report our polling requirments. ! 302: ! 303: IOReturn ! 304: IOATAPIHDDrive::reportPollRequirements(bool * pollRequired, ! 305: bool * pollIsExpensive) ! 306: { ! 307: *pollIsExpensive = false; ! 308: *pollRequired = _isRemovable; ! 309: return kIOReturnSuccess; ! 310: } ! 311: ! 312: // -------------------------------------------------------------------------- ! 313: // Report the current state of the media. ! 314: ! 315: IOReturn ! 316: IOATAPIHDDrive::reportMediaState(bool * mediaPresent, ! 317: bool * changed) ! 318: { ! 319: IOATACommand * cmd; ! 320: ATAResults results; ! 321: IOReturn ret = kIOReturnSuccess; ! 322: UInt8 senseData[18]; ! 323: IOMemoryDescriptor * senseDesc; ! 324: ! 325: assert(mediaPresent && changed); ! 326: ! 327: senseDesc = IOMemoryDescriptor::withAddress(senseData, ! 328: sizeof(senseData), ! 329: kIODirectionIn); ! 330: if (!senseDesc) ! 331: return kIOReturnNoMemory; ! 332: ! 333: cmd = atapiCommandTestUnitReady(senseDesc); ! 334: if (!cmd) ! 335: return kIOReturnNoMemory; ! 336: ! 337: // Execute the Test Unit Ready command with no retries. ! 338: // ! 339: syncExecute(cmd, ATADefaultTimeout, 0); ! 340: ! 341: // Release the memory descriptor. ! 342: // ! 343: senseDesc->release(); ! 344: ! 345: if (cmd->getResults(&results) == ataReturnNoError) ! 346: { ! 347: *mediaPresent = true; ! 348: *changed = (*mediaPresent != _mediaPresent); ! 349: _mediaPresent = true; ! 350: } ! 351: else ! 352: { ! 353: UInt8 errorCode = senseData[0]; ! 354: UInt8 senseKey = senseData[2]; ! 355: ! 356: #ifdef DEBUG_LOG ! 357: UInt8 senseCode = senseData[12]; ! 358: UInt8 senseQualifier = senseData[13]; ! 359: ! 360: IOLog("-- reportMediaState --\n"); ! 361: IOLog("Error code: %02x\n", errorCode); ! 362: IOLog("Sense Key : %02x\n", senseKey); ! 363: IOLog("ASC : %02x\n", senseCode); ! 364: IOLog("ASCQ : %02x\n", senseQualifier); ! 365: #endif ! 366: ! 367: *mediaPresent = false; ! 368: *changed = (*mediaPresent != _mediaPresent); ! 369: _mediaPresent = false; ! 370: ! 371: // The error code field for ATAPI request sense should always ! 372: // be 0x70 or 0x71. Otherwise ignore the sense data. ! 373: // ! 374: if ((errorCode == 0x70) || (errorCode == 0x71)) ! 375: { ! 376: switch (senseKey) { ! 377: case 5: /* Invalid ATAPI command */ ! 378: ret = kIOReturnIOError; ! 379: break; ! 380: ! 381: case 2: /* Not ready */ ! 382: break; ! 383: ! 384: default: ! 385: break; ! 386: } ! 387: } ! 388: } ! 389: ! 390: cmd->release(); ! 391: ! 392: #if 0 ! 393: IOLog("%s: media present %s, changed %s\n", getName(), ! 394: *mediaPresent ? "Y" : "N", ! 395: *changed ? "Y" : "N" ! 396: ); ! 397: #endif ! 398: ! 399: #ifndef DISKPM ! 400: if (*changed && *mediaPresent) ! 401: doStart(); ! 402: #endif ! 403: ! 404: return ret; ! 405: } ! 406: ! 407: // -------------------------------------------------------------------------- ! 408: // Report media removability. ! 409: ! 410: IOReturn ! 411: IOATAPIHDDrive::reportRemovability(bool * isRemovable) ! 412: { ! 413: UInt8 inqBuf[2]; ! 414: ! 415: *isRemovable = false; ! 416: ! 417: if (_ataDevice->getInquiryData(sizeof(inqBuf), (ATAPIInquiry *) inqBuf)) ! 418: { ! 419: if (inqBuf[1] & 0x80) ! 420: *isRemovable = _isRemovable = true; ! 421: else ! 422: *isRemovable = _isRemovable = false; ! 423: } ! 424: ! 425: return kIOReturnSuccess; ! 426: } ! 427: ! 428: // -------------------------------------------------------------------------- ! 429: // Report whether media is write-protected. ! 430: ! 431: IOReturn ! 432: IOATAPIHDDrive::reportWriteProtection(bool * isWriteProtected) ! 433: { ! 434: *isWriteProtected = false; // defaults to read-write ! 435: return kIOReturnSuccess; ! 436: } ! 437: ! 438: // -------------------------------------------------------------------------- ! 439: // Instantiate an ATAPI specific subclass of IOHDDriveNub. ! 440: ! 441: IOService * ! 442: IOATAPIHDDrive::instantiateNub() ! 443: { ! 444: IOService * nub = new IOATAPIHDDriveNub; ! 445: return nub; ! 446: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.