Annotation of ntddk/src/scsi/scsicdrm/cdrom.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1991  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     cdrom.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     The CDROM class driver tranlates IRPs to SRBs with embedded CDBs
                     12:     and sends them to its devices through the port driver.
                     13: 
                     14: Author:
                     15: 
                     16:     Mike Glass (mglass)
                     17: 
                     18: Environment:
                     19: 
                     20:     kernel mode only
                     21: 
                     22: Notes:
                     23: 
                     24:     SCSI Tape, CDRom and Disk class drivers share common routines
                     25:     that can be found in the CLASS directory (..\ntos\dd\class).
                     26: 
                     27: Revision History:
                     28: 
                     29: --*/
                     30: 
                     31: #include "ntddk.h"
                     32: #include "scsi.h"
                     33: #include "class.h"
                     34: #include "string.h"
                     35: 
                     36: #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(BOOLEAN)
                     37: #define SCSI_CDROM_TIMEOUT  10
                     38: #define HITACHI_MODE_DATA_SIZE 12
                     39: #define MODE_DATA_SIZE 64
                     40: 
                     41: #define PLAY_ACTIVE(DeviceExtension) *((PBOOLEAN) (DeviceExtension+1))
                     42: 
                     43: 
                     44: NTSTATUS
                     45: DriverEntry(
                     46:     IN PDRIVER_OBJECT DriverObject,
                     47:     IN PUNICODE_STRING RegistryPath
                     48:     );
                     49: 
                     50: BOOLEAN
                     51: FindScsiCdRoms(
                     52:     IN PDRIVER_OBJECT DriveObject,
                     53:     IN PDEVICE_OBJECT PortDeviceObject,
                     54:     IN UCHAR PortNumber
                     55:     );
                     56: 
                     57: NTSTATUS
                     58: ScsiCdRomOpenClose(
                     59:     IN PDEVICE_OBJECT DeviceObject,
                     60:     IN PIRP Irp
                     61:     );
                     62: 
                     63: NTSTATUS
                     64: ScsiCdRomRead(
                     65:     IN PDEVICE_OBJECT DeviceObject,
                     66:     IN PIRP Irp
                     67:     );
                     68: 
                     69: NTSTATUS
                     70: ScsiCdRomDeviceControl(
                     71:     IN PDEVICE_OBJECT DeviceObject,
                     72:     IN PIRP Irp
                     73:     );
                     74: 
                     75: NTSTATUS
                     76: CreateCdRomDeviceObject(
                     77:     IN PDRIVER_OBJECT DriverObject,
                     78:     IN PDEVICE_OBJECT PortDeviceObject,
                     79:     IN UCHAR PortNumber,
                     80:     IN PULONG DeviceCount,
                     81:     PIO_SCSI_CAPABILITIES PortCapabilities,
                     82:     IN PSCSI_INQUIRY_DATA LunInfo
                     83:     );
                     84: 
                     85: NTSTATUS
                     86: GetTableOfContents(
                     87:     IN PDEVICE_OBJECT DeviceObject
                     88:     );
                     89: 
                     90: VOID
                     91: ScanForSpecial(
                     92:     PDEVICE_OBJECT DeviceObject,
                     93:     PINQUIRYDATA InquiryData,
                     94:     PIO_SCSI_CAPABILITIES PortCapabilities
                     95:     );
                     96: 
                     97: BOOLEAN
                     98: CdRomIsPlayActive(
                     99:     IN PDEVICE_OBJECT DeviceObject
                    100:     );
                    101: 
                    102: VOID
                    103: HitachProcessError(
                    104:     PDEVICE_OBJECT DeviceObject,
                    105:     PSCSI_REQUEST_BLOCK Srb,
                    106:     NTSTATUS *Status,
                    107:     BOOLEAN *Retry
                    108:     );
                    109: 
                    110: #ifdef ALLOC_PRAGMA
                    111: #pragma alloc_text(init, DriverEntry)
                    112: #pragma alloc_text(init, FindScsiCdRoms)
                    113: #pragma alloc_text(init, CreateCdRomDeviceObject)
                    114: #pragma alloc_text(init, ScanForSpecial)
                    115: #endif
                    116: 
                    117: 
                    118: NTSTATUS
                    119: DriverEntry(
                    120:     IN PDRIVER_OBJECT DriverObject,
                    121:     IN PUNICODE_STRING RegistryPath
                    122:     )
                    123: 
                    124: /*++
                    125: 
                    126: Routine Description:
                    127: 
                    128:     This routine initializes the CD-Rom class driver. The class
                    129:     driver opens the port driver by name and then receives
                    130:     configuration information used to attach to the CDROM devices.
                    131: 
                    132: Arguments:
                    133: 
                    134:     DriverObject
                    135: 
                    136: Return Value:
                    137: 
                    138:     NT Status
                    139: 
                    140: --*/
                    141: 
                    142: {
                    143:     UCHAR portNumber = 0;
                    144:     NTSTATUS status;
                    145:     PFILE_OBJECT fileObject;
                    146:     PDEVICE_OBJECT portDeviceObject;
                    147:     STRING deviceNameString;
                    148:     CCHAR deviceNameBuffer[256];
                    149:     UNICODE_STRING unicodeDeviceName;
                    150:     BOOLEAN foundOne = FALSE;
                    151: 
                    152:     DebugPrint((1,"\n\nSCSI CdRom Class Driver\n"));
                    153: 
                    154:     //
                    155:     // Set up the device driver entry points.
                    156:     //
                    157: 
                    158:     DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiCdRomOpenClose;
                    159:     DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiCdRomOpenClose;
                    160:     DriverObject->MajorFunction[IRP_MJ_READ] = ScsiCdRomRead;
                    161:     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiCdRomDeviceControl;
                    162:     DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassInternalIoControl;
                    163: 
                    164: 
                    165:     //
                    166:     // Open port driver device objects by name.
                    167:     //
                    168: 
                    169:     do {
                    170: 
                    171:         //
                    172:         // Create port driver name.
                    173:         //
                    174: 
                    175:         sprintf(deviceNameBuffer,
                    176:                 "\\Device\\ScsiPort%d",
                    177:                 portNumber);
                    178: 
                    179:         DebugPrint((2,"ScsiCdRomInitialize: Open %s\n",
                    180:                     deviceNameBuffer));
                    181: 
                    182:         RtlInitString(&deviceNameString,
                    183:                       deviceNameBuffer);
                    184: 
                    185:         status = RtlAnsiStringToUnicodeString(&unicodeDeviceName,
                    186:                                               &deviceNameString,
                    187:                                               TRUE);
                    188: 
                    189:         if (!NT_SUCCESS(status)) {
                    190:             break;
                    191:         }
                    192: 
                    193:         status = IoGetDeviceObjectPointer(&unicodeDeviceName,
                    194:                                           FILE_READ_ATTRIBUTES,
                    195:                                           &fileObject,
                    196:                                           &portDeviceObject);
                    197: 
                    198:         RtlFreeUnicodeString(&unicodeDeviceName);
                    199: 
                    200:         if (NT_SUCCESS(status)) {
                    201: 
                    202:             //
                    203:             // SCSI port driver exists.
                    204:             //
                    205: 
                    206:             if (FindScsiCdRoms(DriverObject,
                    207:                                portDeviceObject,
                    208:                                portNumber++)) {
                    209: 
                    210:                 foundOne = TRUE;
                    211:             }
                    212: 
                    213:             //
                    214:             // Dereference the file object since the port device pointer is no
                    215:             // longer needed.  The claim device code references the port driver
                    216:             // pointer that is actually being used.
                    217:             //
                    218: 
                    219:             ObDereferenceObject(fileObject);
                    220:         }
                    221: 
                    222:     } while (NT_SUCCESS(status));
                    223: 
                    224:     if (foundOne) {
                    225:         return STATUS_SUCCESS;
                    226:     } else {
                    227:         return STATUS_NO_SUCH_DEVICE;
                    228:     }
                    229: 
                    230: } // end DriverEntry()
                    231: 
                    232: 
                    233: BOOLEAN
                    234: FindScsiCdRoms(
                    235:     IN PDRIVER_OBJECT DriverObject,
                    236:     IN PDEVICE_OBJECT PortDeviceObject,
                    237:     IN UCHAR PortNumber
                    238:     )
                    239: 
                    240: /*++
                    241: 
                    242: Routine Description:
                    243: 
                    244:     Connect to SCSI port driver. Get adapter capabilities and
                    245:     SCSI bus configuration information. Search inquiry data
                    246:     for CDROM devices to process.
                    247: 
                    248: Arguments:
                    249: 
                    250:     DriverObject - CDROM class driver object.
                    251:     PortDeviceObject - SCSI port driver device object.
                    252:     PortNumber - The system ordinal for this scsi adapter.
                    253: 
                    254: Return Value:
                    255: 
                    256:     TRUE if CDROM device present on this SCSI adapter.
                    257: 
                    258: --*/
                    259: 
                    260: {
                    261:     PIO_SCSI_CAPABILITIES portCapabilities;
                    262:     PULONG cdRomCount;
                    263:     PCHAR buffer;
                    264:     PSCSI_INQUIRY_DATA lunInfo;
                    265:     PSCSI_ADAPTER_BUS_INFO  adapterInfo;
                    266:     PINQUIRYDATA inquiryData;
                    267:     ULONG scsiBus;
                    268:     NTSTATUS status;
                    269:     BOOLEAN foundDevice = FALSE;
                    270: 
                    271:     //
                    272:     // Call port driver to get adapter capabilities.
                    273:     //
                    274: 
                    275:     status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
                    276: 
                    277:     if (!NT_SUCCESS(status)) {
                    278:         DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
                    279:         return foundDevice;
                    280:     }
                    281: 
                    282:     //
                    283:     // Call port driver to get inquiry information to find cdroms.
                    284:     //
                    285: 
                    286:     status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer);
                    287: 
                    288:     if (!NT_SUCCESS(status)) {
                    289:         DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
                    290:         return foundDevice;
                    291:     }
                    292: 
                    293:     //
                    294:     // Get the address of the count of the number of cdroms already initialized.
                    295:     //
                    296: 
                    297:     cdRomCount = &IoGetConfigurationInformation()->CdRomCount;
                    298:     adapterInfo = (PVOID) buffer;
                    299: 
                    300:     //
                    301:     // For each SCSI bus this adapter supports ...
                    302:     //
                    303: 
                    304:     for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) {
                    305: 
                    306:         //
                    307:         // Get the SCSI bus scan data for this bus.
                    308:         //
                    309: 
                    310:         lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
                    311: 
                    312:         //
                    313:         // Search list for unclaimed disk devices.
                    314:         //
                    315: 
                    316:         while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
                    317: 
                    318:             inquiryData = (PVOID)lunInfo->InquiryData;
                    319: 
                    320:             if ((inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
                    321:                 (!lunInfo->DeviceClaimed)) {
                    322: 
                    323:                 DebugPrint((1,"FindScsiDevices: Vendor string is %.24s\n",
                    324:                             inquiryData->VendorId));
                    325: 
                    326:                 //
                    327:                 // Create device objects for cdrom
                    328:                 //
                    329: 
                    330:                 status = CreateCdRomDeviceObject(DriverObject,
                    331:                                                  PortDeviceObject,
                    332:                                                  PortNumber,
                    333:                                                  cdRomCount,
                    334:                                                  portCapabilities,
                    335:                                                  lunInfo);
                    336: 
                    337:                 if (NT_SUCCESS(status)) {
                    338: 
                    339:                     //
                    340:                     // Increment system cdrom device count.
                    341:                     //
                    342: 
                    343:                     (*cdRomCount)++;
                    344: 
                    345:                     //
                    346:                     // Indicate that a cdrom device was found.
                    347:                     //
                    348: 
                    349:                     foundDevice = TRUE;
                    350:                 }
                    351:             }
                    352: 
                    353:             //
                    354:             // Get next LunInfo.
                    355:             //
                    356: 
                    357:             if (lunInfo->NextInquiryDataOffset == 0) {
                    358:                 break;
                    359:             }
                    360: 
                    361:             lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
                    362:         }
                    363:     }
                    364: 
                    365:     ExFreePool(buffer);
                    366: 
                    367:     return foundDevice;
                    368: 
                    369: } // end FindScsiCdRoms()
                    370: 
                    371: 
                    372: NTSTATUS
                    373: CreateCdRomDeviceObject(
                    374:     IN PDRIVER_OBJECT DriverObject,
                    375:     IN PDEVICE_OBJECT PortDeviceObject,
                    376:     IN UCHAR PortNumber,
                    377:     IN PULONG DeviceCount,
                    378:     IN PIO_SCSI_CAPABILITIES PortCapabilities,
                    379:     IN PSCSI_INQUIRY_DATA LunInfo
                    380:     )
                    381: 
                    382: /*++
                    383: 
                    384: Routine Description:
                    385: 
                    386:     This routine creates an object for the device and then calls the
                    387:     SCSI port driver for media capacity and sector size.
                    388: 
                    389: Arguments:
                    390: 
                    391:     DriverObject - Pointer to driver object created by system.
                    392:     PortDeviceObject - to connect to SCSI port driver.
                    393:     DeviceCount - Number of previously installed CDROMs.
                    394:     PortCapabilities - Pointer to structure returned by SCSI port
                    395:         driver describing adapter capabilites (and limitations).
                    396:     LunInfo - Pointer to configuration information for this device.
                    397: 
                    398: Return Value:
                    399: 
                    400:     NTSTATUS
                    401: 
                    402: --*/
                    403: {
                    404:     UCHAR ntNameBuffer[64];
                    405:     UCHAR arcNameBuffer[64];
                    406:     STRING ntNameString;
                    407:     STRING arcNameString;
                    408:     UNICODE_STRING ntUnicodeString;
                    409:     UNICODE_STRING arcUnicodeString;
                    410:     NTSTATUS status;
                    411:     PDEVICE_OBJECT deviceObject = NULL;
                    412:     PDEVICE_EXTENSION deviceExtension;
                    413:     PVOID senseData = NULL;
                    414: 
                    415:     //
                    416:     // Claim the device.
                    417:     //
                    418: 
                    419:     status = ScsiClassClaimDevice(
                    420:         PortDeviceObject,
                    421:         LunInfo,
                    422:         FALSE,
                    423:         &PortDeviceObject
                    424:         );
                    425: 
                    426:     if (!NT_SUCCESS(status)) {
                    427:         return(status);
                    428:     }
                    429: 
                    430: 
                    431:     //
                    432:     // Create device object for this device.
                    433:     //
                    434: 
                    435:     sprintf(ntNameBuffer,
                    436:             "\\Device\\CdRom%d",
                    437:             *DeviceCount);
                    438: 
                    439:     RtlInitString(&ntNameString,
                    440:                   ntNameBuffer);
                    441: 
                    442:     DebugPrint((2,"CreateCdRomDeviceObjects: Create device object %s\n",
                    443:                 ntNameBuffer));
                    444: 
                    445:     //
                    446:     // Convert ANSI string to Unicode.
                    447:     //
                    448: 
                    449:     status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
                    450:                                           &ntNameString,
                    451:                                           TRUE);
                    452: 
                    453:     if (!NT_SUCCESS(status)) {
                    454: 
                    455:         DebugPrint((1,
                    456:                     "CreateDiskDeviceObjects: Cannot convert string %s\n",
                    457:                     ntNameBuffer));
                    458: 
                    459:         //
                    460:         // Release the device since an error occured.
                    461:         //
                    462: 
                    463:         ScsiClassClaimDevice(
                    464:             PortDeviceObject,
                    465:             LunInfo,
                    466:             TRUE,
                    467:             NULL
                    468:             );
                    469: 
                    470:             return(status);
                    471:     }
                    472: 
                    473:     //
                    474:     // Create device object for this CDROM.
                    475:     //
                    476: 
                    477:     status = IoCreateDevice(DriverObject,
                    478:                             DEVICE_EXTENSION_SIZE,
                    479:                             &ntUnicodeString,
                    480:                             FILE_DEVICE_CD_ROM,
                    481:                             FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE,
                    482:                             FALSE,
                    483:                             &deviceObject);
                    484: 
                    485: 
                    486:     if (!NT_SUCCESS(status)) {
                    487:         DebugPrint((1,"CreateCdRomDeviceObjects: Can not create device %s\n",
                    488:                     ntNameBuffer));
                    489: 
                    490:         RtlFreeUnicodeString(&ntUnicodeString);
                    491:         deviceObject = NULL;
                    492:         goto CreateCdRomDeviceObjectExit;
                    493:     }
                    494: 
                    495:     //
                    496:     // Indicate that IRPs should include MDLs.
                    497:     //
                    498: 
                    499:     deviceObject->Flags |= DO_DIRECT_IO;
                    500: 
                    501:     //
                    502:     // Set up required stack size in device object.
                    503:     //
                    504: 
                    505:     deviceObject->StackSize = PortDeviceObject->StackSize + 1;
                    506: 
                    507:     deviceExtension = deviceObject->DeviceExtension;
                    508: 
                    509:     //
                    510:     // Allocate spinlock for split request completion.
                    511:     //
                    512: 
                    513:     KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
                    514: 
                    515:     //
                    516:     // This is the physical device.
                    517:     //
                    518: 
                    519:     deviceExtension->PhysicalDevice = deviceObject;
                    520: 
                    521:     //
                    522:     // Copy port device object to device extension.
                    523:     //
                    524: 
                    525:     deviceExtension->PortDeviceObject = PortDeviceObject;
                    526: 
                    527:     //
                    528:     // Set the alignment requirements for the device based on the
                    529:     // host adapter requirements
                    530:     //
                    531: 
                    532:     if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
                    533:         deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
                    534:     }
                    535: 
                    536:     //
                    537:     // Save address of port driver capabilities.
                    538:     //
                    539: 
                    540:     deviceExtension->PortCapabilities = PortCapabilities;
                    541: 
                    542:     //
                    543:     // Disable synchronous transfer for CDROM requests.
                    544:     //
                    545: 
                    546:     deviceExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
                    547: 
                    548:     //
                    549:     // Allocate request sense buffer.
                    550:     //
                    551: 
                    552:     senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
                    553: 
                    554:     if (senseData == NULL) {
                    555: 
                    556:         //
                    557:         // The buffer cannot be allocated.
                    558:         //
                    559: 
                    560:         status = STATUS_INSUFFICIENT_RESOURCES;
                    561:         goto CreateCdRomDeviceObjectExit;
                    562:     }
                    563: 
                    564:     //
                    565:     // Set the sense data pointer in the device extension.
                    566:     //
                    567: 
                    568:     deviceExtension->SenseData = senseData;
                    569: 
                    570:     //
                    571:     // CDROMs are not partitionable so starting offset is 0.
                    572:     //
                    573: 
                    574:     deviceExtension->StartingOffset.LowPart = 0;
                    575:     deviceExtension->StartingOffset.HighPart = 0;
                    576: 
                    577:     //
                    578:     // Path/TargetId/LUN describes a device location on the SCSI bus.
                    579:     // This information comes from the LunInfo buffer.
                    580:     //
                    581: 
                    582:     deviceExtension->PortNumber = PortNumber;
                    583:     deviceExtension->PathId = LunInfo->PathId;
                    584:     deviceExtension->TargetId = LunInfo->TargetId;
                    585:     deviceExtension->Lun = LunInfo->Lun;
                    586: 
                    587:     //
                    588:     // Set timeout value in seconds.
                    589:     //
                    590: 
                    591:     deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
                    592: 
                    593:     //
                    594:     // Back pointer to device object.
                    595:     //
                    596: 
                    597:     deviceExtension->DeviceObject = deviceObject;
                    598: 
                    599:     //
                    600:     // Create a symbolic link from the cdrom name to the corresponding
                    601:     // ARC name, to be used if we're booting off the cdrom.  This will
                    602:     // fail if it's not system initialization time; that's fine.  The
                    603:     // ARC name looks something like \ArcName\scsi(0)cdrom(0)fdisk(0).
                    604:     //
                    605: 
                    606:     sprintf(arcNameBuffer,
                    607:             "\\ArcName\\scsi(%d)cdrom(%d)fdisk(%d)",
                    608:             PortNumber,
                    609:             LunInfo->TargetId + LunInfo->PathId * SCSI_MAXIMUM_TARGETS_PER_BUS,
                    610:             LunInfo->Lun);
                    611: 
                    612:     RtlInitString(&arcNameString, arcNameBuffer);
                    613: 
                    614:     status = RtlAnsiStringToUnicodeString(&arcUnicodeString,
                    615:                                           &arcNameString,
                    616:                                           TRUE);
                    617: 
                    618:     if (!NT_SUCCESS(status)) {
                    619: 
                    620:         DebugPrint((1,
                    621:                     "CreateCdRomDeviceObjects: Cannot convert string %s\n",
                    622:                     arcNameBuffer));
                    623: 
                    624:         RtlFreeUnicodeString(&ntUnicodeString);
                    625: 
                    626:         goto CreateCdRomDeviceObjectExit;
                    627:     }
                    628: 
                    629:     IoAssignArcName(&arcUnicodeString, &ntUnicodeString);
                    630: 
                    631:     RtlFreeUnicodeString(&ntUnicodeString);
                    632:     RtlFreeUnicodeString(&arcUnicodeString);
                    633: 
                    634:     //
                    635:     // Allocate buffer for drive geometry.
                    636:     //
                    637: 
                    638:     deviceExtension->DiskGeometry =
                    639:         ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY));
                    640: 
                    641:     if (deviceExtension->DiskGeometry == NULL) {
                    642: 
                    643:         status = STATUS_INSUFFICIENT_RESOURCES;
                    644:         goto CreateCdRomDeviceObjectExit;
                    645:     }
                    646: 
                    647:     //
                    648:     // Scan for Scsi controllers that require special processing.
                    649:     //
                    650: 
                    651:     ScanForSpecial(deviceObject,
                    652:                    (PINQUIRYDATA) LunInfo->InquiryData,
                    653:                    PortCapabilities);
                    654: 
                    655:     //
                    656:     // Do READ CAPACITY. This SCSI command
                    657:     // returns the last sector address on the device
                    658:     // and the bytes per sector.
                    659:     // These are used to calculate the drive capacity
                    660:     // in bytes.
                    661:     //
                    662: 
                    663:     status = ScsiClassReadDriveCapacity(deviceObject);
                    664: 
                    665:     if ((!NT_SUCCESS(status)) ||
                    666:         (deviceExtension->DiskGeometry->BytesPerSector == 0)) {
                    667: 
                    668:         DebugPrint((1,
                    669:                 "CreateCdRomDeviceObjects: Can't read capacity for device %s\n",
                    670:                 ntNameBuffer));
                    671: 
                    672:         //
                    673:         // Set disk geometry to default values (per ISO 9660).
                    674:         //
                    675: 
                    676:         deviceExtension->DiskGeometry->BytesPerSector = 2048;
                    677:         deviceExtension->SectorShift = 11;
                    678: 
                    679:     }
                    680: 
                    681:     return(STATUS_SUCCESS);
                    682: 
                    683: CreateCdRomDeviceObjectExit:
                    684: 
                    685:     //
                    686:     // Release the device since an error occured.
                    687:     //
                    688: 
                    689:     ScsiClassClaimDevice(
                    690:         PortDeviceObject,
                    691:         LunInfo,
                    692:         TRUE,
                    693:         NULL
                    694:         );
                    695: 
                    696:     if (senseData != NULL) {
                    697:         ExFreePool(senseData);
                    698:     }
                    699: 
                    700:     if (deviceExtension->DiskGeometry != NULL) {
                    701:         ExFreePool(deviceExtension->DiskGeometry);
                    702:     }
                    703: 
                    704:     if (deviceObject != NULL) {
                    705:         IoDeleteDevice(deviceObject);
                    706:     }
                    707: 
                    708: 
                    709:     return status;
                    710: 
                    711: } // end CreateCdromDeviceObject()
                    712: 
                    713: 
                    714: NTSTATUS
                    715: ScsiCdRomOpenClose(
                    716:     IN PDEVICE_OBJECT DeviceObject,
                    717:     IN PIRP Irp
                    718:     )
                    719: 
                    720: /*++
                    721: 
                    722: Routine Description:
                    723: 
                    724:     This routine is called to establish a connection to the CDROM
                    725:     class driver. It does no more than return STATUS_SUCCESS.
                    726: 
                    727: Arguments:
                    728: 
                    729:     DeviceObject - Device object for CDROM drive
                    730:     Irp - Open or Close request packet
                    731: 
                    732: Return Value:
                    733: 
                    734:     NT Status - STATUS_SUCCESS
                    735: 
                    736: --*/
                    737: 
                    738: {
                    739:     //
                    740:     // Set status in Irp.
                    741:     //
                    742: 
                    743:     Irp->IoStatus.Status = STATUS_SUCCESS;
                    744: 
                    745:     //
                    746:     // Complete request at raised IRQ.
                    747:     //
                    748: 
                    749:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
                    750:     return STATUS_SUCCESS;
                    751: 
                    752: } // end ScsiCdRomOpenClose()
                    753: 
                    754: 
                    755: NTSTATUS
                    756: ScsiCdRomRead(
                    757:     IN PDEVICE_OBJECT DeviceObject,
                    758:     IN PIRP Irp
                    759:     )
                    760: 
                    761: /*++
                    762: 
                    763: Routine Description:
                    764: 
                    765:     This is the entry called by the I/O system for read requests.
                    766:     It builds the SRB and sends it to the port driver.
                    767: 
                    768: Arguments:
                    769: 
                    770:     DeviceObject - the system object for the device.
                    771:     Irp - IRP involved.
                    772: 
                    773: Return Value:
                    774: 
                    775:     NT Status
                    776: 
                    777: --*/
                    778: 
                    779: {
                    780:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                    781:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
                    782:     ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
                    783:     LARGE_INTEGER startingOffset;
                    784:     ULONG maximumTransferLength =
                    785:         deviceExtension->PortCapabilities->MaximumTransferLength;
                    786:     ULONG transferPages;
                    787: 
                    788:     //
                    789:     // If the cd is playing music then reject this request.
                    790:     //
                    791: 
                    792:     if (PLAY_ACTIVE(deviceExtension)) {
                    793:         Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
                    794:         IoCompleteRequest(Irp, IO_NO_INCREMENT);
                    795:         return STATUS_DEVICE_BUSY;
                    796:     }
                    797: 
                    798:     //
                    799:     // Check if volume needs verification.
                    800:     //
                    801: 
                    802:     if ((DeviceObject->Flags & DO_VERIFY_VOLUME) &&
                    803:         !(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
                    804: 
                    805:         //
                    806:         // if DO_VERIFY_VOLUME bit is set
                    807:         // in device object flags, fail request.
                    808:         //
                    809: 
                    810:         DebugPrint((2,"ScsiCdRomRead: Volume verfication needed\n"));
                    811: 
                    812:         IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
                    813: 
                    814:         Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
                    815:         Irp->IoStatus.Information = 0;
                    816: 
                    817:         IoCompleteRequest(Irp, IO_NO_INCREMENT);
                    818:         return STATUS_VERIFY_REQUIRED;
                    819:     }
                    820: 
                    821:     //
                    822:     // Verify parameters of this request.
                    823:     // Check that ending sector is on disc and
                    824:     // that number of bytes to transfer is a multiple of
                    825:     // the sector size.
                    826:     //
                    827: 
                    828:     startingOffset = LiFromUlong(transferByteCount);
                    829:     startingOffset = LiAdd(startingOffset,
                    830:                            currentIrpStack->Parameters.Read.ByteOffset);
                    831: 
                    832:     if (LiGtr( startingOffset, deviceExtension->PartitionLength) ||
                    833:         (transferByteCount & deviceExtension->DiskGeometry->BytesPerSector - 1)) {
                    834: 
                    835:         DebugPrint((1,"ScsiCdRomRead: Invalid I/O parameters\n"));
                    836: 
                    837:         //
                    838:         // Fail request with status of invalid parameters.
                    839:         //
                    840: 
                    841:         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                    842: 
                    843:         IoCompleteRequest(Irp, IO_NO_INCREMENT);
                    844:         return STATUS_INVALID_PARAMETER;
                    845:     }
                    846: 
                    847:     //
                    848:     // Mark IRP with status pending.
                    849:     //
                    850: 
                    851:     IoMarkIrpPending(Irp);
                    852: 
                    853:     //
                    854:     // Calculate number of pages in this transfer.
                    855:     //
                    856: 
                    857:     transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
                    858:         MmGetMdlVirtualAddress(Irp->MdlAddress),
                    859:         currentIrpStack->Parameters.Read.Length);
                    860: 
                    861:     //
                    862:     // Check if request length is greater than the maximum number of
                    863:     // bytes that the hardware can transfer.
                    864:     //
                    865: 
                    866:     if (currentIrpStack->Parameters.Read.Length > maximumTransferLength ||
                    867:         transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
                    868: 
                    869:          DebugPrint((2,"ScsiCdromRead: Request greater than maximum\n"));
                    870:          DebugPrint((2,"ScsiCdromRead: Maximum is %lx\n",
                    871:                      maximumTransferLength));
                    872:          DebugPrint((2,"ScsiCdromRead: Byte count is %lx\n",
                    873:                      currentIrpStack->Parameters.Read.Length));
                    874: 
                    875:          transferPages =
                    876:             deviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
                    877: 
                    878:          if (maximumTransferLength > transferPages << PAGE_SHIFT ) {
                    879:              maximumTransferLength = transferPages << PAGE_SHIFT;
                    880:          }
                    881: 
                    882:         //
                    883:         // Check that maximum transfer size is not zero.
                    884:         //
                    885: 
                    886:         if (maximumTransferLength == 0) {
                    887:             maximumTransferLength = PAGE_SIZE;
                    888:         }
                    889: 
                    890:         //
                    891:         // Mark IRP with status pending.
                    892:         //
                    893: 
                    894:         IoMarkIrpPending(Irp);
                    895: 
                    896:         //
                    897:         // Request greater than port driver maximum.
                    898:         // Break up into smaller routines.
                    899:         //
                    900: 
                    901:         ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength);
                    902: 
                    903: 
                    904:         return STATUS_PENDING;
                    905:     }
                    906: 
                    907:     //
                    908:     // Build SRB and CDB for this IRP.
                    909:     //
                    910: 
                    911:     ScsiClassBuildRequest(DeviceObject, Irp);
                    912: 
                    913:     //
                    914:     // Return the results of the call to the port driver.
                    915:     //
                    916: 
                    917:     return IoCallDriver(deviceExtension->PortDeviceObject, Irp);
                    918: 
                    919: } // end ScsiCdRomRead()
                    920: 
                    921: 
                    922: NTSTATUS
                    923: ScsiCdRomDeviceControl(
                    924:     IN PDEVICE_OBJECT DeviceObject,
                    925:     IN PIRP Irp
                    926:     )
                    927: 
                    928: /*++
                    929: 
                    930: Routine Description:
                    931: 
                    932:     This is the NT device control handler for CDROMs.
                    933: 
                    934: Arguments:
                    935: 
                    936:     DeviceObject - for this CDROM
                    937: 
                    938:     Irp - IO Request packet
                    939: 
                    940: Return Value:
                    941: 
                    942:     NTSTATUS
                    943: 
                    944: --*/
                    945: 
                    946: {
                    947:     PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
                    948:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                    949:     SCSI_REQUEST_BLOCK srb;
                    950:     PCDB cdb = (PCDB)srb.Cdb;
                    951:     PVOID outputBuffer;
                    952:     ULONG bytesTransferred = 0;
                    953:     NTSTATUS status;
                    954:     NTSTATUS status2;
                    955: 
                    956: RetryControl:
                    957: 
                    958:     //
                    959:     // Zero the SRB on stack.
                    960:     //
                    961: 
                    962:     RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
                    963: 
                    964:     Irp->IoStatus.Information = 0;
                    965: 
                    966:     switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
                    967: 
                    968:     case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
                    969: 
                    970:         DebugPrint((2,"ScsiCdRomDeviceControl: Get drive geometry\n"));
                    971: 
                    972:         if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
                    973:             sizeof( DISK_GEOMETRY ) ) {
                    974: 
                    975:             status = STATUS_INFO_LENGTH_MISMATCH;
                    976:             break;
                    977:         }
                    978: 
                    979:         //
                    980:         // Issue ReadCapacity to update device extension
                    981:         // with information for current media.
                    982:         //
                    983: 
                    984:         status = ScsiClassReadDriveCapacity(DeviceObject);
                    985: 
                    986:         if ((!NT_SUCCESS(status)) ||
                    987:             (deviceExtension->DiskGeometry->BytesPerSector == 0)) {
                    988:     
                    989:             //
                    990:             // Set disk geometry to default values (per ISO 9660).
                    991:             //
                    992:     
                    993:             deviceExtension->DiskGeometry->BytesPerSector = 2048;
                    994:             deviceExtension->SectorShift = 11;
                    995:         }
                    996:     
                    997:         //
                    998:         // Copy drive geometry information from device extension.
                    999:         //
                   1000: 
                   1001:         RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
                   1002:                       deviceExtension->DiskGeometry,
                   1003:                       sizeof(DISK_GEOMETRY));
                   1004: 
                   1005:         status = STATUS_SUCCESS;
                   1006:         Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
                   1007: 
                   1008:         break;
                   1009: 
                   1010:     case IOCTL_CDROM_GET_LAST_SESSION:
                   1011: 
                   1012:         //
                   1013:         // Set format to return first and last session numbers.
                   1014:         //
                   1015: 
                   1016:         cdb->READ_TOC.Format = GET_LAST_SESSION;
                   1017: 
                   1018:         //
                   1019:         // Fall through to READ TOC code.
                   1020:         //
                   1021: 
                   1022:     case IOCTL_CDROM_READ_TOC:
                   1023: 
                   1024:         {
                   1025:             PCDROM_TOC toc = Irp->AssociatedIrp.SystemBuffer;
                   1026:             ULONG transferBytes;
                   1027: 
                   1028:             DebugPrint((2,"CdRomDeviceControl: Read TOC\n"));
                   1029: 
                   1030:             //
                   1031:             // If the cd is playing music then reject this request.
                   1032:             //
                   1033: 
                   1034:             if (CdRomIsPlayActive(DeviceObject)) {
                   1035:                 Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
                   1036:                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
                   1037:                 return STATUS_DEVICE_BUSY;
                   1038:             }
                   1039: 
                   1040:             //
                   1041:             // Read TOC is 10 byte CDB.
                   1042:             //
                   1043: 
                   1044:             srb.CdbLength = 10;
                   1045: 
                   1046:             cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC;
                   1047: 
                   1048:             if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) {
                   1049: 
                   1050:                 //
                   1051:                 // Use MSF addressing if not request for session information.
                   1052:                 //
                   1053: 
                   1054:                 cdb->READ_TOC.Msf = CDB_USE_MSF;
                   1055:             }
                   1056: 
                   1057:             //
                   1058:             // Start at beginning of disc.
                   1059:             //
                   1060: 
                   1061:             cdb->READ_TOC.StartingTrack = 0;
                   1062: 
                   1063:             //
                   1064:             // Set size of TOC structure.
                   1065:             //
                   1066: 
                   1067:             transferBytes =
                   1068:                 irpStack->Parameters.Read.Length >
                   1069:                     sizeof(CDROM_TOC) ? sizeof(CDROM_TOC):
                   1070:                     irpStack->Parameters.Read.Length;
                   1071: 
                   1072:             cdb->READ_TOC.AllocationLength[0] = (UCHAR) (transferBytes >> 8);
                   1073:             cdb->READ_TOC.AllocationLength[1] = (UCHAR) (transferBytes & 0xFF);
                   1074: 
                   1075:             cdb->READ_TOC.Control = 0;
                   1076: 
                   1077:             //
                   1078:             // Set timeout value.
                   1079:             //
                   1080: 
                   1081:             srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1082: 
                   1083:             status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1084:                                         &srb,
                   1085:                                         toc,
                   1086:                                         transferBytes,
                   1087:                                         FALSE);
                   1088: 
                   1089:             //
                   1090:             // Check for data underrun.
                   1091:             //
                   1092: 
                   1093:             if (status==STATUS_DATA_OVERRUN) {
                   1094:                 status = STATUS_SUCCESS;
                   1095:             }
                   1096: 
                   1097:             Irp->IoStatus.Information  = srb.DataTransferLength;
                   1098:         }
                   1099: 
                   1100:         break;
                   1101: 
                   1102:     case IOCTL_CDROM_PLAY_AUDIO_MSF:
                   1103: 
                   1104:         {
                   1105:             PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
                   1106: 
                   1107:             //
                   1108:             // Play Audio MSF
                   1109:             //
                   1110: 
                   1111:             DebugPrint((2,"ScsiCdRomDeviceControl: Play audio MSF\n"));
                   1112: 
                   1113:             if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1114:                 sizeof(CDROM_PLAY_AUDIO_MSF)) {
                   1115: 
                   1116:                 //
                   1117:                 // Indicate unsuccessful status.
                   1118:                 //
                   1119: 
                   1120:                 status = STATUS_BUFFER_TOO_SMALL;
                   1121:                 break;
                   1122:             }
                   1123: 
                   1124:             cdb->PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF;
                   1125: 
                   1126:             cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM;
                   1127:             cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS;
                   1128:             cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF;
                   1129: 
                   1130:             cdb->PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM;
                   1131:             cdb->PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS;
                   1132:             cdb->PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF;
                   1133: 
                   1134:             srb.CdbLength = 10;
                   1135: 
                   1136:             //
                   1137:             // Set timeout value.
                   1138:             //
                   1139: 
                   1140:             srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1141: 
                   1142:             status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1143:                           &srb,
                   1144:                           NULL,
                   1145:                           0,
                   1146:                           FALSE);
                   1147: 
                   1148:             if (NT_SUCCESS(status)) {
                   1149:                 PLAY_ACTIVE(deviceExtension) = TRUE;
                   1150:             }
                   1151:         }
                   1152: 
                   1153:         break;
                   1154: 
                   1155:     case IOCTL_CDROM_SEEK_AUDIO_MSF:
                   1156: 
                   1157:         {
                   1158:             PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
                   1159: 
                   1160:             //
                   1161:             // Seek Audio MSF
                   1162:             //
                   1163: 
                   1164:             DebugPrint((2,"ScsiCdRomDeviceControl: Seek audio MSF\n"));
                   1165: 
                   1166:             if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1167:                 sizeof(CDROM_SEEK_AUDIO_MSF)) {
                   1168: 
                   1169:                 //
                   1170:                 // Indicate unsuccessful status.
                   1171:                 //
                   1172: 
                   1173:                 status = STATUS_BUFFER_TOO_SMALL;
                   1174:                 break;
                   1175:             }
                   1176: 
                   1177:             cdb->PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF;
                   1178: 
                   1179:             cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->M;
                   1180:             cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->S;
                   1181:             cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->F;
                   1182: 
                   1183:             cdb->PLAY_AUDIO_MSF.EndingM = inputBuffer->M;
                   1184:             cdb->PLAY_AUDIO_MSF.EndingS = inputBuffer->S;
                   1185:             cdb->PLAY_AUDIO_MSF.EndingF = inputBuffer->F;
                   1186: 
                   1187:             srb.CdbLength = 10;
                   1188: 
                   1189:             //
                   1190:             // Set timeout value.
                   1191:             //
                   1192: 
                   1193:             srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1194: 
                   1195:             status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1196:                           &srb,
                   1197:                           NULL,
                   1198:                           0,
                   1199:                           FALSE);
                   1200: 
                   1201:         }
                   1202: 
                   1203:         break;
                   1204: 
                   1205:     case IOCTL_CDROM_PAUSE_AUDIO:
                   1206: 
                   1207:         //
                   1208:         // Pause audio
                   1209:         //
                   1210: 
                   1211:         DebugPrint((2, "ScsiCdRomDeviceControl: Pause audio\n"));
                   1212: 
                   1213:         PLAY_ACTIVE(deviceExtension) = FALSE;
                   1214: 
                   1215:         cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
                   1216: 
                   1217:         cdb->PAUSE_RESUME.Action = CDB_AUDIO_PAUSE;
                   1218: 
                   1219:         srb.CdbLength = 10;
                   1220: 
                   1221:         //
                   1222:         // Set timeout value.
                   1223:         //
                   1224: 
                   1225:         srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1226: 
                   1227:         status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1228:                           &srb,
                   1229:                           NULL,
                   1230:                           0,
                   1231:                           FALSE);
                   1232: 
                   1233:         break;
                   1234: 
                   1235:     case IOCTL_CDROM_RESUME_AUDIO:
                   1236: 
                   1237:         //
                   1238:         // Resume audio
                   1239:         //
                   1240: 
                   1241:         DebugPrint((2, "ScsiCdRomDeviceControl: Resume audio\n"));
                   1242: 
                   1243:         cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
                   1244: 
                   1245:         cdb->PAUSE_RESUME.Action = CDB_AUDIO_RESUME;
                   1246: 
                   1247:         srb.CdbLength = 10;
                   1248: 
                   1249:         //
                   1250:         // Set timeout value.
                   1251:         //
                   1252: 
                   1253:         srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1254: 
                   1255:         status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1256:                                     &srb,
                   1257:                                     NULL,
                   1258:                                     0,
                   1259:                                     FALSE);
                   1260: 
                   1261:         break;
                   1262: 
                   1263:     case IOCTL_CDROM_READ_Q_CHANNEL:
                   1264: 
                   1265:         {
                   1266: 
                   1267:         PSUB_Q_CHANNEL_DATA userChannelData =
                   1268:                          Irp->AssociatedIrp.SystemBuffer;
                   1269:         PCDROM_SUB_Q_DATA_FORMAT inputBuffer =
                   1270:                          Irp->AssociatedIrp.SystemBuffer;
                   1271:         PSUB_Q_CHANNEL_DATA subQPtr;
                   1272: 
                   1273:         //
                   1274:         // Allocate buffer for subq channel information.
                   1275:         //
                   1276: 
                   1277:         subQPtr = ExAllocatePool(NonPagedPoolCacheAligned,
                   1278:                                  sizeof(SUB_Q_CHANNEL_DATA));
                   1279: 
                   1280:         if (!subQPtr) {
                   1281:             status = STATUS_INSUFFICIENT_RESOURCES;
                   1282:             Irp->IoStatus.Information = 0;
                   1283:             break;
                   1284:         }
                   1285: 
                   1286:         //
                   1287:         // Read Subchannel Q
                   1288:         //
                   1289: 
                   1290:         DebugPrint((2,
                   1291:             "ScsiCdRomDeviceControl: Read channel Q Format %u\n", inputBuffer->Format ));
                   1292: 
                   1293:         cdb->SUBCHANNEL.OperationCode = SCSIOP_READ_SUB_CHANNEL;
                   1294: 
                   1295:         //
                   1296:         // Always logical unit 0, but only use MSF addressing
                   1297:         // for IOCTL_CDROM_CURRENT_POSITION
                   1298:         //
                   1299: 
                   1300:         if (inputBuffer->Format==IOCTL_CDROM_CURRENT_POSITION)
                   1301:             cdb->SUBCHANNEL.Msf = CDB_USE_MSF;
                   1302: 
                   1303:         //
                   1304:         // Return subchannel data
                   1305:         //
                   1306: 
                   1307:         cdb->SUBCHANNEL.SubQ = CDB_SUBCHANNEL_BLOCK;
                   1308: 
                   1309:         //
                   1310:         // Specify format of informatin to return
                   1311:         //
                   1312: 
                   1313:         cdb->SUBCHANNEL.Format = inputBuffer->Format;
                   1314: 
                   1315:         //
                   1316:         // Specify which track to access (only used by Track ISRC reads)
                   1317:         //
                   1318: 
                   1319:         if (inputBuffer->Format==IOCTL_CDROM_TRACK_ISRC)
                   1320:             cdb->SUBCHANNEL.TrackNumber = inputBuffer->Track;
                   1321: 
                   1322:         //
                   1323:         // Set size of channel data -- however, this is dependent on
                   1324:         // what information we are requesting (which Format)
                   1325:         //
                   1326: 
                   1327:         switch( inputBuffer->Format ) {
                   1328: 
                   1329:             case IOCTL_CDROM_CURRENT_POSITION:
                   1330:                 bytesTransferred = sizeof(SUB_Q_CURRENT_POSITION);
                   1331:                 break;
                   1332: 
                   1333:             case IOCTL_CDROM_MEDIA_CATALOG:
                   1334:                 bytesTransferred = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER);
                   1335:                 break;
                   1336: 
                   1337:             case IOCTL_CDROM_TRACK_ISRC:
                   1338:                 bytesTransferred = sizeof(SUB_Q_TRACK_ISRC);
                   1339:                 break;
                   1340:         }
                   1341: 
                   1342:         cdb->SUBCHANNEL.AllocationLength[0] = (UCHAR) (bytesTransferred >> 8);
                   1343:         cdb->SUBCHANNEL.AllocationLength[1] = (UCHAR) (bytesTransferred &  0xFF);
                   1344: 
                   1345:         srb.CdbLength = 10;
                   1346: 
                   1347:         //
                   1348:         // Set timeout value.
                   1349:         //
                   1350: 
                   1351:         srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1352: 
                   1353:         status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1354:                                     &srb,
                   1355:                                     subQPtr,
                   1356:                                     bytesTransferred,
                   1357:                                     FALSE);
                   1358: 
                   1359:         if (NT_SUCCESS(status)) {
                   1360: #if DBG
                   1361:             switch( inputBuffer->Format ) {
                   1362: 
                   1363:             case IOCTL_CDROM_CURRENT_POSITION:
                   1364:                 DebugPrint((3,"ScsiCdromDeviceControl: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus ));
                   1365:                 DebugPrint((3,"ScsiCdromDeviceControl: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR ));
                   1366:                 DebugPrint((3,"ScsiCdromDeviceControl: Control = 0x%x\n", subQPtr->CurrentPosition.Control ));
                   1367:                 DebugPrint((3,"ScsiCdromDeviceControl: Track = %u\n", subQPtr->CurrentPosition.TrackNumber ));
                   1368:                 DebugPrint((3,"ScsiCdromDeviceControl: Index = %u\n", subQPtr->CurrentPosition.IndexNumber ));
                   1369:                 break;
                   1370: 
                   1371:             case IOCTL_CDROM_MEDIA_CATALOG:
                   1372:                 DebugPrint((3,"ScsiCdromDeviceControl: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus ));
                   1373:                 DebugPrint((3,"ScsiCdromDeviceControl: Mcval is %u\n", subQPtr->MediaCatalog.Mcval ));
                   1374:                 break;
                   1375: 
                   1376:             case IOCTL_CDROM_TRACK_ISRC:
                   1377:                 DebugPrint((3,"ScsiCdromDeviceControl: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus ));
                   1378:                 DebugPrint((3,"ScsiCdromDeviceControl: Tcval is %u\n", subQPtr->TrackIsrc.Tcval ));
                   1379:                 break;
                   1380: 
                   1381:             }
                   1382: #endif
                   1383: 
                   1384:             //
                   1385:             // Update the play active status.
                   1386:             //
                   1387: 
                   1388:             if (subQPtr->CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) {
                   1389: 
                   1390:                 PLAY_ACTIVE(deviceExtension) = TRUE;
                   1391: 
                   1392:             } else {
                   1393: 
                   1394:                 PLAY_ACTIVE(deviceExtension) = FALSE;
                   1395: 
                   1396:             }
                   1397: 
                   1398:             //
                   1399:             // Check if output buffer is large enough to contain
                   1400:             // the data.
                   1401:             //
                   1402: 
                   1403:             if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
                   1404:                 bytesTransferred) {
                   1405: 
                   1406:                 bytesTransferred =
                   1407:                     irpStack->Parameters.DeviceIoControl.OutputBufferLength;
                   1408:             }
                   1409: 
                   1410:             RtlMoveMemory(userChannelData,
                   1411:                           subQPtr,
                   1412:                           bytesTransferred);
                   1413: 
                   1414:             Irp->IoStatus.Information = bytesTransferred;
                   1415:         } else {
                   1416: 
                   1417:             PLAY_ACTIVE(deviceExtension) = FALSE;
                   1418: 
                   1419:         }
                   1420: 
                   1421:         ExFreePool(subQPtr);
                   1422: 
                   1423:         break;
                   1424: 
                   1425:         }
                   1426: 
                   1427:     case IOCTL_CDROM_GET_CONTROL:
                   1428: 
                   1429:         DebugPrint((2, "ScsiCdRomDeviceControl: Get audio control\n"));
                   1430: 
                   1431:         //
                   1432:         // Verify user buffer is large enough for the data.
                   1433:         //
                   1434: 
                   1435:         if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
                   1436:             sizeof(CDROM_AUDIO_CONTROL)) {
                   1437: 
                   1438:             //
                   1439:             // Indicate unsuccessful status and no data transferred.
                   1440:             //
                   1441: 
                   1442:             status = STATUS_BUFFER_TOO_SMALL;
                   1443:             Irp->IoStatus.Information = 0;
                   1444: 
                   1445:         } else {
                   1446: 
                   1447:             PAUDIO_OUTPUT audioOutput;
                   1448:             PCDROM_AUDIO_CONTROL audioControl = Irp->AssociatedIrp.SystemBuffer;
                   1449: 
                   1450:             //
                   1451:             // Allocate buffer for volume control information.
                   1452:             //
                   1453: 
                   1454:             outputBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
                   1455:                                          MODE_DATA_SIZE);
                   1456: 
                   1457:             if (!outputBuffer) {
                   1458:                 status = STATUS_INSUFFICIENT_RESOURCES;
                   1459:                 Irp->IoStatus.Information = 0;
                   1460:                 break;
                   1461:             }
                   1462: 
                   1463:             //
                   1464:             // Get audio control information
                   1465:             //
                   1466: 
                   1467:             cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
                   1468:             cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE;
                   1469:             cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
                   1470: 
                   1471:             //
                   1472:             // Disable block descriptors.
                   1473:             //
                   1474: 
                   1475:             cdb->MODE_SENSE.Dbd = TRUE;
                   1476: 
                   1477:             srb.CdbLength = 6;
                   1478: 
                   1479:             //
                   1480:             // Set timeout value.
                   1481:             //
                   1482: 
                   1483:             srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1484: 
                   1485:             status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1486:                                         &srb,
                   1487:                                         outputBuffer,
                   1488:                                         MODE_DATA_SIZE,
                   1489:                                         FALSE);
                   1490: 
                   1491:             if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
                   1492:                 status = STATUS_SUCCESS;
                   1493:             }
                   1494: 
                   1495:             if (NT_SUCCESS(status)) {
                   1496: 
                   1497:                 audioOutput = ScsiClassFindModePage( outputBuffer,
                   1498:                                                      srb.DataTransferLength,
                   1499:                                                      CDROM_AUDIO_CONTROL_PAGE);
                   1500:                 //
                   1501:                 // Verify the page is as big as expected.
                   1502:                 //
                   1503: 
                   1504:                 bytesTransferred = (PCHAR) audioOutput - (PCHAR) outputBuffer +
                   1505:                     sizeof(AUDIO_OUTPUT);
                   1506: 
                   1507:                 if (audioOutput != NULL &&
                   1508:                     srb.DataTransferLength >= bytesTransferred) {
                   1509: 
                   1510:                     audioControl->LbaFormat = audioOutput->LbaFormat;
                   1511: 
                   1512:                     audioControl->LogicalBlocksPerSecond =
                   1513:                         (audioOutput->LogicalBlocksPerSecond[0] << (UCHAR)8) |
                   1514:                         audioOutput->LogicalBlocksPerSecond[1];
                   1515: 
                   1516:                     Irp->IoStatus.Information = sizeof(CDROM_AUDIO_CONTROL);
                   1517: 
                   1518:                 } else {
                   1519:                     status = STATUS_INVALID_DEVICE_REQUEST;
                   1520:                 }
                   1521: 
                   1522:             }
                   1523: 
                   1524:             ExFreePool(outputBuffer);
                   1525:         }
                   1526: 
                   1527:         break;
                   1528: 
                   1529:     case IOCTL_CDROM_GET_VOLUME:
                   1530: 
                   1531:         DebugPrint((2, "ScsiCdRomDeviceControl: Get volume control\n"));
                   1532: 
                   1533:         //
                   1534:         // Verify user buffer is large enough for data.
                   1535:         //
                   1536: 
                   1537:         if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
                   1538:             sizeof(VOLUME_CONTROL)) {
                   1539: 
                   1540:             //
                   1541:             // Indicate unsuccessful status and no data transferred.
                   1542:             //
                   1543: 
                   1544:             status = STATUS_BUFFER_TOO_SMALL;
                   1545:             Irp->IoStatus.Information = 0;
                   1546: 
                   1547:         } else {
                   1548: 
                   1549:             PAUDIO_OUTPUT audioOutput;
                   1550:             PVOLUME_CONTROL volumeControl = Irp->AssociatedIrp.SystemBuffer;
                   1551:             ULONG i;
                   1552: 
                   1553:             //
                   1554:             // Allocate buffer for volume control information.
                   1555:             //
                   1556: 
                   1557:             outputBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
                   1558:                                          MODE_DATA_SIZE);
                   1559: 
                   1560:             if (!outputBuffer) {
                   1561:                 status = STATUS_INSUFFICIENT_RESOURCES;
                   1562:                 Irp->IoStatus.Information = 0;
                   1563:                 break;
                   1564:             }
                   1565: 
                   1566:             //
                   1567:             // In case not as much as expected is returned zero
                   1568:             // all of this.
                   1569:             //
                   1570: 
                   1571:             RtlZeroMemory(outputBuffer, MODE_DATA_SIZE);
                   1572: 
                   1573:             //
                   1574:             // Get volume control information
                   1575:             //
                   1576: 
                   1577:             cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
                   1578:             cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE;
                   1579:             cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
                   1580: 
                   1581:             srb.CdbLength = 6;
                   1582: 
                   1583:             //
                   1584:             // Set timeout value.
                   1585:             //
                   1586: 
                   1587:             srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1588: 
                   1589:             status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1590:                                         &srb,
                   1591:                                         outputBuffer,
                   1592:                                         MODE_DATA_SIZE,
                   1593:                                         FALSE);
                   1594: 
                   1595:             if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
                   1596:                 status = STATUS_SUCCESS;
                   1597:             }
                   1598: 
                   1599:             if (NT_SUCCESS(status)) {
                   1600: 
                   1601:                 audioOutput = ScsiClassFindModePage( outputBuffer,
                   1602:                                                      srb.DataTransferLength,
                   1603:                                                      CDROM_AUDIO_CONTROL_PAGE);
                   1604: 
                   1605:                 //
                   1606:                 // Verify the page is as big as expected.
                   1607:                 //
                   1608: 
                   1609:                 bytesTransferred = (PCHAR) audioOutput - (PCHAR) outputBuffer +
                   1610:                     sizeof(AUDIO_OUTPUT);
                   1611: 
                   1612:                 if (audioOutput != NULL &&
                   1613:                     srb.DataTransferLength >= bytesTransferred) {
                   1614: 
                   1615:                     for (i=0; i<4; i++) {
                   1616:                         volumeControl->PortVolume[i] =
                   1617:                             audioOutput->PortOutput[i].Volume;
                   1618:                     }
                   1619: 
                   1620:                     //
                   1621:                     // Set bytes transferred in IRP.
                   1622:                     //
                   1623: 
                   1624:                     Irp->IoStatus.Information = sizeof(VOLUME_CONTROL);
                   1625: 
                   1626:                 } else {
                   1627:                     status = STATUS_INVALID_DEVICE_REQUEST;
                   1628:                 }
                   1629: 
                   1630:             }
                   1631: 
                   1632:             //
                   1633:             // Free buffer.
                   1634:             //
                   1635: 
                   1636:             ExFreePool(outputBuffer);
                   1637:         }
                   1638: 
                   1639:         break;
                   1640: 
                   1641:     case IOCTL_CDROM_SET_VOLUME:
                   1642: 
                   1643:     DebugPrint((2, "ScsiCdRomDeviceControl: Set volume control\n"));
                   1644: 
                   1645:     {
                   1646: 
                   1647:         PAUDIO_OUTPUT audioOutput;
                   1648:         PAUDIO_OUTPUT audioInput;
                   1649:         PVOID inputBuffer;
                   1650:         PVOLUME_CONTROL volumeControl = Irp->AssociatedIrp.SystemBuffer;
                   1651:         ULONG i;
                   1652: 
                   1653:         if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1654:             sizeof(VOLUME_CONTROL)) {
                   1655: 
                   1656:             //
                   1657:             // Indicate unsuccessful status.
                   1658:             //
                   1659: 
                   1660:             status = STATUS_BUFFER_TOO_SMALL;
                   1661:             break;
                   1662:         }
                   1663: 
                   1664:         //
                   1665:         // Get the current audio contorl information so that the
                   1666:         // port control information can be filled in.
                   1667:         // Allocate buffer for volume control information.
                   1668:         //
                   1669: 
                   1670:         inputBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
                   1671:                                      MODE_DATA_SIZE);
                   1672: 
                   1673:         if (!inputBuffer) {
                   1674:             status = STATUS_INSUFFICIENT_RESOURCES;
                   1675:             Irp->IoStatus.Information = 0;
                   1676:             break;
                   1677:         }
                   1678: 
                   1679:         //
                   1680:         // In case not as much as expected is returned zero
                   1681:         // all of this.
                   1682:         //
                   1683: 
                   1684:         RtlZeroMemory(inputBuffer, MODE_DATA_SIZE);
                   1685: 
                   1686:         //
                   1687:         // Get volume control information
                   1688:         //
                   1689: 
                   1690:         cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
                   1691:         cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE;
                   1692:         cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
                   1693: 
                   1694:         srb.CdbLength = 6;
                   1695: 
                   1696:         //
                   1697:         // Set timeout value.
                   1698:         //
                   1699: 
                   1700:         srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1701: 
                   1702:         status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1703:                                     &srb,
                   1704:                                     inputBuffer,
                   1705:                                     MODE_DATA_SIZE,
                   1706:                                     FALSE);
                   1707: 
                   1708:         if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
                   1709:             status = STATUS_SUCCESS;
                   1710:         }
                   1711: 
                   1712:         if (NT_SUCCESS(status)) {
                   1713: 
                   1714:             audioInput = ScsiClassFindModePage( inputBuffer,
                   1715:                                                  srb.DataTransferLength,
                   1716:                                                  CDROM_AUDIO_CONTROL_PAGE);
                   1717: 
                   1718:             if (audioInput == NULL) {
                   1719:                 status = STATUS_INVALID_DEVICE_REQUEST;
                   1720:             }
                   1721: 
                   1722:             //
                   1723:             // Verify the page is as big as expected.
                   1724:             //
                   1725: 
                   1726:             i = (PCHAR) audioInput - (PCHAR) inputBuffer + sizeof(AUDIO_OUTPUT);
                   1727: 
                   1728:             if (srb.DataTransferLength < i) {
                   1729:                 status = STATUS_INVALID_DEVICE_REQUEST;
                   1730:             }
                   1731: 
                   1732:         }
                   1733: 
                   1734:         if (!NT_SUCCESS(status)) {
                   1735: 
                   1736:             //
                   1737:             // Free buffer.
                   1738:             //
                   1739: 
                   1740:             ExFreePool(inputBuffer);
                   1741: 
                   1742:             break;
                   1743:         }
                   1744: 
                   1745:         //
                   1746:         // Mode select buffer is the size of the audio page plus a
                   1747:         // mode parameter header.
                   1748:         //
                   1749: 
                   1750:         bytesTransferred = sizeof(AUDIO_OUTPUT) + sizeof(MODE_PARAMETER_HEADER);
                   1751: 
                   1752:         //
                   1753:         // Allocate buffer for volume control information.
                   1754:         //
                   1755: 
                   1756:         outputBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
                   1757:                                      bytesTransferred);
                   1758: 
                   1759:         if (!outputBuffer) {
                   1760:             status = STATUS_INSUFFICIENT_RESOURCES;
                   1761:             Irp->IoStatus.Information = 0;
                   1762:             break;
                   1763:         }
                   1764: 
                   1765:         //
                   1766:         // Zero the buffer.  The mode parameter header will be left as zeros.
                   1767:         // Also clear the srb again.
                   1768:         //
                   1769: 
                   1770:         RtlZeroMemory(outputBuffer, bytesTransferred);
                   1771:         RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
                   1772: 
                   1773:         //
                   1774:         // Set volume control information
                   1775:         //
                   1776: 
                   1777:         cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
                   1778:         cdb->MODE_SELECT.ParameterListLength = (UCHAR) bytesTransferred;
                   1779:         cdb->MODE_SELECT.PFBit = 1;
                   1780: 
                   1781:         srb.CdbLength = 6;
                   1782: 
                   1783:         audioOutput = (PAUDIO_OUTPUT) ((PCHAR) outputBuffer
                   1784:                         + sizeof(MODE_PARAMETER_HEADER));
                   1785: 
                   1786:         //
                   1787:         // Fill in the volume setting and the port control.
                   1788:         //
                   1789: 
                   1790:         for (i=0; i<4; i++) {
                   1791:             audioOutput->PortOutput[i].Volume =
                   1792:                 volumeControl->PortVolume[i];
                   1793:             audioOutput->PortOutput[i].ChannelSelection =
                   1794:                 audioInput->PortOutput[i].ChannelSelection;
                   1795:         }
                   1796: 
                   1797:         audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE;
                   1798:         audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2;
                   1799:         audioOutput->Immediate = MODE_SELECT_IMMEDIATE;
                   1800: 
                   1801:         //
                   1802:         // Set timeout value.
                   1803:         //
                   1804: 
                   1805:         srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1806: 
                   1807:         status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1808:                                     &srb,
                   1809:                                     outputBuffer,
                   1810:                                     bytesTransferred,
                   1811:                                     TRUE);
                   1812: 
                   1813:         //
                   1814:         // Set bytes transferred in IRP.
                   1815:         //
                   1816: 
                   1817:         Irp->IoStatus.Information = sizeof(VOLUME_CONTROL);
                   1818: 
                   1819:         //
                   1820:         // Free buffers.
                   1821:         //
                   1822: 
                   1823:         ExFreePool(inputBuffer);
                   1824:         ExFreePool(outputBuffer);
                   1825: 
                   1826:         break;
                   1827:     }
                   1828: 
                   1829:     case IOCTL_CDROM_STOP_AUDIO:
                   1830: 
                   1831:         //
                   1832:         // Stop play.
                   1833:         //
                   1834: 
                   1835:         DebugPrint((2, "ScsiCdRomDeviceControl: Stop audio\n"));
                   1836: 
                   1837:         PLAY_ACTIVE(deviceExtension) = FALSE;
                   1838: 
                   1839:         cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
                   1840: 
                   1841:         cdb->START_STOP.Immediate = 1;
                   1842:         cdb->START_STOP.Start = 0;
                   1843:         cdb->START_STOP.LoadEject = 0;
                   1844: 
                   1845:         srb.CdbLength = 6;
                   1846: 
                   1847:         //
                   1848:         // Set timeout value.
                   1849:         //
                   1850: 
                   1851:         srb.TimeOutValue = deviceExtension->TimeOutValue;
                   1852: 
                   1853:         status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1854:                                     &srb,
                   1855:                                     NULL,
                   1856:                                     0,
                   1857:                                     FALSE);
                   1858:         break;
                   1859: 
                   1860:     case IOCTL_CDROM_CHECK_VERIFY:
                   1861: 
                   1862:         srb.CdbLength = 6;
                   1863: 
                   1864:         cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
                   1865: 
                   1866:         //
                   1867:         // Set timeout value.
                   1868:         //
                   1869: 
                   1870:         srb.TimeOutValue = deviceExtension->TimeOutValue * 2;
                   1871: 
                   1872:         status = ScsiClassSendSrbSynchronous(DeviceObject,
                   1873:                                               &srb,
                   1874:                                               NULL,
                   1875:                                               0,
                   1876:                                               FALSE);
                   1877: 
                   1878:         //
                   1879:         // If the status is verify required, redo the test unit ready to
                   1880:         // verify that the cd-rom is done spinning up.
                   1881:         // ScsiClassSendSrbSynchronous will wait for a while for the device to
                   1882:         // spin up.
                   1883:         //
                   1884:         
                   1885:         if (status == STATUS_VERIFY_REQUIRED) {
                   1886: 
                   1887:             srb.CdbLength = 6;
                   1888:     
                   1889:             cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
                   1890:     
                   1891:             //
                   1892:             // Set timeout value.
                   1893:             //
                   1894:     
                   1895:             srb.TimeOutValue = deviceExtension->TimeOutValue * 2;
                   1896:     
                   1897:             status2 = ScsiClassSendSrbSynchronous(DeviceObject,
                   1898:                                         &srb,
                   1899:                                         NULL,
                   1900:                                         0,
                   1901:                                         FALSE);
                   1902: 
                   1903:             DebugPrint((1, "ScsiCdromDeviceControl: Status from second test unit ready is: %lx\n", status2));
                   1904:         }
                   1905: 
                   1906:         //
                   1907:         // Update the play active flag.
                   1908:         //
                   1909: 
                   1910:         if (!CdRomIsPlayActive(DeviceObject) &&
                   1911:              LiEqlZero(deviceExtension->PartitionLength)) {
                   1912: 
                   1913:             //
                   1914:             // If play is not active and the volume needs verification then
                   1915:             // get read capicity again.
                   1916:             //
                   1917: 
                   1918:             status2 = ScsiClassReadDriveCapacity(DeviceObject);
                   1919: 
                   1920:             if ((!NT_SUCCESS(status2)) ||
                   1921:                 (deviceExtension->DiskGeometry->BytesPerSector == 0)) {
                   1922:         
                   1923:                 //
                   1924:                 // Set disk geometry to default values (per ISO 9660).
                   1925:                 //
                   1926:         
                   1927:                 deviceExtension->DiskGeometry->BytesPerSector = 2048;
                   1928:                 deviceExtension->SectorShift = 11;
                   1929:             }
                   1930:         }
                   1931: 
                   1932:         break;
                   1933:         
                   1934:     default:
                   1935: 
                   1936:         //
                   1937:         // Pass the request to the common device control routine.
                   1938:         //
                   1939: 
                   1940:         return(ScsiClassDeviceControl(DeviceObject, Irp));
                   1941: 
                   1942:         break;
                   1943: 
                   1944:     } // end switch()
                   1945: 
                   1946:     if (status == STATUS_VERIFY_REQUIRED) {
                   1947: 
                   1948:         //
                   1949:         // If the status is verified required and the this request
                   1950:         // should bypass verify required then retry the request.
                   1951:         //
                   1952: 
                   1953:         if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) {
                   1954: 
                   1955:             status = STATUS_IO_DEVICE_ERROR;
                   1956:             goto RetryControl;
                   1957: 
                   1958:         }
                   1959: 
                   1960:     }
                   1961: 
                   1962:     if (IoIsErrorUserInduced(status)) {
                   1963: 
                   1964:         IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
                   1965: 
                   1966:     }
                   1967: 
                   1968:     //
                   1969:     // Update IRP with completion status.
                   1970:     //
                   1971: 
                   1972:     Irp->IoStatus.Status = status;
                   1973: 
                   1974:     //
                   1975:     // Complete the request.
                   1976:     //
                   1977: 
                   1978:     IoCompleteRequest(Irp, IO_DISK_INCREMENT);
                   1979:     DebugPrint((2, "ScsiCdromDeviceControl: Status is %lx\n", status));
                   1980:     return status;
                   1981: 
                   1982: } // end ScsiCdromDeviceControl()
                   1983: 
                   1984: 
                   1985: VOID
                   1986: ScanForSpecial(
                   1987:     PDEVICE_OBJECT DeviceObject,
                   1988:     PINQUIRYDATA InquiryData,
                   1989:     PIO_SCSI_CAPABILITIES PortCapabilities
                   1990:     )
                   1991: 
                   1992: /*++
                   1993: 
                   1994: Routine Description:
                   1995: 
                   1996:     This function checks to see if an SCSI logical unit requires an special
                   1997:     initialization or error processing.
                   1998: 
                   1999: Arguments:
                   2000: 
                   2001:     DeviceObject - Supplies the device object to be tested.
                   2002: 
                   2003:     InquiryData - Supplies the inquiry data returned by the device of interest.
                   2004: 
                   2005:     PortCapabilities - Supplies the capabilities of the device object.
                   2006: 
                   2007: Return Value:
                   2008: 
                   2009:     None.
                   2010: 
                   2011: --*/
                   2012: 
                   2013: {
                   2014:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                   2015: 
                   2016:     //
                   2017:     // Look for a Hitachi CDR-1750. Read-ahead must be disabled in order
                   2018:     // to get this cdrom drive to work on scsi adapters that use PIO.
                   2019:     //
                   2020: 
                   2021:     if ((strncmp(InquiryData->VendorId, "HITACHI CDR-1750S", strlen("HITACHI CDR-1750S")) == 0 ||
                   2022:         strncmp(InquiryData->VendorId, "HITACHI CDR-3650/1650S", strlen("HITACHI CDR-3650/1650S")) == 0)
                   2023:         && PortCapabilities->AdapterUsesPio) {
                   2024: 
                   2025:         DebugPrint((1, "ScsiCdrom ScanForSpecial:  Found Hitachi CDR-1750S.\n"));
                   2026: 
                   2027:         //
                   2028:         // Setup an error handler to reinitialize the cd rom after it is reset.
                   2029:         //
                   2030: 
                   2031:         deviceExtension->ClassError = HitachProcessError;
                   2032:     }
                   2033: 
                   2034:     return;
                   2035: }
                   2036: 
                   2037: VOID
                   2038: HitachProcessError(
                   2039:     PDEVICE_OBJECT DeviceObject,
                   2040:     PSCSI_REQUEST_BLOCK Srb,
                   2041:     NTSTATUS *Status,
                   2042:     BOOLEAN *Retry
                   2043:     )
                   2044: /*++
                   2045: 
                   2046: Routine Description:
                   2047: 
                   2048:    This routine checks the type of error.  If the error indicates CD-ROM the
                   2049:    CD-ROM needs to be reinitialized then a Mode sense command is sent to the
                   2050:    device.  This command disables read-ahead for the device.
                   2051: 
                   2052: Arguments:
                   2053: 
                   2054:     DeviceObject - Supplies a pointer to the device object.
                   2055: 
                   2056:     Srb - Supplies a pointer to the failing Srb.
                   2057: 
                   2058:     Status - Not used.
                   2059: 
                   2060:     Retry - Not used.
                   2061: 
                   2062: Return Value:
                   2063: 
                   2064:     None.
                   2065: 
                   2066: --*/
                   2067: 
                   2068: {
                   2069:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                   2070:     PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
                   2071:     LARGE_INTEGER largeInt = LiFromUlong(1);
                   2072:     PUCHAR modePage;
                   2073:     PIO_STACK_LOCATION irpStack;
                   2074:     PIRP irp;
                   2075:     PSCSI_REQUEST_BLOCK srb;
                   2076:     PCOMPLETION_CONTEXT context;
                   2077:     PCDB cdb;
                   2078:     ULONG alignment;
                   2079: 
                   2080:     UNREFERENCED_PARAMETER(Status);
                   2081:     UNREFERENCED_PARAMETER(Retry);
                   2082: 
                   2083:     //
                   2084:     // Check the status.  The initialization command only needs to be sent
                   2085:     // if UNIT ATTENTION is returned.
                   2086:     //
                   2087: 
                   2088:     if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) {
                   2089: 
                   2090:         //
                   2091:         // The drive does not require reinitialization.
                   2092:         //
                   2093: 
                   2094:         return;
                   2095:     }
                   2096: 
                   2097:     //
                   2098:     // Found a bad HITACHI cd-rom.  These devices do not work with PIO
                   2099:     // adapters when read-ahead is enabled.  Read-ahead is disabled by
                   2100:     // a mode select command.  The mode select page code is zero and the
                   2101:     // length is 6 bytes.  All of the other bytes should be zero.
                   2102:     //
                   2103: 
                   2104: 
                   2105:     if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) {
                   2106: 
                   2107:         DebugPrint((1, "HitachiProcessError: Reinitializing the CD-ROM.\n"));
                   2108: 
                   2109:         //
                   2110:         // Send the special mode select command to disable read-ahead
                   2111:         // on the CD-ROM reader.
                   2112:         //
                   2113: 
                   2114:         alignment = DeviceObject->AlignmentRequirement ?
                   2115:             DeviceObject->AlignmentRequirement : 1;
                   2116: 
                   2117:         context = ExAllocatePool(
                   2118:             NonPagedPool,
                   2119:             sizeof(COMPLETION_CONTEXT) +  HITACHI_MODE_DATA_SIZE + alignment
                   2120:             );
                   2121: 
                   2122:         if (context == NULL) {
                   2123: 
                   2124:             //
                   2125:             // If there is not enough memory to fulfill this request,
                   2126:             // simply return. A subsequent retry will fail and another
                   2127:             // chance to start the unit.
                   2128:             //
                   2129: 
                   2130:             return;
                   2131:         }
                   2132: 
                   2133:         context->DeviceObject = DeviceObject;
                   2134:         srb = &context->Srb;
                   2135: 
                   2136:         RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
                   2137: 
                   2138:         //
                   2139:         // Write length to SRB.
                   2140:         //
                   2141: 
                   2142:         srb->Length = SCSI_REQUEST_BLOCK_SIZE;
                   2143: 
                   2144:         //
                   2145:         // Set up SCSI bus address.
                   2146:         //
                   2147: 
                   2148:         srb->PathId = deviceExtension->PathId;
                   2149:         srb->TargetId = deviceExtension->TargetId;
                   2150:         srb->Lun = deviceExtension->Lun;
                   2151: 
                   2152:         srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
                   2153:         srb->TimeOutValue = deviceExtension->TimeOutValue;
                   2154: 
                   2155:         //
                   2156:         // Set the transfer length.
                   2157:         //
                   2158: 
                   2159:         srb->DataTransferLength = HITACHI_MODE_DATA_SIZE;
                   2160:         srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
                   2161: 
                   2162:         //
                   2163:         // The data buffer must be aligned.
                   2164:         //
                   2165: 
                   2166:         srb->DataBuffer = (PVOID) (((ULONG) (context + 1) + (alignment - 1)) &
                   2167:             ~(alignment - 1));
                   2168: 
                   2169: 
                   2170:         //
                   2171:         // Build the HITACHI read-ahead mode select CDB.
                   2172:         //
                   2173: 
                   2174:         srb->CdbLength = 6;
                   2175:         cdb = (PCDB)srb->Cdb;
                   2176:         cdb->MODE_SENSE.LogicalUnitNumber = srb->Lun;
                   2177:         cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SELECT;
                   2178:         cdb->MODE_SENSE.AllocationLength = HITACHI_MODE_DATA_SIZE;
                   2179: 
                   2180:         //
                   2181:         // Initialize the mode sense data.
                   2182:         //
                   2183: 
                   2184:         modePage = srb->DataBuffer;
                   2185: 
                   2186:         RtlZeroMemory(modePage, HITACHI_MODE_DATA_SIZE);
                   2187: 
                   2188:         //
                   2189:         // Set the page length field to 6.
                   2190:         //
                   2191: 
                   2192:         modePage[5] = 6;
                   2193: 
                   2194:         //
                   2195:         // Build the asynchronous request to be sent to the port driver.
                   2196:         //
                   2197: 
                   2198:         irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE,
                   2199:                                            DeviceObject,
                   2200:                                            srb->DataBuffer,
                   2201:                                            srb->DataTransferLength,
                   2202:                                            &largeInt,
                   2203:                                            NULL);
                   2204: 
                   2205:         IoSetCompletionRoutine(irp,
                   2206:                    (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion,
                   2207:                    context,
                   2208:                    TRUE,
                   2209:                    TRUE,
                   2210:                    TRUE);
                   2211: 
                   2212:         irpStack = IoGetNextIrpStackLocation(irp);
                   2213: 
                   2214:         irpStack->MajorFunction = IRP_MJ_SCSI;
                   2215: 
                   2216:         srb->OriginalRequest = irp;
                   2217: 
                   2218:         //
                   2219:         // Save SRB address in next stack for port driver.
                   2220:         //
                   2221: 
                   2222:         irpStack->Parameters.Scsi.Srb = (PVOID)srb;
                   2223: 
                   2224:         //
                   2225:         // Set up IRP Address.
                   2226:         //
                   2227: 
                   2228:         (VOID)IoCallDriver(deviceExtension->PortDeviceObject, irp);
                   2229: 
                   2230:     }
                   2231: }
                   2232: 
                   2233: BOOLEAN
                   2234: CdRomIsPlayActive(
                   2235:     IN PDEVICE_OBJECT DeviceObject
                   2236:     )
                   2237: 
                   2238: /*++
                   2239: 
                   2240: Routine Description:
                   2241: 
                   2242:     This routine determines if the cd is currently playing music.
                   2243: 
                   2244: Arguments:
                   2245: 
                   2246:     DeviceObject - Device object to test.
                   2247: 
                   2248: Return Value:
                   2249: 
                   2250:     TRUE if the device is playing music.
                   2251: 
                   2252: --*/
                   2253: {
                   2254:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
                   2255:     PIRP irp;
                   2256:     IO_STATUS_BLOCK ioStatus;
                   2257:     KEVENT event;
                   2258:     NTSTATUS status;
                   2259:     PSUB_Q_CURRENT_POSITION currentBuffer;
                   2260: 
                   2261:     if (!PLAY_ACTIVE(deviceExtension)) {
                   2262:         return(FALSE);
                   2263:     }
                   2264: 
                   2265:     currentBuffer = ExAllocatePool(NonPagedPoolCacheAligned, sizeof(SUB_Q_CURRENT_POSITION));
                   2266: 
                   2267:     if (currentBuffer == NULL) {
                   2268:         return(FALSE);
                   2269:     }
                   2270: 
                   2271:     ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Format = IOCTL_CDROM_CURRENT_POSITION;
                   2272:     ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Track = 0;
                   2273: 
                   2274:     //
                   2275:     // Create notification event object to be used to signal the
                   2276:     // request completion.
                   2277:     //
                   2278: 
                   2279:     KeInitializeEvent(&event, NotificationEvent, FALSE);
                   2280: 
                   2281:     //
                   2282:     // Build the synchronous request  to be sent to the port driver
                   2283:     // to perform the request.
                   2284:     //
                   2285: 
                   2286:     irp = IoBuildDeviceIoControlRequest(IOCTL_CDROM_READ_Q_CHANNEL,
                   2287:                                         deviceExtension->DeviceObject,
                   2288:                                         currentBuffer,
                   2289:                                         sizeof(CDROM_SUB_Q_DATA_FORMAT),
                   2290:                                         currentBuffer,
                   2291:                                         sizeof(SUB_Q_CURRENT_POSITION),
                   2292:                                         FALSE,
                   2293:                                         &event,
                   2294:                                         &ioStatus);
                   2295: 
                   2296:     if (irp == NULL) {
                   2297:         ExFreePool(currentBuffer);
                   2298:         return FALSE;
                   2299:     }
                   2300: 
                   2301:     //
                   2302:     // Pass request to port driver and wait for request to complete.
                   2303:     //
                   2304: 
                   2305:     status = IoCallDriver(deviceExtension->DeviceObject, irp);
                   2306: 
                   2307:     if (status == STATUS_PENDING) {
                   2308:         KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
                   2309:         status = ioStatus.Status;
                   2310:     }
                   2311: 
                   2312:     if (!NT_SUCCESS(status)) {
                   2313:         ExFreePool(currentBuffer);
                   2314:         return FALSE;
                   2315:     }
                   2316: 
                   2317:     ExFreePool(currentBuffer);
                   2318: 
                   2319:     return(PLAY_ACTIVE(deviceExtension));
                   2320: 
                   2321: }
                   2322: 
                   2323: 

unix.superglobalmegacorp.com

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