cdrom.c
来自「一个类似windows」· C语言 代码 · 共 1,704 行 · 第 1/4 页
C
1,704 行
/*
* ReactOS kernel
* Copyright (C) 2001, 2002 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: cdrom.c 21260 2006-03-08 23:23:57Z audit $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/storage/cdrom/cdrom.c
* PURPOSE: cdrom class driver
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
*/
/*
* TODO:
* - Add io timer routine for autorun support.
* - Add cdaudio support (cd player).
*/
/* INCLUDES *****************************************************************/
#include <ntddk.h>
#include <scsi.h>
#include <ntddscsi.h>
#include <ntdddisk.h>
#include <ntddcdrm.h>
#include <include/class2.h>
#include <stdio.h>
#define NDEBUG
#include <debug.h>
#define VERSION "0.0.1"
#define SCSI_CDROM_TIMEOUT 10 /* Default timeout: 10 seconds */
typedef struct _ERROR_RECOVERY_DATA6
{
MODE_PARAMETER_HEADER Header;
MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
} ERROR_RECOVERY_DATA6, *PERROR_RECOVERY_DATA6;
typedef struct _ERROR_RECOVERY_DATA10
{
MODE_PARAMETER_HEADER10 Header;
MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
} ERROR_RECOVERY_DATA10, *PERROR_RECOVERY_DATA10;
typedef struct _MODE_CAPABILITIES_PAGE2
{
UCHAR PageCode:6;
UCHAR Reserved1:1;
UCHAR PSBit:1;
UCHAR PageLength;
UCHAR Reserved2[2];
UCHAR Capabilities[4];
UCHAR MaximumSpeedSupported[2];
UCHAR Reserved3;
UCHAR NumberVolumeLevels;
UCHAR BufferSize[2];
UCHAR CurrentSpeed[2];
UCHAR Reserved4;
UCHAR Reserved5:1;
UCHAR DigitalOutput:4;
UCHAR Reserved6:3;
UCHAR Reserved7[2];
} MODE_CAPABILITIES_PAGE2, *PMODE_CAPABILITIES_PAGE2;
typedef struct _MODE_CAPABILITIES_DATA6
{
MODE_PARAMETER_HEADER Header;
MODE_CAPABILITIES_PAGE2 CababilitiesPage;
} MODE_CAPABILITIES_DATA6, *PMODE_CAPABILITIES_DATA6;
typedef struct _MODE_CAPABILITIES_DATA10
{
MODE_PARAMETER_HEADER10 Header;
MODE_CAPABILITIES_PAGE2 CababilitiesPage;
} MODE_CAPABILITIES_DATA10, *PMODE_CAPABILITIES_DATA10;
typedef struct _CDROM_DATA
{
BOOLEAN PlayActive;
BOOLEAN RawAccess;
USHORT XaFlags;
} CDROM_DATA, *PCDROM_DATA;
/* CDROM_DATA.XaFlags */
#define XA_USE_6_BYTE 0x0001
#define XA_USE_10_BYTE 0x0002
#define XA_USE_READ_CD 0x0004
#define XA_NOT_SUPPORTED 0x0008
BOOLEAN STDCALL
CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PCLASS_INIT_DATA InitializationData,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber);
BOOLEAN STDCALL
CdromClassCheckDevice(IN PINQUIRYDATA InquiryData);
NTSTATUS STDCALL
CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
static VOID
CdromClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceNumber);
static NTSTATUS
CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber,
IN ULONG DeviceNumber,
IN PIO_SCSI_CAPABILITIES Capabilities,
IN PSCSI_INQUIRY_DATA InquiryData,
IN PCLASS_INIT_DATA InitializationData);
NTSTATUS STDCALL
CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
VOID STDCALL
CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
CdromDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
VOID STDCALL
CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context);
VOID STDCALL
CdromWorkItem(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context);
/* FUNCTIONS ****************************************************************/
/**********************************************************************
* NAME EXPORTED
* DriverEntry
*
* DESCRIPTION:
* This function initializes the driver, locates and claims
* hardware resources, and creates various NT objects needed
* to process I/O requests.
*
* RUN LEVEL:
* PASSIVE_LEVEL
*
* ARGUMENTS:
* DriverObject
* System allocated Driver Object for this driver
* RegistryPath
* Name of registry driver service key
*
* RETURNS:
* Status.
*/
NTSTATUS STDCALL
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
CLASS_INIT_DATA InitData;
DPRINT("CD-ROM Class Driver %s\n",
VERSION);
DPRINT("RegistryPath '%wZ'\n",
RegistryPath);
InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(CDROM_DATA);
InitData.DeviceType = FILE_DEVICE_CD_ROM;
InitData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE;
InitData.ClassError = NULL;
InitData.ClassReadWriteVerification = CdromClassCheckReadWrite;
InitData.ClassFindDeviceCallBack = CdromClassCheckDevice;
InitData.ClassFindDevices = CdromClassFindDevices;
InitData.ClassDeviceControl = CdromClassDeviceControl;
InitData.ClassShutdownFlush = NULL;
InitData.ClassCreateClose = NULL;
InitData.ClassStartIo = CdromClassStartIo;
return(ScsiClassInitialize(DriverObject,
RegistryPath,
&InitData));
}
/**********************************************************************
* NAME EXPORTED
* CdromClassFindDevices
*
* DESCRIPTION:
* This function searches for device that are attached to the
* given scsi port.
*
* RUN LEVEL:
* PASSIVE_LEVEL
*
* ARGUMENTS:
* DriverObject
* System allocated Driver Object for this driver
* RegistryPath
* Name of registry driver service key.
* InitializationData
* Pointer to the main initialization data
* PortDeviceObject
* Scsi port device object
* PortNumber
* Port number
*
* RETURNS:
* TRUE: At least one disk drive was found
* FALSE: No disk drive found
*/
BOOLEAN STDCALL
CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PCLASS_INIT_DATA InitializationData,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber)
{
PCONFIGURATION_INFORMATION ConfigInfo;
PIO_SCSI_CAPABILITIES PortCapabilities;
PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
PSCSI_INQUIRY_DATA UnitInfo;
PINQUIRYDATA InquiryData;
PCHAR Buffer;
ULONG Bus;
ULONG DeviceCount;
BOOLEAN FoundDevice = FALSE;
NTSTATUS Status;
DPRINT("CdromClassFindDevices() called.\n");
/* Get port capabilities */
Status = ScsiClassGetCapabilities(PortDeviceObject,
&PortCapabilities);
if (!NT_SUCCESS(Status))
{
DPRINT1("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
return(FALSE);
}
DPRINT("PortCapabilities: %p\n", PortCapabilities);
DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages);
/* Get inquiry data */
Status = ScsiClassGetInquiryData(PortDeviceObject,
(PSCSI_ADAPTER_BUS_INFO *)&Buffer);
if (!NT_SUCCESS(Status))
{
DPRINT1("ScsiClassGetInquiryData() failed! (Status 0x%lX)\n", Status);
return(FALSE);
}
/* Check whether there are unclaimed devices */
AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
AdapterBusInfo);
if (DeviceCount == 0)
{
DPRINT("No unclaimed devices!\n");
return(FALSE);
}
DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
ConfigInfo = IoGetConfigurationInformation();
DPRINT("Number of SCSI ports: %lu\n", ConfigInfo->ScsiPortCount);
/* Search each bus of this adapter */
for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
{
DPRINT("Searching bus %lu\n", Bus);
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
{
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
if ((InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
(InquiryData->DeviceTypeQualifier == 0) &&
(UnitInfo->DeviceClaimed == FALSE))
{
DPRINT("Vendor: '%.24s'\n",
InquiryData->VendorId);
/* Create device objects for disk */
Status = CdromClassCreateDeviceObject(DriverObject,
RegistryPath,
PortDeviceObject,
PortNumber,
ConfigInfo->CdRomCount,
PortCapabilities,
UnitInfo,
InitializationData);
if (NT_SUCCESS(Status))
{
ConfigInfo->CdRomCount++;
FoundDevice = TRUE;
}
}
if (UnitInfo->NextInquiryDataOffset == 0)
break;
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
}
}
ExFreePool(Buffer);
DPRINT("CdromClassFindDevices() done\n");
return(FoundDevice);
}
/**********************************************************************
* NAME EXPORTED
* CdromClassCheckDevice
*
* DESCRIPTION
* This function checks the InquiryData for the correct device
* type and qualifier.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* InquiryData
* Pointer to the inquiry data for the device in question.
*
* RETURN VALUE
* TRUE: A disk device was found.
* FALSE: Otherwise.
*/
BOOLEAN STDCALL
CdromClassCheckDevice(IN PINQUIRYDATA InquiryData)
{
return((InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
(InquiryData->DeviceTypeQualifier == 0));
}
/**********************************************************************
* NAME EXPORTED
* CdromClassCheckReadWrite
*
* DESCRIPTION
* This function checks the given IRP for correct data.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DeviceObject
* Pointer to the device.
* Irp
* Irp to check.
*
* RETURN VALUE
* STATUS_SUCCESS: The IRP matches the requirements of the given device.
* Others: Failure.
*/
NTSTATUS STDCALL
CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("CdromClassCheckReadWrite() called\n");
return(STATUS_SUCCESS);
}
static VOID
CdromClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceNumber)
{
DeviceExtension->MediaChangeEvent =
IoCreateSynchronizationEvent (NULL,
&DeviceExtension->MediaChangeEventHandle);
KeClearEvent (DeviceExtension->MediaChangeEvent);
}
/**********************************************************************
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?