|
|
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: #include <IOKit/IOLib.h> ! 24: #include <IOKit/IOReturn.h> ! 25: #include <IOKit/IOMemoryDescriptor.h> ! 26: #include <IOKit/scsi/IOSCSIDeviceInterface.h> ! 27: #include <IOKit/storage/scsi/IOSCSICDDrive.h> ! 28: #include <IOKit/storage/scsi/IOSCSICDDriveNub.h> ! 29: ! 30: /* Device types that we intend to handle. */ ! 31: ! 32: const UInt8 DT_CDROM = 0x05; /* CD-ROM */ ! 33: ! 34: #define super IOSCSIHDDrive ! 35: OSDefineMetaClassAndStructors(IOSCSICDDrive,IOSCSIHDDrive) ! 36: ! 37: IOReturn ! 38: IOSCSICDDrive::audioPlay(positioningType addressType,cdAddress address,audioPlayMode mode) ! 39: { ! 40: return(doAudioPlayCommand(addressType,address, ! 41: _audioStopAddress.type,_audioStopAddress.address)); ! 42: } ! 43: ! 44: IOReturn ! 45: IOSCSICDDrive::audioPause(bool pause) ! 46: { ! 47: //xxxx ! 48: return(kIOReturnUnsupported); ! 49: } ! 50: ! 51: IOReturn ! 52: IOSCSICDDrive::audioScan(positioningType addressType,cdAddress address,bool reverse) ! 53: { ! 54: struct context *cx; ! 55: struct IOAudioScancdb *c; ! 56: IOSCSICommand *req; ! 57: SCSICDBInfo scsiCDB; ! 58: IOReturn result; ! 59: ! 60: cx = allocateContext(); ! 61: if (cx == NULL) { ! 62: return(kIOReturnNoMemory); ! 63: } ! 64: ! 65: req = cx->scsireq; ! 66: ! 67: bzero( &scsiCDB, sizeof(scsiCDB) ); ! 68: ! 69: c = (struct IOAudioScancdb *)&scsiCDB.cdb; ! 70: ! 71: c->opcode = SOP_AUDIOSCAN; ! 72: c->lunbits = 0; ! 73: if (!reverse) { ! 74: c->lunbits |= IOAudioScancdb::kForward; ! 75: } ! 76: ! 77: switch (addressType) { ! 78: ! 79: case kBlockAddress : ! 80: c->start3 = address >> 24; ! 81: c->start2 = address >> 16; ! 82: c->start1 = address >> 8; ! 83: c->start0 = address & 0xff; ! 84: c->ctlbyte = IOAudioScancdb::kType_lba; ! 85: break; ! 86: ! 87: case kAbsoluteTime : ! 88: c->start3 = address >> 24; ! 89: c->start2 = address >> 16; ! 90: c->start1 = address >> 8; ! 91: c->start0 = address & 0xff; ! 92: c->ctlbyte = IOAudioScancdb::kType_msf; ! 93: break; ! 94: ! 95: case kTrackNumber : ! 96: c->start3 = 0; ! 97: c->start2 = 0; ! 98: c->start1 = 0; ! 99: c->start0 = address & 0xff; ! 100: c->ctlbyte = IOAudioScancdb::kType_track; ! 101: break; ! 102: ! 103: default : ! 104: deleteContext(cx); ! 105: return(kIOReturnBadArgument); ! 106: }; ! 107: ! 108: scsiCDB.cdbLength = 6; ! 109: scsiCDB.cdbFlags = 0; ! 110: req->setCDB( &scsiCDB ); ! 111: req->setPointers(cx->senseDataDesc, 255, false, true); ! 112: req->setPointers( cx->memory, 0, false ); ! 113: req->setTimeout(1 * 1000); ! 114: ! 115: result = simpleSynchIO(cx); ! 116: ! 117: deleteContext(cx); ! 118: ! 119: return(result); ! 120: } ! 121: ! 122: IOReturn ! 123: IOSCSICDDrive::audioTrackSearch(positioningType addressType,cdAddress address, ! 124: bool startPlay,audioPlayMode mode) ! 125: { ! 126: IOReturn result; ! 127: UInt32 lba; ! 128: ! 129: result = convertMSFToLba(&lba,address); ! 130: if (result != kIOReturnSuccess) { ! 131: return(result); ! 132: } ! 133: ! 134: result = seek(lba); ! 135: if (result != kIOReturnSuccess) { ! 136: return(result); ! 137: } ! 138: ! 139: if (startPlay) { ! 140: return(audioPlay(addressType,address,mode)); ! 141: } else { ! 142: return(result); ! 143: } ! 144: } ! 145: ! 146: IOReturn ! 147: IOSCSICDDrive::convertMSFToLba(UInt32 *lba,cdAddress address) ! 148: { ! 149: //xxx wrong! incoming msf values are bcd! ! 150: *lba = ((address >> 16) * 75 * 60) + /* min */ ! 151: ((address >> 8) * 75) + /* sec */ ! 152: (address & 0xff); /* frames */ ! 153: ! 154: return(kIOReturnSuccess); ! 155: } ! 156: ! 157: bool ! 158: IOSCSICDDrive::deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen) ! 159: { ! 160: if ((inqBuf[0] & 0x1f) == DT_CDROM) { ! 161: // IOLog("%s[IOSCSICDDrive]::deviceTypeMatches, returning TRUE\n",getName()); ! 162: return(true); ! 163: } else { ! 164: // IOLog("%s[IOSCSICDDrive]::deviceTypeMatches, returning FALSE\n",getName()); ! 165: return(false); /* we don't handle other devices */ ! 166: } ! 167: } ! 168: ! 169: IOReturn ! 170: IOSCSICDDrive::doAudioPlayCommand(positioningType startType,cdAddress startAddress, ! 171: positioningType endType,cdAddress endAddress) ! 172: { ! 173: struct context *cx; ! 174: struct IOAudioPlaycdb *c; ! 175: struct IOAudioPlayMSFcdb *p; ! 176: IOSCSICommand *req; ! 177: SCSICDBInfo scsiCDB; ! 178: IOReturn result; ! 179: UInt32 length; ! 180: ! 181: /* Can we return an error here, or must we ensure that start and stop are always ! 182: * locally converted to the same units before we use them? ! 183: */ ! 184: if (startType != endType) { ! 185: return(kIOReturnBadArgument); ! 186: } ! 187: ! 188: if (startType != kAbsoluteTime || startType != kBlockAddress) { ! 189: return(kIOReturnBadArgument); ! 190: } ! 191: ! 192: cx = allocateContext(); ! 193: if (cx == NULL) { ! 194: return(kIOReturnNoMemory); ! 195: } ! 196: ! 197: req = cx->scsireq; ! 198: ! 199: bzero( &scsiCDB, sizeof(scsiCDB) ); ! 200: ! 201: if (startType == kBlockAddress) { /* use PlayAudio command */ ! 202: c = (struct IOAudioPlaycdb *)scsiCDB.cdb; ! 203: ! 204: c->opcode = SOP_PLAYAUDIO; ! 205: c->lunbits = 0; ! 206: c->lba_3 = startAddress >> 24; ! 207: c->lba_2 = startAddress >> 16; ! 208: c->lba_1 = startAddress >> 8; ! 209: c->lba_0 = startAddress & 0xff; ! 210: c->reserved1 = 0; ! 211: length = endAddress - startAddress; ! 212: c->len_hi = length >> 8; ! 213: c->len_lo = length & 0xff; ! 214: c->ctlbyte = 0; ! 215: ! 216: } else { /* absolute time: use PlayAudioMSF */ ! 217: ! 218: p = (struct IOAudioPlayMSFcdb *)scsiCDB.cdb; ! 219: ! 220: p->opcode = SOP_PLAYAUDIOMSF; ! 221: p->lunbits = 0; ! 222: p->reserved1 = 0; ! 223: p->start_m = startAddress >> 16; ! 224: p->start_s = startAddress >> 8; ! 225: p->start_f = startAddress & 0xff; ! 226: p->end_m = endAddress >> 16; ! 227: p->end_s = endAddress >> 8; ! 228: p->end_f = endAddress & 0xff; ! 229: p->ctlbyte = 0; ! 230: } ! 231: ! 232: scsiCDB.cdbLength = 10; ! 233: req->setCDB( &scsiCDB ); ! 234: req->setPointers(cx->senseDataDesc, 255, false, true); ! 235: ! 236: req->setPointers( cx->memory, 0, false ); ! 237: req->setTimeout( 1000 ); ! 238: ! 239: result = simpleSynchIO(cx); ! 240: ! 241: deleteContext(cx); ! 242: ! 243: return(result); ! 244: } ! 245: ! 246: IOReturn ! 247: IOSCSICDDrive::getAudioStatus(struct audioStatus *status) ! 248: { ! 249: const UInt8 qBufLen = 16; ! 250: IOReturn result; ! 251: UInt8 *tempBuf; ! 252: ! 253: /* Get a buffer for the returned data: */ ! 254: ! 255: result = allocateTempBuffer(&tempBuf,qBufLen); ! 256: if (result != kIOReturnSuccess) { ! 257: return(kIOReturnNoMemory); ! 258: } ! 259: ! 260: result = readSubchannel(tempBuf,qBufLen,0,IORSCcdb::kCurrentPosition); ! 261: ! 262: if ((result == kIOReturnSuccess) && ((tempBuf[5] & 0xf0) == 0x10)) { /* we got the data */ ! 263: status->playMode = _audioPlayMode; ! 264: status->type = (trackType)(tempBuf[5] & 0xff); ! 265: status->address = tempBuf[ 9] << 16 | ! 266: tempBuf[10] << 8 | ! 267: tempBuf[11]; ! 268: switch (tempBuf[1]) { /* convert audio status */ ! 269: ! 270: ! 271: case 0x11: ! 272: status->status = kAudioPlayInProgress; ! 273: break; ! 274: ! 275: case 0x12: ! 276: status->status = kHoldTrackMode; ! 277: break; ! 278: ! 279: case 0x13: ! 280: status->status = kAudioPlayCompleted; ! 281: break; ! 282: ! 283: case 0x14: ! 284: status->status = kError; ! 285: break; ! 286: ! 287: case 0x15: ! 288: status->status = kAudioPlayNotRequested; ! 289: break; ! 290: ! 291: case 0x00: ! 292: default: ! 293: status->status = kUnknown; ! 294: break; ! 295: } ! 296: } ! 297: deleteTempBuffer(tempBuf,qBufLen); ! 298: ! 299: return(result); ! 300: } ! 301: ! 302: const char * ! 303: IOSCSICDDrive::getDeviceTypeName(void) ! 304: { ! 305: return(kDeviceTypeCDROM); ! 306: } ! 307: ! 308: bool ! 309: IOSCSICDDrive::init(OSDictionary * properties) ! 310: { ! 311: initAudioModes(); ! 312: ! 313: _audioStopAddress.address = 0L; ! 314: _audioStopAddress.type = kBlockAddress; ! 315: ! 316: return(super::init(properties)); ! 317: } ! 318: ! 319: void ! 320: IOSCSICDDrive::initAudioModes(void) ! 321: { ! 322: _audioPlayMode = stereo; ! 323: _leftVolume = 0xff; ! 324: _leftPortChannel = playModeToDriveBits(_audioPlayMode,kLeft); ! 325: _rightVolume = 0xff; ! 326: _rightPortChannel = playModeToDriveBits(_audioPlayMode,kRight); ! 327: } ! 328: ! 329: IOService * ! 330: IOSCSICDDrive::instantiateNub(void) ! 331: { ! 332: IOService *nub; ! 333: ! 334: /* Instantiate a generic CDROM nub so a generic driver can match above us. */ ! 335: ! 336: nub = new IOSCSICDDriveNub; ! 337: return(nub); ! 338: } ! 339: ! 340: void ! 341: IOSCSICDDrive::mediaGone(void) ! 342: { ! 343: } ! 344: ! 345: /* Convert the audioPlayMode signal routing bits to the drive's bits. */ ! 346: ! 347: UInt8 ! 348: IOSCSICDDrive::playModeToDriveBits(audioPlayMode mode,channel chan) ! 349: { ! 350: UInt8 bits; ! 351: int shift; ! 352: ! 353: bits = 0; ! 354: ! 355: switch (chan) { ! 356: ! 357: case kLeft : shift = shift_Left_Channel; break; ! 358: case kRight : shift = shift_Right_Channel; break; ! 359: ! 360: default : return(bits); ! 361: } ! 362: ! 363: if (mode & (signal_Left << shift)) { ! 364: bits |= drive_left_signal; ! 365: } ! 366: if (mode & (signal_Right << shift)) { ! 367: bits |= drive_right_signal; ! 368: } ! 369: ! 370: return(bits); ! 371: } ! 372: ! 373: IOReturn ! 374: IOSCSICDDrive::readAudioData(positioningType addressType,cdAddress address, ! 375: UInt8 blockCount,UInt8 *buffer) ! 376: { ! 377: /* what about buffer vs. IOMemoryDescriptor? */ ! 378: ! 379: //xxxx ! 380: return(kIOReturnUnsupported); ! 381: } ! 382: ! 383: IOReturn ! 384: IOSCSICDDrive::readAudioSubcodes(positioningType addressType,cdAddress address, ! 385: UInt8 blockCount,UInt8 *buffer) ! 386: { ! 387: /* what about buffer vs. IOMemoryDescriptor? */ ! 388: ! 389: // xxxx ! 390: return(kIOReturnUnsupported); ! 391: } ! 392: ! 393: IOReturn ! 394: IOSCSICDDrive::readAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume) ! 395: { ! 396: /* Return the cached values. */ ! 397: ! 398: *leftVolume = _leftVolume; ! 399: *rightVolume = _rightVolume; ! 400: ! 401: return(kIOReturnSuccess); ! 402: } ! 403: ! 404: IOReturn ! 405: IOSCSICDDrive::readAudioWithQSubcode(positioningType addressType,cdAddress address, ! 406: UInt8 blockCount,UInt8 *buffer) ! 407: { ! 408: /* what about buffer vs. IOMemoryDescriptor? */ ! 409: ! 410: //xxxx ! 411: return(kIOReturnUnsupported); ! 412: } ! 413: ! 414: IOReturn ! 415: IOSCSICDDrive::readAudioWithAllSubcodes(positioningType addressType,cdAddress address, ! 416: UInt8 blockCount,UInt8 *buffer) ! 417: { ! 418: /* what about buffer vs. IOMemoryDescriptor? */ ! 419: ! 420: //xxxx ! 421: return(kIOReturnUnsupported); ! 422: } ! 423: ! 424: IOReturn ! 425: IOSCSICDDrive::readHeader(UInt32 blockAddress,struct headerInfo *buffer) ! 426: { ! 427: const UInt8 hdrBufLen = 24; ! 428: struct context *cx; ! 429: struct IOReadHeadercdb *c; ! 430: IOSCSICommand *req; ! 431: SCSICDBInfo scsiCDB; ! 432: IOReturn result; ! 433: UInt8 *tempBuf; ! 434: ! 435: bzero(buffer,sizeof(struct headerInfo)); ! 436: ! 437: /* Get a buffer for the returned data: */ ! 438: ! 439: result = allocateTempBuffer(&tempBuf,hdrBufLen); ! 440: if (result != kIOReturnSuccess) { ! 441: return(kIOReturnNoMemory); ! 442: } ! 443: ! 444: cx = allocateContext(); ! 445: if (cx == NULL) { ! 446: return(kIOReturnNoMemory); ! 447: } ! 448: ! 449: req = cx->scsireq; ! 450: ! 451: bzero( &scsiCDB, sizeof(scsiCDB) ); ! 452: ! 453: c = (struct IOReadHeadercdb *)scsiCDB.cdb; ! 454: ! 455: c->opcode = SOP_READHEADER; ! 456: c->lunbits = 0; ! 457: c->lunbits |= IOReadHeadercdb::kMSF; /* return results in M:S:F format */ ! 458: c->lba_3 = blockAddress >> 24; ! 459: c->lba_2 = blockAddress >> 18; ! 460: c->lba_1 = blockAddress >> 8; ! 461: c->lba_0 = blockAddress & 0xff; ! 462: c->reserved1 = 0; ! 463: c->len_hi = 0; ! 464: c->len_lo = hdrBufLen; ! 465: c->ctlbyte = 0; ! 466: ! 467: scsiCDB.cdbLength = 10; ! 468: req->setCDB( &scsiCDB ); ! 469: req->setPointers(cx->senseDataDesc, 255, false, true); ! 470: ! 471: cx->memory = IOMemoryDescriptor::withAddress((void *)tempBuf, ! 472: hdrBufLen, ! 473: kIODirectionIn); ! 474: req->setPointers( cx->memory, hdrBufLen, false ); ! 475: ! 476: req->setTimeout( 1000 ); ! 477: ! 478: result = simpleSynchIO(cx); ! 479: ! 480: deleteContext(cx); ! 481: ! 482: if (result == kIOReturnSuccess) { /* return the header info */ ! 483: buffer->mode = (dataMode)(tempBuf[0]); ! 484: buffer->address = tempBuf[4] << 24 || ! 485: tempBuf[5] << 16 || ! 486: tempBuf[6] << 8 || ! 487: tempBuf[7]; ! 488: } ! 489: ! 490: deleteTempBuffer(tempBuf,hdrBufLen); ! 491: ! 492: return(result); ! 493: } ! 494: ! 495: IOReturn ! 496: IOSCSICDDrive::readISRC(UInt32 track,UInt8 *buffer,bool *found) ! 497: { ! 498: return(readISRCMCN(IORSCcdb::kISRC,track,buffer,found)); ! 499: } ! 500: ! 501: /* Since the ISRC and MCN are the same size and behave the same, we use common code. */ ! 502: IOReturn ! 503: IOSCSICDDrive::readISRCMCN(UInt8 dataformat,UInt32 track,UInt8 *buffer,bool *found) ! 504: { ! 505: const UInt8 mcnISRCBufLen = 24; ! 506: IOReturn result; ! 507: UInt8 *tempBuf; ! 508: ! 509: *found = false; /* assume no ISRC/MCN will be found */ ! 510: bzero(buffer,mcnISRCBufLen); ! 511: ! 512: /* Get a buffer for the returned data: */ ! 513: ! 514: result = allocateTempBuffer(&tempBuf,mcnISRCBufLen); ! 515: if (result != kIOReturnSuccess) { ! 516: return(kIOReturnNoMemory); ! 517: } ! 518: ! 519: result = readSubchannel(tempBuf,mcnISRCBufLen,track,dataformat); ! 520: ! 521: if ((result == kIOReturnSuccess) && (tempBuf[8] & 0x80)) { /* return the ISRC/MCN */ ! 522: bcopy(buffer,&tempBuf[9],15); ! 523: *found = true; ! 524: } ! 525: ! 526: deleteTempBuffer(tempBuf,mcnISRCBufLen); ! 527: ! 528: return(result); ! 529: } ! 530: ! 531: IOReturn ! 532: IOSCSICDDrive::readMCN(UInt8 *buffer,bool *found) ! 533: { ! 534: return(readISRCMCN(IORSCcdb::kMCN,0,buffer,found)); /* any track will do */ ! 535: } ! 536: ! 537: ! 538: IOReturn ! 539: IOSCSICDDrive::readQSubcodes(struct qSubcodeTocInfo *buffer,UInt32 bufSize) ! 540: { ! 541: /* what about buffer vs. IOMemoryDescriptor? */ ! 542: ! 543: //xxxx ! 544: return(kIOReturnUnsupported); ! 545: } ! 546: ! 547: IOReturn ! 548: IOSCSICDDrive::readSubcodeBuffer(UInt8 *buffer,bool purge,UInt32 entryCount) ! 549: { ! 550: /* what about buffer vs. IOMemoryDescriptor? */ ! 551: ! 552: //xxxx ! 553: return(kIOReturnUnsupported); ! 554: } ! 555: ! 556: IOReturn ! 557: IOSCSICDDrive::readSubchannel(UInt8 *buffer,UInt32 length,UInt8 track,UInt8 dataFormat) ! 558: { ! 559: struct context *cx; ! 560: struct IORSCcdb *c; ! 561: IOSCSICommand *req; ! 562: SCSICDBInfo scsiCDB; ! 563: IOReturn result; ! 564: ! 565: cx = allocateContext(); ! 566: if (cx == NULL) { ! 567: return(kIOReturnNoMemory); ! 568: } ! 569: ! 570: req = cx->scsireq; ! 571: ! 572: bzero( &scsiCDB, sizeof(scsiCDB) ); ! 573: ! 574: bzero(buffer,length); ! 575: ! 576: c = (struct IORSCcdb *)(scsiCDB.cdb); ! 577: ! 578: c->opcode = SOP_READSUBCHANNEL; ! 579: c->lunbits = 0; ! 580: c->lunbits |= IORSCcdb::kMSF; ! 581: c->subq = IORSCcdb::kSubq; ! 582: c->dataformat = dataFormat; ! 583: c->track = track; /* any valid track will do */ ! 584: c->reserved1 = 0; ! 585: c->reserved2 = 0; ! 586: c->len_hi = length >> 8; ! 587: c->len_lo = length & 0xff; ! 588: c->ctlbyte = 0; ! 589: ! 590: scsiCDB.cdbLength = 10; ! 591: req->setCDB( &scsiCDB ); ! 592: req->setPointers(cx->senseDataDesc, 255, false, true); ! 593: ! 594: cx->memory = IOMemoryDescriptor::withAddress((void *)buffer, ! 595: length, ! 596: kIODirectionIn); ! 597: req->setPointers( cx->memory, length, false ); ! 598: ! 599: req->setTimeout( 1000 ); ! 600: ! 601: result = simpleSynchIO(cx); ! 602: ! 603: deleteContext(cx); ! 604: ! 605: return(result); ! 606: } ! 607: ! 608: IOReturn ! 609: IOSCSICDDrive::readTheQSubcode(struct qSubcode *buffer) ! 610: { ! 611: const UInt8 qBufLen = 16; ! 612: IOReturn result; ! 613: UInt8 *tempBuf; ! 614: ! 615: bzero(buffer,sizeof(struct qSubcode)); ! 616: ! 617: /* Get a buffer for the returned data: */ ! 618: ! 619: result = allocateTempBuffer(&tempBuf,qBufLen); ! 620: if (result != kIOReturnSuccess) { ! 621: return(kIOReturnNoMemory); ! 622: } ! 623: ! 624: result = readSubchannel(tempBuf,qBufLen,0, IORSCcdb::kCurrentPosition); ! 625: ! 626: if ((result == kIOReturnSuccess) && ((tempBuf[5] & 0xf0) == 0x10)) { /* we got the data */ ! 627: buffer->type = (trackType)(tempBuf[ 5] & 0x0f); ! 628: buffer->track = tempBuf[ 6]; ! 629: buffer->index = tempBuf[ 7]; ! 630: buffer->absAddress = tempBuf[ 9] << 16 | ! 631: tempBuf[10] << 8 | ! 632: tempBuf[11]; ! 633: buffer->relAddress = tempBuf[13] << 16 | ! 634: tempBuf[14] << 8 | ! 635: tempBuf[15]; ! 636: } ! 637: ! 638: deleteTempBuffer(tempBuf,qBufLen); ! 639: ! 640: return(result); ! 641: } ! 642: ! 643: IOReturn ! 644: IOSCSICDDrive::readTOC(struct rawToc *buffer,UInt32 length,tocFormat format) ! 645: { ! 646: struct context *cx; ! 647: struct IOReadToccdb *c; ! 648: IOSCSICommand *req; ! 649: SCSICDBInfo scsiCDB; ! 650: IOReturn result; ! 651: ! 652: cx = allocateContext(); ! 653: if (cx == NULL) { ! 654: return(kIOReturnNoMemory); ! 655: } ! 656: ! 657: req = cx->scsireq; ! 658: ! 659: bzero( &scsiCDB, sizeof(scsiCDB) ); ! 660: ! 661: c = (struct IOReadToccdb *)scsiCDB.cdb; ! 662: ! 663: c->opcode = SOP_READTOC; ! 664: c->lunbits = 0; ! 665: if (format == ktocSCSI2MSF) { ! 666: c->lunbits |= IOReadToccdb::kMSF; ! 667: } ! 668: c->reserved1 = 0; ! 669: c->reserved2 = 0; ! 670: c->reserved3 = 0; ! 671: c->reserved4 = 0; ! 672: c->len_hi = length >> 8; ! 673: c->len_lo = length & 0xff; ! 674: c->ctlbyte = 0; ! 675: ! 676: switch (format) { ! 677: case ktocSCSI2MSF : ! 678: case ktocSCSI2LBA : ! 679: c->ctlbyte |= IOReadToccdb::kSCSI2; ! 680: break; ! 681: ! 682: case ktocSessionInfo : ! 683: c->ctlbyte |= IOReadToccdb::kSessionInfo; ! 684: break; ! 685: ! 686: case ktocQLeadin : ! 687: c->ctlbyte |= IOReadToccdb::kQLeadIn; ! 688: break; ! 689: } ! 690: ! 691: scsiCDB.cdbLength = 10; ! 692: req->setCDB( &scsiCDB ); ! 693: req->setPointers(cx->senseDataDesc, 255, false, true); ! 694: ! 695: cx->memory = IOMemoryDescriptor::withAddress((void *)buffer, ! 696: length, ! 697: kIODirectionIn); ! 698: req->setPointers( cx->memory, length, false ); ! 699: ! 700: req->setTimeout( 1000 ); ! 701: ! 702: result = simpleSynchIO(cx); ! 703: ! 704: if ( result == kIOReturnUnderrun ) result = kIOReturnSuccess; ! 705: ! 706: deleteContext(cx); ! 707: ! 708: return(result); ! 709: } ! 710: ! 711: /* We track media changes so we can: ! 712: * - set default audio playMode and volume ! 713: */ ! 714: ! 715: IOReturn ! 716: IOSCSICDDrive::reportMediaState(bool *mediaPresent,bool *changed) ! 717: { ! 718: IOReturn result; ! 719: IOReturn internalResult; ! 720: ! 721: result = super::reportMediaState(mediaPresent,changed); ! 722: ! 723: /** ! 724: IOLog("%s[IOSCSICDDrive]::reportMediaState; result=%s, changed = %s, present = %s\n", ! 725: getName(),stringFromReturn(result),*changed ? "Y" : "N", *mediaPresent ? "Y" : "N"); ! 726: **/ ! 727: ! 728: if ((result == kIOReturnSuccess) && *changed) { /* the media state changed */ ! 729: if (*mediaPresent) { /* new media inserted */ ! 730: internalResult = setDefaultAudioModes(); ! 731: } else { /* media went away */ ! 732: mediaGone(); ! 733: } ! 734: } ! 735: ! 736: /* We don't return the result of our internal operations. But since they ! 737: * indicate a problem, we probably should report some kind of problem, ! 738: * or maybe just ignore the media change. ! 739: */ ! 740: ! 741: return(result); ! 742: } ! 743: ! 744: IOReturn ! 745: IOSCSICDDrive::seek(UInt32 lba) ! 746: { ! 747: struct context *cx; ! 748: struct IOSeekcdb *c; ! 749: IOSCSICommand *req; ! 750: SCSICDBInfo scsiCDB; ! 751: IOReturn result; ! 752: ! 753: cx = allocateContext(); ! 754: if (cx == NULL) { ! 755: return(kIOReturnNoMemory); ! 756: } ! 757: ! 758: req = cx->scsireq; ! 759: ! 760: bzero( &scsiCDB, sizeof(scsiCDB) ); ! 761: ! 762: c = (struct IOSeekcdb *)(scsiCDB.cdb); ! 763: ! 764: c->opcode = SOP_SEEK; ! 765: c->lunbits = 0; ! 766: c->lba_3 = lba >> 24; ! 767: c->lba_2 = lba >> 16; ! 768: c->lba_1 = lba >> 8; ! 769: c->lba_0 = lba & 0xff; ! 770: c->reserved1 = 0; ! 771: c->reserved2 = 0; ! 772: c->reserved3 = 0; ! 773: c->ctlbyte = 0; ! 774: ! 775: scsiCDB.cdbLength = 10; ! 776: req->setCDB( &scsiCDB ); ! 777: req->setPointers(cx->senseDataDesc, 255, false, true); ! 778: ! 779: req->setPointers( cx->memory, 0, false ); ! 780: ! 781: req->setTimeout( 5000 ); ! 782: ! 783: result = simpleSynchIO(cx); ! 784: ! 785: deleteContext(cx); ! 786: ! 787: return(result); ! 788: } ! 789: ! 790: IOReturn ! 791: IOSCSICDDrive::setAudioStopAddress(positioningType addressType,cdAddress address) ! 792: { ! 793: /* We have to stash the stop address locally, because the client often sets ! 794: * the stop address before providing the start address. We can't send the ! 795: * stop address to the drive without a valid start address, because the pickup ! 796: * could be currently over a data track, which would return an error. ! 797: */ ! 798: ! 799: _audioStopAddress.type = addressType; ! 800: _audioStopAddress.address = address; ! 801: ! 802: /* If the address is for block=0, we must stop any audio play in progress. */ ! 803: ! 804: if (addressType == kBlockAddress && address == 0L) { /* stop play */ ! 805: return(doAudioPlayCommand(kAbsoluteTime,0xffffff,kAbsoluteTime,0)); ! 806: } else { /* set new stop addr */ ! 807: return(doAudioPlayCommand(kAbsoluteTime,0xffffff,addressType,address)); ! 808: } ! 809: } ! 810: ! 811: IOReturn ! 812: IOSCSICDDrive::setDefaultAudioModes(void) ! 813: { ! 814: initAudioModes(); ! 815: return(setVolume(_leftVolume,_rightVolume)); ! 816: } ! 817: ! 818: struct audioPage { ! 819: UInt8 pagecode; ! 820: UInt8 paramlen; ! 821: UInt8 immed; ! 822: UInt8 reserved[5]; ! 823: UInt8 leftportchannel; ! 824: UInt8 leftvolume; ! 825: UInt8 rightportchannel; ! 826: UInt8 rightvolume; ! 827: UInt8 port2channel; ! 828: UInt8 port2volume; ! 829: UInt8 port3channel; ! 830: UInt8 port3volume; ! 831: }; ! 832: ! 833: IOReturn ! 834: IOSCSICDDrive::setVolume(UInt8 leftVolume,UInt8 rightVolume) ! 835: { ! 836: struct context *cx; ! 837: struct IOModeSelectcdb *c; ! 838: IOSCSICommand *req; ! 839: SCSICDBInfo scsiCDB; ! 840: IOReturn result; ! 841: struct audioPage *page; ! 842: ! 843: cx = allocateContext(); ! 844: if (cx == NULL) { ! 845: return(kIOReturnNoMemory); ! 846: } ! 847: ! 848: req = cx->scsireq; ! 849: ! 850: bzero( &scsiCDB, sizeof(scsiCDB) ); ! 851: ! 852: /* Set up a Mode Select for page 0x0e. We set volume and audioPlay mode. */ ! 853: ! 854: result = allocateTempBuffer((UInt8 **)(&page),sizeof(struct audioPage)); ! 855: if (result != kIOReturnSuccess) { ! 856: deleteContext(cx); ! 857: return(kIOReturnNoMemory); ! 858: } ! 859: ! 860: bzero(page,sizeof(struct audioPage)), ! 861: page->pagecode = 0x0e; ! 862: page->paramlen = 0x0e; ! 863: ! 864: page->leftportchannel = playModeToDriveBits(_audioPlayMode,kLeft); ! 865: page->leftvolume = leftVolume; ! 866: page->rightportchannel = playModeToDriveBits(_audioPlayMode,kRight); ! 867: page->rightvolume = rightVolume; ! 868: ! 869: c = (struct IOModeSelectcdb *)(scsiCDB.cdb); ! 870: ! 871: c->opcode = SOP_MODESELECT; ! 872: c->lunbits = 0; ! 873: c->reserved1 = 0; ! 874: c->reserved2 = 0; ! 875: c->paramlen = sizeof(struct audioPage); ! 876: c->ctlbyte = 0; ! 877: ! 878: // IOLog("%s[IOSCSICDDrive::setVolume\n",getName()); ! 879: ! 880: scsiCDB.cdbLength = 6; ! 881: req->setCDB( &scsiCDB ); ! 882: req->setPointers(cx->senseDataDesc, 255, false, true); ! 883: ! 884: cx->memory = IOMemoryDescriptor::withAddress((void *)page, ! 885: c->paramlen, ! 886: kIODirectionOut); ! 887: req->setPointers( cx->memory, c->paramlen, true ); ! 888: ! 889: req->setTimeout( 1000 ); ! 890: ! 891: result = simpleSynchIO(cx); ! 892: ! 893: deleteTempBuffer((UInt8 *)page,sizeof(struct audioPage)); ! 894: deleteContext(cx); ! 895: ! 896: if (result == kIOReturnSuccess) { /* only remember settings if they worked */ ! 897: _leftVolume = leftVolume; ! 898: _rightVolume = rightVolume; ! 899: } ! 900: ! 901: return(result); ! 902: } ! 903:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.