cdrom.c
来自「一个类似windows」· C语言 代码 · 共 1,704 行 · 第 1/4 页
C
1,704 行
}
if (CapabilitiesData->Capabilities[2] & 0x08)
{
DbgPrint(" Drive can eject a disc or changer cartridge\n");
}
if (CapabilitiesData->Capabilities[2] & 0x10)
{
DbgPrint(" Drive supports C2 error pointers\n");
}
switch (CapabilitiesData->Capabilities[2] >> 5)
{
case 0:
DbgPrint(" Drive use a caddy type loading mechanism\n");
break;
case 1:
DbgPrint(" Drive use a tray type loading mechanism\n");
break;
case 2:
DbgPrint(" Drive use a pop-up type loading mechanism\n");
break;
case 4:
DbgPrint(" Drive is a changer with individually changeable discs\n");
break;
case 5:
DbgPrint(" Drive is a changer with cartridge mechanism\n");
break;
}
DPRINT("CapabilitiesData.Capabilities[3] %x\n", CapabilitiesData->Capabilities[3]);
if (CapabilitiesData->Capabilities[3] & 0x01)
{
DbgPrint(" Audio level for each channel can be controlled independently\n");
}
if (CapabilitiesData->Capabilities[3] & 0x02)
{
DbgPrint(" Audio for each channel can be muted independently\n");
}
if (CapabilitiesData->Capabilities[3] & 0x04)
{
DbgPrint(" Changer can report exact contents of slots\n");
}
if (CapabilitiesData->Capabilities[3] & 0x08)
{
DbgPrint(" Drive supports software slot selection\n");
}
DbgPrint(" Maximum speed is %d kB/s\n",
(CapabilitiesData->MaximumSpeedSupported[0] << 8)
| CapabilitiesData->MaximumSpeedSupported[1]);
DbgPrint(" Current speed is %d kB/s\n",
(CapabilitiesData->CurrentSpeed[0] << 8)
| CapabilitiesData->CurrentSpeed[1]);
DbgPrint(" Number of discrete volume levels is %d\n",
(CapabilitiesData->Reserved3 << 8)
| CapabilitiesData->NumberVolumeLevels);
DbgPrint(" Buffer size is %d kB\n",
(CapabilitiesData->BufferSize[0] << 8)
| CapabilitiesData->BufferSize[1]);
#endif
}
else
{
DPRINT("XA not supported\n");
CdromData->XaFlags |= XA_NOT_SUPPORTED;
}
}
ExFreePool (Buffer);
/* Initialize device timer */
IoInitializeTimer(DiskDeviceObject,
CdromTimerRoutine,
NULL);
IoStartTimer(DiskDeviceObject);
DPRINT("CdromClassCreateDeviceObjects() done\n");
return(STATUS_SUCCESS);
}
/**********************************************************************
* NAME
* CdromClassReadTocEntry
*
* ARGUMENTS:
* DeviceObject
* TrackNo
* Buffer
* Length
*
* RETURNS:
* Status.
*/
static NTSTATUS
CdromClassReadTocEntry (PDEVICE_OBJECT DeviceObject,
SIZE_T TrackNo,
PVOID Buffer,
SIZE_T Length)
{
PDEVICE_EXTENSION DeviceExtension;
SCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
Srb.CdbLength = 10;
Srb.TimeOutValue = DeviceExtension->TimeOutValue;
Cdb = (PCDB)Srb.Cdb;
Cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC;
Cdb->READ_TOC.StartingTrack = TrackNo;
Cdb->READ_TOC.Format = 0;
Cdb->READ_TOC.AllocationLength[0] = Length >> 8;
Cdb->READ_TOC.AllocationLength[1] = Length & 0xff;
Cdb->READ_TOC.Msf = 1;
return(ScsiClassSendSrbSynchronous(DeviceObject,
&Srb,
Buffer,
Length,
FALSE));
}
static NTSTATUS
CdromClassReadLastSession (PDEVICE_OBJECT DeviceObject,
SIZE_T TrackNo,
PVOID Buffer,
SIZE_T Length)
{
PDEVICE_EXTENSION DeviceExtension;
SCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
Srb.CdbLength = 10;
Srb.TimeOutValue = DeviceExtension->TimeOutValue;
Cdb = (PCDB)Srb.Cdb;
Cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC;
Cdb->READ_TOC.StartingTrack = TrackNo;
Cdb->READ_TOC.Format = 1;
Cdb->READ_TOC.AllocationLength[0] = Length >> 8;
Cdb->READ_TOC.AllocationLength[1] = Length & 0xff;
Cdb->READ_TOC.Msf = 0;
return(ScsiClassSendSrbSynchronous(DeviceObject,
&Srb,
Buffer,
Length,
FALSE));
}
/**********************************************************************
* NAME EXPORTED
* CdromClassDeviceControl
*
* DESCRIPTION:
* Answer requests for device control calls
*
* RUN LEVEL:
* PASSIVE_LEVEL
*
* ARGUMENTS:
* DeviceObject
* Irp
* Standard dispatch arguments
*
* RETURNS:
* Status.
*/
NTSTATUS STDCALL
CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
ULONG ControlCode, InputLength, OutputLength;
PCDROM_DATA CdromData;
ULONG Information;
NTSTATUS Status;
DPRINT("CdromClassDeviceControl() called!\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
Information = 0;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
CdromData = (PCDROM_DATA)(DeviceExtension + 1);
switch (ControlCode)
{
case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
DPRINT ("CdromClassDeviceControl: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
IoMarkIrpPending (Irp);
IoStartPacket (DeviceObject,
Irp,
NULL,
NULL);
return STATUS_PENDING;
case IOCTL_CDROM_CHECK_VERIFY:
DPRINT ("CdromClassDeviceControl: IOCTL_CDROM_CHECK_VERIFY\n");
if (OutputLength != 0 && OutputLength < sizeof (ULONG))
{
DPRINT1("Buffer too small\n");
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
IoMarkIrpPending (Irp);
IoStartPacket (DeviceObject,
Irp,
NULL,
NULL);
return STATUS_PENDING;
case IOCTL_CDROM_READ_TOC:
DPRINT("IOCTL_CDROM_READ_TOC\n");
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(CDROM_TOC))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
PCDROM_TOC TocBuffer;
USHORT Length;
TocBuffer = Irp->AssociatedIrp.SystemBuffer;
/* First read the lead out */
Length = 4 + sizeof(TRACK_DATA);
Status = CdromClassReadTocEntry(DeviceObject,
0xAA,
TocBuffer,
Length);
if (NT_SUCCESS(Status))
{
if (TocBuffer->FirstTrack == 0xaa)
{
/* there is an empty cd */
Information = Length;
}
else
{
/* read the toc */
Length = 4 + sizeof(TRACK_DATA) * (TocBuffer->LastTrack - TocBuffer->FirstTrack + 2);
Status = CdromClassReadTocEntry(DeviceObject,
TocBuffer->FirstTrack,
TocBuffer, Length);
if (NT_SUCCESS(Status))
{
Information = Length;
}
}
}
}
break;
case IOCTL_CDROM_GET_LAST_SESSION:
DPRINT("IOCTL_CDROM_GET_LAST_SESSION\n");
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < 4 + sizeof(TRACK_DATA))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
PCDROM_TOC TocBuffer;
USHORT Length;
TocBuffer = Irp->AssociatedIrp.SystemBuffer;
Length = 4 + sizeof(TRACK_DATA);
Status = CdromClassReadLastSession(DeviceObject,
0,
TocBuffer,
Length);
if (NT_SUCCESS(Status))
{
Information = Length;
}
}
break;
default:
/* Call the common device control function */
return(ScsiClassDeviceControl(DeviceObject, Irp));
}
/* Verify the device if the user caused the error */
if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
{
IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
IoCompleteRequest(Irp,
IO_DISK_INCREMENT);
return Status;
}
/**********************************************************************
* NAME
* CdromClassStartIo
*
* DESCRIPTION:
* Starts IRP processing.
*
* RUN LEVEL:
* PASSIVE_LEVEL
*
* ARGUMENTS:
* DeviceObject
* Irp
* Standard dispatch arguments
*
* RETURNS:
* None.
*/
VOID STDCALL
CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
PIO_STACK_LOCATION SubIrpStack;
ULONG MaximumTransferLength;
ULONG TransferPages;
PSCSI_REQUEST_BLOCK Srb;
PIRP SubIrp;
PUCHAR SenseBuffer;
PVOID DataBuffer;
PCDB Cdb;
DPRINT("CdromClassStartIo() called!\n");
IoMarkIrpPending (Irp);
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
IrpStack = IoGetCurrentIrpStackLocation (Irp);
MaximumTransferLength = DeviceExtension->PortCapabilities->MaximumTransferLength;
if (DeviceObject->Flags & DO_VERIFY_VOLUME)
{
if (!(IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME))
{
DPRINT1 ("Verify required\n");
if (Irp->Tail.Overlay.Thread)
{
IoSetHardErrorOrVerifyDevice (Irp,
DeviceObject);
}
Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
/* FIXME: Update drive capacity */
IoCompleteRequest (Irp,
IO_DISK_INCREMENT);
IoStartNextPacket (DeviceObject,
FALSE);
return;
}
}
if (IrpStack->MajorFunction == IRP_MJ_READ)
{
DPRINT ("CdromClassStartIo: IRP_MJ_READ\n");
TransferPages =
ADDRESS_AND_SIZE_TO_SPAN_PAGES (MmGetMdlVirtualAddress(Irp->MdlAddress),
IrpStack->Parameters.Read.Length);
/* Check transfer size */
if ((IrpStack->Parameters.Read.Length > MaximumTransferLength) ||
(TransferPages > DeviceExtension->PortCapabilities->MaximumPhysicalPages))
{
/* Transfer size is too large - split it */
TransferPages =
DeviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
/* Adjust transfer size */
if (MaximumTransferLength > TransferPages * PAGE_SIZE)
MaximumTransferLength = TransferPages * PAGE_SIZE;
if (MaximumTransferLength == 0)
MaximumTransferLength = PAGE_SIZE;
/* Split the transfer */
ScsiClassSplitRequest (DeviceObject,
Irp,
MaximumTransferLength);
return;
}
else
{
/* Build SRB */
ScsiClassBuildRequest (DeviceObject,
Irp);
}
}
else if (IrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
{
DPRINT ("CdromClassStartIo: IRP_MJ_IRP_MJ_DEVICE_CONTROL\n");
/* Allocate an IRP for sending requests to the port driver */
SubIrp = IoAllocateIrp ((CCHAR)(DeviceObject->StackSize + 1),
FALSE);
if (SubIrp == NULL)
{
Irp->IoStatus.Information = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?