Annotation of ntddk/src/scsi/cdaudio/cdaudio.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1992, 1993  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     audio.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This driver filters scsi-2 cdrom audio commands for non-scsi-2
        !            12:     compliant cdrom drives.  At initialization, the driver scans the
        !            13:     scsi bus for a recognized non-scsi-2 cdrom drive, and if one is
        !            14:     found attached, installs itself to intercept IO_DEVICE_CONTROL
        !            15:     requests for this drive.
        !            16: 
        !            17: Author:
        !            18: 
        !            19:     Rick Turner
        !            20: 
        !            21: Environment:
        !            22: 
        !            23:     kernel mode only
        !            24: 
        !            25: Notes:
        !            26: 
        !            27: Revision History:
        !            28: 
        !            29: 
        !            30: --*/
        !            31: 
        !            32: #include "ntddk.h"
        !            33: #include "scsi.h"
        !            34: #include "stdio.h"
        !            35: #include "stdarg.h"
        !            36: 
        !            37: #include "cdaudio.h"
        !            38: 
        !            39: 
        !            40: //
        !            41: // Function declarations
        !            42: //
        !            43: 
        !            44: NTSTATUS
        !            45: DriverEntry (
        !            46:     IN PDRIVER_OBJECT DriverObject,
        !            47:     IN PUNICODE_STRING RegistryPath
        !            48:     );
        !            49: 
        !            50: NTSTATUS
        !            51: CdAudioInitialize(
        !            52:     IN PDRIVER_OBJECT DriverObject
        !            53:     );
        !            54: 
        !            55: NTSTATUS
        !            56: CdAudioCreate(
        !            57:     IN PDEVICE_OBJECT DeviceObject,
        !            58:     IN PIRP Irp
        !            59:     );
        !            60: 
        !            61: NTSTATUS
        !            62: CdAudioReadWrite(
        !            63:     IN PDEVICE_OBJECT DeviceObject,
        !            64:     IN PIRP Irp
        !            65:     );
        !            66: 
        !            67: NTSTATUS
        !            68: CdAudioDeviceControl(
        !            69:     IN PDEVICE_OBJECT DeviceObject,
        !            70:     IN PIRP Irp
        !            71:     );
        !            72: 
        !            73: NTSTATUS
        !            74: CdAudioSendToNextDriver(
        !            75:     IN PDEVICE_OBJECT DeviceObject,
        !            76:     IN PIRP Irp
        !            77:     );
        !            78: 
        !            79: BOOLEAN
        !            80: CdAudioIsPlayActive(
        !            81:     IN PDEVICE_OBJECT DeviceObject
        !            82:     );
        !            83: 
        !            84: NTSTATUS
        !            85: CdAudioNECDeviceControl(
        !            86:     IN PDEVICE_OBJECT DeviceObject,
        !            87:     IN PIRP Irp
        !            88:     );
        !            89: 
        !            90: NTSTATUS
        !            91: CdAudioNECInterpretSenseInfo(
        !            92:     IN PDEVICE_OBJECT DeviceObject,
        !            93:     IN PSCSI_REQUEST_BLOCK Srb,
        !            94:     IN UCHAR MajorFunctionCode,
        !            95:     IN ULONG IoDeviceCode,
        !            96:     IN ULONG RetryCount,
        !            97:     OUT NTSTATUS *Status
        !            98:     );
        !            99: 
        !           100: NTSTATUS
        !           101: CdAudioNECSendSrbSynchronous(
        !           102:     PDEVICE_OBJECT DeviceObject,
        !           103:     PSCSI_REQUEST_BLOCK Srb,
        !           104:     PVOID BufferAddress,
        !           105:     ULONG BufferLength,
        !           106:     BOOLEAN WriteToDevice
        !           107:     );
        !           108: 
        !           109: NTSTATUS
        !           110: CdAudioPioneerDeviceControl(
        !           111:     IN PDEVICE_OBJECT DeviceObject,
        !           112:     IN PIRP Irp
        !           113:     );
        !           114: 
        !           115: NTSTATUS
        !           116: CdAudioDenonDeviceControl(
        !           117:     IN PDEVICE_OBJECT DeviceObject,
        !           118:     IN PIRP Irp
        !           119:     );
        !           120: 
        !           121: NTSTATUS
        !           122: CdAudioHitatchiSendPauseCommand(
        !           123:     IN PDEVICE_OBJECT DeviceObject
        !           124:     );
        !           125: 
        !           126: NTSTATUS
        !           127: CdAudioHitatchiDeviceControl(
        !           128:     IN PDEVICE_OBJECT DeviceObject,
        !           129:     IN PIRP Irp
        !           130:     );
        !           131: 
        !           132: NTSTATUS
        !           133: CdAudio535DeviceControl(
        !           134:     IN PDEVICE_OBJECT DeviceObject,
        !           135:     IN PIRP Irp
        !           136:     );
        !           137: 
        !           138: 
        !           139: NTSTATUS
        !           140: CdAudio435DeviceControl(
        !           141:     IN PDEVICE_OBJECT DeviceObject,
        !           142:     IN PIRP Irp
        !           143:     );
        !           144: 
        !           145: 
        !           146: NTSTATUS
        !           147: CdAudioIoCompletion(
        !           148:     IN PDEVICE_OBJECT DeviceObject,
        !           149:     IN PIRP Irp,
        !           150:     IN PVOID Context
        !           151:     );
        !           152: 
        !           153: //
        !           154: // from class.h
        !           155: //
        !           156: 
        !           157: NTSTATUS
        !           158: ScsiClassSendSrbSynchronous(
        !           159:     PDEVICE_OBJECT DeviceObject,
        !           160:     PSCSI_REQUEST_BLOCK Srb,
        !           161:     PVOID BufferAddress,
        !           162:     ULONG BufferLength,
        !           163:     BOOLEAN WriteToDevice
        !           164:     );
        !           165: 
        !           166: VOID
        !           167: ScsiClassReleaseQueue(
        !           168:     IN PDEVICE_OBJECT DeviceObject
        !           169:     );
        !           170: 
        !           171: //
        !           172: // define for private CdDump
        !           173: //
        !           174: 
        !           175: int
        !           176: sprintf(
        !           177:     char *s,
        !           178:     const char *format,
        !           179:     ...
        !           180:     );
        !           181: 
        !           182: 
        !           183: NTSTATUS
        !           184: DriverEntry(
        !           185:     IN PDRIVER_OBJECT DriverObject,
        !           186:     IN PUNICODE_STRING RegistryPath
        !           187:     )
        !           188: 
        !           189: {
        !           190:     return CdAudioInitialize(DriverObject);
        !           191: }
        !           192: 
        !           193: 
        !           194: 
        !           195: NTSTATUS
        !           196: CdAudioInitialize(
        !           197:     IN PDRIVER_OBJECT DriverObject
        !           198:     )
        !           199: 
        !           200: /*++
        !           201: 
        !           202: Routine Description:
        !           203: 
        !           204:     Initialize CdAudio driver.
        !           205:     This is the system initialization entry point when
        !           206:     the driver is linked into the kernel.
        !           207: 
        !           208: Arguments:
        !           209: 
        !           210:     DriverObject
        !           211: 
        !           212: Return Value:
        !           213: 
        !           214:     NTSTATUS
        !           215: 
        !           216: --*/
        !           217: 
        !           218: {
        !           219:     PCONFIGURATION_INFORMATION configurationInformation;
        !           220:     UCHAR               deviceNameBuffer[64];
        !           221:     ANSI_STRING         deviceName;
        !           222:     UNICODE_STRING      unicodeDeviceName;
        !           223:     PDEVICE_OBJECT      cdaudioDevice;
        !           224:     PCD_DEVICE_EXTENSION   deviceExtension;
        !           225:     NTSTATUS            status;
        !           226:     ULONG               disks,activedisks;
        !           227:     SCSI_REQUEST_BLOCK  srb;
        !           228:     PCDB                cdb = (PCDB)srb.Cdb;
        !           229:     PUCHAR              inquiryDataPtr;
        !           230: 
        !           231:     //
        !           232:     // Set up the device driver entry points.
        !           233:     //
        !           234: 
        !           235:     DriverObject->MajorFunction[IRP_MJ_CREATE]         = CdAudioCreate;
        !           236:     DriverObject->MajorFunction[IRP_MJ_READ]           = CdAudioReadWrite;
        !           237:     DriverObject->MajorFunction[IRP_MJ_WRITE]          = CdAudioReadWrite;
        !           238:     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CdAudioDeviceControl;
        !           239: 
        !           240:     //
        !           241:     // Get the configuration information for this driver.
        !           242:     //
        !           243: 
        !           244:     configurationInformation = IoGetConfigurationInformation();
        !           245: 
        !           246:     CdDump((1, "CdAudioInitialize: Found %d CdRom drives\n",
        !           247:                 configurationInformation->CdRomCount));
        !           248: 
        !           249:     //
        !           250:     // Find disk devices.
        !           251:     //
        !           252: 
        !           253:     activedisks = 0;
        !           254:     for (disks = 0; disks < configurationInformation->CdRomCount; disks++) {
        !           255: 
        !           256: 
        !           257:         //
        !           258:         // Create device name for CdAudio (one per CdRom).
        !           259:         //
        !           260: 
        !           261:         sprintf(deviceNameBuffer,
        !           262:                 "\\Device\\CdAudio%d",
        !           263:                 disks);
        !           264:         CdDump(( 5, "CdAudioInitialize: Checking \\Device\\CdRom%d\n",
        !           265:                      disks ));
        !           266:         RtlInitAnsiString(&deviceName,
        !           267:                           deviceNameBuffer);
        !           268:         RtlAnsiStringToUnicodeString(&unicodeDeviceName,
        !           269:                                      &deviceName,
        !           270:                                      TRUE);
        !           271: 
        !           272:         //
        !           273:         // Create the device object for CdAudio.
        !           274:         //
        !           275: 
        !           276:         status = IoCreateDevice(DriverObject,
        !           277:                                 sizeof(CD_DEVICE_EXTENSION),
        !           278:                                 &unicodeDeviceName,
        !           279:                                 FILE_DEVICE_CD_ROM,
        !           280:                                 0,
        !           281:                                 FALSE,
        !           282:                                 &cdaudioDevice);
        !           283: 
        !           284:         RtlFreeUnicodeString(&unicodeDeviceName);
        !           285: 
        !           286:         if (!NT_SUCCESS(status)) {
        !           287:             CdDump((1, "CdAudioInitialize: IoCreateDevice( \"%s\" ) failed, 0x%lX\n",
        !           288:                         deviceNameBuffer, status));
        !           289:             continue;
        !           290:         }
        !           291: 
        !           292:         //
        !           293:         // Point device extension back at device object.
        !           294:         //
        !           295: 
        !           296:         deviceExtension = cdaudioDevice->DeviceExtension;
        !           297:         deviceExtension->DeviceObject = cdaudioDevice;
        !           298: 
        !           299:         //
        !           300:         // Attach to cdrom drive. This call links the newly created
        !           301:         // device to the target device, returning the target device
        !           302:         // object.
        !           303:         //
        !           304: 
        !           305:         sprintf(deviceNameBuffer,
        !           306:                 "\\Device\\CdRom%d",
        !           307:                 disks);
        !           308:         RtlInitAnsiString(&deviceName,
        !           309:                           deviceNameBuffer);
        !           310:         RtlAnsiStringToUnicodeString(&unicodeDeviceName,
        !           311:                                      &deviceName,
        !           312:                                      TRUE);
        !           313:         status = IoAttachDevice(cdaudioDevice,
        !           314:                                 &unicodeDeviceName,
        !           315:                                 &deviceExtension->TargetDeviceObject);
        !           316:         RtlFreeUnicodeString(&unicodeDeviceName);
        !           317: 
        !           318:         if (!NT_SUCCESS(status)) {
        !           319:             IoDeleteDevice(cdaudioDevice);
        !           320:             CdDump((1, "CdAudioInialize: IoAttachDevice( \"%s\" ) failed, 0x%lX\n",
        !           321:                         deviceNameBuffer, status));
        !           322:             continue;
        !           323:         }
        !           324: 
        !           325:         //
        !           326:         // Initialize the class device extension. This is used by the
        !           327:         // class commands such as ScsiClassSendSrbSynchronous.  The only fields used
        !           328:         // are the port device object pointer which is set to the attached
        !           329:         // device.  The DeviceNumber, DeviceObject, and TimeOutVlaue are also
        !           330:         // used. The logical unit address will be set the the lower driver.
        !           331:         //
        !           332: 
        !           333:         deviceExtension->ClassDeviceExtension.DeviceObject = cdaudioDevice;
        !           334:         deviceExtension->ClassDeviceExtension.DeviceNumber = disks;
        !           335:         deviceExtension->ClassDeviceExtension.PortDeviceObject =
        !           336:             deviceExtension->TargetDeviceObject;
        !           337:         deviceExtension->ClassDeviceExtension.TimeOutValue = AUDIO_TIMEOUT;
        !           338: 
        !           339:         //
        !           340:         // Indicate to drivers above us that we want IRPs
        !           341:         // with MDLs, so we can pass them directly on to
        !           342:         // scsicdrm.sys when we don't handle the call.
        !           343:         //
        !           344: 
        !           345:         cdaudioDevice->Flags |= DO_DIRECT_IO;
        !           346: 
        !           347:         //
        !           348:         // Check to see if we want to install for this
        !           349:         // cdrom drive.  Build up cdb/srb, and send it
        !           350:         // to this drive.
        !           351:         //
        !           352: 
        !           353:         //
        !           354:         // Zero CDB in SRB on stack
        !           355:         //
        !           356: 
        !           357:         RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !           358: 
        !           359:         //
        !           360:         // Fill in CDB for INQUIRY to CDROM
        !           361:         //
        !           362: 
        !           363:         cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
        !           364:         cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
        !           365: 
        !           366:         //
        !           367:         // Allocate buffer for returned inquiry data
        !           368:         //
        !           369: 
        !           370:         inquiryDataPtr = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !           371:                                                  INQUIRYDATABUFFERSIZE
        !           372:                                                 );
        !           373: 
        !           374:         //
        !           375:         // Set length of CDB
        !           376:         //
        !           377: 
        !           378:         srb.CdbLength = 6;
        !           379: 
        !           380:         //
        !           381:         // Set timeout value.
        !           382:         //
        !           383: 
        !           384:         srb.TimeOutValue = AUDIO_TIMEOUT;
        !           385: 
        !           386:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !           387:                                      &srb,
        !           388:                                      inquiryDataPtr,
        !           389:                                      INQUIRYDATABUFFERSIZE,
        !           390:                                      FALSE
        !           391:                                     );
        !           392: 
        !           393:         if (!NT_SUCCESS(status)) {
        !           394: 
        !           395:             CdDump(( 1, "CdAudioInitialize: Inquiry failed! (0x%lx)\n",
        !           396:                          status ));
        !           397: 
        !           398:             ExFreePool( inquiryDataPtr );
        !           399:             IoDetachDevice(deviceExtension->TargetDeviceObject);
        !           400:             IoDeleteDevice(cdaudioDevice);
        !           401: 
        !           402:         } else {
        !           403: 
        !           404:             //
        !           405:             // Initialize device extension data
        !           406:             //
        !           407: 
        !           408:             deviceExtension->Active = CDAUDIO_NOT_ACTIVE;
        !           409:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !           410:             deviceExtension->PausedM  = 0;
        !           411:             deviceExtension->PausedS  = 0;
        !           412:             deviceExtension->PausedF  = 0;
        !           413:             deviceExtension->LastEndM = 0;
        !           414:             deviceExtension->LastEndS = 0;
        !           415:             deviceExtension->LastEndF = 0;
        !           416: 
        !           417:             //
        !           418:             // Check for NEC drive
        !           419:             //
        !           420: 
        !           421:             if ((inquiryDataPtr[8] =='N') &&
        !           422:                 (inquiryDataPtr[9] =='E') &&
        !           423:                 (inquiryDataPtr[10]=='C')) {
        !           424: 
        !           425:                 deviceExtension->Active = CDAUDIO_NEC;
        !           426:                 CdDump(( 3, "CdAudioInitialize: %s is a NEC drive.\n",
        !           427:                              deviceNameBuffer ));
        !           428:             }
        !           429: 
        !           430:             //
        !           431:             // Check for PIONEER DRM-6xx drive
        !           432:             //
        !           433: 
        !           434:             if ((inquiryDataPtr[8] =='P') &&
        !           435:                 (inquiryDataPtr[9] =='I') &&
        !           436:                 (inquiryDataPtr[10]=='O') &&
        !           437:                 (inquiryDataPtr[23]=='D') &&
        !           438:                 (inquiryDataPtr[24]=='R') &&
        !           439:                 (inquiryDataPtr[25]=='M') &&
        !           440:                 (inquiryDataPtr[27]=='6')) {
        !           441: 
        !           442:                 deviceExtension->Active = CDAUDIO_PIONEER;
        !           443:                 CdDump(( 3, "CdAudioInitialize: %s is a PIONEER DRM-6xx drive.\n",
        !           444:                              deviceNameBuffer ));
        !           445:             }
        !           446: 
        !           447:             //
        !           448:             // Check for DENON drive
        !           449:             //
        !           450: 
        !           451:             if ((inquiryDataPtr[8] =='D') &&
        !           452:                 (inquiryDataPtr[9] =='E') &&
        !           453:                 (inquiryDataPtr[10]=='N') &&
        !           454:                 (inquiryDataPtr[16]=='D') &&
        !           455:                 (inquiryDataPtr[17]=='R') &&
        !           456:                 (inquiryDataPtr[18]=='D') &&
        !           457:                 (inquiryDataPtr[20]=='2') &&
        !           458:                 (inquiryDataPtr[21]=='5') &&
        !           459:                 (inquiryDataPtr[22]=='X')) {
        !           460: 
        !           461:                 deviceExtension->Active = CDAUDIO_DENON;
        !           462:                 CdDump(( 3, "CdAudioInitialize: %s is a DENON DRD-25X drive.\n",
        !           463:                              deviceNameBuffer ));
        !           464:             }
        !           465:                 
        !           466:             //
        !           467:             // Check for Chinon CDS-535
        !           468:             //
        !           469:             
        !           470:             if ((inquiryDataPtr[8] =='C') &&
        !           471:                 (inquiryDataPtr[9] =='H') &&
        !           472:                 (inquiryDataPtr[10]=='I') &&
        !           473:                 (inquiryDataPtr[11]=='N') &&
        !           474:                 (inquiryDataPtr[12]=='O') &&
        !           475:                 (inquiryDataPtr[13]=='N') &&
        !           476:                 (inquiryDataPtr[27]=='5') &&
        !           477:                 (inquiryDataPtr[28]=='3') &&
        !           478:                 (inquiryDataPtr[29]=='5') &&
        !           479:                 (inquiryDataPtr[32]=='Q')) {
        !           480:             
        !           481:                 deviceExtension->Active = CDAUDIO_CDS535;
        !           482:                 CdDump(( 3, "CdAudioInitialize: %s is a Chinon CDS-535 drive.\n",
        !           483:                              deviceNameBuffer ));
        !           484:             }
        !           485:             
        !           486:             //
        !           487:             // Check for Chinon CDS-435 or CDS-431
        !           488:             //  (willing to handle versions M/N, S/U, and H)
        !           489:             
        !           490:             if ((inquiryDataPtr[8] =='C') &&
        !           491:                 (inquiryDataPtr[9] =='H') &&
        !           492:                 (inquiryDataPtr[10]=='I') &&
        !           493:                 (inquiryDataPtr[11]=='N') &&
        !           494:                 (inquiryDataPtr[12]=='O') &&
        !           495:                 (inquiryDataPtr[13]=='N') &&
        !           496:                 (inquiryDataPtr[27]=='4') &&
        !           497:                 (inquiryDataPtr[28]=='3') &&
        !           498:                 ((inquiryDataPtr[29]=='5') || (inquiryDataPtr[29]=='1')) &&
        !           499:                 ((inquiryDataPtr[32]=='M') ||
        !           500:                  (inquiryDataPtr[32]=='N') ||
        !           501:                  (inquiryDataPtr[32]=='S') ||
        !           502:                  (inquiryDataPtr[32]=='U') ||
        !           503:                  (inquiryDataPtr[32]=='H')
        !           504:                 )) {
        !           505:             
        !           506:                 deviceExtension->Active = CDAUDIO_CDS435;
        !           507:                 CdDump(( 3, "CdAudioInitialize: %s is a Chinon CDS-435/431 drive.\n",
        !           508:                              deviceNameBuffer ));
        !           509:             }
        !           510: 
        !           511:             //
        !           512:             // Check for HITATCHI drives
        !           513:             //
        !           514: 
        !           515:             if ((inquiryDataPtr[8] =='H') &&
        !           516:                 (inquiryDataPtr[9] =='I') &&
        !           517:                 (inquiryDataPtr[10]=='T') &&
        !           518:                 (inquiryDataPtr[16]=='C') &&
        !           519:                 (inquiryDataPtr[17]=='D') &&
        !           520:                 (inquiryDataPtr[18]=='R')) {
        !           521: 
        !           522:                 //
        !           523:                 // It's a Hitatchi drive...is it one we want to
        !           524:                 // handle...?
        !           525:                 //
        !           526: 
        !           527:                 if ( ((inquiryDataPtr[20]=='1') &&
        !           528:                       (inquiryDataPtr[21]=='7') &&
        !           529:                       (inquiryDataPtr[22]=='5') &&
        !           530:                       (inquiryDataPtr[23]=='0') &&
        !           531:                       (inquiryDataPtr[24]=='S'))  ||
        !           532: 
        !           533:                      ((inquiryDataPtr[20]=='1') &&
        !           534:                       (inquiryDataPtr[21]=='6') &&
        !           535:                       (inquiryDataPtr[22]=='5') &&
        !           536:                       (inquiryDataPtr[23]=='0') &&
        !           537:                       (inquiryDataPtr[24]=='S'))  ||
        !           538: 
        !           539:                      ((inquiryDataPtr[20]=='3') &&
        !           540:                       (inquiryDataPtr[21]=='6') &&
        !           541:                       (inquiryDataPtr[22]=='5') &&
        !           542:                       (inquiryDataPtr[23]=='0'))
        !           543: 
        !           544:                    ) {
        !           545: 
        !           546:                         //
        !           547:                         // Yes, we want to handle this HITATCHI drive...
        !           548:                         //
        !           549: 
        !           550:                         deviceExtension->Active = CDAUDIO_HITATCHI;
        !           551:                         inquiryDataPtr[25] = (UCHAR)0;
        !           552:                         CdDump(( 3,
        !           553:                             "CdAudioInitialize: %s is a HITATCHI %s drive.\n",
        !           554:                             deviceNameBuffer, &inquiryDataPtr[16] ));
        !           555:                     }
        !           556:                 
        !           557:             }
        !           558: 
        !           559:             ExFreePool( inquiryDataPtr );
        !           560: 
        !           561:             //
        !           562:             // Check to see if we attached to ANY drives.
        !           563:             //
        !           564: 
        !           565:             if (deviceExtension->Active==CDAUDIO_NOT_ACTIVE) {
        !           566: 
        !           567:                 IoDetachDevice(deviceExtension->TargetDeviceObject);
        !           568:                 IoDeleteDevice(cdaudioDevice);
        !           569:                 CdDump((1, "CdAudioInitialize: failed attach to %s\n",
        !           570:                             deviceNameBuffer));
        !           571: 
        !           572:             } else
        !           573: 
        !           574:                 activedisks++;
        !           575: 
        !           576:         } // end inquiry was successful
        !           577: 
        !           578:     } // end for (disks ...)
        !           579: 
        !           580:     CdDump((1, "CdAudioInitialize: Done searching all cdrom drives\n"));
        !           581: 
        !           582:     if (activedisks==0)
        !           583: 
        !           584:         return STATUS_NO_SUCH_DEVICE;
        !           585: 
        !           586:     else
        !           587: 
        !           588:         return STATUS_SUCCESS;
        !           589: 
        !           590: } // end CdAudioInitialize()
        !           591: 
        !           592: 
        !           593: NTSTATUS
        !           594: CdAudioCreate(
        !           595:     IN PDEVICE_OBJECT DeviceObject,
        !           596:     IN PIRP Irp
        !           597:     )
        !           598: 
        !           599: /*++
        !           600: 
        !           601: Routine Description:
        !           602: 
        !           603:     This routine serves create commands. It does no more than
        !           604:     establish the drivers existance by returning status success.
        !           605: 
        !           606: Arguments:
        !           607: 
        !           608:     DeviceObject
        !           609:     IRP
        !           610: 
        !           611: Return Value:
        !           612: 
        !           613:     NT Status
        !           614: 
        !           615: --*/
        !           616: 
        !           617: {
        !           618:     UNREFERENCED_PARAMETER(DeviceObject);
        !           619: 
        !           620:     Irp->IoStatus.Status = STATUS_SUCCESS;
        !           621: 
        !           622:     IoCompleteRequest(Irp, 0);
        !           623:     return STATUS_SUCCESS;
        !           624: 
        !           625: } // end CdAudioCreate()
        !           626: 
        !           627: 
        !           628: NTSTATUS
        !           629: CdAudioReadWrite(
        !           630:     IN PDEVICE_OBJECT DeviceObject,
        !           631:     IN PIRP Irp
        !           632:     )
        !           633: 
        !           634: /*++
        !           635: 
        !           636: Routine Description:
        !           637: 
        !           638:     This is the driver entry point for read and write requests
        !           639:     to the cdrom.  Since we only want to trap device control requests,
        !           640:     we will just pass these requests on to the original driver.
        !           641: 
        !           642: Arguments:
        !           643: 
        !           644:     DeviceObject - pointer to device object for disk partition
        !           645:     Irp - NT IO Request Packet
        !           646: 
        !           647: Return Value:
        !           648: 
        !           649:     NTSTATUS - status of request
        !           650: 
        !           651: --*/
        !           652: 
        !           653: {
        !           654:     PCD_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !           655: 
        !           656:     //
        !           657:     // If the cd is playing music then reject this request.
        !           658:     //
        !           659: 
        !           660:     if (deviceExtension->PlayActive) {
        !           661:         Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
        !           662:         IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !           663:         return STATUS_DEVICE_BUSY;
        !           664:     }
        !           665: 
        !           666:     //
        !           667:     // simply return status of driver below us...
        !           668:     //
        !           669: 
        !           670:     return CdAudioSendToNextDriver( DeviceObject, Irp );
        !           671: 
        !           672: } // end CdAudioReadWrite()
        !           673: 
        !           674: 
        !           675: NTSTATUS
        !           676: CdAudioDeviceControl(
        !           677:     PDEVICE_OBJECT DeviceObject,
        !           678:     PIRP Irp
        !           679:     )
        !           680: 
        !           681: /*++
        !           682: 
        !           683: Routine Description:
        !           684: 
        !           685:     This routine is called by the I/O subsystem for device controls.
        !           686: 
        !           687: Arguments:
        !           688: 
        !           689:     DeviceObject
        !           690:     Irp
        !           691: 
        !           692: Return Value:
        !           693: 
        !           694:     NTSTATUS
        !           695: 
        !           696: --*/
        !           697: 
        !           698: {
        !           699:     PCD_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !           700:     NTSTATUS status;
        !           701: 
        !           702:     switch( deviceExtension->Active ) {
        !           703: 
        !           704:         case CDAUDIO_NOT_ACTIVE:
        !           705:             CdDump(( 3,
        !           706:                 "CdAudioDeviceControl: NOT ACTIVE for this drive.\n"
        !           707:                 ));
        !           708:             status = CdAudioSendToNextDriver( DeviceObject, Irp );
        !           709:             break;
        !           710: 
        !           711:         case CDAUDIO_NEC:
        !           712:             status = CdAudioNECDeviceControl( DeviceObject, Irp );
        !           713:             break;
        !           714: 
        !           715:         case CDAUDIO_PIONEER:
        !           716:             status = CdAudioPioneerDeviceControl( DeviceObject, Irp );
        !           717:             break;
        !           718: 
        !           719:         case CDAUDIO_DENON:
        !           720:             status = CdAudioDenonDeviceControl( DeviceObject, Irp );
        !           721:             break;
        !           722: 
        !           723:         case CDAUDIO_HITATCHI:
        !           724:             status = CdAudioHitatchiDeviceControl( DeviceObject, Irp );
        !           725:             break;
        !           726: 
        !           727:         case CDAUDIO_CDS535:
        !           728:             status = CdAudio535DeviceControl( DeviceObject, Irp );
        !           729:             break;
        !           730: 
        !           731:         case CDAUDIO_CDS435:
        !           732:             status = CdAudio435DeviceControl( DeviceObject, Irp );
        !           733:             break;
        !           734: 
        !           735:         default:
        !           736:             CdDump(( 1,
        !           737:                 "CdAudioDeviceControl: Active==UNKNOWN!!! This is bad!\n"
        !           738:                 ));
        !           739:             status = STATUS_UNSUCCESSFUL;
        !           740: 
        !           741:     }
        !           742: 
        !           743:     return status;
        !           744: 
        !           745: } // end CdAudioDeviceControl()
        !           746: 
        !           747: 
        !           748: 
        !           749: NTSTATUS
        !           750: CdAudioSendToNextDriver(
        !           751:     PDEVICE_OBJECT DeviceObject,
        !           752:     PIRP Irp
        !           753:     )
        !           754: 
        !           755: /*++
        !           756: 
        !           757: Routine Description:
        !           758: 
        !           759:     This routine is sends the Irp to the next driver in line
        !           760:     when the Irp is not processed by this driver.
        !           761: 
        !           762: Arguments:
        !           763: 
        !           764:     DeviceObject
        !           765:     Irp
        !           766: 
        !           767: Return Value:
        !           768: 
        !           769:     NTSTATUS
        !           770: 
        !           771: --*/
        !           772: 
        !           773: {
        !           774:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !           775:     PIO_STACK_LOCATION nextIrpStack    = IoGetNextIrpStackLocation(Irp);
        !           776:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !           777: 
        !           778:     //
        !           779:     // Copy stack parameters to next stack.
        !           780:     //
        !           781: 
        !           782:     RtlMoveMemory(nextIrpStack,
        !           783:                   currentIrpStack,
        !           784:                   sizeof(IO_STACK_LOCATION));
        !           785: 
        !           786:     //
        !           787:     // Set IRP so IoComplete calls our completion routine.
        !           788:     //
        !           789: 
        !           790:     IoSetCompletionRoutine(Irp,
        !           791:                            CdAudioIoCompletion,
        !           792:                            deviceExtension,
        !           793:                            TRUE,
        !           794:                            TRUE,
        !           795:                            TRUE);
        !           796: 
        !           797:     //
        !           798:     // Pass unrecognized device control requests
        !           799:     // down to next driver layer.
        !           800:     //
        !           801: 
        !           802:     return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
        !           803: 
        !           804: }
        !           805: 
        !           806: NTSTATUS
        !           807: CdAudioIoCompletion(
        !           808:     IN PDEVICE_OBJECT DeviceObject,
        !           809:     IN PIRP Irp,
        !           810:     IN PVOID Context
        !           811:     )
        !           812: 
        !           813: /*++
        !           814: 
        !           815: Routine Description:
        !           816: 
        !           817:     This routine is called when the I/O request has completed.
        !           818: 
        !           819: Arguments:
        !           820: 
        !           821:     DeviceObject - SimBad device object.
        !           822:     Irp          - Completed request.
        !           823:     Context      - not used.  Set up to also be a pointer to the DeviceObject.
        !           824: 
        !           825: Return Value:
        !           826: 
        !           827:     NTSTATUS
        !           828: 
        !           829: --*/
        !           830: 
        !           831: {
        !           832:     UNREFERENCED_PARAMETER(Context);
        !           833:     UNREFERENCED_PARAMETER(DeviceObject);
        !           834: 
        !           835: 
        !           836:     //
        !           837:     // If pending is returned for this Irp then mark current stack
        !           838:     // as pending
        !           839:     //
        !           840: 
        !           841:     if (Irp->PendingReturned) {
        !           842: 
        !           843:         IoMarkIrpPending( Irp );
        !           844: 
        !           845:     }
        !           846: 
        !           847:     return Irp->IoStatus.Status;
        !           848: 
        !           849: }
        !           850: 
        !           851: BOOLEAN
        !           852: CdAudioIsPlayActive(
        !           853:     IN PDEVICE_OBJECT DeviceObject
        !           854:     )
        !           855: 
        !           856: /*++
        !           857: 
        !           858: Routine Description:
        !           859: 
        !           860:     This routine determines if the cd is currently playing music.
        !           861: 
        !           862: Arguments:
        !           863: 
        !           864:     DeviceObject - Device object to test.
        !           865: 
        !           866: Return Value:
        !           867: 
        !           868:     TRUE if the device is playing music.
        !           869: 
        !           870: --*/
        !           871: {
        !           872:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !           873:     PIRP irp;
        !           874:     IO_STATUS_BLOCK ioStatus;
        !           875:     KEVENT event;
        !           876:     NTSTATUS status;
        !           877:     PSUB_Q_CURRENT_POSITION currentBuffer;
        !           878:     BOOLEAN returnValue;
        !           879: 
        !           880:     if (!deviceExtension->PlayActive) {
        !           881:         return(FALSE);
        !           882:     }
        !           883: 
        !           884:     currentBuffer = ExAllocatePool(NonPagedPoolCacheAligned, sizeof(SUB_Q_CURRENT_POSITION));
        !           885: 
        !           886:     if (currentBuffer == NULL) {
        !           887:         return(FALSE);
        !           888:     }
        !           889: 
        !           890:     ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Format = IOCTL_CDROM_CURRENT_POSITION;
        !           891:     ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Track = 0;
        !           892: 
        !           893:     //
        !           894:     // Create notification event object to be used to signal the
        !           895:     // request completion.
        !           896:     //
        !           897: 
        !           898:     KeInitializeEvent(&event, NotificationEvent, FALSE);
        !           899: 
        !           900:     //
        !           901:     // Build the synchronous request  to be sent to the port driver
        !           902:     // to perform the request.
        !           903:     //
        !           904: 
        !           905:     irp = IoBuildDeviceIoControlRequest(IOCTL_CDROM_READ_Q_CHANNEL,
        !           906:                                         deviceExtension->DeviceObject,
        !           907:                                         currentBuffer,
        !           908:                                         sizeof(CDROM_SUB_Q_DATA_FORMAT),
        !           909:                                         currentBuffer,
        !           910:                                         sizeof(SUB_Q_CURRENT_POSITION),
        !           911:                                         FALSE,
        !           912:                                         &event,
        !           913:                                         &ioStatus);
        !           914: 
        !           915:     if (irp == NULL) {
        !           916:         ExFreePool(currentBuffer);
        !           917:         return FALSE;
        !           918:     }
        !           919: 
        !           920:     //
        !           921:     // Pass request to port driver and wait for request to complete.
        !           922:     //
        !           923: 
        !           924:     status = IoCallDriver(deviceExtension->DeviceObject, irp);
        !           925: 
        !           926:     if (status == STATUS_PENDING) {
        !           927:         KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
        !           928:         status = ioStatus.Status;
        !           929:     }
        !           930: 
        !           931:     if (!NT_SUCCESS(status)) {
        !           932:         ExFreePool(currentBuffer);
        !           933:         return FALSE;
        !           934:     }
        !           935: 
        !           936:     if (currentBuffer->Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) {
        !           937: 
        !           938:         returnValue = TRUE;
        !           939:     } else {
        !           940:         returnValue = FALSE;
        !           941:         deviceExtension->PlayActive = FALSE;
        !           942:     }
        !           943: 
        !           944:     ExFreePool(currentBuffer);
        !           945: 
        !           946:     return(returnValue);
        !           947: 
        !           948: 
        !           949: }
        !           950: 
        !           951: 
        !           952: NTSTATUS
        !           953: CdAudioNECInterpretSenseInfo(
        !           954:     IN PDEVICE_OBJECT DeviceObject,
        !           955:     IN PSCSI_REQUEST_BLOCK Srb,
        !           956:     IN UCHAR MajorFunctionCode,
        !           957:     IN ULONG IoDeviceCode,
        !           958:     IN ULONG RetryCount,
        !           959:     OUT NTSTATUS *Status
        !           960:     )
        !           961: 
        !           962: /*++
        !           963: 
        !           964: Routine Description:
        !           965: 
        !           966:     This routine interprets the data returned from the SCSI
        !           967:     request sense. It determines the status to return in the
        !           968:     IRP and whether this request can be retried.
        !           969: 
        !           970: Arguments:
        !           971: 
        !           972:     DeviceObject - Supplies the device object associated with this request.
        !           973: 
        !           974:     Srb - Supplies the scsi request block which failed.
        !           975: 
        !           976:     MajorFunctionCode - Supplies the function code to be used for logging.
        !           977: 
        !           978:     IoDeviceCode - Supplies the device code to be used for logging.
        !           979: 
        !           980:     Status - Returns the status for the request.
        !           981: 
        !           982: Return Value:
        !           983: 
        !           984:     BOOLEAN TRUE: Drivers should retry this request.
        !           985:             FALSE: Drivers should not retry this request.
        !           986: 
        !           987: --*/
        !           988: 
        !           989: {
        !           990:     PCD_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !           991:     PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
        !           992:     PIRP irp = Srb->OriginalRequest;
        !           993:     BOOLEAN retry;
        !           994:     BOOLEAN logError;
        !           995:     ULONG uniqueId;
        !           996:     NTSTATUS logStatus;
        !           997:     PIO_ERROR_LOG_PACKET errorLogEntry;
        !           998:     ULONG badSector;
        !           999: 
        !          1000:     logError = FALSE;
        !          1001:     retry = TRUE;
        !          1002:     badSector = 0;
        !          1003: 
        !          1004:     //
        !          1005:     // Check that request sense buffer is valid.
        !          1006:     //
        !          1007: 
        !          1008:     if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) {
        !          1009: 
        !          1010:         CdDump((1,"CdAudioNECInterpretSenseInfo: Error code is %x\n",
        !          1011:                     senseBuffer->ErrorCode));
        !          1012: 
        !          1013:         CdDump((1,"CdAudioNECInterpretSenseInfo: Sense key is %x\n",
        !          1014:                     senseBuffer->SenseKey));
        !          1015: 
        !          1016:         CdDump((1,"CdAudioNECInterpretSenseInfo: Additional sense code is %x\n",
        !          1017:                     senseBuffer->CommandSpecificInformation[1]));
        !          1018: 
        !          1019:             switch (senseBuffer->SenseKey & 0xf) {
        !          1020: 
        !          1021:                 case SCSI_SENSE_NOT_READY:
        !          1022: 
        !          1023:                     CdDump((1,"CdAudioNECInterpretSenseInfo: Device not ready\n"));
        !          1024: 
        !          1025:                     *Status = STATUS_DEVICE_NOT_READY;
        !          1026: 
        !          1027:                     retry = TRUE;
        !          1028: 
        !          1029:                     switch (senseBuffer->CommandSpecificInformation[1]) {
        !          1030: 
        !          1031:                     case NEC_SCSI_ERROR_NO_DISC:
        !          1032:                         CdDump(( 1, "CdAudioNECInterpretSenseInfo: No disc in drive\n" ));
        !          1033:                         *Status = STATUS_NO_MEDIA_IN_DEVICE;
        !          1034:                         retry = FALSE;
        !          1035:                         break;
        !          1036: 
        !          1037:                     case NEC_SCSI_ERROR_ILLEGAL_DISC:
        !          1038:                         CdDump(( 1, "CdAudioNECInterpretSenseInfo: Unrecognized media\n" ));
        !          1039:                         *Status = STATUS_UNRECOGNIZED_MEDIA;
        !          1040:                         retry = FALSE;
        !          1041:                         break;
        !          1042: 
        !          1043:                     case NEC_SCSI_ERROR_TRAY_OPEN:
        !          1044:                         CdDump(( 1, "CdAudioNECInterpretSenseInfo: Tray open\n" ));
        !          1045:                         *Status = STATUS_NO_MEDIA_IN_DEVICE;
        !          1046:                         retry = FALSE;
        !          1047:                         break;
        !          1048: 
        !          1049:                     } // end switch
        !          1050: 
        !          1051:                     break;
        !          1052: 
        !          1053:                 case SCSI_SENSE_DATA_PROTECT:
        !          1054: 
        !          1055:                     CdDump((1,
        !          1056:                                 "CdAudioNECInterpretSenseInfo: Media write protected\n"));
        !          1057: 
        !          1058:                     *Status = STATUS_MEDIA_WRITE_PROTECTED;
        !          1059: 
        !          1060:                     retry = FALSE;
        !          1061: 
        !          1062:                     break;
        !          1063: 
        !          1064:                 case SCSI_SENSE_MEDIUM_ERROR:
        !          1065: 
        !          1066:                     CdDump((1,"CdAudioNECInterpretSenseInfo: Bad media\n"));
        !          1067:                     *Status = STATUS_DEVICE_DATA_ERROR;
        !          1068: 
        !          1069:                     retry = TRUE;
        !          1070:                     logError = TRUE;
        !          1071:                     uniqueId = 256;
        !          1072:                     logStatus = IO_ERR_BAD_BLOCK;
        !          1073:                     switch (senseBuffer->CommandSpecificInformation[1]) {
        !          1074: 
        !          1075:                     case NEC_SCSI_ERROR_SEEK_ERROR:
        !          1076:                         CdDump(( 1, "CdAudioNECInterpretSenseInfo: Sector not found\n" ));
        !          1077:                         *Status = STATUS_NONEXISTENT_SECTOR;
        !          1078:                         retry = FALSE;
        !          1079:                         break;
        !          1080:                     case NEC_SCSI_ERROR_MUSIC_AREA:
        !          1081:                         CdDump((1,"CdAudioNECInterpretSenseInfo: Music area\n"));
        !          1082:                         break;
        !          1083: 
        !          1084:                     case NEC_SCSI_ERROR_DATA_AREA:
        !          1085:                         CdDump((1,"CdAudioNECInterpretSenseInfo: Data area\n"));
        !          1086:                         break;
        !          1087: 
        !          1088: 
        !          1089:                     } // end switch
        !          1090:                     break;
        !          1091: 
        !          1092:                 case SCSI_SENSE_HARDWARE_ERROR:
        !          1093: 
        !          1094:                     CdDump((1,"CdAudioNECInterpretSenseInfo: Hardware error\n"));
        !          1095:                     *Status = STATUS_IO_DEVICE_ERROR;
        !          1096: 
        !          1097:                     retry = TRUE;
        !          1098:                     logError = TRUE;
        !          1099:                     uniqueId = 257;
        !          1100:                     logStatus = IO_ERR_CONTROLLER_ERROR;
        !          1101:                     switch (senseBuffer->CommandSpecificInformation[1]) {
        !          1102: 
        !          1103:                     case NEC_SCSI_ERROR_PARITY_ERROR:
        !          1104:                         CdDump(( 1, "CdAudioNECInterpretSenseInfo: Parity error\n" ));
        !          1105:                         *Status = STATUS_PARITY_ERROR;
        !          1106:                         retry = FALSE;
        !          1107:                         break;
        !          1108: 
        !          1109:                     } // end switch
        !          1110: 
        !          1111:                     break;
        !          1112: 
        !          1113:                 case SCSI_SENSE_ILLEGAL_REQUEST:
        !          1114: 
        !          1115:                     CdDump((1,
        !          1116:                                 "CdAudioNECInterpretSenseInfo: Illegal SCSI request\n"));
        !          1117: 
        !          1118:                     *Status = STATUS_INVALID_DEVICE_REQUEST;
        !          1119: 
        !          1120:                     switch (senseBuffer->AdditionalSenseCode) {
        !          1121: 
        !          1122:                     case NEC_SCSI_ERROR_INVALID_COMMAND:
        !          1123:                         CdDump((1,
        !          1124:                                   "CdAudioNECInterpretSenseInfo: Illegal command\n"));
        !          1125:                         break;
        !          1126: 
        !          1127:                     case NEC_SCSI_ERROR_INVALID_ADDRESS:
        !          1128:                         CdDump((1,
        !          1129:                             "CdAudioNECInterpretSenseInfo: Illegal block address\n"));
        !          1130:                         *Status = STATUS_NONEXISTENT_SECTOR;
        !          1131:                         break;
        !          1132: 
        !          1133:                     case NEC_SCSI_ERROR_END_OF_VOLUME:
        !          1134:                         CdDump((1,
        !          1135:                                   "CdAudioNECInterpretSenseInfo: Volume overflow\n"));
        !          1136:                         *Status = STATUS_NONEXISTENT_SECTOR;
        !          1137:                         break;
        !          1138: 
        !          1139:                     case NEC_SCSI_ERROR_MEDIA_CHANGED:
        !          1140:                     case NEC_SCSI_ERROR_DEVICE_RESET:
        !          1141:                         CdDump((1,
        !          1142:                             "CdAudioNECInterpretSenseInfo: Media Changed or device reset\n"));
        !          1143: 
        !          1144:                         if (DeviceObject->Vpb->Flags & VPB_MOUNTED  &&
        !          1145:                             DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
        !          1146: 
        !          1147:                             //
        !          1148:                             // Set bit to indicate that media may have changed
        !          1149:                             // and volume needs verification.
        !          1150:                             //
        !          1151: 
        !          1152:                             DeviceObject->Flags |= DO_VERIFY_VOLUME;
        !          1153: 
        !          1154:                             *Status = STATUS_VERIFY_REQUIRED;
        !          1155: 
        !          1156:                             retry = FALSE;
        !          1157: 
        !          1158:                         } else {
        !          1159:                             *Status = STATUS_IO_DEVICE_ERROR;
        !          1160: 
        !          1161:                             retry = TRUE;
        !          1162: 
        !          1163:                         }
        !          1164:                         break;
        !          1165: 
        !          1166: 
        !          1167:                     } // end switch ...
        !          1168: 
        !          1169:                     retry = FALSE;
        !          1170: 
        !          1171:                     break;
        !          1172: 
        !          1173:                 case SCSI_SENSE_UNIT_ATTENTION:
        !          1174: 
        !          1175:                     CdDump((3,"CdAudioNECInterpretSenseInfo: Unit attention\n"));
        !          1176: 
        !          1177:                     if (DeviceObject->Vpb->Flags & VPB_MOUNTED  &&
        !          1178:                         DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
        !          1179: 
        !          1180:                         //
        !          1181:                         // Set bit to indicate that media may have changed
        !          1182:                         // and volume needs verification.
        !          1183:                         //
        !          1184: 
        !          1185:                         DeviceObject->Flags |= DO_VERIFY_VOLUME;
        !          1186: 
        !          1187:                         *Status = STATUS_VERIFY_REQUIRED;
        !          1188: 
        !          1189:                         retry = FALSE;
        !          1190: 
        !          1191:                     } else {
        !          1192:                         *Status = STATUS_IO_DEVICE_ERROR;
        !          1193: 
        !          1194:                         retry = TRUE;
        !          1195: 
        !          1196:                     }
        !          1197: 
        !          1198:                     break;
        !          1199: 
        !          1200:                 case SCSI_SENSE_ABORTED_COMMAND:
        !          1201: 
        !          1202:                     CdDump((1,"CdAudioNECInterpretSenseInfo: Command aborted\n"));
        !          1203: 
        !          1204:                     *Status = STATUS_IO_DEVICE_ERROR;
        !          1205: 
        !          1206:                     retry = TRUE;
        !          1207: 
        !          1208:                     break;
        !          1209: 
        !          1210:                 case SCSI_SENSE_RECOVERED_ERROR:
        !          1211:                     CdDump((1,"CdAudioNECInterpretSenseInfo: Recovered error\n"));
        !          1212:                     *Status = STATUS_SUCCESS;
        !          1213:                     retry = FALSE;
        !          1214:                     logError = TRUE;
        !          1215:                     uniqueId = 258;
        !          1216:                     logStatus = IO_ERR_CONTROLLER_ERROR;
        !          1217:                     break;
        !          1218: 
        !          1219:                 case SCSI_SENSE_NO_SENSE:
        !          1220:                     CdDump((1,
        !          1221:                     "CdAudioNECInterpretSenseInfo: No specific sense key\n"));
        !          1222:                     *Status = STATUS_IO_DEVICE_ERROR;
        !          1223:                     retry   = TRUE;
        !          1224:                     break;
        !          1225: 
        !          1226:                 case SCSI_SENSE_BLANK_CHECK:
        !          1227:                     CdDump((1,
        !          1228:                                 "CdAudioNECInterpretSenseInfo: Media blank check\n"));
        !          1229:                     *Status = STATUS_NO_DATA_DETECTED;
        !          1230:                     retry = FALSE;
        !          1231:                     break;
        !          1232: 
        !          1233:                 default:
        !          1234: 
        !          1235:                     CdDump((1,
        !          1236:                         "CdAudioNECInterpretSenseInfo: Unrecognized sense code\n"));
        !          1237:                     *Status = STATUS_IO_DEVICE_ERROR;
        !          1238:                     retry = TRUE;
        !          1239: 
        !          1240:         } // end switch
        !          1241: 
        !          1242:     } else {
        !          1243: 
        !          1244:         //
        !          1245:         // Request sense buffer not valid. No sense information
        !          1246:         // to pinpoint the error. Return general request fail.
        !          1247:         //
        !          1248: 
        !          1249:         CdDump((1,"CdAudioNECInterpretSenseInfo: Request sense info not valid\n"));
        !          1250:         retry = TRUE;
        !          1251: 
        !          1252:         switch (SRB_STATUS(Srb->SrbStatus)) {
        !          1253:         case SRB_STATUS_INVALID_LUN:
        !          1254:         case SRB_STATUS_INVALID_TARGET_ID:
        !          1255:         case SRB_STATUS_NO_DEVICE:
        !          1256:         case SRB_STATUS_NO_HBA:
        !          1257:             *Status = STATUS_NO_SUCH_DEVICE;
        !          1258:             retry = FALSE;
        !          1259:             break;
        !          1260: 
        !          1261:         case SRB_STATUS_COMMAND_TIMEOUT:
        !          1262:         case SRB_STATUS_TIMEOUT:
        !          1263:             *Status = STATUS_IO_TIMEOUT;
        !          1264:             break;
        !          1265: 
        !          1266:         case SRB_STATUS_SELECTION_TIMEOUT:
        !          1267:             *Status = STATUS_DEVICE_NOT_CONNECTED;
        !          1268:             break;
        !          1269: 
        !          1270:         case SRB_STATUS_DATA_OVERRUN:
        !          1271:             *Status = STATUS_DATA_OVERRUN;
        !          1272:             retry = FALSE;
        !          1273:             break;
        !          1274: 
        !          1275:         case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
        !          1276:             *Status = STATUS_IO_DEVICE_ERROR;
        !          1277: 
        !          1278:             //
        !          1279:             // If there was  phase sequence error then limit the number of
        !          1280:             // retries.
        !          1281:             //
        !          1282: 
        !          1283:             if (RetryCount > 1 ) {
        !          1284:                 retry = FALSE;
        !          1285:             }
        !          1286: 
        !          1287:             break;
        !          1288: 
        !          1289:         case SRB_STATUS_REQUEST_FLUSHED:
        !          1290: 
        !          1291:             //
        !          1292:             // If the status needs verification bit is set.  Then set
        !          1293:             // the status to need verificaiton and no retry; otherwise,
        !          1294:             // just retry the request.
        !          1295:             //
        !          1296: 
        !          1297:             if (DeviceObject->Flags & DO_VERIFY_VOLUME) {
        !          1298: 
        !          1299:                 *Status = STATUS_VERIFY_REQUIRED;
        !          1300:                 retry = FALSE;
        !          1301:             } else {
        !          1302:                 *Status = STATUS_IO_DEVICE_ERROR;
        !          1303:                 retry = TRUE;
        !          1304: 
        !          1305:             }
        !          1306: 
        !          1307:             break;
        !          1308: 
        !          1309:         default:
        !          1310:             *Status = STATUS_IO_DEVICE_ERROR;
        !          1311:             break;
        !          1312: 
        !          1313:         }
        !          1314: 
        !          1315:     }
        !          1316: 
        !          1317:     //
        !          1318:     // If there is a class specific error handler call it.
        !          1319:     //
        !          1320: 
        !          1321: //    if (deviceExtension->ClassError != NULL) {
        !          1322: //
        !          1323: //        deviceExtension->ClassError(
        !          1324: //            DeviceObject,
        !          1325: //            Srb
        !          1326: //            );
        !          1327: //    }
        !          1328: 
        !          1329:     if (logError) {
        !          1330: 
        !          1331:         errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
        !          1332:             DeviceObject,
        !          1333:             sizeof(IO_ERROR_LOG_PACKET) + 5 * sizeof(ULONG)
        !          1334:             );
        !          1335: 
        !          1336:         if (errorLogEntry == NULL) {
        !          1337: 
        !          1338:             return retry;
        !          1339: 
        !          1340:         }
        !          1341: 
        !          1342:         if (retry && RetryCount < MAXIMUM_RETRIES) {
        !          1343:             errorLogEntry->FinalStatus = STATUS_SUCCESS;
        !          1344:         } else {
        !          1345:             errorLogEntry->FinalStatus = *Status;
        !          1346:         }
        !          1347: 
        !          1348:         errorLogEntry->ErrorCode = logStatus;
        !          1349:         errorLogEntry->SequenceNumber = 0;
        !          1350:         errorLogEntry->MajorFunctionCode = MajorFunctionCode;
        !          1351:         errorLogEntry->IoControlCode = IoDeviceCode;
        !          1352:         errorLogEntry->RetryCount = RetryCount;
        !          1353:         errorLogEntry->DumpDataSize = 5 * sizeof(ULONG);
        !          1354:         errorLogEntry->UniqueErrorValue = uniqueId;
        !          1355:         errorLogEntry->DumpDataSize = 5 * sizeof(ULONG);
        !          1356:         errorLogEntry->DumpData[0] = Srb->PathId;
        !          1357:         errorLogEntry->DumpData[1] = Srb->TargetId;
        !          1358:         errorLogEntry->DumpData[2] = Srb->Lun;
        !          1359:         errorLogEntry->DumpData[3] = 0;
        !          1360:         errorLogEntry->DumpData[4] = Srb->SrbStatus << 8 | Srb->ScsiStatus;
        !          1361:         errorLogEntry->DumpData[5] = senseBuffer->SenseKey << 16 |
        !          1362:                                  senseBuffer->AdditionalSenseCode << 8 |
        !          1363:                                  senseBuffer->AdditionalSenseCodeQualifier;
        !          1364: 
        !          1365:         IoWriteErrorLogEntry(errorLogEntry);
        !          1366:     }
        !          1367: 
        !          1368:     return retry;
        !          1369: 
        !          1370: } // end InterpretSenseInfo()
        !          1371: 
        !          1372: NTSTATUS
        !          1373: CdAudioNECSendSrbSynchronous(
        !          1374:     PDEVICE_OBJECT DeviceObject,
        !          1375:     PSCSI_REQUEST_BLOCK Srb,
        !          1376:     PVOID BufferAddress,
        !          1377:     ULONG BufferLength,
        !          1378:     BOOLEAN WriteToDevice
        !          1379:     )
        !          1380: 
        !          1381: /*++
        !          1382: 
        !          1383: Routine Description:
        !          1384: 
        !          1385:     This routine is called by SCSI device controls to complete an
        !          1386:     SRB and send it to the port driver synchronously (ie wait for
        !          1387:     completion).
        !          1388:     The CDB is already completed along with the SRB CDB size and
        !          1389:     request timeout value.
        !          1390: 
        !          1391: Arguments:
        !          1392: 
        !          1393:     Device Object
        !          1394:     SRB
        !          1395:     Buffer address and length (if transfer)
        !          1396:     WriteToDevice
        !          1397: 
        !          1398: Return Value:
        !          1399: 
        !          1400:     NTSTATUS
        !          1401: 
        !          1402: --*/
        !          1403: 
        !          1404: {
        !          1405:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !          1406:     IO_STATUS_BLOCK ioStatus;
        !          1407:     PIRP irp;
        !          1408:     PIO_STACK_LOCATION irpStack;
        !          1409:     KEVENT event;
        !          1410:     PUCHAR senseInfoBuffer;
        !          1411:     LARGE_INTEGER largeInt = RtlConvertUlongToLargeInteger(0);
        !          1412:     ULONG retryCount = MAXIMUM_RETRIES;
        !          1413:     NTSTATUS status;
        !          1414:     BOOLEAN retry;
        !          1415: 
        !          1416:     //
        !          1417:     // Write length to SRB.
        !          1418:     //
        !          1419: 
        !          1420:     Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
        !          1421: 
        !          1422:     //
        !          1423:     // Set SCSI bus address.
        !          1424:     //
        !          1425: 
        !          1426:     Srb->PathId = deviceExtension->PathId;
        !          1427:     Srb->TargetId = deviceExtension->TargetId;
        !          1428:     Srb->Lun = deviceExtension->Lun;
        !          1429: 
        !          1430:     Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
        !          1431: 
        !          1432:     //
        !          1433:     // BUGBUG:  This is a violation of the SCSI spec but it is required for
        !          1434:     // some targets.
        !          1435:     //
        !          1436: 
        !          1437:     Srb->Cdb[1] |= deviceExtension->Lun << 5;
        !          1438: 
        !          1439:     //
        !          1440:     // Enable auto request sense.
        !          1441:     //
        !          1442: 
        !          1443:     Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
        !          1444: 
        !          1445:     //
        !          1446:     // Sense buffer is in non-paged pool.
        !          1447:     //
        !          1448: 
        !          1449:     senseInfoBuffer = ExAllocatePool( NonPagedPoolCacheAligned,
        !          1450:                                       SENSE_BUFFER_SIZE
        !          1451:                                      );
        !          1452: 
        !          1453:     if (senseInfoBuffer == NULL) {
        !          1454: 
        !          1455:         CdDump((1,
        !          1456:             "CdAudioNECSendSrbSynchronous: Can't allocate request sense buffer\n"));
        !          1457:         return(STATUS_INSUFFICIENT_RESOURCES);
        !          1458:     }
        !          1459: 
        !          1460:     Srb->SenseInfoBuffer = senseInfoBuffer;
        !          1461: 
        !          1462:     Srb->DataBuffer = BufferAddress;
        !          1463: 
        !          1464:     //
        !          1465:     // Start retries here.
        !          1466:     //
        !          1467: 
        !          1468: retry:
        !          1469: 
        !          1470:     if (BufferAddress != NULL) {
        !          1471: 
        !          1472:         //
        !          1473:         // Build the synchronous request with data transfer.
        !          1474:         //
        !          1475: 
        !          1476:         irp = IoBuildSynchronousFsdRequest(
        !          1477:                WriteToDevice ? IRP_MJ_WRITE : IRP_MJ_READ,
        !          1478:                deviceExtension->PortDeviceObject,
        !          1479:                BufferAddress,
        !          1480:                BufferLength,
        !          1481:                &largeInt,
        !          1482:                &event,
        !          1483:                &ioStatus);
        !          1484: 
        !          1485:         if (irp == NULL) {
        !          1486:             ExFreePool(senseInfoBuffer);
        !          1487:             CdDump((1, "CdAudioNECSendSrbSynchronous: Can't allocate Irp\n"));
        !          1488:             return(STATUS_INSUFFICIENT_RESOURCES);
        !          1489:         }
        !          1490: 
        !          1491:         //
        !          1492:         // Set read flag.
        !          1493:         //
        !          1494: 
        !          1495:         Srb->SrbFlags = WriteToDevice ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN;
        !          1496: 
        !          1497:     } else {
        !          1498: 
        !          1499:         //
        !          1500:         // Build synchronous request with no transfer.
        !          1501:         //
        !          1502: 
        !          1503:         irp = IoBuildDeviceIoControlRequest(
        !          1504:                     IRP_MJ_DEVICE_CONTROL,
        !          1505:                     deviceExtension->PortDeviceObject,
        !          1506:                     NULL,
        !          1507:                     0,
        !          1508:                     NULL,
        !          1509:                     0,
        !          1510:                     TRUE,
        !          1511:                     &event,
        !          1512:                     &ioStatus
        !          1513:                        );
        !          1514: 
        !          1515:         if (irp == NULL) {
        !          1516:             ExFreePool(senseInfoBuffer);
        !          1517:             CdDump((1, "ScsiClassSendSrbSynchronous: Can't allocate Irp\n"));
        !          1518:             return(STATUS_INSUFFICIENT_RESOURCES);
        !          1519:         }
        !          1520: 
        !          1521:         //
        !          1522:         // Clear flags.
        !          1523:         //
        !          1524: 
        !          1525:         Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
        !          1526:     }
        !          1527: 
        !          1528:     //
        !          1529:     // Disable synchronous transfer for these requests.
        !          1530:     //
        !          1531: 
        !          1532:     Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
        !          1533: 
        !          1534:     //
        !          1535:     // Set the event object to the unsignaled state.
        !          1536:     // It will be used to signal request completion.
        !          1537:     //
        !          1538: 
        !          1539:     KeInitializeEvent(&event, NotificationEvent, FALSE);
        !          1540: 
        !          1541:     //
        !          1542:     // Set the transfer length.
        !          1543:     //
        !          1544: 
        !          1545:     Srb->DataTransferLength = BufferLength;
        !          1546: 
        !          1547:     //
        !          1548:     // Zero out status.
        !          1549:     //
        !          1550: 
        !          1551:     Srb->ScsiStatus = Srb->SrbStatus = 0;
        !          1552: 
        !          1553:     Srb->NextSrb = 0;
        !          1554: 
        !          1555:     //
        !          1556:     // Get next stack location and
        !          1557:     // set major function code.
        !          1558:     //
        !          1559: 
        !          1560:     irpStack = IoGetNextIrpStackLocation(irp);
        !          1561: 
        !          1562:     irpStack->MajorFunction = IRP_MJ_SCSI;
        !          1563: 
        !          1564:     //
        !          1565:     // Set up SRB for execute scsi request.
        !          1566:     // Save SRB address in next stack for port driver.
        !          1567:     //
        !          1568: 
        !          1569:     irpStack->Parameters.Others.Argument1 = (PVOID)Srb;
        !          1570: 
        !          1571:     //
        !          1572:     // Set up IRP Address.
        !          1573:     //
        !          1574: 
        !          1575:     Srb->OriginalRequest = irp;
        !          1576: 
        !          1577:     //
        !          1578:     // No need to check the following 2 returned statuses as
        !          1579:     // SRB will have ending status.
        !          1580:     //
        !          1581: 
        !          1582:     status = IoCallDriver(deviceExtension->PortDeviceObject, irp);
        !          1583: 
        !          1584:     if (status == STATUS_PENDING) {
        !          1585:         KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
        !          1586:     }
        !          1587: 
        !          1588:     //
        !          1589:     // Check that request completed without error.
        !          1590:     //
        !          1591: 
        !          1592:     if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) {
        !          1593: 
        !          1594:         //
        !          1595:         // Release the queue if it is frozen.
        !          1596:         //
        !          1597: 
        !          1598:         if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
        !          1599:             ScsiClassReleaseQueue(DeviceObject);
        !          1600:         }
        !          1601: 
        !          1602:         //
        !          1603:         // Update status and determine if request should be retried.
        !          1604:         //
        !          1605: 
        !          1606:         retry = CdAudioNECInterpretSenseInfo(
        !          1607:             DeviceObject,
        !          1608:             Srb,
        !          1609:             IRP_MJ_SCSI,
        !          1610:             0,
        !          1611:             MAXIMUM_RETRIES  - retryCount,
        !          1612:             &status
        !          1613:             );
        !          1614: 
        !          1615:         if (retry) {
        !          1616: 
        !          1617:             if ((status == STATUS_DEVICE_NOT_READY && ((PSENSE_DATA) senseInfoBuffer)
        !          1618:                 ->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) ||
        !          1619:                 SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) {
        !          1620: 
        !          1621:                 LARGE_INTEGER delay;
        !          1622: 
        !          1623:                 //
        !          1624:                 // Delay for 2 seconds.
        !          1625:                 //
        !          1626: 
        !          1627:                 delay.LowPart = - ( 10 * 1000 * 1000 * 2 );
        !          1628:                 delay.HighPart = -1;
        !          1629: 
        !          1630: 
        !          1631:                 //
        !          1632:                 // Stall for a while to let the controller spinup.
        !          1633:                 //
        !          1634: 
        !          1635:                 (VOID) KeDelayExecutionThread(
        !          1636:                     KernelMode,
        !          1637:                     FALSE,
        !          1638:                     &delay
        !          1639:                     );
        !          1640: 
        !          1641:             }
        !          1642: 
        !          1643: 
        !          1644:             //
        !          1645:             // If retries are not exhausted then
        !          1646:             // retry this operation.
        !          1647:             //
        !          1648: 
        !          1649:             if (retryCount--) {
        !          1650:                 goto retry;
        !          1651:             }
        !          1652:         }
        !          1653: 
        !          1654:     } else {
        !          1655: 
        !          1656:         status = STATUS_SUCCESS;
        !          1657:     }
        !          1658: 
        !          1659:     ExFreePool(senseInfoBuffer);
        !          1660:     return status;
        !          1661: 
        !          1662: } // end CdAudioNECSendSrbSynchronous()
        !          1663: 
        !          1664: 
        !          1665: NTSTATUS
        !          1666: CdAudioNECDeviceControl(
        !          1667:     PDEVICE_OBJECT DeviceObject,
        !          1668:     PIRP Irp
        !          1669:     )
        !          1670: 
        !          1671: /*++
        !          1672: 
        !          1673: Routine Description:
        !          1674: 
        !          1675:     This routine is called by CdAudioDeviceControl to handle
        !          1676:     audio IOCTLs sent to NEC cdrom drives.
        !          1677: 
        !          1678: Arguments:
        !          1679: 
        !          1680:     DeviceObject
        !          1681:     Irp
        !          1682: 
        !          1683: Return Value:
        !          1684: 
        !          1685:     NTSTATUS
        !          1686: 
        !          1687: --*/
        !          1688: 
        !          1689: {
        !          1690:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          1691:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          1692:     PCDROM_TOC         cdaudioDataOut  = Irp->AssociatedIrp.SystemBuffer;
        !          1693:     SCSI_REQUEST_BLOCK srb;
        !          1694:     PNEC_CDB           cdb = (PNEC_CDB)srb.Cdb;
        !          1695:     NTSTATUS           status;
        !          1696:     ULONG              i,bytesTransfered;
        !          1697:     PUCHAR             Toc;
        !          1698:     ULONG              retryCount = 0;
        !          1699:     ULONG              address;
        !          1700:     LARGE_INTEGER delay;
        !          1701: 
        !          1702: 
        !          1703: NECRestart:
        !          1704: 
        !          1705:     //
        !          1706:     // Clear out cdb
        !          1707:     //
        !          1708: 
        !          1709:     RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          1710: 
        !          1711:     //
        !          1712:     // What IOCTL do we need to execute?
        !          1713:     //
        !          1714: 
        !          1715:     switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
        !          1716: 
        !          1717:     case IOCTL_CDROM_GET_LAST_SESSION:
        !          1718: 
        !          1719:         CdDump(( 2,
        !          1720:                      "CdAudioNECDeviceControl: IOCTL_CDROM_GET_LAST_SESSION received.\n"
        !          1721:                      ));
        !          1722: 
        !          1723:         if (currentIrpStack->Parameters.Read.Length <
        !          1724:             FIELD_OFFSET(CDROM_TOC, TrackData[1])) {
        !          1725:             status = STATUS_INFO_LENGTH_MISMATCH;
        !          1726:             break;
        !          1727:             
        !          1728:         }
        !          1729: 
        !          1730: 
        !          1731:         //
        !          1732:         // If the cd is playing music then reject this request.
        !          1733:         //
        !          1734: 
        !          1735:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          1736:             status = STATUS_DEVICE_BUSY;
        !          1737:             break;
        !          1738:         }
        !          1739: 
        !          1740:         //
        !          1741:         // Allocate storage to hold TOC from disc
        !          1742:         //
        !          1743: 
        !          1744:         Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !          1745:                                       NEC_CDROM_TOC_SIZE
        !          1746:                                      );
        !          1747: 
        !          1748:         if (Toc==NULL) {
        !          1749: 
        !          1750:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          1751:             goto SetStatusAndReturn;
        !          1752: 
        !          1753:         }
        !          1754: 
        !          1755:         //
        !          1756:         // Set up defaults
        !          1757:         //
        !          1758: 
        !          1759:         RtlZeroMemory( Toc, NEC_CDROM_TOC_SIZE );
        !          1760:         srb.CdbLength = 10;
        !          1761: 
        !          1762:         //
        !          1763:         // Fill in CDB
        !          1764:         //
        !          1765: 
        !          1766:         cdb->NEC_READ_TOC.OperationCode = NEC_READ_TOC_CODE;
        !          1767:         cdb->NEC_READ_TOC.Type          = NEC_TRANSFER_WHOLE_TOC;
        !          1768:         cdb->NEC_READ_TOC.TrackNumber   = NEC_TOC_TYPE_SESSION;        
        !          1769:         srb.TimeOutValue      = AUDIO_TIMEOUT;
        !          1770:         status = CdAudioNECSendSrbSynchronous(
        !          1771:                                      deviceExtension->DeviceObject,
        !          1772:                                      &srb,
        !          1773:                                      Toc,
        !          1774:                                      NEC_CDROM_TOC_SIZE,
        !          1775:                                      FALSE
        !          1776:                                     );
        !          1777: 
        !          1778:         if (!NT_SUCCESS(status) && (status!=STATUS_DATA_OVERRUN)) {
        !          1779: 
        !          1780:             CdDump(( 1,
        !          1781:                 "CdAudioNECDeviceControl: READ_TOC error (0x%08lX)\n",
        !          1782:                  status ));
        !          1783: 
        !          1784: 
        !          1785:             if (SRB_STATUS(srb.SrbStatus)!=SRB_STATUS_DATA_OVERRUN) {
        !          1786: 
        !          1787:                 CdDump(( 1, "CdAudioNECDeviceControl: SRB ERROR (0x%lX)\n",
        !          1788:                              srb.SrbStatus ));
        !          1789:                 ExFreePool( Toc );
        !          1790:                 goto SetStatusAndReturn;
        !          1791:             }
        !          1792: 
        !          1793:         } else {
        !          1794: 
        !          1795:             status = STATUS_SUCCESS;
        !          1796:         }
        !          1797: 
        !          1798:         //
        !          1799:         // Translate data into our format.
        !          1800:         //
        !          1801: 
        !          1802:         bytesTransfered = FIELD_OFFSET(CDROM_TOC, TrackData[1]);
        !          1803:         Irp->IoStatus.Information = bytesTransfered;
        !          1804: 
        !          1805:         RtlZeroMemory(cdaudioDataOut, bytesTransfered);
        !          1806:         
        !          1807:         cdaudioDataOut->Length[0]  = bytesTransfered >> 8;
        !          1808:         cdaudioDataOut->Length[1]  = (bytesTransfered & 0xFF);
        !          1809: 
        !          1810:         //
        !          1811:         // Determine if this is a multisession cd.
        !          1812:         //
        !          1813: 
        !          1814:         if (*((ULONG UNALIGNED *) &Toc[14]) == 0) {
        !          1815: 
        !          1816:             //
        !          1817:             // This is a single session disk.  Just return.
        !          1818:             //
        !          1819: 
        !          1820:             ExFreePool(Toc);
        !          1821:             break;
        !          1822:         }
        !          1823: 
        !          1824:         //
        !          1825:         // Fake the session information.
        !          1826:         //
        !          1827:         
        !          1828:         cdaudioDataOut->FirstTrack = 1;
        !          1829:         cdaudioDataOut->LastTrack  = 2;
        !          1830: 
        !          1831:         CdDump(( 4,
        !          1832:                      "CdAudioNECDeviceControl: Tracks %d - %d, (0x%lX bytes)\n",
        !          1833:                      cdaudioDataOut->FirstTrack,
        !          1834:                      cdaudioDataOut->LastTrack,
        !          1835:                      bytesTransfered
        !          1836:                      ));
        !          1837: 
        !          1838: 
        !          1839:         //
        !          1840:         // Grab Information for the last session.
        !          1841:         //
        !          1842: 
        !          1843:         cdaudioDataOut->TrackData[0].Reserved = 0;
        !          1844:         cdaudioDataOut->TrackData[0].Control =
        !          1845:             ((Toc[2] & 0x0F) << 4) | (Toc[2] >> 4);
        !          1846:         cdaudioDataOut->TrackData[0].TrackNumber = 1;
        !          1847: 
        !          1848:         cdaudioDataOut->TrackData[0].Reserved1 = 0;
        !          1849: 
        !          1850:         //
        !          1851:         // Convert the minutes, seconds and frames to an absolute block
        !          1852:         // address.  The formula comes from NEC.
        !          1853:         //
        !          1854: 
        !          1855:         address = (BCD_TO_DEC(Toc[15]) * 60 + BCD_TO_DEC(Toc[16])) * 75 + BCD_TO_DEC(Toc[17]);
        !          1856: 
        !          1857:         //
        !          1858:         // Put the address in big-endian in the the user's TOC.
        !          1859:         //
        !          1860: 
        !          1861:         cdaudioDataOut->TrackData[0].Address[0] = (UCHAR) (address >> 24);
        !          1862:         cdaudioDataOut->TrackData[0].Address[1] = (UCHAR) (address >> 16);
        !          1863:         cdaudioDataOut->TrackData[0].Address[2] = (UCHAR) (address >> 8);
        !          1864:         cdaudioDataOut->TrackData[0].Address[3] = (UCHAR) address;        
        !          1865: 
        !          1866:         //
        !          1867:         // Free storage now that we've stored it elsewhere
        !          1868:         //
        !          1869: 
        !          1870:         ExFreePool( Toc );
        !          1871:         break;
        !          1872: 
        !          1873:     case IOCTL_CDROM_READ_TOC:
        !          1874: 
        !          1875:         CdDump(( 2,
        !          1876:                      "CdAudioNECDeviceControl: IOCTL_CDROM_READ_TOC received.\n"
        !          1877:                      ));
        !          1878: 
        !          1879:         //
        !          1880:         // If the cd is playing music then reject this request.
        !          1881:         //
        !          1882: 
        !          1883:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          1884:             status = STATUS_DEVICE_BUSY;
        !          1885:             break;
        !          1886:         }
        !          1887: 
        !          1888:         //
        !          1889:         // Allocate storage to hold TOC from disc
        !          1890:         //
        !          1891: 
        !          1892:         Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !          1893:                                       NEC_CDROM_TOC_SIZE
        !          1894:                                      );
        !          1895: 
        !          1896:         if (Toc==NULL) {
        !          1897: 
        !          1898:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          1899:             goto SetStatusAndReturn;
        !          1900: 
        !          1901:         }
        !          1902: 
        !          1903:         CdDump(( 4,
        !          1904:                      "CdAudioNECDeviceControl: Toc = 0x%lX  cdaudioDataOut = 0x%lX\n",
        !          1905:                      Toc, cdaudioDataOut
        !          1906:                     ));
        !          1907: 
        !          1908:         //
        !          1909:         // Set up defaults
        !          1910:         //
        !          1911: 
        !          1912:         RtlZeroMemory( Toc, NEC_CDROM_TOC_SIZE );
        !          1913:         srb.CdbLength = 10;
        !          1914: 
        !          1915:         //
        !          1916:         // Fill in CDB
        !          1917:         //
        !          1918: 
        !          1919:         cdb->NEC_READ_TOC.OperationCode = NEC_READ_TOC_CODE;
        !          1920:         cdb->NEC_READ_TOC.Type          = NEC_TRANSFER_WHOLE_TOC;
        !          1921:         srb.TimeOutValue      = AUDIO_TIMEOUT;
        !          1922:         status = CdAudioNECSendSrbSynchronous(
        !          1923:                                      deviceExtension->DeviceObject,
        !          1924:                                      &srb,
        !          1925:                                      Toc,
        !          1926:                                      NEC_CDROM_TOC_SIZE,
        !          1927:                                      FALSE
        !          1928:                                     );
        !          1929: 
        !          1930:         if (!NT_SUCCESS(status) && (status!=STATUS_DATA_OVERRUN)) {
        !          1931: 
        !          1932:             CdDump(( 1,
        !          1933:                 "CdAudioNECDeviceControl: READ_TOC error (0x%08lX)\n",
        !          1934:                  status ));
        !          1935: 
        !          1936: 
        !          1937:             if (SRB_STATUS(srb.SrbStatus)!=SRB_STATUS_DATA_OVERRUN) {
        !          1938: 
        !          1939:                 CdDump(( 1, "CdAudioNECDeviceControl: SRB ERROR (0x%lX)\n",
        !          1940:                              srb.SrbStatus ));
        !          1941:                 ExFreePool( Toc );
        !          1942:                 goto SetStatusAndReturn;
        !          1943:             }
        !          1944: 
        !          1945:         } else {
        !          1946: 
        !          1947:             status = STATUS_SUCCESS;
        !          1948:         }
        !          1949: 
        !          1950:         //
        !          1951:         // Translate data into our format.
        !          1952:         //
        !          1953: 
        !          1954:         bytesTransfered =
        !          1955:             currentIrpStack->Parameters.Read.Length > sizeof(CDROM_TOC) ?
        !          1956:             sizeof(CDROM_TOC) : currentIrpStack->Parameters.Read.Length;
        !          1957:         Irp->IoStatus.Information = bytesTransfered;
        !          1958: 
        !          1959:         cdaudioDataOut->Length[0]  = bytesTransfered >> 8;
        !          1960:         cdaudioDataOut->Length[1]  = (bytesTransfered & 0xFF);
        !          1961:         cdaudioDataOut->FirstTrack = BCD_TO_DEC(Toc[9]);
        !          1962:         cdaudioDataOut->LastTrack  = BCD_TO_DEC(Toc[19]);
        !          1963: 
        !          1964:         CdDump(( 4,
        !          1965:                      "CdAudioNECDeviceControl: Tracks %d - %d, (0x%lX bytes)\n",
        !          1966:                      cdaudioDataOut->FirstTrack,
        !          1967:                      cdaudioDataOut->LastTrack,
        !          1968:                      bytesTransfered
        !          1969:                      ));
        !          1970: 
        !          1971: 
        !          1972:         for( i=0;
        !          1973:              i<=( (ULONG)cdaudioDataOut->LastTrack -
        !          1974:                   (ULONG)cdaudioDataOut->FirstTrack   );
        !          1975:              i++
        !          1976:             ) {
        !          1977: 
        !          1978:             //
        !          1979:             // Grab Information for each track
        !          1980:             //
        !          1981: 
        !          1982:             cdaudioDataOut->TrackData[i].Reserved = 0;
        !          1983:             cdaudioDataOut->TrackData[i].Control =
        !          1984:                 ((Toc[(i*10)+32] & 0x0F) << 4) | (Toc[(i*10)+32] >> 4);
        !          1985:             cdaudioDataOut->TrackData[i].TrackNumber =
        !          1986:                 (i + cdaudioDataOut->FirstTrack);
        !          1987: 
        !          1988:             cdaudioDataOut->TrackData[i].Reserved1 = 0;
        !          1989:             cdaudioDataOut->TrackData[i].Address[0] = 0;
        !          1990:             cdaudioDataOut->TrackData[i].Address[1] = BCD_TO_DEC((Toc[(i*10)+39]));
        !          1991:             cdaudioDataOut->TrackData[i].Address[2] = BCD_TO_DEC((Toc[(i*10)+40]));
        !          1992:             cdaudioDataOut->TrackData[i].Address[3] = BCD_TO_DEC((Toc[(i*10)+41]));
        !          1993: 
        !          1994:             CdDump(( 4,
        !          1995:                          "CdAudioNECDeviceControl: Track %d  %d:%d:%d\n",
        !          1996:                          cdaudioDataOut->TrackData[i].TrackNumber,
        !          1997:                          cdaudioDataOut->TrackData[i].Address[1],
        !          1998:                          cdaudioDataOut->TrackData[i].Address[2],
        !          1999:                          cdaudioDataOut->TrackData[i].Address[3]
        !          2000:                        ));
        !          2001: 
        !          2002: 
        !          2003: 
        !          2004:         }
        !          2005: 
        !          2006:         //
        !          2007:         // Fake "lead out track" info
        !          2008:         //
        !          2009: 
        !          2010:         cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          2011:         cdaudioDataOut->TrackData[i].Control     = 0x10;
        !          2012:         cdaudioDataOut->TrackData[i].TrackNumber = 0xaa;
        !          2013:         cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          2014:         cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          2015:         cdaudioDataOut->TrackData[i].Address[1]  = BCD_TO_DEC(Toc[29]);
        !          2016:         cdaudioDataOut->TrackData[i].Address[2]  = BCD_TO_DEC(Toc[30]);
        !          2017:         cdaudioDataOut->TrackData[i].Address[3]  = BCD_TO_DEC(Toc[31]);
        !          2018: 
        !          2019:         CdDump(( 4,
        !          2020:                      "CdAudioNECDeviceControl: Track %d  %d:%d:%d\n",
        !          2021:                      cdaudioDataOut->TrackData[i].TrackNumber,
        !          2022:                      cdaudioDataOut->TrackData[i].Address[1],
        !          2023:                      cdaudioDataOut->TrackData[i].Address[2],
        !          2024:                      cdaudioDataOut->TrackData[i].Address[3]
        !          2025:                    ));
        !          2026: 
        !          2027:         //
        !          2028:         // Free storage now that we've stored it elsewhere
        !          2029:         //
        !          2030: 
        !          2031:         ExFreePool( Toc );
        !          2032:         break;
        !          2033: 
        !          2034:     case IOCTL_CDROM_STOP_AUDIO:
        !          2035: 
        !          2036:         deviceExtension->PlayActive = FALSE;
        !          2037: 
        !          2038:         //
        !          2039:         // Same as scsi-2 spec, so just send to default driver
        !          2040:         //
        !          2041: 
        !          2042:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          2043:         break;
        !          2044: 
        !          2045:     case IOCTL_CDROM_PLAY_AUDIO_MSF:
        !          2046:         {
        !          2047: 
        !          2048:         PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          2049: 
        !          2050:         CdDump(( 3,
        !          2051:             "CdAudioNECDeviceControl: IOCTL_CDROM_PLAY_AUDIO_MSF received.\n"
        !          2052:             ));
        !          2053: 
        !          2054:         //
        !          2055:         // First, seek to Starting MSF and enter play mode.
        !          2056:         //
        !          2057: 
        !          2058:         srb.CdbLength                 = 10;
        !          2059:         srb.TimeOutValue              = AUDIO_TIMEOUT;
        !          2060:         cdb->NEC_PLAY_AUDIO.OperationCode = NEC_AUDIO_TRACK_SEARCH_CODE;
        !          2061:         cdb->NEC_PLAY_AUDIO.PlayMode      = NEC_ENTER_PLAY_MODE;
        !          2062:         cdb->NEC_PLAY_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->StartingM);
        !          2063:         cdb->NEC_PLAY_AUDIO.Second        = DEC_TO_BCD(inputBuffer->StartingS);
        !          2064:         cdb->NEC_PLAY_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->StartingF);
        !          2065:         cdb->NEC_PLAY_AUDIO.Control       = NEC_TYPE_ATIME;
        !          2066: 
        !          2067:         CdDump(( 3,
        !          2068:                      "CdAudioNECDeviceControl: play start MSF is BCD(%x:%x:%x)\n",
        !          2069:                      cdb->NEC_PLAY_AUDIO.Minute,
        !          2070:                      cdb->NEC_PLAY_AUDIO.Second,
        !          2071:                      cdb->NEC_PLAY_AUDIO.Frame
        !          2072:                    ));
        !          2073: 
        !          2074: 
        !          2075:         status = CdAudioNECSendSrbSynchronous(deviceExtension->DeviceObject,
        !          2076:                                               &srb,
        !          2077:                                               NULL,
        !          2078:                                               0,
        !          2079:                                               FALSE
        !          2080:                                              );
        !          2081:         if (NT_SUCCESS(status)) {
        !          2082: 
        !          2083:             //
        !          2084:             // Indicate the play actition is active.
        !          2085:             //
        !          2086: 
        !          2087:             deviceExtension->PlayActive = TRUE;
        !          2088: 
        !          2089:             //
        !          2090:             // Now, set the termination point for the play operation
        !          2091:             //
        !          2092: 
        !          2093:             RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          2094:             cdb->NEC_PLAY_AUDIO.OperationCode = NEC_PLAY_AUDIO_CODE;
        !          2095:             cdb->NEC_PLAY_AUDIO.PlayMode      = NEC_PLAY_STEREO;
        !          2096:             cdb->NEC_PLAY_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->EndingM);
        !          2097:             cdb->NEC_PLAY_AUDIO.Second        = DEC_TO_BCD(inputBuffer->EndingS);
        !          2098:             cdb->NEC_PLAY_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->EndingF);
        !          2099:             cdb->NEC_PLAY_AUDIO.Control       = NEC_TYPE_ATIME;
        !          2100: 
        !          2101:             CdDump(( 3,
        !          2102:                          "CdAudioNECDeviceControl: play end MSF is BCD(%x:%x:%x)\n",
        !          2103:                          cdb->NEC_PLAY_AUDIO.Minute,
        !          2104:                          cdb->NEC_PLAY_AUDIO.Second,
        !          2105:                          cdb->NEC_PLAY_AUDIO.Frame
        !          2106:                        ));
        !          2107: 
        !          2108:             status = CdAudioNECSendSrbSynchronous(
        !          2109:                                          deviceExtension->DeviceObject,
        !          2110:                                          &srb,
        !          2111:                                          NULL,
        !          2112:                                          0,
        !          2113:                                          FALSE
        !          2114:                                         );
        !          2115: 
        !          2116: 
        !          2117:         }
        !          2118:         }
        !          2119:         break;
        !          2120: 
        !          2121:     case IOCTL_CDROM_SEEK_AUDIO_MSF:
        !          2122:         {
        !          2123: 
        !          2124:         PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          2125: 
        !          2126:         CdDump(( 3,
        !          2127:             "CdAudioNECDeviceControl: IOCTL_CDROM_SEEK_AUDIO_MSF received.\n"
        !          2128:              ));
        !          2129: 
        !          2130:         //
        !          2131:         // seek to MSF and enter pause (still) mode.
        !          2132:         //
        !          2133: 
        !          2134:         srb.CdbLength                 = 10;
        !          2135:         srb.TimeOutValue              = AUDIO_TIMEOUT;
        !          2136:         cdb->NEC_SEEK_AUDIO.OperationCode = NEC_AUDIO_TRACK_SEARCH_CODE;
        !          2137:         cdb->NEC_SEEK_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->M);
        !          2138:         cdb->NEC_SEEK_AUDIO.Second        = DEC_TO_BCD(inputBuffer->S);
        !          2139:         cdb->NEC_SEEK_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->F);
        !          2140:         cdb->NEC_SEEK_AUDIO.Control       = NEC_TYPE_ATIME;
        !          2141:         CdDump(( 4,
        !          2142:                      "CdAudioNECDeviceControl: seek MSF is %d:%d:%d\n",
        !          2143:                      cdb->NEC_SEEK_AUDIO.Minute,
        !          2144:                      cdb->NEC_SEEK_AUDIO.Second,
        !          2145:                      cdb->NEC_SEEK_AUDIO.Frame
        !          2146:                    ));
        !          2147: 
        !          2148:         status = CdAudioNECSendSrbSynchronous(
        !          2149:                                      deviceExtension->DeviceObject,
        !          2150:                                      &srb,
        !          2151:                                      NULL,
        !          2152:                                      0,
        !          2153:                                      FALSE
        !          2154:                                     );
        !          2155: 
        !          2156:         }
        !          2157:         break;
        !          2158: 
        !          2159:     case IOCTL_CDROM_PAUSE_AUDIO:
        !          2160: 
        !          2161:         CdDump(( 3,
        !          2162:             "CdAudioNECDeviceControl: IOCTL_CDROM_PAUSE_AUDIO received.\n"
        !          2163:             ));
        !          2164: 
        !          2165:         deviceExtension->PlayActive = FALSE;
        !          2166: 
        !          2167:         //
        !          2168:         // Enter pause (still ) mode
        !          2169:         //
        !          2170: 
        !          2171:         srb.CdbLength                  = 10;
        !          2172:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          2173:         cdb->NEC_PAUSE_AUDIO.OperationCode = NEC_STILL_CODE;
        !          2174:         status = CdAudioNECSendSrbSynchronous(
        !          2175:                                      deviceExtension->DeviceObject,
        !          2176:                                      &srb,
        !          2177:                                      NULL,
        !          2178:                                      0,
        !          2179:                                      FALSE
        !          2180:                                     );
        !          2181: 
        !          2182:         break;
        !          2183: 
        !          2184:     case IOCTL_CDROM_RESUME_AUDIO:
        !          2185: 
        !          2186:         CdDump(( 3,
        !          2187:             "CdAudioNECDeviceControl: IOCTL_CDROM_RESUME_AUDIO received.\n"
        !          2188:             ));
        !          2189: 
        !          2190:         //
        !          2191:         // Resume play
        !          2192:         //
        !          2193: 
        !          2194:         srb.CdbLength                 = 10;
        !          2195:         srb.TimeOutValue              = AUDIO_TIMEOUT;
        !          2196:         cdb->NEC_PLAY_AUDIO.OperationCode = NEC_PLAY_AUDIO_CODE;
        !          2197:         cdb->NEC_PLAY_AUDIO.PlayMode      = NEC_PLAY_STEREO;
        !          2198:         cdb->NEC_PLAY_AUDIO.Control       = NEC_TYPE_NO_CHANGE;
        !          2199:         status = CdAudioNECSendSrbSynchronous(
        !          2200:                                      deviceExtension->DeviceObject,
        !          2201:                                      &srb,
        !          2202:                                      NULL,
        !          2203:                                      0,
        !          2204:                                      FALSE
        !          2205:                                     );
        !          2206:         break;
        !          2207: 
        !          2208:     case IOCTL_CDROM_READ_Q_CHANNEL:
        !          2209:         {
        !          2210: 
        !          2211:         PSUB_Q_CURRENT_POSITION userPtr =
        !          2212:             Irp->AssociatedIrp.SystemBuffer;
        !          2213:         PUCHAR SubQPtr =
        !          2214:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          2215:                             NEC_Q_CHANNEL_TRANSFER_SIZE
        !          2216:                            );
        !          2217: 
        !          2218:         CdDump(( 5,
        !          2219:             "CdAudioNECDeviceControl: IOCTL_CDROM_READ_Q_CHANNEL received.\n"
        !          2220:             ));
        !          2221: 
        !          2222:         if (SubQPtr==NULL) {
        !          2223: 
        !          2224:             CdDump(( 1,
        !          2225:                 "CdAudioNECDeviceControl: READ_Q_CHANNEL, SubQPtr==NULL!\n"
        !          2226:                 ));
        !          2227: 
        !          2228:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          2229:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          2230:             goto SetStatusAndReturn;
        !          2231: 
        !          2232:         }
        !          2233: 
        !          2234:         RtlZeroMemory( SubQPtr, NEC_Q_CHANNEL_TRANSFER_SIZE );
        !          2235: 
        !          2236:         if ( ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format!=
        !          2237:              IOCTL_CDROM_CURRENT_POSITION) {
        !          2238: 
        !          2239:             CdDump(( 1,
        !          2240:                 "CdAudioNECDeviceControl: READ_Q_CHANNEL, illegal Format (%d)\n",
        !          2241:                 ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format
        !          2242:                 ));
        !          2243: 
        !          2244:             ExFreePool( SubQPtr );
        !          2245:             status = STATUS_UNSUCCESSFUL;
        !          2246:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          2247:             goto SetStatusAndReturn;
        !          2248:         }
        !          2249: 
        !          2250: NECSeek:
        !          2251: 
        !          2252:         //
        !          2253:         // Set up to read Q Channel
        !          2254:         //
        !          2255: 
        !          2256:         srb.CdbLength                     = 10;
        !          2257:         srb.TimeOutValue                  = AUDIO_TIMEOUT;
        !          2258:         cdb->NEC_READ_Q_CHANNEL.OperationCode = NEC_READ_SUB_Q_CHANNEL_CODE;
        !          2259:         cdb->NEC_READ_Q_CHANNEL.TransferSize  = NEC_Q_CHANNEL_TRANSFER_SIZE;  // Transfer Length
        !          2260:         CdDump(( 4, "CdAudioNECDeviceControl: cdb = 0x%lx  srb = 0x%x  SubQPtr = 0x%lx\n",
        !          2261:                        cdb,
        !          2262:                        &srb,
        !          2263:                        SubQPtr
        !          2264:                       ));
        !          2265: #if DBG
        !          2266:         if (CdAudioDebug>5) {
        !          2267: 
        !          2268:             DbgBreakPoint();
        !          2269: 
        !          2270:         }
        !          2271: #endif
        !          2272:         status = CdAudioNECSendSrbSynchronous(
        !          2273:                                      deviceExtension->DeviceObject,
        !          2274:                                      &srb,
        !          2275:                                      SubQPtr,
        !          2276:                                      NEC_Q_CHANNEL_TRANSFER_SIZE,
        !          2277:                                      FALSE
        !          2278:                                     );
        !          2279:         CdDump(( 4, "CdAudioNECDeviceControl: READ_Q_CHANNEL, status is 0x%lX\n",
        !          2280:                        status
        !          2281:                      ));
        !          2282: 
        !          2283:         if ((NT_SUCCESS(status)) || (status==STATUS_DATA_OVERRUN)) {
        !          2284: 
        !          2285:             userPtr->Header.Reserved = 0;
        !          2286:             if (SubQPtr[0]==0x00)
        !          2287:                 userPtr->Header.AudioStatus = AUDIO_STATUS_IN_PROGRESS;
        !          2288:             else if (SubQPtr[0]==0x01) {
        !          2289: 
        !          2290:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PAUSED;
        !          2291:                 deviceExtension->PlayActive = FALSE;
        !          2292:             } else if (SubQPtr[0]==0x02) {
        !          2293:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PAUSED;
        !          2294:                 deviceExtension->PlayActive = FALSE;
        !          2295:             } else if (SubQPtr[0]==0x03) {
        !          2296: 
        !          2297:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PLAY_COMPLETE;
        !          2298:                 deviceExtension->PlayActive = FALSE;
        !          2299: 
        !          2300:             } else {
        !          2301:                 deviceExtension->PlayActive = FALSE;
        !          2302: 
        !          2303:             }
        !          2304: 
        !          2305:             userPtr->Header.DataLength[0] = 0;
        !          2306:             userPtr->Header.DataLength[0] = 12;
        !          2307: 
        !          2308:             userPtr->FormatCode = 0x01;
        !          2309:             userPtr->Control = SubQPtr[1] & 0x0F;
        !          2310:             userPtr->ADR     = 0;
        !          2311:             userPtr->TrackNumber = BCD_TO_DEC(SubQPtr[2]);
        !          2312:             userPtr->IndexNumber = BCD_TO_DEC(SubQPtr[3]);
        !          2313:             userPtr->AbsoluteAddress[0] = 0;
        !          2314:             userPtr->AbsoluteAddress[1] = BCD_TO_DEC((SubQPtr[7]));
        !          2315:             userPtr->AbsoluteAddress[2] = BCD_TO_DEC((SubQPtr[8]));
        !          2316:             userPtr->AbsoluteAddress[3] = BCD_TO_DEC((SubQPtr[9]));
        !          2317:             userPtr->TrackRelativeAddress[0] = 0;
        !          2318:             userPtr->TrackRelativeAddress[1] = BCD_TO_DEC((SubQPtr[4]));
        !          2319:             userPtr->TrackRelativeAddress[2] = BCD_TO_DEC((SubQPtr[5]));
        !          2320:             userPtr->TrackRelativeAddress[3] = BCD_TO_DEC((SubQPtr[6]));
        !          2321:             Irp->IoStatus.Information = 16;
        !          2322:             CdDump(( 5,
        !          2323:                            "CdAudioNECDeviceControl: <SubQPtr> Status = 0x%lx, [%x %x:%x]  (%x:%x:%x)\n",
        !          2324:                            SubQPtr[0],
        !          2325:                            SubQPtr[2],
        !          2326:                            SubQPtr[4],
        !          2327:                            SubQPtr[5],
        !          2328:                            SubQPtr[7],
        !          2329:                            SubQPtr[8],
        !          2330:                            SubQPtr[9]
        !          2331:                           ));
        !          2332:             CdDump(( 5,
        !          2333:                            "CdAudioNECDeviceControl: <userPtr> Status = 0x%lx, [%d %d:%d]  (%d:%d:%d)\n",
        !          2334:                            userPtr->Header.AudioStatus,
        !          2335:                            userPtr->TrackNumber,
        !          2336:                            userPtr->TrackRelativeAddress[1],
        !          2337:                            userPtr->TrackRelativeAddress[2],
        !          2338:                            userPtr->AbsoluteAddress[1],
        !          2339:                            userPtr->AbsoluteAddress[2],
        !          2340:                            userPtr->AbsoluteAddress[3]
        !          2341:                           ));
        !          2342: 
        !          2343:             //
        !          2344:             // Sometimes the NEC will return a bogus value for track number.
        !          2345:             // if this occurs just retry.
        !          2346:             //
        !          2347: 
        !          2348:             if (userPtr->TrackNumber > MAXIMUM_NUMBER_TRACKS) {
        !          2349: 
        !          2350:                 //
        !          2351:                 // Delay for .5 seconds.
        !          2352:                 //
        !          2353: 
        !          2354:                 delay = LiFromLong( - 10 * 1000 * 100 * 5 );
        !          2355: 
        !          2356:                 //
        !          2357:                 // Stall for a while to let the controller spinup.
        !          2358:                 //
        !          2359: 
        !          2360:                 KeDelayExecutionThread(KernelMode,
        !          2361:                                        FALSE,
        !          2362:                                        &delay);
        !          2363: 
        !          2364:                 if (retryCount++ < MAXIMUM_RETRIES) {
        !          2365:                     goto NECSeek;
        !          2366:                 } else {
        !          2367:                     status = STATUS_DEVICE_PROTOCOL_ERROR;
        !          2368:                 }
        !          2369: 
        !          2370:             } else {
        !          2371:                 status = STATUS_SUCCESS;
        !          2372:             }
        !          2373: 
        !          2374:         } else {
        !          2375: 
        !          2376:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          2377:             CdDump(( 1,
        !          2378:                 "CdAudioNECDeviceControl: READ_Q_CHANNEL failed (0x%08lX)\n",
        !          2379:                 status
        !          2380:                 ));
        !          2381: 
        !          2382:         }
        !          2383: 
        !          2384:         ExFreePool( SubQPtr );
        !          2385: 
        !          2386:         }
        !          2387:         break;
        !          2388: 
        !          2389:     case IOCTL_CDROM_EJECT_MEDIA:
        !          2390: 
        !          2391:         CdDump(( 3,
        !          2392:             "CdAudioNECDeviceControl: IOCTL_CDROM_EJECT_MEDIA received.\n"
        !          2393:             ));
        !          2394: 
        !          2395:         deviceExtension->PlayActive = FALSE;
        !          2396: 
        !          2397:         //
        !          2398:         // Set up to read Q Channel
        !          2399:         //
        !          2400: 
        !          2401:         srb.CdbLength            = 10;
        !          2402:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          2403:         cdb->NEC_EJECT.OperationCode = NEC_EJECT_CODE;
        !          2404:         status = CdAudioNECSendSrbSynchronous(
        !          2405:                                      deviceExtension->DeviceObject,
        !          2406:                                      &srb,
        !          2407:                                      NULL,
        !          2408:                                      0,
        !          2409:                                      FALSE
        !          2410:                                     );
        !          2411: 
        !          2412:         CdDump(( 3,
        !          2413:                      "CdAudioNECDeviceControl: invalidating cached TOC!\n"
        !          2414:                      ));
        !          2415:         break;
        !          2416: 
        !          2417:     case IOCTL_CDROM_GET_CONTROL:
        !          2418:     case IOCTL_CDROM_GET_VOLUME:
        !          2419:     case IOCTL_CDROM_SET_VOLUME:
        !          2420: 
        !          2421:         CdDump(( 3, "CdAudioNECDeviceControl: Not Supported yet.\n" ));
        !          2422:         status = STATUS_INVALID_DEVICE_REQUEST;
        !          2423:         break;
        !          2424: 
        !          2425:     case IOCTL_CDROM_CHECK_VERIFY:
        !          2426: 
        !          2427:         //
        !          2428:         // Update the play active flag.
        !          2429:         //
        !          2430: 
        !          2431:         CdAudioIsPlayActive(DeviceObject);
        !          2432: 
        !          2433:         //
        !          2434:         // Fall through and pass the request to the next driver.
        !          2435:         //
        !          2436: 
        !          2437:     default:
        !          2438: 
        !          2439:         CdDump(( 5,
        !          2440:                        "CdAudioNECDeviceControl: Unsupported device IOCTL (0x%lX)\n",
        !          2441:                        currentIrpStack->Parameters.DeviceIoControl.IoControlCode
        !          2442:                        ));
        !          2443:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          2444:         break;
        !          2445: 
        !          2446:     } // end switch( IOCTL )
        !          2447: 
        !          2448: SetStatusAndReturn:
        !          2449: 
        !          2450:     //
        !          2451:     // set status code and return
        !          2452:     //
        !          2453: 
        !          2454:     if (status == STATUS_VERIFY_REQUIRED) {
        !          2455: 
        !          2456: 
        !          2457:         //
        !          2458:         // If the status is verified required and the this request
        !          2459:         // should bypass verify required then retry the request.
        !          2460:         //
        !          2461: 
        !          2462:         if (currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) {
        !          2463: 
        !          2464:             status = STATUS_IO_DEVICE_ERROR;
        !          2465:             goto NECRestart;
        !          2466: 
        !          2467:         }
        !          2468: 
        !          2469:         IoSetHardErrorOrVerifyDevice( Irp,
        !          2470:                                       deviceExtension->TargetDeviceObject
        !          2471:                                      );
        !          2472: 
        !          2473:         Irp->IoStatus.Information = 0;
        !          2474:     }
        !          2475: 
        !          2476:     Irp->IoStatus.Status = status;
        !          2477:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          2478:     return status;
        !          2479: 
        !          2480: }
        !          2481: 
        !          2482: 
        !          2483: NTSTATUS
        !          2484: CdAudioPioneerDeviceControl(
        !          2485:     PDEVICE_OBJECT DeviceObject,
        !          2486:     PIRP Irp
        !          2487:     )
        !          2488: 
        !          2489: /*++
        !          2490: 
        !          2491: Routine Description:
        !          2492: 
        !          2493:     This routine is called by CdAudioDeviceControl to handle
        !          2494:     audio IOCTLs sent to PIONEER DRM-6xx cdrom drives.
        !          2495: 
        !          2496: Arguments:
        !          2497: 
        !          2498:     DeviceObject
        !          2499:     Irp
        !          2500: 
        !          2501: Return Value:
        !          2502: 
        !          2503:     NTSTATUS
        !          2504: 
        !          2505: --*/
        !          2506: 
        !          2507: {
        !          2508:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          2509:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          2510:     PCDROM_TOC         cdaudioDataOut  = Irp->AssociatedIrp.SystemBuffer;
        !          2511:     SCSI_REQUEST_BLOCK srb;
        !          2512:     PPNR_CDB           cdb = (PPNR_CDB)srb.Cdb;
        !          2513:     NTSTATUS           status;
        !          2514:     ULONG              i,bytesTransfered,retry;
        !          2515:     PUCHAR             Toc;
        !          2516: 
        !          2517: PioneerRestart:
        !          2518: 
        !          2519:     //
        !          2520:     // Clear out cdb
        !          2521:     //
        !          2522: 
        !          2523:     RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          2524: 
        !          2525:     //
        !          2526:     // What IOCTL do we need to execute?
        !          2527:     //
        !          2528: 
        !          2529:     switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
        !          2530: 
        !          2531:     case IOCTL_CDROM_READ_TOC:
        !          2532:         CdDump(( 3,
        !          2533:                      "CdAudioPioneerDeviceControl: IOCTL_CDROM_READ_TOC received.\n"
        !          2534:                      ));
        !          2535: 
        !          2536:         //
        !          2537:         // If the cd is playing music then reject this request.
        !          2538:         //
        !          2539: 
        !          2540:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          2541:             status = STATUS_DEVICE_BUSY;
        !          2542:             break;
        !          2543:         }
        !          2544: 
        !          2545:         //
        !          2546:         // Allocate storage to hold TOC from disc
        !          2547:         //
        !          2548: 
        !          2549:         Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !          2550:                                       CDROM_TOC_SIZE
        !          2551:                                      );
        !          2552: 
        !          2553:         if (Toc==NULL) {
        !          2554: 
        !          2555:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          2556:             goto SetStatusAndReturn;
        !          2557: 
        !          2558:         }
        !          2559: 
        !          2560:         //
        !          2561:         // Set up defaults
        !          2562:         //
        !          2563: 
        !          2564:         RtlZeroMemory( Toc, CDROM_TOC_SIZE );
        !          2565: 
        !          2566:         //
        !          2567:         // mount this disc (via START/STOP unit), which is
        !          2568:         // necessary since we don't know which is the
        !          2569:         // currently loaded disc.
        !          2570:         //
        !          2571: 
        !          2572:         cdb->PNR_START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
        !          2573:         cdb->PNR_START_STOP.Start         = 1;
        !          2574:         srb.CdbLength = 6;
        !          2575:         srb.TimeOutValue = AUDIO_TIMEOUT;
        !          2576:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2577:                                      &srb,
        !          2578:                                      NULL,
        !          2579:                                      0,
        !          2580:                                      FALSE
        !          2581:                                     );
        !          2582: 
        !          2583:         if (!NT_SUCCESS(status)) {
        !          2584: 
        !          2585:             CdDump(( 1,
        !          2586:                 "CdAudioPioneerDeviceControl: Start Unit failed (0x%lx)\n",
        !          2587:                 status ));
        !          2588:             ExFreePool( Toc );
        !          2589:             goto SetStatusAndReturn;
        !          2590: 
        !          2591:         }
        !          2592: 
        !          2593:         //
        !          2594:         // Get first and last tracks
        !          2595:         //
        !          2596: 
        !          2597:         RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          2598:         srb.CdbLength = 10;
        !          2599:         cdb->PNR_READ_TOC.OperationCode     = PIONEER_READ_TOC_CODE;
        !          2600:         cdb->PNR_READ_TOC.AssignedLength[1] = PIONEER_TRANSFER_SIZE;
        !          2601:         cdb->PNR_READ_TOC.Type              = PIONEER_READ_FIRST_AND_LAST;
        !          2602:         srb.TimeOutValue                    = AUDIO_TIMEOUT;
        !          2603:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2604:                                      &srb,
        !          2605:                                      Toc,
        !          2606:                                      PIONEER_TRANSFER_SIZE,
        !          2607:                                      FALSE
        !          2608:                                     );
        !          2609: 
        !          2610:         if (!NT_SUCCESS(status)) {
        !          2611: 
        !          2612:             CdDump(( 1,
        !          2613:                 "CdAudioPioneerDeviceControl: ReadTOC, First/Last Tracks failed (0x%lx)\n",
        !          2614:                 status ));
        !          2615:             ExFreePool( Toc );
        !          2616:             goto SetStatusAndReturn;
        !          2617: 
        !          2618:         }
        !          2619: 
        !          2620:         cdaudioDataOut->FirstTrack = BCD_TO_DEC(Toc[0]);
        !          2621:         cdaudioDataOut->LastTrack  = BCD_TO_DEC(Toc[1]);
        !          2622: 
        !          2623:         //
        !          2624:         // Now, get info about each track
        !          2625:         //
        !          2626: 
        !          2627:         for( i=0;
        !          2628:              i<=( (ULONG)cdaudioDataOut->LastTrack -
        !          2629:                   (ULONG)cdaudioDataOut->FirstTrack   );
        !          2630:              i++
        !          2631:             ) {
        !          2632: 
        !          2633:             //
        !          2634:             // Get TOC info for this track
        !          2635:             //
        !          2636: 
        !          2637:             RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          2638:             cdb->PNR_READ_TOC.OperationCode     = PIONEER_READ_TOC_CODE;
        !          2639:             cdb->PNR_READ_TOC.TrackNumber       = DEC_TO_BCD((i+cdaudioDataOut->FirstTrack)); // track
        !          2640:             cdb->PNR_READ_TOC.AssignedLength[1] = PIONEER_TRANSFER_SIZE;
        !          2641:             cdb->PNR_READ_TOC.Type              = PIONEER_READ_TRACK_INFO;
        !          2642:             srb.TimeOutValue                    = AUDIO_TIMEOUT;
        !          2643:             status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2644:                                          &srb,
        !          2645:                                          Toc,
        !          2646:                                          PIONEER_TRANSFER_SIZE,
        !          2647:                                          FALSE
        !          2648:                                         );
        !          2649: 
        !          2650:             if (!NT_SUCCESS(status)) {
        !          2651: 
        !          2652:                 CdDump(( 1,
        !          2653:                     "CdAudioPioneerDeviceControl: ReadTOC, Track #%d, failed (0x%lx)\n",
        !          2654:                     i+cdaudioDataOut->FirstTrack,
        !          2655:                     status ));
        !          2656:                 ExFreePool( Toc );
        !          2657:                 goto SetStatusAndReturn;
        !          2658: 
        !          2659:             }
        !          2660: 
        !          2661:             cdaudioDataOut->TrackData[i].Reserved = 0;
        !          2662:             cdaudioDataOut->TrackData[i].Control  = Toc[0];
        !          2663:             cdaudioDataOut->TrackData[i].TrackNumber =
        !          2664:                 (i + cdaudioDataOut->FirstTrack);
        !          2665:             cdaudioDataOut->TrackData[i].Reserved1 = 0;
        !          2666:             cdaudioDataOut->TrackData[i].Address[0]=0;
        !          2667:             cdaudioDataOut->TrackData[i].Address[1]=BCD_TO_DEC(Toc[1]);
        !          2668:             cdaudioDataOut->TrackData[i].Address[2]=BCD_TO_DEC(Toc[2]);
        !          2669:             cdaudioDataOut->TrackData[i].Address[3]=BCD_TO_DEC(Toc[3]);
        !          2670: 
        !          2671:         }
        !          2672: 
        !          2673:         //
        !          2674:         // Get info for lead out track
        !          2675:         //
        !          2676: 
        !          2677:         RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          2678:         cdb->PNR_READ_TOC.OperationCode     = PIONEER_READ_TOC_CODE;
        !          2679:         cdb->PNR_READ_TOC.AssignedLength[1] = PIONEER_TRANSFER_SIZE;
        !          2680:         cdb->PNR_READ_TOC.Type              = PIONEER_READ_LEAD_OUT_INFO;
        !          2681:         srb.TimeOutValue                    = AUDIO_TIMEOUT;
        !          2682:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2683:                                      &srb,
        !          2684:                                      Toc,
        !          2685:                                      PIONEER_TRANSFER_SIZE,
        !          2686:                                      FALSE
        !          2687:                                     );
        !          2688: 
        !          2689:         if (!NT_SUCCESS(status)) {
        !          2690: 
        !          2691:             CdDump(( 1,
        !          2692:                 "CdAudioPioneerDeviceControl: ReadTOC, read LeadOutTrack failed (0x%lx)\n",
        !          2693:                 status ));
        !          2694:             ExFreePool( Toc );
        !          2695:             goto SetStatusAndReturn;
        !          2696: 
        !          2697:         }
        !          2698: 
        !          2699:         cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          2700:         cdaudioDataOut->TrackData[i].Control     = 0x10;
        !          2701:         cdaudioDataOut->TrackData[i].TrackNumber = 0xaa;
        !          2702:         cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          2703:         cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          2704:         cdaudioDataOut->TrackData[i].Address[1]  = BCD_TO_DEC(Toc[0]);
        !          2705:         cdaudioDataOut->TrackData[i].Address[2]  = BCD_TO_DEC(Toc[1]);
        !          2706:         cdaudioDataOut->TrackData[i].Address[3]  = BCD_TO_DEC(Toc[2]);
        !          2707: 
        !          2708:         //
        !          2709:         // Set size of information transfered to
        !          2710:         // max size possible for CDROM Table of Contents
        !          2711:         //
        !          2712: 
        !          2713:         Irp->IoStatus.Information  = CDROM_TOC_SIZE;
        !          2714:         cdaudioDataOut->Length[0]  = CDROM_TOC_SIZE >> 8;
        !          2715:         cdaudioDataOut->Length[1]  = CDROM_TOC_SIZE & 0xFF;
        !          2716:         break;
        !          2717: 
        !          2718:     case IOCTL_CDROM_STOP_AUDIO:
        !          2719: 
        !          2720:         CdDump(( 3,
        !          2721:                      "CdAudioPioneerDeviceControl: IOCTL_CDROM_STOP_AUDIO received.\n"
        !          2722:                      ));
        !          2723: 
        !          2724: 
        !          2725:         deviceExtension->PlayActive = FALSE;
        !          2726: 
        !          2727:         //
        !          2728:         // Same as scsi-2 spec, so just send to default driver
        !          2729:         //
        !          2730: 
        !          2731:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          2732:         break;
        !          2733: 
        !          2734:     case IOCTL_CDROM_PLAY_AUDIO_MSF:
        !          2735:         {
        !          2736: 
        !          2737:         PCDROM_PLAY_AUDIO_MSF inputBuffer =
        !          2738:             Irp->AssociatedIrp.SystemBuffer;
        !          2739: 
        !          2740:         CdDump(( 3,
        !          2741:                  "CdAudioPioneerDeviceControl: IOCTL_CDROM_PLAY_AUDIO_MSF received.\n"
        !          2742:                 ));
        !          2743: 
        !          2744: 
        !          2745:         //
        !          2746:         // First, set play END point for the play operation
        !          2747:         //
        !          2748: 
        !          2749:         retry = 5;
        !          2750:         do {
        !          2751: 
        !          2752:             srb.CdbLength                     = 10;
        !          2753:             srb.TimeOutValue                  = AUDIO_TIMEOUT;
        !          2754:             cdb->PNR_SEEK_AUDIO.OperationCode = PIONEER_AUDIO_TRACK_SEARCH_CODE;
        !          2755:             cdb->PNR_SEEK_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->StartingM);
        !          2756:             cdb->PNR_SEEK_AUDIO.Second        = DEC_TO_BCD(inputBuffer->StartingS);
        !          2757:             cdb->PNR_SEEK_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->StartingF);
        !          2758:             cdb->PNR_SEEK_AUDIO.Type          = PIONEER_TYPE_ATIME;
        !          2759:             status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2760:                                          &srb,
        !          2761:                                          NULL,
        !          2762:                                          0,
        !          2763:                                          FALSE
        !          2764:                                         );
        !          2765: 
        !          2766:         } while( !NT_SUCCESS(status) && ((retry--)>0) );
        !          2767: 
        !          2768:         if (NT_SUCCESS(status)) {
        !          2769: 
        !          2770:             //
        !          2771:             // Now, set play start position and start playing.
        !          2772:             //
        !          2773: 
        !          2774:             RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          2775:             retry = 5;
        !          2776:             do {
        !          2777:                 srb.CdbLength = 10;
        !          2778:                 srb.TimeOutValue = AUDIO_TIMEOUT;
        !          2779:                 cdb->PNR_PLAY_AUDIO.OperationCode = PIONEER_PLAY_AUDIO_CODE;
        !          2780:                 cdb->PNR_PLAY_AUDIO.StopAddr      = 1;
        !          2781:                 cdb->PNR_PLAY_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->EndingM);
        !          2782:                 cdb->PNR_PLAY_AUDIO.Second        = DEC_TO_BCD(inputBuffer->EndingS);
        !          2783:                 cdb->PNR_PLAY_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->EndingF);
        !          2784:                 cdb->PNR_PLAY_AUDIO.Type          = PIONEER_TYPE_ATIME;
        !          2785:                 status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2786:                                              &srb,
        !          2787:                                              NULL,
        !          2788:                                              0,
        !          2789:                                              FALSE
        !          2790:                                             );
        !          2791:             } while( !NT_SUCCESS(status) && ((retry--)>0) );
        !          2792: 
        !          2793:             if (NT_SUCCESS(status)) {
        !          2794: 
        !          2795:                 //
        !          2796:                 // Indicate the play actition is active.
        !          2797:                 //
        !          2798: 
        !          2799:                 deviceExtension->PlayActive = TRUE;
        !          2800: 
        !          2801: 
        !          2802:             }
        !          2803: 
        !          2804: #if DBG
        !          2805:             if (!NT_SUCCESS(status)) {
        !          2806:                 CdDump(( 1,
        !          2807:                          "CdAudioPioneerDeviceControl: PLAY_AUDIO_MSF(stop) failed 0x%lx\n",
        !          2808:                          status
        !          2809:                         ));
        !          2810: 
        !          2811:                 CdDump(( 3,
        !          2812:                          "CdAudioPioneerDeviceControl: cdb = 0x%lx, srb = 0x%lx\n",
        !          2813:                          cdb, &srb
        !          2814:                         ));
        !          2815: 
        !          2816:                 if (CdAudioDebug>2)
        !          2817:                     DbgBreakPoint();
        !          2818:             }
        !          2819: #endif
        !          2820:         }
        !          2821: #if DBG
        !          2822:         else {
        !          2823: 
        !          2824:             CdDump(( 1,
        !          2825:                      "CdAudioPioneerDeviceControl: PLAY_AUDIO_MSF(start) failed 0x%lx\n",
        !          2826:                      status
        !          2827:                     ));
        !          2828:             CdDump(( 3,
        !          2829:                      "CdAudioPioneerDeviceControl: cdb = 0x%lx, srb = 0x%lx\n",
        !          2830:                      cdb, &srb
        !          2831:                     ));
        !          2832: 
        !          2833:             if (CdAudioDebug>2)
        !          2834:                 DbgBreakPoint();
        !          2835: 
        !          2836: 
        !          2837:         }
        !          2838: #endif
        !          2839:         }
        !          2840:         break;
        !          2841: 
        !          2842:     case IOCTL_CDROM_SEEK_AUDIO_MSF:
        !          2843:         {
        !          2844: 
        !          2845:         PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          2846: 
        !          2847:         CdDump(( 1,
        !          2848:                      "CdAudioPioneerDeviceControl: IOCTL_CDROM_SEEK_AUDIO_MSF received.\n"
        !          2849:                      ));
        !          2850: 
        !          2851: 
        !          2852:         retry = 5;
        !          2853:         do {
        !          2854: 
        !          2855:             //
        !          2856:             // seek to MSF and enter pause (still) mode.
        !          2857:             //
        !          2858: 
        !          2859:             srb.CdbLength                     = 10;
        !          2860:             srb.TimeOutValue                  = AUDIO_TIMEOUT;
        !          2861:             cdb->PNR_SEEK_AUDIO.OperationCode = PIONEER_AUDIO_TRACK_SEARCH_CODE;
        !          2862:             cdb->PNR_SEEK_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->M);
        !          2863:             cdb->PNR_SEEK_AUDIO.Second        = DEC_TO_BCD(inputBuffer->S);
        !          2864:             cdb->PNR_SEEK_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->F);
        !          2865:             cdb->PNR_SEEK_AUDIO.Type          = PIONEER_TYPE_ATIME;
        !          2866:             CdDump(( 3,
        !          2867:                      "CdAudioPioneerDeviceControl: Seek to MSF %d:%d:%d, BCD(%x:%x:%x)\n",
        !          2868:                      inputBuffer->M,
        !          2869:                      inputBuffer->S,
        !          2870:                      inputBuffer->F,
        !          2871:                      cdb->PNR_SEEK_AUDIO.Minute,
        !          2872:                      cdb->PNR_SEEK_AUDIO.Second,
        !          2873:                      cdb->PNR_SEEK_AUDIO.Frame
        !          2874:                     ));
        !          2875:             CdDump(( 3,
        !          2876:                      "CdAudioPioneerDeviceControl: Seek to MSF, cdb is 0x%x, srb is 0x%x\n",
        !          2877:                       cdb,
        !          2878:                       &srb
        !          2879:                      ));
        !          2880:     #if DBG
        !          2881:             if (CdAudioDebug>2) {
        !          2882: 
        !          2883:                 DbgBreakPoint();
        !          2884: 
        !          2885:             }
        !          2886:     #endif
        !          2887:             status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2888:                                          &srb,
        !          2889:                                          NULL,
        !          2890:                                          0,
        !          2891:                                          FALSE
        !          2892:                                         );
        !          2893: 
        !          2894:         } while( !NT_SUCCESS(status) && ((retry--)>0) );
        !          2895: #if DBG
        !          2896:         if (!NT_SUCCESS(status)) {
        !          2897: 
        !          2898:             CdDump(( 1, "CdAudioPioneerDeviceControl: Seek to MSF failed 0x%lx\n",
        !          2899:                      status
        !          2900:                     ));
        !          2901: 
        !          2902:             if (CdAudioDebug>5) {
        !          2903: 
        !          2904:                 DbgBreakPoint();
        !          2905: 
        !          2906:             }
        !          2907:         }
        !          2908: #endif
        !          2909:         }
        !          2910:         break;
        !          2911: 
        !          2912:     case IOCTL_CDROM_PAUSE_AUDIO:
        !          2913: 
        !          2914:         CdDump(( 3,
        !          2915:                      "CdAudioPioneerDeviceControl: IOCTL_CDROM_PAUSE_AUDIO received.\n"
        !          2916:                      ));
        !          2917: 
        !          2918:         deviceExtension->PlayActive = FALSE;
        !          2919: 
        !          2920:         //
        !          2921:         // Enter pause (still ) mode
        !          2922:         //
        !          2923: 
        !          2924:         srb.CdbLength                      = 10;
        !          2925:         srb.TimeOutValue                   = AUDIO_TIMEOUT;
        !          2926:         cdb->PNR_PAUSE_AUDIO.OperationCode = PIONEER_PAUSE_CODE;
        !          2927:         cdb->PNR_PAUSE_AUDIO.Pause         = 1;
        !          2928:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2929:                                      &srb,
        !          2930:                                      NULL,
        !          2931:                                      0,
        !          2932:                                      FALSE
        !          2933:                                     );
        !          2934:         break;
        !          2935: 
        !          2936:     case IOCTL_CDROM_RESUME_AUDIO:
        !          2937: 
        !          2938:         CdDump(( 3,
        !          2939:                      "CdAudioPioneerDeviceControl: IOCTL_CDROM_RESUME_AUDIO received.\n"
        !          2940:                      ));
        !          2941: 
        !          2942: 
        !          2943:         //
        !          2944:         // Resume Play
        !          2945:         //
        !          2946: 
        !          2947:         srb.CdbLength                      = 10;
        !          2948:         srb.TimeOutValue                   = AUDIO_TIMEOUT;
        !          2949:         cdb->PNR_PAUSE_AUDIO.OperationCode = PIONEER_PAUSE_CODE;
        !          2950:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          2951:                                      &srb,
        !          2952:                                      NULL,
        !          2953:                                      0,
        !          2954:                                      FALSE
        !          2955:                                     );
        !          2956:         break;
        !          2957: 
        !          2958:     case IOCTL_CDROM_READ_Q_CHANNEL:
        !          2959:         {
        !          2960:         PSUB_Q_CURRENT_POSITION userPtr =
        !          2961:             Irp->AssociatedIrp.SystemBuffer;
        !          2962:         PUCHAR SubQPtr =
        !          2963:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          2964:                             PIONEER_Q_CHANNEL_TRANSFER_SIZE
        !          2965:                            );
        !          2966: 
        !          2967:         CdDump(( 5,
        !          2968:                      "CdAudioPioneerDeviceControl: IOCTL_CDROM_READ_Q_CHANNEL received.\n"
        !          2969:                      ));
        !          2970: 
        !          2971:         if (SubQPtr==NULL) {
        !          2972: 
        !          2973:             CdDump(( 1,
        !          2974:                          "CdAudioPioneerDeviceControl: READ_Q_CHANNEL, SubQPtr==NULL!\n"
        !          2975:                          ));
        !          2976: 
        !          2977:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          2978:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          2979:             goto SetStatusAndReturn;
        !          2980: 
        !          2981:         }
        !          2982: 
        !          2983:         if ( ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format!=
        !          2984:              IOCTL_CDROM_CURRENT_POSITION) {
        !          2985: 
        !          2986:             CdDump(( 1,
        !          2987:                          "CdAudioPioneerDeviceControl: READ_Q_CHANNEL, Illegal Format (%d)!\n",
        !          2988:                          ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format
        !          2989:                          ));
        !          2990: 
        !          2991:             ExFreePool( SubQPtr );
        !          2992:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          2993:             status = STATUS_INVALID_DEVICE_REQUEST;
        !          2994:             goto SetStatusAndReturn;
        !          2995:         }
        !          2996: 
        !          2997:         //
        !          2998:         // Read audio play status
        !          2999:         //
        !          3000: 
        !          3001:         retry = 5;
        !          3002:         do {
        !          3003:             srb.CdbLength = 10;
        !          3004:             srb.TimeOutValue = AUDIO_TIMEOUT;
        !          3005:             cdb->PNR_AUDIO_STATUS.OperationCode  = PIONEER_AUDIO_STATUS_CODE;
        !          3006:             cdb->PNR_AUDIO_STATUS.AssignedLength = PIONEER_AUDIO_STATUS_TRANSFER_SIZE;  // Transfer Length
        !          3007:             status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3008:                                          &srb,
        !          3009:                                          SubQPtr,
        !          3010:                                          6,
        !          3011:                                          FALSE
        !          3012:                                         );
        !          3013:         } while( !NT_SUCCESS(status) && ((retry--)>0) && status != STATUS_DEVICE_NOT_READY);
        !          3014:         if (NT_SUCCESS(status)) {
        !          3015: 
        !          3016:             userPtr->Header.Reserved = 0;
        !          3017:             if (SubQPtr[0]==0x00)
        !          3018:                 userPtr->Header.AudioStatus = AUDIO_STATUS_IN_PROGRESS;
        !          3019:             else if (SubQPtr[0]==0x01) {
        !          3020:                 deviceExtension->PlayActive = FALSE;
        !          3021:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PAUSED;
        !          3022:             } else if (SubQPtr[0]==0x02) {
        !          3023:                 deviceExtension->PlayActive = FALSE;
        !          3024:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PAUSED;
        !          3025:             } else if (SubQPtr[0]==0x03) {
        !          3026: 
        !          3027:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PLAY_COMPLETE;
        !          3028:                 deviceExtension->PlayActive = FALSE;
        !          3029: 
        !          3030:             } else {
        !          3031:                 deviceExtension->PlayActive = FALSE;
        !          3032: 
        !          3033:             }
        !          3034: 
        !          3035:         } else {
        !          3036: 
        !          3037:             CdDump(( 1,
        !          3038:                          "CdAudioPioneerDeviceControl: read status code (Q) failed (0x%lx)\n",
        !          3039:                          status
        !          3040:                          ));
        !          3041: 
        !          3042:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          3043:             ExFreePool( SubQPtr );
        !          3044:             goto SetStatusAndReturn;
        !          3045: 
        !          3046:         }
        !          3047: 
        !          3048:         //
        !          3049:         // Set up to read current position from Q Channel
        !          3050:         //
        !          3051: 
        !          3052:         RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          3053:         retry =  5;
        !          3054:         do {
        !          3055:             srb.CdbLength = 10;
        !          3056:             srb.TimeOutValue = AUDIO_TIMEOUT;
        !          3057:             cdb->PNR_READ_Q_CHANNEL.OperationCode  = PIONEER_READ_SUB_Q_CHANNEL_CODE;
        !          3058:             cdb->PNR_READ_Q_CHANNEL.AssignedLength = PIONEER_Q_CHANNEL_TRANSFER_SIZE;  // Transfer Length
        !          3059:             status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3060:                                          &srb,
        !          3061:                                          SubQPtr,
        !          3062:                                          PIONEER_Q_CHANNEL_TRANSFER_SIZE,
        !          3063:                                          FALSE
        !          3064:                                         );
        !          3065: 
        !          3066:         } while( !NT_SUCCESS(status) && ((retry--)>0) );
        !          3067: 
        !          3068:         if (NT_SUCCESS(status)) {
        !          3069: 
        !          3070:             userPtr->Header.DataLength[0] = 0;
        !          3071:             userPtr->Header.DataLength[0] = 12;
        !          3072: 
        !          3073:             userPtr->FormatCode = 0x01;
        !          3074:             userPtr->Control = SubQPtr[0] & 0x0F;
        !          3075:             userPtr->ADR     = 0;
        !          3076:             userPtr->TrackNumber = BCD_TO_DEC(SubQPtr[1]);
        !          3077:             userPtr->IndexNumber = BCD_TO_DEC(SubQPtr[2]);
        !          3078:             userPtr->AbsoluteAddress[0] = 0;
        !          3079:             userPtr->AbsoluteAddress[1] = BCD_TO_DEC((SubQPtr[6]));
        !          3080:             userPtr->AbsoluteAddress[2] = BCD_TO_DEC((SubQPtr[7]));
        !          3081:             userPtr->AbsoluteAddress[3] = BCD_TO_DEC((SubQPtr[8]));
        !          3082:             userPtr->TrackRelativeAddress[0] = 0;
        !          3083:             userPtr->TrackRelativeAddress[1] = BCD_TO_DEC((SubQPtr[3]));
        !          3084:             userPtr->TrackRelativeAddress[2] = BCD_TO_DEC((SubQPtr[4]));
        !          3085:             userPtr->TrackRelativeAddress[3] = BCD_TO_DEC((SubQPtr[5]));
        !          3086:             Irp->IoStatus.Information = 16;
        !          3087: 
        !          3088:         } else {
        !          3089: 
        !          3090:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          3091:             CdDump(( 1,
        !          3092:                          "CdAudioPioneerDeviceControl: read q channel failed (0x%lx)\n",
        !          3093:                          status
        !          3094:                          ));
        !          3095: 
        !          3096: 
        !          3097:         }
        !          3098: 
        !          3099:         ExFreePool( SubQPtr );
        !          3100:         }
        !          3101:         break;
        !          3102: 
        !          3103:     case IOCTL_CDROM_EJECT_MEDIA:
        !          3104: 
        !          3105:         CdDump(( 3,
        !          3106:                      "CdAudioPioneerDeviceControl: IOCTL_CDROM_EJECT_MEDIA received.\n"
        !          3107:                      ));
        !          3108: 
        !          3109: 
        !          3110:         deviceExtension->PlayActive = FALSE;
        !          3111: 
        !          3112:         //
        !          3113:         // Build cdb to eject cartridge
        !          3114:         //
        !          3115: 
        !          3116:         srb.CdbLength            = 10;
        !          3117:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          3118:         cdb->PNR_EJECT.OperationCode = PIONEER_EJECT_CODE;
        !          3119:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3120:                                      &srb,
        !          3121:                                      NULL,
        !          3122:                                      0,
        !          3123:                                      FALSE
        !          3124:                                     );
        !          3125:         break;
        !          3126: 
        !          3127:     case IOCTL_CDROM_GET_CONTROL:
        !          3128:     case IOCTL_CDROM_GET_VOLUME:
        !          3129:     case IOCTL_CDROM_SET_VOLUME:
        !          3130: 
        !          3131:         CdDump(( 3, "CdAudioPioneerDeviceControl: Not Supported yet.\n" ));
        !          3132:         status = STATUS_INVALID_DEVICE_REQUEST;
        !          3133:         break;
        !          3134: 
        !          3135:     case IOCTL_CDROM_CHECK_VERIFY:
        !          3136: 
        !          3137:         //
        !          3138:         // Update the play active flag.
        !          3139:         //
        !          3140: 
        !          3141:         CdAudioIsPlayActive(DeviceObject);
        !          3142: 
        !          3143:     default:
        !          3144: 
        !          3145:         CdDump((5,"CdAudioPioneerDeviceControl: Unsupported device IOCTL\n"));
        !          3146:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          3147:         break;
        !          3148: 
        !          3149: 
        !          3150: 
        !          3151:     } // end switch( IOCTL )
        !          3152: 
        !          3153: SetStatusAndReturn:
        !          3154:     //
        !          3155:     // set status code and return
        !          3156:     //
        !          3157: 
        !          3158:     if (status == STATUS_VERIFY_REQUIRED) {
        !          3159: 
        !          3160:         //
        !          3161:         // If the status is verified required and the this request
        !          3162:         // should bypass verify required then retry the request.
        !          3163:         //
        !          3164: 
        !          3165:         if (currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) {
        !          3166: 
        !          3167:             status = STATUS_IO_DEVICE_ERROR;
        !          3168:             goto PioneerRestart;
        !          3169: 
        !          3170:         }
        !          3171: 
        !          3172: 
        !          3173:         IoSetHardErrorOrVerifyDevice( Irp,
        !          3174:                                       deviceExtension->TargetDeviceObject
        !          3175:                                      );
        !          3176: 
        !          3177:         Irp->IoStatus.Information = 0;
        !          3178:     }
        !          3179: 
        !          3180:     Irp->IoStatus.Status = status;
        !          3181:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          3182:     return status;
        !          3183: 
        !          3184: }
        !          3185: 
        !          3186: 
        !          3187: NTSTATUS
        !          3188: CdAudioDenonDeviceControl(
        !          3189:     PDEVICE_OBJECT DeviceObject,
        !          3190:     PIRP Irp
        !          3191:     )
        !          3192: 
        !          3193: /*++
        !          3194: 
        !          3195: Routine Description:
        !          3196: 
        !          3197:     This routine is called by CdAudioDeviceControl to handle
        !          3198:     audio IOCTLs sent to DENON DRD-253 cdrom drive.
        !          3199: 
        !          3200: Arguments:
        !          3201: 
        !          3202:     DeviceObject
        !          3203:     Irp
        !          3204: 
        !          3205: Return Value:
        !          3206: 
        !          3207:     NTSTATUS
        !          3208: 
        !          3209: --*/
        !          3210: 
        !          3211: {
        !          3212:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          3213:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          3214:     PCDROM_TOC         cdaudioDataOut  = Irp->AssociatedIrp.SystemBuffer;
        !          3215:     SCSI_REQUEST_BLOCK srb;
        !          3216:     PCDB               cdb = (PCDB)srb.Cdb;
        !          3217:     NTSTATUS           status;
        !          3218:     ULONG              i,bytesTransfered;
        !          3219:     PUCHAR             Toc;
        !          3220: 
        !          3221: DenonRestart:
        !          3222: 
        !          3223:     //
        !          3224:     // Clear out cdb
        !          3225:     //
        !          3226: 
        !          3227:     RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          3228: 
        !          3229:     //
        !          3230:     // What IOCTL do we need to execute?
        !          3231:     //
        !          3232: 
        !          3233:     switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
        !          3234: 
        !          3235:     case IOCTL_CDROM_READ_TOC:
        !          3236:         CdDump(( 3,
        !          3237:                      "CdAudioDenonDeviceControl: IOCTL_CDROM_READ_TOC received.\n"
        !          3238:                      ));
        !          3239: 
        !          3240:         //
        !          3241:         // If the cd is playing music then reject this request.
        !          3242:         //
        !          3243: 
        !          3244:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          3245:             status = STATUS_DEVICE_BUSY;
        !          3246:             break;
        !          3247:         }
        !          3248: 
        !          3249: 
        !          3250:         //
        !          3251:         // Allocate storage to hold TOC from disc
        !          3252:         //
        !          3253: 
        !          3254:         Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !          3255:                                       CDROM_TOC_SIZE
        !          3256:                                      );
        !          3257: 
        !          3258:         if (Toc==NULL) {
        !          3259: 
        !          3260:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          3261:             goto SetStatusAndReturn;
        !          3262: 
        !          3263:         }
        !          3264: 
        !          3265:         //
        !          3266:         // Set up defaults
        !          3267:         //
        !          3268: 
        !          3269:         RtlZeroMemory( Toc, CDROM_TOC_SIZE );
        !          3270: 
        !          3271:         //
        !          3272:         // Fill in cdb for this operation
        !          3273:         //
        !          3274: 
        !          3275:         cdb->CDB6GENERIC.OperationCode = DENON_READ_TOC_CODE;
        !          3276:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          3277:         srb.CdbLength                  = 6;
        !          3278:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3279:                                      &srb,
        !          3280:                                      Toc,
        !          3281:                                      CDROM_TOC_SIZE,
        !          3282:                                      FALSE
        !          3283:                                     );
        !          3284: 
        !          3285:         if (!NT_SUCCESS(status) && (status!=STATUS_DATA_OVERRUN)) {
        !          3286: 
        !          3287:             CdDump(( 1,
        !          3288:                 "CdAudioDenonDeviceControl: READ_TOC error (0x%08lX)\n",
        !          3289:                  status ));
        !          3290: 
        !          3291:             if (SRB_STATUS(srb.SrbStatus)!=SRB_STATUS_DATA_OVERRUN) {
        !          3292: 
        !          3293:                 CdDump(( 1, "CdAudioDenonDeviceControl: SRB ERROR (0x%lX)\n",
        !          3294:                              srb.SrbStatus ));
        !          3295:                 ExFreePool( Toc );
        !          3296:                 goto SetStatusAndReturn;
        !          3297:             }
        !          3298: 
        !          3299:         }
        !          3300: 
        !          3301:         //
        !          3302:         // Set the status to success since data under runs are not an error.
        !          3303:         //
        !          3304: 
        !          3305:         status = STATUS_SUCCESS;
        !          3306: 
        !          3307:         //
        !          3308:         // Since the Denon manual didn't define the format of
        !          3309:         // the buffer returned from this call, here it is:
        !          3310:         //
        !          3311:         // Byte  Data (4 byte "packets")
        !          3312:         //
        !          3313:         //  00   a0 FT 00 00 (FT       == BCD of first track number on disc)
        !          3314:         //  04   a1 LT 00 00 (LT       == BCD of last  track number on disc)
        !          3315:         //  08   a2 MM SS FF (MM SS FF == BCD of total disc time, in MSF)
        !          3316:         //
        !          3317:         //  For each track on disc:
        !          3318:         //
        !          3319:         //  0C   XX   MM SS FF (MM SS FF == BCD MSF start position of track XX)
        !          3320:         //  0C+4 XX+1 MM SS FF (MM SS FF == BCD MSF start position of track XX+1)
        !          3321:         //
        !          3322:         //  etc., for each track
        !          3323:         //
        !          3324: 
        !          3325:         //
        !          3326:         // Translate data into our format
        !          3327:         //
        !          3328: 
        !          3329:         bytesTransfered =
        !          3330:             currentIrpStack->Parameters.Read.Length > srb.DataTransferLength ?
        !          3331:             srb.DataTransferLength : currentIrpStack->Parameters.Read.Length;
        !          3332:         Irp->IoStatus.Information = bytesTransfered;
        !          3333:         cdaudioDataOut->Length[0]  = bytesTransfered >> 8;
        !          3334:         cdaudioDataOut->Length[1]  = (bytesTransfered & 0xFF);
        !          3335:         cdaudioDataOut->FirstTrack = BCD_TO_DEC(Toc[1]);
        !          3336:         cdaudioDataOut->LastTrack  = BCD_TO_DEC(Toc[5]);
        !          3337: 
        !          3338:         for( i=0;
        !          3339:              i<=( (ULONG)cdaudioDataOut->LastTrack -
        !          3340:                   (ULONG)cdaudioDataOut->FirstTrack   );
        !          3341:              i++
        !          3342:             ) {
        !          3343: 
        !          3344:             //
        !          3345:             // Grab Information for each track
        !          3346:             //
        !          3347: 
        !          3348:             cdaudioDataOut->TrackData[i].Reserved = 0;
        !          3349:             cdaudioDataOut->TrackData[i].Control  = Toc[(i*4)+12];
        !          3350:             cdaudioDataOut->TrackData[i].TrackNumber =
        !          3351:                 (i + cdaudioDataOut->FirstTrack);
        !          3352: 
        !          3353:             cdaudioDataOut->TrackData[i].Reserved1  = 0;
        !          3354:             cdaudioDataOut->TrackData[i].Address[0] = 0;
        !          3355:             cdaudioDataOut->TrackData[i].Address[1] =
        !          3356:                 BCD_TO_DEC((Toc[(i*4)+13]));
        !          3357:             cdaudioDataOut->TrackData[i].Address[2] =
        !          3358:                 BCD_TO_DEC((Toc[(i*4)+14]));
        !          3359:             cdaudioDataOut->TrackData[i].Address[3] =
        !          3360:                 BCD_TO_DEC((Toc[(i*4)+15]));
        !          3361: 
        !          3362:         }
        !          3363: 
        !          3364:         //
        !          3365:         // Fake "lead out track" info
        !          3366:         //
        !          3367: 
        !          3368:         cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          3369:         cdaudioDataOut->TrackData[i].Control     = 0;
        !          3370:         cdaudioDataOut->TrackData[i].TrackNumber = 0xaa;
        !          3371:         cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          3372:         cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          3373:         cdaudioDataOut->TrackData[i].Address[1]  = BCD_TO_DEC(Toc[9]);
        !          3374:         cdaudioDataOut->TrackData[i].Address[2]  = BCD_TO_DEC(Toc[10]);
        !          3375:         cdaudioDataOut->TrackData[i].Address[3]  = BCD_TO_DEC(Toc[11]);
        !          3376: 
        !          3377:         //
        !          3378:         // Clear out deviceExtension data
        !          3379:         //
        !          3380: 
        !          3381:         deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          3382:         deviceExtension->PausedM = 0;
        !          3383:         deviceExtension->PausedS = 0;
        !          3384:         deviceExtension->PausedF = 0;
        !          3385:         deviceExtension->LastEndM = 0;
        !          3386:         deviceExtension->LastEndS = 0;
        !          3387:         deviceExtension->LastEndF = 0;
        !          3388: 
        !          3389:         //
        !          3390:         // Free storage now that we've stored it elsewhere
        !          3391:         //
        !          3392: 
        !          3393:         ExFreePool( Toc );
        !          3394:         break;
        !          3395: 
        !          3396:     case IOCTL_CDROM_PLAY_AUDIO_MSF:
        !          3397:     case IOCTL_CDROM_STOP_AUDIO:
        !          3398:         {
        !          3399: 
        !          3400:         PCDROM_PLAY_AUDIO_MSF inputBuffer =
        !          3401:             Irp->AssociatedIrp.SystemBuffer;
        !          3402: 
        !          3403:         deviceExtension->PlayActive = FALSE;
        !          3404: 
        !          3405:         srb.CdbLength                  = 6;
        !          3406:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          3407:         cdb->CDB6GENERIC.OperationCode = DENON_STOP_AUDIO_CODE;
        !          3408:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3409:                                      &srb,
        !          3410:                                      NULL,
        !          3411:                                      0,
        !          3412:                                      FALSE
        !          3413:                                     );
        !          3414: 
        !          3415:         if (NT_SUCCESS(status)) {
        !          3416: 
        !          3417:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          3418:             deviceExtension->PausedM = 0;
        !          3419:             deviceExtension->PausedS = 0;
        !          3420:             deviceExtension->PausedF = 0;
        !          3421:             deviceExtension->LastEndM = 0;
        !          3422:             deviceExtension->LastEndS = 0;
        !          3423:             deviceExtension->LastEndF = 0;
        !          3424: 
        !          3425:         } else {
        !          3426: 
        !          3427:             CdDump(( 3,
        !          3428:                 "CdAudioDenonDeviceControl: STOP failed (0x%08lX)\n",
        !          3429:                 status ));
        !          3430: 
        !          3431:         }
        !          3432: 
        !          3433: 
        !          3434:         if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
        !          3435:             IOCTL_CDROM_STOP_AUDIO
        !          3436:            ) {
        !          3437: 
        !          3438:             CdDump(( 3,
        !          3439:                          "CdAudioDenonDeviceControl: IOCTL_CDROM_STOP_AUDIO received.\n"
        !          3440:                          ));
        !          3441: 
        !          3442:             goto SetStatusAndReturn;
        !          3443: 
        !          3444:         }
        !          3445: 
        !          3446:         CdDump(( 3,
        !          3447:             "CdAudioDenonDeviceControl: IOCTL_CDROM_PLAY_AUDIO_MSF received.\n"
        !          3448:             ));
        !          3449: 
        !          3450:         //
        !          3451:         // Fill in cdb for this operation
        !          3452:         //
        !          3453: 
        !          3454:         srb.CdbLength                = 10;
        !          3455:         srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          3456:         cdb->CDB10.OperationCode     = DENON_PLAY_AUDIO_EXTENDED_CODE;
        !          3457:         cdb->CDB10.LogicalBlockByte0 = DEC_TO_BCD(inputBuffer->StartingM);
        !          3458:         cdb->CDB10.LogicalBlockByte1 = DEC_TO_BCD(inputBuffer->StartingS);
        !          3459:         cdb->CDB10.LogicalBlockByte2 = DEC_TO_BCD(inputBuffer->StartingF);
        !          3460:         cdb->CDB10.LogicalBlockByte3 = DEC_TO_BCD(inputBuffer->EndingM);
        !          3461:         cdb->CDB10.Reserved2         = DEC_TO_BCD(inputBuffer->EndingS);
        !          3462:         cdb->CDB10.TransferBlocksMsb = DEC_TO_BCD(inputBuffer->EndingF);
        !          3463:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3464:                                      &srb,
        !          3465:                                      NULL,
        !          3466:                                      0,
        !          3467:                                      FALSE
        !          3468:                                     );
        !          3469: 
        !          3470:         if (NT_SUCCESS(status)) {
        !          3471: 
        !          3472:             //
        !          3473:             // Indicate the play actition is active.
        !          3474:             //
        !          3475: 
        !          3476:             deviceExtension->PlayActive = TRUE;
        !          3477:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          3478: 
        !          3479:             //
        !          3480:             // Set last play ending address for next pause command
        !          3481:             //
        !          3482: 
        !          3483:             deviceExtension->LastEndM = DEC_TO_BCD(inputBuffer->EndingM);
        !          3484:             deviceExtension->LastEndS = DEC_TO_BCD(inputBuffer->EndingS);
        !          3485:             deviceExtension->LastEndF = DEC_TO_BCD(inputBuffer->EndingF);
        !          3486:             CdDump(( 3,
        !          3487:                 "CdAudioDenonDeviceControl: PLAY  ==> BcdLastEnd set to (%x %x %x)\n",
        !          3488:                 deviceExtension->LastEndM,
        !          3489:                 deviceExtension->LastEndS,
        !          3490:                 deviceExtension->LastEndF ));
        !          3491: 
        !          3492:         } else {
        !          3493: 
        !          3494:             CdDump(( 3,
        !          3495:                 "CdAudioDenonDeviceControl: PLAY failed (0x%08lX)\n",
        !          3496:                 status ));
        !          3497: 
        !          3498:             //
        !          3499:             // The Denon drive returns STATUS_INVALD_DEVICE_REQUEST
        !          3500:             // when we ask to play an invalid address, so we need
        !          3501:             // to map to STATUS_NONEXISTENT_SECTOR in order to be
        !          3502:             // consistent with the other drives.
        !          3503:             //
        !          3504: 
        !          3505:             if (status==STATUS_INVALID_DEVICE_REQUEST) {
        !          3506: 
        !          3507:                 status = STATUS_NONEXISTENT_SECTOR;
        !          3508:             }
        !          3509: 
        !          3510:         }
        !          3511:         }
        !          3512:         break;
        !          3513: 
        !          3514:     case IOCTL_CDROM_SEEK_AUDIO_MSF:
        !          3515:         {
        !          3516: 
        !          3517:         PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          3518: 
        !          3519:         CdDump(( 3,
        !          3520:             "CdAudioDenonDeviceControl: IOCTL_CDROM_SEEK_AUDIO_MSF received.\n"
        !          3521:             ));
        !          3522: 
        !          3523:         //
        !          3524:         // Fill in cdb for this operation
        !          3525:         //
        !          3526: 
        !          3527:         srb.CdbLength                = 10;
        !          3528:         srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          3529:         cdb->CDB10.OperationCode     = DENON_PLAY_AUDIO_EXTENDED_CODE;
        !          3530:         cdb->CDB10.LogicalBlockByte0 = DEC_TO_BCD(inputBuffer->M);
        !          3531:         cdb->CDB10.LogicalBlockByte1 = DEC_TO_BCD(inputBuffer->S);
        !          3532:         cdb->CDB10.LogicalBlockByte2 = DEC_TO_BCD(inputBuffer->F);
        !          3533:         cdb->CDB10.LogicalBlockByte3 = DEC_TO_BCD(inputBuffer->M);
        !          3534:         cdb->CDB10.Reserved2         = DEC_TO_BCD(inputBuffer->S);
        !          3535:         cdb->CDB10.TransferBlocksMsb = DEC_TO_BCD(inputBuffer->F);
        !          3536:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3537:                                      &srb,
        !          3538:                                      NULL,
        !          3539:                                      0,
        !          3540:                                      FALSE
        !          3541:                                     );
        !          3542: 
        !          3543:         if (NT_SUCCESS(status)) {
        !          3544: 
        !          3545:             deviceExtension->Paused = CDAUDIO_PAUSED;
        !          3546:             deviceExtension->PausedM = DEC_TO_BCD(inputBuffer->M);
        !          3547:             deviceExtension->PausedS = DEC_TO_BCD(inputBuffer->S);
        !          3548:             deviceExtension->PausedF = DEC_TO_BCD(inputBuffer->F);
        !          3549:             deviceExtension->LastEndM = DEC_TO_BCD(inputBuffer->M);
        !          3550:             deviceExtension->LastEndS = DEC_TO_BCD(inputBuffer->S);
        !          3551:             deviceExtension->LastEndF = DEC_TO_BCD(inputBuffer->F);
        !          3552:             CdDump(( 3,
        !          3553:                 "CdAudioDenonDeviceControl: SEEK, Paused (%x %x %x) LastEnd (%x %x %x)\n",
        !          3554:                 deviceExtension->PausedM,
        !          3555:                 deviceExtension->PausedS,
        !          3556:                 deviceExtension->PausedF,
        !          3557:                 deviceExtension->LastEndM,
        !          3558:                 deviceExtension->LastEndS,
        !          3559:                 deviceExtension->LastEndF ));
        !          3560: 
        !          3561:         } else {
        !          3562: 
        !          3563:             CdDump(( 3,
        !          3564:                 "CdAudioDenonDeviceControl: SEEK failed (0x%08lX)\n",
        !          3565:                 status ));
        !          3566: 
        !          3567:             //
        !          3568:             // The Denon drive returns STATUS_INVALD_DEVICE_REQUEST
        !          3569:             // when we ask to play an invalid address, so we need
        !          3570:             // to map to STATUS_NONEXISTENT_SECTOR in order to be
        !          3571:             // consistent with the other drives.
        !          3572:             //
        !          3573: 
        !          3574:             if (status==STATUS_INVALID_DEVICE_REQUEST) {
        !          3575: 
        !          3576:                 status = STATUS_NONEXISTENT_SECTOR;
        !          3577:             }
        !          3578: 
        !          3579:         }
        !          3580:         }
        !          3581:         break;
        !          3582: 
        !          3583:     case IOCTL_CDROM_PAUSE_AUDIO:
        !          3584:         {
        !          3585:         PUCHAR SubQPtr =
        !          3586:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          3587:                             10
        !          3588:                            );
        !          3589: 
        !          3590:         CdDump(( 3,
        !          3591:                      "CdAudioDenonDeviceControl: IOCTL_CDROM_PAUSE_AUDIO received.\n"
        !          3592:                      ));
        !          3593: 
        !          3594:         deviceExtension->PlayActive = FALSE;
        !          3595: 
        !          3596:         if (SubQPtr==NULL) {
        !          3597: 
        !          3598:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          3599:             goto SetStatusAndReturn;
        !          3600: 
        !          3601:         }
        !          3602: 
        !          3603:         //
        !          3604:         // Enter pause (still ) mode
        !          3605:         //
        !          3606: 
        !          3607:         if (deviceExtension->Paused==CDAUDIO_PAUSED) {
        !          3608: 
        !          3609:             CdDump(( 3,
        !          3610:                 "CdAudioDenonDeviceControl: PAUSE: Already Paused!\n"
        !          3611:                 ));
        !          3612: 
        !          3613:             ExFreePool( SubQPtr );
        !          3614:             status = STATUS_SUCCESS;
        !          3615:             goto SetStatusAndReturn;
        !          3616: 
        !          3617:         }
        !          3618: 
        !          3619:         //
        !          3620:         // Since the Denon doesn't have a pause mode,
        !          3621:         // we'll just record the current position and
        !          3622:         // stop the drive.
        !          3623:         //
        !          3624: 
        !          3625:         srb.CdbLength                  = 6;
        !          3626:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          3627:         cdb->CDB6GENERIC.OperationCode = DENON_READ_SUB_Q_CHANNEL_CODE;
        !          3628:         cdb->CDB6GENERIC.CommandUniqueBytes[2] = 10; // Transfer Length
        !          3629:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3630:                                      &srb,
        !          3631:                                      SubQPtr,
        !          3632:                                      10,
        !          3633:                                      FALSE
        !          3634:                                     );
        !          3635:         if (!NT_SUCCESS(status)) {
        !          3636: 
        !          3637:                 CdDump(( 1,
        !          3638:                     "CdAudioDenonDeviceControl: Pause, Read Q Channel failed (0x%lx)\n",
        !          3639:                     status ));
        !          3640:                 ExFreePool( SubQPtr );
        !          3641:                 goto SetStatusAndReturn;
        !          3642:         }
        !          3643: 
        !          3644:         deviceExtension->PausedM = SubQPtr[7];
        !          3645:         deviceExtension->PausedS = SubQPtr[8];
        !          3646:         deviceExtension->PausedF = SubQPtr[9];
        !          3647: 
        !          3648:         RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          3649:         srb.CdbLength                  = 6;
        !          3650:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          3651:         cdb->CDB6GENERIC.OperationCode = DENON_STOP_AUDIO_CODE;
        !          3652:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3653:                                      &srb,
        !          3654:                                      NULL,
        !          3655:                                      0,
        !          3656:                                      FALSE
        !          3657:                                     );
        !          3658:         if (!NT_SUCCESS(status)) {
        !          3659: 
        !          3660:                 CdDump(( 1,
        !          3661:                     "CdAudioDenonDeviceControl: PAUSE, StopAudio failed! (0x%08lX)\n",
        !          3662:                     status ));
        !          3663:                 ExFreePool( SubQPtr );
        !          3664:                 goto SetStatusAndReturn;
        !          3665:         }
        !          3666: 
        !          3667:         deviceExtension->Paused = CDAUDIO_PAUSED;
        !          3668:         deviceExtension->PausedM = SubQPtr[7];
        !          3669:         deviceExtension->PausedS = SubQPtr[8];
        !          3670:         deviceExtension->PausedF = SubQPtr[9];
        !          3671: 
        !          3672:         CdDump((3,
        !          3673:             "CdAudioDenonDeviceControl: PAUSE ==> Paused  set to (%x %x %x)\n",
        !          3674:             deviceExtension->PausedM,
        !          3675:             deviceExtension->PausedS,
        !          3676:             deviceExtension->PausedF ));
        !          3677: 
        !          3678:         ExFreePool( SubQPtr );
        !          3679:         }
        !          3680:         break;
        !          3681: 
        !          3682:     case IOCTL_CDROM_RESUME_AUDIO:
        !          3683: 
        !          3684:         //
        !          3685:         // Resume cdrom
        !          3686:         //
        !          3687: 
        !          3688:         CdDump(( 3,
        !          3689:                      "CdAudioDenonDeviceControl: IOCTL_CDROM_RESUME_AUDIO received.\n"
        !          3690:                      ));
        !          3691: 
        !          3692: 
        !          3693:         //
        !          3694:         // Since the Denon doesn't have a resume IOCTL,
        !          3695:         // we'll just start playing (if paused) from the
        !          3696:         // last recored paused position to the last recorded
        !          3697:         // "end of play" position.
        !          3698:         //
        !          3699: 
        !          3700:         if (deviceExtension->Paused==CDAUDIO_NOT_PAUSED) {
        !          3701: 
        !          3702:             status = STATUS_UNSUCCESSFUL;
        !          3703:             goto SetStatusAndReturn;
        !          3704: 
        !          3705:         }
        !          3706: 
        !          3707: 
        !          3708: 
        !          3709:         //
        !          3710:         // Fill in cdb for this operation
        !          3711:         //
        !          3712: 
        !          3713:         srb.CdbLength                = 10;
        !          3714:         srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          3715:         cdb->CDB10.OperationCode     = DENON_PLAY_AUDIO_EXTENDED_CODE;
        !          3716:         cdb->CDB10.LogicalBlockByte0 = deviceExtension->PausedM;
        !          3717:         cdb->CDB10.LogicalBlockByte1 = deviceExtension->PausedS;
        !          3718:         cdb->CDB10.LogicalBlockByte2 = deviceExtension->PausedF;
        !          3719:         cdb->CDB10.LogicalBlockByte3 = deviceExtension->LastEndM;
        !          3720:         cdb->CDB10.Reserved2         = deviceExtension->LastEndS;
        !          3721:         cdb->CDB10.TransferBlocksMsb = deviceExtension->LastEndF;
        !          3722:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3723:                                      &srb,
        !          3724:                                      NULL,
        !          3725:                                      0,
        !          3726:                                      FALSE
        !          3727:                                     );
        !          3728: 
        !          3729:         if (NT_SUCCESS(status)) {
        !          3730: 
        !          3731:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          3732: 
        !          3733:         } else {
        !          3734: 
        !          3735:             CdDump(( 1,
        !          3736:                 "CdAudioDenonDeviceControl: RESUME (%x %x %x) - (%x %x %x) failed (0x%08lX)\n",
        !          3737:                 deviceExtension->PausedM,
        !          3738:                 deviceExtension->PausedS,
        !          3739:                 deviceExtension->PausedF,
        !          3740:                 deviceExtension->LastEndM,
        !          3741:                 deviceExtension->LastEndS,
        !          3742:                 deviceExtension->LastEndF,
        !          3743:                 status ));
        !          3744: 
        !          3745:         }
        !          3746:         break;
        !          3747: 
        !          3748:     case IOCTL_CDROM_READ_Q_CHANNEL:
        !          3749:         {
        !          3750:         PSUB_Q_CURRENT_POSITION userPtr =
        !          3751:             Irp->AssociatedIrp.SystemBuffer;
        !          3752:         PUCHAR SubQPtr =
        !          3753:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          3754:                             sizeof(SUB_Q_CHANNEL_DATA)
        !          3755:                            );
        !          3756: 
        !          3757:         CdDump(( 5,
        !          3758:                      "CdAudioDenonDeviceControl: IOCTL_CDROM_READ_Q_CHANNEL received.\n"
        !          3759:                      ));
        !          3760: 
        !          3761:         if (SubQPtr==NULL) {
        !          3762: 
        !          3763:             CdDump(( 1,
        !          3764:                          "CdAudioDenonDeviceControl: READ_Q_CHANNEL, SubQPtr==NULL!\n"
        !          3765:                          ));
        !          3766: 
        !          3767:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          3768:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          3769:             goto SetStatusAndReturn;
        !          3770: 
        !          3771:         }
        !          3772: 
        !          3773:         if ( ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format!=
        !          3774:              IOCTL_CDROM_CURRENT_POSITION) {
        !          3775: 
        !          3776:             CdDump(( 1,
        !          3777:                          "CdAudioDenonDeviceControl: READ_Q_CHANNEL, illegal Format (%d)\n",
        !          3778:                          ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format
        !          3779:                          ));
        !          3780: 
        !          3781:             ExFreePool( SubQPtr );
        !          3782:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          3783:             status = STATUS_UNSUCCESSFUL;
        !          3784:             goto SetStatusAndReturn;
        !          3785:         }
        !          3786: 
        !          3787:         //
        !          3788:         // Read audio play status
        !          3789:         //
        !          3790: 
        !          3791:         srb.CdbLength            = 6;
        !          3792:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          3793:         cdb->CDB6GENERIC.OperationCode = DENON_READ_SUB_Q_CHANNEL_CODE;
        !          3794:         cdb->CDB6GENERIC.CommandUniqueBytes[2] = 10; // Transfer Length
        !          3795:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3796:                                      &srb,
        !          3797:                                      SubQPtr,
        !          3798:                                      10,
        !          3799:                                      FALSE
        !          3800:                                     );
        !          3801:         if (NT_SUCCESS(status)) {
        !          3802: 
        !          3803:             userPtr->Header.Reserved = 0;
        !          3804: 
        !          3805:             if (deviceExtension->Paused==CDAUDIO_PAUSED) {
        !          3806: 
        !          3807:                 deviceExtension->PlayActive = FALSE;
        !          3808:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PAUSED;
        !          3809: 
        !          3810:             } else {
        !          3811: 
        !          3812:                 if (SubQPtr[0]==0x01)
        !          3813:                     userPtr->Header.AudioStatus = AUDIO_STATUS_IN_PROGRESS;
        !          3814:                 else if (SubQPtr[0]==0x00){
        !          3815:                     userPtr->Header.AudioStatus = AUDIO_STATUS_PLAY_COMPLETE;
        !          3816:                     deviceExtension->PlayActive = FALSE;
        !          3817: 
        !          3818:                 } else {
        !          3819:                     deviceExtension->PlayActive = FALSE;
        !          3820:                 }
        !          3821: 
        !          3822:             }
        !          3823: 
        !          3824:             userPtr->Header.DataLength[0] = 0;
        !          3825:             userPtr->Header.DataLength[0] = 12;
        !          3826: 
        !          3827:             userPtr->FormatCode = 0x01;
        !          3828:             userPtr->Control = SubQPtr[1];
        !          3829:             userPtr->ADR     = 0;
        !          3830:             userPtr->TrackNumber = BCD_TO_DEC(SubQPtr[2]);
        !          3831:             userPtr->IndexNumber = BCD_TO_DEC(SubQPtr[3]);
        !          3832:             userPtr->AbsoluteAddress[0] = 0;
        !          3833:             userPtr->AbsoluteAddress[1] = BCD_TO_DEC((SubQPtr[7]));
        !          3834:             userPtr->AbsoluteAddress[2] = BCD_TO_DEC((SubQPtr[8]));
        !          3835:             userPtr->AbsoluteAddress[3] = BCD_TO_DEC((SubQPtr[9]));
        !          3836:             userPtr->TrackRelativeAddress[0] = 0;
        !          3837:             userPtr->TrackRelativeAddress[1] = BCD_TO_DEC((SubQPtr[4]));
        !          3838:             userPtr->TrackRelativeAddress[2] = BCD_TO_DEC((SubQPtr[5]));
        !          3839:             userPtr->TrackRelativeAddress[3] = BCD_TO_DEC((SubQPtr[6]));
        !          3840:             Irp->IoStatus.Information = 16;
        !          3841: 
        !          3842:         } else {
        !          3843: 
        !          3844:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          3845:             CdDump(( 1,
        !          3846:                          "CdAudioDenonDeviceControl: READ_Q_CHANNEL failed (0x%08lX)\n",
        !          3847:                          status
        !          3848:                          ));
        !          3849: 
        !          3850: 
        !          3851:         }
        !          3852: 
        !          3853:         ExFreePool( SubQPtr );
        !          3854:         }
        !          3855:         break;
        !          3856: 
        !          3857:     case IOCTL_CDROM_EJECT_MEDIA:
        !          3858: 
        !          3859:         //
        !          3860:         // Build cdb to eject cartridge
        !          3861:         //
        !          3862: 
        !          3863:         CdDump(( 3,
        !          3864:                      "CdAudioDenonDeviceControl: IOCTL_CDROM_EJECT_MEDIA received.\n"
        !          3865:                      ));
        !          3866: 
        !          3867:         deviceExtension->PlayActive = FALSE;
        !          3868: 
        !          3869:         srb.CdbLength                  = 6;
        !          3870:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          3871:         cdb->CDB6GENERIC.OperationCode = DENON_EJECT_CODE;
        !          3872:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3873:                                      &srb,
        !          3874:                                      NULL,
        !          3875:                                      0,
        !          3876:                                      FALSE
        !          3877:                                     );
        !          3878:         break;
        !          3879: 
        !          3880:     case IOCTL_CDROM_GET_CONTROL:
        !          3881:     case IOCTL_CDROM_GET_VOLUME:
        !          3882:     case IOCTL_CDROM_SET_VOLUME:
        !          3883:         CdDump(( 3, "CdAudioDenonDeviceControl: Not Supported yet.\n" ));
        !          3884:         status = STATUS_INVALID_DEVICE_REQUEST;
        !          3885:         break;
        !          3886: 
        !          3887:     case IOCTL_CDROM_CHECK_VERIFY:
        !          3888: 
        !          3889:         //
        !          3890:         // Update the play active flag.
        !          3891:         //
        !          3892: 
        !          3893:         CdAudioIsPlayActive(DeviceObject);
        !          3894: 
        !          3895:     default:
        !          3896: 
        !          3897:         CdDump((5,"CdAudioDenonDeviceControl: Unsupported device IOCTL\n"));
        !          3898:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          3899:         break;
        !          3900: 
        !          3901:     } // end switch( IOCTL )
        !          3902: 
        !          3903: SetStatusAndReturn:
        !          3904:     //
        !          3905:     // set status code and return
        !          3906:     //
        !          3907: 
        !          3908:     if (status == STATUS_VERIFY_REQUIRED) {
        !          3909: 
        !          3910:         //
        !          3911:         // If the status is verified required and the this request
        !          3912:         // should bypass verify required then retry the request.
        !          3913:         //
        !          3914: 
        !          3915:         if (currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) {
        !          3916: 
        !          3917:             status = STATUS_IO_DEVICE_ERROR;
        !          3918:             goto DenonRestart;
        !          3919: 
        !          3920:         }
        !          3921: 
        !          3922: 
        !          3923:         IoSetHardErrorOrVerifyDevice( Irp,
        !          3924:                                       deviceExtension->TargetDeviceObject
        !          3925:                                      );
        !          3926: 
        !          3927:         Irp->IoStatus.Information = 0;
        !          3928:     }
        !          3929: 
        !          3930:     Irp->IoStatus.Status = status;
        !          3931:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          3932:     return status;
        !          3933: 
        !          3934: }
        !          3935: 
        !          3936: NTSTATUS
        !          3937: CdAudioHitatchiSendPauseCommand(
        !          3938:     IN PDEVICE_OBJECT DeviceObject
        !          3939:     )
        !          3940: 
        !          3941: /*++
        !          3942: 
        !          3943: Routine Description:
        !          3944: 
        !          3945:     This routine sends a PAUSE cdb to the Hitatchi drive.  The Hitatchi
        !          3946:     drive returns a "busy" condition whenever a play audio command is in
        !          3947:     progress...so we need to bump the drive out of audio play to issue
        !          3948:     a new command.  This routine is in place for this purpose.
        !          3949: 
        !          3950: Arguments:
        !          3951: 
        !          3952:     DeviceObject
        !          3953:     Irp
        !          3954: 
        !          3955: Return Value:
        !          3956: 
        !          3957:     NTSTATUS
        !          3958: 
        !          3959: --*/
        !          3960: 
        !          3961: {
        !          3962:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          3963:     SCSI_REQUEST_BLOCK srb;
        !          3964:     PCDB12             cdb = (PCDB12)srb.Cdb;
        !          3965:     NTSTATUS           status;
        !          3966:     PUCHAR             PausePos;
        !          3967: 
        !          3968:     //
        !          3969:     // Allocate buffer for pause data
        !          3970:     //
        !          3971: 
        !          3972:     PausePos = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned, 3 );
        !          3973: 
        !          3974:     if (PausePos==NULL) {
        !          3975: 
        !          3976:         return(STATUS_INSUFFICIENT_RESOURCES);
        !          3977: 
        !          3978:     }
        !          3979: 
        !          3980:     RtlZeroMemory( PausePos, 3 );
        !          3981: 
        !          3982:     //
        !          3983:     // Clear out cdb
        !          3984:     //
        !          3985: 
        !          3986:     RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          3987: 
        !          3988:     //
        !          3989:     // Clear audio play command so that next command will be issued
        !          3990:     //
        !          3991: 
        !          3992:     srb.CdbLength    = 12;
        !          3993:     srb.TimeOutValue = AUDIO_TIMEOUT;
        !          3994:     cdb->PAUSE_AUDIO.OperationCode = HITATCHI_PAUSE_AUDIO_CODE;
        !          3995:     status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          3996:                                  &srb,
        !          3997:                                  PausePos,
        !          3998:                                  3,
        !          3999:                                  FALSE
        !          4000:                                 );
        !          4001: 
        !          4002:     ExFreePool( PausePos );
        !          4003: 
        !          4004:     return status;
        !          4005: }
        !          4006: 
        !          4007: NTSTATUS
        !          4008: CdAudioHitatchiDeviceControl(
        !          4009:     IN PDEVICE_OBJECT DeviceObject,
        !          4010:     IN PIRP Irp
        !          4011:     )
        !          4012: 
        !          4013: /*++
        !          4014: 
        !          4015: Routine Description:
        !          4016: 
        !          4017:     This routine is called by CdAudioDeviceControl to handle
        !          4018:     audio IOCTLs sent to Hitatchi cdrom drives.
        !          4019: 
        !          4020: Arguments:
        !          4021: 
        !          4022:     DeviceObject
        !          4023:     Irp
        !          4024: 
        !          4025: Return Value:
        !          4026: 
        !          4027:     NTSTATUS
        !          4028: 
        !          4029: --*/
        !          4030: 
        !          4031: {
        !          4032:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          4033:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          4034:     PCDROM_TOC         cdaudioDataOut  = Irp->AssociatedIrp.SystemBuffer;
        !          4035:     SCSI_REQUEST_BLOCK srb;
        !          4036:     PCDB12             cdb = (PCDB12)srb.Cdb;
        !          4037:     NTSTATUS           status;
        !          4038:     ULONG              i,bytesTransfered;
        !          4039:     PUCHAR             Toc;
        !          4040: 
        !          4041: HitatchiRestart:
        !          4042: 
        !          4043:     //
        !          4044:     // Clear out cdb
        !          4045:     //
        !          4046: 
        !          4047:     RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          4048: 
        !          4049:     //
        !          4050:     // What IOCTL do we need to execute?
        !          4051:     //
        !          4052: 
        !          4053:     switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
        !          4054: 
        !          4055:     case IOCTL_CDROM_READ_TOC:
        !          4056:         CdDump(( 3,
        !          4057:                      "CdAudioHitatchiDeviceControl: IOCTL_CDROM_READ_TOC received.\n"
        !          4058:                      ));
        !          4059: 
        !          4060:         //
        !          4061:         // If the cd is playing music then reject this request.
        !          4062:         //
        !          4063: 
        !          4064:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          4065:             status = STATUS_DEVICE_BUSY;
        !          4066:             break;
        !          4067:         }
        !          4068: 
        !          4069:         //
        !          4070:         // Allocate storage to hold TOC from disc
        !          4071:         //
        !          4072: 
        !          4073:         Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !          4074:                                       CDROM_TOC_SIZE
        !          4075:                                      );
        !          4076: 
        !          4077:         if (Toc==NULL) {
        !          4078: 
        !          4079:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          4080:             goto SetStatusAndReturn;
        !          4081: 
        !          4082:         }
        !          4083: 
        !          4084:         //
        !          4085:         // Set up defaults
        !          4086:         //
        !          4087: 
        !          4088:         RtlZeroMemory( Toc, CDROM_TOC_SIZE );
        !          4089:         srb.CdbLength = 12;
        !          4090: 
        !          4091:         //
        !          4092:         // Fill in CDB
        !          4093:         //
        !          4094: 
        !          4095:         cdb->READ_DISC_INFO.OperationCode       = HITATCHI_READ_TOC_CODE;
        !          4096:         cdb->READ_DISC_INFO.AllocationLength[0] = CDROM_TOC_SIZE >> 8;
        !          4097:         cdb->READ_DISC_INFO.AllocationLength[1] = CDROM_TOC_SIZE & 0xFF;
        !          4098:         srb.TimeOutValue                        = AUDIO_TIMEOUT;
        !          4099:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4100:                                      &srb,
        !          4101:                                      Toc,
        !          4102:                                      CDROM_TOC_SIZE,
        !          4103:                                      FALSE
        !          4104:                                     );
        !          4105: 
        !          4106:         if (!NT_SUCCESS(status) && (status!=STATUS_DATA_OVERRUN)) {
        !          4107: 
        !          4108:             CdDump(( 1,
        !          4109:                 "CdAudioHitatchiDeviceControl: READ_TOC error (0x%08lX)\n",
        !          4110:                  status ));
        !          4111: 
        !          4112: 
        !          4113:             if (SRB_STATUS(srb.SrbStatus)!=SRB_STATUS_DATA_OVERRUN) {
        !          4114: 
        !          4115:                 CdDump(( 1, "CdAudioHitatchiDeviceControl: SRB ERROR (0x%lX)\n",
        !          4116:                              srb.SrbStatus ));
        !          4117:                 ExFreePool( Toc );
        !          4118:                 goto SetStatusAndReturn;
        !          4119:             }
        !          4120: 
        !          4121:         } else
        !          4122: 
        !          4123:             status = STATUS_SUCCESS;
        !          4124: 
        !          4125:         //
        !          4126:         // Translate data into our format
        !          4127:         //
        !          4128: 
        !          4129:         bytesTransfered =
        !          4130:             currentIrpStack->Parameters.Read.Length > sizeof(CDROM_TOC) ?
        !          4131:             sizeof(CDROM_TOC) : currentIrpStack->Parameters.Read.Length;
        !          4132:         Irp->IoStatus.Information  = bytesTransfered;
        !          4133:         cdaudioDataOut->Length[0]  = bytesTransfered >> 8;
        !          4134:         cdaudioDataOut->Length[1]  = (bytesTransfered & 0xFF);
        !          4135:         cdaudioDataOut->FirstTrack = Toc[2];
        !          4136:         cdaudioDataOut->LastTrack  = Toc[3];
        !          4137: 
        !          4138:         for( i=0;
        !          4139:              i<=( (ULONG)cdaudioDataOut->LastTrack -
        !          4140:                   (ULONG)cdaudioDataOut->FirstTrack   );
        !          4141:              i++
        !          4142:             ) {
        !          4143: 
        !          4144:             //
        !          4145:             // Grab Information for each track
        !          4146:             //
        !          4147: 
        !          4148:             cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          4149:             cdaudioDataOut->TrackData[i].Control     =
        !          4150:                 ((Toc[(i*4)+8] & 0x0F) << 4) | (Toc[(i*4)+8] >> 4);
        !          4151:             cdaudioDataOut->TrackData[i].TrackNumber =
        !          4152:                 (i + cdaudioDataOut->FirstTrack);
        !          4153: 
        !          4154:             cdaudioDataOut->TrackData[i].Reserved1 =  0;
        !          4155:             cdaudioDataOut->TrackData[i].Address[0] = 0;
        !          4156:             cdaudioDataOut->TrackData[i].Address[1] = Toc[(i*4)+9];
        !          4157:             cdaudioDataOut->TrackData[i].Address[2] = Toc[(i*4)+10];
        !          4158:             cdaudioDataOut->TrackData[i].Address[3] = Toc[(i*4)+11];
        !          4159: 
        !          4160:         }
        !          4161: 
        !          4162:         //
        !          4163:         // Fake "lead out track" info
        !          4164:         //
        !          4165: 
        !          4166:         cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          4167:         cdaudioDataOut->TrackData[i].Control     = 0x10;
        !          4168:         cdaudioDataOut->TrackData[i].TrackNumber = 0xaa;
        !          4169:         cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          4170:         cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          4171:         cdaudioDataOut->TrackData[i].Address[1]  = Toc[5];
        !          4172:         cdaudioDataOut->TrackData[i].Address[2]  = Toc[6];
        !          4173:         cdaudioDataOut->TrackData[i].Address[3]  = Toc[7];
        !          4174: 
        !          4175:         //
        !          4176:         // Clear out device extension data
        !          4177:         //
        !          4178: 
        !          4179:         deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          4180:         deviceExtension->PausedM = 0;
        !          4181:         deviceExtension->PausedS = 0;
        !          4182:         deviceExtension->PausedF = 0;
        !          4183:         deviceExtension->LastEndM = 0;
        !          4184:         deviceExtension->LastEndS = 0;
        !          4185:         deviceExtension->LastEndF = 0;
        !          4186: 
        !          4187:         //
        !          4188:         // Free storage now that we've stored it elsewhere
        !          4189:         //
        !          4190: 
        !          4191:         ExFreePool( Toc );
        !          4192:         break;
        !          4193: 
        !          4194:     case IOCTL_CDROM_STOP_AUDIO:
        !          4195: 
        !          4196:         deviceExtension->PlayActive = FALSE;
        !          4197: 
        !          4198:         //
        !          4199:         // Kill any current play operation
        !          4200:         //
        !          4201: 
        !          4202:         CdAudioHitatchiSendPauseCommand( DeviceObject );
        !          4203: 
        !          4204:         //
        !          4205:         // Same as scsi-2 spec, so just send to default driver
        !          4206:         //
        !          4207: 
        !          4208:         deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          4209:         deviceExtension->PausedM = 0;
        !          4210:         deviceExtension->PausedS = 0;
        !          4211:         deviceExtension->PausedF = 0;
        !          4212:         deviceExtension->LastEndM = 0;
        !          4213:         deviceExtension->LastEndS = 0;
        !          4214:         deviceExtension->LastEndF = 0;
        !          4215: 
        !          4216:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          4217:         break;
        !          4218: 
        !          4219:     case IOCTL_CDROM_PLAY_AUDIO_MSF:
        !          4220:         {
        !          4221: 
        !          4222:         PCDROM_PLAY_AUDIO_MSF inputBuffer =
        !          4223:             Irp->AssociatedIrp.SystemBuffer;
        !          4224: 
        !          4225:         CdDump(( 3,
        !          4226:             "CdAudioHitatchiDeviceControl: IOCTL_CDROM_PLAY_AUDIO_MSF received.\n"
        !          4227:             ));
        !          4228: 
        !          4229:         //
        !          4230:         // Kill any current play operation
        !          4231:         //
        !          4232: 
        !          4233:         CdAudioHitatchiSendPauseCommand( DeviceObject );
        !          4234: 
        !          4235:         //
        !          4236:         // Fill in CDB for PLAY operation
        !          4237:         //
        !          4238: 
        !          4239:         srb.CdbLength                 = 12;
        !          4240:         srb.TimeOutValue              = AUDIO_TIMEOUT;
        !          4241:         cdb->PLAY_AUDIO.OperationCode = HITATCHI_PLAY_AUDIO_MSF_CODE;
        !          4242:         cdb->PLAY_AUDIO.Immediate     = 1;
        !          4243:         cdb->PLAY_AUDIO.StartingM     = inputBuffer->StartingM;
        !          4244:         cdb->PLAY_AUDIO.StartingS     = inputBuffer->StartingS;
        !          4245:         cdb->PLAY_AUDIO.StartingF     = inputBuffer->StartingF;
        !          4246:         cdb->PLAY_AUDIO.EndingM       = inputBuffer->EndingM;
        !          4247:         cdb->PLAY_AUDIO.EndingS       = inputBuffer->EndingS;
        !          4248:         cdb->PLAY_AUDIO.EndingF       = inputBuffer->EndingF;
        !          4249:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4250:                                      &srb,
        !          4251:                                      NULL,
        !          4252:                                      0,
        !          4253:                                      FALSE
        !          4254:                                     );
        !          4255: 
        !          4256:         if (NT_SUCCESS(status)) {
        !          4257: 
        !          4258:             //
        !          4259:             // Indicate the play actition is active.
        !          4260:             //
        !          4261: 
        !          4262:             deviceExtension->PlayActive = TRUE;
        !          4263: 
        !          4264:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          4265: 
        !          4266: 
        !          4267:             //
        !          4268:             // Set last play ending address for next pause command
        !          4269:             //
        !          4270: 
        !          4271:             deviceExtension->PausedM  = inputBuffer->StartingM;
        !          4272:             deviceExtension->PausedS  = inputBuffer->StartingS;
        !          4273:             deviceExtension->PausedF  = inputBuffer->StartingF;
        !          4274:             deviceExtension->LastEndM = inputBuffer->EndingM;
        !          4275:             deviceExtension->LastEndS = inputBuffer->EndingS;
        !          4276:             deviceExtension->LastEndF = inputBuffer->EndingF;
        !          4277: 
        !          4278:         } else {
        !          4279: 
        !          4280:             CdDump(( 3,
        !          4281:                 "CdAudioHitatchiDeviceControl: PLAY failed (0x%08lX)\n",
        !          4282:                 status ));
        !          4283:         }
        !          4284: 
        !          4285:         }
        !          4286:         break;
        !          4287: 
        !          4288:     case IOCTL_CDROM_SEEK_AUDIO_MSF:
        !          4289:         {
        !          4290: 
        !          4291:         PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          4292: 
        !          4293:         CdDump(( 3,
        !          4294:             "CdAudioHitatchiDeviceControl: IOCTL_CDROM_SEEK_AUDIO_MSF received.\n"
        !          4295:              ));
        !          4296: 
        !          4297:         //
        !          4298:         // Kill any current play operation
        !          4299:         //
        !          4300: 
        !          4301:         CdAudioHitatchiSendPauseCommand( DeviceObject );
        !          4302: 
        !          4303:         //
        !          4304:         // seek to MSF and enter pause (still) mode.
        !          4305:         //
        !          4306: 
        !          4307:         //
        !          4308:         // Fill in CDB for PLAY operation
        !          4309:         //
        !          4310: 
        !          4311:         srb.CdbLength                 = 12;
        !          4312:         srb.TimeOutValue              = AUDIO_TIMEOUT;
        !          4313:         cdb->PLAY_AUDIO.OperationCode = HITATCHI_PLAY_AUDIO_MSF_CODE;
        !          4314:         cdb->PLAY_AUDIO.Immediate     = 1;
        !          4315:         cdb->PLAY_AUDIO.StartingM     = inputBuffer->M;
        !          4316:         cdb->PLAY_AUDIO.StartingS     = inputBuffer->S;
        !          4317:         cdb->PLAY_AUDIO.StartingF     = inputBuffer->F;
        !          4318:         cdb->PLAY_AUDIO.EndingM       = inputBuffer->M;
        !          4319:         cdb->PLAY_AUDIO.EndingS       = inputBuffer->S;
        !          4320:         cdb->PLAY_AUDIO.EndingF       = inputBuffer->F;
        !          4321: 
        !          4322:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4323:                                      &srb,
        !          4324:                                      NULL,
        !          4325:                                      0,
        !          4326:                                      FALSE
        !          4327:                                     );
        !          4328:         if (NT_SUCCESS(status)) {
        !          4329: 
        !          4330:             deviceExtension->PausedM = inputBuffer->M;
        !          4331:             deviceExtension->PausedS = inputBuffer->S;
        !          4332:             deviceExtension->PausedF = inputBuffer->F;
        !          4333:             deviceExtension->LastEndM = inputBuffer->M;
        !          4334:             deviceExtension->LastEndS = inputBuffer->S;
        !          4335:             deviceExtension->LastEndF = inputBuffer->F;
        !          4336: 
        !          4337:         } else {
        !          4338: 
        !          4339:             CdDump(( 3,
        !          4340:                 "CdAudioHitatchiDeviceControl: SEEK failed (0x%08lX)\n",
        !          4341:                 status ));
        !          4342:         }
        !          4343: 
        !          4344:         }
        !          4345:         break;
        !          4346: 
        !          4347:     case IOCTL_CDROM_PAUSE_AUDIO:
        !          4348:         {
        !          4349: 
        !          4350:         PUCHAR PausePos = ExAllocatePool( NonPagedPoolCacheAligned, 3 );
        !          4351:         if (PausePos==NULL) {
        !          4352: 
        !          4353:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          4354:             goto SetStatusAndReturn;
        !          4355: 
        !          4356:         }
        !          4357: 
        !          4358:         deviceExtension->PlayActive = FALSE;
        !          4359: 
        !          4360:         RtlZeroMemory( PausePos, 3 );
        !          4361: 
        !          4362:         CdDump(( 3,
        !          4363:             "CdAudioHitatchiDeviceControl: IOCTL_CDROM_PAUSE_AUDIO received.\n"
        !          4364:             ));
        !          4365: 
        !          4366:         //
        !          4367:         // Enter pause (still ) mode
        !          4368:         //
        !          4369: 
        !          4370:         srb.CdbLength    = 12;
        !          4371:         srb.TimeOutValue = AUDIO_TIMEOUT;
        !          4372:         cdb->PAUSE_AUDIO.OperationCode = HITATCHI_PAUSE_AUDIO_CODE;
        !          4373:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4374:                                      &srb,
        !          4375:                                      PausePos,
        !          4376:                                      3,
        !          4377:                                      FALSE
        !          4378:                                     );
        !          4379: 
        !          4380:         deviceExtension->Paused = CDAUDIO_PAUSED;
        !          4381:         deviceExtension->PausedM = PausePos[0];
        !          4382:         deviceExtension->PausedS = PausePos[1];
        !          4383:         deviceExtension->PausedF = PausePos[2];
        !          4384: 
        !          4385:         ExFreePool( PausePos );
        !          4386:         }
        !          4387:         break;
        !          4388: 
        !          4389:     case IOCTL_CDROM_RESUME_AUDIO:
        !          4390: 
        !          4391:         CdDump(( 3,
        !          4392:             "CdAudioHitatchiDeviceControl: IOCTL_CDROM_RESUME_AUDIO received.\n"
        !          4393:             ));
        !          4394: 
        !          4395:         //
        !          4396:         // Kill any current play operation
        !          4397:         //
        !          4398: 
        !          4399:         CdAudioHitatchiSendPauseCommand( DeviceObject );
        !          4400: 
        !          4401:         //
        !          4402:         // Resume play
        !          4403:         //
        !          4404: 
        !          4405:         //
        !          4406:         // Fill in CDB for PLAY operation
        !          4407:         //
        !          4408: 
        !          4409:         srb.CdbLength    = 12;
        !          4410:         srb.TimeOutValue = AUDIO_TIMEOUT;
        !          4411:         cdb->PLAY_AUDIO.OperationCode = HITATCHI_PLAY_AUDIO_MSF_CODE;
        !          4412:         cdb->PLAY_AUDIO.Immediate     = 1;
        !          4413:         cdb->PLAY_AUDIO.StartingM     = deviceExtension->PausedM;
        !          4414:         cdb->PLAY_AUDIO.StartingS     = deviceExtension->PausedS;
        !          4415:         cdb->PLAY_AUDIO.StartingF     = deviceExtension->PausedF;
        !          4416:         cdb->PLAY_AUDIO.EndingM       = deviceExtension->LastEndM;
        !          4417:         cdb->PLAY_AUDIO.EndingS       = deviceExtension->LastEndS;
        !          4418:         cdb->PLAY_AUDIO.EndingF       = deviceExtension->LastEndF;
        !          4419:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4420:                                      &srb,
        !          4421:                                      NULL,
        !          4422:                                      0,
        !          4423:                                      FALSE
        !          4424:                                     );
        !          4425: 
        !          4426:         if (NT_SUCCESS(status)) {
        !          4427: 
        !          4428:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          4429: 
        !          4430:         }
        !          4431: 
        !          4432:         break;
        !          4433: 
        !          4434:     case IOCTL_CDROM_READ_Q_CHANNEL:
        !          4435:         {
        !          4436: 
        !          4437:         PSUB_Q_CURRENT_POSITION userPtr =
        !          4438:             Irp->AssociatedIrp.SystemBuffer;
        !          4439:         PUCHAR SubQPtr =
        !          4440:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          4441:                             sizeof(SUB_Q_CHANNEL_DATA)
        !          4442:                            );
        !          4443: 
        !          4444:         CdDump(( 5,
        !          4445:             "CdAudioHitatchiDeviceControl: IOCTL_CDROM_READ_Q_CHANNEL received.\n"
        !          4446:             ));
        !          4447: 
        !          4448:         if (SubQPtr==NULL) {
        !          4449: 
        !          4450:             CdDump(( 1,
        !          4451:                 "CdAudioHitatchiDeviceControl: READ_Q_CHANNEL, SubQPtr==NULL!\n"
        !          4452:                 ));
        !          4453: 
        !          4454:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          4455:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          4456:             goto SetStatusAndReturn;
        !          4457: 
        !          4458:         }
        !          4459: 
        !          4460:         if ( ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format!=
        !          4461:              IOCTL_CDROM_CURRENT_POSITION) {
        !          4462: 
        !          4463:             CdDump(( 1,
        !          4464:                 "CdAudioHitatchiDeviceControl: READ_Q_CHANNEL, illegal Format (%d)\n",
        !          4465:                 ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format
        !          4466:                 ));
        !          4467: 
        !          4468:             ExFreePool( SubQPtr );
        !          4469:             status = STATUS_UNSUCCESSFUL;
        !          4470:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          4471:             goto SetStatusAndReturn;
        !          4472:         }
        !          4473: 
        !          4474:         //
        !          4475:         // Set up to read Q Channel
        !          4476:         //
        !          4477: 
        !          4478:         srb.CdbLength            = 12;
        !          4479:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          4480:         cdb->AUDIO_STATUS.OperationCode = HITATCHI_READ_SUB_Q_CHANNEL_CODE;
        !          4481:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4482:                                      &srb,
        !          4483:                                      SubQPtr,
        !          4484:                                      sizeof(SUB_Q_CHANNEL_DATA),
        !          4485:                                      FALSE
        !          4486:                                     );
        !          4487:         if ((NT_SUCCESS(status)) || (status==STATUS_DATA_OVERRUN)) {
        !          4488: 
        !          4489:             userPtr->Header.Reserved = 0;
        !          4490:             if (deviceExtension->Paused == CDAUDIO_PAUSED) {
        !          4491:             
        !          4492:                 deviceExtension->PlayActive = FALSE;
        !          4493:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PAUSED;
        !          4494:             } else {
        !          4495:                 if (SubQPtr[0]==0x01)
        !          4496:                     userPtr->Header.AudioStatus = AUDIO_STATUS_IN_PROGRESS;
        !          4497:                 else if (SubQPtr[0]==0x00){
        !          4498:                     userPtr->Header.AudioStatus = AUDIO_STATUS_PLAY_COMPLETE;
        !          4499:                     deviceExtension->PlayActive = FALSE;
        !          4500: 
        !          4501:                 } else {
        !          4502:                     deviceExtension->PlayActive = FALSE;
        !          4503:                 }
        !          4504:             }
        !          4505:             userPtr->Header.DataLength[0] = 0;
        !          4506:             userPtr->Header.DataLength[0] = 12;
        !          4507: 
        !          4508:             userPtr->FormatCode = 0x01;
        !          4509:             userPtr->Control = ((SubQPtr[1] & 0xF0) >> 4);
        !          4510:             userPtr->ADR     = SubQPtr[1] & 0x0F;
        !          4511:             userPtr->TrackNumber = SubQPtr[2];
        !          4512:             userPtr->IndexNumber = SubQPtr[3];
        !          4513:             userPtr->AbsoluteAddress[0] = 0;
        !          4514:             userPtr->AbsoluteAddress[1] = SubQPtr[8];
        !          4515:             userPtr->AbsoluteAddress[2] = SubQPtr[9];
        !          4516:             userPtr->AbsoluteAddress[3] = SubQPtr[10];
        !          4517:             userPtr->TrackRelativeAddress[0] = 0;
        !          4518:             userPtr->TrackRelativeAddress[1] = SubQPtr[4];
        !          4519:             userPtr->TrackRelativeAddress[2] = SubQPtr[5];
        !          4520:             userPtr->TrackRelativeAddress[3] = SubQPtr[6];
        !          4521:             Irp->IoStatus.Information = 16;
        !          4522:             status = STATUS_SUCCESS;
        !          4523: 
        !          4524:         } else {
        !          4525: 
        !          4526:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          4527:             CdDump(( 1,
        !          4528:                 "CdAudioHitatchiDeviceControl: READ_Q_CHANNEL failed (0x%08lX)\n",
        !          4529:                 status
        !          4530:                 ));
        !          4531: 
        !          4532:         }
        !          4533: 
        !          4534:         ExFreePool( SubQPtr );
        !          4535: 
        !          4536:         }
        !          4537:         break;
        !          4538: 
        !          4539:     case IOCTL_CDROM_EJECT_MEDIA:
        !          4540:         {
        !          4541: 
        !          4542:         PUCHAR EjectStatus = ExAllocatePool( NonPagedPoolCacheAligned, 1 );
        !          4543: 
        !          4544:         if (EjectStatus==NULL) {
        !          4545: 
        !          4546:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          4547:             goto SetStatusAndReturn;
        !          4548: 
        !          4549:         }
        !          4550: 
        !          4551:         deviceExtension->PlayActive = FALSE;
        !          4552: 
        !          4553:         CdDump(( 3,
        !          4554:             "CdAudioHitatchiDeviceControl: IOCTL_CDROM_EJECT_MEDIA received.\n"
        !          4555:             ));
        !          4556: 
        !          4557:         //
        !          4558:         // Set up to EJECT disc
        !          4559:         //
        !          4560: 
        !          4561:         srb.CdbLength            = 12;
        !          4562:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          4563:         cdb->EJECT.OperationCode = HITATCHI_EJECT_CODE;
        !          4564:         cdb->EJECT.Eject         = 1;  // Set Eject flag
        !          4565:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4566:                                      &srb,
        !          4567:                                      EjectStatus,
        !          4568:                                      1,
        !          4569:                                      FALSE
        !          4570:                                     );
        !          4571:         if (NT_SUCCESS(status)) {
        !          4572: 
        !          4573:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          4574:             deviceExtension->PausedM = 0;
        !          4575:             deviceExtension->PausedS = 0;
        !          4576:             deviceExtension->PausedF = 0;
        !          4577:             deviceExtension->LastEndM = 0;
        !          4578:             deviceExtension->LastEndS = 0;
        !          4579:             deviceExtension->LastEndF = 0;
        !          4580: 
        !          4581:         }
        !          4582: 
        !          4583:         ExFreePool( EjectStatus );
        !          4584:         }
        !          4585:         break;
        !          4586: 
        !          4587:     case IOCTL_CDROM_GET_CONTROL:
        !          4588:     case IOCTL_CDROM_GET_VOLUME:
        !          4589:     case IOCTL_CDROM_SET_VOLUME:
        !          4590: 
        !          4591:         CdDump(( 3, "CdAudioHitatchieviceControl: Not Supported yet.\n" ));
        !          4592:         status = STATUS_INVALID_DEVICE_REQUEST;
        !          4593:         break;
        !          4594: 
        !          4595:     case IOCTL_CDROM_CHECK_VERIFY:
        !          4596: 
        !          4597:         //
        !          4598:         // Update the play active flag.
        !          4599:         //
        !          4600: 
        !          4601:         CdAudioIsPlayActive(DeviceObject);
        !          4602: 
        !          4603:     default:
        !          4604: 
        !          4605:         CdDump((5,"CdAudioHitatchiDeviceControl: Unsupported device IOCTL\n"));
        !          4606:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          4607:         break;
        !          4608: 
        !          4609:     } // end switch( IOCTL )
        !          4610: 
        !          4611: SetStatusAndReturn:
        !          4612: 
        !          4613:     //
        !          4614:     // set status code and return
        !          4615:     //
        !          4616: 
        !          4617:     if (status == STATUS_VERIFY_REQUIRED) {
        !          4618: 
        !          4619:         //
        !          4620:         // If the status is verified required and the this request
        !          4621:         // should bypass verify required then retry the request.
        !          4622:         //
        !          4623: 
        !          4624:         if (currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) {
        !          4625: 
        !          4626:             status = STATUS_IO_DEVICE_ERROR;
        !          4627:             goto HitatchiRestart;
        !          4628: 
        !          4629:         }
        !          4630: 
        !          4631: 
        !          4632:         IoSetHardErrorOrVerifyDevice( Irp,
        !          4633:                                       deviceExtension->TargetDeviceObject
        !          4634:                                      );
        !          4635: 
        !          4636:         Irp->IoStatus.Information = 0;
        !          4637:     }
        !          4638: 
        !          4639:     Irp->IoStatus.Status = status;
        !          4640:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          4641:     return status;
        !          4642: 
        !          4643: }
        !          4644: 
        !          4645: NTSTATUS
        !          4646: CdAudio535DeviceControl(
        !          4647:     PDEVICE_OBJECT DeviceObject,
        !          4648:     PIRP Irp
        !          4649:     )
        !          4650: 
        !          4651: /*++
        !          4652: 
        !          4653: Routine Description:
        !          4654: 
        !          4655:     This routine is called by CdAudioDeviceControl to handle
        !          4656:     audio IOCTLs sent to Chinon CDS-535 cdrom drive.
        !          4657: 
        !          4658: Arguments:
        !          4659: 
        !          4660:     DeviceObject
        !          4661:     Irp
        !          4662: 
        !          4663: Return Value:
        !          4664: 
        !          4665:     NTSTATUS
        !          4666: 
        !          4667: --*/
        !          4668: 
        !          4669: {
        !          4670:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          4671:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          4672:     PCDROM_TOC         cdaudioDataOut  = Irp->AssociatedIrp.SystemBuffer;
        !          4673:     SCSI_REQUEST_BLOCK srb;
        !          4674:     PREAD_CAPACITY_DATA lastSession;
        !          4675:     PCDB               cdb = (PCDB)srb.Cdb;
        !          4676:     NTSTATUS           status;
        !          4677:     ULONG              i,bytesTransfered;
        !          4678:     PUCHAR             Toc;
        !          4679:     ULONG              retry;
        !          4680:     ULONG              destblock;
        !          4681: 
        !          4682: 
        !          4683:     //
        !          4684:     // Clear out cdb
        !          4685:     //
        !          4686: 
        !          4687:     RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          4688: 
        !          4689:     //
        !          4690:     // What IOCTL do we need to execute?
        !          4691:     //
        !          4692: 
        !          4693:     switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
        !          4694: 
        !          4695:     case IOCTL_CDROM_GET_LAST_SESSION:
        !          4696: 
        !          4697:         //
        !          4698:         // If the cd is playing music then reject this request.
        !          4699:         //
        !          4700: 
        !          4701:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          4702:             status = STATUS_DEVICE_BUSY;
        !          4703:             break;
        !          4704:         }
        !          4705: 
        !          4706:         if (currentIrpStack->Parameters.Read.Length <
        !          4707:             FIELD_OFFSET(CDROM_TOC, TrackData[1])) {
        !          4708:             status = STATUS_INFO_LENGTH_MISMATCH;
        !          4709:             break;
        !          4710:             
        !          4711:         }
        !          4712: 
        !          4713:         // Allocate storage to hold lastSession from disc
        !          4714:         //
        !          4715: 
        !          4716:         lastSession = ExAllocatePool( NonPagedPoolCacheAligned,
        !          4717:                                       sizeof(READ_CAPACITY_DATA)
        !          4718:                                      );
        !          4719: 
        !          4720:         if (lastSession==NULL) {
        !          4721: 
        !          4722:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          4723:             goto SetStatusAndReturn;
        !          4724: 
        !          4725:         }
        !          4726: 
        !          4727:         //
        !          4728:         // Set up defaults
        !          4729:         //
        !          4730: 
        !          4731:         RtlZeroMemory( lastSession, sizeof(READ_CAPACITY_DATA));
        !          4732:         srb.CdbLength = 10;
        !          4733: 
        !          4734:         //
        !          4735:         // Fill in CDB
        !          4736:         //
        !          4737: 
        !          4738:         cdb->CDB10.OperationCode = CDS535_GET_LAST_SESSION;
        !          4739:         srb.TimeOutValue      = AUDIO_TIMEOUT;
        !          4740:         status = ScsiClassSendSrbSynchronous(
        !          4741:                                      deviceExtension->DeviceObject,
        !          4742:                                      &srb,
        !          4743:                                      lastSession,
        !          4744:                                      sizeof(READ_CAPACITY_DATA),
        !          4745:                                      FALSE
        !          4746:                                     );
        !          4747: 
        !          4748:         if (!NT_SUCCESS(status)) {
        !          4749: 
        !          4750:             CdDump(( 1,
        !          4751:                 "CdAudio535DeviceControl: READ_TOC error (0x%08lX)\n",
        !          4752:                  status ));
        !          4753: 
        !          4754: 
        !          4755:             ExFreePool( lastSession );
        !          4756:             goto SetStatusAndReturn;
        !          4757: 
        !          4758:         } else {
        !          4759: 
        !          4760:             status = STATUS_SUCCESS;
        !          4761:         }
        !          4762: 
        !          4763:         //
        !          4764:         // Translate data into our format.
        !          4765:         //
        !          4766: 
        !          4767:         bytesTransfered = FIELD_OFFSET(CDROM_TOC, TrackData[1]);
        !          4768:         Irp->IoStatus.Information = bytesTransfered;
        !          4769: 
        !          4770:         RtlZeroMemory(cdaudioDataOut, bytesTransfered);
        !          4771:         
        !          4772:         cdaudioDataOut->Length[0]  = bytesTransfered >> 8;
        !          4773:         cdaudioDataOut->Length[1]  = (bytesTransfered & 0xFF);
        !          4774: 
        !          4775:         //
        !          4776:         // Determine if this is a multisession cd.
        !          4777:         //
        !          4778: 
        !          4779:         if (lastSession->LogicalBlockAddress == 0) {
        !          4780: 
        !          4781:             //
        !          4782:             // This is a single session disk.  Just return.
        !          4783:             //
        !          4784: 
        !          4785:             ExFreePool(lastSession);
        !          4786:             break;
        !          4787:         }
        !          4788: 
        !          4789:         //
        !          4790:         // Fake the session information.
        !          4791:         //
        !          4792:         
        !          4793:         cdaudioDataOut->FirstTrack = 1;
        !          4794:         cdaudioDataOut->LastTrack  = 2;
        !          4795: 
        !          4796:         CdDump(( 4,
        !          4797:                      "CdAudio535DeviceControl: Tracks %d - %d, (0x%lX bytes)\n",
        !          4798:                      cdaudioDataOut->FirstTrack,
        !          4799:                      cdaudioDataOut->LastTrack,
        !          4800:                      bytesTransfered
        !          4801:                      ));
        !          4802: 
        !          4803: 
        !          4804:         //
        !          4805:         // Grab Information for the last session.
        !          4806:         //
        !          4807: 
        !          4808:         *((ULONG *)&cdaudioDataOut->TrackData[0].Address[0]) =
        !          4809:             lastSession->LogicalBlockAddress;
        !          4810: 
        !          4811:         //
        !          4812:         // Free storage now that we've stored it elsewhere
        !          4813:         //
        !          4814: 
        !          4815:         ExFreePool( lastSession );
        !          4816:         break;
        !          4817: 
        !          4818: 
        !          4819:     case IOCTL_CDROM_READ_TOC:
        !          4820:         CdDump(( 3,
        !          4821:                      "CdAudio535DeviceControl: IOCTL_CDROM_READ_TOC received.\n"
        !          4822:                      ));
        !          4823: 
        !          4824: 
        !          4825:         //
        !          4826:         // If the cd is playing music then reject this request.
        !          4827:         //
        !          4828: 
        !          4829:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          4830:             status = STATUS_DEVICE_BUSY;
        !          4831:             break;
        !          4832:         }
        !          4833: 
        !          4834:         //
        !          4835:         // Allocate storage to hold TOC from disc
        !          4836:         //
        !          4837: 
        !          4838:         Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !          4839:                                       CDROM_TOC_SIZE
        !          4840:                                      );
        !          4841: 
        !          4842:         if (Toc==NULL) {
        !          4843: 
        !          4844:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          4845:             goto SetStatusAndReturn;
        !          4846: 
        !          4847:         }
        !          4848: 
        !          4849:         //
        !          4850:         // Set up defaults
        !          4851:         //
        !          4852: 
        !          4853:         RtlZeroMemory( Toc, CDROM_TOC_SIZE );
        !          4854: 
        !          4855:         //
        !          4856:         // Fill in cdb for this operation
        !          4857:         //
        !          4858: 
        !          4859:         cdb->CDB10.OperationCode = CDS535_READ_TOC_CODE;
        !          4860:         cdb->CDB10.Reserved1 = 1;       // MSF mode
        !          4861:         cdb->CDB10.TransferBlocksMsb = (CDROM_TOC_SIZE >> 8);
        !          4862:         cdb->CDB10.TransferBlocksLsb = (CDROM_TOC_SIZE & 0xFF);
        !          4863:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          4864:         srb.CdbLength                  = 10;
        !          4865:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4866:                                      &srb,
        !          4867:                                      Toc,
        !          4868:                                      CDROM_TOC_SIZE,
        !          4869:                                      FALSE
        !          4870:                                     );
        !          4871: 
        !          4872:         if (!NT_SUCCESS(status) && (status!=STATUS_DATA_OVERRUN)) {
        !          4873: 
        !          4874:             CdDump(( 1,
        !          4875:                 "CdAudio535DeviceControl: READ_TOC error (0x%08lX)\n",
        !          4876:                  status ));
        !          4877: 
        !          4878:             if (SRB_STATUS(srb.SrbStatus)!=SRB_STATUS_DATA_OVERRUN) {
        !          4879: 
        !          4880:                 CdDump(( 1, "CdAudio535DeviceControl: SRB ERROR (0x%lX)\n",
        !          4881:                              srb.SrbStatus ));
        !          4882:                 ExFreePool( Toc );
        !          4883:                 goto SetStatusAndReturn;
        !          4884:             }
        !          4885: 
        !          4886:         } else {
        !          4887: 
        !          4888:             status = STATUS_SUCCESS;
        !          4889:         }
        !          4890: 
        !          4891:         //
        !          4892:         // Translate data into SCSI-II format
        !          4893:         //   (track numbers, except 0xAA, must be converted from BCD)
        !          4894: 
        !          4895:         bytesTransfered =
        !          4896:             currentIrpStack->Parameters.Read.Length > sizeof(CDROM_TOC) ?
        !          4897:             sizeof(CDROM_TOC) : currentIrpStack->Parameters.Read.Length;
        !          4898:         Irp->IoStatus.Information  = bytesTransfered;
        !          4899: 
        !          4900:         cdaudioDataOut->Length[0]  = Toc[0];
        !          4901:         cdaudioDataOut->Length[1]  = Toc[1];
        !          4902:         cdaudioDataOut->FirstTrack = BCD_TO_DEC(Toc[2]);
        !          4903:         cdaudioDataOut->LastTrack  = BCD_TO_DEC(Toc[3]);
        !          4904: 
        !          4905:         for( i=0;
        !          4906:              i<=( (ULONG)cdaudioDataOut->LastTrack -
        !          4907:                   (ULONG)cdaudioDataOut->FirstTrack   );
        !          4908:              i++
        !          4909:             ) {
        !          4910: 
        !          4911:             //
        !          4912:             // Grab Information for each track
        !          4913:             //
        !          4914: 
        !          4915:             cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          4916:             cdaudioDataOut->TrackData[i].Control     = Toc[(i*8)+4+1];
        !          4917:             cdaudioDataOut->TrackData[i].TrackNumber = BCD_TO_DEC(Toc[(i*8)+4+2]);
        !          4918:             cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          4919:             cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          4920:             cdaudioDataOut->TrackData[i].Address[1]  = Toc[(i*8)+4+5];
        !          4921:             cdaudioDataOut->TrackData[i].Address[2]  = Toc[(i*8)+4+6];
        !          4922:             cdaudioDataOut->TrackData[i].Address[3]  = Toc[(i*8)+4+7];
        !          4923: 
        !          4924:         }
        !          4925: 
        !          4926:         //
        !          4927:         // Copy "lead out track" info
        !          4928:         //
        !          4929: 
        !          4930:         cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          4931:         cdaudioDataOut->TrackData[i].Control     = Toc[(i*8)+4+1];
        !          4932:         cdaudioDataOut->TrackData[i].TrackNumber = Toc[(i*8)+4+2];  /* leave as 0xAA */
        !          4933:         cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          4934:         cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          4935:         cdaudioDataOut->TrackData[i].Address[1]  = Toc[(i*8)+4+5];
        !          4936:         cdaudioDataOut->TrackData[i].Address[2]  = Toc[(i*8)+4+6];
        !          4937:         cdaudioDataOut->TrackData[i].Address[3]  = Toc[(i*8)+4+7];
        !          4938: 
        !          4939:         //
        !          4940:         // Free storage now that we've stored it elsewhere
        !          4941:         //
        !          4942: 
        !          4943:         ExFreePool( Toc );
        !          4944:         break;
        !          4945: 
        !          4946:     case IOCTL_CDROM_READ_Q_CHANNEL:
        !          4947:         {
        !          4948:         PSUB_Q_CURRENT_POSITION userPtr =
        !          4949:             Irp->AssociatedIrp.SystemBuffer;
        !          4950:         PUCHAR SubQPtr =
        !          4951:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          4952:                             sizeof(SUB_Q_CURRENT_POSITION)
        !          4953:                            );
        !          4954: 
        !          4955:         CdDump(( 5,
        !          4956:                      "CdAudio535DeviceControl: IOCTL_CDROM_READ_Q_CHANNEL received.\n"
        !          4957:                      ));
        !          4958: 
        !          4959:         if (SubQPtr==NULL) {
        !          4960: 
        !          4961:             CdDump(( 1,
        !          4962:                          "CdAudio535DeviceControl: READ_Q_CHANNEL, SubQPtr==NULL!\n"
        !          4963:                          ));
        !          4964: 
        !          4965:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          4966:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          4967:             goto SetStatusAndReturn;
        !          4968: 
        !          4969:         }
        !          4970: 
        !          4971:         if ( ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format!=
        !          4972:              IOCTL_CDROM_CURRENT_POSITION) {
        !          4973: 
        !          4974:             CdDump(( 1,
        !          4975:                          "CdAudio535DeviceControl: READ_Q_CHANNEL, illegal Format (%d)\n",
        !          4976:                          ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format
        !          4977:                          ));
        !          4978: 
        !          4979:             ExFreePool( SubQPtr );
        !          4980:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          4981:             status = STATUS_UNSUCCESSFUL;
        !          4982:             goto SetStatusAndReturn;
        !          4983:         }
        !          4984: 
        !          4985:         //
        !          4986:         // Get Current Position
        !          4987:         //
        !          4988: 
        !          4989:         srb.CdbLength            = 10;
        !          4990:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          4991:         cdb->SUBCHANNEL.OperationCode = CDS535_READ_SUB_Q_CHANNEL_CODE;
        !          4992:         cdb->SUBCHANNEL.Msf = 1;
        !          4993:         cdb->SUBCHANNEL.SubQ = 1;
        !          4994:         cdb->SUBCHANNEL.Format = 1;
        !          4995:         cdb->SUBCHANNEL.AllocationLength[1] = sizeof(SUB_Q_CURRENT_POSITION);
        !          4996:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          4997:                                      &srb,
        !          4998:                                      SubQPtr,
        !          4999:                                      sizeof(SUB_Q_CURRENT_POSITION),
        !          5000:                                      FALSE
        !          5001:                                     );
        !          5002: 
        !          5003:         //
        !          5004:         // Copy current position, converting track and index from BCD
        !          5005:         //
        !          5006: 
        !          5007:         if (NT_SUCCESS(status)) {
        !          5008:             if(SubQPtr[1] == 0x11) deviceExtension->PlayActive = TRUE;
        !          5009:             else deviceExtension->PlayActive = FALSE;
        !          5010: 
        !          5011:             userPtr->Header.Reserved = 0;
        !          5012:             userPtr->Header.AudioStatus = SubQPtr[1];
        !          5013:             userPtr->Header.DataLength[0] = 0;
        !          5014:             userPtr->Header.DataLength[1] = 12;
        !          5015:             userPtr->FormatCode = 0x01;
        !          5016:             userPtr->Control = SubQPtr[5];
        !          5017:             userPtr->ADR     = 0;
        !          5018:             userPtr->TrackNumber = BCD_TO_DEC(SubQPtr[6]);
        !          5019:             userPtr->IndexNumber = BCD_TO_DEC(SubQPtr[7]);
        !          5020:             userPtr->AbsoluteAddress[0] = 0;
        !          5021:             userPtr->AbsoluteAddress[1] = SubQPtr[9];
        !          5022:             userPtr->AbsoluteAddress[2] = SubQPtr[10];
        !          5023:             userPtr->AbsoluteAddress[3] = SubQPtr[11];
        !          5024:             userPtr->TrackRelativeAddress[0] = 0;
        !          5025:             userPtr->TrackRelativeAddress[1] = SubQPtr[13];
        !          5026:             userPtr->TrackRelativeAddress[2] = SubQPtr[14];
        !          5027:             userPtr->TrackRelativeAddress[3] = SubQPtr[15];
        !          5028:             Irp->IoStatus.Information = 16;
        !          5029:         } else {
        !          5030:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          5031:             CdDump(( 1,
        !          5032:                          "CdAudio535DeviceControl: READ_Q_CHANNEL failed (0x%08lX)\n",
        !          5033:                          status
        !          5034:                          ));
        !          5035:         }
        !          5036: 
        !          5037:         ExFreePool( SubQPtr );
        !          5038:         }
        !          5039:         break;
        !          5040: 
        !          5041:     case IOCTL_CDROM_PLAY_AUDIO_MSF:
        !          5042: 
        !          5043:         {
        !          5044:             PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          5045: 
        !          5046:             //
        !          5047:             // Play Audio MSF
        !          5048:             //
        !          5049: 
        !          5050:             DebugPrint((2,"ScsiCdRomDeviceControl: Play audio MSF\n"));
        !          5051: 
        !          5052:             if (currentIrpStack->Parameters.DeviceIoControl.InputBufferLength <
        !          5053:                 sizeof(CDROM_PLAY_AUDIO_MSF)) {
        !          5054: 
        !          5055:                 //
        !          5056:                 // Indicate unsuccessful status.
        !          5057:                 //
        !          5058: 
        !          5059:                 status = STATUS_BUFFER_TOO_SMALL;
        !          5060:                 break;
        !          5061:             }
        !          5062: 
        !          5063:             if (inputBuffer->StartingM == inputBuffer->EndingM &&
        !          5064:                 inputBuffer->StartingS == inputBuffer->EndingS &&
        !          5065:                 inputBuffer->StartingF == inputBuffer->EndingF) {
        !          5066:                 
        !          5067:                 cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
        !          5068:                 cdb->PAUSE_RESUME.Action = CDB_AUDIO_PAUSE;
        !          5069: 
        !          5070:             } else {
        !          5071:                 cdb->PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF;
        !          5072:     
        !          5073:                 cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM;
        !          5074:                 cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS;
        !          5075:                 cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF;
        !          5076:     
        !          5077:                 cdb->PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM;
        !          5078:                 cdb->PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS;
        !          5079:                 cdb->PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF;
        !          5080:     
        !          5081:             }
        !          5082: 
        !          5083:             srb.CdbLength = 10;
        !          5084: 
        !          5085:             //
        !          5086:             // Set timeout value.
        !          5087:             //
        !          5088: 
        !          5089:             srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          5090: 
        !          5091:             status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          5092:                           &srb,
        !          5093:                           NULL,
        !          5094:                           0,
        !          5095:                           FALSE);
        !          5096: 
        !          5097:             if (NT_SUCCESS(status) &&
        !          5098:                 cdb->PLAY_AUDIO_MSF.OperationCode == SCSIOP_PLAY_AUDIO_MSF) {
        !          5099:                 deviceExtension->PlayActive = TRUE;
        !          5100:             }
        !          5101:         }
        !          5102: 
        !          5103:         break;
        !          5104: 
        !          5105:     case IOCTL_CDROM_SEEK_AUDIO_MSF:
        !          5106:         {
        !          5107: 
        !          5108:         PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          5109: 
        !          5110:         CdDump(( 3,
        !          5111:             "CdAudio535DeviceControl: IOCTL_CDROM_SEEK_AUDIO_MSF received.\n"
        !          5112:             ));
        !          5113: 
        !          5114:         //
        !          5115:         // Use the data seek command to move the pickup
        !          5116:         // BUGBUG: blithely assumes logical block size == 2048 bytes
        !          5117:         //
        !          5118: 
        !          5119:         destblock = ((((ULONG)(inputBuffer->M) * 60)
        !          5120:                     + (ULONG)(inputBuffer->S)) * 75)
        !          5121:                     + (ULONG)(inputBuffer->F)
        !          5122:                     - 150;
        !          5123: 
        !          5124:         srb.CdbLength                = 10;
        !          5125:         srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          5126:         cdb->SEEK.OperationCode      = SCSIOP_SEEK;
        !          5127:         cdb->SEEK.LogicalBlockAddress[0] = (destblock >> 24) & 0xFF;
        !          5128:         cdb->SEEK.LogicalBlockAddress[1] = (destblock >> 16) & 0xFF;
        !          5129:         cdb->SEEK.LogicalBlockAddress[2] = (destblock >>  8) & 0xFF;
        !          5130:         cdb->SEEK.LogicalBlockAddress[3] = destblock & 0xFF;
        !          5131:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5132:                                      &srb,
        !          5133:                                      NULL,
        !          5134:                                      0,
        !          5135:                                      FALSE
        !          5136:                                     );
        !          5137: 
        !          5138:         if (!NT_SUCCESS(status)) {
        !          5139: 
        !          5140:             CdDump(( 3,
        !          5141:                 "CdAudio535DeviceControl: SEEK failed (0x%08lX)\n",
        !          5142:                 status ));
        !          5143: 
        !          5144:         }
        !          5145:         }
        !          5146:         break;
        !          5147: 
        !          5148:     case IOCTL_CDROM_EJECT_MEDIA:
        !          5149: 
        !          5150:         //
        !          5151:         // Build cdb to eject cartridge
        !          5152:         //
        !          5153: 
        !          5154:         CdDump(( 3,
        !          5155:                      "CdAudio535DeviceControl: IOCTL_CDROM_EJECT_MEDIA received.\n"
        !          5156:                      ));
        !          5157: 
        !          5158:         deviceExtension->PlayActive = FALSE;
        !          5159: 
        !          5160:         srb.CdbLength                  = 10;
        !          5161:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          5162:         cdb->CDB10.OperationCode = CDS535_EJECT_CODE;
        !          5163:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5164:                                      &srb,
        !          5165:                                      NULL,
        !          5166:                                      0,
        !          5167:                                      FALSE
        !          5168:                                     );
        !          5169:         break;
        !          5170: 
        !          5171:     case IOCTL_CDROM_GET_CONTROL:
        !          5172:     case IOCTL_CDROM_GET_VOLUME:
        !          5173:     case IOCTL_CDROM_SET_VOLUME:
        !          5174:         CdDump(( 3, "CdAudio535DeviceControl: Not Supported yet.\n" ));
        !          5175:         status = STATUS_INVALID_DEVICE_REQUEST;
        !          5176:         break;
        !          5177: 
        !          5178:     case IOCTL_CDROM_CHECK_VERIFY:
        !          5179: 
        !          5180:         //
        !          5181:         // Update the play active flag.
        !          5182:         //
        !          5183: 
        !          5184:         CdAudioIsPlayActive(DeviceObject);
        !          5185: 
        !          5186:     default:
        !          5187: 
        !          5188:         CdDump((5,"ChCdAudio535DeviceControl: Unsupported device IOCTL\n"));
        !          5189:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          5190:         break;
        !          5191: 
        !          5192:     } // end switch( IOCTL )
        !          5193: 
        !          5194: SetStatusAndReturn:
        !          5195:     //
        !          5196:     // set status code and return
        !          5197:     //
        !          5198: 
        !          5199:     if (status == STATUS_VERIFY_REQUIRED) {
        !          5200: 
        !          5201:         IoSetHardErrorOrVerifyDevice( Irp,
        !          5202:                                       deviceExtension->TargetDeviceObject
        !          5203:                                      );
        !          5204: 
        !          5205:         Irp->IoStatus.Information = 0;
        !          5206:     }
        !          5207: 
        !          5208:     Irp->IoStatus.Status = status;
        !          5209:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          5210:     return status;
        !          5211: 
        !          5212: }
        !          5213: 
        !          5214: 
        !          5215: NTSTATUS
        !          5216: CdAudio435DeviceControl(
        !          5217:     PDEVICE_OBJECT DeviceObject,
        !          5218:     PIRP Irp
        !          5219:     )
        !          5220: 
        !          5221: /*++
        !          5222: 
        !          5223: Routine Description:
        !          5224: 
        !          5225:     This routine is called by CdAudioDeviceControl to handle
        !          5226:     audio IOCTLs sent to Chinon CDS-435 cdrom drive.
        !          5227: 
        !          5228: Arguments:
        !          5229: 
        !          5230:     DeviceObject
        !          5231:     Irp
        !          5232: 
        !          5233: Return Value:
        !          5234: 
        !          5235:     NTSTATUS
        !          5236: 
        !          5237: --*/
        !          5238: 
        !          5239: {
        !          5240:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          5241:     PCD_DEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          5242:     PCDROM_TOC         cdaudioDataOut  = Irp->AssociatedIrp.SystemBuffer;
        !          5243:     SCSI_REQUEST_BLOCK srb;
        !          5244:     PCDB               cdb = (PCDB)srb.Cdb;
        !          5245:     NTSTATUS           status;
        !          5246:     ULONG              i,bytesTransfered;
        !          5247:     PUCHAR             Toc;
        !          5248: 
        !          5249:     //
        !          5250:     // Clear out cdb
        !          5251:     //
        !          5252: 
        !          5253:     RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          5254: 
        !          5255:     //
        !          5256:     // What IOCTL do we need to execute?
        !          5257:     //
        !          5258: 
        !          5259:     switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
        !          5260: 
        !          5261:     case IOCTL_CDROM_READ_TOC:
        !          5262:         CdDump(( 3,
        !          5263:                      "CdAudio435DeviceControl: IOCTL_CDROM_READ_TOC received.\n"
        !          5264:                      ));
        !          5265: 
        !          5266: 
        !          5267:         //
        !          5268:         // If the cd is playing music then reject this request.
        !          5269:         //
        !          5270: 
        !          5271:         if (CdAudioIsPlayActive(DeviceObject)) {
        !          5272:             status = STATUS_DEVICE_BUSY;
        !          5273:             break;
        !          5274:         }
        !          5275: 
        !          5276:         //
        !          5277:         // Allocate storage to hold TOC from disc
        !          5278:         //
        !          5279: 
        !          5280:         Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
        !          5281:                                       CDROM_TOC_SIZE
        !          5282:                                      );
        !          5283: 
        !          5284:         if (Toc==NULL) {
        !          5285: 
        !          5286:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          5287:             goto SetStatusAndReturn;
        !          5288: 
        !          5289:         }
        !          5290: 
        !          5291:         //
        !          5292:         // Set up defaults
        !          5293:         //
        !          5294: 
        !          5295:         RtlZeroMemory( Toc, CDROM_TOC_SIZE );
        !          5296: 
        !          5297:         //
        !          5298:         // Fill in cdb for this operation
        !          5299:         //
        !          5300: 
        !          5301:         cdb->READ_TOC.OperationCode = CDS435_READ_TOC_CODE;
        !          5302:         cdb->READ_TOC.Msf = 1;
        !          5303:         cdb->READ_TOC.AllocationLength[0] = (CDROM_TOC_SIZE >> 8);
        !          5304:         cdb->READ_TOC.AllocationLength[1] = (CDROM_TOC_SIZE & 0xFF);
        !          5305:         srb.TimeOutValue                  = AUDIO_TIMEOUT;
        !          5306:         srb.CdbLength                     = 10;
        !          5307:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5308:                                      &srb,
        !          5309:                                      Toc,
        !          5310:                                      CDROM_TOC_SIZE,
        !          5311:                                      FALSE
        !          5312:                                     );
        !          5313: 
        !          5314:         if (!NT_SUCCESS(status) && (status!=STATUS_DATA_OVERRUN)) {
        !          5315: 
        !          5316:             CdDump(( 1,
        !          5317:                 "CdAudio435DeviceControl: READ_TOC error (0x%08lX)\n",
        !          5318:                  status ));
        !          5319: 
        !          5320:             if (SRB_STATUS(srb.SrbStatus)!=SRB_STATUS_DATA_OVERRUN) {
        !          5321: 
        !          5322:                 CdDump(( 1, "CdAudio435DeviceControl: SRB ERROR (0x%lX)\n",
        !          5323:                              srb.SrbStatus ));
        !          5324:                 ExFreePool( Toc );
        !          5325:                 goto SetStatusAndReturn;
        !          5326:             }
        !          5327: 
        !          5328:         } else {
        !          5329: 
        !          5330:             status = STATUS_SUCCESS;
        !          5331:         }
        !          5332: 
        !          5333:         //
        !          5334:         // Translate data into SCSI-II format
        !          5335:         //   (track numbers, except 0xAA, must be converted from BCD)
        !          5336: 
        !          5337:         bytesTransfered =
        !          5338:             currentIrpStack->Parameters.Read.Length > sizeof(CDROM_TOC) ?
        !          5339:             sizeof(CDROM_TOC) : currentIrpStack->Parameters.Read.Length;
        !          5340:         Irp->IoStatus.Information  = bytesTransfered;
        !          5341: 
        !          5342:         cdaudioDataOut->Length[0]  = Toc[0];
        !          5343:         cdaudioDataOut->Length[1]  = Toc[1];
        !          5344:         cdaudioDataOut->FirstTrack = BCD_TO_DEC(Toc[2]);
        !          5345:         cdaudioDataOut->LastTrack  = BCD_TO_DEC(Toc[3]);
        !          5346: 
        !          5347:         for( i=0;
        !          5348:              i<=( (ULONG)cdaudioDataOut->LastTrack -
        !          5349:                   (ULONG)cdaudioDataOut->FirstTrack   );
        !          5350:              i++
        !          5351:             ) {
        !          5352: 
        !          5353:             //
        !          5354:             // Grab Information for each track
        !          5355:             //
        !          5356: 
        !          5357:             cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          5358:             cdaudioDataOut->TrackData[i].Control     = Toc[(i*8)+4+1];
        !          5359:             cdaudioDataOut->TrackData[i].TrackNumber = BCD_TO_DEC(Toc[(i*8)+4+2]);
        !          5360:             cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          5361:             cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          5362:             cdaudioDataOut->TrackData[i].Address[1]  = Toc[(i*8)+4+5];
        !          5363:             cdaudioDataOut->TrackData[i].Address[2]  = Toc[(i*8)+4+6];
        !          5364:             cdaudioDataOut->TrackData[i].Address[3]  = Toc[(i*8)+4+7];
        !          5365: 
        !          5366:         }
        !          5367: 
        !          5368:         //
        !          5369:         // Copy "lead out track" info
        !          5370:         //
        !          5371: 
        !          5372:         cdaudioDataOut->TrackData[i].Reserved    = 0;
        !          5373:         cdaudioDataOut->TrackData[i].Control     = Toc[(i*8)+4+1];
        !          5374:         cdaudioDataOut->TrackData[i].TrackNumber = Toc[(i*8)+4+2];  /* leave as 0xAA */
        !          5375:         cdaudioDataOut->TrackData[i].Reserved1   = 0;
        !          5376:         cdaudioDataOut->TrackData[i].Address[0]  = 0;
        !          5377:         cdaudioDataOut->TrackData[i].Address[1]  = Toc[(i*8)+4+5];
        !          5378:         cdaudioDataOut->TrackData[i].Address[2]  = Toc[(i*8)+4+6];
        !          5379:         cdaudioDataOut->TrackData[i].Address[3]  = Toc[(i*8)+4+7];
        !          5380: 
        !          5381:         //
        !          5382:         // Clear out deviceExtension data
        !          5383:         //
        !          5384: 
        !          5385:         deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          5386:         deviceExtension->PausedM = 0;
        !          5387:         deviceExtension->PausedS = 0;
        !          5388:         deviceExtension->PausedF = 0;
        !          5389:         deviceExtension->LastEndM = 0;
        !          5390:         deviceExtension->LastEndS = 0;
        !          5391:         deviceExtension->LastEndF = 0;
        !          5392: 
        !          5393:         //
        !          5394:         // Free storage now that we've stored it elsewhere
        !          5395:         //
        !          5396: 
        !          5397:         ExFreePool( Toc );
        !          5398:         break;
        !          5399: 
        !          5400:     case IOCTL_CDROM_PLAY_AUDIO_MSF:
        !          5401:     case IOCTL_CDROM_STOP_AUDIO:
        !          5402:         {
        !          5403: 
        !          5404:         PCDROM_PLAY_AUDIO_MSF inputBuffer =
        !          5405:             Irp->AssociatedIrp.SystemBuffer;
        !          5406: 
        !          5407:         srb.CdbLength                  = 10;
        !          5408:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          5409:         cdb->CDB10.OperationCode = CDS435_STOP_AUDIO_CODE;
        !          5410:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5411:                                      &srb,
        !          5412:                                      NULL,
        !          5413:                                      0,
        !          5414:                                      FALSE
        !          5415:                                     );
        !          5416: 
        !          5417:         if (NT_SUCCESS(status)) {
        !          5418: 
        !          5419:             deviceExtension->PlayActive = FALSE;
        !          5420: 
        !          5421:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          5422:             deviceExtension->PausedM = 0;
        !          5423:             deviceExtension->PausedS = 0;
        !          5424:             deviceExtension->PausedF = 0;
        !          5425:             deviceExtension->LastEndM = 0;
        !          5426:             deviceExtension->LastEndS = 0;
        !          5427:             deviceExtension->LastEndF = 0;
        !          5428: 
        !          5429:         } else {
        !          5430: 
        !          5431:             CdDump(( 3,
        !          5432:                 "CdAudio435DeviceControl: STOP failed (0x%08lX)\n",
        !          5433:                 status ));
        !          5434: 
        !          5435:         }
        !          5436: 
        !          5437: 
        !          5438:         if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
        !          5439:             IOCTL_CDROM_STOP_AUDIO
        !          5440:            ) {
        !          5441: 
        !          5442:             CdDump(( 3,
        !          5443:                          "CdAudio435DeviceControl: IOCTL_CDROM_STOP_AUDIO received.\n"
        !          5444:                          ));
        !          5445: 
        !          5446:             goto SetStatusAndReturn;
        !          5447: 
        !          5448:         }
        !          5449: 
        !          5450:         CdDump(( 3,
        !          5451:             "CdAudio435DeviceControl: IOCTL_CDROM_PLAY_AUDIO_MSF received.\n"
        !          5452:             ));
        !          5453: 
        !          5454:         //
        !          5455:         // Fill in cdb for this operation
        !          5456:         //
        !          5457: 
        !          5458:         srb.CdbLength                = 10;
        !          5459:         srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          5460:         cdb->PLAY_AUDIO_MSF.OperationCode     = CDS435_PLAY_AUDIO_EXTENDED_CODE;
        !          5461:         cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM;
        !          5462:         cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS;
        !          5463:         cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF;
        !          5464:         cdb->PLAY_AUDIO_MSF.EndingM   = inputBuffer->EndingM;
        !          5465:         cdb->PLAY_AUDIO_MSF.EndingS   = inputBuffer->EndingS;
        !          5466:         cdb->PLAY_AUDIO_MSF.EndingF   = inputBuffer->EndingF;
        !          5467:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5468:                                      &srb,
        !          5469:                                      NULL,
        !          5470:                                      0,
        !          5471:                                      FALSE
        !          5472:                                     );
        !          5473: 
        !          5474:         if (NT_SUCCESS(status)) {
        !          5475: 
        !          5476:             deviceExtension->PlayActive = TRUE;
        !          5477: 
        !          5478:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          5479: 
        !          5480:             //
        !          5481:             // Set last play ending address for next pause command
        !          5482:             //
        !          5483: 
        !          5484:             deviceExtension->LastEndM = inputBuffer->EndingM;
        !          5485:             deviceExtension->LastEndS = inputBuffer->EndingS;
        !          5486:             deviceExtension->LastEndF = inputBuffer->EndingF;
        !          5487:             CdDump(( 3,
        !          5488:                 "CdAudio435DeviceControl: PLAY  ==> BcdLastEnd set to (%x %x %x)\n",
        !          5489:                 deviceExtension->LastEndM,
        !          5490:                 deviceExtension->LastEndS,
        !          5491:                 deviceExtension->LastEndF ));
        !          5492: 
        !          5493:         } else {
        !          5494: 
        !          5495:             CdDump(( 3,
        !          5496:                 "CdAudio435DeviceControl: PLAY failed (0x%08lX)\n",
        !          5497:                 status ));
        !          5498: 
        !          5499:         }
        !          5500:         }
        !          5501:         break;
        !          5502: 
        !          5503:     case IOCTL_CDROM_SEEK_AUDIO_MSF:
        !          5504:         {
        !          5505: 
        !          5506:         PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
        !          5507: 
        !          5508:         CdDump(( 3,
        !          5509:             "CdAudio435DeviceControl: IOCTL_CDROM_SEEK_AUDIO_MSF received.\n"
        !          5510:             ));
        !          5511: 
        !          5512:         //
        !          5513:         // Fill in cdb for this operation
        !          5514:         //
        !          5515: 
        !          5516:         srb.CdbLength                = 10;
        !          5517:         srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          5518:         cdb->CDB10.OperationCode     = CDS435_PLAY_AUDIO_EXTENDED_CODE;
        !          5519:         cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->M;
        !          5520:         cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->S;
        !          5521:         cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->F;
        !          5522:         cdb->PLAY_AUDIO_MSF.EndingM   = inputBuffer->M;
        !          5523:         cdb->PLAY_AUDIO_MSF.EndingS   = inputBuffer->S;
        !          5524:         cdb->PLAY_AUDIO_MSF.EndingF   = inputBuffer->F;
        !          5525:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5526:                                      &srb,
        !          5527:                                      NULL,
        !          5528:                                      0,
        !          5529:                                      FALSE
        !          5530:                                     );
        !          5531: 
        !          5532:         if (NT_SUCCESS(status)) {
        !          5533: 
        !          5534:             deviceExtension->Paused = CDAUDIO_PAUSED;
        !          5535:             deviceExtension->PausedM = inputBuffer->M;
        !          5536:             deviceExtension->PausedS = inputBuffer->S;
        !          5537:             deviceExtension->PausedF = inputBuffer->F;
        !          5538:             deviceExtension->LastEndM = inputBuffer->M;
        !          5539:             deviceExtension->LastEndS = inputBuffer->S;
        !          5540:             deviceExtension->LastEndF = inputBuffer->F;
        !          5541:             CdDump(( 3,
        !          5542:                 "CdAudio435DeviceControl: SEEK, Paused (%x %x %x) LastEnd (%x %x %x)\n",
        !          5543:                 deviceExtension->PausedM,
        !          5544:                 deviceExtension->PausedS,
        !          5545:                 deviceExtension->PausedF,
        !          5546:                 deviceExtension->LastEndM,
        !          5547:                 deviceExtension->LastEndS,
        !          5548:                 deviceExtension->LastEndF ));
        !          5549: 
        !          5550:         } else {
        !          5551: 
        !          5552:             CdDump(( 3,
        !          5553:                 "CdAudio435DeviceControl: SEEK failed (0x%08lX)\n",
        !          5554:                 status ));
        !          5555: 
        !          5556:             //
        !          5557:             // The CDS-435 drive returns STATUS_INVALID_DEVICE_REQUEST
        !          5558:             // when we ask to play an invalid address, so we need
        !          5559:             // to map to STATUS_NONEXISTENT_SECTOR in order to be
        !          5560:             // consistent with the other drives.
        !          5561:             //
        !          5562: 
        !          5563:             if (status==STATUS_INVALID_DEVICE_REQUEST) {
        !          5564: 
        !          5565:                 status = STATUS_NONEXISTENT_SECTOR;
        !          5566:             }
        !          5567: 
        !          5568:         }
        !          5569:         }
        !          5570:         break;
        !          5571: 
        !          5572:     case IOCTL_CDROM_PAUSE_AUDIO:
        !          5573:         {
        !          5574:         PUCHAR SubQPtr =
        !          5575:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          5576:                             sizeof(SUB_Q_CHANNEL_DATA)
        !          5577:                            );
        !          5578: 
        !          5579:         CdDump(( 3,
        !          5580:                      "CdAudio435DeviceControl: IOCTL_CDROM_PAUSE_AUDIO received.\n"
        !          5581:                      ));
        !          5582: 
        !          5583:         if (SubQPtr==NULL) {
        !          5584: 
        !          5585:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          5586:             goto SetStatusAndReturn;
        !          5587: 
        !          5588:         }
        !          5589: 
        !          5590:         //
        !          5591:         // Enter pause (still ) mode
        !          5592:         //
        !          5593: 
        !          5594:         if (deviceExtension->Paused==CDAUDIO_PAUSED) {
        !          5595: 
        !          5596:             CdDump(( 3,
        !          5597:                 "CdAudio435DeviceControl: PAUSE: Already Paused!\n"
        !          5598:                 ));
        !          5599: 
        !          5600:             ExFreePool( SubQPtr );
        !          5601:             status = STATUS_SUCCESS;
        !          5602:             goto SetStatusAndReturn;
        !          5603: 
        !          5604:         }
        !          5605: 
        !          5606:         //
        !          5607:         // Since the CDS-435 doesn't have a pause mode,
        !          5608:         // we'll just record the current position and
        !          5609:         // stop the drive.
        !          5610:         //
        !          5611: 
        !          5612:         srb.CdbLength            = 10;
        !          5613:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          5614:         cdb->SUBCHANNEL.OperationCode = CDS435_READ_SUB_Q_CHANNEL_CODE;
        !          5615:         cdb->SUBCHANNEL.Msf = 1;
        !          5616:         cdb->SUBCHANNEL.SubQ = 1;
        !          5617:         cdb->SUBCHANNEL.AllocationLength[1] = sizeof(SUB_Q_CHANNEL_DATA);
        !          5618:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5619:                                      &srb,
        !          5620:                                      SubQPtr,
        !          5621:                                      sizeof(SUB_Q_CHANNEL_DATA),
        !          5622:                                      FALSE
        !          5623:                                     );
        !          5624:         if (!NT_SUCCESS(status)) {
        !          5625: 
        !          5626:                 CdDump(( 1,
        !          5627:                     "CdAudio435DeviceControl: Pause, Read Q Channel failed (0x%lx)\n",
        !          5628:                     status ));
        !          5629:                 ExFreePool( SubQPtr );
        !          5630:                 goto SetStatusAndReturn;
        !          5631:         }
        !          5632: 
        !          5633:         deviceExtension->PausedM = SubQPtr[9];
        !          5634:         deviceExtension->PausedS = SubQPtr[10];
        !          5635:         deviceExtension->PausedF = SubQPtr[11];
        !          5636: 
        !          5637:         //
        !          5638:         // now stop audio
        !          5639:         //
        !          5640:         RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
        !          5641:         srb.CdbLength                  = 10;
        !          5642:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          5643:         cdb->CDB10.OperationCode = CDS435_STOP_AUDIO_CODE;
        !          5644:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5645:                                      &srb,
        !          5646:                                      NULL,
        !          5647:                                      0,
        !          5648:                                      FALSE
        !          5649:                                     );
        !          5650:         if (!NT_SUCCESS(status)) {
        !          5651: 
        !          5652:                 CdDump(( 1,
        !          5653:                     "CdAudio435DeviceControl: PAUSE, StopAudio failed! (0x%08lX)\n",
        !          5654:                     status ));
        !          5655:                 ExFreePool( SubQPtr );
        !          5656:                 goto SetStatusAndReturn;
        !          5657:         }
        !          5658: 
        !          5659:         deviceExtension->PlayActive = FALSE;
        !          5660: 
        !          5661:         deviceExtension->Paused = CDAUDIO_PAUSED;
        !          5662:         deviceExtension->PausedM = SubQPtr[9];
        !          5663:         deviceExtension->PausedS = SubQPtr[10];
        !          5664:         deviceExtension->PausedF = SubQPtr[11];
        !          5665: 
        !          5666:         CdDump((3,
        !          5667:             "CdAudio435DeviceControl: PAUSE ==> Paused  set to (%x %x %x)\n",
        !          5668:             deviceExtension->PausedM,
        !          5669:             deviceExtension->PausedS,
        !          5670:             deviceExtension->PausedF ));
        !          5671: 
        !          5672:         ExFreePool( SubQPtr );
        !          5673:         }
        !          5674:         break;
        !          5675: 
        !          5676:     case IOCTL_CDROM_RESUME_AUDIO:
        !          5677: 
        !          5678:         //
        !          5679:         // Resume cdrom
        !          5680:         //
        !          5681: 
        !          5682:         CdDump(( 3,
        !          5683:                      "CdAudio435DeviceControl: IOCTL_CDROM_RESUME_AUDIO received.\n"
        !          5684:                      ));
        !          5685: 
        !          5686: 
        !          5687:         //
        !          5688:         // Since the CDS-435 doesn't have a resume IOCTL,
        !          5689:         // we'll just start playing (if paused) from the
        !          5690:         // last recored paused position to the last recorded
        !          5691:         // "end of play" position.
        !          5692:         //
        !          5693: 
        !          5694:         if (deviceExtension->Paused==CDAUDIO_NOT_PAUSED) {
        !          5695: 
        !          5696:             status = STATUS_UNSUCCESSFUL;
        !          5697:             goto SetStatusAndReturn;
        !          5698: 
        !          5699:         }
        !          5700: 
        !          5701:         //
        !          5702:         // Fill in cdb for this operation
        !          5703:         //
        !          5704: 
        !          5705:         srb.CdbLength                = 10;
        !          5706:         srb.TimeOutValue             = AUDIO_TIMEOUT;
        !          5707:         cdb->PLAY_AUDIO_MSF.OperationCode     = CDS435_PLAY_AUDIO_EXTENDED_CODE;
        !          5708:         cdb->PLAY_AUDIO_MSF.StartingM = deviceExtension->PausedM;
        !          5709:         cdb->PLAY_AUDIO_MSF.StartingS = deviceExtension->PausedS;
        !          5710:         cdb->PLAY_AUDIO_MSF.StartingF = deviceExtension->PausedF;
        !          5711:         cdb->PLAY_AUDIO_MSF.EndingM   = deviceExtension->LastEndM;
        !          5712:         cdb->PLAY_AUDIO_MSF.EndingS   = deviceExtension->LastEndS;
        !          5713:         cdb->PLAY_AUDIO_MSF.EndingF   = deviceExtension->LastEndF;
        !          5714:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5715:                                      &srb,
        !          5716:                                      NULL,
        !          5717:                                      0,
        !          5718:                                      FALSE
        !          5719:                                     );
        !          5720: 
        !          5721:         if (NT_SUCCESS(status)) {
        !          5722: 
        !          5723:             deviceExtension->PlayActive = TRUE;
        !          5724: 
        !          5725:             deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          5726: 
        !          5727:         } else {
        !          5728: 
        !          5729:             CdDump(( 1,
        !          5730:                 "CdAudio435DeviceControl: RESUME (%x %x %x) - (%x %x %x) failed (0x%08lX)\n",
        !          5731:                 deviceExtension->PausedM,
        !          5732:                 deviceExtension->PausedS,
        !          5733:                 deviceExtension->PausedF,
        !          5734:                 deviceExtension->LastEndM,
        !          5735:                 deviceExtension->LastEndS,
        !          5736:                 deviceExtension->LastEndF,
        !          5737:                 status ));
        !          5738: 
        !          5739:         }
        !          5740:         break;
        !          5741: 
        !          5742:     case IOCTL_CDROM_READ_Q_CHANNEL:
        !          5743:         {
        !          5744:         PSUB_Q_CURRENT_POSITION userPtr =
        !          5745:             Irp->AssociatedIrp.SystemBuffer;
        !          5746:         PUCHAR SubQPtr =
        !          5747:             ExAllocatePool( NonPagedPoolCacheAligned,
        !          5748:                             sizeof(SUB_Q_CHANNEL_DATA)
        !          5749:                            );
        !          5750: 
        !          5751:         CdDump(( 5,
        !          5752:                      "CdAudio435DeviceControl: IOCTL_CDROM_READ_Q_CHANNEL received.\n"
        !          5753:                      ));
        !          5754: 
        !          5755:         if (SubQPtr==NULL) {
        !          5756: 
        !          5757:             CdDump(( 1,
        !          5758:                          "CdAudio435DeviceControl: READ_Q_CHANNEL, SubQPtr==NULL!\n"
        !          5759:                          ));
        !          5760: 
        !          5761:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          5762:             status = STATUS_INSUFFICIENT_RESOURCES;
        !          5763:             goto SetStatusAndReturn;
        !          5764: 
        !          5765:         }
        !          5766: 
        !          5767:         if ( ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format!=
        !          5768:              IOCTL_CDROM_CURRENT_POSITION) {
        !          5769: 
        !          5770:             CdDump(( 1,
        !          5771:                          "CdAudio435DeviceControl: READ_Q_CHANNEL, illegal Format (%d)\n",
        !          5772:                          ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format
        !          5773:                          ));
        !          5774: 
        !          5775:             ExFreePool( SubQPtr );
        !          5776:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          5777:             status = STATUS_UNSUCCESSFUL;
        !          5778:             goto SetStatusAndReturn;
        !          5779:         }
        !          5780: 
        !          5781:         //
        !          5782:         // Read audio play status
        !          5783:         //
        !          5784: 
        !          5785:         srb.CdbLength            = 10;
        !          5786:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          5787:         cdb->SUBCHANNEL.OperationCode = CDS435_READ_SUB_Q_CHANNEL_CODE;
        !          5788:         cdb->SUBCHANNEL.Msf = 1;
        !          5789:         cdb->SUBCHANNEL.SubQ = 1;
        !          5790:         cdb->SUBCHANNEL.AllocationLength[1] = sizeof(SUB_Q_CHANNEL_DATA);
        !          5791:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5792:                                      &srb,
        !          5793:                                      SubQPtr,
        !          5794:                                      sizeof(SUB_Q_CHANNEL_DATA),
        !          5795:                                      FALSE
        !          5796:                                     );
        !          5797:         if (NT_SUCCESS(status)) {
        !          5798: 
        !          5799:             userPtr->Header.Reserved = 0;
        !          5800: 
        !          5801:             if (deviceExtension->Paused==CDAUDIO_PAUSED) {
        !          5802: 
        !          5803:                 deviceExtension->PlayActive = FALSE;
        !          5804:                 userPtr->Header.AudioStatus = AUDIO_STATUS_PAUSED;
        !          5805: 
        !          5806:             } else {
        !          5807: 
        !          5808:                 if (SubQPtr[1] == 0x11) {
        !          5809: 
        !          5810:                     deviceExtension->PlayActive = TRUE;
        !          5811:                     userPtr->Header.AudioStatus = AUDIO_STATUS_IN_PROGRESS;
        !          5812: 
        !          5813:                 } else {
        !          5814: 
        !          5815:                     deviceExtension->PlayActive = FALSE;
        !          5816:                     userPtr->Header.AudioStatus = AUDIO_STATUS_PLAY_COMPLETE;
        !          5817: 
        !          5818:                 }
        !          5819:             }
        !          5820: 
        !          5821:             userPtr->Header.DataLength[0] = 0;
        !          5822:             userPtr->Header.DataLength[1] = 12;
        !          5823: 
        !          5824:             userPtr->FormatCode = 0x01;
        !          5825:             userPtr->Control = SubQPtr[5];
        !          5826:             userPtr->ADR     = 0;
        !          5827:             userPtr->TrackNumber = BCD_TO_DEC(SubQPtr[6]);
        !          5828:             userPtr->IndexNumber = BCD_TO_DEC(SubQPtr[7]);
        !          5829:             userPtr->AbsoluteAddress[0] = 0;
        !          5830:             userPtr->AbsoluteAddress[1] = SubQPtr[9];
        !          5831:             userPtr->AbsoluteAddress[2] = SubQPtr[10];
        !          5832:             userPtr->AbsoluteAddress[3] = SubQPtr[11];
        !          5833:             userPtr->TrackRelativeAddress[0] = 0;
        !          5834:             userPtr->TrackRelativeAddress[1] = SubQPtr[13];
        !          5835:             userPtr->TrackRelativeAddress[2] = SubQPtr[14];
        !          5836:             userPtr->TrackRelativeAddress[3] = SubQPtr[15];
        !          5837:             Irp->IoStatus.Information = 16;
        !          5838: 
        !          5839:         } else {
        !          5840: 
        !          5841:             RtlZeroMemory( userPtr, sizeof(SUB_Q_CURRENT_POSITION) );
        !          5842:             CdDump(( 1,
        !          5843:                          "CdAudio435DeviceControl: READ_Q_CHANNEL failed (0x%08lX)\n",
        !          5844:                          status
        !          5845:                          ));
        !          5846: 
        !          5847: 
        !          5848:         }
        !          5849: 
        !          5850:         ExFreePool( SubQPtr );
        !          5851:         }
        !          5852:         break;
        !          5853: 
        !          5854:     case IOCTL_CDROM_EJECT_MEDIA:
        !          5855: 
        !          5856:         //
        !          5857:         // Build cdb to eject cartridge
        !          5858:         //
        !          5859: 
        !          5860:         CdDump(( 3,
        !          5861:                      "CdAudio435DeviceControl: IOCTL_CDROM_EJECT_MEDIA received.\n"
        !          5862:                      ));
        !          5863: 
        !          5864:         srb.CdbLength                  = 10;
        !          5865:         srb.TimeOutValue               = AUDIO_TIMEOUT;
        !          5866:         cdb->CDB10.OperationCode = CDS435_EJECT_CODE;
        !          5867:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5868:                                      &srb,
        !          5869:                                      NULL,
        !          5870:                                      0,
        !          5871:                                      FALSE
        !          5872:                                     );
        !          5873: 
        !          5874:         deviceExtension->Paused = CDAUDIO_NOT_PAUSED;
        !          5875:         deviceExtension->PausedM = 0;
        !          5876:         deviceExtension->PausedS = 0;
        !          5877:         deviceExtension->PausedF = 0;
        !          5878:         deviceExtension->LastEndM = 0;
        !          5879:         deviceExtension->LastEndS = 0;
        !          5880:         deviceExtension->LastEndF = 0;
        !          5881: 
        !          5882:         break;
        !          5883: 
        !          5884:     case IOCTL_CDROM_GET_CONTROL:
        !          5885:     case IOCTL_CDROM_GET_VOLUME:
        !          5886:     case IOCTL_CDROM_SET_VOLUME:
        !          5887:         CdDump(( 3, "CdAudio435DeviceControl: Not Supported yet.\n" ));
        !          5888:         status = STATUS_INVALID_DEVICE_REQUEST;
        !          5889:         break;
        !          5890: 
        !          5891:     case IOCTL_CDROM_CHECK_VERIFY:
        !          5892:         //
        !          5893:         // Update the play active flag.
        !          5894:         //
        !          5895: 
        !          5896:         CdAudioIsPlayActive(DeviceObject);
        !          5897: 
        !          5898:         //
        !          5899:         // This normally uses the Test_Unit_Ready (TUR) command.  The
        !          5900:         // CDS-435/431 respond to the TUR command with a status byte
        !          5901:         // of 0x08 to indicate that an audio play is in progress.  That
        !          5902:         // looks like SCSISTAT_BUSY, so it ends up getting retried.
        !          5903:         // There are a couple of solutions:
        !          5904:         //  a) install a class error handler that watches for
        !          5905:         //     Status == STATUS_DEVICE_NOT_READY
        !          5906:         //     and/or Srb->ScsiStatus = SCSISTAT_BUSY
        !          5907:         //     and converts it to Status = STATUS_SUCCESS,
        !          5908:         //     Srb->ScsiStatus = SCSISTAT_GOOD
        !          5909:         //     This is considerably more general than really necessary,
        !          5910:         //     since only the TUR command behaves this way.
        !          5911:         //  b) use another command, like ReadSubQ to get the drive's status
        !          5912:         //     (we don't need to transfer any data, i.e. allocation length
        !          5913:         //     = 0)
        !          5914:         //
        !          5915: 
        !          5916:         CdDump(( 3, "CdAudio435DeviceControl: IOCTL_CDROM_CHECK_VERIFY received.\n"
        !          5917:                      ));
        !          5918: 
        !          5919:         //
        !          5920:         // Read audio play status
        !          5921:         //
        !          5922: 
        !          5923:         srb.CdbLength            = 10;
        !          5924:         srb.TimeOutValue         = AUDIO_TIMEOUT;
        !          5925:         cdb->SUBCHANNEL.OperationCode = CDS435_READ_SUB_Q_CHANNEL_CODE;
        !          5926:         cdb->SUBCHANNEL.Msf = 1;
        !          5927:         cdb->SUBCHANNEL.SubQ = 1;
        !          5928:         status = ScsiClassSendSrbSynchronous( deviceExtension->DeviceObject,
        !          5929:                                      &srb,
        !          5930:                                      NULL,
        !          5931:                                      0,
        !          5932:                                      FALSE
        !          5933:                                     );
        !          5934:         break;
        !          5935: 
        !          5936:     default:
        !          5937: 
        !          5938:         CdDump((5,"CdAudio435DeviceControl: Unsupported device IOCTL\n"));
        !          5939:         return CdAudioSendToNextDriver( DeviceObject, Irp );
        !          5940:         break;
        !          5941: 
        !          5942:     } // end switch( IOCTL )
        !          5943: 
        !          5944: SetStatusAndReturn:
        !          5945:     //
        !          5946:     // set status code and return
        !          5947:     //
        !          5948: 
        !          5949:     if (status == STATUS_VERIFY_REQUIRED) {
        !          5950: 
        !          5951:         IoSetHardErrorOrVerifyDevice( Irp,
        !          5952:                                       deviceExtension->TargetDeviceObject
        !          5953:                                      );
        !          5954: 
        !          5955:         Irp->IoStatus.Information = 0;
        !          5956:     }
        !          5957: 
        !          5958:     Irp->IoStatus.Status = status;
        !          5959:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          5960:     return status;
        !          5961: 
        !          5962: }
        !          5963: 
        !          5964: #if DBG
        !          5965: VOID
        !          5966: CdAudioDebugPrint(
        !          5967:     ULONG DebugPrintLevel,
        !          5968:     PCCHAR DebugMessage,
        !          5969:     ...
        !          5970:     )
        !          5971: 
        !          5972: /*++
        !          5973: 
        !          5974: Routine Description:
        !          5975: 
        !          5976:     Debug print for CdAudio driver
        !          5977: 
        !          5978: Arguments:
        !          5979: 
        !          5980:     Debug print level between 0 and 3, with 3 being the most verbose.
        !          5981: 
        !          5982: Return Value:
        !          5983: 
        !          5984:     None
        !          5985: 
        !          5986: --*/
        !          5987: 
        !          5988: {
        !          5989:     va_list ap;
        !          5990: 
        !          5991:     va_start( ap, DebugMessage );
        !          5992: 
        !          5993:     if (DebugPrintLevel <= CdAudioDebug) {
        !          5994: 
        !          5995:         char buffer[128];
        !          5996: 
        !          5997:         vsprintf(buffer, DebugMessage, ap);
        !          5998:         DbgPrint(buffer);
        !          5999:     }
        !          6000: 
        !          6001:     va_end(ap);
        !          6002: 
        !          6003: } // end CdAudioDebugPrint
        !          6004: 
        !          6005: #endif // DBG

unix.superglobalmegacorp.com

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