|
|
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: * IOATAPICDDrive.h - Generic ATAPI CD-ROM driver. ! 26: * ! 27: * HISTORY ! 28: * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. ! 29: */ ! 30: ! 31: #include <IOKit/assert.h> ! 32: #include <IOKit/storage/ata/IOATAPICDDrive.h> ! 33: #include <IOKit/storage/ata/IOATAPICDDriveNub.h> ! 34: ! 35: #define super IOATAPIHDDrive ! 36: OSDefineMetaClassAndStructors( IOATAPICDDrive, IOATAPIHDDrive ) ! 37: ! 38: // -------------------------------------------------------------------------- ! 39: // Looks for an ATAPI device which is a CD-ROM device. ! 40: ! 41: bool ! 42: IOATAPICDDrive::matchATAPIDeviceType(UInt8 type) ! 43: { ! 44: if (type == kIOATAPIDeviceTypeCDROM) ! 45: return true; ! 46: return false; ! 47: } ! 48: ! 49: // -------------------------------------------------------------------------- ! 50: // Instantiate an ATAPI specific subclass of IOCDDriveNub. ! 51: ! 52: IOService * ! 53: IOATAPICDDrive::instantiateNub() ! 54: { ! 55: IOService * nub = new IOATAPICDDriveNub; ! 56: return nub; ! 57: } ! 58: ! 59: // -------------------------------------------------------------------------- ! 60: // Report whether media is write-protected. ! 61: ! 62: IOReturn ! 63: IOATAPICDDrive::reportWriteProtection(bool * isWriteProtected) ! 64: { ! 65: *isWriteProtected = true; ! 66: return kIOReturnSuccess; ! 67: } ! 68: ! 69: // -------------------------------------------------------------------------- ! 70: // Returns the device type. ! 71: ! 72: const char * ! 73: IOATAPICDDrive::getDeviceTypeName() ! 74: { ! 75: return kDeviceTypeCDROM; ! 76: } ! 77: ! 78: // -------------------------------------------------------------------------- ! 79: // Read the Table of Contents. ! 80: ! 81: IOReturn ! 82: IOATAPICDDrive::readTOC(struct rawToc * buffer, ! 83: UInt32 length, ! 84: tocFormat format) ! 85: { ! 86: IOReturn ret; ! 87: IOATACommand * cmd; ! 88: IOMemoryDescriptor * tocDesc; ! 89: ! 90: assert(buffer); ! 91: ! 92: tocDesc = IOMemoryDescriptor::withAddress(buffer, ! 93: length, ! 94: kIODirectionIn); ! 95: if (!tocDesc) ! 96: return kIOReturnNoMemory; ! 97: ! 98: cmd = atapiCommandReadTOC(tocDesc, format, 0); ! 99: if (!cmd) ! 100: return kIOReturnNoMemory; ! 101: ! 102: // Execute the Read TOC command. ! 103: // ! 104: ret = getIOReturn(syncExecute(cmd)); ! 105: ! 106: // Release the memory descriptor. ! 107: // ! 108: tocDesc->release(); ! 109: ! 110: cmd->release(); ! 111: ! 112: return ret; ! 113: } ! 114: ! 115: // -------------------------------------------------------------------------- ! 116: // Start analog audio play ! 117: ! 118: IOReturn ! 119: IOATAPICDDrive::setAudioStopAddress (positioningType addressType, ! 120: cdAddress address) ! 121: { ! 122: if (addressType == kAbsoluteTime) ! 123: fMSFStopAddress = (UInt32)address; ! 124: if (addressType == kBlockAddress) ! 125: fLBAStopAddress = (UInt32)address; ! 126: return 0; ! 127: } ! 128: ! 129: IOReturn ! 130: IOATAPICDDrive::audioPlay(positioningType addressType, ! 131: cdAddress address, ! 132: audioPlayMode mode) ! 133: { ! 134: if (addressType == kBlockAddress) { ! 135: return playAudio((UInt32)address,0xfff); ! 136: } ! 137: if (addressType == kAbsoluteTime) { ! 138: return playAudioMSF((UInt32)address,(UInt32)fMSFStopAddress); ! 139: } ! 140: return 0; ! 141: } ! 142: ! 143: IOReturn ! 144: IOATAPICDDrive::playAudioMSF (UInt32 start_msf, ! 145: UInt32 end_msf) ! 146: { ! 147: IOATACommand * cmd; ! 148: IOReturn ret; ! 149: ! 150: // IOLog("IOATAPICDDrive::playAudioMSF %x %x\n",start_msf,end_msf); ! 151: cmd = atapiCommandPlayAudioMSF(start_msf, end_msf); ! 152: if (!cmd) ! 153: return kIOReturnNoMemory; ! 154: ! 155: // Execute the audio play command. ! 156: // ! 157: ret = getIOReturn(syncExecute(cmd)); ! 158: ! 159: cmd->release(); ! 160: ! 161: return ret; ! 162: } ! 163: ! 164: IOReturn ! 165: IOATAPICDDrive::playAudio (UInt32 start_lba, ! 166: UInt32 len_lba) ! 167: { ! 168: IOATACommand * cmd; ! 169: IOReturn ret; ! 170: ! 171: // IOLog("IOATAPICDDrive::playAudio\n"); ! 172: cmd = atapiCommandPlayAudio(start_lba, len_lba); ! 173: if (!cmd) ! 174: return kIOReturnNoMemory; ! 175: ! 176: // Execute the audio play command. ! 177: // ! 178: ret = getIOReturn(syncExecute(cmd)); ! 179: ! 180: cmd->release(); ! 181: ! 182: return ret; ! 183: } ! 184: ! 185: IOReturn ! 186: IOATAPICDDrive::audioPause(bool pause) ! 187: { ! 188: IOATACommand * cmd; ! 189: IOReturn ret; ! 190: ! 191: // IOLog("IOATAPICDDrive::audioPause\n"); ! 192: cmd = atapiCommandPauseResume(!pause); ! 193: if (!cmd) ! 194: return kIOReturnNoMemory; ! 195: ! 196: // Execute the audio pause/resume command. ! 197: // ! 198: ret = getIOReturn(syncExecute(cmd)); ! 199: ! 200: cmd->release(); ! 201: ! 202: return ret; ! 203: } ! 204: ! 205: IOReturn ! 206: IOATAPICDDrive::readAudioVolume(UInt8 * leftVolume, UInt8 * rightVolume) ! 207: { ! 208: UInt8 *audio_control; ! 209: IOReturn status = -1; ! 210: ! 211: audio_control = (UInt8 *)IOMalloc(144); ! 212: if (!audio_control) return kIOReturnNoMemory; ! 213: ! 214: status = readModeSense(audio_control,(UInt32)144,(UInt32)0xe); ! 215: *leftVolume = audio_control[21] & 0xff; ! 216: *rightVolume = audio_control[17] & 0xff; ! 217: ! 218: // IOLog("IOATAPICDDrive::readAudioVolume left0=%d right0=%d left1=%d right1=%d\n", *leftVolume,*rightVolume, audio_control[23],audio_control[19]); ! 219: ! 220: // IOLog("IOATAPICDDrive::readAudioVolume p0=%d p1=%d p2=%d p3=%d\n", audio_control[8],audio_control[10], audio_control[12],audio_control[14]); ! 221: ! 222: IOFree(audio_control,144); ! 223: return status; ! 224: } ! 225: ! 226: IOReturn ! 227: IOATAPICDDrive::setVolume(UInt8 leftVolume, UInt8 rightVolume) ! 228: { ! 229: UInt8 *audio_control; ! 230: IOReturn status = -1; ! 231: UInt32 len; ! 232: ! 233: // IOLog("IOATAPICDDrive::setVolume %d %d\n",leftVolume,rightVolume); ! 234: ! 235: // init ! 236: audio_control = (UInt8 *)IOMalloc(144); ! 237: if (!audio_control) return kIOReturnNoMemory; ! 238: ! 239: // get current values ! 240: status = readModeSense(audio_control,(UInt32)144,(UInt32)0xe); ! 241: len = (UInt32)audio_control[1] + 2; ! 242: ! 243: // set new values ! 244: // audio_control[ 9] = audio_control[11] = 0xff; ! 245: // audio_control[23] = audio_control[21] = leftVolume & 0xff; ! 246: audio_control[19] = audio_control[17] = rightVolume & 0xff; ! 247: ! 248: // get current values ! 249: status = writeModeSelect(audio_control,(UInt32)len,(UInt32)0xe); ! 250: ! 251: // cleanup and exit ! 252: IOFree(audio_control,144); ! 253: return status; ! 254: } ! 255: ! 256: IOReturn ! 257: IOATAPICDDrive::readModeSense(UInt8 * buffer, UInt32 length, UInt32 pageCode) ! 258: { ! 259: IOReturn ret; ! 260: IOATACommand * cmd; ! 261: IOMemoryDescriptor * senseDesc; ! 262: ! 263: assert(buffer); ! 264: ! 265: // IOLog("IOATAPICDDrive::readModeSense len=%d page=%d\n",length,pageCode); ! 266: ! 267: senseDesc = IOMemoryDescriptor::withAddress(buffer, ! 268: length, ! 269: kIODirectionIn); ! 270: if (!senseDesc) ! 271: return kIOReturnNoMemory; ! 272: ! 273: cmd = atapiCommandModeSense(senseDesc, pageCode); ! 274: if (!cmd) ! 275: return kIOReturnNoMemory; ! 276: ! 277: // Execute the Mode Sense command. ! 278: // ! 279: ret = getIOReturn(syncExecute(cmd)); ! 280: ! 281: // Release the memory descriptor. ! 282: // ! 283: senseDesc->release(); ! 284: ! 285: cmd->release(); ! 286: ! 287: return ret; ! 288: } ! 289: ! 290: IOReturn ! 291: IOATAPICDDrive::writeModeSelect(UInt8 * buffer, UInt32 length, UInt32 pageCode) ! 292: { ! 293: IOReturn ret; ! 294: IOATACommand * cmd; ! 295: IOMemoryDescriptor * selectDesc; ! 296: ! 297: // IOLog("IOATAPICDDrive::writeModeSelect %d %d\n",length,pageCode); ! 298: assert(buffer); ! 299: ! 300: selectDesc = IOMemoryDescriptor::withAddress(buffer, ! 301: length, ! 302: kIODirectionOut); ! 303: if (!selectDesc) ! 304: return kIOReturnNoMemory; ! 305: ! 306: cmd = atapiCommandModeSelect(selectDesc, pageCode); ! 307: if (!cmd) ! 308: return kIOReturnNoMemory; ! 309: ! 310: // Execute the Mode Select command. ! 311: // ! 312: ret = getIOReturn(syncExecute(cmd)); ! 313: ! 314: // Release the memory descriptor. ! 315: // ! 316: selectDesc->release(); ! 317: ! 318: cmd->release(); ! 319: ! 320: return ret; ! 321: } ! 322: ! 323: IOReturn ! 324: IOATAPICDDrive::readTheQSubcode(struct qSubcode *buffer) ! 325: { ! 326: UInt8 * channel_data; ! 327: UInt32 address; ! 328: IOReturn ret; ! 329: ! 330: // init ! 331: channel_data = (UInt8 *)IOMalloc(16); ! 332: if (!channel_data) return kIOReturnNoMemory; ! 333: ! 334: // get audio status ! 335: ret = readSubChannel(channel_data,16,0x01,0x00,true); ! 336: ! 337: // get current absolute address ! 338: address = ((channel_data[ 8] & 0xff) << 24) | ! 339: ((channel_data[ 9] & 0xff) << 16) | ! 340: ((channel_data[10] & 0xff) << 8) | ! 341: ((channel_data[11] & 0xff)); ! 342: buffer->absAddress = (cdAddress)address; ! 343: ! 344: // get current track relative address ! 345: address = ((channel_data[12] & 0xff) << 24) | ! 346: ((channel_data[13] & 0xff) << 16) | ! 347: ((channel_data[14] & 0xff) << 8) | ! 348: ((channel_data[15] & 0xff)); ! 349: buffer->relAddress = (cdAddress)address; ! 350: ! 351: // get type, track, index ! 352: buffer->type = channel_data[5] & 0x0f; ! 353: buffer->track = channel_data[6] & 0x0f; ! 354: buffer->index = channel_data[7] & 0x0f; ! 355: ! 356: // IOLog("IOATAPICDDrive::readTheQSubcode absAddr=0x%x relAddr=0x%xx\n", buffer->absAddress, buffer->relAddress); ! 357: ! 358: // cleanup ! 359: IOFree(channel_data,16); ! 360: return ret; ! 361: } ! 362: ! 363: IOReturn ! 364: IOATAPICDDrive::getAudioStatus(struct audioStatus *status) ! 365: { ! 366: UInt8 * channel_data; ! 367: UInt32 address; ! 368: IOReturn ret; ! 369: ! 370: // init ! 371: channel_data = (UInt8 *)IOMalloc(16); ! 372: if (!channel_data) return kIOReturnNoMemory; ! 373: ! 374: // get audio status ! 375: ret = readSubChannel(channel_data,16,0x01,0x00,true); ! 376: ! 377: // get current absolute address ! 378: address = ((channel_data[ 8] & 0xff) << 24) | ! 379: ((channel_data[ 9] & 0xff) << 16) | ! 380: ((channel_data[10] & 0xff) << 8) | ! 381: ((channel_data[11] & 0xff)); ! 382: status->address = (cdAddress)address; ! 383: ! 384: // get current status ! 385: if ((channel_data[1] & 0xff) == 0x00) status->status = kUnknown; ! 386: if ((channel_data[1] & 0xff) == 0x11) status->status = kAudioPlayInProgress; ! 387: if ((channel_data[1] & 0xff) == 0x12) status->status = kHoldTrackMode; ! 388: if ((channel_data[1] & 0xff) == 0x13) status->status = kAudioPlayCompleted; ! 389: if ((channel_data[1] & 0xff) == 0x14) status->status = kError; ! 390: if ((channel_data[1] & 0xff) == 0x15) status->status = fStatus; ! 391: fStatus = status->status; ! 392: ! 393: // get current track type ! 394: status->type = channel_data[5] & 0x0f; ! 395: ! 396: // IOLog("IOATAPICDDrive::getAudioStatus addr=0x%x status=0x%x type=0x%x\n", status->address, status->status, status->type); ! 397: ! 398: // cleanup ! 399: IOFree(channel_data,16); ! 400: return ret; ! 401: } ! 402: ! 403: IOReturn ! 404: IOATAPICDDrive::readMCN(UInt8 * buffer, bool * found) ! 405: { ! 406: UInt8 * channel_data; ! 407: UInt32 address; ! 408: IOReturn ret; ! 409: ! 410: // init ! 411: channel_data = (UInt8 *)IOMalloc(24); ! 412: if (!channel_data) return kIOReturnNoMemory; ! 413: ! 414: // get audio status ! 415: ret = readSubChannel(channel_data,24,0x02,0x00,true); ! 416: ! 417: // check if found ! 418: *found = (channel_data[8] & 0x80 == 0x80); ! 419: ! 420: // copy the data ! 421: if (*found) { ! 422: bcopy(&channel_data[9],buffer,15); ! 423: } ! 424: ! 425: // IOLog("IOATAPICDDrive::readMCN found=%d\n",*found); ! 426: ! 427: // cleanup ! 428: IOFree(channel_data,24); ! 429: return ret; ! 430: } ! 431: ! 432: IOReturn ! 433: IOATAPICDDrive::readISRC(UInt32 track, UInt8 * buffer, bool * found) ! 434: { ! 435: UInt8 * channel_data; ! 436: UInt32 address; ! 437: IOReturn ret; ! 438: ! 439: // init ! 440: channel_data = (UInt8 *)IOMalloc(24); ! 441: if (!channel_data) return kIOReturnNoMemory; ! 442: ! 443: // get audio status ! 444: ret = readSubChannel(channel_data,24,0x03,track,true); ! 445: ! 446: // check if found ! 447: *found = (channel_data[8] & 0x80 == 0x80); ! 448: ! 449: // copy the data ! 450: if (*found) { ! 451: bcopy(&channel_data[9],buffer,15); ! 452: } ! 453: ! 454: // IOLog("IOATAPICDDrive::readISRC found=%d\n",*found); ! 455: ! 456: // cleanup ! 457: IOFree(channel_data,24); ! 458: return ret; ! 459: } ! 460: ! 461: IOReturn ! 462: IOATAPICDDrive::readHeader(UInt32 blockAddress,struct headerInfo *buffer) ! 463: { ! 464: UInt8 * header_data; ! 465: IOReturn ret; ! 466: IOATACommand * cmd; ! 467: IOMemoryDescriptor * readDesc; ! 468: ! 469: // init ! 470: header_data = (UInt8 *)IOMalloc(8); ! 471: if (!header_data) return kIOReturnNoMemory; ! 472: ! 473: // IOLog("IOATAPICDDrive::readHeader addr=0x%x\n",blockAddress); ! 474: ! 475: readDesc = IOMemoryDescriptor::withAddress(header_data, ! 476: 8, ! 477: kIODirectionIn); ! 478: if (!readDesc) ! 479: return kIOReturnNoMemory; ! 480: ! 481: cmd = atapiCommandReadHeader(readDesc, blockAddress); ! 482: if (!cmd) ! 483: return kIOReturnNoMemory; ! 484: ! 485: // Execute the Read Header command. ! 486: // ! 487: ret = getIOReturn(syncExecute(cmd)); ! 488: ! 489: // Release the memory descriptor. ! 490: // ! 491: readDesc->release(); ! 492: cmd->release(); ! 493: ! 494: // save the data ! 495: buffer->address = ((header_data[4] & 0xff) << 24) | ! 496: ((header_data[5] & 0xff) << 16) | ! 497: ((header_data[6] & 0xff) << 8) | ! 498: ((header_data[7] & 0xff)); ! 499: buffer->mode = header_data[0] & 0xff; ! 500: ! 501: IOFree(header_data,8); ! 502: ! 503: return ret; ! 504: } ! 505: ! 506: IOReturn ! 507: IOATAPICDDrive::readSubChannel(UInt8 * buffer, ! 508: UInt32 length, ! 509: UInt8 dataFormat, ! 510: UInt8 trackNumber, ! 511: bool subQ) ! 512: { ! 513: IOReturn ret; ! 514: IOATACommand * cmd; ! 515: IOMemoryDescriptor * readDesc; ! 516: ! 517: assert(buffer); ! 518: ! 519: // IOLog("IOATAPICDDrive::readSubChannel len=%d\n",length); ! 520: ! 521: readDesc = IOMemoryDescriptor::withAddress(buffer, ! 522: length, ! 523: kIODirectionIn); ! 524: if (!readDesc) ! 525: return kIOReturnNoMemory; ! 526: ! 527: cmd = atapiCommandReadSubChannel(readDesc, dataFormat, trackNumber, subQ); ! 528: if (!cmd) ! 529: return kIOReturnNoMemory; ! 530: ! 531: // Execute the Mode Sense command. ! 532: // ! 533: ret = getIOReturn(syncExecute(cmd)); ! 534: ! 535: // Release the memory descriptor. ! 536: // ! 537: readDesc->release(); ! 538: ! 539: cmd->release(); ! 540: ! 541: return ret; ! 542: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.