Annotation of XNU/iokit/Families/IOSCSICDDrive/IOSCSICDDrive.cpp, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.