📄 cdrom.c
字号:
/*
* PROJECT: ReactOS Storage Stack
* LICENSE: DDK - see license.txt in the root dir
* FILE: drivers/storage/cdrom/cdrom.c
* PURPOSE: CDROM driver
* PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK
*/
#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 CDB12GENERIC_LENGTH 12
typedef struct _XA_CONTEXT {
//
// Pointer to the device object.
//
PDEVICE_OBJECT DeviceObject;
//
// Pointer to the original request when
// a mode select must be sent.
//
PIRP OriginalRequest;
//
// Pointer to the mode select srb.
//
PSCSI_REQUEST_BLOCK Srb;
} XA_CONTEXT, *PXA_CONTEXT;
typedef struct _ERROR_RECOVERY_DATA {
MODE_PARAMETER_HEADER Header;
MODE_PARAMETER_BLOCK BlockDescriptor;
MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
} ERROR_RECOVERY_DATA, *PERROR_RECOVERY_DATA;
typedef struct _ERROR_RECOVERY_DATA10 {
MODE_PARAMETER_HEADER10 Header10;
MODE_PARAMETER_BLOCK BlockDescriptor10;
MODE_READ_RECOVERY_PAGE ReadRecoveryPage10;
} ERROR_RECOVERY_DATA10, *PERROR_RECOVERY_DATA10;
//
// CdRom specific addition to device extension.
//
typedef struct _CDROM_DATA {
//
// Indicates whether an audio play operation
// is currently being performed.
//
BOOLEAN PlayActive;
//
// Indicates whether the blocksize used for user data
// is 2048 or 2352.
//
BOOLEAN RawAccess;
//
// Indicates whether 6 or 10 byte mode sense/select
// should be used.
//
USHORT XAFlags;
//
// Storage for the error recovery page. This is used
// as an easy method to switch block sizes.
//
union {
ERROR_RECOVERY_DATA u1;
ERROR_RECOVERY_DATA10 u2;
};
//
// Pointer to the original irp for the raw read.
//
PIRP SavedReadIrp;
//
// Used to protect accesses to the RawAccess flag.
//
KSPIN_LOCK FormSpinLock;
//
// Even if media change support is requested, there are some devices
// that are not supported. This flag will indicate that such a device
// is present when it is FALSE.
//
BOOLEAN MediaChangeSupported;
//
// The media change event is being supported. The media change timer
// should be running whenever this is true.
//
BOOLEAN MediaChange;
//
// The timer value to support media change events. This is a countdown
// value used to determine when to poll the device for a media change.
// The max value for the timer is 255 seconds.
//
UCHAR MediaChangeCountDown;
#ifdef DBG
//
// Second timer to keep track of how long the media change IRP has been
// in use. If this value exceeds the timeout (#defined) then we should
// print out a message to the user and set the MediaChangeIrpLost flag
//
SHORT MediaChangeIrpTimeInUse;
//
// Set by CdRomTickHandler when we determine that the media change irp has
// been lost
//
BOOLEAN MediaChangeIrpLost;
#endif
UCHAR PadReserve; // use this for new flags.
//
// An IRP is allocated and kept for the duration that media change
// detection is in effect. If this is NULL and MediaChange is TRUE,
// the detection is in progress. This should always be NULL when
// MediaChange is FALSE.
//
PIRP MediaChangeIrp;
//
// The timer work list is a collection of IRPS that are prepared for
// submission, but need to allow some time to pass before they are
// run.
//
LIST_ENTRY TimerIrpList;
KSPIN_LOCK TimerIrpSpinLock;
} CDROM_DATA, *PCDROM_DATA;
#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(CDROM_DATA)
#define SCSI_CDROM_TIMEOUT 10
#define SCSI_CHANGER_BONUS_TIMEOUT 10
#define HITACHI_MODE_DATA_SIZE 12
#define MODE_DATA_SIZE 64
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
#define MEDIA_CHANGE_DEFAULT_TIME 4
#define CDROM_SRB_LIST_SIZE 4
#ifdef DBG
//
// Used to detect the loss of the autorun irp. The driver prints out a message
// (debug level 0) if this timeout ever occurs
//
#define MEDIA_CHANGE_TIMEOUT_TIME 300
#endif
#define PLAY_ACTIVE(DeviceExtension) (((PCDROM_DATA)(DeviceExtension + 1))->PlayActive)
#define MSF_TO_LBA(Minutes,Seconds,Frames) \
(ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150))
#define LBA_TO_MSF(Lba,Minutes,Seconds,Frames) \
{ \
(Minutes) = (UCHAR)(Lba / (60 * 75)); \
(Seconds) = (UCHAR)((Lba % (60 * 75)) / 75); \
(Frames) = (UCHAR)((Lba % (60 * 75)) % 75); \
}
#define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
//
// Define flags for XA, CDDA, and Mode Select/Sense
//
#define XA_USE_6_BYTE 0x01
#define XA_USE_10_BYTE 0x02
#define XA_USE_READ_CD 0x04
#define XA_NOT_SUPPORTED 0x08
#define PLEXTOR_CDDA 0x10
#define NEC_CDDA 0x20
//
// Sector types for READ_CD
//
#define ANY_SECTOR 0
#define CD_DA_SECTOR 1
#define YELLOW_MODE1_SECTOR 2
#define YELLOW_MODE2_SECTOR 3
#define FORM2_MODE1_SECTOR 4
#define FORM2_MODE2_SECTOR 5
#ifdef POOL_TAGGING
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'CscS')
#endif
NTSTATUS
STDCALL
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
BOOLEAN
STDCALL
ScsiCdRomFindDevices(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PCLASS_INIT_DATA InitializationData,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber
);
NTSTATUS
STDCALL
ScsiCdRomOpenClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
STDCALL
ScsiCdRomReadVerification(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
STDCALL
ScsiCdRomSwitchMode(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG SectorSize,
IN PIRP OriginalRequest
);
NTSTATUS
STDCALL
CdRomDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
STDCALL
CdRomDeviceControlCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
STDCALL
CdRomSetVolumeIntermediateCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
STDCALL
CdRomSwitchModeCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
STDCALL
CdRomXACompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
STDCALL
CdRomClassIoctlCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
VOID
STDCALL
ScsiCdRomStartIo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
STDCALL
CdRomTickHandler(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
);
BOOLEAN
STDCALL
CdRomCheckRegistryForMediaChangeValue(
IN PUNICODE_STRING RegistryPath,
IN ULONG DeviceNumber
);
NTSTATUS
STDCALL
CdRomUpdateCapacity(
IN PDEVICE_EXTENSION DeviceExtension,
IN PIRP IrpToComplete,
IN OPTIONAL PKEVENT IoctlEvent
);
NTSTATUS
STDCALL
CreateCdRomDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber,
IN PULONG DeviceCount,
PIO_SCSI_CAPABILITIES PortCapabilities,
IN PSCSI_INQUIRY_DATA LunInfo,
IN PCLASS_INIT_DATA InitializationData,
IN PUNICODE_STRING RegistryPath
);
VOID
STDCALL
ScanForSpecial(
PDEVICE_OBJECT DeviceObject,
PINQUIRYDATA InquiryData,
PIO_SCSI_CAPABILITIES PortCapabilities
);
BOOLEAN
STDCALL
CdRomIsPlayActive(
IN PDEVICE_OBJECT DeviceObject
);
VOID
STDCALL
HitachProcessError(
PDEVICE_OBJECT DeviceObject,
PSCSI_REQUEST_BLOCK Srb,
NTSTATUS *Status,
BOOLEAN *Retry
);
VOID
STDCALL
ToshibaProcessError(
PDEVICE_OBJECT DeviceObject,
PSCSI_REQUEST_BLOCK Srb,
NTSTATUS *Status,
BOOLEAN *Retry
);
BOOLEAN
STDCALL
IsThisAnAtapiChanger(
IN PDEVICE_OBJECT DeviceObject,
OUT PULONG DiscsPresent
);
BOOLEAN
STDCALL
IsThisASanyo(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR PathId,
IN UCHAR TargetId
);
BOOLEAN
STDCALL
IsThisAMultiLunDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT PortDeviceObject
);
VOID
STDCALL
CdRomCreateNamedEvent(
IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceNumber
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -