diff --git a/drivers/storage/class/cdrom/CMakeLists.txt b/drivers/storage/class/cdrom/CMakeLists.txt deleted file mode 100644 index 97b7a2431df..00000000000 --- a/drivers/storage/class/cdrom/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -include_directories(${REACTOS_SOURCE_DIR}/drivers/storage/class) - -list(APPEND SOURCE - cdrom.c - findscsi.c - precomp.h) - -add_library(cdrom MODULE ${SOURCE} cdrom.rc) -set_module_type(cdrom kernelmodedriver) -add_importlibs(cdrom class2 scsiport ntoskrnl hal) -add_pch(cdrom precomp.h SOURCE) -add_cd_file(TARGET cdrom DESTINATION reactos/system32/drivers NO_CAB FOR all) -add_registry_inf(cdrom_reg.inf) -add_driver_inf(cdrom cdrom.inf) diff --git a/drivers/storage/class/cdrom/cdrom.c b/drivers/storage/class/cdrom/cdrom.c deleted file mode 100644 index 2794e62f2ea..00000000000 --- a/drivers/storage/class/cdrom/cdrom.c +++ /dev/null @@ -1,7359 +0,0 @@ -/* - * 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 "precomp.h" - -#include -#include -#include -#include -#include -#include - -//#define NDEBUG -#include - -#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; - -#if 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 - - -#if 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 -NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ); - -BOOLEAN -NTAPI -ScsiCdRomFindDevices( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN PCLASS_INIT_DATA InitializationData, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber - ); - -NTSTATUS -NTAPI -ScsiCdRomOpenClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiCdRomReadVerification( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiCdRomSwitchMode( - IN PDEVICE_OBJECT DeviceObject, - IN ULONG SectorSize, - IN PIRP OriginalRequest - ); - -NTSTATUS -NTAPI -CdRomDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -IO_COMPLETION_ROUTINE CdRomDeviceControlCompletion; -NTSTATUS -NTAPI -CdRomDeviceControlCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -IO_COMPLETION_ROUTINE CdRomSetVolumeIntermediateCompletion; -NTSTATUS -NTAPI -CdRomSetVolumeIntermediateCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -IO_COMPLETION_ROUTINE CdRomSwitchModeCompletion; -NTSTATUS -NTAPI -CdRomSwitchModeCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -IO_COMPLETION_ROUTINE CdRomXACompletion; -NTSTATUS -NTAPI -CdRomXACompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -IO_COMPLETION_ROUTINE CdRomClassIoctlCompletion; -NTSTATUS -NTAPI -CdRomClassIoctlCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -VOID -NTAPI -ScsiCdRomStartIo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -NTAPI -CdRomTickHandler( - IN PDEVICE_OBJECT DeviceObject, - IN PVOID Context - ); - -BOOLEAN -NTAPI -CdRomCheckRegistryForMediaChangeValue( - IN PUNICODE_STRING RegistryPath, - IN ULONG DeviceNumber - ); - -NTSTATUS -NTAPI -CdRomUpdateCapacity( - IN PDEVICE_EXTENSION DeviceExtension, - IN PIRP IrpToComplete, - IN OPTIONAL PKEVENT IoctlEvent - ); - -NTSTATUS -NTAPI -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 -NTAPI -ScanForSpecial( - PDEVICE_OBJECT DeviceObject, - PINQUIRYDATA InquiryData, - PIO_SCSI_CAPABILITIES PortCapabilities - ); - -BOOLEAN -NTAPI -CdRomIsPlayActive( - IN PDEVICE_OBJECT DeviceObject - ); - -VOID -NTAPI -HitachProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ); - -IO_COMPLETION_ROUTINE ToshibaProcessErrorCompletion; -VOID -NTAPI -ToshibaProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ); - -BOOLEAN -NTAPI -IsThisAnAtapiChanger( - IN PDEVICE_OBJECT DeviceObject, - OUT PULONG DiscsPresent - ); - -BOOLEAN -NTAPI -IsThisASanyo( - IN PDEVICE_OBJECT DeviceObject, - IN UCHAR PathId, - IN UCHAR TargetId - ); - -BOOLEAN -NTAPI -IsThisAMultiLunDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PDEVICE_OBJECT PortDeviceObject - ); - -VOID -NTAPI -CdRomCreateNamedEvent( - IN PDEVICE_EXTENSION DeviceExtension, - IN ULONG DeviceNumber - ); - -#ifdef _PPC_ -NTSTATUS -FindScsiAdapter ( - IN HANDLE KeyHandle, - IN UNICODE_STRING ScsiUnicodeString[], - OUT PUCHAR IntermediateController - ); -#endif - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, DriverEntry) -#pragma alloc_text(PAGE, ScsiCdRomFindDevices) -#pragma alloc_text(PAGE, CreateCdRomDeviceObject) -#pragma alloc_text(PAGE, ScanForSpecial) -//#pragma alloc_text(PAGE, CdRomDeviceControl) -#pragma alloc_text(PAGE, HitachProcessError) -#pragma alloc_text(PAGE, CdRomIsPlayActive) -#pragma alloc_text(PAGE, ScsiCdRomReadVerification) -#pragma alloc_text(INIT, CdRomCheckRegistryForMediaChangeValue) -#pragma alloc_text(INIT, IsThisAnAtapiChanger) -#pragma alloc_text(INIT, IsThisASanyo) -#pragma alloc_text(INIT, IsThisAMultiLunDevice) -#pragma alloc_text(INIT, CdRomCreateNamedEvent) -#ifdef _PPC_ -#pragma alloc_text(PAGE, FindScsiAdapter) -#endif -#endif - -ULONG NoLoad = 0; - -NTSTATUS -NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) - -/*++ - -Routine Description: - - This routine initializes the cdrom class driver. - -Arguments: - - DriverObject - Pointer to driver object created by system. - - RegistryPath - Pointer to the name of the services node for this driver. - -Return Value: - - The function value is the final status from the initialization operation. - ---*/ - -{ - CLASS_INIT_DATA InitializationData; - - if(NoLoad) { - return STATUS_NO_SUCH_DEVICE; - } - - // - // Zero InitData - // - - RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA)); - - // - // Set sizes - // - - InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA); - InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE; - - InitializationData.DeviceType = FILE_DEVICE_CD_ROM; - InitializationData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE; - - // - // Set entry points - // - - InitializationData.ClassReadWriteVerification = ScsiCdRomReadVerification; - InitializationData.ClassDeviceControl = CdRomDeviceControl; - InitializationData.ClassFindDevices = ScsiCdRomFindDevices; - InitializationData.ClassShutdownFlush = NULL; - InitializationData.ClassCreateClose = NULL; - InitializationData.ClassStartIo = ScsiCdRomStartIo; - - // - // Call the class init routine - // - - return ScsiClassInitialize( DriverObject, RegistryPath, &InitializationData); - -} // end DriverEntry() - -BOOLEAN -NTAPI -ScsiCdRomFindDevices( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN PCLASS_INIT_DATA InitializationData, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber - ) - -/*++ - -Routine Description: - - Connect to SCSI port driver. Get adapter capabilities and - SCSI bus configuration information. Search inquiry data - for CDROM devices to process. - -Arguments: - - DriverObject - CDROM class driver object. - PortDeviceObject - SCSI port driver device object. - PortNumber - The system ordinal for this scsi adapter. - -Return Value: - - TRUE if CDROM device present on this SCSI adapter. - ---*/ - -{ - PIO_SCSI_CAPABILITIES portCapabilities; - PULONG cdRomCount; - PCHAR buffer; - PSCSI_INQUIRY_DATA lunInfo; - PSCSI_ADAPTER_BUS_INFO adapterInfo; - PINQUIRYDATA inquiryData; - ULONG scsiBus; - NTSTATUS status; - BOOLEAN foundDevice = FALSE; - - // - // Call port driver to get adapter capabilities. - // - - status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities); - - if (!NT_SUCCESS(status)) { - DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n")); - return foundDevice; - } - - // - // Call port driver to get inquiry information to find cdroms. - // - - status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer); - - if (!NT_SUCCESS(status)) { - DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n")); - return foundDevice; - } - - // - // Get the address of the count of the number of cdroms already initialized. - // - - cdRomCount = &IoGetConfigurationInformation()->CdRomCount; - adapterInfo = (PVOID) buffer; - - // - // For each SCSI bus this adapter supports ... - // - - for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) { - - // - // Get the SCSI bus scan data for this bus. - // - - lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset); - - // - // Search list for unclaimed disk devices. - // - - while (adapterInfo->BusData[scsiBus].InquiryDataOffset) { - - inquiryData = (PVOID)lunInfo->InquiryData; - - if ((inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) && - (inquiryData->DeviceTypeQualifier == 0) && - (!lunInfo->DeviceClaimed)) { - - DebugPrint((1,"FindScsiDevices: Vendor string is %.24s\n", - inquiryData->VendorId)); - - // - // Create device objects for cdrom - // - - status = CreateCdRomDeviceObject(DriverObject, - PortDeviceObject, - PortNumber, - cdRomCount, - portCapabilities, - lunInfo, - InitializationData, - RegistryPath); - - if (NT_SUCCESS(status)) { - - // - // Increment system cdrom device count. - // - - (*cdRomCount)++; - - // - // Indicate that a cdrom device was found. - // - - foundDevice = TRUE; - } - } - - // - // Get next LunInfo. - // - - if (lunInfo->NextInquiryDataOffset == 0) { - break; - } - - lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset); - } - } - - ExFreePool(buffer); - - - return foundDevice; - -} // end FindScsiCdRoms() - -VOID -NTAPI -CdRomCreateNamedEvent( - IN PDEVICE_EXTENSION DeviceExtension, - IN ULONG DeviceNumber - ) - -/*++ - -Routine Description: - - Create the named synchronization event for notification of media change - events to the system. The event is reset before this function returns. - -Arguments: - - DeviceExtension - the device extension pointer for storage of the event pointer. - -Return Value: - - None. - ---*/ - -{ - UNICODE_STRING unicodeString; - OBJECT_ATTRIBUTES objectAttributes; - CCHAR eventNameBuffer[MAXIMUM_FILENAME_LENGTH]; - STRING eventNameString; - HANDLE handle; - NTSTATUS status; - - - sprintf(eventNameBuffer,"\\Device\\MediaChangeEvent%ld", - DeviceNumber); - - RtlInitString(&eventNameString, - eventNameBuffer); - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &eventNameString, - TRUE); - - if (!NT_SUCCESS(status)) { - return; - } - - InitializeObjectAttributes(&objectAttributes, - &unicodeString, - OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, - NULL, - NULL); - - DeviceExtension->MediaChangeEvent = IoCreateSynchronizationEvent(&unicodeString, - &handle); - DeviceExtension->MediaChangeEventHandle = handle; - - KeClearEvent(DeviceExtension->MediaChangeEvent); - - RtlFreeUnicodeString(&unicodeString); -} - - -VOID -NTAPI -ReportToMountMgr( - IN PDEVICE_OBJECT CdDeviceObject - ) - -/*++ - -Routine Description: - - This routine reports the creation of a cdrom device object to the - MountMgr to fake PnP. - -Arguments: - - CdDeviceObject - Pointer to the created cdrom device. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS status; - UNICODE_STRING mountMgrDevice; - PDEVICE_OBJECT deviceObject; - PFILE_OBJECT fileObject; - PMOUNTMGR_TARGET_NAME mountTarget; - ULONG cdLen; - PDEVICE_EXTENSION deviceExtension; - PIRP irp; - KEVENT event; - IO_STATUS_BLOCK ioStatus; - - // - // First, get MountMgr DeviceObject. - // - - RtlInitUnicodeString(&mountMgrDevice, MOUNTMGR_DEVICE_NAME); - status = IoGetDeviceObjectPointer(&mountMgrDevice, FILE_READ_ATTRIBUTES, - &fileObject, &deviceObject); - - if (!NT_SUCCESS(status)) { - - DebugPrint((1, - "ReportToMountMgr: Can't get MountMgr pointers %lx\n", - status)); - - return; - } - - deviceExtension = CdDeviceObject->DeviceExtension; - cdLen = deviceExtension->DeviceName.Length; - - // - // Allocate input buffer to report our partition device. - // - - mountTarget = ExAllocatePool(NonPagedPool, - sizeof(MOUNTMGR_TARGET_NAME) + cdLen); - - if (!mountTarget) { - - DebugPrint((1, - "ReportToMountMgr: Allocation of mountTarget failed\n")); - - ObDereferenceObject(fileObject); - return; - } - - mountTarget->DeviceNameLength = cdLen; - RtlCopyMemory(mountTarget->DeviceName, deviceExtension->DeviceName.Buffer, cdLen); - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Build the IRP used to communicate with the MountMgr. - // - - irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, - deviceObject, - mountTarget, - sizeof(MOUNTMGR_TARGET_NAME) + cdLen, - NULL, - 0, - FALSE, - &event, - &ioStatus); - - if (!irp) { - - DebugPrint((1, - "ReportToMountMgr: Allocation of irp failed\n")); - - ExFreePool(mountTarget); - ObDereferenceObject(fileObject); - return; - } - - // - // Call the MountMgr. - // - - status = IoCallDriver(deviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - // - // We're done. - // - - DPRINT1("Reported to the MountMgr: %lx\n", status); - - ExFreePool(mountTarget); - ObDereferenceObject(fileObject); - - return; -} - - -NTSTATUS -NTAPI -CreateCdRomDeviceObject( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber, - IN PULONG DeviceCount, - IN PIO_SCSI_CAPABILITIES PortCapabilities, - IN PSCSI_INQUIRY_DATA LunInfo, - IN PCLASS_INIT_DATA InitializationData, - IN PUNICODE_STRING RegistryPath - ) - -/*++ - -Routine Description: - - This routine creates an object for the device and then calls the - SCSI port driver for media capacity and sector size. - -Arguments: - - DriverObject - Pointer to driver object created by system. - PortDeviceObject - to connect to SCSI port driver. - DeviceCount - Number of previously installed CDROMs. - PortCapabilities - Pointer to structure returned by SCSI port - driver describing adapter capabilities (and limitations). - LunInfo - Pointer to configuration information for this device. - -Return Value: - - NTSTATUS - ---*/ -{ - CHAR ntNameBuffer[64]; - NTSTATUS status; - BOOLEAN changerDevice; - SCSI_REQUEST_BLOCK srb; - ULONG length; - PCDROM_DATA cddata; - PCDB cdb; - PVOID senseData = NULL; - PDEVICE_OBJECT deviceObject = NULL; - PDEVICE_EXTENSION deviceExtension = NULL; - PUCHAR buffer; - ULONG bps; - ULONG lastBit; - ULONG timeOut; - BOOLEAN srbListInitialized = FALSE; - - // - // Claim the device. Note that any errors after this - // will goto the generic handler, where the device will - // be released. - // - - status = ScsiClassClaimDevice(PortDeviceObject, - LunInfo, - FALSE, - &PortDeviceObject); - - if (!NT_SUCCESS(status)) { - return(status); - } - - // - // Create device object for this device. - // - - sprintf(ntNameBuffer, - "\\Device\\CdRom%lu", - *DeviceCount); - - status = ScsiClassCreateDeviceObject(DriverObject, - ntNameBuffer, - NULL, - &deviceObject, - InitializationData); - - if (!NT_SUCCESS(status)) { - DebugPrint((1,"CreateCdRomDeviceObjects: Can not create device %s\n", - ntNameBuffer)); - - goto CreateCdRomDeviceObjectExit; - } - - // - // Indicate that IRPs should include MDLs. - // - - deviceObject->Flags |= DO_DIRECT_IO; - - // - // Set up required stack size in device object. - // - - deviceObject->StackSize = PortDeviceObject->StackSize + 2; - - deviceExtension = deviceObject->DeviceExtension; - - // - // Allocate spinlock for split request completion. - // - - KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock); - - // - // This is the physical device. - // - - deviceExtension->PhysicalDevice = deviceObject; - - // - // Initialize lock count to zero. The lock count is used to - // disable the ejection mechanism when media is mounted. - // - - deviceExtension->LockCount = 0; - - // - // Save system cdrom number - // - - deviceExtension->DeviceNumber = *DeviceCount; - - // - // Copy port device object to device extension. - // - - deviceExtension->PortDeviceObject = PortDeviceObject; - - // - // Set the alignment requirements for the device based on the - // host adapter requirements - // - - if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) { - deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement; - } - - // - // Save address of port driver capabilities. - // - - deviceExtension->PortCapabilities = PortCapabilities; - - // - // Clear SRB flags. - // - - deviceExtension->SrbFlags = 0; - deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // - // Allocate request sense buffer. - // - - senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); - - if (senseData == NULL) { - - // - // The buffer cannot be allocated. - // - - status = STATUS_INSUFFICIENT_RESOURCES; - goto CreateCdRomDeviceObjectExit; - } - - // - // Set the sense data pointer in the device extension. - // - - deviceExtension->SenseData = senseData; - - // - // CDROMs are not partitionable so starting offset is 0. - // - - deviceExtension->StartingOffset.LowPart = 0; - deviceExtension->StartingOffset.HighPart = 0; - - // - // Path/TargetId/LUN describes a device location on the SCSI bus. - // This information comes from the LunInfo buffer. - // - - deviceExtension->PortNumber = (UCHAR)PortNumber; - deviceExtension->PathId = LunInfo->PathId; - deviceExtension->TargetId = LunInfo->TargetId; - deviceExtension->Lun = LunInfo->Lun; - - // - // Set timeout value in seconds. - // - - timeOut = ScsiClassQueryTimeOutRegistryValue(RegistryPath); - if (timeOut) { - deviceExtension->TimeOutValue = timeOut; - } else { - deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT; - } - - // - // Build the lookaside list for srb's for the physical disk. Should only - // need a couple. - // - - ScsiClassInitializeSrbLookasideList(deviceExtension, - CDROM_SRB_LIST_SIZE); - - srbListInitialized = TRUE; - - // - // Back pointer to device object. - // - - deviceExtension->DeviceObject = deviceObject; - - // - // Allocate buffer for drive geometry. - // - - deviceExtension->DiskGeometry = - ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY_EX)); - - if (deviceExtension->DiskGeometry == NULL) { - - status = STATUS_INSUFFICIENT_RESOURCES; - goto CreateCdRomDeviceObjectExit; - } - - // - // Set up media change support defaults. - // - - cddata = (PCDROM_DATA)(deviceExtension + 1); - - KeInitializeSpinLock(&cddata->FormSpinLock); - KeInitializeSpinLock(&cddata->TimerIrpSpinLock); - InitializeListHead(&cddata->TimerIrpList); - - cddata->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME; - cddata->MediaChangeSupported = FALSE; - cddata->MediaChange = FALSE; - - // - // Assume that there is initially no media in the device - // only notify upper layers if there is something there - // - - deviceExtension->MediaChangeNoMedia = TRUE; - cddata->MediaChangeIrp = NULL; -#if DBG - cddata->MediaChangeIrpTimeInUse = 0; - cddata->MediaChangeIrpLost = FALSE; -#endif - - // - // Scan for Scsi controllers that require special processing. - // - - ScanForSpecial(deviceObject, - (PINQUIRYDATA) LunInfo->InquiryData, - PortCapabilities); - - // - // Do READ CAPACITY. This SCSI command - // returns the last sector address on the device - // and the bytes per sector. - // These are used to calculate the drive capacity - // in bytes. - // - - status = ScsiClassReadDriveCapacity(deviceObject); - bps = deviceExtension->DiskGeometry->Geometry.BytesPerSector; - - if (!NT_SUCCESS(status) || !bps) { - - DebugPrint((1, - "CreateCdRomDeviceObjects: Can't read capacity for device %s\n", - ntNameBuffer)); - - // - // Set disk geometry to default values (per ISO 9660). - // - - bps = 2048; - deviceExtension->SectorShift = 11; - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff); - } else { - - // - // Insure that bytes per sector is a power of 2 - // This corrects a problem with the HP 4020i CDR where it - // returns an incorrect number for bytes per sector. - // - - lastBit = (ULONG) -1; - while (bps) { - lastBit++; - bps = bps >> 1; - } - - bps = 1 << lastBit; - } - deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; - DebugPrint((2, "CreateCdRomDeviceObject: Calc'd bps = %x\n", bps)); - - // - // Check to see if this is some sort of changer device - // - - changerDevice = FALSE; - - // - // Search for devices that have special requirements for media - // change support. - // - - if (deviceExtension->Lun > 0) { - changerDevice = TRUE; - } - - if (!changerDevice) { - changerDevice = IsThisASanyo(deviceObject, deviceExtension->PathId, - deviceExtension->TargetId); - } - - if (!changerDevice) { - ULONG tmp; - changerDevice = IsThisAnAtapiChanger(deviceObject, &tmp); - } - - if (!changerDevice) { - changerDevice = IsThisAMultiLunDevice(deviceObject, PortDeviceObject); - } - - // - // If it is a changer device, increment the timeout to take platter-swapping - // time into account - // - - if(changerDevice) { - deviceExtension->TimeOutValue += SCSI_CHANGER_BONUS_TIMEOUT; - } - - // - // Create the media change named event. If this succeeds then continue - // initializing the media change support data items. - // - - CdRomCreateNamedEvent(deviceExtension,*DeviceCount); - if (deviceExtension->MediaChangeEvent) { - - // - // If this is not a changer, get an IRP for the timer request - // and initialize the timer. - // - - if (!changerDevice) { - - // - // Not a changer device - continue with media change initialization. - // Determine if the user actually wants media change events. - // - - if (CdRomCheckRegistryForMediaChangeValue(RegistryPath, *DeviceCount)) { - PIO_STACK_LOCATION irpStack; - PSCSI_REQUEST_BLOCK srb; - PIRP irp; - - // - // User wants it - preallocate IRP and SRB. - // - - irp = IoAllocateIrp((CCHAR)(deviceObject->StackSize+1), - FALSE); - if (irp) { - PVOID buffer; - - srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); - buffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); - - if (srb && buffer) { - PCDB cdb; - - // - // All resources have been allocated set up the IRP. - // - - IoSetNextIrpStackLocation(irp); - irpStack = IoGetCurrentIrpStackLocation(irp); - irpStack->DeviceObject = deviceObject; - irpStack = IoGetNextIrpStackLocation(irp); - cddata->MediaChangeIrp = irp; - irpStack->Parameters.Scsi.Srb = srb; - - // - // Initialize the SRB - // - - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - - srb->CdbLength = 6; - srb->TimeOutValue = deviceExtension->TimeOutValue * 2; - srb->QueueTag = SP_UNTAGGED; - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - - // - // Initialize and set up the sense information buffer - // - - RtlZeroMemory(buffer, SENSE_BUFFER_SIZE); - srb->SenseInfoBuffer = buffer; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - - // - // Initialize the CDB - // - - cdb = (PCDB)&srb->Cdb[0]; - cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; - cdb->CDB6GENERIC.LogicalUnitNumber = deviceExtension->Lun; - - // - // It is ok to support media change events on this device. - // - - cddata->MediaChangeSupported = TRUE; - cddata->MediaChange = TRUE; - - } else { - - if (srb) { - ExFreePool(srb); - } - if (buffer) { - ExFreePool(buffer); - } - IoFreeIrp(irp); - } - } - } else { - deviceExtension->MediaChangeEvent = NULL; - } - } else { - deviceExtension->MediaChangeEvent = NULL; - } - } - - // - // Assume use of 6-byte mode sense/select for now. - // - - cddata->XAFlags |= XA_USE_6_BYTE; - - // - // Build and issue mode sense with Read error recovery page. This will be used to change - // block size in case of any raw reads (Mode 2, Form 2). - // - - length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH); - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - srb.CdbLength = 6; - cdb = (PCDB)srb.Cdb; - - // - // Set timeout value from device extension. - // - - srb.TimeOutValue = deviceExtension->TimeOutValue; - - // - // Build the MODE SENSE CDB. The data returned will be kept in the device extension - // and used to set block size. - // - - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.PageCode = 0x1; - cdb->MODE_SENSE.AllocationLength = (UCHAR)length; - - buffer = ExAllocatePool(NonPagedPoolCacheAligned, (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10)); - if (!buffer) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto CreateCdRomDeviceObjectExit; - } - - status = ScsiClassSendSrbSynchronous(deviceObject, - &srb, - buffer, - length, - FALSE); - if (!NT_SUCCESS(status)) { - - // - // May be Atapi, try 10-byte. - // - - length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10); - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // - // Build the MODE SENSE CDB. - // - - srb.CdbLength = 10; - cdb = (PCDB)srb.Cdb; - - // - // Set timeout value from device extension. - // - - srb.TimeOutValue = deviceExtension->TimeOutValue; - - cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; - cdb->MODE_SENSE10.PageCode = 0x1; - - cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(length >> 8); - cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(length & 0xFF); - - status = ScsiClassSendSrbSynchronous(deviceObject, - &srb, - buffer, - length, - FALSE); - if (status == STATUS_DATA_OVERRUN) { - - // - // Build and issue the ReadCd command to ensure that this device supports it. - // - - RtlZeroMemory(cdb, 12); - - cdb->READ_CD.OperationCode = SCSIOP_READ_CD; - - status = ScsiClassSendSrbSynchronous(deviceObject, - &srb, - NULL, - 0, - FALSE); - - // - // If the command wasn't rejected then support the READ_CD. - // - - if (NT_SUCCESS(status) || (status == STATUS_NO_MEDIA_IN_DEVICE)) { - - // - // Using Read CD precludes issuing a mode select to - // set the user data size. So, no buffer copy is - // necessary. - // - - cddata->XAFlags &= ~XA_USE_6_BYTE; - cddata->XAFlags |= XA_USE_READ_CD | XA_USE_10_BYTE; - } else { - - RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10)); - cddata->u1.Header.ModeDataLength = 0; - - cddata->XAFlags &= ~XA_USE_6_BYTE; - cddata->XAFlags |= XA_USE_10_BYTE; - } - - } else if (NT_SUCCESS(status)) { - - RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10)); - cddata->u1.Header.ModeDataLength = 0; - - cddata->XAFlags &= ~XA_USE_6_BYTE; - cddata->XAFlags |= XA_USE_10_BYTE; - - } else { - cddata->XAFlags |= XA_NOT_SUPPORTED; - } - } else { - RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA)); - cddata->u1.Header.ModeDataLength = 0; - } - - ExFreePool(buffer); - - ReportToMountMgr(deviceObject); - - // - // Start the timer now regardless of if Autorun is enabled. - // The timer must run forever since IoStopTimer faults. - // - - IoInitializeTimer(deviceObject, CdRomTickHandler, NULL); - IoStartTimer(deviceObject); - - return(STATUS_SUCCESS); - -CreateCdRomDeviceObjectExit: - - // - // Release the device since an error occured. - // - - ScsiClassClaimDevice(PortDeviceObject, - LunInfo, - TRUE, - NULL); - - if (senseData != NULL) { - ExFreePool(senseData); - } - - if (deviceExtension->DiskGeometry != NULL) { - ExFreePool(deviceExtension->DiskGeometry); - } - - if (deviceObject != NULL) { - if (srbListInitialized) { - ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead); - } - IoDeleteDevice(deviceObject); - } - - - return status; - -} // end CreateCdRomDeviceObject() - -VOID -NTAPI -ScsiCdRomStartIo( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) -{ - - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); - PIO_STACK_LOCATION irpStack; - PIRP irp2 = NULL; - ULONG transferPages; - ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; - ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; - PCDROM_DATA cdData; - PSCSI_REQUEST_BLOCK srb = NULL; - PCDB cdb; - PUCHAR senseBuffer = NULL; - PVOID dataBuffer; - NTSTATUS status; - BOOLEAN use6Byte; - - // - // Mark IRP with status pending. - // - - IoMarkIrpPending(Irp); - - // - // If the flag is set in the device object, force a verify. - // - - if (DeviceObject->Flags & DO_VERIFY_VOLUME) { - DebugPrint((2, "ScsiCdRomStartIo: [%lx] Volume needs verified\n", Irp)); - if (!(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { - - if (Irp->Tail.Overlay.Thread) { - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - } - - Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; - - DebugPrint((2, "ScsiCdRomStartIo: [%lx] Calling UpdateCapacity - " - "ioctl event = %lx\n", - Irp, - nextIrpStack->Parameters.Others.Argument1 - )); - - // - // our device control dispatch routine stores an event in the next - // stack location to signal when startio has completed. We need to - // pass this in so that the update capacity completion routine can - // set it rather than completing the Irp. - // - - status = CdRomUpdateCapacity(deviceExtension, - Irp, - nextIrpStack->Parameters.Others.Argument1 - ); - - DebugPrint((2, "ScsiCdRomStartIo: [%lx] UpdateCapacity returned %lx\n", Irp, status)); - ASSERT(status == STATUS_PENDING); - return; - } - } - - cdData = (PCDROM_DATA)(deviceExtension + 1); - use6Byte = cdData->XAFlags & XA_USE_6_BYTE; - - if (currentIrpStack->MajorFunction == IRP_MJ_READ) { - - // - // Add partition byte offset to make starting byte relative to - // beginning of disk. In addition, add in skew for DM Driver, if any. - // - - currentIrpStack->Parameters.Read.ByteOffset.QuadPart += (deviceExtension->StartingOffset.QuadPart); - - // - // Calculate number of pages in this transfer. - // - - transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), - currentIrpStack->Parameters.Read.Length); - - // - // Check if request length is greater than the maximum number of - // bytes that the hardware can transfer. - // - - if (cdData->RawAccess) { - - ASSERT(!(cdData->XAFlags & XA_USE_READ_CD)); - - // - // Fire off a mode select to switch back to cooked sectors. - // - - irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1), - FALSE); - - if (!irp2) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); - if (!srb) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - - cdb = (PCDB)srb->Cdb; - - // - // Allocate sense buffer. - // - - senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); - - if (!senseBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - // - // Set up the irp. - // - - IoSetNextIrpStackLocation(irp2); - irp2->IoStatus.Status = STATUS_SUCCESS; - irp2->IoStatus.Information = 0; - irp2->Flags = 0; - irp2->UserBuffer = NULL; - - // - // Save the device object and irp in a private stack location. - // - - irpStack = IoGetCurrentIrpStackLocation(irp2); - irpStack->DeviceObject = deviceExtension->DeviceObject; - irpStack->Parameters.Others.Argument2 = (PVOID) Irp; - - // - // The retry count will be in the real Irp, as the retry logic will - // recreate our private irp. - // - - if (!(nextIrpStack->Parameters.Others.Argument1)) { - - // - // Only jam this in if it doesn't exist. The completion routines can - // call StartIo directly in the case of retries and resetting it will - // cause infinite loops. - // - - nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; - } - - // - // Construct the IRP stack for the lower level driver. - // - - irpStack = IoGetNextIrpStackLocation(irp2); - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - irpStack->Parameters.Scsi.Srb = srb; - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->Cdb[1] |= deviceExtension->Lun << 5; - srb->SrbStatus = srb->ScsiStatus = 0; - srb->NextSrb = 0; - srb->OriginalRequest = irp2; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - srb->SenseInfoBuffer = senseBuffer; - - transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10); - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount ); - if (!dataBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - - } - - irp2->MdlAddress = IoAllocateMdl(dataBuffer, - transferByteCount, - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp2->MdlAddress) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp2->MdlAddress); - - srb->DataBuffer = dataBuffer; - - // - // Set the new block size in the descriptor. - // - - cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(COOKED_SECTOR_SIZE >> 16) & 0xFF; - cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(COOKED_SECTOR_SIZE >> 8) & 0xFF; - cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(COOKED_SECTOR_SIZE & 0xFF); - - // - // Move error page into dataBuffer. - // - - RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount); - - // - // Build and send a mode select to switch into raw mode. - // - - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT); - srb->DataTransferLength = transferByteCount; - srb->TimeOutValue = deviceExtension->TimeOutValue * 2; - - if (use6Byte) { - srb->CdbLength = 6; - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.PFBit = 1; - cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount; - } else { - - srb->CdbLength = 10; - cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; - cdb->MODE_SELECT10.PFBit = 1; - cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8); - cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF); - } - - // - // Update completion routine. - // - - IoSetCompletionRoutine(irp2, - CdRomSwitchModeCompletion, - srb, - TRUE, - TRUE, - TRUE); - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - } - - if ((currentIrpStack->Parameters.Read.Length > maximumTransferLength) || - (transferPages > - deviceExtension->PortCapabilities->MaximumPhysicalPages)) { - - // - // Request needs to be split. Completion of each portion of the - // request will fire off the next portion. The final request will - // signal Io to send a new request. - // - - transferPages = - deviceExtension->PortCapabilities->MaximumPhysicalPages - 1; - - if(maximumTransferLength > transferPages << PAGE_SHIFT) { - maximumTransferLength = transferPages << PAGE_SHIFT; - } - - // - // Check that the maximum transfer size is not zero - // - - if(maximumTransferLength == 0) { - maximumTransferLength = PAGE_SIZE; - } - - ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength); - return; - - } else { - - // - // Build SRB and CDB for this IRP. - // - - ScsiClassBuildRequest(DeviceObject, Irp); - - } - - - } else if (currentIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { - - // - // Allocate an irp, srb and associated structures. - // - - irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1), - FALSE); - - if (!irp2) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - IoStartNextPacket(DeviceObject, FALSE); - DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); - return; - } - - srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); - if (!srb) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); - return; - } - - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - - cdb = (PCDB)srb->Cdb; - - // - // Allocate sense buffer. - // - - senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); - - if (!senseBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); - return; - } - - // - // Set up the irp. - // - - IoSetNextIrpStackLocation(irp2); - irp2->IoStatus.Status = STATUS_SUCCESS; - irp2->IoStatus.Information = 0; - irp2->Flags = 0; - irp2->UserBuffer = NULL; - - // - // Save the device object and irp in a private stack location. - // - - irpStack = IoGetCurrentIrpStackLocation(irp2); - irpStack->DeviceObject = deviceExtension->DeviceObject; - irpStack->Parameters.Others.Argument2 = (PVOID) Irp; - - // - // The retry count will be in the real Irp, as the retry logic will - // recreate our private irp. - // - - if (!(nextIrpStack->Parameters.Others.Argument1)) { - - // - // Only jam this in if it doesn't exist. The completion routines can - // call StartIo directly in the case of retries and resetting it will - // cause infinite loops. - // - - nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; - } - - // - // Construct the IRP stack for the lower level driver. - // - - irpStack = IoGetNextIrpStackLocation(irp2); - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - irpStack->Parameters.Scsi.Srb = srb; - - IoSetCompletionRoutine(irp2, - CdRomDeviceControlCompletion, - srb, - TRUE, - TRUE, - TRUE); - // - // Setup those fields that are generic to all requests. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->Cdb[1] |= deviceExtension->Lun << 5; - srb->SrbStatus = srb->ScsiStatus = 0; - srb->NextSrb = 0; - srb->OriginalRequest = irp2; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - srb->SenseInfoBuffer = senseBuffer; - - switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) { - - case IOCTL_CDROM_RAW_READ: { - - // - // Determine whether the drive is currently in raw or cooked mode, - // and which command to use to read the data. - // - - if (!(cdData->XAFlags & XA_USE_READ_CD)) { - - PRAW_READ_INFO rawReadInfo = - (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; - ULONG maximumTransferLength; - ULONG transferPages; - - if (cdData->RawAccess) { - - ULONG startingSector; - - // - // Free the recently allocated irp, as we don't need it. - // - - IoFreeIrp(irp2); - - cdb = (PCDB)srb->Cdb; - RtlZeroMemory(cdb, 12); - - // - // Calculate starting offset. - // - - startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift); - transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; - maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; - transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), - transferByteCount); - - // - // Determine if request is within limits imposed by miniport. - // - - if (transferByteCount > maximumTransferLength || - transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) { - - // - // The claim is that this won't happen, and is backed up by - // ActiveMovie usage, which does unbuffered XA reads of 0x18000, yet - // we get only 4 sector requests. - // - - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoStartNextPacket(DeviceObject, FALSE); - return; - - } - - srb->OriginalRequest = Irp; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - srb->DataTransferLength = transferByteCount; - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->CdbLength = 10; - srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); - - if (rawReadInfo->TrackMode == CDDA) { - if (cdData->XAFlags & PLEXTOR_CDDA) { - - srb->CdbLength = 12; - - cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun; - cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); - cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); - cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); - cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); - - cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); - cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8); - cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0; - cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0; - - cdb->PLXTR_READ_CDDA.SubCode = 0; - cdb->PLXTR_READ_CDDA.OperationCode = 0xD8; - - } else if (cdData->XAFlags & NEC_CDDA) { - - cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); - cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); - cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); - cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); - - cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); - cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8); - - cdb->NEC_READ_CDDA.OperationCode = 0xD4; - } - } else { - - cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; - - cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8); - cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF); - - cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); - cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); - cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); - cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); - - cdb->CDB10.OperationCode = SCSIOP_READ; - } - - srb->SrbStatus = srb->ScsiStatus = 0; - - nextIrpStack->MajorFunction = IRP_MJ_SCSI; - nextIrpStack->Parameters.Scsi.Srb = srb; - - if (!(nextIrpStack->Parameters.Others.Argument1)) { - - // - // Only jam this in if it doesn't exist. The completion routines can - // call StartIo directly in the case of retries and resetting it will - // cause infinite loops. - // - - nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; - } - - // - // Set up IoCompletion routine address. - // - - IoSetCompletionRoutine(Irp, - CdRomXACompletion, - srb, - TRUE, - TRUE, - TRUE); - - IoCallDriver(deviceExtension->PortDeviceObject, Irp); - return; - - } else { - - transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10); - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount ); - if (!dataBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - - } - - irp2->MdlAddress = IoAllocateMdl(dataBuffer, - transferByteCount, - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp2->MdlAddress) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp2->MdlAddress); - - srb->DataBuffer = dataBuffer; - - // - // Set the new block size in the descriptor. - // - - cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(RAW_SECTOR_SIZE >> 16) & 0xFF; - cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(RAW_SECTOR_SIZE >> 8) & 0xFF; - cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(RAW_SECTOR_SIZE & 0xFF); - - - // - // TODO: Set density code, based on operation - // - - cdData->u1.BlockDescriptor.DensityCode = 0; - - - // - // Move error page into dataBuffer. - // - - RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount); - - - // - // Build and send a mode select to switch into raw mode. - // - - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT); - srb->DataTransferLength = transferByteCount; - srb->TimeOutValue = deviceExtension->TimeOutValue * 2; - - if (use6Byte) { - srb->CdbLength = 6; - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.PFBit = 1; - cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount; - } else { - - srb->CdbLength = 10; - cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; - cdb->MODE_SELECT10.PFBit = 1; - cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8); - cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF); - } - - // - // Update completion routine. - // - - IoSetCompletionRoutine(irp2, - CdRomSwitchModeCompletion, - srb, - TRUE, - TRUE, - TRUE); - - } - - } else { - - PRAW_READ_INFO rawReadInfo = - (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; - ULONG startingSector; - - // - // Free the recently allocated irp, as we don't need it. - // - - IoFreeIrp(irp2); - - cdb = (PCDB)srb->Cdb; - RtlZeroMemory(cdb, 12); - - - // - // Calculate starting offset. - // - - startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift); - transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; - - - srb->OriginalRequest = Irp; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - srb->DataTransferLength = transferByteCount; - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); - srb->CdbLength = 12; - srb->SrbStatus = srb->ScsiStatus = 0; - - // - // Fill in CDB fields. - // - - cdb = (PCDB)srb->Cdb; - - - cdb->READ_CD.TransferBlocks[2] = (UCHAR) (rawReadInfo->SectorCount & 0xFF); - cdb->READ_CD.TransferBlocks[1] = (UCHAR) (rawReadInfo->SectorCount >> 8 ); - cdb->READ_CD.TransferBlocks[0] = (UCHAR) (rawReadInfo->SectorCount >> 16); - - - cdb->READ_CD.StartingLBA[3] = (UCHAR) (startingSector & 0xFF); - cdb->READ_CD.StartingLBA[2] = (UCHAR) ((startingSector >> 8)); - cdb->READ_CD.StartingLBA[1] = (UCHAR) ((startingSector >> 16)); - cdb->READ_CD.StartingLBA[0] = (UCHAR) ((startingSector >> 24)); - - // - // Setup cdb depending upon the sector type we want. - // - - switch (rawReadInfo->TrackMode) { - case CDDA: - - cdb->READ_CD.ExpectedSectorType = CD_DA_SECTOR; - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 3; - cdb->READ_CD.IncludeSyncData = 1; - break; - - case YellowMode2: - - cdb->READ_CD.ExpectedSectorType = YELLOW_MODE2_SECTOR; - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 1; - cdb->READ_CD.IncludeSyncData = 1; - break; - - case XAForm2: - - cdb->READ_CD.ExpectedSectorType = FORM2_MODE2_SECTOR; - cdb->READ_CD.IncludeUserData = 1; - cdb->READ_CD.HeaderCode = 3; - cdb->READ_CD.IncludeSyncData = 1; - break; - - default: - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoStartNextPacket(DeviceObject, FALSE); - DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); - return; - } - - cdb->READ_CD.OperationCode = SCSIOP_READ_CD; - - nextIrpStack->MajorFunction = IRP_MJ_SCSI; - nextIrpStack->Parameters.Scsi.Srb = srb; - - if (!(nextIrpStack->Parameters.Others.Argument1)) { - - // - // Only jam this in if it doesn't exist. The completion routines can - // call StartIo directly in the case of retries and resetting it will - // cause infinite loops. - // - - nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; - } - - // - // Set up IoCompletion routine address. - // - - IoSetCompletionRoutine(Irp, - CdRomXACompletion, - srb, - TRUE, - TRUE, - TRUE); - - IoCallDriver(deviceExtension->PortDeviceObject, Irp); - return; - - } - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - } - - case IOCTL_DISK_GET_LENGTH_INFO: - case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { - - // - // Issue ReadCapacity to update device extension - // with information for current media. - // - - DebugPrint((3, - "CdRomStartIo: Get drive capacity\n")); - - // - // setup remaining srb and cdb parameters. - // - - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - srb->DataTransferLength = sizeof(READ_CAPACITY_DATA); - srb->CdbLength = 10; - srb->TimeOutValue = deviceExtension->TimeOutValue; - - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, sizeof(READ_CAPACITY_DATA)); - if (!dataBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); - return; - - } - - irp2->MdlAddress = IoAllocateMdl(dataBuffer, - sizeof(READ_CAPACITY_DATA), - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp2->MdlAddress) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__)); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp2->MdlAddress); - - srb->DataBuffer = dataBuffer; - cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - } - - case IOCTL_CDROM_CHECK_VERIFY: { - - // - // Since a test unit ready is about to be performed, reset the timer - // value to decrease the opportunities for it to race with this code. - // - - cdData->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME; - - // - // Set up the SRB/CDB - // - - srb->CdbLength = 6; - cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; - srb->TimeOutValue = deviceExtension->TimeOutValue * 2; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); - - DebugPrint((2, "ScsiCdRomStartIo: [%lx] Sending CHECK_VERIFY irp %lx\n", Irp, irp2)); - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - } - - case IOCTL_CDROM_GET_LAST_SESSION: - - // - // Set format to return first and last session numbers. - // - - cdb->READ_TOC.Format = GET_LAST_SESSION; - - // - // Fall through to READ TOC code. - // - - case IOCTL_CDROM_READ_TOC: { - - - if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) { - - // - // Use MSF addressing if not request for session information. - // - - cdb->READ_TOC.Msf = CDB_USE_MSF; - } - - // - // Set size of TOC structure. - // - - transferByteCount = - currentIrpStack->Parameters.Read.Length > - sizeof(CDROM_TOC) ? sizeof(CDROM_TOC): - currentIrpStack->Parameters.Read.Length; - - cdb->READ_TOC.AllocationLength[0] = (UCHAR) (transferByteCount >> 8); - cdb->READ_TOC.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF); - - cdb->READ_TOC.Control = 0; - - // - // Start at beginning of disc. - // - - cdb->READ_TOC.StartingTrack = 0; - - // - // setup remaining srb and cdb parameters. - // - - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - srb->DataTransferLength = transferByteCount; - srb->CdbLength = 10; - srb->TimeOutValue = deviceExtension->TimeOutValue; - - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount); - if (!dataBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - - } - - irp2->MdlAddress = IoAllocateMdl(dataBuffer, - transferByteCount, - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp2->MdlAddress) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp2->MdlAddress); - - srb->DataBuffer = dataBuffer; - cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC; - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - - } - - case IOCTL_CDROM_PLAY_AUDIO_MSF: { - - PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer; - - // - // Set up the SRB/CDB - // - - srb->CdbLength = 10; - cdb->PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF; - - cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM; - cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS; - cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF; - - cdb->PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM; - cdb->PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS; - cdb->PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF; - - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - - } - - case IOCTL_CDROM_READ_Q_CHANNEL: { - - PCDROM_SUB_Q_DATA_FORMAT inputBuffer = - Irp->AssociatedIrp.SystemBuffer; - - // - // Allocate buffer for subq channel information. - // - - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, - sizeof(SUB_Q_CHANNEL_DATA)); - - if (!dataBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - - } - - irp2->MdlAddress = IoAllocateMdl(dataBuffer, - transferByteCount, - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp2->MdlAddress) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp2->MdlAddress); - - srb->DataBuffer = dataBuffer; - - // - // Always logical unit 0, but only use MSF addressing - // for IOCTL_CDROM_CURRENT_POSITION - // - - if (inputBuffer->Format==IOCTL_CDROM_CURRENT_POSITION) - cdb->SUBCHANNEL.Msf = CDB_USE_MSF; - - // - // Return subchannel data - // - - cdb->SUBCHANNEL.SubQ = CDB_SUBCHANNEL_BLOCK; - - // - // Specify format of information to return - // - - cdb->SUBCHANNEL.Format = inputBuffer->Format; - - // - // Specify which track to access (only used by Track ISRC reads) - // - - if (inputBuffer->Format==IOCTL_CDROM_TRACK_ISRC) { - cdb->SUBCHANNEL.TrackNumber = inputBuffer->Track; - } - - // - // Set size of channel data -- however, this is dependent on - // what information we are requesting (which Format) - // - - switch( inputBuffer->Format ) { - - case IOCTL_CDROM_CURRENT_POSITION: - transferByteCount = sizeof(SUB_Q_CURRENT_POSITION); - break; - - case IOCTL_CDROM_MEDIA_CATALOG: - transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER); - break; - - case IOCTL_CDROM_TRACK_ISRC: - transferByteCount = sizeof(SUB_Q_TRACK_ISRC); - break; - } - - cdb->SUBCHANNEL.AllocationLength[0] = (UCHAR) (transferByteCount >> 8); - cdb->SUBCHANNEL.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF); - cdb->SUBCHANNEL.OperationCode = SCSIOP_READ_SUB_CHANNEL; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - srb->DataTransferLength = transferByteCount; - srb->CdbLength = 10; - srb->TimeOutValue = deviceExtension->TimeOutValue; - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - - } - - case IOCTL_CDROM_PAUSE_AUDIO: { - - cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME; - cdb->PAUSE_RESUME.Action = CDB_AUDIO_PAUSE; - - srb->CdbLength = 10; - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - } - - case IOCTL_CDROM_RESUME_AUDIO: { - - cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME; - cdb->PAUSE_RESUME.Action = CDB_AUDIO_RESUME; - - srb->CdbLength = 10; - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - } - - case IOCTL_CDROM_SEEK_AUDIO_MSF: { - - PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer; - ULONG logicalBlockAddress; - - logicalBlockAddress = MSF_TO_LBA(inputBuffer->M, inputBuffer->S, inputBuffer->F); - - cdb->SEEK.OperationCode = SCSIOP_SEEK; - cdb->SEEK.LogicalBlockAddress[0] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; - cdb->SEEK.LogicalBlockAddress[1] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; - cdb->SEEK.LogicalBlockAddress[2] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; - cdb->SEEK.LogicalBlockAddress[3] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; - - srb->CdbLength = 10; - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - - } - - case IOCTL_CDROM_STOP_AUDIO: { - - cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb->START_STOP.Immediate = 1; - cdb->START_STOP.Start = 0; - cdb->START_STOP.LoadEject = 0; - - srb->CdbLength = 6; - srb->TimeOutValue = deviceExtension->TimeOutValue; - - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_NO_DATA_TRANSFER); - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - } - - case IOCTL_CDROM_GET_CONTROL: { - // - // Allocate buffer for volume control information. - // - - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, - MODE_DATA_SIZE); - - if (!dataBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - - } - - irp2->MdlAddress = IoAllocateMdl(dataBuffer, - MODE_DATA_SIZE, - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp2->MdlAddress) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp2->MdlAddress); - srb->DataBuffer = dataBuffer; - - RtlZeroMemory(dataBuffer, MODE_DATA_SIZE); - - // - // Setup for either 6 or 10 byte CDBs. - // - - if (use6Byte) { - - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE; - cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE; - - // - // Disable block descriptors. - // - - cdb->MODE_SENSE.Dbd = TRUE; - - srb->CdbLength = 6; - } else { - - cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; - cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE; - cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8); - cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF); - - // - // Disable block descriptors. - // - - cdb->MODE_SENSE10.Dbd = TRUE; - - srb->CdbLength = 10; - } - - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->DataTransferLength = MODE_DATA_SIZE; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - - } - - case IOCTL_CDROM_GET_VOLUME: - case IOCTL_CDROM_SET_VOLUME: { - - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, - MODE_DATA_SIZE); - - if (!dataBuffer) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - irp2->MdlAddress = IoAllocateMdl(dataBuffer, - MODE_DATA_SIZE, - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp2->MdlAddress) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp2); - IoStartNextPacket(DeviceObject, FALSE); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp2->MdlAddress); - srb->DataBuffer = dataBuffer; - - RtlZeroMemory(dataBuffer, MODE_DATA_SIZE); - - - if (use6Byte) { - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE; - cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE; - - srb->CdbLength = 6; - - } else { - - cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10; - cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE; - cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8); - cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF); - - srb->CdbLength = 10; - } - - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->DataTransferLength = MODE_DATA_SIZE; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - - if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_SET_VOLUME) { - - // - // Setup a different completion routine as the mode sense data is needed in order - // to send the mode select. - // - - IoSetCompletionRoutine(irp2, - CdRomSetVolumeIntermediateCompletion, - srb, - TRUE, - TRUE, - TRUE); - - } - - IoCallDriver(deviceExtension->PortDeviceObject, irp2); - return; - - } - - default: - - // - // Just complete the request - CdRomClassIoctlCompletion will take - // care of it for us - // - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - ExFreePool(senseBuffer); - ExFreePool(srb); - IoFreeIrp(irp2); - return; - - } // end switch() - } - - // - // If a read or an unhandled IRP_MJ_XX, end up here. The unhandled IRP_MJ's - // are expected and composed of AutoRun Irps, at present. - // - - IoCallDriver(deviceExtension->PortDeviceObject, Irp); - return; -} - - -NTSTATUS -NTAPI -ScsiCdRomReadVerification( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This is the entry called by the I/O system for read requests. - It builds the SRB and sends it to the port driver. - -Arguments: - - DeviceObject - the system object for the device. - Irp - IRP involved. - -Return Value: - - NT Status - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; - LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; - - // - // If the cd is playing music then reject this request. - // - - if (PLAY_ACTIVE(deviceExtension)) { - Irp->IoStatus.Status = STATUS_DEVICE_BUSY; - return STATUS_DEVICE_BUSY; - } - - // - // Verify parameters of this request. - // Check that ending sector is on disc and - // that number of bytes to transfer is a multiple of - // the sector size. - // - - startingOffset.QuadPart = currentIrpStack->Parameters.Read.ByteOffset.QuadPart + - transferByteCount; - - if (!deviceExtension->DiskGeometry->Geometry.BytesPerSector) { - deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048; - } - - if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) || - (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1))) { - - DebugPrint((1,"ScsiCdRomRead: Invalid I/O parameters\n")); - DebugPrint((1, "\toffset %x:%x, Length %x:%x\n", - startingOffset.u.HighPart, - startingOffset.u.LowPart, - deviceExtension->PartitionLength.u.HighPart, - deviceExtension->PartitionLength.u.LowPart)); - DebugPrint((1, "\tbps %x\n", deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - // - // Fail request with status of invalid parameters. - // - - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - - return STATUS_INVALID_PARAMETER; - } - - - return STATUS_SUCCESS; - -} // end ScsiCdRomReadVerification() - - -NTSTATUS -NTAPI -CdRomDeviceControlCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1); - BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE; - PIO_STACK_LOCATION realIrpStack; - PIO_STACK_LOCATION realIrpNextStack; - PSCSI_REQUEST_BLOCK srb = Context; - PIRP realIrp = NULL; - NTSTATUS status; - BOOLEAN retry; - - // - // Extract the 'real' irp from the irpstack. - // - - realIrp = (PIRP) irpStack->Parameters.Others.Argument2; - realIrpStack = IoGetCurrentIrpStackLocation(realIrp); - realIrpNextStack = IoGetNextIrpStackLocation(realIrp); - - // - // Check SRB status for success of completing request. - // - - if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { - - DebugPrint((2, - "CdRomDeviceControlCompletion: Irp %lx, Srb %lx Real Irp %lx Status %lx\n", - Irp, - srb, - realIrp, - srb->SrbStatus)); - - // - // Release the queue if it is frozen. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - DebugPrint((2, "CdRomDeviceControlCompletion: Releasing Queue\n")); - ScsiClassReleaseQueue(DeviceObject); - } - - - retry = ScsiClassInterpretSenseInfo(DeviceObject, - srb, - irpStack->MajorFunction, - irpStack->Parameters.DeviceIoControl.IoControlCode, - MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), - &status); - - DebugPrint((2, "CdRomDeviceControlCompletion: IRP will %sbe retried\n", - (retry ? "" : "not "))); - - // - // Some of the Device Controls need special cases on non-Success status's. - // - - if (realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { - if ((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) || - (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) || - (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_CONTROL) || - (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_VOLUME)) { - - if (status == STATUS_DATA_OVERRUN) { - status = STATUS_SUCCESS; - retry = FALSE; - } - } - - if (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_Q_CHANNEL) { - PLAY_ACTIVE(deviceExtension) = FALSE; - } - } - - // - // If the status is verified required and the this request - // should bypass verify required then retry the request. - // - - if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && - status == STATUS_VERIFY_REQUIRED) { - - if (((realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) || - (realIrpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)) && - (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY)) { - - ExFreePool(srb->SenseInfoBuffer); - if (srb->DataBuffer) { - ExFreePool(srb->DataBuffer); - } - ExFreePool(srb); - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - - IoFreeIrp(Irp); - - // - // Update the geometry information, as the media could have changed. - // The completion routine for this will complete the real irp and start - // the next packet. - // - - status = CdRomUpdateCapacity(deviceExtension,realIrp, NULL); - DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] CdRomUpdateCapacity completed with status %lx\n", realIrp, status)); - ASSERT(status == STATUS_PENDING); - - return STATUS_MORE_PROCESSING_REQUIRED; - - } else { - - status = STATUS_IO_DEVICE_ERROR; - retry = TRUE; - } - - } - - if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) { - - - if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { - - // - // Retry request. - // - - DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp)); - - - ExFreePool(srb->SenseInfoBuffer); - if (srb->DataBuffer) { - ExFreePool(srb->DataBuffer); - } - ExFreePool(srb); - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - - IoFreeIrp(Irp); - - // - // Call StartIo directly since IoStartNextPacket hasn't been called, - // the serialisation is still intact. - // - - ScsiCdRomStartIo(DeviceObject, realIrp); - return STATUS_MORE_PROCESSING_REQUIRED; - - } - - // - // Exhausted retries. Fall through and complete the request with the appropriate status. - // - - } - } else { - - // - // Set status for successful request. - // - - status = STATUS_SUCCESS; - } - - if (NT_SUCCESS(status)) { - - switch (realIrpStack->Parameters.DeviceIoControl.IoControlCode) { - - case IOCTL_DISK_GET_LENGTH_INFO: { - - PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer; - ULONG lastSector; - ULONG bps; - ULONG lastBit; - ULONG tmp; - - // - // Swizzle bytes from Read Capacity and translate into - // the necessary geometry information in the device extension. - // - - tmp = readCapacityBuffer->BytesPerBlock; - ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; - ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; - ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; - ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; - - // - // Insure that bps is a power of 2. - // This corrects a problem with the HP 4020i CDR where it - // returns an incorrect number for bytes per sector. - // - - if (!bps) { - bps = 2048; - } else { - lastBit = (ULONG) -1; - while (bps) { - lastBit++; - bps = bps >> 1; - } - - bps = 1 << lastBit; - } - deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; - - DebugPrint((2, - "CdRomDeviceControlCompletion: Calculated bps %#x\n", - deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - // - // Copy last sector in reverse byte order. - // - - tmp = readCapacityBuffer->LogicalBlockAddress; - ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; - ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; - ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; - ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; - - // - // Calculate sector to byte shift. - // - - WHICH_BIT(bps, deviceExtension->SectorShift); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", - deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", - lastSector + 1)); - - // - // Calculate media capacity in bytes. - // - - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); - - // - // Calculate number of cylinders. - // - - deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); - - deviceExtension->PartitionLength.QuadPart = - (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - - // - // This device supports removable media. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - - } else { - - // - // Assume media type is fixed disk. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; - } - - // - // Assume sectors per track are 32; - // - - deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; - - // - // Assume tracks per cylinder (number of heads) is 64. - // - - deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; - - // - // Copy the device extension's geometry info into the user buffer. - // - - RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, - &deviceExtension->PartitionLength, - sizeof(GET_LENGTH_INFORMATION)); - - // - // update information field. - // - - realIrp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); - break; - } - - case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: { - - PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer; - ULONG lastSector; - ULONG bps; - ULONG lastBit; - ULONG tmp; - PDISK_GEOMETRY_EX geometryEx; - - // - // Swizzle bytes from Read Capacity and translate into - // the necessary geometry information in the device extension. - // - - tmp = readCapacityBuffer->BytesPerBlock; - ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; - ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; - ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; - ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; - - // - // Insure that bps is a power of 2. - // This corrects a problem with the HP 4020i CDR where it - // returns an incorrect number for bytes per sector. - // - - if (!bps) { - bps = 2048; - } else { - lastBit = (ULONG) -1; - while (bps) { - lastBit++; - bps = bps >> 1; - } - - bps = 1 << lastBit; - } - deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; - - DebugPrint((2, - "CdRomDeviceControlCompletion: Calculated bps %#x\n", - deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - // - // Copy last sector in reverse byte order. - // - - tmp = readCapacityBuffer->LogicalBlockAddress; - ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; - ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; - ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; - ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; - - // - // Calculate sector to byte shift. - // - - WHICH_BIT(bps, deviceExtension->SectorShift); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", - deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", - lastSector + 1)); - - // - // Calculate media capacity in bytes. - // - - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); - - // - // Calculate number of cylinders. - // - - deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); - - deviceExtension->PartitionLength.QuadPart = - (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - - // - // This device supports removable media. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - - } else { - - // - // Assume media type is fixed disk. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; - } - - // - // Assume sectors per track are 32; - // - - deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; - - // - // Assume tracks per cylinder (number of heads) is 64. - // - - deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; - - // - // Copy the device extension's geometry info into the user buffer. - // - - geometryEx = realIrp->AssociatedIrp.SystemBuffer; - RtlMoveMemory(&geometryEx->Geometry, - &deviceExtension->DiskGeometry->Geometry, - sizeof(DISK_GEOMETRY)); - - // - // Copy the extended information - // - - geometryEx->DiskSize = deviceExtension->PartitionLength; - - // - // update information field. - // - - realIrp->IoStatus.Information = FIELD_OFFSET(DISK_GEOMETRY_EX, Data); - break; - } - - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { - - PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer; - ULONG lastSector; - ULONG bps; - ULONG lastBit; - ULONG tmp; - - // - // Swizzle bytes from Read Capacity and translate into - // the necessary geometry information in the device extension. - // - - tmp = readCapacityBuffer->BytesPerBlock; - ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; - ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; - ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; - ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; - - // - // Insure that bps is a power of 2. - // This corrects a problem with the HP 4020i CDR where it - // returns an incorrect number for bytes per sector. - // - - if (!bps) { - bps = 2048; - } else { - lastBit = (ULONG) -1; - while (bps) { - lastBit++; - bps = bps >> 1; - } - - bps = 1 << lastBit; - } - deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps; - - DebugPrint((2, - "CdRomDeviceControlCompletion: Calculated bps %#x\n", - deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - // - // Copy last sector in reverse byte order. - // - - tmp = readCapacityBuffer->LogicalBlockAddress; - ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3; - ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2; - ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1; - ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0; - - // - // Calculate sector to byte shift. - // - - WHICH_BIT(bps, deviceExtension->SectorShift); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", - deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", - lastSector + 1)); - - // - // Calculate media capacity in bytes. - // - - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); - - // - // Calculate number of cylinders. - // - - deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); - - deviceExtension->PartitionLength.QuadPart = - (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - - // - // This device supports removable media. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - - } else { - - // - // Assume media type is fixed disk. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; - } - - // - // Assume sectors per track are 32; - // - - deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; - - // - // Assume tracks per cylinder (number of heads) is 64. - // - - deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; - - // - // Copy the device extension's geometry info into the user buffer. - // - - RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, - deviceExtension->DiskGeometry, - sizeof(DISK_GEOMETRY)); - - // - // update information field. - // - - realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY); - break; - } - - case IOCTL_CDROM_CHECK_VERIFY: - - if((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY) && - (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength)) { - - *((PULONG)realIrp->AssociatedIrp.SystemBuffer) = - physicalExtension->MediaChangeCount; - realIrp->IoStatus.Information = sizeof(ULONG); - } else { - realIrp->IoStatus.Information = 0; - } - - DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] completing CHECK_VERIFY buddy irp %lx\n", realIrp, Irp)); - break; - - case IOCTL_CDROM_GET_LAST_SESSION: - case IOCTL_CDROM_READ_TOC: { - - PCDROM_TOC toc = srb->DataBuffer; - - // - // Copy the device extension's geometry info into the user buffer. - // - - RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer, - toc, - srb->DataTransferLength); - - // - // update information field. - // - - realIrp->IoStatus.Information = srb->DataTransferLength; - break; - } - - case IOCTL_CDROM_PLAY_AUDIO_MSF: - - PLAY_ACTIVE(deviceExtension) = TRUE; - - break; - - case IOCTL_CDROM_READ_Q_CHANNEL: { - - PSUB_Q_CHANNEL_DATA userChannelData = realIrp->AssociatedIrp.SystemBuffer; -#if DBG - PCDROM_SUB_Q_DATA_FORMAT inputBuffer = realIrp->AssociatedIrp.SystemBuffer; -#endif - PSUB_Q_CHANNEL_DATA subQPtr = srb->DataBuffer; - -#if DBG - switch( inputBuffer->Format ) { - - case IOCTL_CDROM_CURRENT_POSITION: - DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus )); - DebugPrint((2,"CdRomDeviceControlCompletion: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR )); - DebugPrint((2,"CdRomDeviceControlCompletion: Control = 0x%x\n", subQPtr->CurrentPosition.Control )); - DebugPrint((2,"CdRomDeviceControlCompletion: Track = %u\n", subQPtr->CurrentPosition.TrackNumber )); - DebugPrint((2,"CdRomDeviceControlCompletion: Index = %u\n", subQPtr->CurrentPosition.IndexNumber )); - DebugPrint((2,"CdRomDeviceControlCompletion: Absolute Address = %x\n", *((PULONG)subQPtr->CurrentPosition.AbsoluteAddress) )); - DebugPrint((2,"CdRomDeviceControlCompletion: Relative Address = %x\n", *((PULONG)subQPtr->CurrentPosition.TrackRelativeAddress) )); - break; - - case IOCTL_CDROM_MEDIA_CATALOG: - DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus )); - DebugPrint((2,"CdRomDeviceControlCompletion: Mcval is %u\n", subQPtr->MediaCatalog.Mcval )); - break; - - case IOCTL_CDROM_TRACK_ISRC: - DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus )); - DebugPrint((2,"CdRomDeviceControlCompletion: Tcval is %u\n", subQPtr->TrackIsrc.Tcval )); - break; - - } -#endif - - // - // Update the play active status. - // - - if (subQPtr->CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS) { - - PLAY_ACTIVE(deviceExtension) = TRUE; - - } else { - - PLAY_ACTIVE(deviceExtension) = FALSE; - - } - - // - // Check if output buffer is large enough to contain - // the data. - // - - if (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength < - srb->DataTransferLength) { - - srb->DataTransferLength = - realIrpStack->Parameters.DeviceIoControl.OutputBufferLength; - } - - // - // Copy our buffer into users. - // - - RtlMoveMemory(userChannelData, - subQPtr, - srb->DataTransferLength); - - realIrp->IoStatus.Information = srb->DataTransferLength; - break; - } - - case IOCTL_CDROM_PAUSE_AUDIO: - - PLAY_ACTIVE(deviceExtension) = FALSE; - realIrp->IoStatus.Information = 0; - break; - - case IOCTL_CDROM_RESUME_AUDIO: - - realIrp->IoStatus.Information = 0; - break; - - case IOCTL_CDROM_SEEK_AUDIO_MSF: - - realIrp->IoStatus.Information = 0; - break; - - case IOCTL_CDROM_STOP_AUDIO: - - PLAY_ACTIVE(deviceExtension) = FALSE; - - realIrp->IoStatus.Information = 0; - break; - - case IOCTL_CDROM_GET_CONTROL: { - - PCDROM_AUDIO_CONTROL audioControl = srb->DataBuffer; - PAUDIO_OUTPUT audioOutput; - ULONG bytesTransferred; - - audioOutput = ScsiClassFindModePage((PCHAR)audioControl, - srb->DataTransferLength, - CDROM_AUDIO_CONTROL_PAGE, - use6Byte); - // - // Verify the page is as big as expected. - // - - bytesTransferred = (PCHAR) audioOutput - (PCHAR) audioControl + - sizeof(AUDIO_OUTPUT); - - if (audioOutput != NULL && - srb->DataTransferLength >= bytesTransferred) { - - audioControl->LbaFormat = audioOutput->LbaFormat; - - audioControl->LogicalBlocksPerSecond = - (audioOutput->LogicalBlocksPerSecond[0] << (UCHAR)8) | - audioOutput->LogicalBlocksPerSecond[1]; - - realIrp->IoStatus.Information = sizeof(CDROM_AUDIO_CONTROL); - - } else { - realIrp->IoStatus.Information = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - break; - } - - case IOCTL_CDROM_GET_VOLUME: { - - PAUDIO_OUTPUT audioOutput; - PVOLUME_CONTROL volumeControl = srb->DataBuffer; - ULONG i,bytesTransferred; - - audioOutput = ScsiClassFindModePage((PCHAR)volumeControl, - srb->DataTransferLength, - CDROM_AUDIO_CONTROL_PAGE, - use6Byte); - - // - // Verify the page is as big as expected. - // - - bytesTransferred = (PCHAR) audioOutput - (PCHAR) volumeControl + - sizeof(AUDIO_OUTPUT); - - if (audioOutput != NULL && - srb->DataTransferLength >= bytesTransferred) { - - for (i=0; i<4; i++) { - volumeControl->PortVolume[i] = - audioOutput->PortOutput[i].Volume; - } - - // - // Set bytes transferred in IRP. - // - - realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL); - - } else { - realIrp->IoStatus.Information = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - } - - break; - } - - case IOCTL_CDROM_SET_VOLUME: - - realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL); - break; - - default: - - ASSERT(FALSE); - realIrp->IoStatus.Information = 0; - status = STATUS_INVALID_DEVICE_REQUEST; - - } // end switch() - } - - // - // Deallocate srb and sense buffer. - // - - if (srb) { - if (srb->DataBuffer) { - ExFreePool(srb->DataBuffer); - } - if (srb->SenseInfoBuffer) { - ExFreePool(srb->SenseInfoBuffer); - } - ExFreePool(srb); - } - - if (realIrp->PendingReturned) { - IoMarkIrpPending(realIrp); - } - - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - - IoFreeIrp(Irp); - - // - // Set status in completing IRP. - // - - realIrp->IoStatus.Status = status; - - // - // Set the hard error if necessary. - // - - if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { - - // - // Store DeviceObject for filesystem, and clear - // in IoStatus.Information field. - // - - DebugPrint((1, "CdRomDeviceCompletion - Setting Hard Error on realIrp %lx\n", - realIrp)); - IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); - realIrp->IoStatus.Information = 0; - } - - IoCompleteRequest(realIrp, IO_DISK_INCREMENT); - - IoStartNextPacket(DeviceObject, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -CdRomSetVolumeIntermediateCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1); - BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE; - PIO_STACK_LOCATION realIrpStack; - PIO_STACK_LOCATION realIrpNextStack; - PSCSI_REQUEST_BLOCK srb = Context; - PIRP realIrp = NULL; - NTSTATUS status; - BOOLEAN retry; - - // - // Extract the 'real' irp from the irpstack. - // - - realIrp = (PIRP) irpStack->Parameters.Others.Argument2; - realIrpStack = IoGetCurrentIrpStackLocation(realIrp); - realIrpNextStack = IoGetNextIrpStackLocation(realIrp); - - // - // Check SRB status for success of completing request. - // - - if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { - - DebugPrint((2, - "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n", - Irp, - srb, - realIrp)); - - // - // Release the queue if it is frozen. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(DeviceObject); - } - - - retry = ScsiClassInterpretSenseInfo(DeviceObject, - srb, - irpStack->MajorFunction, - irpStack->Parameters.DeviceIoControl.IoControlCode, - MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), - &status); - - if (status == STATUS_DATA_OVERRUN) { - status = STATUS_SUCCESS; - retry = FALSE; - } - - // - // If the status is verified required and the this request - // should bypass verify required then retry the request. - // - - if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && - status == STATUS_VERIFY_REQUIRED) { - - status = STATUS_IO_DEVICE_ERROR; - retry = TRUE; - } - - if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) { - - if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { - - // - // Retry request. - // - - DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp)); - - - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb->DataBuffer); - ExFreePool(srb); - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - - IoFreeIrp(Irp); - - // - // Call StartIo directly since IoStartNextPacket hasn't been called, - // the serialisation is still intact. - // - ScsiCdRomStartIo(DeviceObject, realIrp); - return STATUS_MORE_PROCESSING_REQUIRED; - - } - - // - // Exhausted retries. Fall through and complete the request with the appropriate status. - // - - } - } else { - - // - // Set status for successful request. - // - - status = STATUS_SUCCESS; - } - - if (NT_SUCCESS(status)) { - - PAUDIO_OUTPUT audioInput = NULL; - PAUDIO_OUTPUT audioOutput; - PVOLUME_CONTROL volumeControl = realIrp->AssociatedIrp.SystemBuffer; - ULONG i,bytesTransferred,headerLength; - PVOID dataBuffer; - PCDB cdb; - - audioInput = ScsiClassFindModePage((PCHAR)srb->DataBuffer, - srb->DataTransferLength, - CDROM_AUDIO_CONTROL_PAGE, - use6Byte); - - // - // Check to make sure the mode sense data is valid before we go on - // - - if(audioInput == NULL) { - - DebugPrint((1, "Mode Sense Page %d not found\n", - CDROM_AUDIO_CONTROL_PAGE)); - - realIrp->IoStatus.Information = 0; - realIrp->IoStatus.Status = STATUS_IO_DEVICE_ERROR; - IoCompleteRequest(realIrp, IO_DISK_INCREMENT); - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb); - IoFreeMdl(Irp->MdlAddress); - IoFreeIrp(Irp); - return STATUS_MORE_PROCESSING_REQUIRED; - } - - if (use6Byte) { - headerLength = sizeof(MODE_PARAMETER_HEADER); - } else { - headerLength = sizeof(MODE_PARAMETER_HEADER10); - } - - bytesTransferred = sizeof(AUDIO_OUTPUT) + headerLength; - - // - // Allocate a new buffer for the mode select. - // - - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, bytesTransferred); - - if (!dataBuffer) { - realIrp->IoStatus.Information = 0; - realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(realIrp, IO_DISK_INCREMENT); - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb); - IoFreeMdl(Irp->MdlAddress); - IoFreeIrp(Irp); - return STATUS_MORE_PROCESSING_REQUIRED; - } - - RtlZeroMemory(dataBuffer, bytesTransferred); - - // - // Rebuild the data buffer to include the user requested values. - // - - audioOutput = (PAUDIO_OUTPUT) ((PCHAR) dataBuffer + headerLength); - - for (i=0; i<4; i++) { - audioOutput->PortOutput[i].Volume = - volumeControl->PortVolume[i]; - audioOutput->PortOutput[i].ChannelSelection = - audioInput->PortOutput[i].ChannelSelection; - } - - audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE; - audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2; - audioOutput->Immediate = MODE_SELECT_IMMEDIATE; - - // - // Free the old data buffer, mdl. - // - - ExFreePool(srb->DataBuffer); - IoFreeMdl(Irp->MdlAddress); - - // - // rebuild the srb. - // - - cdb = (PCDB)srb->Cdb; - RtlZeroMemory(cdb, CDB12GENERIC_LENGTH); - - srb->SrbStatus = srb->ScsiStatus = 0; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT); - srb->DataTransferLength = bytesTransferred; - - if (use6Byte) { - - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.ParameterListLength = (UCHAR) bytesTransferred; - cdb->MODE_SELECT.PFBit = 1; - srb->CdbLength = 6; - } else { - - cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10; - cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR) (bytesTransferred >> 8); - cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR) (bytesTransferred & 0xFF); - cdb->MODE_SELECT10.PFBit = 1; - srb->CdbLength = 10; - } - - // - // Prepare the MDL - // - - Irp->MdlAddress = IoAllocateMdl(dataBuffer, - bytesTransferred, - FALSE, - FALSE, - (PIRP) NULL); - - if (!Irp->MdlAddress) { - realIrp->IoStatus.Information = 0; - realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(realIrp, IO_DISK_INCREMENT); - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(Irp); - return STATUS_MORE_PROCESSING_REQUIRED; - - } - - MmBuildMdlForNonPagedPool(Irp->MdlAddress); - srb->DataBuffer = dataBuffer; - - irpStack = IoGetNextIrpStackLocation(Irp); - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - irpStack->Parameters.Scsi.Srb = srb; - - // - // reset the irp completion. - // - - IoSetCompletionRoutine(Irp, - CdRomDeviceControlCompletion, - srb, - TRUE, - TRUE, - TRUE); - // - // Call the port driver. - // - - IoCallDriver(deviceExtension->PortDeviceObject, Irp); - - return STATUS_MORE_PROCESSING_REQUIRED; - } - - // - // Deallocate srb and sense buffer. - // - - if (srb) { - if (srb->DataBuffer) { - ExFreePool(srb->DataBuffer); - } - if (srb->SenseInfoBuffer) { - ExFreePool(srb->SenseInfoBuffer); - } - ExFreePool(srb); - } - - if (Irp->PendingReturned) { - IoMarkIrpPending(Irp); - } - - if (realIrp->PendingReturned) { - IoMarkIrpPending(realIrp); - } - - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - - IoFreeIrp(Irp); - - // - // Set status in completing IRP. - // - - realIrp->IoStatus.Status = status; - - // - // Set the hard error if necessary. - // - - if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { - - // - // Store DeviceObject for filesystem, and clear - // in IoStatus.Information field. - // - - IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); - realIrp->IoStatus.Information = 0; - } - - IoCompleteRequest(realIrp, IO_DISK_INCREMENT); - - IoStartNextPacket(DeviceObject, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - - -NTSTATUS -NTAPI -CdRomSwitchModeCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1); - PIO_STACK_LOCATION realIrpStack; - PIO_STACK_LOCATION realIrpNextStack; - PSCSI_REQUEST_BLOCK srb = Context; - PIRP realIrp = NULL; - NTSTATUS status; - BOOLEAN retry; - - // - // Extract the 'real' irp from the irpstack. - // - - realIrp = (PIRP) irpStack->Parameters.Others.Argument2; - realIrpStack = IoGetCurrentIrpStackLocation(realIrp); - realIrpNextStack = IoGetNextIrpStackLocation(realIrp); - - // - // Check SRB status for success of completing request. - // - - if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { - - DebugPrint((2, - "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n", - Irp, - srb, - realIrp)); - - // - // Release the queue if it is frozen. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(DeviceObject); - } - - - retry = ScsiClassInterpretSenseInfo(DeviceObject, - srb, - irpStack->MajorFunction, - irpStack->Parameters.DeviceIoControl.IoControlCode, - MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1), - &status); - - // - // If the status is verified required and the this request - // should bypass verify required then retry the request. - // - - if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && - status == STATUS_VERIFY_REQUIRED) { - - status = STATUS_IO_DEVICE_ERROR; - retry = TRUE; - } - - if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) { - - if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) { - - // - // Retry request. - // - - DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp)); - - - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb->DataBuffer); - ExFreePool(srb); - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - - IoFreeIrp(Irp); - - // - // Call StartIo directly since IoStartNextPacket hasn't been called, - // the serialisation is still intact. - // - - ScsiCdRomStartIo(DeviceObject, realIrp); - return STATUS_MORE_PROCESSING_REQUIRED; - - } - - // - // Exhausted retries. Fall through and complete the request with the appropriate status. - // - } - } else { - - // - // Set status for successful request. - // - - status = STATUS_SUCCESS; - } - - if (NT_SUCCESS(status)) { - - ULONG sectorSize, startingSector, transferByteCount; - PCDB cdb; - - // - // Update device ext. to show which mode we are currently using. - // - - sectorSize = cdData->u1.BlockDescriptor.BlockLength[0] << 16; - sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[1] << 8); - sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[2]); - - cdData->RawAccess = (sectorSize == RAW_SECTOR_SIZE) ? TRUE : FALSE; - - // - // Free the old data buffer, mdl. - // - - ExFreePool(srb->DataBuffer); - IoFreeMdl(Irp->MdlAddress); - IoFreeIrp(Irp); - - // - // rebuild the srb. - // - - cdb = (PCDB)srb->Cdb; - RtlZeroMemory(cdb, CDB12GENERIC_LENGTH); - - - if (cdData->RawAccess) { - - PRAW_READ_INFO rawReadInfo = - (PRAW_READ_INFO)realIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; - - ULONG maximumTransferLength; - ULONG transferPages; - - // - // Calculate starting offset. - // - - startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift); - transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; - maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; - transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress), - transferByteCount); - - // - // Determine if request is within limits imposed by miniport. - // If the request is larger than the miniport's capabilities, split it. - // - - if (transferByteCount > maximumTransferLength || - transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) { - - realIrp->IoStatus.Information = 0; - realIrp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(realIrp, IO_DISK_INCREMENT); - - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb); - - IoStartNextPacket(DeviceObject, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; - } - - srb->OriginalRequest = realIrp; - srb->SrbFlags = deviceExtension->SrbFlags; - srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN); - srb->DataTransferLength = transferByteCount; - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->CdbLength = 10; - srb->DataBuffer = MmGetMdlVirtualAddress(realIrp->MdlAddress); - - if (rawReadInfo->TrackMode == CDDA) { - if (cdData->XAFlags & PLEXTOR_CDDA) { - - srb->CdbLength = 12; - - cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun; - cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); - cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); - cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); - cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); - - cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); - cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8); - cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0; - cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0; - - cdb->PLXTR_READ_CDDA.SubCode = 0; - cdb->PLXTR_READ_CDDA.OperationCode = 0xD8; - - } else if (cdData->XAFlags & NEC_CDDA) { - - cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); - cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); - cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); - cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); - - cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF); - cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8); - - cdb->NEC_READ_CDDA.OperationCode = 0xD4; - } - } else { - cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; - - cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8); - cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF); - - cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF); - cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF); - cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF); - cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF); - - cdb->CDB10.OperationCode = SCSIOP_READ; - } - - srb->SrbStatus = srb->ScsiStatus = 0; - - - irpStack = IoGetNextIrpStackLocation(realIrp); - irpStack->MajorFunction = IRP_MJ_SCSI; - irpStack->Parameters.Scsi.Srb = srb; - - if (!(irpStack->Parameters.Others.Argument1)) { - - // - // Only jam this in if it doesn't exist. The completion routines can - // call StartIo directly in the case of retries and resetting it will - // cause infinite loops. - // - - irpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; - } - - // - // Set up IoCompletion routine address. - // - - IoSetCompletionRoutine(realIrp, - CdRomXACompletion, - srb, - TRUE, - TRUE, - TRUE); - } else { - - ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; - ULONG transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress), - realIrpStack->Parameters.Read.Length); - // - // Back to cooked sectors. Build and send a normal read. - // The real work for setting offsets and checking for splitrequests was - // done in startio - // - - if ((realIrpStack->Parameters.Read.Length > maximumTransferLength) || - (transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages)) { - - // - // Request needs to be split. Completion of each portion of the request will - // fire off the next portion. The final request will signal Io to send a new request. - // - - ScsiClassSplitRequest(DeviceObject, realIrp, maximumTransferLength); - return STATUS_MORE_PROCESSING_REQUIRED; - - } else { - - // - // Build SRB and CDB for this IRP. - // - - ScsiClassBuildRequest(DeviceObject, realIrp); - - } - } - - // - // Call the port driver. - // - - IoCallDriver(deviceExtension->PortDeviceObject, realIrp); - - return STATUS_MORE_PROCESSING_REQUIRED; - } - - // - // Update device Extension flags to indicate that XA isn't supported. - // - - cdData->XAFlags |= XA_NOT_SUPPORTED; - - // - // Deallocate srb and sense buffer. - // - - if (srb) { - if (srb->DataBuffer) { - ExFreePool(srb->DataBuffer); - } - if (srb->SenseInfoBuffer) { - ExFreePool(srb->SenseInfoBuffer); - } - ExFreePool(srb); - } - - if (Irp->PendingReturned) { - IoMarkIrpPending(Irp); - } - - if (realIrp->PendingReturned) { - IoMarkIrpPending(realIrp); - } - - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - - IoFreeIrp(Irp); - - // - // Set status in completing IRP. - // - - realIrp->IoStatus.Status = status; - - // - // Set the hard error if necessary. - // - - if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { - - // - // Store DeviceObject for filesystem, and clear - // in IoStatus.Information field. - // - - IoSetHardErrorOrVerifyDevice(realIrp, DeviceObject); - realIrp->IoStatus.Information = 0; - } - - IoCompleteRequest(realIrp, IO_DISK_INCREMENT); - - IoStartNextPacket(DeviceObject, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -CdRomXACompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine executes when the port driver has completed a request. - It looks at the SRB status in the completing SRB and if not success - it checks for valid request sense buffer information. If valid, the - info is used to update status with more precise message of type of - error. This routine deallocates the SRB. - -Arguments: - - DeviceObject - Supplies the device object which represents the logical - unit. - - Irp - Supplies the Irp which has completed. - - Context - Supplies a pointer to the SRB. - -Return Value: - - NT status - ---*/ - -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION irpNextStack = IoGetNextIrpStackLocation(Irp); - PSCSI_REQUEST_BLOCK srb = Context; - NTSTATUS status; - BOOLEAN retry; - - // - // Check SRB status for success of completing request. - // - - if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { - - DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb)); - - // - // Release the queue if it is frozen. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(DeviceObject); - } - - retry = ScsiClassInterpretSenseInfo( - DeviceObject, - srb, - irpStack->MajorFunction, - irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, - MAXIMUM_RETRIES - ((ULONG_PTR)irpNextStack->Parameters.Others.Argument1), - &status); - - // - // If the status is verified required and the this request - // should bypass verify required then retry the request. - // - - if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && - status == STATUS_VERIFY_REQUIRED) { - - status = STATUS_IO_DEVICE_ERROR; - retry = TRUE; - } - - if (retry && (irpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)irpNextStack->Parameters.Others.Argument1-1))) { - - if (((ULONG_PTR)irpNextStack->Parameters.Others.Argument1)) { - - // - // Retry request. - // - - DebugPrint((1, "CdRomXACompletion: Retry request %lx - Calling StartIo\n", Irp)); - - - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb->DataBuffer); - ExFreePool(srb); - - // - // Call StartIo directly since IoStartNextPacket hasn't been called, - // the serialisation is still intact. - // - - ScsiCdRomStartIo(DeviceObject, Irp); - return STATUS_MORE_PROCESSING_REQUIRED; - - } - - // - // Exhausted retries. Fall through and complete the request with the appropriate status. - // - } - } else { - - // - // Set status for successful request. - // - - status = STATUS_SUCCESS; - - } // end if (SRB_STATUS(srb->SrbStatus) ... - - // - // Return SRB to nonpaged pool. - // - - ExFreePool(srb); - - // - // Set status in completing IRP. - // - - Irp->IoStatus.Status = status; - - // - // Set the hard error if necessary. - // - - if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { - - // - // Store DeviceObject for filesystem, and clear - // in IoStatus.Information field. - // - - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - Irp->IoStatus.Information = 0; - } - - // - // If pending has be returned for this irp then mark the current stack as - // pending. - // - - if (Irp->PendingReturned) { - IoMarkIrpPending(Irp); - } - - //IoCompleteRequest(Irp, IO_DISK_INCREMENT); - IoStartNextPacket(DeviceObject, FALSE); - - return status; -} - -NTSTATUS -NTAPI -CdRomDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This is the NT device control handler for CDROMs. - -Arguments: - - DeviceObject - for this CDROM - - Irp - IO Request packet - -Return Value: - - NTSTATUS - ---*/ - -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION nextStack; - PKEVENT deviceControlEvent; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1); - SCSI_REQUEST_BLOCK srb; - NTSTATUS status; - KIRQL irql; - - ULONG ioctlCode; - ULONG baseCode; - ULONG functionCode; - -RetryControl: - - // - // Zero the SRB on stack. - // - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - Irp->IoStatus.Information = 0; - - // - // if this is a class driver ioctl then we need to change the base code - // to IOCTL_CDROM_BASE so that the switch statement can handle it. - // - // WARNING - currently the scsi class ioctl function codes are between - // 0x200 & 0x300. this routine depends on that fact - // - - ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; - baseCode = ioctlCode >> 16; - functionCode = (ioctlCode & (~0xffffc003)) >> 2; - - DebugPrint((1, "CdRomDeviceControl: Ioctl Code = %#08lx, Base Code = %#lx," - " Function Code = %#lx\n", - ioctlCode, - baseCode, - functionCode - )); - - if((functionCode >= 0x200) && (functionCode <= 0x300)) { - - ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_CDROM_BASE, 0, 0, 0); - - DebugPrint((1, "CdRomDeviceControl: Class Code - new ioctl code is %#08lx\n", - ioctlCode)); - - irpStack->Parameters.DeviceIoControl.IoControlCode = ioctlCode; - - } - - switch (ioctlCode) { - - case IOCTL_CDROM_RAW_READ: { - - LARGE_INTEGER startingOffset; - ULONG transferBytes; - PRAW_READ_INFO rawReadInfo = (PRAW_READ_INFO)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; - PUCHAR userData = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; - - // - // Ensure that XA reads are supported. - // - - if (cdData->XAFlags & XA_NOT_SUPPORTED) { - - DebugPrint((1, - "CdRomDeviceControl: XA Reads not supported. Flags (%x)\n", - cdData->XAFlags)); - - status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - - // - // Check that ending sector is on disc and buffers are there and of - // correct size. - // - - if (rawReadInfo == NULL) { - - // - // Called from user space. Validate the buffers. - // - - rawReadInfo = (PRAW_READ_INFO)userData; - irpStack->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)userData; - - if (rawReadInfo == NULL) { - - DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (No extent info\n")); - - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INVALID_PARAMETER; - } - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(RAW_READ_INFO)) { - - DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Invalid info buffer\n")); - - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INVALID_PARAMETER; - } - } - - startingOffset.QuadPart = rawReadInfo->DiskOffset.QuadPart; - transferBytes = rawReadInfo->SectorCount * RAW_SECTOR_SIZE; - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < transferBytes) { - - DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Bad buffer size)\n")); - - // - // Fail request with status of invalid parameters. - // - - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INVALID_PARAMETER; - } - - if ((startingOffset.QuadPart + transferBytes) > deviceExtension->PartitionLength.QuadPart) { - - DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Request Out of Bounds)\n")); - - // - // Fail request with status of invalid parameters. - // - - status = STATUS_INVALID_PARAMETER; - break; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY: { - - DebugPrint((2,"CdRomDeviceControl: 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_DISK_GET_DRIVE_GEOMETRY_EX: - case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX: { - - DebugPrint((2,"CdRomDeviceControl: Get drive geometry ex\n")); - - if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof( DISK_GEOMETRY_EX ) ) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject,Irp, NULL,NULL); - - return STATUS_PENDING; - } - - case IOCTL_DISK_GET_LENGTH_INFO: { - - DebugPrint((2,"CdRomDeviceControl: Get length info\n")); - - if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof( GET_LENGTH_INFORMATION ) ) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject,Irp, NULL,NULL); - - return STATUS_PENDING; - } - - case IOCTL_CDROM_GET_LAST_SESSION: - case IOCTL_CDROM_READ_TOC: { - - // - // If the cd is playing music then reject this request. - // - - if (CdRomIsPlayActive(DeviceObject)) { - Irp->IoStatus.Status = STATUS_DEVICE_BUSY; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_DEVICE_BUSY; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - - case IOCTL_CDROM_PLAY_AUDIO_MSF: { - - // - // Play Audio MSF - // - - DebugPrint((2,"CdRomDeviceControl: Play audio MSF\n")); - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_PLAY_AUDIO_MSF)) { - - // - // Indicate unsuccessful status. - // - - status = STATUS_BUFFER_TOO_SMALL; - break; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - - case IOCTL_CDROM_SEEK_AUDIO_MSF: { - - - // - // Seek Audio MSF - // - - DebugPrint((2,"CdRomDeviceControl: Seek audio MSF\n")); - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_SEEK_AUDIO_MSF)) { - - // - // Indicate unsuccessful status. - // - - status = STATUS_BUFFER_TOO_SMALL; - break; - } else { - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - - } - } - - case IOCTL_CDROM_PAUSE_AUDIO: { - - // - // Pause audio - // - - DebugPrint((2, "CdRomDeviceControl: Pause audio\n")); - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - - break; - } - - case IOCTL_CDROM_RESUME_AUDIO: { - - // - // Resume audio - // - - DebugPrint((2, "CdRomDeviceControl: Resume audio\n")); - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - - case IOCTL_CDROM_READ_Q_CHANNEL: { - - if(irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(CDROM_SUB_Q_DATA_FORMAT)) { - - status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = 0; - break; - } - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - - case IOCTL_CDROM_GET_CONTROL: { - - DebugPrint((2, "CdRomDeviceControl: Get audio control\n")); - - // - // Verify user buffer is large enough for the data. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(CDROM_AUDIO_CONTROL)) { - - // - // Indicate unsuccessful status and no data transferred. - // - - status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = 0; - break; - - } else { - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - } - - case IOCTL_CDROM_GET_VOLUME: { - - DebugPrint((2, "CdRomDeviceControl: Get volume control\n")); - - // - // Verify user buffer is large enough for data. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(VOLUME_CONTROL)) { - - // - // Indicate unsuccessful status and no data transferred. - // - - status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = 0; - break; - - } else { - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - } - - case IOCTL_CDROM_SET_VOLUME: { - - DebugPrint((2, "CdRomDeviceControl: Set volume control\n")); - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(VOLUME_CONTROL)) { - - // - // Indicate unsuccessful status. - // - - status = STATUS_BUFFER_TOO_SMALL; - break; - } else { - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - return STATUS_PENDING; - } - } - - case IOCTL_CDROM_STOP_AUDIO: { - - // - // Stop play. - // - - DebugPrint((2, "CdRomDeviceControl: Stop audio\n")); - - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject,Irp, NULL,NULL); - - return STATUS_PENDING; - } - - case IOCTL_CDROM_CHECK_VERIFY: { - DebugPrint((1, "CdRomDeviceControl: [%lx] Check Verify\n", Irp)); - IoMarkIrpPending(Irp); - - if((irpStack->Parameters.DeviceIoControl.OutputBufferLength) && - (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))) { - - DebugPrint((1, "CdRomDeviceControl: Check Verify: media count " - "buffer too small\n")); - - status = STATUS_BUFFER_TOO_SMALL; - break; - } - - IoStartPacket(DeviceObject,Irp, NULL,NULL); - - return STATUS_PENDING; - } - - default: { - - // - // allocate an event and stuff it into our stack location. - // - - deviceControlEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); - - if(!deviceControlEvent) { - - status = STATUS_INSUFFICIENT_RESOURCES; - - } else { - - PIO_STACK_LOCATION currentStack; - - KeInitializeEvent(deviceControlEvent, NotificationEvent, FALSE); - - currentStack = IoGetCurrentIrpStackLocation(Irp); - nextStack = IoGetNextIrpStackLocation(Irp); - - // - // Copy the stack down a notch - // - - *nextStack = *currentStack; - - IoSetCompletionRoutine( - Irp, - CdRomClassIoctlCompletion, - deviceControlEvent, - TRUE, - TRUE, - TRUE - ); - - IoSetNextIrpStackLocation(Irp); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - // - // Override volume verifies on this stack location so that we - // will be forced through the synchronization. Once this location - // goes away we get the old value back - // - - nextStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; - - IoMarkIrpPending(Irp); - - IoStartPacket(DeviceObject, Irp, NULL, NULL); - - // - // Wait for CdRomClassIoctlCompletion to set the event. This - // ensures serialization remains intact for these unhandled device - // controls. - // - - KeWaitForSingleObject( - deviceControlEvent, - Suspended, - KernelMode, - FALSE, - NULL); - - ExFreePool(deviceControlEvent); - - DebugPrint((2, "CdRomDeviceControl: irp %#08lx synchronized\n", Irp)); - - // - // If an error occured then propagate that back up - we are no longer - // guaranteed synchronization and the upper layers will have to - // retry. - // - // If no error occured, call down to the class driver directly - // then start up the next request. - // - - if(Irp->IoStatus.Status == STATUS_SUCCESS) { - - status = ScsiClassDeviceControl(DeviceObject, Irp); - - KeRaiseIrql(DISPATCH_LEVEL, &irql); - - IoStartNextPacket(DeviceObject, FALSE); - - KeLowerIrql(irql); - } - } - - return status; - } - - } // end switch() - - if (status == STATUS_VERIFY_REQUIRED) { - - // - // If the status is verified required and this request - // should bypass verify required then retry the request. - // - - if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) { - - status = STATUS_IO_DEVICE_ERROR; - goto RetryControl; - - } - } - - if (IoIsErrorUserInduced(status)) { - - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - - } - - // - // Update IRP with completion status. - // - - Irp->IoStatus.Status = status; - - // - // Complete the request. - // - - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - DebugPrint((2, "CdRomDeviceControl: Status is %lx\n", status)); - return status; - -} // end ScsiCdRomDeviceControl() - -VOID -NTAPI -ScanForSpecial( - PDEVICE_OBJECT DeviceObject, - PINQUIRYDATA InquiryData, - PIO_SCSI_CAPABILITIES PortCapabilities - ) - -/*++ - -Routine Description: - - This function checks to see if an SCSI logical unit requires an special - initialization or error processing. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - - InquiryData - Supplies the inquiry data returned by the device of interest. - - PortCapabilities - Supplies the capabilities of the device object. - -Return Value: - - None. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1); - - // - // Look for a Hitachi CDR-1750. Read-ahead must be disabled in order - // to get this cdrom drive to work on scsi adapters that use PIO. - // - - if ((strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-1750S", strlen("HITACHI CDR-1750S")) == 0 || - strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-3650/1650S", strlen("HITACHI CDR-3650/1650S")) == 0) - && PortCapabilities->AdapterUsesPio) { - - DebugPrint((1, "CdRom ScanForSpecial: Found Hitachi CDR-1750S.\n")); - - // - // Setup an error handler to reinitialize the cd rom after it is reset. - // - - deviceExtension->ClassError = HitachProcessError; - - } else if (( RtlCompareMemory( InquiryData->VendorId,"FUJITSU", 7 ) == 7 ) && - (( RtlCompareMemory( InquiryData->ProductId,"FMCD-101", 8 ) == 8 ) || - ( RtlCompareMemory( InquiryData->ProductId,"FMCD-102", 8 ) == 8 ))) { - - // - // When Read command is issued to FMCD-101 or FMCD-102 and there is a music - // cd in it. It takes longer time than SCSI_CDROM_TIMEOUT before returning - // error status. - // - - deviceExtension->TimeOutValue = 20; - - } else if (( RtlCompareMemory( InquiryData->VendorId,"TOSHIBA", 7) == 7) && - (( RtlCompareMemory( InquiryData->ProductId,"CD-ROM XM-34", 12) == 12))) { - - SCSI_REQUEST_BLOCK srb; - PCDB cdb; - ULONG length; - PUCHAR buffer; - NTSTATUS status; - - // - // Set the density code and the error handler. - // - - length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH); - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // - // Build the MODE SENSE CDB. - // - - srb.CdbLength = 6; - cdb = (PCDB)srb.Cdb; - - // - // Set timeout value from device extension. - // - - srb.TimeOutValue = deviceExtension->TimeOutValue; - - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.PageCode = 0x1; - cdb->MODE_SENSE.AllocationLength = (UCHAR)length; - - buffer = ExAllocatePool(NonPagedPoolCacheAligned, (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH)); - if (!buffer) { - return; - } - - status = ScsiClassSendSrbSynchronous(DeviceObject, - &srb, - buffer, - length, - FALSE); - - ((PERROR_RECOVERY_DATA)buffer)->BlockDescriptor.DensityCode = 0x83; - ((PERROR_RECOVERY_DATA)buffer)->Header.ModeDataLength = 0x0; - - RtlCopyMemory(&cdData->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA)); - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // - // Build the MODE SENSE CDB. - // - - srb.CdbLength = 6; - cdb = (PCDB)srb.Cdb; - - // - // Set timeout value from device extension. - // - - srb.TimeOutValue = deviceExtension->TimeOutValue; - - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.PFBit = 1; - cdb->MODE_SELECT.ParameterListLength = (UCHAR)length; - - status = ScsiClassSendSrbSynchronous(DeviceObject, - &srb, - buffer, - length, - TRUE); - - if (!NT_SUCCESS(status)) { - DebugPrint((1, - "Cdrom.ScanForSpecial: Setting density code on Toshiba failed [%x]\n", - status)); - } - - deviceExtension->ClassError = ToshibaProcessError; - - ExFreePool(buffer); - - } - - // - // Determine special CD-DA requirements. - // - - if (RtlCompareMemory( InquiryData->VendorId,"PLEXTOR",7) == 7) { - cdData->XAFlags |= PLEXTOR_CDDA; - } else if (RtlCompareMemory ( InquiryData->VendorId,"NEC",3) == 3) { - cdData->XAFlags |= NEC_CDDA; - } - - return; -} - -VOID -NTAPI -HitachProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ) -/*++ - -Routine Description: - - This routine checks the type of error. If the error indicates CD-ROM the - CD-ROM needs to be reinitialized then a Mode sense command is sent to the - device. This command disables read-ahead for the device. - -Arguments: - - DeviceObject - Supplies a pointer to the device object. - - Srb - Supplies a pointer to the failing Srb. - - Status - Not used. - - Retry - Not used. - -Return Value: - - None. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - LARGE_INTEGER largeInt; - PUCHAR modePage; - PIO_STACK_LOCATION irpStack; - PIRP irp; - PSCSI_REQUEST_BLOCK srb; - PCOMPLETION_CONTEXT context; - PCDB cdb; - ULONG alignment; - - UNREFERENCED_PARAMETER(Status); - UNREFERENCED_PARAMETER(Retry); - - largeInt.QuadPart = (LONGLONG) 1; - - // - // Check the status. The initialization command only needs to be sent - // if UNIT ATTENTION is returned. - // - - if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { - - // - // The drive does not require reinitialization. - // - - return; - } - - // - // Found a bad HITACHI cd-rom. These devices do not work with PIO - // adapters when read-ahead is enabled. Read-ahead is disabled by - // a mode select command. The mode select page code is zero and the - // length is 6 bytes. All of the other bytes should be zero. - // - - - if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) { - - DebugPrint((1, "HitachiProcessError: Reinitializing the CD-ROM.\n")); - - // - // Send the special mode select command to disable read-ahead - // on the CD-ROM reader. - // - - alignment = DeviceObject->AlignmentRequirement ? - DeviceObject->AlignmentRequirement : 1; - - context = ExAllocatePool( - NonPagedPool, - sizeof(COMPLETION_CONTEXT) + HITACHI_MODE_DATA_SIZE + alignment - ); - - if (context == NULL) { - - // - // If there is not enough memory to fulfill this request, - // simply return. A subsequent retry will fail and another - // chance to start the unit. - // - - return; - } - - context->DeviceObject = DeviceObject; - srb = &context->Srb; - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - // - // Write length to SRB. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set up SCSI bus address. - // - - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->TimeOutValue = deviceExtension->TimeOutValue; - - // - // Set the transfer length. - // - - srb->DataTransferLength = HITACHI_MODE_DATA_SIZE; - srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // - // The data buffer must be aligned. - // - - srb->DataBuffer = (PVOID) (((ULONG_PTR) (context + 1) + (alignment - 1)) & - ~(alignment - 1)); - - - // - // Build the HITACHI read-ahead mode select CDB. - // - - srb->CdbLength = 6; - cdb = (PCDB)srb->Cdb; - cdb->MODE_SENSE.LogicalUnitNumber = srb->Lun; - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SENSE.AllocationLength = HITACHI_MODE_DATA_SIZE; - - // - // Initialize the mode sense data. - // - - modePage = srb->DataBuffer; - - RtlZeroMemory(modePage, HITACHI_MODE_DATA_SIZE); - - // - // Set the page length field to 6. - // - - modePage[5] = 6; - - // - // Build the asynchronous request to be sent to the port driver. - // - - irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE, - DeviceObject, - srb->DataBuffer, - srb->DataTransferLength, - &largeInt, - NULL); - - IoSetCompletionRoutine(irp, - (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion, - context, - TRUE, - TRUE, - TRUE); - - irpStack = IoGetNextIrpStackLocation(irp); - - irpStack->MajorFunction = IRP_MJ_SCSI; - - srb->OriginalRequest = irp; - - // - // Save SRB address in next stack for port driver. - // - - irpStack->Parameters.Scsi.Srb = (PVOID)srb; - - // - // Set up IRP Address. - // - - (VOID)IoCallDriver(deviceExtension->PortDeviceObject, irp); - - } -} - -NTSTATUS -NTAPI -ToshibaProcessErrorCompletion( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Context - ) - -/*++ - -Routine Description: - - Completion routine for the ClassError routine to handle older Toshiba units - that require setting the density code. - -Arguments: - - DeviceObject - Supplies a pointer to the device object. - - Irp - Pointer to irp created to set the density code. - - Context - Supplies a pointer to the Mode Select Srb. - - -Return Value: - - STATUS_MORE_PROCESSING_REQUIRED - ---*/ - -{ - - PSCSI_REQUEST_BLOCK srb = Context; - - // - // Check for a frozen queue. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - - // - // Unfreeze the queue getting the device object from the context. - // - - ScsiClassReleaseQueue(DeviceObject); - } - - // - // Free all of the allocations. - // - - ExFreePool(srb->DataBuffer); - ExFreePool(srb); - IoFreeMdl(Irp->MdlAddress); - IoFreeIrp(Irp); - - // - // Indicate the I/O system should stop processing the Irp completion. - // - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -VOID -NTAPI -ToshibaProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ) - -/*++ - -Routine Description: - - This routine checks the type of error. If the error indicates a unit attention, - the density code needs to be set via a Mode select command. - -Arguments: - - DeviceObject - Supplies a pointer to the device object. - - Srb - Supplies a pointer to the failing Srb. - - Status - Not used. - - Retry - Not used. - -Return Value: - - None. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1); - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - PIO_STACK_LOCATION irpStack; - PIRP irp; - PSCSI_REQUEST_BLOCK srb; - ULONG length; - PCDB cdb; - PUCHAR dataBuffer; - - - if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { - return; - } - - // - // The Toshiba's require the density code to be set on power up and media changes. - // - - if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) { - - - irp = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1), - FALSE); - - if (!irp) { - return; - } - - srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); - if (!srb) { - IoFreeIrp(irp); - return; - } - - - length = sizeof(ERROR_RECOVERY_DATA); - dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, length); - if (!dataBuffer) { - ExFreePool(srb); - IoFreeIrp(irp); - return; - } - - irp->MdlAddress = IoAllocateMdl(dataBuffer, - length, - FALSE, - FALSE, - (PIRP) NULL); - - if (!irp->MdlAddress) { - ExFreePool(srb); - ExFreePool(dataBuffer); - IoFreeIrp(irp); - return; - } - - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp->MdlAddress); - - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - - srb->DataBuffer = dataBuffer; - cdb = (PCDB)srb->Cdb; - - // - // Set up the irp. - // - - IoSetNextIrpStackLocation(irp); - irp->IoStatus.Status = STATUS_SUCCESS; - irp->IoStatus.Information = 0; - irp->Flags = 0; - irp->UserBuffer = NULL; - - // - // Save the device object and irp in a private stack location. - // - - irpStack = IoGetCurrentIrpStackLocation(irp); - irpStack->DeviceObject = deviceExtension->DeviceObject; - - // - // Construct the IRP stack for the lower level driver. - // - - irpStack = IoGetNextIrpStackLocation(irp); - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_OUT; - irpStack->Parameters.Scsi.Srb = srb; - - IoSetCompletionRoutine(irp, - ToshibaProcessErrorCompletion, - srb, - TRUE, - TRUE, - TRUE); - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->Cdb[1] |= deviceExtension->Lun << 5; - srb->SrbStatus = srb->ScsiStatus = 0; - srb->NextSrb = 0; - srb->OriginalRequest = irp; - srb->SenseInfoBufferLength = 0; - - // - // Set the transfer length. - // - - srb->DataTransferLength = length; - srb->SrbFlags = SRB_FLAGS_DATA_OUT | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - - srb->CdbLength = 6; - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.PFBit = 1; - cdb->MODE_SELECT.ParameterListLength = (UCHAR)length; - - // - // Copy the Mode page into the databuffer. - // - - RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, length); - - // - // Set the density code. - // - - ((PERROR_RECOVERY_DATA)srb->DataBuffer)->BlockDescriptor.DensityCode = 0x83; - - IoCallDriver(deviceExtension->PortDeviceObject, irp); - } -} - -BOOLEAN -NTAPI -CdRomIsPlayActive( - IN PDEVICE_OBJECT DeviceObject - ) - -/*++ - -Routine Description: - - This routine determines if the cd is currently playing music. - -Arguments: - - DeviceObject - Device object to test. - -Return Value: - - TRUE if the device is playing music. - ---*/ -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIRP irp; - IO_STATUS_BLOCK ioStatus; - KEVENT event; - NTSTATUS status; - PSUB_Q_CURRENT_POSITION currentBuffer; - - if (!PLAY_ACTIVE(deviceExtension)) { - return(FALSE); - } - - currentBuffer = ExAllocatePool(NonPagedPoolCacheAligned, sizeof(SUB_Q_CURRENT_POSITION)); - - if (currentBuffer == NULL) { - return(FALSE); - } - - ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Format = IOCTL_CDROM_CURRENT_POSITION; - ((PCDROM_SUB_Q_DATA_FORMAT) currentBuffer)->Track = 0; - - // - // Create notification event object to be used to signal the - // request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Build the synchronous request to be sent to the port driver - // to perform the request. - // - - irp = IoBuildDeviceIoControlRequest(IOCTL_CDROM_READ_Q_CHANNEL, - deviceExtension->DeviceObject, - currentBuffer, - sizeof(CDROM_SUB_Q_DATA_FORMAT), - currentBuffer, - sizeof(SUB_Q_CURRENT_POSITION), - FALSE, - &event, - &ioStatus); - - if (irp == NULL) { - ExFreePool(currentBuffer); - return FALSE; - } - - // - // Pass request to port driver and wait for request to complete. - // - - status = IoCallDriver(deviceExtension->DeviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - if (!NT_SUCCESS(status)) { - ExFreePool(currentBuffer); - return FALSE; - } - - ExFreePool(currentBuffer); - - return(PLAY_ACTIVE(deviceExtension)); - -} - -IO_COMPLETION_ROUTINE CdRomMediaChangeCompletion; -NTSTATUS -NTAPI -CdRomMediaChangeCompletion( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Context - ) - -/*++ - -Routine Description: - - This routine handles the completion of the test unit ready irps - used to determine if the media has changed. If the media has - changed, this code signals the named event to wake up other - system services that react to media change (aka AutoPlay). - -Arguments: - - DeviceObject - the object for the completion - Irp - the IRP being completed - Context - the SRB from the IRP - -Return Value: - - NTSTATUS - ---*/ - -{ - PSCSI_REQUEST_BLOCK srb = (PSCSI_REQUEST_BLOCK) Context; - PIO_STACK_LOCATION cdStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION irpNextStack = IoGetNextIrpStackLocation(Irp); - PDEVICE_EXTENSION deviceExtension; - PDEVICE_EXTENSION physicalExtension; - PSENSE_DATA senseBuffer; - PCDROM_DATA cddata; - - ASSERT(Irp); - ASSERT(cdStack); - DeviceObject = cdStack->DeviceObject; - ASSERT(DeviceObject); - - deviceExtension = DeviceObject->DeviceExtension; - physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension; - cddata = (PCDROM_DATA)(deviceExtension + 1); - - ASSERT(cddata->MediaChangeIrp == NULL); - - // - // If the sense data field is valid, look for a media change. - // otherwise this iteration of the polling will just assume nothing - // changed. - // - - DebugPrint((3, "CdRomMediaChangeHandler: Completing Autorun Irp 0x%lx " - "for device %d\n", - Irp, deviceExtension->DeviceNumber)); - - if (srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) { - if (srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) { - - // - // See if this is a media change. - // - - senseBuffer = srb->SenseInfoBuffer; - if ((senseBuffer->SenseKey & 0x0f) == SCSI_SENSE_UNIT_ATTENTION) { - if (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_MEDIUM_CHANGED) { - - DebugPrint((1, "CdRomMediaChangeCompletion: New media inserted " - "into CdRom%d [irp = 0x%lx]\n", - deviceExtension->DeviceNumber, Irp)); - - // - // Media change event occurred - signal the named event. - // - - KeSetEvent(deviceExtension->MediaChangeEvent, - (KPRIORITY) 0, - FALSE); - - deviceExtension->MediaChangeNoMedia = FALSE; - - } - - if (DeviceObject->Vpb->Flags & VPB_MOUNTED) { - - // - // Must remember the media changed and force the - // file system to verify on next access - // - - DeviceObject->Flags |= DO_VERIFY_VOLUME; - } - - physicalExtension->MediaChangeCount++; - - } else if(((senseBuffer->SenseKey & 0x0f) == SCSI_SENSE_NOT_READY)&& - (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)&& - (!deviceExtension->MediaChangeNoMedia)){ - - // - // If there was no media in the device then signal the waiters if - // we haven't already done so before. - // - - DebugPrint((1, "CdRomMediaChangeCompletion: No media in device" - "CdRom%d [irp = 0x%lx]\n", - deviceExtension->DeviceNumber, Irp)); - - KeSetEvent(deviceExtension->MediaChangeEvent, - (KPRIORITY) 0, - FALSE); - - deviceExtension->MediaChangeNoMedia = TRUE; - - } - } - } else if((srb->SrbStatus == SRB_STATUS_SUCCESS)&& - (deviceExtension->MediaChangeNoMedia)) { - // - // We didn't have any media before and now the requests are succeeding - // we probably missed the Media change somehow. Signal the change - // anyway - // - - DebugPrint((1, "CdRomMediaChangeCompletion: Request completed normally" - "for CdRom%d which was marked w/NoMedia [irp = 0x%lx]\n", - deviceExtension->DeviceNumber, Irp)); - - KeSetEvent(deviceExtension->MediaChangeEvent, - (KPRIORITY) 0, - FALSE); - - deviceExtension->MediaChangeNoMedia = FALSE; - - } - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(deviceExtension->DeviceObject); - } - - // - // Remember the IRP and SRB for use the next time. - // - - irpNextStack->Parameters.Scsi.Srb = srb; - cddata->MediaChangeIrp = Irp; - - if (deviceExtension->ClassError) { - - NTSTATUS status; - BOOLEAN retry; - - // - // Throw away the status and retry values. Just give the error routine a chance - // to do what it needs to. - // - - deviceExtension->ClassError(DeviceObject, - srb, - &status, - &retry); - } - - IoStartNextPacket(DeviceObject, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -VOID -NTAPI -CdRomTickHandler( - IN PDEVICE_OBJECT DeviceObject, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine handles the once per second timer provided by the - Io subsystem. It is only used when the cdrom device itself is - a candidate for autoplay support. It should never be called if - the cdrom device is a changer device. - -Arguments: - - DeviceObject - what to check. - Context - not used. - -Return Value: - - None. - ---*/ - -{ - PIRP irp; - PIRP heldIrpList; - PIRP nextIrp; - PLIST_ENTRY listEntry; - PCDROM_DATA cddata; - PIO_STACK_LOCATION irpStack; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - - cddata = (PCDROM_DATA)(deviceExtension + 1); - - if (cddata->MediaChange) { - if (cddata->MediaChangeIrp != NULL) { - - // - // Media change support is active and the IRP is waiting. - // Decrement the timer. - // There is no MP protection on the timer counter. This - // code is the only code that will manipulate the timer - // and only one instance of it should be running at any - // given time. - // - - cddata->MediaChangeCountDown--; - -#if DBG - cddata->MediaChangeIrpTimeInUse = 0; - cddata->MediaChangeIrpLost = FALSE; -#endif - - if (!cddata->MediaChangeCountDown) { - PSCSI_REQUEST_BLOCK srb; - PIO_STACK_LOCATION irpNextStack; - PCDB cdb; - - // - // Reset the timer. - // - - cddata->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME; - - // - // Prepare the IRP for the test unit ready - // - - irp = cddata->MediaChangeIrp; - cddata->MediaChangeIrp = NULL; - - irp->IoStatus.Status = STATUS_SUCCESS; - irp->IoStatus.Information = 0; - irp->Flags = 0; - irp->UserBuffer = NULL; - - // - // If the irp is sent down when the volume needs to be - // verified, CdRomUpdateGeometryCompletion won't complete - // it since it's not associated with a thread. Marking - // it to override the verify causes it always be sent - // to the port driver - // - - irpStack = IoGetCurrentIrpStackLocation(irp); - irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; - - irpNextStack = IoGetNextIrpStackLocation(irp); - irpNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpNextStack->Parameters.DeviceIoControl.IoControlCode = - IOCTL_SCSI_EXECUTE_NONE; - - // - // Prepare the SRB for execution. - // - - srb = irpNextStack->Parameters.Scsi.Srb; - srb->SrbStatus = srb->ScsiStatus = 0; - srb->NextSrb = 0; - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - srb->DataTransferLength = 0; - srb->OriginalRequest = irp; - - RtlZeroMemory(srb->SenseInfoBuffer, SENSE_BUFFER_SIZE); - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - - cdb = (PCDB) &srb->Cdb[0]; - cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; - cdb->CDB6GENERIC.LogicalUnitNumber = srb->Lun; - - // - // Setup the IRP to perform a test unit ready. - // - - IoSetCompletionRoutine(irp, - CdRomMediaChangeCompletion, - srb, - TRUE, - TRUE, - TRUE); - - // - // Issue the request. - // - - IoStartPacket(DeviceObject, irp, NULL, NULL); - } - } else { - -#if DBG - if(cddata->MediaChangeIrpLost == FALSE) { - if(cddata->MediaChangeIrpTimeInUse++ > - MEDIA_CHANGE_TIMEOUT_TIME) { - - DebugPrint((0, "CdRom%d: AutoPlay has lost it's irp and " - "doesn't know where to find it. Leave it " - "alone and it'll come home dragging it's " - "stack behind it.\n", - deviceExtension->DeviceNumber)); - cddata->MediaChangeIrpLost = TRUE; - } - } - -#endif - } - } - - // - // Process all generic timer IRPS in the timer list. As IRPs are pulled - // off of the TimerIrpList they must be remembered in the first loop - // if they are not sent to the lower driver. After all items have - // been pulled off the list, it is possible to put the held IRPs back - // into the TimerIrpList. - // - - heldIrpList = NULL; - if (IsListEmpty(&cddata->TimerIrpList)) { - listEntry = NULL; - } else { - listEntry = ExInterlockedRemoveHeadList(&cddata->TimerIrpList, - &cddata->TimerIrpSpinLock); - } - while (listEntry) { - - // - // There is something in the timer list. Pick up the IRP and - // see if it is ready to be submitted. - // - - irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry); - irpStack = IoGetCurrentIrpStackLocation(irp); - - if (irpStack->Parameters.Others.Argument3) { - ULONG_PTR count; - - // - // Decrement the countdown timer and put the IRP back in the list. - // - - count = (ULONG_PTR) irpStack->Parameters.Others.Argument3; - count--; - irpStack->Parameters.Others.Argument3 = (PVOID) count; - - ASSERT(irp->AssociatedIrp.MasterIrp == NULL); - if (heldIrpList) { - irp->AssociatedIrp.MasterIrp = (PVOID) heldIrpList; - } - heldIrpList = irp; - - } else { - - // - // Submit this IRP to the lower driver. This IRP does not - // need to be remembered here. It will be handled again when - // it completes. - // - - DebugPrint((1, "CdRomTickHandler: Reissuing request %lx (thread = %lx)\n", irp, irp->Tail.Overlay.Thread)); - - // - // feed this to the appropriate port driver - // - - IoCallDriver (deviceExtension->PortDeviceObject, irp); - - } - - // - // Pick up the next IRP from the timer list. - // - - listEntry = ExInterlockedRemoveHeadList(&cddata->TimerIrpList, - &cddata->TimerIrpSpinLock); - } - - // - // Move all held IRPs back onto the timer list. - // - - while (heldIrpList) { - - // - // Save the single list pointer before queueing this IRP. - // - - nextIrp = (PIRP) heldIrpList->AssociatedIrp.MasterIrp; - heldIrpList->AssociatedIrp.MasterIrp = NULL; - - // - // Return the held IRP to the timer list. - // - - ExInterlockedInsertTailList(&cddata->TimerIrpList, - &heldIrpList->Tail.Overlay.ListEntry, - &cddata->TimerIrpSpinLock); - - // - // Continue processing the held IRPs - // - - heldIrpList = nextIrp; - } -} - -BOOLEAN -NTAPI -CdRomCheckRegistryForMediaChangeValue( - IN PUNICODE_STRING RegistryPath, - IN ULONG DeviceNumber - ) - -/*++ - -Routine Description: - - The user must specify that AutoPlay is to run on the platform - by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\ - Services\Cdrom\Autorun:REG_DWORD:1. - - The user can override the global setting to enable or disable Autorun on a - specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\ - CurrentControlSet\Services\Cdrom\Device\Autorun:REG_DWORD to one or zero. - (CURRENTLY UNIMPLEMENTED) - - If this registry value does not exist or contains the value zero then - the timer to check for media change does not run. - -Arguments: - - RegistryPath - pointer to the unicode string inside - ...\CurrentControlSet\Services\Cdrom - DeviceNumber - The number of the device object - -Return Value: - - TRUE - Autorun is enabled. - FALSE - no autorun. - ---*/ - -{ -#define ITEMS_TO_QUERY 2 /* always 1 greater than what is searched */ - PRTL_QUERY_REGISTRY_TABLE parameters = NULL; - NTSTATUS status; - LONG zero = 0; - - LONG tmp = 0; - LONG doRun = 0; - - CHAR buf[32]; - ANSI_STRING paramNum; - - UNICODE_STRING paramStr; - - UNICODE_STRING paramSuffix; - UNICODE_STRING paramPath; - UNICODE_STRING paramDevPath; - - // - // First append \Parameters to the passed in registry path - // - - RtlInitUnicodeString(¶mStr, L"\\Parameters"); - - RtlInitUnicodeString(¶mPath, NULL); - - paramPath.MaximumLength = RegistryPath->Length + - paramStr.Length + - sizeof(WCHAR); - - paramPath.Buffer = ExAllocatePool(PagedPool, paramPath.MaximumLength); - - if(!paramPath.Buffer) { - - DebugPrint((1,"CdRomCheckRegAP: couldn't allocate paramPath\n")); - - return FALSE; - } - - RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength); - RtlAppendUnicodeToString(¶mPath, RegistryPath->Buffer); - RtlAppendUnicodeToString(¶mPath, paramStr.Buffer); - - DebugPrint((2, "CdRomCheckRegAP: paramPath [%d] = %ws\n", - paramPath.Length, - paramPath.Buffer)); - - // - // build a counted ANSI string that contains - // the suffix for the path - // - - sprintf(buf, "\\Device%lu", DeviceNumber); - RtlInitAnsiString(¶mNum, buf); - - // - // Next convert this into a unicode string - // - - status = RtlAnsiStringToUnicodeString(¶mSuffix, ¶mNum, TRUE); - - if(!NT_SUCCESS(status)) { - DebugPrint((1,"CdRomCheckRegAP: couldn't convert paramNum to paramSuffix\n")); - ExFreePool(paramPath.Buffer); - return FALSE; - } - - RtlInitUnicodeString(¶mDevPath, NULL); - - // - // now build the device specific path - // - - paramDevPath.MaximumLength = paramPath.Length + - paramSuffix.Length + - sizeof(WCHAR); - paramDevPath.Buffer = ExAllocatePool(PagedPool, paramDevPath.MaximumLength); - - if(!paramDevPath.Buffer) { - RtlFreeUnicodeString(¶mSuffix); - ExFreePool(paramPath.Buffer); - return FALSE; - } - - RtlZeroMemory(paramDevPath.Buffer, paramDevPath.MaximumLength); - RtlAppendUnicodeToString(¶mDevPath, paramPath.Buffer); - RtlAppendUnicodeToString(¶mDevPath, paramSuffix.Buffer); - - DebugPrint((2, "CdRomCheckRegAP: paramDevPath [%d] = %ws\n", - paramPath.Length, - paramPath.Buffer)); - - parameters = ExAllocatePool(NonPagedPool, - sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY); - - if (parameters) { - - // - // Check for the Autorun value. - // - - RtlZeroMemory(parameters, - (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); - - parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - parameters[0].Name = L"Autorun"; - parameters[0].EntryContext = &doRun; - parameters[0].DefaultType = REG_DWORD; - parameters[0].DefaultData = &zero; - parameters[0].DefaultLength = sizeof(ULONG); - - status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - RegistryPath->Buffer, - parameters, - NULL, - NULL); - - DebugPrint((2, "CdRomCheckRegAP: cdrom/Autorun flag = %d\n", doRun)); - - RtlZeroMemory(parameters, - (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY)); - - parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - parameters[0].Name = L"Autorun"; - parameters[0].EntryContext = &tmp; - parameters[0].DefaultType = REG_DWORD; - parameters[0].DefaultData = &doRun; - parameters[0].DefaultLength = sizeof(ULONG); - - status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - paramPath.Buffer, - parameters, - NULL, - NULL); - - DebugPrint((2, "CdRomCheckRegAP: cdrom/parameters/autorun flag = %d\n", tmp)); - - RtlZeroMemory(parameters, - (sizeof(RTL_QUERY_REGISTRY_TABLE) * ITEMS_TO_QUERY)); - - parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - parameters[0].Name = L"Autorun"; - parameters[0].EntryContext = &doRun; - parameters[0].DefaultType = REG_DWORD; - parameters[0].DefaultData = &tmp; - parameters[0].DefaultLength = sizeof(ULONG); - - status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - paramDevPath.Buffer, - parameters, - NULL, - NULL); - - DebugPrint((1, "CdRomCheckRegAP: cdrom/parameters/device%d/autorun flag = %d\n", DeviceNumber, doRun)); - - ExFreePool(parameters); - - } - - ExFreePool(paramPath.Buffer); - ExFreePool(paramDevPath.Buffer); - RtlFreeUnicodeString(¶mSuffix); - - DebugPrint((1, "CdRomCheckRegAP: Autoplay for device %d is %s\n", - DeviceNumber, - (doRun ? "on" : "off"))); - - if(doRun) { - return TRUE; - } - - return FALSE; -} - - -BOOLEAN -NTAPI -IsThisASanyo( - IN PDEVICE_OBJECT DeviceObject, - IN UCHAR PathId, - IN UCHAR TargetId - ) - -/*++ - -Routine Description: - - This routine is called by DriverEntry to determine whether a Sanyo 3-CD - changer device is present. - -Arguments: - - DeviceObject - Supplies the device object for the 'real' device. - - PathId - - -Return Value: - - TRUE - if an Atapi changer device is found. - ---*/ - -{ - KEVENT event; - PIRP irp; - PCHAR inquiryBuffer; - IO_STATUS_BLOCK ioStatus; - NTSTATUS status; - PSCSI_ADAPTER_BUS_INFO adapterInfo; - ULONG scsiBus; - PINQUIRYDATA inquiryData; - PSCSI_INQUIRY_DATA lunInfo; - - inquiryBuffer = ExAllocatePool(NonPagedPool, 2048); - KeInitializeEvent(&event, NotificationEvent, FALSE); - irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA, - DeviceObject, - NULL, - 0, - inquiryBuffer, - 2048, - FALSE, - &event, - &ioStatus); - if (!irp) { - return FALSE; - } - - status = IoCallDriver(DeviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - if (!NT_SUCCESS(status)) { - return FALSE; - } - - adapterInfo = (PVOID) inquiryBuffer; - - for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) { - - // - // Get the SCSI bus scan data for this bus. - // - - lunInfo = (PVOID) (inquiryBuffer + adapterInfo->BusData[scsiBus].InquiryDataOffset); - - for (;;) { - - if (lunInfo->PathId == PathId && lunInfo->TargetId == TargetId) { - - inquiryData = (PVOID) lunInfo->InquiryData; - - if (RtlCompareMemory(inquiryData->VendorId, "TORiSAN CD-ROM CDR-C", 20) == 20) { - ExFreePool(inquiryBuffer); - return TRUE; - } - - ExFreePool(inquiryBuffer); - return FALSE; - } - - if (!lunInfo->NextInquiryDataOffset) { - break; - } - - lunInfo = (PVOID) (inquiryBuffer + lunInfo->NextInquiryDataOffset); - } - } - - ExFreePool(inquiryBuffer); - return FALSE; -} - -BOOLEAN -NTAPI -IsThisAnAtapiChanger( - IN PDEVICE_OBJECT DeviceObject, - OUT PULONG DiscsPresent - ) - -/*++ - -Routine Description: - - This routine is called by DriverEntry to determine whether an Atapi - changer device is present. - -Arguments: - - DeviceObject - Supplies the device object for the 'real' device. - - DiscsPresent - Supplies a pointer to the number of Discs supported by the changer. - -Return Value: - - TRUE - if an Atapi changer device is found. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PMECHANICAL_STATUS_INFORMATION_HEADER mechanicalStatusBuffer; - NTSTATUS status; - SCSI_REQUEST_BLOCK srb; - PCDB cdb = (PCDB) &srb.Cdb[0]; - BOOLEAN retVal = FALSE; - - *DiscsPresent = 0; - - // - // Some devices can't handle 12 byte CDB's gracefully - // - - if(deviceExtension->DeviceFlags & DEV_NO_12BYTE_CDB) { - - return FALSE; - - } - - // - // Build and issue the mechanical status command. - // - - mechanicalStatusBuffer = ExAllocatePool(NonPagedPoolCacheAligned, - sizeof(MECHANICAL_STATUS_INFORMATION_HEADER)); - - if (!mechanicalStatusBuffer) { - retVal = FALSE; - } else { - - // - // Build and send the Mechanism status CDB. - // - - RtlZeroMemory(&srb, sizeof(srb)); - - srb.CdbLength = 12; - srb.TimeOutValue = 20; - - cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS; - cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER); - - status = ScsiClassSendSrbSynchronous(DeviceObject, - &srb, - mechanicalStatusBuffer, - sizeof(MECHANICAL_STATUS_INFORMATION_HEADER), - FALSE); - - - if (status == STATUS_SUCCESS) { - - // - // Indicate number of slots available - // - - *DiscsPresent = mechanicalStatusBuffer->NumberAvailableSlots; - if (*DiscsPresent > 1) { - retVal = TRUE; - } else { - - // - // If only one disc, no need for this driver. - // - - retVal = FALSE; - } - } else { - - // - // Device doesn't support this command. - // - - retVal = FALSE; - } - - ExFreePool(mechanicalStatusBuffer); - } - - return retVal; -} - -BOOLEAN -NTAPI -IsThisAMultiLunDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PDEVICE_OBJECT PortDeviceObject - ) -/*++ - -Routine Description: - - This routine is called to determine whether a multi-lun - device is present. - -Arguments: - - DeviceObject - Supplies the device object for the 'real' device. - -Return Value: - - TRUE - if a Multi-lun device is found. - ---*/ -{ - PCHAR buffer; - PSCSI_INQUIRY_DATA lunInfo; - PSCSI_ADAPTER_BUS_INFO adapterInfo; - PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; - PINQUIRYDATA inquiryData; - ULONG scsiBus; - NTSTATUS status; - UCHAR lunCount = 0; - - status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer); - - if (!NT_SUCCESS(status)) { - DebugPrint((1,"IsThisAMultiLunDevice: ScsiClassGetInquiryData failed\n")); - return FALSE; - } - - adapterInfo = (PVOID) buffer; - - // - // For each SCSI bus this adapter supports ... - // - - for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) { - - // - // Get the SCSI bus scan data for this bus. - // - - lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset); - - while (adapterInfo->BusData[scsiBus].InquiryDataOffset) { - - inquiryData = (PVOID)lunInfo->InquiryData; - - if ((lunInfo->PathId == deviceExtension->PathId) && - (lunInfo->TargetId == deviceExtension->TargetId) && - (inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE)) { - - DebugPrint((1,"IsThisAMultiLunDevice: Vendor string is %.24s\n", - inquiryData->VendorId)); - - // - // If this device has more than one cdrom-type lun then we - // won't support autoplay on it - // - - if (lunCount++) { - ExFreePool(buffer); - return TRUE; - } - } - - // - // Get next LunInfo. - // - - if (lunInfo->NextInquiryDataOffset == 0) { - break; - } - - lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset); - } - } - - ExFreePool(buffer); - return FALSE; - -} - -IO_COMPLETION_ROUTINE CdRomUpdateGeometryCompletion; -NTSTATUS -NTAPI -CdRomUpdateGeometryCompletion( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Context - ) - -/*++ - -Routine Description: - - This routine andles the completion of the test unit ready irps - used to determine if the media has changed. If the media has - changed, this code signals the named event to wake up other - system services that react to media change (aka AutoPlay). - -Arguments: - - DeviceObject - the object for the completion - Irp - the IRP being completed - Context - the SRB from the IRP - -Return Value: - - NTSTATUS - ---*/ - -{ - PSCSI_REQUEST_BLOCK srb = (PSCSI_REQUEST_BLOCK) Context; - PREAD_CAPACITY_DATA readCapacityBuffer; - PDEVICE_EXTENSION deviceExtension; - PIO_STACK_LOCATION irpStack; - NTSTATUS status; - BOOLEAN retry; - ULONG_PTR retryCount; - ULONG lastSector; - PIRP originalIrp; - PCDROM_DATA cddata; - - // - // Get items saved in the private IRP stack location. - // - - irpStack = IoGetCurrentIrpStackLocation(Irp); - retryCount = (ULONG_PTR) irpStack->Parameters.Others.Argument1; - originalIrp = (PIRP) irpStack->Parameters.Others.Argument2; - - if (!DeviceObject) { - DeviceObject = irpStack->DeviceObject; - } - ASSERT(DeviceObject); - - deviceExtension = DeviceObject->DeviceExtension; - cddata = (PCDROM_DATA) (deviceExtension + 1); - readCapacityBuffer = srb->DataBuffer; - - if ((NT_SUCCESS(Irp->IoStatus.Status)) && (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)) { - PFOUR_BYTE from; - PFOUR_BYTE to; - - DebugPrint((2, "CdRomUpdateCapacityCompletion: [%lx] successful completion of buddy-irp %lx\n", originalIrp, Irp)); - // - // Copy sector size from read capacity buffer to device extension - // in reverse byte order. - // - - from = (PFOUR_BYTE) &readCapacityBuffer->BytesPerBlock; - to = (PFOUR_BYTE) &deviceExtension->DiskGeometry->Geometry.BytesPerSector; - to->Byte0 = from->Byte3; - to->Byte1 = from->Byte2; - to->Byte2 = from->Byte1; - to->Byte3 = from->Byte0; - - // - // Using the new BytesPerBlock, calculate and store the SectorShift. - // - - WHICH_BIT(deviceExtension->DiskGeometry->Geometry.BytesPerSector, deviceExtension->SectorShift); - - // - // Copy last sector in reverse byte order. - // - - from = (PFOUR_BYTE) &readCapacityBuffer->LogicalBlockAddress; - to = (PFOUR_BYTE) &lastSector; - to->Byte0 = from->Byte3; - to->Byte1 = from->Byte2; - to->Byte2 = from->Byte1; - to->Byte3 = from->Byte0; - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); - - // - // Calculate number of cylinders. - // - - deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64)); - deviceExtension->PartitionLength.QuadPart = - (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - - // - // Assume sectors per track are 32; - // - - deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32; - - // - // Assume tracks per cylinder (number of heads) is 64. - // - - deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64; - - } else { - - DebugPrint((1, "CdRomUpdateCapacityCompletion: [%lx] unsuccessful completion of buddy-irp %lx (status - %lx)\n", originalIrp, Irp, Irp->IoStatus.Status)); - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(DeviceObject); - } - - retry = ScsiClassInterpretSenseInfo(DeviceObject, - srb, - IRP_MJ_SCSI, - 0, - retryCount, - &status); - if (retry) { - retryCount--; - if (retryCount) { - PCDB cdb; - - DebugPrint((1, "CdRomUpdateCapacityCompletion: [%lx] Retrying request %lx .. thread is %lx\n", originalIrp, Irp, Irp->Tail.Overlay.Thread)); - // - // set up a one shot timer to get this process started over - // - - irpStack->Parameters.Others.Argument1 = (PVOID) retryCount; - irpStack->Parameters.Others.Argument2 = (PVOID) originalIrp; - irpStack->Parameters.Others.Argument3 = (PVOID) 2; - - // - // Setup the IRP to be submitted again in the timer routine. - // - - irpStack = IoGetNextIrpStackLocation(Irp); - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - irpStack->Parameters.Scsi.Srb = srb; - IoSetCompletionRoutine(Irp, - CdRomUpdateGeometryCompletion, - srb, - TRUE, - TRUE, - TRUE); - - // - // Set up the SRB for read capacity. - // - - srb->CdbLength = 10; - srb->TimeOutValue = deviceExtension->TimeOutValue; - srb->SrbStatus = srb->ScsiStatus = 0; - srb->NextSrb = 0; - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - srb->DataTransferLength = sizeof(READ_CAPACITY_DATA); - - // - // Set up the CDB - // - - cdb = (PCDB) &srb->Cdb[0]; - cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; - cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; - - // - // Requests queued onto this list will be sent to the - // lower level driver during CdRomTickHandler - // - - ExInterlockedInsertHeadList(&cddata->TimerIrpList, - &Irp->Tail.Overlay.ListEntry, - &cddata->TimerIrpSpinLock); - - return STATUS_MORE_PROCESSING_REQUIRED; - } else { - - // - // This has been bounced for a number of times. Error the - // original request. - // - - originalIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY_EX)); - deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048; - deviceExtension->SectorShift = 11; - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff); - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - } - } else { - - // - // Set up reasonable defaults - // - - RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY_EX)); - deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048; - deviceExtension->SectorShift = 11; - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff); - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - } - } - - // - // Free resources held. - // - - ExFreePool(srb->SenseInfoBuffer); - ExFreePool(srb->DataBuffer); - ExFreePool(srb); - if (Irp->MdlAddress) { - IoFreeMdl(Irp->MdlAddress); - } - IoFreeIrp(Irp); - if (originalIrp->Tail.Overlay.Thread) { - - DebugPrint((2, "CdRomUpdateCapacityCompletion: [%lx] completing original IRP\n", originalIrp)); - IoCompleteRequest(originalIrp, IO_DISK_INCREMENT); - - } else { - DebugPrint((1, "CdRomUpdateCapacityCompletion: [%lx] original irp has " - "no thread\n", - originalIrp - )); - } - - // - // It's now safe to either start the next request or let the waiting ioctl - // request continue along it's merry way - // - - IoStartNextPacket(DeviceObject, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -CdRomUpdateCapacity( - IN PDEVICE_EXTENSION DeviceExtension, - IN PIRP IrpToComplete, - IN OPTIONAL PKEVENT IoctlEvent - ) - -/*++ - -Routine Description: - - This routine updates the capacity of the disk as recorded in the device extension. - It also completes the IRP given with STATUS_VERIFY_REQUIRED. This routine is called - when a media change has occurred and it is necessary to determine the capacity of the - new media prior to the next access. - -Arguments: - - DeviceExtension - the device to update - IrpToComplete - the request that needs to be completed when done. - -Return Value: - - NTSTATUS - ---*/ - -{ - PCDB cdb; - PIRP irp; - PSCSI_REQUEST_BLOCK srb; - PREAD_CAPACITY_DATA capacityBuffer; - PIO_STACK_LOCATION irpStack; - PUCHAR senseBuffer; - - irp = IoAllocateIrp((CCHAR)(DeviceExtension->DeviceObject->StackSize+1), - FALSE); - - if (irp) { - - srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); - if (srb) { - capacityBuffer = ExAllocatePool(NonPagedPoolCacheAligned, - sizeof(READ_CAPACITY_DATA)); - - if (capacityBuffer) { - - - senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); - - if (senseBuffer) { - - irp->MdlAddress = IoAllocateMdl(capacityBuffer, - sizeof(READ_CAPACITY_DATA), - FALSE, - FALSE, - (PIRP) NULL); - - if (irp->MdlAddress) { - - // - // Have all resources. Set up the IRP to send for the capacity. - // - - IoSetNextIrpStackLocation(irp); - irp->IoStatus.Status = STATUS_SUCCESS; - irp->IoStatus.Information = 0; - irp->Flags = 0; - irp->UserBuffer = NULL; - - // - // Save the device object and retry count in a private stack location. - // - - irpStack = IoGetCurrentIrpStackLocation(irp); - irpStack->DeviceObject = DeviceExtension->DeviceObject; - irpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES; - irpStack->Parameters.Others.Argument2 = (PVOID) IrpToComplete; - - // - // Construct the IRP stack for the lower level driver. - // - - irpStack = IoGetNextIrpStackLocation(irp); - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN; - irpStack->Parameters.Scsi.Srb = srb; - IoSetCompletionRoutine(irp, - CdRomUpdateGeometryCompletion, - srb, - TRUE, - TRUE, - TRUE); - // - // Prepare the MDL - // - - MmBuildMdlForNonPagedPool(irp->MdlAddress); - - - // - // Set up the SRB for read capacity. - // - - RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); - RtlZeroMemory(senseBuffer, SENSE_BUFFER_SIZE); - srb->CdbLength = 10; - srb->TimeOutValue = DeviceExtension->TimeOutValue; - srb->SrbStatus = srb->ScsiStatus = 0; - srb->NextSrb = 0; - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->PathId = DeviceExtension->PathId; - srb->TargetId = DeviceExtension->TargetId; - srb->Lun = DeviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - srb->DataBuffer = capacityBuffer; - srb->DataTransferLength = sizeof(READ_CAPACITY_DATA); - srb->OriginalRequest = irp; - srb->SenseInfoBuffer = senseBuffer; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - - // - // Set up the CDB - // - - cdb = (PCDB) &srb->Cdb[0]; - cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; - cdb->CDB10.LogicalUnitNumber = DeviceExtension->Lun; - - // - // Set the return value in the IRP that will be completed - // upon completion of the read capacity. - // - - IrpToComplete->IoStatus.Status = STATUS_IO_DEVICE_ERROR; - IoMarkIrpPending(IrpToComplete); - - IoCallDriver(DeviceExtension->PortDeviceObject, irp); - - // - // status is not checked because the completion routine for this - // IRP will always get called and it will free the resources. - // - - return STATUS_PENDING; - - } else { - ExFreePool(senseBuffer); - ExFreePool(capacityBuffer); - ExFreePool(srb); - IoFreeIrp(irp); - } - } else { - ExFreePool(capacityBuffer); - ExFreePool(srb); - IoFreeIrp(irp); - } - } else { - ExFreePool(srb); - IoFreeIrp(irp); - } - } else { - IoFreeIrp(irp); - } - } - - return STATUS_INSUFFICIENT_RESOURCES; -} - -NTSTATUS -NTAPI -CdRomClassIoctlCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine signals the event used by CdRomDeviceControl to synchronize - class driver (and lower level driver) ioctls with cdrom's startio routine. - The irp completion is short-circuited so that CdRomDeviceControl can - reissue it once it wakes up. - -Arguments: - - DeviceObject - the device object - Irp - the request we are synchronizing - Context - a PKEVENT that we need to signal - -Return Value: - - NTSTATUS - ---*/ - -{ - PKEVENT syncEvent = (PKEVENT) Context; - - DebugPrint((2, "CdRomClassIoctlCompletion: setting event for irp %#08lx\n", - Irp - )); - - KeSetEvent(syncEvent, IO_DISK_INCREMENT, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} diff --git a/drivers/storage/class/cdrom/cdrom.inf b/drivers/storage/class/cdrom/cdrom.inf deleted file mode 100644 index 046ba2e75eb..00000000000 --- a/drivers/storage/class/cdrom/cdrom.inf +++ /dev/null @@ -1,122 +0,0 @@ -; CDROM.INF - -; Installation of CDROMs - -[Version] -Signature = "$Windows NT$" -;Signature = "$ReactOS$" -LayoutFile = layout.inf -Class = CDROM -ClassGUID = {4D36E965-E325-11CE-BFC1-08002BE10318} -Provider = %ReactOS% -DriverVer = 10/19/1999,5.00.2157.1 - -[DestinationDirs] -DefaultDestDir = 12 - -[ClassInstall32.NT] -AddReg = CDROMClass.NT.AddReg - -[CDROMClass.NT.AddReg] -HKR, , , 0, %CDROMClassName% -HKR, , EnumPropPages32,0, "MmSys.Cpl,MediaPropPageProvider" -HKR, , Icon, 0, "-51" -HKR, , NoInstallClass, 0, 1 - -[Manufacturer] -%GenericMfg% = GenericMfg - -[GenericMfg] -%GenCdRom.DeviceDesc% = CdRom_Install,GenCdRom - -[CdRom_Install] -CopyFiles=CdRom_CopyFiles - -[CdRom_Install.Services] -AddService=cdrom,0x00000002,CdRom_Service_Inst - -[CdRom_Service_Inst] -ServiceType = 1 -StartType = 1 -ErrorControl = 1 -ServiceBinary = %12%\cdrom.sys -LoadOrderGroup = SCSI CDROM Class -AddReg = Autorun_AddReg - -[CdRom_CopyFiles] -cdrom.sys - -[Autorun_AddReg] -HKLM,"System\CurrentControlSet\Services\cdrom","AutoRun",0x00010003,1 - -;-------------------------------- STRINGS ------------------------------- - -[Strings] -ReactOS = "ReactOS Team" -CDROMClassName = "DVD/CD-ROM drives" -GenCdRom.DeviceDesc = "CD-ROM Drive" -GenericMfg = "(Generic DVD/CD-ROM Drives)" - -[Strings.0405] -CDROMClassName = "Jednotky DVD/CD-ROM" -GenCdRom.DeviceDesc = "Jednotka CD-ROM" -GenericMfg = "(Obecné jednotky DVD/CD-ROM)" - -[Strings.0407] -CDROMClassName = "DVD/CD-ROM Laufwerke" - -[Strings.0408] -CDROMClassName = "Οδηγοί DVD/CD-ROM" - -[Strings.0a] -ReactOS = "Equipo de ReactOS" -CDROMClassName = "Unidades de DVD/CD-ROM" -GenCdRom.DeviceDesc = "Unidad CD-ROM" -GenericMfg = "(Unidades de DVD/CD-ROM genéricas)" - -[Strings.040C] -ReactOS = "Equipe ReactOS" -CDROMClassName = "Lecteurs DVD/CD-ROM" -GenCdRom.DeviceDesc = "Lecteur CD-ROM" -GenericMfg = "(Lecteurs DVD/CD-ROM génériques)" - -[Strings.041B] -CDROMClassName = "DVD/CD-ROM mechaniky" - -[Strings.0415] -ReactOS = "Zespół ReactOS" -CDROMClassName = "Stacje dysków DVD/CD-ROM" - -[Strings.0416] -CDROMClassName = "Unidades de DVD/CD-ROM" - -[Strings.0418] -ReactOS = "Echipa ReactOS" -CDROMClassName = "Dispozitive DVD/CD-ROM" -GenCdRom.DeviceDesc = "Dispozitiv CD-ROM" -GenericMfg = "(dispozitive DVD/CD-ROM generice)" - -[Strings.0419] -ReactOS = "Команда ReactOS" -CDROMClassName = "DVD/CD-ROM приводы" -GenCdRom.DeviceDesc = "CD-ROM привод" -GenericMfg = "(Стандартные DVD/CD-ROM приводы)" - -[Strings.041f] -ReactOS = "ReactOS Takımı" -CDROMClassName = "DVD/CD-ROM Aygıtları" -GenCdRom.DeviceDesc = "CD-ROM Aygıtı" -GenericMfg = "(Umûmî DVD/CD-ROM Aygıtları)" - -[Strings.0422] -ReactOS = "Команда ReactOS" -CDROMClassName = "Приводи DVD/CD-ROM" -GenCdRom.DeviceDesc = "Привід CD-ROM" -GenericMfg = "(Стандартні приводи DVD/CD-ROM)" - -[Strings.0427] -CDROMClassName = "DVD/CD-ROM įrenginiai" - -[Strings.0804] -GenCdRom.DeviceDesc = "CD-ROM 驱动器" -GenericMfg = "(通用 DVD/CD-ROM 驱动器)" diff --git a/drivers/storage/class/cdrom/cdrom.rc b/drivers/storage/class/cdrom/cdrom.rc deleted file mode 100644 index 27e55f7de97..00000000000 --- a/drivers/storage/class/cdrom/cdrom.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "CD-ROM Class Driver" -#define REACTOS_STR_INTERNAL_NAME "cdrom" -#define REACTOS_STR_ORIGINAL_FILENAME "cdrom.sys" -#include diff --git a/drivers/storage/class/cdrom/cdrom_reg.inf b/drivers/storage/class/cdrom/cdrom_reg.inf deleted file mode 100644 index 0379b27ea36..00000000000 --- a/drivers/storage/class/cdrom/cdrom_reg.inf +++ /dev/null @@ -1,7 +0,0 @@ -; Cdrom class driver -[AddReg] -HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","ErrorControl",0x00010001,0x00000000 -HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","Group",0x00000000,"SCSI Class" -HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","ImagePath",0x00020000,"system32\drivers\cdrom.sys" -HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","Start",0x00010001,0x00000001 -HKLM,"SYSTEM\CurrentControlSet\Services\Cdrom","Type",0x00010001,0x00000001 diff --git a/drivers/storage/class/cdrom/findscsi.c b/drivers/storage/class/cdrom/findscsi.c deleted file mode 100644 index f683f62eaea..00000000000 --- a/drivers/storage/class/cdrom/findscsi.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * 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 "precomp.h" - -//#define NDEBUG -#include - -NTSTATUS -NTAPI -FindScsiAdapter ( - IN HANDLE KeyHandle, - IN UNICODE_STRING ScsiUnicodeString[], - OUT PUCHAR IntermediateController - ); - -#define INIT_OPEN_KEY(name, rootHandle, pNewHandle) \ - InitializeObjectAttributes( \ - &objectAttributes, \ - (name), \ - OBJ_CASE_INSENSITIVE, \ - (rootHandle), \ - NULL \ - ); \ - \ - status = ZwOpenKey( \ - (pNewHandle), \ - KEY_READ | KEY_ENUMERATE_SUB_KEYS, \ - &objectAttributes \ - ); - - -NTSTATUS -NTAPI -FindScsiAdapter ( - IN HANDLE KeyHandle, - IN UNICODE_STRING ScsiUnicodeString[], - OUT UCHAR *IntermediateController - ) - -/*++ - - Routine Description: - - Recursive routine to walk registry tree under KeyHandle looking for - location of ScsiAdapter and other valid controllers that the ScsiAdapter - might hang off of. When ScsiAdapter is found, FindScsiAdapter - returns an ARC name for the intervening controller(s) between the - original key and ScsiAdapter. - - Arguments: - - KeyHandle -- Handle of open registry key (somewhere under - \Registry\Machine\Hardware\Description\System) - - ScsiUnicodeString -- NT name of SCSI device being sought in the registry - - IntermediateController -- Null terminated buffer which this routine fills with - ARC name for intervening controller(s). Null is returned - if ScsiAdapter sits at the root or if it is not found. - - Return Value: - - STATUS_SUCCESS -- IntermediateController set to something like multi(1) - - STATUS_OBJECT_PATH_NOT_FOUND -- all ok, but no ScsiAdapter - (with correct scsi id & lun info) found; In this case - IntermediateController is explicitly set to null. - - Other status codes as returned by open\enumerate registry routines - may also be returned. - ---*/ - -{ -#if 0 - NTSTATUS status; - ULONG index; - ULONG resultLength; - UCHAR lowerController[64]; - BOOLEAN validControllerNumber; - UNICODE_STRING unicodeString[64]; - OBJECT_ATTRIBUTES objectAttributes; - - HANDLE controllerHandle; - HANDLE controllerNumberHandle; - ULONG controllerIndex; - ULONG controllerNumberIndex; - UCHAR keyBuffer[256]; // Allow for variable length name at end - UCHAR numberKeyBuffer[64]; - PKEY_BASIC_INFORMATION pControllerKeyInformation; - PKEY_BASIC_INFORMATION pControllerNumberKeyInformation; - - // TODO: Any PAGED_CODE stuff... - - // - // Walk enumerated subkeys, looking for valid controllers - // - - for (controllerIndex = 0; TRUE; controllerIndex++) { - - // - // Ensure pControllerKeyInformation->Name is null terminated - // - - RtlZeroMemory(keyBuffer, sizeof(keyBuffer)); - - pControllerKeyInformation = (PKEY_BASIC_INFORMATION) keyBuffer; - - status = ZwEnumerateKey( - KeyHandle, - controllerIndex, - KeyBasicInformation, - pControllerKeyInformation, - sizeof(keyBuffer), - &resultLength - ); - - if (!NT_SUCCESS(status)) { - - if (status != STATUS_NO_MORE_ENTRIES) { - DebugPrint ((2, "FindScsiAdapter: Error 0x%x enumerating key\n", status)); - return(status); - } - - break; // return NOT_FOUND - } - - DebugPrint ((3, "FindScsiAdapter: Found Adapter=%S\n", pControllerKeyInformation->Name)); - - if (!_wcsicmp(pControllerKeyInformation->Name, L"ScsiAdapter")) { - - // - // Found scsi, now verify that it's the same one we're trying to initialize. - // - - INIT_OPEN_KEY (ScsiUnicodeString, KeyHandle, &controllerHandle); - - ZwClose(controllerHandle); - - if (NT_SUCCESS(status)) { - - // - // Found correct scsi, now build ARC name of IntermediateController - // (i.e. the intervening controllers, or everything above ScsiAdapter) - // start with null, and build string one controller at a time as we - // return up the recursively called routine. - // - - IntermediateController = "\0"; - - return (STATUS_SUCCESS); - } - - // - // Found ScsiAdapter, but wrong scsi id or Lun info doesn't match, - // (ignore other ZwOpenKey errors &) keep looking... - // - - } - - else if (!_wcsicmp(pControllerKeyInformation->Name, L"MultifunctionAdapter") || - !_wcsicmp(pControllerKeyInformation->Name, L"EisaAdapter")) { - - // - // This is a valid controller that may have ScsiAdapter beneath it. - // Open controller & walk controller's subkeys: 0, 1, 2, etc.... - // - - RtlInitUnicodeString (unicodeString, pControllerKeyInformation->Name); - - INIT_OPEN_KEY (unicodeString, KeyHandle, &controllerHandle); - - if (!NT_SUCCESS(status)) { - DebugPrint ((2, "FindScsiAdapter: ZwOpenKey got status = %x \n", status)); - ZwClose (controllerHandle); - return (status); - } - - - - for (controllerNumberIndex = 0; TRUE; controllerNumberIndex++) { - - RtlZeroMemory(numberKeyBuffer, sizeof(numberKeyBuffer)); - - pControllerNumberKeyInformation = (PKEY_BASIC_INFORMATION) numberKeyBuffer; - - status = ZwEnumerateKey( - controllerHandle, - controllerNumberIndex, - KeyBasicInformation, - pControllerNumberKeyInformation, - sizeof(numberKeyBuffer), - &resultLength - ); - - if (!NT_SUCCESS(status)) { - - if (status != STATUS_NO_MORE_ENTRIES) { - DebugPrint ((2, "FindScsiAdapter: Status %x enumerating key\n", status)); - ZwClose(controllerHandle); - return (status); - } - - ZwClose(controllerHandle); - - break; // next controller - } - - DebugPrint ((3, "FindScsiAdapter: Found Adapter #=%S\n", pControllerNumberKeyInformation->Name)); - - validControllerNumber = TRUE; - - for (index = 0; index < pControllerNumberKeyInformation->NameLength / 2; index++) { - - if (!isxdigit(pControllerNumberKeyInformation->Name[index])) { - validControllerNumber = FALSE; - break; - } - - } - - if (validControllerNumber) { - - // - // Found valid controller and controller number: check children for scsi. - // - - RtlInitUnicodeString (unicodeString, pControllerNumberKeyInformation->Name); - - INIT_OPEN_KEY (unicodeString, controllerHandle, &controllerNumberHandle); - - if (!NT_SUCCESS(status)) { - DebugPrint ((2, "FindScsiAdapter: Status %x opening controller number key\n", status)); - ZwClose(controllerNumberHandle); - ZwClose(controllerHandle); - return (status); - } - - RtlZeroMemory(lowerController, sizeof(lowerController)); - - status = FindScsiAdapter( - controllerNumberHandle, - ScsiUnicodeString, - &lowerController[0] - ); - - ZwClose(controllerNumberHandle); - - if (NT_SUCCESS(status)) { - - // - // SUCCESS! - // - // Scsi adapter DOES exist under this node, - // prepend Arc Name for the current adapter to whatever was returned - // by other calls to this routine. - // - - if (!_wcsicmp(pControllerKeyInformation->Name, L"MultifunctionAdapter")) { - sprintf(IntermediateController, "multi(0)%s", lowerController); - } else { - sprintf(IntermediateController, "eisa(0)%s", lowerController); - } - - ZwClose(controllerHandle); - - return(STATUS_SUCCESS); - } - - else if (status != STATUS_OBJECT_PATH_NOT_FOUND) { - ZwClose(controllerHandle); - return(status); - } - - // - // Scsi not found under this controller number, check next one - // - - } // if validControllerNumber - - } // for controllerNumberIndex - - - - // - // ScsiAdapter not found under this controller - // - - ZwClose(controllerHandle); - - } // else if valid subkey (i.e., scsi, multi, eisa) - - } // for controllerIndex - - // - // ScsiAdapter not found under key we were called with - // - - IntermediateController = "\0"; -#endif - return (STATUS_OBJECT_PATH_NOT_FOUND); -} diff --git a/drivers/storage/class/cdrom/license.txt b/drivers/storage/class/cdrom/license.txt deleted file mode 100644 index 28ba760a5ad..00000000000 --- a/drivers/storage/class/cdrom/license.txt +++ /dev/null @@ -1,53 +0,0 @@ -Window NT Device Driver Kit -END-USER LICENSE AGREEMENT FOR MICROSOFT SOFTWARE - -IMPORTANT-READ CAREFULLY: This Microsoft End-User License Agreement ("EULA") is a legal agreement between you (either an individual or a single entity) and Microsoft Corporation for the Microsoft software product identified above, which includes computer software and associated media and printed materials, and may include "online" or electronic documentation ("SOFTWARE PRODUCT" or "SOFTWARE"). By installing, copying, or otherwise using the SOFTWARE PRODUCT, you agree to be bound by the terms of this EULA. If you do not agree to the terms of this EULA, promptly return the unused SOFTWARE PRODUCT to the place from which you obtained it for a full refund, or if you received the SOFTWARE PRODUCT as part of a subscription or other service from Microsoft, you may cancel the subscription and receive a refund of a prorata portion of the subscription price. - -SOFTWARE PRODUCT LICENSE -The SOFTWARE PRODUCT is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. The SOFTWARE PRODUCT is licensed, not sold. To develop Windows NT(tm) device drivers, you will need to utilize two computers, one for development and one for debugging. - -1. GRANT OF LICENSE. This EULA grants you the following limited, non-exclusive rights: -* SOFTWARE PRODUCT. (a) You may make two (2) copies of the SOFTWARE PRODUCT for installation and use on two (2) computers, one for use in development and one for use in debugging to design, develop, and test your software product(s), including but not limited to device driver(s) and other software products, for use with Microsoft(r) Windows(r) or Windows NT ("Software Product"). You may make an additional copy of the Windows NT Workstation operating system (licensed and provided separately) for use on a single computer used for debugging purposes. -* Microsoft Developer Network Subscriber. If you acquired the SOFTWARE PRODUCT through a subscription to the Microsoft Developer Network, and you are either an individual developer or an individual designated within a single entity, you are granted the following additional rights with respect to the SOFTWARE PRODUCT: (a) you may make and use copies of the SOFTWARE PRODUCT on up to ten (10) separate computers, provided that you are the only individual using the SOFTWARE PRODUCT on each such computer, and (b) if you are a single entity, you may designate one individual within your organization to have the right to use the SOFTWARE PRODUCT in the manner described herein. -* SAMPLE CODE. You may modify the sample source code ("Sample Code") to design, develop and test your Software Product, and reproduce and distribute the Sample Code with such modifications in source and object code forms, provided that you comply with the Distribution Requirements described below. -* DISTRIBUTION REQUIREMENTS. You may copy and redistribute the Sample Code as described above, provided that (a) you distribute the Sample Code only in conjunction with and as a part of your Software Product; (b) you do not make any statements to the effect or which imply that your Software Product is "certified" by Microsoft or that its performance is guaranteed by Microsoft; (c) you do not use Microsoft's name, logo, or trademarks to market your Software Product; (d) you include a valid copyright notice on your Software Product; and (e) you indemnify, hold harmless, and defend Microsoft from and against any claims or lawsuits, including attorneys' fees, that arise or result from the use or distribution of your Software Product. Contact Microsoft for the applicable royalties due and other licensing terms for all other uses and/or distribution of the Sample Code -* Microsoft reserves all rights not expressly granted to you. - -2. COPYRIGHT. All right, title, and copyrights in and to the SOFTWARE PRODUCT (including but not limited to any images, photographs, animations, video, audio, music, text, and "applets" incorporated into the SOFTWARE PRODUCT), and any copies of the SOFTWARE PRODUCT, are owned by Microsoft or its suppliers. The SOFTWARE PRODUCT is protected by copyright laws and international treaty provisions. Therefore, you must treat the SOFTWARE PRODUCT like any other copyrighted material except that you may either (a) make one copy of the SOFTWARE PRODUCT solely for backup or archival purposes, or (b) install the SOFTWARE PRODUCT on a single computer, provided you keep the original solely for backup or archival purposes. You may not copy the printed materials accompanying the SOFTWARE PRODUCT. - -3. PRERELEASE CODE. The SOFTWARE PRODUCT may contain PRERELEASE CODE that is not at the level of performance and compatibility of the final, generally available, product offering. These portions of the SOFTWARE PRODUCT may not operate correctly and may be substantially modified prior to first commercial shipment. Microsoft is not obligated to make this or any later version of the SOFTWARE PRODUCT commercially available. Microsoft grants you the right to distribute test versions of your Application created using the PRERELEASE CODE provided you comply with the Distribution Requirements described in Section 1 and the following additional provisions: (a) you must mark the test version of your Application "BETA" and (b) you are solely responsible for updating your customers with versions of your Application that operate satisfactorily with the final commercial release of the PRERELEASE CODE. - -4. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS. -( Limitations on Reverse Engineering, Decompilation, and Disassembly. You may not reverse-engineer, decompile, or disassemble the SOFTWARE PRODUCT, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation. -( Rental. You may not rent or lease the SOFTWARE PRODUCT. -( Software Transfer. You may permanently transfer all of your rights under this EULA, provided you retain no copies, you transfer all of the SOFTWARE PRODUCT (including all component parts, the media and printed materials, any upgrades, this EULA, and, if applicable, the Certificate of Authenticity), and the recipient agrees to the terms of this EULA. If the SOFTWARE PRODUCT is an upgrade, any transfer must include all prior versions of the SOFTWARE PRODUCT. -( Termination. Without prejudice to any other rights, Microsoft may terminate this EULA if you fail to comply with the terms and conditions of this EULA. In such event, you must destroy all copies of the SOFTWARE PRODUCT and all of its component parts. - -5. EXPORT RESTRICTIONS. You agree that neither you nor your customers intend to or will, directly or indirectly, export or transmit (a) the SOFTWARE PRODUCT or related documentation and technical data or (b) your Application as described in Section 1 of this Agreement (or any part thereof), or process, or service that is the direct product of the SOFTWARE PRODUCT to any country to which such export or transmission is restricted by any applicable U.S. regulation or statute, without the prior written consent, if required, of the Bureau of Export Administration of the U.S. Department of Commerce, or such other governmental entity as may have jurisdiction over such export or transmission. - -NO WARRANTIES. To the maximum extent permitted by applicable law, Microsoft expressly disclaims any warranty for the SOFTWARE PRODUCT. The SOFTWARE PRODUCT and any related documentation are provided "as is" without warranty of any kind, either express or implied, including, without limitation, the implied warranties of merchantability or fitness for a particular purpose. The entire risk arising out of use or performance of the SOFTWARE PRODUCT remains with you. - -LIMITATION OF LIABILITY. Microsoft's entire liability and your exclusive remedy under this EULA shall not exceed one hundred dollars (US$100.00). - -NO LIABILITY FOR CONSEQUENTIAL DAMAGES. To the maximum extent permitted by applicable law, in no event shall Microsoft or its suppliers be liable for any damages whatsoever (including, without limitation, damages for loss of business profit, business interruption, loss of business information, or any other pecuniary loss) arising out of the use or inability to use this Microsoft product, even if Microsoft has been advised of the possibility of such damages. Because some states/jurisdictions do not allow the exclusion or limitation of liability for consequential or incidental damages, the above limitation may not apply to you. - -U.S. GOVERNMENT RESTRICTED RIGHTS.The SOFTWARE and documentation are provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and (2) of the Commercial Computer Software -- Restricted Rights at 48 CFR 52.227-19, as applicable. Manufacturer is Microsoft Corporation/One Microsoft Way/Redmond, WA 98052-6399. - -If you acquired this product in the United States, this Agreement is governed by the laws of the State of Washington. If you acquired this product outside the United States, local law may apply. - -Should you have any questions concerning this Agreement, if you desire rights to use the product beyond what is listed here, or if you desire to contact Microsoft for any reason, please contact your local Microsoft subsidiary or sales office or write to: Microsoft Sales and Service, One Microsoft Way, Redmond, WA 98052-6399. - -Si vous avez acquis votre produit Microsoft au CANADA, la garantie limite suivante vous concerne : - -GARANTIE LIMITE - -EXCLUSION DE GARANTIES. Microsoft renonce entirement toute garantie pour le LOGICIEL. Le LOGICIEL et toute autre documentation s'y rapportant sont fournis comme tels sans aucune garantie quelle qu'elle soit, expresse ou implicite, y compris, mais ne se limitant pas, aux garanties implicites de la qualit marchande ou un usage particulier. Le risque total dcoulant de l'utilisation ou de la performance du LOGICIEL est entre vos mains. - -RESPONSABILIT LIMITE. La seule obligation de Microsoft et votre recours exclusif concernant ce contrat n'excderont pas cent dollars (US$100.00). - -ABSENCE DE RESPONSABILIT POUR LES DOMMAGES INDIRECTS. Microsoft ou ses fournisseurs ne pourront tre tenus responsables en aucune circonstance de tout dommage quel qu'il soit (y compris mais non de faon limitative aux dommages directs ou indirects causs par la perte de bnfices commerciaux, l'interruption des affaires, la perte d'information commerciale ou toute autre perte pcuniaire) rsultant de l'utilisation ou de l'impossibilit d'utilisation de ce produit, et ce, mme si la socit Microsoft a t avise de l'ventualit de tels dommages. Certains tats/juridictions ne permettent pas l'exclusion ou la limitation de responsabilit relative aux dommages indirects ou conscutifs, et la limitation ci-dessus peut ne pas s'appliquer votre gard. - -La prsente Convention est rgie par les lois de la province d'Ontario, Canada. Chacune des parties la prsente reconnat irrvocablement la comptence des tribunaux de la province d'Ontario et consent instituer tout litige qui pourrait dcouler de la prsente auprs des tribunaux situs dans le district judiciaire de York, province d'Ontario. - -Au cas o vous auriez des questions concernant cette licence ou que vous dsiriez vous mettre en rapport avec Microsoft pour quelque raison que ce soit, veuillez contacter la succursale Microsoft desservant votre pays, dont l'adresse est fournie dans ce produit, ou crire : Microsoft Customer Sales and Service, One Microsoft Way, Redmond, Washington 98052-6399. - diff --git a/drivers/storage/class/cdrom/precomp.h b/drivers/storage/class/cdrom/precomp.h deleted file mode 100644 index 586ddfa59fc..00000000000 --- a/drivers/storage/class/cdrom/precomp.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _CDROM_PCH_ -#define _CDROM_PCH_ - -#include -#include -#include -#include - -#endif /* _CDROM_PCH_ */ diff --git a/drivers/storage/class/class2/CMakeLists.txt b/drivers/storage/class/class2/CMakeLists.txt deleted file mode 100644 index c1a33a04644..00000000000 --- a/drivers/storage/class/class2/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ - -include_directories(..) -spec2def(class2.sys class2.spec ADD_IMPORTLIB) - -list(APPEND SOURCE - class2.c - class2.rc - ${CMAKE_CURRENT_BINARY_DIR}/class2.def) - -add_library(class2 MODULE ${SOURCE}) -set_module_type(class2 kernelmodedriver) -add_importlibs(class2 scsiport ntoskrnl hal) -add_cd_file(TARGET class2 DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/storage/class/class2/class2.c b/drivers/storage/class/class2/class2.c deleted file mode 100644 index c3265c38ec8..00000000000 --- a/drivers/storage/class/class2/class2.c +++ /dev/null @@ -1,5007 +0,0 @@ -/* - * PROJECT: ReactOS Storage Stack - * LICENSE: DDK - see license.txt in the root dir - * FILE: drivers/storage/class2/class2.c - * PURPOSE: SCSI Class driver routines - * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK - */ - -#include -#include -#include -#include -#include -#include - -//#define NDEBUG -#include - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, ScsiClassGetInquiryData) -#pragma alloc_text(PAGE, ScsiClassInitialize) -#pragma alloc_text(PAGE, ScsiClassGetCapabilities) -#pragma alloc_text(PAGE, ScsiClassSendSrbSynchronous) -#pragma alloc_text(PAGE, ScsiClassClaimDevice) -#pragma alloc_text(PAGE, ScsiClassSendSrbAsynchronous) -#endif - - -#define INQUIRY_DATA_SIZE 2048 -#define START_UNIT_TIMEOUT 30 - -/* Disk layout used by Windows NT4 and earlier versions. */ -//#define DEFAULT_SECTORS_PER_TRACK 32 -//#define DEFAULT_TRACKS_PER_CYLINDER 64 - -/* Disk layout used by Windows 2000 and later versions. */ -#define DEFAULT_SECTORS_PER_TRACK 63 -#define DEFAULT_TRACKS_PER_CYLINDER 255 - -NTSTATUS -NTAPI -ScsiClassCreateClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiClassReadWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiClassDeviceControlDispatch( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiClassDeviceControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiClassInternalIoControl ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiClassShutdownFlush( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ); - -// -// Class internal routines -// - - -VOID -NTAPI -RetryRequest( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PSCSI_REQUEST_BLOCK Srb, - BOOLEAN Associated - ); - -VOID -NTAPI -StartUnit( - IN PDEVICE_OBJECT DeviceObject - ); - -NTSTATUS -NTAPI -ClassIoCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -NTSTATUS -NTAPI -ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context); - - -NTSTATUS -NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) -{ - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -ScsiClassPlugPlay( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - - if (IrpSp->MinorFunction == IRP_MN_START_DEVICE) - { - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - else - { - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_SUPPORTED; - } -} - - - -ULONG -NTAPI -ScsiClassInitialize( - IN PVOID Argument1, - IN PVOID Argument2, - IN PCLASS_INIT_DATA InitializationData - ) - -/*++ - -Routine Description: - - This routine is called by a class driver during its - DriverEntry routine to initialize the driver. - -Arguments: - - Argument1 - Driver Object. - Argument2 - Registry Path. - InitializationData - Device-specific driver's initialization data. - -Return Value: - - A valid return code for a DriverEntry routine. - ---*/ - -{ - - - PDRIVER_OBJECT DriverObject = Argument1; - ULONG portNumber = 0; - PDEVICE_OBJECT portDeviceObject; - NTSTATUS status; - STRING deviceNameString; - UNICODE_STRING unicodeDeviceName; - PFILE_OBJECT fileObject; - CCHAR deviceNameBuffer[256]; - BOOLEAN deviceFound = FALSE; - - DebugPrint((3,"\n\nSCSI Class Driver\n")); - - // - // Validate the length of this structure. This is effectively a - // version check. - // - - if (InitializationData->InitializationDataSize > sizeof(CLASS_INIT_DATA)) { - - DebugPrint((0,"ScsiClassInitialize: Class driver wrong version\n")); - return (ULONG) STATUS_REVISION_MISMATCH; - } - - // - // Check that each required entry is not NULL. Note that Shutdown, Flush and Error - // are not required entry points. - // - - if ((!InitializationData->ClassFindDevices) || - (!InitializationData->ClassDeviceControl) || - (!((InitializationData->ClassReadWriteVerification) || - (InitializationData->ClassStartIo)))) { - - DebugPrint((0, - "ScsiClassInitialize: Class device-specific driver missing required entry\n")); - - return (ULONG) STATUS_REVISION_MISMATCH; - } - - // - // Update driver object with entry points. - // - - DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose; - DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite; - DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite; - DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiClassPlugPlay; - DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassInternalIoControl; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceControlDispatch; - DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush; - DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush; - - if (InitializationData->ClassStartIo) { - DriverObject->DriverStartIo = InitializationData->ClassStartIo; - } - - // - // Open port driver controller device objects by name. - // - - do { - - sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", portNumber); - - DebugPrint((2, "ScsiClassInitialize: Open Port %s\n", deviceNameBuffer)); - - RtlInitString(&deviceNameString, deviceNameBuffer); - - status = RtlAnsiStringToUnicodeString(&unicodeDeviceName, - &deviceNameString, - TRUE); - - if (!NT_SUCCESS(status)){ - break; - } - - status = IoGetDeviceObjectPointer(&unicodeDeviceName, - FILE_READ_ATTRIBUTES, - &fileObject, - &portDeviceObject); - - if (NT_SUCCESS(status)) { - - // - // Call the device-specific driver's FindDevice routine. - // - - if (InitializationData->ClassFindDevices(DriverObject, Argument2, InitializationData, - portDeviceObject, portNumber)) { - - deviceFound = TRUE; - } - } - - // - // Check next SCSI adapter. - // - - portNumber++; - - } while(NT_SUCCESS(status)); - - return deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE; -} - - -NTSTATUS -NTAPI -ScsiClassCreateClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - SCSI class driver create and close routine. This is called by the I/O system - when the device is opened or closed. - -Arguments: - - DriverObject - Pointer to driver object created by system. - - Irp - IRP involved. - -Return Value: - - Device-specific drivers return value or STATUS_SUCCESS. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Invoke the device-specific routine, if one exists. Otherwise complete - // with SUCCESS - // - - if (deviceExtension->ClassCreateClose) { - - return deviceExtension->ClassCreateClose(DeviceObject, Irp); - - } else { - Irp->IoStatus.Status = STATUS_SUCCESS; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return(STATUS_SUCCESS); - } -} - - - -NTSTATUS -NTAPI -ScsiClassReadWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This is the system entry point for read and write requests. The device-specific handler is invoked - to perform any validation necessary. The number of bytes in the request are - checked against the maximum byte counts that the adapter supports and requests are broken up into - smaller sizes if necessary. - -Arguments: - - DeviceObject - Irp - IO request - -Return Value: - - NT Status - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - ULONG transferPages; - ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; - ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength; - NTSTATUS status; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - if (DeviceObject->Flags & DO_VERIFY_VOLUME && - !(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { - - // - // if DO_VERIFY_VOLUME bit is set - // in device object flags, fail request. - // - - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - - Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, 0); - return STATUS_VERIFY_REQUIRED; - } - - // - // Invoke the device specific routine to do whatever it needs to verify - // this request. - // - - ASSERT(deviceExtension->ClassReadWriteVerification); - - status = deviceExtension->ClassReadWriteVerification(DeviceObject,Irp); - - if (!NT_SUCCESS(status)) { - - // - // It is up to the device specific driver to set the Irp status. - // - - IoCompleteRequest (Irp, IO_NO_INCREMENT); - return status; - } else if (status == STATUS_PENDING) { - - IoMarkIrpPending(Irp); - return STATUS_PENDING; - } - - // - // Check for a zero length IO, as several macros will turn this into - // seemingly a 0xffffffff length request. - // - - if (transferByteCount == 0) { - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - - } - - if (deviceExtension->ClassStartIo) { - - IoMarkIrpPending(Irp); - - IoStartPacket(DeviceObject, - Irp, - NULL, - NULL); - - return STATUS_PENDING; - } - - // - // Mark IRP with status pending. - // - - IoMarkIrpPending(Irp); - - // - // Add partition byte offset to make starting byte relative to - // beginning of disk. In addition, add in skew for DM Driver, if any. - // - - currentIrpStack->Parameters.Read.ByteOffset.QuadPart += (deviceExtension->StartingOffset.QuadPart + - deviceExtension->DMByteSkew); - - // - // Calculate number of pages in this transfer. - // - - transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), - currentIrpStack->Parameters.Read.Length); - - // - // Check if request length is greater than the maximum number of - // bytes that the hardware can transfer. - // - - if (currentIrpStack->Parameters.Read.Length > maximumTransferLength || - transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) { - - DebugPrint((2,"ScsiClassReadWrite: Request greater than maximum\n")); - DebugPrint((2,"ScsiClassReadWrite: Maximum is %lx\n", - maximumTransferLength)); - DebugPrint((2,"ScsiClassReadWrite: Byte count is %lx\n", - currentIrpStack->Parameters.Read.Length)); - - transferPages = - deviceExtension->PortCapabilities->MaximumPhysicalPages - 1; - - if (maximumTransferLength > transferPages << PAGE_SHIFT ) { - maximumTransferLength = transferPages << PAGE_SHIFT; - } - - // - // Check that maximum transfer size is not zero. - // - - if (maximumTransferLength == 0) { - maximumTransferLength = PAGE_SIZE; - } - - // - // Mark IRP with status pending. - // - - IoMarkIrpPending(Irp); - - // - // Request greater than port driver maximum. - // Break up into smaller routines. - // - - ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength); - - - return STATUS_PENDING; - } - - // - // Build SRB and CDB for this IRP. - // - - ScsiClassBuildRequest(DeviceObject, Irp); - - // - // Return the results of the call to the port driver. - // - - return IoCallDriver(deviceExtension->PortDeviceObject, Irp); - -} // end ScsiClassReadWrite() - - -NTSTATUS -NTAPI -ScsiClassGetCapabilities( - IN PDEVICE_OBJECT PortDeviceObject, - OUT PIO_SCSI_CAPABILITIES *PortCapabilities - ) - -/*++ - -Routine Description: - - This routine builds and sends a request to the port driver to - get a pointer to a structure that describes the adapter's - capabilities/limitations. This routine is synchronous. - -Arguments: - - PortDeviceObject - Port driver device object representing the HBA. - - PortCapabilities - Location to store pointer to capabilities structure. - -Return Value: - - Nt status indicating the results of the operation. - -Notes: - - This routine should only be called at initialization time. - ---*/ - -{ - PIRP irp; - IO_STATUS_BLOCK ioStatus; - KEVENT event; - NTSTATUS status; - - PAGED_CODE(); - - // - // Create notification event object to be used to signal the - // request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Build the synchronous request to be sent to the port driver - // to perform the request. - // - - irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES, - PortDeviceObject, - NULL, - 0, - PortCapabilities, - sizeof(PVOID), - FALSE, - &event, - &ioStatus); - - if (irp == NULL) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Pass request to port driver and wait for request to complete. - // - - status = IoCallDriver(PortDeviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - return(ioStatus.Status); - } - - return status; - -} // end ScsiClassGetCapabilities() - - -NTSTATUS -NTAPI -ScsiClassGetInquiryData( - IN PDEVICE_OBJECT PortDeviceObject, - OUT PSCSI_ADAPTER_BUS_INFO *ConfigInfo - ) - -/*++ - -Routine Description: - - This routine sends a request to a port driver to return - configuration information. Space for the information is - allocated by this routine. The caller is responsible for - freeing the configuration information. This routine is - synchronous. - -Arguments: - - PortDeviceObject - Port driver device object representing the HBA. - - ConfigInfo - Returns a pointer to the configuration information. - -Return Value: - - Nt status indicating the results of the operation. - -Notes: - - This routine should be called only at initialization time. - ---*/ - -{ - PIRP irp; - IO_STATUS_BLOCK ioStatus; - KEVENT event; - NTSTATUS status; - PSCSI_ADAPTER_BUS_INFO buffer; - - PAGED_CODE(); - - buffer = ExAllocatePool(PagedPool, INQUIRY_DATA_SIZE); - *ConfigInfo = buffer; - - if (buffer == NULL) { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - // - // Create notification event object to be used to signal the inquiry - // request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Build the synchronous request to be sent to the port driver - // to perform the inquiries. - // - - irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA, - PortDeviceObject, - NULL, - 0, - buffer, - INQUIRY_DATA_SIZE, - FALSE, - &event, - &ioStatus); - - if (irp == NULL) { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - // - // Pass request to port driver and wait for request to complete. - // - - status = IoCallDriver(PortDeviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - if (!NT_SUCCESS(status)) { - - // - // Free the buffer on an error. - // - - ExFreePool(buffer); - *ConfigInfo = NULL; - - } - - return status; - -} // end ScsiClassGetInquiryData() - - -NTSTATUS -NTAPI -ScsiClassReadDriveCapacity( - IN PDEVICE_OBJECT DeviceObject - ) - -/*++ - -Routine Description: - - This routine sends a READ CAPACITY to the requested device, updates - the geometry information in the device object and returns - when it is complete. This routine is synchronous. - -Arguments: - - DeviceObject - Supplies a pointer to the device object that represents - the device whose capacity is to be read. - -Return Value: - - Status is returned. - ---*/ -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - ULONG retries = 1; - ULONG lastSector; - PCDB cdb; - PREAD_CAPACITY_DATA readCapacityBuffer; - SCSI_REQUEST_BLOCK srb; - NTSTATUS status; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Allocate read capacity buffer from nonpaged pool. - // - - readCapacityBuffer = ExAllocatePool(NonPagedPoolCacheAligned, - sizeof(READ_CAPACITY_DATA)); - - if (!readCapacityBuffer) { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // - // Build the read capacity CDB. - // - - srb.CdbLength = 10; - cdb = (PCDB)srb.Cdb; - - // - // Set timeout value from device extension. - // - - srb.TimeOutValue = deviceExtension->TimeOutValue; - - cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; - -Retry: - - status = ScsiClassSendSrbSynchronous(DeviceObject, - &srb, - readCapacityBuffer, - sizeof(READ_CAPACITY_DATA), - FALSE); - - if (NT_SUCCESS(status)) { - - // - // Copy sector size from read capacity buffer to device extension - // in reverse byte order. - // - - ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte0 = - ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte3; - - ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte1 = - ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte2; - - ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte2 = - ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte1; - - ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte3 = - ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte0; - - // - // Copy last sector in reverse byte order. - // - - ((PFOUR_BYTE)&lastSector)->Byte0 = - ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte3; - - ((PFOUR_BYTE)&lastSector)->Byte1 = - ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte2; - - ((PFOUR_BYTE)&lastSector)->Byte2 = - ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte1; - - ((PFOUR_BYTE)&lastSector)->Byte3 = - ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte0; - - // - // Calculate sector to byte shift. - // - - WHICH_BIT(deviceExtension->DiskGeometry->Geometry.BytesPerSector, deviceExtension->SectorShift); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n", - deviceExtension->DiskGeometry->Geometry.BytesPerSector)); - - DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n", - lastSector + 1)); - - // - // Calculate number of cylinders. - // - - deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(DEFAULT_SECTORS_PER_TRACK * DEFAULT_TRACKS_PER_CYLINDER)); - - // - // Calculate media capacity in bytes. - // - - deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1); - deviceExtension->PartitionLength.QuadPart = - (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift); - deviceExtension->DiskGeometry->DiskSize.QuadPart = deviceExtension->PartitionLength.QuadPart; - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - - // - // This device supports removable media. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - - } else { - - // - // Assume media type is fixed disk. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; - } - - // - // Assume sectors per track are DEFAULT_SECTORS_PER_TRACK; - // - - deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = DEFAULT_SECTORS_PER_TRACK; - - // - // Assume tracks per cylinder (number of heads) is DEFAULT_TRACKS_PER_CYLINDER. - // - - deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = DEFAULT_TRACKS_PER_CYLINDER; - } - - if (status == STATUS_VERIFY_REQUIRED) { - - // - // Routine ScsiClassSendSrbSynchronous does not retry - // requests returned with this status. - // Read Capacities should be retried - // anyway. - // - - if (retries--) { - - // - // Retry request. - // - - goto Retry; - } - } - - if (!NT_SUCCESS(status)) { - - // - // If the read capacity fails, set the geometry to reasonable parameter - // so things don't fail at unexpected places. Zero the geometry - // except for the bytes per sector and sector shift. - // - - RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY_EX)); - deviceExtension->DiskGeometry->Geometry.BytesPerSector = 512; - deviceExtension->SectorShift = 9; - deviceExtension->PartitionLength.QuadPart = (LONGLONG) 0; - deviceExtension->DiskGeometry->DiskSize.QuadPart = (LONGLONG) 0; - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - - // - // This device supports removable media. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia; - - } else { - - // - // Assume media type is fixed disk. - // - - deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia; - } - } - - // - // Deallocate read capacity buffer. - // - - ExFreePool(readCapacityBuffer); - - return status; - -} // end ScsiClassReadDriveCapacity() - - -VOID -NTAPI -ScsiClassReleaseQueue( - IN PDEVICE_OBJECT DeviceObject - ) - -/*++ - -Routine Description: - - This routine issues an internal device control command - to the port driver to release a frozen queue. The call - is issued asynchronously as ScsiClassReleaseQueue will be invoked - from the IO completion DPC (and will have no context to - wait for a synchronous call to complete). - -Arguments: - - DeviceObject - The device object for the logical unit with - the frozen queue. - -Return Value: - - None. - ---*/ -{ - PIO_STACK_LOCATION irpStack; - PIRP irp; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PCOMPLETION_CONTEXT context; - PSCSI_REQUEST_BLOCK srb; - KIRQL currentIrql; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Allocate context from nonpaged pool. - // - - context = ExAllocatePool(NonPagedPoolMustSucceed, - sizeof(COMPLETION_CONTEXT)); - - // - // Save the device object in the context for use by the completion - // routine. - // - - context->DeviceObject = DeviceObject; - srb = &context->Srb; - - // - // Zero out srb. - // - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - // - // Write length to SRB. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set up SCSI bus address. - // - - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - - // - // If this device is removable then flush the queue. This will also - // release it. - // - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - - srb->Function = SRB_FUNCTION_FLUSH_QUEUE; - - } else { - - srb->Function = SRB_FUNCTION_RELEASE_QUEUE; - - } - - // - // Build the asynchronous request to be sent to the port driver. - // - - irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - - if(irp == NULL) { - - // - // We have no better way of dealing with this at the moment - // - - KeBugCheck((ULONG)0x0000002DL); - - } - - IoSetCompletionRoutine(irp, - (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion, - context, - TRUE, - TRUE, - TRUE); - - irpStack = IoGetNextIrpStackLocation(irp); - - irpStack->MajorFunction = IRP_MJ_SCSI; - - srb->OriginalRequest = irp; - - // - // Store the SRB address in next stack for port driver. - // - - irpStack->Parameters.Scsi.Srb = srb; - - // - // Since this routine can cause outstanding requests to be completed, and - // calling a completion routine at < DISPATCH_LEVEL is dangerous (if they - // call IoStartNextPacket we will bugcheck) raise up to dispatch level before - // issuing the request - // - - currentIrql = KeGetCurrentIrql(); - - if(currentIrql < DISPATCH_LEVEL) { - KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); - IoCallDriver(deviceExtension->PortDeviceObject, irp); - KeLowerIrql(currentIrql); - } else { - IoCallDriver(deviceExtension->PortDeviceObject, irp); - } - - return; - -} // end ScsiClassReleaseQueue() - - -VOID -NTAPI -StartUnit( - IN PDEVICE_OBJECT DeviceObject - ) - -/*++ - -Routine Description: - - Send command to SCSI unit to start or power up. - Because this command is issued asynchronously, that is, without - waiting on it to complete, the IMMEDIATE flag is not set. This - means that the CDB will not return until the drive has powered up. - This should keep subsequent requests from being submitted to the - device before it has completely spun up. - This routine is called from the InterpretSense routine, when a - request sense returns data indicating that a drive must be - powered up. - -Arguments: - - DeviceObject - The device object for the logical unit with - the frozen queue. - -Return Value: - - None. - ---*/ -{ - PIO_STACK_LOCATION irpStack; - PIRP irp; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PSCSI_REQUEST_BLOCK srb; - PCOMPLETION_CONTEXT context; - PCDB cdb; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Allocate Srb from nonpaged pool. - // - - context = ExAllocatePool(NonPagedPoolMustSucceed, - sizeof(COMPLETION_CONTEXT)); - - // - // Save the device object in the context for use by the completion - // routine. - // - - context->DeviceObject = DeviceObject; - srb = &context->Srb; - - // - // Zero out srb. - // - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - // - // Write length to SRB. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set up SCSI bus address. - // - - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - - // - // Set timeout value large enough for drive to spin up. - // - - srb->TimeOutValue = START_UNIT_TIMEOUT; - - // - // Set the transfer length. - // - - srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // - // Build the start unit CDB. - // - - srb->CdbLength = 6; - cdb = (PCDB)srb->Cdb; - - cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb->START_STOP.Start = 1; - cdb->START_STOP.LogicalUnitNumber = srb->Lun; - - // - // Build the asynchronous request to be sent to the port driver. - // Since this routine is called from a DPC the IRP should always be - // available. - // - - irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - IoSetCompletionRoutine(irp, - (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion, - context, - TRUE, - TRUE, - TRUE); - - irpStack = IoGetNextIrpStackLocation(irp); - irpStack->MajorFunction = IRP_MJ_SCSI; - srb->OriginalRequest = irp; - - // - // Store the SRB address in next stack for port driver. - // - - irpStack->Parameters.Scsi.Srb = srb; - - // - // Call the port driver with the IRP. - // - - IoCallDriver(deviceExtension->PortDeviceObject, irp); - - return; - -} // end StartUnit() - - -NTSTATUS -NTAPI -ScsiClassAsynchronousCompletion( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Context - ) -/*++ - -Routine Description: - - This routine is called when an asynchronous I/O request - which was issued by the class driver completes. Examples of such requests - are release queue or START UNIT. This routine releases the queue if - necessary. It then frees the context and the IRP. - -Arguments: - - DeviceObject - The device object for the logical unit; however since this - is the top stack location the value is NULL. - - Irp - Supplies a pointer to the Irp to be processed. - - Context - Supplies the context to be used to process this request. - -Return Value: - - None. - ---*/ - -{ - PCOMPLETION_CONTEXT context = Context; - PSCSI_REQUEST_BLOCK srb; - - srb = &context->Srb; - - // - // If this is an execute srb, then check the return status and make sure. - // the queue is not frozen. - // - - if (srb->Function == SRB_FUNCTION_EXECUTE_SCSI) { - - // - // Check for a frozen queue. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - - // - // Unfreeze the queue getting the device object from the context. - // - - ScsiClassReleaseQueue(context->DeviceObject); - } - } - - // - // Free the context and the Irp. - // - - if (Irp->MdlAddress != NULL) { - MmUnlockPages(Irp->MdlAddress); - IoFreeMdl(Irp->MdlAddress); - - Irp->MdlAddress = NULL; - } - - ExFreePool(context); - IoFreeIrp(Irp); - - // - // Indicate the I/O system should stop processing the Irp completion. - // - - return STATUS_MORE_PROCESSING_REQUIRED; - -} // ScsiClassAsynchronousCompletion() - - -VOID -NTAPI -ScsiClassSplitRequest( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN ULONG MaximumBytes - ) - -/*++ - -Routine Description: - - Break request into smaller requests. Each new request will be the - maximum transfer size that the port driver can handle or if it - is the final request, it may be the residual size. - - The number of IRPs required to process this request is written in the - current stack of the original IRP. Then as each new IRP completes - the count in the original IRP is decremented. When the count goes to - zero, the original IRP is completed. - -Arguments: - - DeviceObject - Pointer to the class device object to be addressed. - - Irp - Pointer to Irp the original request. - -Return Value: - - None. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); - ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; - LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; - PVOID dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); - ULONG dataLength = MaximumBytes; - ULONG irpCount = (transferByteCount + MaximumBytes - 1) / MaximumBytes; - ULONG i; - PSCSI_REQUEST_BLOCK srb; - - DebugPrint((2, "ScsiClassSplitRequest: Requires %d IRPs\n", irpCount)); - DebugPrint((2, "ScsiClassSplitRequest: Original IRP %lx\n", Irp)); - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // If all partial transfers complete successfully then the status and - // bytes transferred are already set up. Failing a partial-transfer IRP - // will set status to error and bytes transferred to 0 during - // IoCompletion. Setting bytes transferred to 0 if an IRP fails allows - // asynchronous partial transfers. This is an optimization for the - // successful case. - // - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = transferByteCount; - - // - // Save number of IRPs to complete count on current stack - // of original IRP. - // - - nextIrpStack->Parameters.Others.Argument1 = (PVOID)(ULONG_PTR) irpCount; - - for (i = 0; i < irpCount; i++) { - - PIRP newIrp; - PIO_STACK_LOCATION newIrpStack; - - // - // Allocate new IRP. - // - - newIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - - if (newIrp == NULL) { - - DebugPrint((1,"ScsiClassSplitRequest: Can't allocate Irp\n")); - - // - // If an Irp can't be allocated then the original request cannot - // be executed. If this is the first request then just fail the - // original request; otherwise just return. When the pending - // requests complete, they will complete the original request. - // In either case set the IRP status to failure. - // - - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Information = 0; - - if (i == 0) { - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - - return; - } - - DebugPrint((2, "ScsiClassSplitRequest: New IRP %lx\n", newIrp)); - - // - // Write MDL address to new IRP. In the port driver the SRB data - // buffer field is used as an offset into the MDL, so the same MDL - // can be used for each partial transfer. This saves having to build - // a new MDL for each partial transfer. - // - - newIrp->MdlAddress = Irp->MdlAddress; - - // - // At this point there is no current stack. IoSetNextIrpStackLocation - // will make the first stack location the current stack so that the - // SRB address can be written there. - // - - IoSetNextIrpStackLocation(newIrp); - newIrpStack = IoGetCurrentIrpStackLocation(newIrp); - - newIrpStack->MajorFunction = currentIrpStack->MajorFunction; - newIrpStack->Parameters.Read.Length = dataLength; - newIrpStack->Parameters.Read.ByteOffset = startingOffset; - newIrpStack->DeviceObject = DeviceObject; - - // - // Build SRB and CDB. - // - - ScsiClassBuildRequest(DeviceObject, newIrp); - - // - // Adjust SRB for this partial transfer. - // - - newIrpStack = IoGetNextIrpStackLocation(newIrp); - - srb = newIrpStack->Parameters.Others.Argument1; - srb->DataBuffer = dataBuffer; - - // - // Write original IRP address to new IRP. - // - - newIrp->AssociatedIrp.MasterIrp = Irp; - - // - // Set the completion routine to ScsiClassIoCompleteAssociated. - // - - IoSetCompletionRoutine(newIrp, - ScsiClassIoCompleteAssociated, - srb, - TRUE, - TRUE, - TRUE); - - // - // Call port driver with new request. - // - - IoCallDriver(deviceExtension->PortDeviceObject, newIrp); - - // - // Set up for next request. - // - - dataBuffer = (PCHAR)dataBuffer + MaximumBytes; - - transferByteCount -= MaximumBytes; - - if (transferByteCount > MaximumBytes) { - - dataLength = MaximumBytes; - - } else { - - dataLength = transferByteCount; - } - - // - // Adjust disk byte offset. - // - - startingOffset.QuadPart = startingOffset.QuadPart + MaximumBytes; - } - - return; - -} // end ScsiClassSplitRequest() - - -NTSTATUS -NTAPI -ScsiClassIoComplete( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine executes when the port driver has completed a request. - It looks at the SRB status in the completing SRB and if not success - it checks for valid request sense buffer information. If valid, the - info is used to update status with more precise message of type of - error. This routine deallocates the SRB. - -Arguments: - - DeviceObject - Supplies the device object which represents the logical - unit. - - Irp - Supplies the Irp which has completed. - - Context - Supplies a pointer to the SRB. - -Return Value: - - NT status - ---*/ - -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PSCSI_REQUEST_BLOCK srb = Context; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - NTSTATUS status; - BOOLEAN retry; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Check SRB status for success of completing request. - // - - if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { - - DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb)); - - // - // Release the queue if it is frozen. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(DeviceObject); - } - - retry = ScsiClassInterpretSenseInfo( - DeviceObject, - srb, - irpStack->MajorFunction, - irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, - MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4), - &status); - - // - // If the status is verified required and the this request - // should bypass verify required then retry the request. - // - - if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && - status == STATUS_VERIFY_REQUIRED) { - - status = STATUS_IO_DEVICE_ERROR; - retry = TRUE; - } - - if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) { - - // - // Retry request. - // - - DebugPrint((1, "Retry request %lx\n", Irp)); - RetryRequest(DeviceObject, Irp, srb, FALSE); - return STATUS_MORE_PROCESSING_REQUIRED; - } - } else { - - // - // Set status for successful request. - // - - status = STATUS_SUCCESS; - - } // end if (SRB_STATUS(srb->SrbStatus) ... - - // - // Return SRB to list. - // - - ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead, - srb); - - // - // Set status in completing IRP. - // - - Irp->IoStatus.Status = status; - if ((NT_SUCCESS(status)) && (Irp->Flags & IRP_PAGING_IO)) { - ASSERT(Irp->IoStatus.Information); - } - - // - // Set the hard error if necessary. - // - - if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { - - // - // Store DeviceObject for filesystem, and clear - // in IoStatus.Information field. - // - - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - Irp->IoStatus.Information = 0; - } - - // - // If pending has be returned for this irp then mark the current stack as - // pending. - // - - if (Irp->PendingReturned) { - IoMarkIrpPending(Irp); - } - - if (deviceExtension->ClassStartIo) { - if (irpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) { - IoStartNextPacket(DeviceObject, FALSE); - } - } - - return status; - -} // end ScsiClassIoComplete() - - -NTSTATUS -NTAPI -ScsiClassIoCompleteAssociated( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine executes when the port driver has completed a request. - It looks at the SRB status in the completing SRB and if not success - it checks for valid request sense buffer information. If valid, the - info is used to update status with more precise message of type of - error. This routine deallocates the SRB. This routine is used for - requests which were build by split request. After it has processed - the request it decrements the Irp count in the master Irp. If the - count goes to zero then the master Irp is completed. - -Arguments: - - DeviceObject - Supplies the device object which represents the logical - unit. - - Irp - Supplies the Irp which has completed. - - Context - Supplies a pointer to the SRB. - -Return Value: - - NT status - ---*/ - -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PSCSI_REQUEST_BLOCK srb = Context; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIRP originalIrp = Irp->AssociatedIrp.MasterIrp; - LONG irpCount; - NTSTATUS status; - BOOLEAN retry; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Check SRB status for success of completing request. - // - - if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) { - - DebugPrint((2,"ScsiClassIoCompleteAssociated: IRP %lx, SRB %lx", Irp, srb)); - - // - // Release the queue if it is frozen. - // - - if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(DeviceObject); - } - - retry = ScsiClassInterpretSenseInfo( - DeviceObject, - srb, - irpStack->MajorFunction, - irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, - MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4), - &status); - - // - // If the status is verified required and the this request - // should bypass verify required then retry the request. - // - - if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME && - status == STATUS_VERIFY_REQUIRED) { - - status = STATUS_IO_DEVICE_ERROR; - retry = TRUE; - } - - if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) { - - // - // Retry request. If the class driver has supplied a StartIo, - // call it directly for retries. - // - - DebugPrint((1, "Retry request %lx\n", Irp)); - - /* - if (!deviceExtension->ClassStartIo) { - RetryRequest(DeviceObject, Irp, srb, TRUE); - } else { - deviceExtension->ClassStartIo(DeviceObject, Irp); - } - */ - - RetryRequest(DeviceObject, Irp, srb, TRUE); - - return STATUS_MORE_PROCESSING_REQUIRED; - } - - - - } else { - - // - // Set status for successful request. - // - - status = STATUS_SUCCESS; - - } // end if (SRB_STATUS(srb->SrbStatus) ... - - // - // Return SRB to list. - // - - ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead, - srb); - - // - // Set status in completing IRP. - // - - Irp->IoStatus.Status = status; - - DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial xfer IRP %lx\n", Irp)); - - // - // Get next stack location. This original request is unused - // except to keep track of the completing partial IRPs so the - // stack location is valid. - // - - irpStack = IoGetNextIrpStackLocation(originalIrp); - - // - // Update status only if error so that if any partial transfer - // completes with error, then the original IRP will return with - // error. If any of the asynchronous partial transfer IRPs fail, - // with an error then the original IRP will return 0 bytes transfered. - // This is an optimization for successful transfers. - // - - if (!NT_SUCCESS(status)) { - - originalIrp->IoStatus.Status = status; - originalIrp->IoStatus.Information = 0; - - // - // Set the hard error if necessary. - // - - if (IoIsErrorUserInduced(status)) { - - // - // Store DeviceObject for filesystem. - // - - IoSetHardErrorOrVerifyDevice(originalIrp, DeviceObject); - } - } - - // - // Decrement and get the count of remaining IRPs. - // - - irpCount = InterlockedDecrement((PLONG)&irpStack->Parameters.Others.Argument1); - - DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial IRPs left %d\n", - irpCount)); - - // - // Old bug could cause irp count to negative - // - - ASSERT(irpCount >= 0); - - if (irpCount == 0) { - - // - // All partial IRPs have completed. - // - - DebugPrint((2, - "ScsiClassIoCompleteAssociated: All partial IRPs complete %lx\n", - originalIrp)); - - IoCompleteRequest(originalIrp, IO_DISK_INCREMENT); - - // - // If the class driver has supplied a startio, start the - // next request. - // - - if (deviceExtension->ClassStartIo) { - IoStartNextPacket(DeviceObject, FALSE); - } - } - - // - // Deallocate IRP and indicate the I/O system should not attempt any more - // processing. - // - - IoFreeIrp(Irp); - return STATUS_MORE_PROCESSING_REQUIRED; - -} // end ScsiClassIoCompleteAssociated() - - -NTSTATUS -NTAPI -ScsiClassSendSrbSynchronous( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - PVOID BufferAddress, - ULONG BufferLength, - BOOLEAN WriteToDevice - ) - -/*++ - -Routine Description: - - This routine is called by SCSI device controls to complete an - SRB and send it to the port driver synchronously (ie wait for - completion). The CDB is already completed along with the SRB CDB - size and request timeout value. - -Arguments: - - DeviceObject - Supplies the device object which represents the logical - unit. - - Srb - Supplies a partially initialized SRB. The SRB cannot come from zone. - - BufferAddress - Supplies the address of the buffer. - - BufferLength - Supplies the length in bytes of the buffer. - - WriteToDevice - Indicates the data should be transfer to the device. - -Return Value: - - Nt status indicating the final results of the operation. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - IO_STATUS_BLOCK ioStatus; - ULONG controlType, mjFunction; - PIRP irp; - PIO_STACK_LOCATION irpStack; - KEVENT event; - PUCHAR senseInfoBuffer; - ULONG retryCount = MAXIMUM_RETRIES; - NTSTATUS status; - BOOLEAN retry; - LARGE_INTEGER dummy; - - PAGED_CODE(); - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - dummy.QuadPart = 0; - - // - // Write length to SRB. - // - - Srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set SCSI bus address. - // - - Srb->PathId = deviceExtension->PathId; - Srb->TargetId = deviceExtension->TargetId; - Srb->Lun = deviceExtension->Lun; - Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - - // - // NOTICE: The SCSI-II specification indicates that this field should be - // zero; however, some target controllers ignore the logical unit number - // in the IDENTIFY message and only look at the logical unit number field - // in the CDB. - // - - Srb->Cdb[1] |= deviceExtension->Lun << 5; - - // - // Enable auto request sense. - // - - Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - - // - // Sense buffer is in aligned nonpaged pool. - // - - senseInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); - - if (senseInfoBuffer == NULL) { - - DebugPrint((1, - "ScsiClassSendSrbSynchronous: Can't allocate request sense buffer\n")); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - Srb->SenseInfoBuffer = senseInfoBuffer; - Srb->DataBuffer = BufferAddress; - - // - // Start retries here. - // - -retry: - - // - // Set the event object to the unsignaled state. - // It will be used to signal request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Set controlType and Srb direction flags. - // - - if (BufferAddress != NULL) { - - if (WriteToDevice) { - - controlType = IOCTL_SCSI_EXECUTE_OUT; - Srb->SrbFlags = SRB_FLAGS_DATA_OUT; - mjFunction = IRP_MJ_WRITE; - - } else { - - controlType = IOCTL_SCSI_EXECUTE_IN; - Srb->SrbFlags = SRB_FLAGS_DATA_IN; - mjFunction = IRP_MJ_READ; - } - - } else { - - BufferLength = 0; - controlType = IOCTL_SCSI_EXECUTE_NONE; - Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER; - mjFunction = IRP_MJ_FLUSH_BUFFERS; - } - - // - // Build device I/O control request with data transfer. - // - irp = IoBuildAsynchronousFsdRequest( - mjFunction, - deviceExtension->DeviceObject, - BufferAddress, - (BufferAddress) ? BufferLength : 0, - &dummy, - &ioStatus); - - if (irp == NULL) { - ExFreePool(senseInfoBuffer); - DebugPrint((1, "ScsiClassSendSrbSynchronous: Can't allocate Irp\n")); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - // Set event field - irp->UserEvent = &event; - - // - // Disable synchronous transfer for these requests. - // - - Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // - // Set the transfer length. - // - - Srb->DataTransferLength = BufferLength; - - // - // Zero out status. - // - - Srb->ScsiStatus = Srb->SrbStatus = 0; - Srb->NextSrb = 0; - - // Set completion routine - IoSetCompletionRoutine( - irp, - ClassCompletionRoutine, - NULL, - TRUE, - TRUE, - TRUE); - - // - // Get next stack location. - // - - irpStack = IoGetNextIrpStackLocation(irp); - - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - irpStack->Parameters.DeviceIoControl.IoControlCode = controlType; - - // - // Set up SRB for execute scsi request. Save SRB address in next stack - // for the port driver. - // - - irpStack->Parameters.Scsi.Srb = Srb; - - // - // Set up IRP Address. - // - - Srb->OriginalRequest = irp; - - // - // Call the port driver with the request and wait for it to complete. - // - - status = IoCallDriver(deviceExtension->PortDeviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - } - - // - // Check that request completed without error. - // - - if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) { - - // - // Release the queue if it is frozen. - // - - if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) { - ScsiClassReleaseQueue(DeviceObject); - } - - // - // Update status and determine if request should be retried. - // - - retry = ScsiClassInterpretSenseInfo(DeviceObject, - Srb, - IRP_MJ_SCSI, - 0, - MAXIMUM_RETRIES - retryCount, - &status); - - if (retry) { - - if ((status == STATUS_DEVICE_NOT_READY && ((PSENSE_DATA) senseInfoBuffer) - ->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) || - SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) { - - LARGE_INTEGER delay; - - // - // Delay for 2 seconds. - // - - delay.QuadPart = (LONGLONG)( - 10 * 1000 * 1000 * 2 ); - - // - // Stall for a while to let the controller spinup. - // - - KeDelayExecutionThread(KernelMode, - FALSE, - &delay); - - } - - // - // If retries are not exhausted then retry this operation. - // - - if (retryCount--) { - goto retry; - } - } - - } else { - - status = STATUS_SUCCESS; - } - - ExFreePool(senseInfoBuffer); - return status; - -} // end ScsiClassSendSrbSynchronous() - - -BOOLEAN -NTAPI -ScsiClassInterpretSenseInfo( - IN PDEVICE_OBJECT DeviceObject, - IN PSCSI_REQUEST_BLOCK Srb, - IN UCHAR MajorFunctionCode, - IN ULONG IoDeviceCode, - IN ULONG RetryCount, - OUT NTSTATUS *Status - ) - -/*++ - -Routine Description: - - This routine interprets the data returned from the SCSI - request sense. It determines the status to return in the - IRP and whether this request can be retried. - -Arguments: - - DeviceObject - Supplies the device object associated with this request. - - Srb - Supplies the scsi request block which failed. - - MajorFunctionCode - Supplies the function code to be used for logging. - - IoDeviceCode - Supplies the device code to be used for logging. - - Status - Returns the status for the request. - -Return Value: - - BOOLEAN TRUE: Drivers should retry this request. - FALSE: Drivers should not retry this request. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension; - PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; - BOOLEAN retry = TRUE; - BOOLEAN logError = FALSE; - ULONG badSector = 0; - ULONG uniqueId = 0; - NTSTATUS logStatus; - ULONG readSector; - ULONG index; - PIO_ERROR_LOG_PACKET errorLogEntry; -#if DBG - ULONG i; -#endif - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Check that request sense buffer is valid. - // - -#if DBG - DebugPrint((3, "Opcode %x\nParameters: ",Srb->Cdb[0])); - for (i = 1; i < 12; i++) { - DebugPrint((3,"%x ",Srb->Cdb[i])); - } - DebugPrint((3,"\n")); -#endif - - if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && - Srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) { - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Error code is %x\n", - senseBuffer->ErrorCode)); - DebugPrint((1,"ScsiClassInterpretSenseInfo: Sense key is %x\n", - senseBuffer->SenseKey)); - DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code is %x\n", - senseBuffer->AdditionalSenseCode)); - DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code qualifier is %x\n", - senseBuffer->AdditionalSenseCodeQualifier)); - - // - // Zero the additional sense code and additional sense code qualifier - // if they were not returned by the device. - // - - readSector = senseBuffer->AdditionalSenseLength + - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength); - - if (readSector > Srb->SenseInfoBufferLength) { - readSector = Srb->SenseInfoBufferLength; - } - - if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCode)) { - senseBuffer->AdditionalSenseCode = 0; - } - - if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCodeQualifier)) { - senseBuffer->AdditionalSenseCodeQualifier = 0; - } - - switch (senseBuffer->SenseKey & 0xf) { - - case SCSI_SENSE_NOT_READY: - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Device not ready\n")); - *Status = STATUS_DEVICE_NOT_READY; - - switch (senseBuffer->AdditionalSenseCode) { - - case SCSI_ADSENSE_LUN_NOT_READY: - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Lun not ready\n")); - - switch (senseBuffer->AdditionalSenseCodeQualifier) { - - case SCSI_SENSEQ_BECOMING_READY: - - DebugPrint((1, "ScsiClassInterpretSenseInfo:" - " In process of becoming ready\n")); - break; - - case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED: - - DebugPrint((1, "ScsiClassInterpretSenseInfo:" - " Manual intervention required\n")); - *Status = STATUS_NO_MEDIA_IN_DEVICE; - retry = FALSE; - break; - - case SCSI_SENSEQ_FORMAT_IN_PROGRESS: - - DebugPrint((1, "ScsiClassInterpretSenseInfo: Format in progress\n")); - retry = FALSE; - break; - - case SCSI_SENSEQ_INIT_COMMAND_REQUIRED: - - default: - - DebugPrint((1, "ScsiClassInterpretSenseInfo:" - " Initializing command required\n")); - - // - // This sense code/additional sense code - // combination may indicate that the device - // needs to be started. Send an start unit if this - // is a disk device. - // - - if (deviceExtension->DeviceFlags & DEV_SAFE_START_UNIT) { - StartUnit(DeviceObject); - } - - break; - - } // end switch (senseBuffer->AdditionalSenseCodeQualifier) - - break; - - case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE: - - DebugPrint((1, - "ScsiClassInterpretSenseInfo:" - " No Media in device.\n")); - *Status = STATUS_NO_MEDIA_IN_DEVICE; - retry = FALSE; - - // - // signal autorun that there isn't any media in the device - // - - if((deviceExtension->MediaChangeEvent != NULL)&& - (!deviceExtension->MediaChangeNoMedia)) { - KeSetEvent(deviceExtension->MediaChangeEvent, - (KPRIORITY) 0, - FALSE); - DebugPrint((0, "ScsiClassInterpretSenseInfo:" - "Detected No Media In Device " - "[irp = 0x%lx]\n", Srb->OriginalRequest)); - deviceExtension->MediaChangeNoMedia = TRUE; - } - - break; - } // end switch (senseBuffer->AdditionalSenseCode) - - break; - - case SCSI_SENSE_DATA_PROTECT: - - DebugPrint((1, "ScsiClassInterpretSenseInfo: Media write protected\n")); - *Status = STATUS_MEDIA_WRITE_PROTECTED; - retry = FALSE; - break; - - case SCSI_SENSE_MEDIUM_ERROR: - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Bad media\n")); - *Status = STATUS_DEVICE_DATA_ERROR; - - retry = FALSE; - logError = TRUE; - uniqueId = 256; - logStatus = 0;//IO_ERR_BAD_BLOCK; - break; - - case SCSI_SENSE_HARDWARE_ERROR: - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Hardware error\n")); - *Status = STATUS_IO_DEVICE_ERROR; - - logError = TRUE; - uniqueId = 257; - logStatus = 0;//IO_ERR_CONTROLLER_ERROR; - - break; - - case SCSI_SENSE_ILLEGAL_REQUEST: - - DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal SCSI request\n")); - *Status = STATUS_INVALID_DEVICE_REQUEST; - - switch (senseBuffer->AdditionalSenseCode) { - - case SCSI_ADSENSE_ILLEGAL_COMMAND: - DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal command\n")); - retry = FALSE; - break; - - case SCSI_ADSENSE_ILLEGAL_BLOCK: - DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal block address\n")); - *Status = STATUS_NONEXISTENT_SECTOR; - retry = FALSE; - break; - - case SCSI_ADSENSE_INVALID_LUN: - DebugPrint((1,"ScsiClassInterpretSenseInfo: Invalid LUN\n")); - *Status = STATUS_NO_SUCH_DEVICE; - retry = FALSE; - break; - - case SCSI_ADSENSE_MUSIC_AREA: - DebugPrint((1,"ScsiClassInterpretSenseInfo: Music area\n")); - retry = FALSE; - break; - - case SCSI_ADSENSE_DATA_AREA: - DebugPrint((1,"ScsiClassInterpretSenseInfo: Data area\n")); - retry = FALSE; - break; - - case SCSI_ADSENSE_VOLUME_OVERFLOW: - DebugPrint((1, "ScsiClassInterpretSenseInfo: Volume overflow\n")); - retry = FALSE; - break; - - case SCSI_ADSENSE_INVALID_CDB: - DebugPrint((1, "ScsiClassInterpretSenseInfo: Invalid CDB\n")); - - // - // Check if write cache enabled. - // - - if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) { - - // - // Assume FUA is not supported. - // - - deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE; - retry = TRUE; - - } else { - retry = FALSE; - } - - break; - - } // end switch (senseBuffer->AdditionalSenseCode) - - break; - - case SCSI_SENSE_UNIT_ATTENTION: - - switch (senseBuffer->AdditionalSenseCode) { - case SCSI_ADSENSE_MEDIUM_CHANGED: - DebugPrint((1, "ScsiClassInterpretSenseInfo: Media changed\n")); - - if(deviceExtension->MediaChangeEvent != NULL) { - - KeSetEvent(deviceExtension->MediaChangeEvent, - (KPRIORITY) 0, - FALSE); - DebugPrint((0, "ScsiClassInterpretSenseInfo:" - "New Media Found - Setting MediaChanged event" - " [irp = 0x%lx]\n", Srb->OriginalRequest)); - deviceExtension->MediaChangeNoMedia = FALSE; - - } - break; - - case SCSI_ADSENSE_BUS_RESET: - DebugPrint((1,"ScsiClassInterpretSenseInfo: Bus reset\n")); - break; - - default: - DebugPrint((1,"ScsiClassInterpretSenseInfo: Unit attention\n")); - break; - - } // end switch (senseBuffer->AdditionalSenseCode) - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA && - DeviceObject->Vpb->Flags & VPB_MOUNTED) { - - // - // Set bit to indicate that media may have changed - // and volume needs verification. - // - - DeviceObject->Flags |= DO_VERIFY_VOLUME; - - *Status = STATUS_VERIFY_REQUIRED; - retry = FALSE; - - } else { - - *Status = STATUS_IO_DEVICE_ERROR; - - } - - // - // A media change may have occured so increment the change - // count for the physical device - // - - physicalExtension->MediaChangeCount++; - - DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change " - "count for device %d is %d\n", - physicalExtension->DeviceNumber, - physicalExtension->MediaChangeCount)); - - break; - - case SCSI_SENSE_ABORTED_COMMAND: - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Command aborted\n")); - *Status = STATUS_IO_DEVICE_ERROR; - break; - - case SCSI_SENSE_RECOVERED_ERROR: - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Recovered error\n")); - *Status = STATUS_SUCCESS; - retry = FALSE; - logError = TRUE; - uniqueId = 258; - - switch(senseBuffer->AdditionalSenseCode) { - case SCSI_ADSENSE_SEEK_ERROR: - case SCSI_ADSENSE_TRACK_ERROR: - logStatus = 0;//IO_ERR_SEEK_ERROR; - break; - - case SCSI_ADSENSE_REC_DATA_NOECC: - case SCSI_ADSENSE_REC_DATA_ECC: - logStatus = 0;//IO_RECOVERED_VIA_ECC; - break; - - default: - logStatus = 0;//IO_ERR_CONTROLLER_ERROR; - break; - - } // end switch(senseBuffer->AdditionalSenseCode) - - if (senseBuffer->IncorrectLength) { - - DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n")); - *Status = STATUS_INVALID_BLOCK_LENGTH ; - } - - break; - - case SCSI_SENSE_NO_SENSE: - - // - // Check other indicators. - // - - if (senseBuffer->IncorrectLength) { - - DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n")); - *Status = STATUS_INVALID_BLOCK_LENGTH ; - retry = FALSE; - - } else { - - DebugPrint((1, "ScsiClassInterpretSenseInfo: No specific sense key\n")); - *Status = STATUS_IO_DEVICE_ERROR; - retry = TRUE; - } - - break; - - default: - - DebugPrint((1, "ScsiClassInterpretSenseInfo: Unrecognized sense code\n")); - *Status = STATUS_IO_DEVICE_ERROR; - break; - - } // end switch (senseBuffer->SenseKey & 0xf) - - // - // Try to determine the bad sector from the inquiry data. - // - - if ((((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_READ || - ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY || - ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_WRITE)) { - - for (index = 0; index < 4; index++) { - badSector = (badSector << 8) | senseBuffer->Information[index]; - } - - readSector = 0; - for (index = 0; index < 4; index++) { - readSector = (readSector << 8) | Srb->Cdb[index+2]; - } - - index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) | - ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb; - - // - // Make sure the bad sector is within the read sectors. - // - - if (!(badSector >= readSector && badSector < readSector + index)) { - badSector = readSector; - } - } - - } else { - - // - // Request sense buffer not valid. No sense information - // to pinpoint the error. Return general request fail. - // - - DebugPrint((1,"ScsiClassInterpretSenseInfo: Request sense info not valid. SrbStatus %2x\n", - SRB_STATUS(Srb->SrbStatus))); - retry = TRUE; - - switch (SRB_STATUS(Srb->SrbStatus)) { - case SRB_STATUS_INVALID_LUN: - case SRB_STATUS_INVALID_TARGET_ID: - case SRB_STATUS_NO_DEVICE: - case SRB_STATUS_NO_HBA: - case SRB_STATUS_INVALID_PATH_ID: - *Status = STATUS_NO_SUCH_DEVICE; - retry = FALSE; - break; - - case SRB_STATUS_COMMAND_TIMEOUT: - case SRB_STATUS_ABORTED: - case SRB_STATUS_TIMEOUT: - - // - // Update the error count for the device. - // - - deviceExtension->ErrorCount++; - *Status = STATUS_IO_TIMEOUT; - break; - - case SRB_STATUS_SELECTION_TIMEOUT: - logError = TRUE; - logStatus = 0;//IO_ERR_NOT_READY; - uniqueId = 260; - *Status = STATUS_DEVICE_NOT_CONNECTED; - retry = FALSE; - break; - - case SRB_STATUS_DATA_OVERRUN: - *Status = STATUS_DATA_OVERRUN; - retry = FALSE; - break; - - case SRB_STATUS_PHASE_SEQUENCE_FAILURE: - - // - // Update the error count for the device. - // - - deviceExtension->ErrorCount++; - *Status = STATUS_IO_DEVICE_ERROR; - - // - // If there was phase sequence error then limit the number of - // retries. - // - - if (RetryCount > 1 ) { - retry = FALSE; - } - - break; - - case SRB_STATUS_REQUEST_FLUSHED: - - // - // If the status needs verification bit is set. Then set - // the status to need verification and no retry; otherwise, - // just retry the request. - // - - if (DeviceObject->Flags & DO_VERIFY_VOLUME ) { - - *Status = STATUS_VERIFY_REQUIRED; - retry = FALSE; - } else { - *Status = STATUS_IO_DEVICE_ERROR; - } - - break; - - case SRB_STATUS_INVALID_REQUEST: - - // - // An invalid request was attempted. - // - - *Status = STATUS_INVALID_DEVICE_REQUEST; - retry = FALSE; - break; - - case SRB_STATUS_UNEXPECTED_BUS_FREE: - case SRB_STATUS_PARITY_ERROR: - - // - // Update the error count for the device. - // - - deviceExtension->ErrorCount++; - - // - // Fall through to below. - // - - case SRB_STATUS_BUS_RESET: - *Status = STATUS_IO_DEVICE_ERROR; - break; - - case SRB_STATUS_ERROR: - - *Status = STATUS_IO_DEVICE_ERROR; - if (Srb->ScsiStatus == 0) { - - // - // This is some strange return code. Update the error - // count for the device. - // - - deviceExtension->ErrorCount++; - - } if (Srb->ScsiStatus == SCSISTAT_BUSY) { - - *Status = STATUS_DEVICE_NOT_READY; - - } if (Srb->ScsiStatus == SCSISTAT_RESERVATION_CONFLICT) { - - *Status = STATUS_DEVICE_BUSY; - retry = FALSE; - - } - - break; - - default: - logError = TRUE; - logStatus = 0;//IO_ERR_CONTROLLER_ERROR; - uniqueId = 259; - *Status = STATUS_IO_DEVICE_ERROR; - break; - - } - - // - // If the error count has exceeded the error limit, then disable - // any tagged queuing, multiple requests per lu queueing - // and synchronous data transfers. - // - - if (deviceExtension->ErrorCount == 4) { - - // - // Clearing the no queue freeze flag prevents the port driver - // from sending multiple requests per logical unit. - // - - deviceExtension->SrbFlags &= ~(SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_NO_QUEUE_FREEZE); - - deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling tagged queuing and synchronous data tranfers.\n")); - - } else if (deviceExtension->ErrorCount == 8) { - - // - // If a second threshold is reached, disable disconnects. - // - - deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT; - DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling disconnects.\n")); - } - } - - // - // If there is a class specific error handler call it. - // - - if (deviceExtension->ClassError != NULL) { - - deviceExtension->ClassError(DeviceObject, - Srb, - Status, - &retry); - } - - // - // Log an error if necessary. - // - - if (logError) { - - errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( - DeviceObject, - sizeof(IO_ERROR_LOG_PACKET) + 5 * sizeof(ULONG)); - - if (errorLogEntry == NULL) { - - // - // Return if no packet could be allocated. - // - - return retry; - - } - - if (retry && RetryCount < MAXIMUM_RETRIES) { - errorLogEntry->FinalStatus = STATUS_SUCCESS; - } else { - errorLogEntry->FinalStatus = *Status; - } - - // - // Calculate the device offset if there is a geometry. - // - - if (deviceExtension->DiskGeometry != NULL) { - - errorLogEntry->DeviceOffset.QuadPart = (LONGLONG) badSector; - errorLogEntry->DeviceOffset = RtlExtendedIntegerMultiply( - errorLogEntry->DeviceOffset, - deviceExtension->DiskGeometry->Geometry.BytesPerSector); - } - - errorLogEntry->ErrorCode = logStatus; - errorLogEntry->SequenceNumber = 0; - errorLogEntry->MajorFunctionCode = MajorFunctionCode; - errorLogEntry->IoControlCode = IoDeviceCode; - errorLogEntry->RetryCount = (UCHAR) RetryCount; - errorLogEntry->UniqueErrorValue = uniqueId; - errorLogEntry->DumpDataSize = 6 * sizeof(ULONG); - errorLogEntry->DumpData[0] = Srb->PathId; - errorLogEntry->DumpData[1] = Srb->TargetId; - errorLogEntry->DumpData[2] = Srb->Lun; - errorLogEntry->DumpData[3] = 0; - errorLogEntry->DumpData[4] = Srb->SrbStatus << 8 | Srb->ScsiStatus; - - if (senseBuffer != NULL) { - errorLogEntry->DumpData[5] = senseBuffer->SenseKey << 16 | - senseBuffer->AdditionalSenseCode << 8 | - senseBuffer->AdditionalSenseCodeQualifier; - - } - - // - // Write the error log packet. - // - - IoWriteErrorLogEntry(errorLogEntry); - } - - return retry; - -} // end ScsiClassInterpretSenseInfo() - - -VOID -NTAPI -RetryRequest( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PSCSI_REQUEST_BLOCK Srb, - BOOLEAN Associated - ) - -/*++ - -Routine Description: - - This routine reinitializes the necessary fields, and sends the request - to the port driver. - -Arguments: - - DeviceObject - Supplies the device object associated with this request. - - Irp - Supplies the request to be retried. - - Srb - Supplies a Pointer to the SCSI request block to be retied. - - Associated - Indicates this is an associated Irp created by split request. - -Return Value: - - None - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); - ULONG transferByteCount; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Determine the transfer count of the request. If this is a read or a - // write then the transfer count is in the Irp stack. Otherwise assume - // the MDL contains the correct length. If there is no MDL then the - // transfer length must be zero. - // - - if (currentIrpStack->MajorFunction == IRP_MJ_READ || - currentIrpStack->MajorFunction == IRP_MJ_WRITE) { - - transferByteCount = currentIrpStack->Parameters.Read.Length; - - } else if (Irp->MdlAddress != NULL) { - - // - // Note this assumes that only read and write requests are spilt and - // other request do not need to be. If the data buffer address in - // the MDL and the SRB don't match then transfer length is most - // likely incorrect. - // - - ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress)); - transferByteCount = Irp->MdlAddress->ByteCount; - - } else { - - transferByteCount = 0; - } - - // - // Reset byte count of transfer in SRB Extension. - // - - Srb->DataTransferLength = transferByteCount; - - // - // Zero SRB statuses. - // - - Srb->SrbStatus = Srb->ScsiStatus = 0; - - // - // Set the no disconnect flag, disable synchronous data transfers and - // disable tagged queuing. This fixes some errors. - // - - Srb->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - Srb->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE; - Srb->QueueTag = SP_UNTAGGED; - - // - // Set up major SCSI function. - // - - nextIrpStack->MajorFunction = IRP_MJ_SCSI; - - // - // Save SRB address in next stack for port driver. - // - - nextIrpStack->Parameters.Scsi.Srb = Srb; - - // - // Set up IoCompletion routine address. - // - - if (Associated) { - - IoSetCompletionRoutine(Irp, ScsiClassIoCompleteAssociated, Srb, TRUE, TRUE, TRUE); - - } else { - - IoSetCompletionRoutine(Irp, ScsiClassIoComplete, Srb, TRUE, TRUE, TRUE); - } - - // - // Pass the request to the port driver. - // - - (VOID)IoCallDriver(deviceExtension->PortDeviceObject, Irp); - -} // end RetryRequest() - -VOID -NTAPI -ScsiClassBuildRequest( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ) - -/*++ - -Routine Description: - - This routine allocates and builds an Srb for a read or write request. - The block address and length are supplied by the Irp. The retry count - is stored in the current stack for use by ScsiClassIoComplete which - processes these requests when they complete. The Irp is ready to be - passed to the port driver when this routine returns. - -Arguments: - - DeviceObject - Supplies the device object associated with this request. - - Irp - Supplies the request to be retried. - -Note: - - If the IRP is for a disk transfer, the byteoffset field - will already have been adjusted to make it relative to - the beginning of the disk. - - -Return Value: - - None. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); - LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset; - PSCSI_REQUEST_BLOCK srb; - PCDB cdb; - ULONG logicalBlockAddress; - USHORT transferBlocks; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Calculate relative sector address. - // - - logicalBlockAddress = (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, deviceExtension->SectorShift)); - - // - // Allocate an Srb. - // - - srb = ExAllocateFromNPagedLookasideList(&deviceExtension->SrbLookasideListHead); - - srb->SrbFlags = 0; - - // - // Write length to SRB. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set up IRP Address. - // - - srb->OriginalRequest = Irp; - - // - // Set up target ID and logical unit number. - // - - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); - - // - // Save byte count of transfer in SRB Extension. - // - - srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; - - // - // Initialize the queue actions field. - // - - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - - // - // Queue sort key is Relative Block Address. - // - - srb->QueueSortKey = logicalBlockAddress; - - // - // Indicate auto request sense by specifying buffer and size. - // - - srb->SenseInfoBuffer = deviceExtension->SenseData; - srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - - // - // Set timeout value of one unit per 64k bytes of data. - // - - srb->TimeOutValue = ((srb->DataTransferLength + 0xFFFF) >> 16) * - deviceExtension->TimeOutValue; - - // - // Zero statuses. - // - - srb->SrbStatus = srb->ScsiStatus = 0; - srb->NextSrb = 0; - - // - // Indicate that 10-byte CDB's will be used. - // - - srb->CdbLength = 10; - - // - // Fill in CDB fields. - // - - cdb = (PCDB)srb->Cdb; - - // - // Zero 12 bytes for Atapi Packets - // - - RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); - - cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun; - transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift); - - // - // Move little endian values into CDB in big endian format. - // - - cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3; - cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2; - cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1; - cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0; - - cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1; - cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0; - - // - // Set transfer direction flag and Cdb command. - // - - if (currentIrpStack->MajorFunction == IRP_MJ_READ) { - - DebugPrint((3, "ScsiClassBuildRequest: Read Command\n")); - - srb->SrbFlags |= SRB_FLAGS_DATA_IN; - cdb->CDB10.OperationCode = SCSIOP_READ; - - } else { - - DebugPrint((3, "ScsiClassBuildRequest: Write Command\n")); - - srb->SrbFlags |= SRB_FLAGS_DATA_OUT; - cdb->CDB10.OperationCode = SCSIOP_WRITE; - } - - // - // If this is not a write-through request, then allow caching. - // - - if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) { - - srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE; - - } else { - - // - // If write caching is enable then force media access in the - // cdb. - // - - if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) { - cdb->CDB10.ForceUnitAccess = TRUE; - } - } - - // - // Or in the default flags from the device object. - // - - srb->SrbFlags |= deviceExtension->SrbFlags; - - // - // Set up major SCSI function. - // - - nextIrpStack->MajorFunction = IRP_MJ_SCSI; - - // - // Save SRB address in next stack for port driver. - // - - nextIrpStack->Parameters.Scsi.Srb = srb; - - // - // Save retry count in current IRP stack. - // - - currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; - - // - // Set up IoCompletion routine address. - // - - IoSetCompletionRoutine(Irp, ScsiClassIoComplete, srb, TRUE, TRUE, TRUE); - - return; - -} // end ScsiClassBuildRequest() - -ULONG -NTAPI -ScsiClassModeSense( - IN PDEVICE_OBJECT DeviceObject, - IN PCHAR ModeSenseBuffer, - IN ULONG Length, - IN UCHAR PageMode - ) - -/*++ - -Routine Description: - - This routine sends a mode sense command to a target ID and returns - when it is complete. - -Arguments: - - DeviceObject - Supplies the device object associated with this request. - - ModeSenseBuffer - Supplies a buffer to store the sense data. - - Length - Supplies the length in bytes of the mode sense buffer. - - PageMode - Supplies the page or pages of mode sense data to be retrieved. - -Return Value: - - Length of the transferred data is returned. - ---*/ -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PCDB cdb; - SCSI_REQUEST_BLOCK srb; - ULONG retries = 1; - NTSTATUS status; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // - // Build the MODE SENSE CDB. - // - - srb.CdbLength = 6; - cdb = (PCDB)srb.Cdb; - - // - // Set timeout value from device extension. - // - - srb.TimeOutValue = deviceExtension->TimeOutValue; - - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.PageCode = PageMode; - cdb->MODE_SENSE.AllocationLength = (UCHAR)Length; - -Retry: - - status = ScsiClassSendSrbSynchronous(DeviceObject, - &srb, - ModeSenseBuffer, - Length, - FALSE); - - - if (status == STATUS_VERIFY_REQUIRED) { - - // - // Routine ScsiClassSendSrbSynchronous does not retry requests returned with - // this status. MODE SENSE commands should be retried anyway. - // - - if (retries--) { - - // - // Retry request. - // - - goto Retry; - } - - } else if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) { - status = STATUS_SUCCESS; - } - - if (NT_SUCCESS(status)) { - return(srb.DataTransferLength); - } else { - return(0); - } - -} // end ScsiClassModeSense() - - -PVOID -NTAPI -ScsiClassFindModePage( - IN PCHAR ModeSenseBuffer, - IN ULONG Length, - IN UCHAR PageMode, - IN BOOLEAN Use6Byte - ) - -/*++ - -Routine Description: - - This routine scans through the mode sense data and finds the requested - mode sense page code. - -Arguments: - ModeSenseBuffer - Supplies a pointer to the mode sense data. - - Length - Indicates the length of valid data. - - PageMode - Supplies the page mode to be searched for. - - Use6Byte - Indicates whether 6 or 10 byte mode sense was used. - -Return Value: - - A pointer to the the requested mode page. If the mode page was not found - then NULL is return. - ---*/ -{ - PUCHAR limit; - ULONG parameterHeaderLength; - - limit = (PUCHAR)ModeSenseBuffer + Length; - parameterHeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10); - - - // - // Skip the mode select header and block descriptors. - // - - if (Length < parameterHeaderLength) { - return(NULL); - } - - - - ModeSenseBuffer += parameterHeaderLength + ((Use6Byte) ? ((PMODE_PARAMETER_HEADER) ModeSenseBuffer)->BlockDescriptorLength : - ((PMODE_PARAMETER_HEADER10) ModeSenseBuffer)->BlockDescriptorLength[1]); - - // - // ModeSenseBuffer now points at pages. Walk the pages looking for the - // requested page until the limit is reached. - // - - - while ((PUCHAR)ModeSenseBuffer < limit) { - - if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode) { - return(ModeSenseBuffer); - } - - // - // Advance to the next page. - // - - ModeSenseBuffer += ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength + 2; - } - - return(NULL); -} - -NTSTATUS -NTAPI -ScsiClassSendSrbAsynchronous( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - PIRP Irp, - PVOID BufferAddress, - ULONG BufferLength, - BOOLEAN WriteToDevice - ) -/*++ - -Routine Description: - - This routine takes a partially built Srb and an Irp and sends it down to - the port driver. - -Arguments: - DeviceObject - Supplies the device object for the original request. - - Srb - Supplies a partially built ScsiRequestBlock. In particular, the - CDB and the SRB timeout value must be filled in. The SRB must not be - allocated from zone. - - Irp - Supplies the requesting Irp. - - BufferAddress - Supplies a pointer to the buffer to be transfered. - - BufferLength - Supplies the length of data transfer. - - WriteToDevice - Indicates the data transfer will be from system memory to - device. - -Return Value: - - Returns STATUS_INSUFFICIENT_RESOURCES or the status of IoCallDriver. - ---*/ -{ - - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpStack; - - PAGED_CODE(); - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Write length to SRB. - // - - Srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set SCSI bus address. - // - - Srb->PathId = deviceExtension->PathId; - Srb->TargetId = deviceExtension->TargetId; - Srb->Lun = deviceExtension->Lun; - - Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - - // - // This is a violation of the SCSI spec but it is required for - // some targets. - // - - Srb->Cdb[1] |= deviceExtension->Lun << 5; - - // - // Indicate auto request sense by specifying buffer and size. - // - - Srb->SenseInfoBuffer = deviceExtension->SenseData; - Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; - Srb->DataBuffer = BufferAddress; - - if (BufferAddress != NULL) { - - // - // Build Mdl if necessary. - // - - if (Irp->MdlAddress == NULL) { - - if (IoAllocateMdl(BufferAddress, - BufferLength, - FALSE, - FALSE, - Irp) == NULL) { - - return(STATUS_INSUFFICIENT_RESOURCES); - } - - MmBuildMdlForNonPagedPool(Irp->MdlAddress); - - } else { - - // - // Make sure the buffer requested matches the MDL. - // - - ASSERT(BufferAddress == MmGetMdlVirtualAddress(Irp->MdlAddress)); - } - - // - // Set read flag. - // - - Srb->SrbFlags = WriteToDevice ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN; - - } else { - - // - // Clear flags. - // - - Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER; - } - - // - // Disable synchronous transfer for these requests. - // - - Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - // - // Set the transfer length. - // - - Srb->DataTransferLength = BufferLength; - - // - // Zero out status. - // - - Srb->ScsiStatus = Srb->SrbStatus = 0; - - Srb->NextSrb = 0; - - // - // Save a few parameters in the current stack location. - // - - irpStack = IoGetCurrentIrpStackLocation(Irp); - - // - // Save retry count in current Irp stack. - // - - irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; - - // - // Set up IoCompletion routine address. - // - - IoSetCompletionRoutine(Irp, ScsiClassIoComplete, Srb, TRUE, TRUE, TRUE); - - // - // Get next stack location and - // set major function code. - // - - irpStack = IoGetNextIrpStackLocation(Irp); - - irpStack->MajorFunction = IRP_MJ_SCSI; - - // - // Save SRB address in next stack for port driver. - // - - irpStack->Parameters.Scsi.Srb = Srb; - - // - // Set up Irp Address. - // - - Srb->OriginalRequest = Irp; - - // - // Call the port driver to process the request. - // - - return(IoCallDriver(deviceExtension->PortDeviceObject, Irp)); - -} - - -NTSTATUS -NTAPI -ScsiClassDeviceControlDispatch( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ) - -/*++ - -Routine Description: - - The routine is the common class driver device control dispatch entry point. - This routine is invokes the device-specific drivers DeviceControl routine, - (which may call the Class driver's common DeviceControl routine). - -Arguments: - - DeviceObject - Supplies a pointer to the device object for this request. - - Irp - Supplies the Irp making the request. - -Return Value: - - Returns the status returned from the device-specific driver. - ---*/ - -{ - - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Call the class specific driver DeviceControl routine. - // If it doesn't handle it, it will call back into ScsiClassDeviceControl. - // - - ASSERT(deviceExtension->ClassDeviceControl); - - return deviceExtension->ClassDeviceControl(DeviceObject,Irp); -} - - -NTSTATUS -NTAPI -ScsiClassDeviceControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ) -/*++ - -Routine Description: - - The routine is the common class driver device control dispatch function. - This routine is called by a class driver when it get an unrecognized - device control request. This routine will perform the correct action for - common requests such as lock media. If the device request is unknown it - passed down to the next level. - -Arguments: - - DeviceObject - Supplies a pointer to the device object for this request. - - Irp - Supplies the Irp making the request. - -Return Value: - - Returns back a STATUS_PENDING or a completion status. - ---*/ - -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PIO_STACK_LOCATION nextStack; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PSCSI_REQUEST_BLOCK srb; - PCDB cdb; - NTSTATUS status; - ULONG modifiedIoControlCode; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - if (irpStack->Parameters.DeviceIoControl.IoControlCode == - IOCTL_STORAGE_RESET_DEVICE) { - - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_UNSUCCESSFUL; - goto SetStatusAndReturn; - } - - // - // If this is a pass through I/O control, set the minor function code - // and device address and pass it to the port driver. - // - - if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH - || irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) { - - PSCSI_PASS_THROUGH scsiPass; - - nextStack = IoGetNextIrpStackLocation(Irp); - - // - // Validate the user buffer. - // - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)){ - - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_INVALID_PARAMETER; - goto SetStatusAndReturn; - } - - // - // Force the SCSI address to the correct value. - // - - scsiPass = Irp->AssociatedIrp.SystemBuffer; - scsiPass->PathId = deviceExtension->PathId; - scsiPass->TargetId = deviceExtension->TargetId; - scsiPass->Lun = deviceExtension->Lun; - - // - // NOTICE: The SCSI-II specification indicates that this field - // should be zero; however, some target controllers ignore the logical - // unit number in the IDENTIFY message and only look at the logical - // unit number field in the CDB. - // - - scsiPass->Cdb[1] |= deviceExtension->Lun << 5; - - nextStack->Parameters = irpStack->Parameters; - nextStack->MajorFunction = irpStack->MajorFunction; - nextStack->MinorFunction = IRP_MN_SCSI_CLASS; - - status = IoCallDriver(deviceExtension->PortDeviceObject, Irp); - goto SetStatusAndReturn; - } - - if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS) { - - PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer; - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(SCSI_ADDRESS)) { - - // - // Indicate unsuccessful status and no data transferred. - // - - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_BUFFER_TOO_SMALL; - goto SetStatusAndReturn; - - } - - scsiAddress->Length = sizeof(SCSI_ADDRESS); - scsiAddress->PortNumber = deviceExtension->PortNumber; - scsiAddress->PathId = deviceExtension->PathId; - scsiAddress->TargetId = deviceExtension->TargetId; - scsiAddress->Lun = deviceExtension->Lun; - Irp->IoStatus.Information = sizeof(SCSI_ADDRESS); - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_SUCCESS; - goto SetStatusAndReturn; - } - - if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME) { - - UNIMPLEMENTED; - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_NOT_IMPLEMENTED; - goto SetStatusAndReturn; - } - - if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_UNIQUE_ID) { - - // - // FIXME - // This is a HACK. We don't have unique ID. - // We'll just return device name as unique ID. - // It's unique but may not survive to a reboot, - // which is not matching the requirements for - // a MountMgr unique ID. - // - - PMOUNTDEV_UNIQUE_ID uniqueId = Irp->AssociatedIrp.SystemBuffer; - - // - // Check output buffer is big enough. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_UNIQUE_ID)) { - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_INVALID_PARAMETER; - goto SetStatusAndReturn; - } - - // - // Set size we'll return so that caller can allocate big enough buffer. - // - - RtlZeroMemory(uniqueId, sizeof(MOUNTDEV_UNIQUE_ID)); - uniqueId->UniqueIdLength = deviceExtension->DeviceName.Length; - - // - // Check buffer is big enough to contain device name. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + uniqueId->UniqueIdLength) { - - Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID); - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_BUFFER_OVERFLOW; - goto SetStatusAndReturn; - } - - // - // Copy device name. - // - - RtlCopyMemory(uniqueId->UniqueId, deviceExtension->DeviceName.Buffer, - uniqueId->UniqueIdLength); - status = STATUS_SUCCESS; - - // - // And return to the caller. - // - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + uniqueId->UniqueIdLength; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - goto SetStatusAndReturn; - } - - if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_DEVICE_NAME) { - - PMOUNTDEV_NAME name = Irp->AssociatedIrp.SystemBuffer; - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME)) { - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_INVALID_PARAMETER; - goto SetStatusAndReturn; - } - - RtlZeroMemory(name, sizeof(MOUNTDEV_NAME)); - name->NameLength = deviceExtension->DeviceName.Length; - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_NAME, Name) + name->NameLength) { - - Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME); - Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_BUFFER_OVERFLOW; - goto SetStatusAndReturn; - } - - RtlCopyMemory(name->Name, deviceExtension->DeviceName.Buffer, - name->NameLength); - status = STATUS_SUCCESS; - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_NAME, Name) + name->NameLength; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - goto SetStatusAndReturn; - } - - srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); - - if (srb == NULL) { - - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_INSUFFICIENT_RESOURCES; - goto SetStatusAndReturn; - } - - // - // Write zeros to Srb. - // - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - cdb = (PCDB)srb->Cdb; - - // - // Change the device type to disk for the switch statement. - // - - modifiedIoControlCode = (irpStack->Parameters.DeviceIoControl.IoControlCode - & ~0xffff0000) | (IOCTL_DISK_BASE << 16); - - switch (modifiedIoControlCode) { - - case IOCTL_DISK_CHECK_VERIFY: { - - PIRP irp2 = NULL; - PIO_STACK_LOCATION newStack; - - DebugPrint((1,"ScsiDeviceIoControl: Check verify\n")); - - // - // If a buffer for a media change count was provided, make sure it's - // big enough to hold the result - // - - if(irpStack->Parameters.DeviceIoControl.OutputBufferLength) { - - // - // If the buffer is too small to hold the media change count - // then return an error to the caller - // - - if(irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(ULONG)) { - - DebugPrint((3,"ScsiDeviceIoControl: media count " - "buffer too small\n")); - - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = 0; - ExFreePool(srb); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_BUFFER_TOO_SMALL; - goto SetStatusAndReturn; - - } - - // - // The caller has provided a valid buffer. Allocate an additional - // irp and stick the CheckVerify completion routine on it. We will - // then send this down to the port driver instead of the irp the - // caller sent in - // - - DebugPrint((2,"ScsiDeviceIoControl: Check verify wants " - "media count\n")); - - // - // Allocate a new irp to send the TestUnitReady to the port driver - // - - irp2 = IoAllocateIrp((CCHAR) (DeviceObject->StackSize + 3), FALSE); - - if(irp2 == NULL) { - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - Irp->IoStatus.Information = 0; - ExFreePool(srb); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_INSUFFICIENT_RESOURCES; - goto SetStatusAndReturn; - } - - irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread; - IoSetNextIrpStackLocation(irp2); - - // - // Set the top stack location and shove the master Irp into the - // top location - // - - newStack = IoGetCurrentIrpStackLocation(irp2); - newStack->Parameters.Others.Argument1 = Irp; - newStack->DeviceObject = DeviceObject; - - // - // Stick the check verify completion routine onto the stack - // and prepare the irp for the port driver - // - - IoSetCompletionRoutine(irp2, - ScsiClassCheckVerifyComplete, - NULL, - TRUE, - TRUE, - TRUE); - - IoSetNextIrpStackLocation(irp2); - newStack = IoGetCurrentIrpStackLocation(irp2); - newStack->DeviceObject = DeviceObject; - - // - // Mark the master irp as pending - whether the lower level - // driver completes it immediately or not this should allow it - // to go all the way back up. - // - - IoMarkIrpPending(Irp); - - Irp = irp2; - - } - - // - // Test Unit Ready - // - - srb->CdbLength = 6; - cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - - // - // Since this routine will always hand the request to the - // port driver if there isn't a data transfer to be done - // we don't have to worry about completing the request here - // on an error - // - - status = ScsiClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - - break; - } - - case IOCTL_DISK_MEDIA_REMOVAL: { - - PPREVENT_MEDIA_REMOVAL MediaRemoval = Irp->AssociatedIrp.SystemBuffer; - - // - // Prevent/Allow media removal. - // - - DebugPrint((3,"DiskIoControl: Prevent/Allow media removal\n")); - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(PREVENT_MEDIA_REMOVAL)) { - - // - // Indicate unsuccessful status and no data transferred. - // - - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - Irp->IoStatus.Information = 0; - ExFreePool(srb); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_BUFFER_TOO_SMALL; - goto SetStatusAndReturn; - } - - // - // Get physical device extension. This is where the - // lock count is stored. - // - - deviceExtension = deviceExtension->PhysicalDevice->DeviceExtension; - - // - // If command succeeded then increment or decrement lock counter. - // - - if (MediaRemoval->PreventMediaRemoval) { - - // - // This is a lock command. Reissue the command in case bus or device - // was reset and lock cleared. - // - - InterlockedIncrement(&deviceExtension->LockCount); - - DebugPrint((1, - "ScsiClassDeviceControl: Lock media, lock count %x on disk %x\n", - deviceExtension->LockCount, - deviceExtension->DeviceNumber)); - - } else { - - // - // This is an unlock command. - // - - if (!deviceExtension->LockCount || - (InterlockedDecrement(&deviceExtension->LockCount) != 0)) { - - DebugPrint((1, - "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n", - deviceExtension->LockCount, - deviceExtension->DeviceNumber)); - - // - // Don't unlock because someone still wants it locked. - // - - Irp->IoStatus.Status = STATUS_SUCCESS; - ExFreePool(srb); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - status = STATUS_SUCCESS; - goto SetStatusAndReturn; - } - - DebugPrint((1, - "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n", - deviceExtension->LockCount, - deviceExtension->DeviceNumber)); - } - - srb->CdbLength = 6; - - cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL; - - // - // TRUE - prevent media removal. - // FALSE - allow media removal. - // - - cdb->MEDIA_REMOVAL.Prevent = MediaRemoval->PreventMediaRemoval; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - status = ScsiClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - - // - // Some devices will not support lock/unlock. - // Pretend that it worked. - // - - break; - } - - case IOCTL_DISK_RESERVE: { - - // - // Reserve logical unit. - // - - srb->CdbLength = 6; - - cdb->CDB6GENERIC.OperationCode = SCSIOP_RESERVE_UNIT; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - - status = ScsiClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - - break; - } - - case IOCTL_DISK_RELEASE: { - - // - // Release logical unit. - // - - srb->CdbLength = 6; - - cdb->CDB6GENERIC.OperationCode = SCSIOP_RELEASE_UNIT; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - - status = ScsiClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - - break; - } - - case IOCTL_DISK_EJECT_MEDIA: { - - // - // Eject media. - // - - srb->CdbLength = 6; - - cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb->START_STOP.LoadEject = 1; - cdb->START_STOP.Start = 0; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - status = ScsiClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - break; - } - - case IOCTL_DISK_LOAD_MEDIA: { - - // - // Load media. - // - - DebugPrint((3,"CdRomDeviceControl: Load media\n")); - - srb->CdbLength = 6; - - cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; - cdb->START_STOP.LoadEject = 1; - cdb->START_STOP.Start = 1; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - status = ScsiClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - - break; - } - - case IOCTL_DISK_FIND_NEW_DEVICES: { - - // - // Search for devices that have been powered on since the last - // device search or system initialization. - // - - DebugPrint((3,"CdRomDeviceControl: Find devices\n")); - status = DriverEntry(DeviceObject->DriverObject, - NULL); - - Irp->IoStatus.Status = status; - ExFreePool(srb); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - break; - } - - default: { - - DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n")); - - // - // Pass the device control to the next driver. - // - - ExFreePool(srb); - - // - // Copy the Irp stack parameters to the next stack location. - // - - nextStack = IoGetNextIrpStackLocation(Irp); - nextStack->Parameters = irpStack->Parameters; - nextStack->MajorFunction = irpStack->MajorFunction; - nextStack->MinorFunction = irpStack->MinorFunction; - - status = IoCallDriver(deviceExtension->PortDeviceObject, Irp); - break; - } - - } // end switch( ... - -SetStatusAndReturn: - - return status; -} - - -NTSTATUS -NTAPI -ScsiClassShutdownFlush( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This routine is called for a shutdown and flush IRPs. These are sent by the - system before it actually shuts down or when the file system does a flush. - If it exists, the device-specific driver's routine will be invoked. If there - wasn't one specified, the Irp will be completed with an Invalid device request. - -Arguments: - - DriverObject - Pointer to device object to being shutdown by system. - - Irp - IRP involved. - -Return Value: - - NT Status - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - if (deviceExtension->ClassShutdownFlush) { - - // - // Call the device-specific driver's routine. - // - - return deviceExtension->ClassShutdownFlush(DeviceObject, Irp); - } - - // - // Device-specific driver doesn't support this. - // - - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_INVALID_DEVICE_REQUEST; -} - - -ULONG -NTAPI -ScsiClassFindUnclaimedDevices( - IN PCLASS_INIT_DATA InitializationData, - IN PSCSI_ADAPTER_BUS_INFO AdapterInformation - ) - -{ - ULONG scsiBus,deviceCount = 0; - PCHAR buffer = (PCHAR)AdapterInformation; - PSCSI_INQUIRY_DATA lunInfo; - PINQUIRYDATA inquiryData; - - for (scsiBus=0; scsiBus < (ULONG)AdapterInformation->NumberOfBuses; scsiBus++) { - - // - // Get the SCSI bus scan data for this bus. - // - - lunInfo = (PVOID) (buffer + AdapterInformation->BusData[scsiBus].InquiryDataOffset); - - // - // Search list for unclaimed disk devices. - // - - while (AdapterInformation->BusData[scsiBus].InquiryDataOffset) { - - inquiryData = (PVOID)lunInfo->InquiryData; - - ASSERT(InitializationData->ClassFindDeviceCallBack); - - if ((InitializationData->ClassFindDeviceCallBack(inquiryData)) && (!lunInfo->DeviceClaimed)) { - - deviceCount++; - } - - if (lunInfo->NextInquiryDataOffset == 0) { - break; - } - - lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset); - } - } - return deviceCount; -} - - - -NTSTATUS -NTAPI -ScsiClassCreateDeviceObject( - IN PDRIVER_OBJECT DriverObject, - IN PCCHAR ObjectNameBuffer, - IN OPTIONAL PDEVICE_OBJECT PhysicalDeviceObject, - IN OUT PDEVICE_OBJECT *DeviceObject, - IN PCLASS_INIT_DATA InitializationData - ) - -/*++ - -Routine Description: - - This routine creates an object for the physical device specified and - sets up the deviceExtension's function pointers for each entry point - in the device-specific driver. - -Arguments: - - DriverObject - Pointer to driver object created by system. - - ObjectNameBuffer - Dir. name of the object to create. - - PhysicalDeviceObject - Pointer to the physical (class) device object for - this logical unit or NULL if this is it. - - DeviceObject - Pointer to the device object pointer we will return. - - InitializationData - Pointer to the init data created by the device-specific driver. - -Return Value: - - NTSTATUS - ---*/ - -{ - STRING ntNameString; - UNICODE_STRING ntUnicodeString; - NTSTATUS status; - PDEVICE_OBJECT deviceObject = NULL; - - *DeviceObject = NULL; - - DebugPrint((2, - "ScsiClassCreateDeviceObject: Create device object %s\n", - ObjectNameBuffer)); - - RtlInitString(&ntNameString, - ObjectNameBuffer); - - status = RtlAnsiStringToUnicodeString(&ntUnicodeString, - &ntNameString, - TRUE); - - if (!NT_SUCCESS(status)) { - - DebugPrint((1, - "CreateDiskDeviceObjects: Cannot convert string %s\n", - ObjectNameBuffer)); - - ntUnicodeString.Buffer = NULL; - return status; - } - - status = IoCreateDevice(DriverObject, - InitializationData->DeviceExtensionSize, - &ntUnicodeString, - InitializationData->DeviceType, - InitializationData->DeviceCharacteristics, - FALSE, - &deviceObject); - - - if (!NT_SUCCESS(status)) { - - DebugPrint((1, - "CreateDiskDeviceObjects: Can not create device object %s\n", - ObjectNameBuffer)); - - } else { - - PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Fill in entry points - // - - deviceExtension->ClassError = InitializationData->ClassError; - deviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification; - deviceExtension->ClassFindDevices = InitializationData->ClassFindDevices; - deviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl; - deviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush; - deviceExtension->ClassCreateClose = InitializationData->ClassCreateClose; - deviceExtension->ClassStartIo = InitializationData->ClassStartIo; - - deviceExtension->MediaChangeCount = 0; - - // - // If a pointer to the physical device object was passed in then use - // that. If the value was NULL, then this is the physical device so - // use the pointer to the device we just created. - // - - if(ARGUMENT_PRESENT(PhysicalDeviceObject)) { - deviceExtension->PhysicalDevice = PhysicalDeviceObject; - } else { - deviceExtension->PhysicalDevice = deviceObject; - } - - deviceExtension->DeviceName = ntUnicodeString; - } - - deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - *DeviceObject = deviceObject; - - return status; -} - - -NTSTATUS -NTAPI -ScsiClassClaimDevice( - IN PDEVICE_OBJECT PortDeviceObject, - IN PSCSI_INQUIRY_DATA LunInfo, - IN BOOLEAN Release, - OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL - ) -/*++ - -Routine Description: - - This function claims a device in the port driver. The port driver object - is updated with the correct driver object if the device is successfully - claimed. - -Arguments: - - PortDeviceObject - Supplies the base port device object. - - LunInfo - Supplies the logical unit inforamtion of the device to be claimed. - - Release - Indicates the logical unit should be released rather than claimed. - - NewPortDeviceObject - Returns the updated port device object to be used - for all future accesses. - -Return Value: - - Returns a status indicating success or failure of the operation. - ---*/ - -{ - IO_STATUS_BLOCK ioStatus; - PIRP irp; - PIO_STACK_LOCATION irpStack; - KEVENT event; - NTSTATUS status; - SCSI_REQUEST_BLOCK srb; - - PAGED_CODE(); - - if (NewPortDeviceObject != NULL) { - *NewPortDeviceObject = NULL; - } - - // - // Clear the SRB fields. - // - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // - // Write length to SRB. - // - - srb.Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set SCSI bus address. - // - - srb.PathId = LunInfo->PathId; - srb.TargetId = LunInfo->TargetId; - srb.Lun = LunInfo->Lun; - - srb.Function = Release ? SRB_FUNCTION_RELEASE_DEVICE : - SRB_FUNCTION_CLAIM_DEVICE; - - // - // Set the event object to the unsignaled state. - // It will be used to signal request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Build synchronous request with no transfer. - // - - irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE, - PortDeviceObject, - NULL, - 0, - NULL, - 0, - TRUE, - &event, - &ioStatus); - - if (irp == NULL) { - - DebugPrint((1, "ScsiClassClaimDevice: Can't allocate Irp\n")); - return STATUS_INSUFFICIENT_RESOURCES; - } - - irpStack = IoGetNextIrpStackLocation(irp); - - // - // Save SRB address in next stack for port driver. - // - - irpStack->Parameters.Scsi.Srb = &srb; - - // - // Set up IRP Address. - // - - srb.OriginalRequest = irp; - - // - // Call the port driver with the request and wait for it to complete. - // - - status = IoCallDriver(PortDeviceObject, irp); - if (status == STATUS_PENDING) { - - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - // - // If this is a release request, then just decrement the reference count - // and return. The status does not matter. - // - - if (Release) { - - //ObDereferenceObject(PortDeviceObject); - return STATUS_SUCCESS; - } - - if (!NT_SUCCESS(status)) { - return status; - } - - ASSERT(srb.DataBuffer != NULL); - - // - // Reference the new port driver object so that it will not go away while - // it is being used. - // - - status = ObReferenceObjectByPointer(srb.DataBuffer, - 0, - NULL, - KernelMode ); - - if (!NT_SUCCESS(status)) { - - return status; - } - ObDereferenceObject(srb.DataBuffer); - - // - // Return the new port device object pointer. - // - - if (NewPortDeviceObject != NULL) { - *NewPortDeviceObject = srb.DataBuffer; - } - - return status; -} - - -NTSTATUS -NTAPI -ScsiClassInternalIoControl ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This routine passes internal device controls to the port driver. - Internal device controls are used by higher level class drivers to - send scsi requests to a device that are not normally sent by a generic - class driver. - - The path ID, target ID and logical unit ID are set in the srb so the - higher level driver does not have to figure out what values are actually - used. - -Arguments: - - DeviceObject - Supplies a pointer to the device object for this request. - - Irp - Supplies the Irp making the request. - -Return Value: - - Returns back a STATUS_PENDING or a completion status. - ---*/ -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PSCSI_REQUEST_BLOCK srb; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - - // - // Get a pointer to the SRB. - // - - srb = irpStack->Parameters.Scsi.Srb; - - // - // Set SCSI bus address. - // - - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - - // - // NOTICE: The SCSI-II specification indicates that this field should be - // zero; however, some target controllers ignore the logical unit number - // in the IDENTIFY message and only look at the logical unit number field - // in the CDB. - // - - srb->Cdb[1] |= deviceExtension->Lun << 5; - - // - // Set the parameters in the next stack location. - // - - irpStack = IoGetNextIrpStackLocation(Irp); - - irpStack->Parameters.Scsi.Srb = srb; - irpStack->MajorFunction = IRP_MJ_SCSI; - irpStack->MinorFunction = IRP_MN_SCSI_CLASS; - - IoSetCompletionRoutine(Irp, ClassIoCompletion, NULL, TRUE, TRUE, TRUE); - return IoCallDriver(deviceExtension->PortDeviceObject, Irp); -} - -NTSTATUS -NTAPI -ClassIoCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is called when an internal device control I/O request - has completed. It marks the IRP pending if necessary and returns the - status of the request. - -Arguments: - - DeviceObject - Target device object. - - Irp - Completed request. - - Context - not used. - -Return Value: - - Returns the status of the completed request. - ---*/ - -{ - UNREFERENCED_PARAMETER(Context); - UNREFERENCED_PARAMETER(DeviceObject); - - // - // If pending is returned for this Irp then mark current stack - // as pending - // - - if (Irp->PendingReturned) { - - IoMarkIrpPending( Irp ); - } - - return Irp->IoStatus.Status; -} - - -VOID -NTAPI -ScsiClassInitializeSrbLookasideList( - IN PDEVICE_EXTENSION DeviceExtension, - IN ULONG NumberElements - ) - -/*++ - -Routine Description: - - This routine sets up a lookaside listhead for srbs. - -Arguments: - - DeviceExtension - Pointer to the deviceExtension containing the listhead. - - NumberElements - Supplies the maximum depth of the lookaside list. - - -Return Value: - - None - ---*/ - -{ - ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead, - NULL, - NULL, - NonPagedPoolMustSucceed, - SCSI_REQUEST_BLOCK_SIZE, - 'HscS', - (USHORT)NumberElements); - -} - - -ULONG -NTAPI -ScsiClassQueryTimeOutRegistryValue( - IN PUNICODE_STRING RegistryPath - ) - -/*++ - -Routine Description: - - This routine determines whether a reg key for a user-specified timeout value exists. - -Arguments: - - RegistryPath - Pointer to the hardware reg. entry describing the key. - -Return Value: - - New default timeout for a class of devices. - ---*/ - -{ - // - // Find the appropriate reg. key - // - - PRTL_QUERY_REGISTRY_TABLE parameters = NULL; - PWSTR path; - NTSTATUS status; - LONG timeOut = 0; - ULONG zero = 0; - ULONG size; - - if (!RegistryPath) { - return 0; - } - - parameters = ExAllocatePool(NonPagedPool, - sizeof(RTL_QUERY_REGISTRY_TABLE)*2); - - if (!parameters) { - return 0; - } - - size = RegistryPath->MaximumLength + sizeof(WCHAR); - path = ExAllocatePool(NonPagedPool, size); - - if (!path) { - ExFreePool(parameters); - return 0; - } - - RtlZeroMemory(path,size); - RtlCopyMemory(path, RegistryPath->Buffer, size - sizeof(WCHAR)); - - - // - // Check for the Timeout value. - // - - RtlZeroMemory(parameters, - (sizeof(RTL_QUERY_REGISTRY_TABLE)*2)); - - parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - parameters[0].Name = L"TimeOutValue"; - parameters[0].EntryContext = &timeOut; - parameters[0].DefaultType = REG_DWORD; - parameters[0].DefaultData = &zero; - parameters[0].DefaultLength = sizeof(ULONG); - - status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, - path, - parameters, - NULL, - NULL); - - if (!(NT_SUCCESS(status))) { - timeOut = 0; - } - - ExFreePool(parameters); - ExFreePool(path); - - DebugPrint((2, - "ScsiClassQueryTimeOutRegistryValue: Timeout value %d\n", - timeOut)); - - - return timeOut; - -} - -NTSTATUS -NTAPI -ScsiClassCheckVerifyComplete( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine executes when the port driver has completed a check verify - ioctl. It will set the status of the master Irp, copy the media change - count and complete the request. - -Arguments: - - DeviceObject - Supplies the device object which represents the logical - unit. - - Irp - Supplies the Irp which has completed. - - Context - NULL - -Return Value: - - NT status - ---*/ - -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PDEVICE_EXTENSION physicalExtension = - deviceExtension->PhysicalDevice->DeviceExtension; - PIRP originalIrp; - - ASSERT(*(PULONG)deviceExtension != '2slc'); - ASSERT(*(PULONG)physicalExtension != '2slc'); - - originalIrp = irpStack->Parameters.Others.Argument1; - - // - // Copy the media change count and status - // - - *((PULONG) (originalIrp->AssociatedIrp.SystemBuffer)) = - physicalExtension->MediaChangeCount; - - DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change count for" - "device %d is %d\n", - physicalExtension->DeviceNumber, - physicalExtension->MediaChangeCount)); - - originalIrp->IoStatus.Status = Irp->IoStatus.Status; - originalIrp->IoStatus.Information = sizeof(ULONG); - - IoCompleteRequest(originalIrp, IO_DISK_INCREMENT); - - IoFreeIrp(Irp); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context) -{ - PIO_STATUS_BLOCK IoStatusBlock = Irp->UserIosb; - PKEVENT Event = Irp->UserEvent; - PMDL Mdl; - - *IoStatusBlock = Irp->IoStatus; - Irp->UserIosb = NULL; - Irp->UserEvent = NULL; - - if(Irp->MdlAddress) - { - Mdl = Irp->MdlAddress; - - // if necessary - unlock pages - if ((Mdl->MdlFlags & MDL_PAGES_LOCKED) && - !(Mdl->MdlFlags & MDL_PARTIAL_HAS_BEEN_MAPPED)) - { - MmUnlockPages(Mdl); - } - - // free this mdl - IoFreeMdl(Mdl); - } - - // free irp and set event to unsignaled state - IoFreeIrp(Irp); - KeSetEvent(Event, IO_NO_INCREMENT, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} diff --git a/drivers/storage/class/class2/class2.rc b/drivers/storage/class/class2/class2.rc deleted file mode 100644 index 738ceaae602..00000000000 --- a/drivers/storage/class/class2/class2.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "SCSI Class Driver Helper" -#define REACTOS_STR_INTERNAL_NAME "class2" -#define REACTOS_STR_ORIGINAL_FILENAME "class2.sys" -#include diff --git a/drivers/storage/class/class2/class2.spec b/drivers/storage/class/class2/class2.spec deleted file mode 100644 index ae6bf608d95..00000000000 --- a/drivers/storage/class/class2/class2.spec +++ /dev/null @@ -1,22 +0,0 @@ -@ stdcall ScsiClassAsynchronousCompletion(ptr ptr ptr) -@ stdcall ScsiClassBuildRequest(ptr ptr) -@ stdcall ScsiClassClaimDevice(ptr ptr long ptr) -@ stdcall ScsiClassCreateDeviceObject(ptr ptr ptr ptr ptr) -@ stdcall ScsiClassDeviceControl(ptr ptr) -@ stdcall ScsiClassFindModePage(ptr long long long) -@ stdcall ScsiClassFindUnclaimedDevices(ptr ptr) -@ stdcall ScsiClassGetCapabilities(ptr ptr) -@ stdcall ScsiClassGetInquiryData(ptr ptr) -@ stdcall ScsiClassInitialize(ptr ptr ptr) -@ stdcall ScsiClassInitializeSrbLookasideList(ptr long) -@ stdcall ScsiClassInternalIoControl(ptr ptr) -@ stdcall ScsiClassInterpretSenseInfo(ptr ptr long long long long) -@ stdcall ScsiClassIoComplete(ptr ptr ptr) -@ stdcall ScsiClassIoCompleteAssociated(ptr ptr ptr) -@ stdcall ScsiClassModeSense(ptr ptr long long) -@ stdcall ScsiClassQueryTimeOutRegistryValue(ptr) -@ stdcall ScsiClassReadDriveCapacity(ptr) -@ stdcall ScsiClassReleaseQueue(ptr) -@ stdcall ScsiClassSendSrbAsynchronous(ptr ptr ptr ptr long long) -@ stdcall ScsiClassSendSrbSynchronous(ptr ptr ptr long long) -@ stdcall ScsiClassSplitRequest(ptr ptr long) diff --git a/drivers/storage/class/class2/license.txt b/drivers/storage/class/class2/license.txt deleted file mode 100644 index 28ba760a5ad..00000000000 --- a/drivers/storage/class/class2/license.txt +++ /dev/null @@ -1,53 +0,0 @@ -Window NT Device Driver Kit -END-USER LICENSE AGREEMENT FOR MICROSOFT SOFTWARE - -IMPORTANT-READ CAREFULLY: This Microsoft End-User License Agreement ("EULA") is a legal agreement between you (either an individual or a single entity) and Microsoft Corporation for the Microsoft software product identified above, which includes computer software and associated media and printed materials, and may include "online" or electronic documentation ("SOFTWARE PRODUCT" or "SOFTWARE"). By installing, copying, or otherwise using the SOFTWARE PRODUCT, you agree to be bound by the terms of this EULA. If you do not agree to the terms of this EULA, promptly return the unused SOFTWARE PRODUCT to the place from which you obtained it for a full refund, or if you received the SOFTWARE PRODUCT as part of a subscription or other service from Microsoft, you may cancel the subscription and receive a refund of a prorata portion of the subscription price. - -SOFTWARE PRODUCT LICENSE -The SOFTWARE PRODUCT is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. The SOFTWARE PRODUCT is licensed, not sold. To develop Windows NT(tm) device drivers, you will need to utilize two computers, one for development and one for debugging. - -1. GRANT OF LICENSE. This EULA grants you the following limited, non-exclusive rights: -* SOFTWARE PRODUCT. (a) You may make two (2) copies of the SOFTWARE PRODUCT for installation and use on two (2) computers, one for use in development and one for use in debugging to design, develop, and test your software product(s), including but not limited to device driver(s) and other software products, for use with Microsoft(r) Windows(r) or Windows NT ("Software Product"). You may make an additional copy of the Windows NT Workstation operating system (licensed and provided separately) for use on a single computer used for debugging purposes. -* Microsoft Developer Network Subscriber. If you acquired the SOFTWARE PRODUCT through a subscription to the Microsoft Developer Network, and you are either an individual developer or an individual designated within a single entity, you are granted the following additional rights with respect to the SOFTWARE PRODUCT: (a) you may make and use copies of the SOFTWARE PRODUCT on up to ten (10) separate computers, provided that you are the only individual using the SOFTWARE PRODUCT on each such computer, and (b) if you are a single entity, you may designate one individual within your organization to have the right to use the SOFTWARE PRODUCT in the manner described herein. -* SAMPLE CODE. You may modify the sample source code ("Sample Code") to design, develop and test your Software Product, and reproduce and distribute the Sample Code with such modifications in source and object code forms, provided that you comply with the Distribution Requirements described below. -* DISTRIBUTION REQUIREMENTS. You may copy and redistribute the Sample Code as described above, provided that (a) you distribute the Sample Code only in conjunction with and as a part of your Software Product; (b) you do not make any statements to the effect or which imply that your Software Product is "certified" by Microsoft or that its performance is guaranteed by Microsoft; (c) you do not use Microsoft's name, logo, or trademarks to market your Software Product; (d) you include a valid copyright notice on your Software Product; and (e) you indemnify, hold harmless, and defend Microsoft from and against any claims or lawsuits, including attorneys' fees, that arise or result from the use or distribution of your Software Product. Contact Microsoft for the applicable royalties due and other licensing terms for all other uses and/or distribution of the Sample Code -* Microsoft reserves all rights not expressly granted to you. - -2. COPYRIGHT. All right, title, and copyrights in and to the SOFTWARE PRODUCT (including but not limited to any images, photographs, animations, video, audio, music, text, and "applets" incorporated into the SOFTWARE PRODUCT), and any copies of the SOFTWARE PRODUCT, are owned by Microsoft or its suppliers. The SOFTWARE PRODUCT is protected by copyright laws and international treaty provisions. Therefore, you must treat the SOFTWARE PRODUCT like any other copyrighted material except that you may either (a) make one copy of the SOFTWARE PRODUCT solely for backup or archival purposes, or (b) install the SOFTWARE PRODUCT on a single computer, provided you keep the original solely for backup or archival purposes. You may not copy the printed materials accompanying the SOFTWARE PRODUCT. - -3. PRERELEASE CODE. The SOFTWARE PRODUCT may contain PRERELEASE CODE that is not at the level of performance and compatibility of the final, generally available, product offering. These portions of the SOFTWARE PRODUCT may not operate correctly and may be substantially modified prior to first commercial shipment. Microsoft is not obligated to make this or any later version of the SOFTWARE PRODUCT commercially available. Microsoft grants you the right to distribute test versions of your Application created using the PRERELEASE CODE provided you comply with the Distribution Requirements described in Section 1 and the following additional provisions: (a) you must mark the test version of your Application "BETA" and (b) you are solely responsible for updating your customers with versions of your Application that operate satisfactorily with the final commercial release of the PRERELEASE CODE. - -4. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS. -( Limitations on Reverse Engineering, Decompilation, and Disassembly. You may not reverse-engineer, decompile, or disassemble the SOFTWARE PRODUCT, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation. -( Rental. You may not rent or lease the SOFTWARE PRODUCT. -( Software Transfer. You may permanently transfer all of your rights under this EULA, provided you retain no copies, you transfer all of the SOFTWARE PRODUCT (including all component parts, the media and printed materials, any upgrades, this EULA, and, if applicable, the Certificate of Authenticity), and the recipient agrees to the terms of this EULA. If the SOFTWARE PRODUCT is an upgrade, any transfer must include all prior versions of the SOFTWARE PRODUCT. -( Termination. Without prejudice to any other rights, Microsoft may terminate this EULA if you fail to comply with the terms and conditions of this EULA. In such event, you must destroy all copies of the SOFTWARE PRODUCT and all of its component parts. - -5. EXPORT RESTRICTIONS. You agree that neither you nor your customers intend to or will, directly or indirectly, export or transmit (a) the SOFTWARE PRODUCT or related documentation and technical data or (b) your Application as described in Section 1 of this Agreement (or any part thereof), or process, or service that is the direct product of the SOFTWARE PRODUCT to any country to which such export or transmission is restricted by any applicable U.S. regulation or statute, without the prior written consent, if required, of the Bureau of Export Administration of the U.S. Department of Commerce, or such other governmental entity as may have jurisdiction over such export or transmission. - -NO WARRANTIES. To the maximum extent permitted by applicable law, Microsoft expressly disclaims any warranty for the SOFTWARE PRODUCT. The SOFTWARE PRODUCT and any related documentation are provided "as is" without warranty of any kind, either express or implied, including, without limitation, the implied warranties of merchantability or fitness for a particular purpose. The entire risk arising out of use or performance of the SOFTWARE PRODUCT remains with you. - -LIMITATION OF LIABILITY. Microsoft's entire liability and your exclusive remedy under this EULA shall not exceed one hundred dollars (US$100.00). - -NO LIABILITY FOR CONSEQUENTIAL DAMAGES. To the maximum extent permitted by applicable law, in no event shall Microsoft or its suppliers be liable for any damages whatsoever (including, without limitation, damages for loss of business profit, business interruption, loss of business information, or any other pecuniary loss) arising out of the use or inability to use this Microsoft product, even if Microsoft has been advised of the possibility of such damages. Because some states/jurisdictions do not allow the exclusion or limitation of liability for consequential or incidental damages, the above limitation may not apply to you. - -U.S. GOVERNMENT RESTRICTED RIGHTS.The SOFTWARE and documentation are provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and (2) of the Commercial Computer Software -- Restricted Rights at 48 CFR 52.227-19, as applicable. Manufacturer is Microsoft Corporation/One Microsoft Way/Redmond, WA 98052-6399. - -If you acquired this product in the United States, this Agreement is governed by the laws of the State of Washington. If you acquired this product outside the United States, local law may apply. - -Should you have any questions concerning this Agreement, if you desire rights to use the product beyond what is listed here, or if you desire to contact Microsoft for any reason, please contact your local Microsoft subsidiary or sales office or write to: Microsoft Sales and Service, One Microsoft Way, Redmond, WA 98052-6399. - -Si vous avez acquis votre produit Microsoft au CANADA, la garantie limite suivante vous concerne : - -GARANTIE LIMITE - -EXCLUSION DE GARANTIES. Microsoft renonce entirement toute garantie pour le LOGICIEL. Le LOGICIEL et toute autre documentation s'y rapportant sont fournis comme tels sans aucune garantie quelle qu'elle soit, expresse ou implicite, y compris, mais ne se limitant pas, aux garanties implicites de la qualit marchande ou un usage particulier. Le risque total dcoulant de l'utilisation ou de la performance du LOGICIEL est entre vos mains. - -RESPONSABILIT LIMITE. La seule obligation de Microsoft et votre recours exclusif concernant ce contrat n'excderont pas cent dollars (US$100.00). - -ABSENCE DE RESPONSABILIT POUR LES DOMMAGES INDIRECTS. Microsoft ou ses fournisseurs ne pourront tre tenus responsables en aucune circonstance de tout dommage quel qu'il soit (y compris mais non de faon limitative aux dommages directs ou indirects causs par la perte de bnfices commerciaux, l'interruption des affaires, la perte d'information commerciale ou toute autre perte pcuniaire) rsultant de l'utilisation ou de l'impossibilit d'utilisation de ce produit, et ce, mme si la socit Microsoft a t avise de l'ventualit de tels dommages. Certains tats/juridictions ne permettent pas l'exclusion ou la limitation de responsabilit relative aux dommages indirects ou conscutifs, et la limitation ci-dessus peut ne pas s'appliquer votre gard. - -La prsente Convention est rgie par les lois de la province d'Ontario, Canada. Chacune des parties la prsente reconnat irrvocablement la comptence des tribunaux de la province d'Ontario et consent instituer tout litige qui pourrait dcouler de la prsente auprs des tribunaux situs dans le district judiciaire de York, province d'Ontario. - -Au cas o vous auriez des questions concernant cette licence ou que vous dsiriez vous mettre en rapport avec Microsoft pour quelque raison que ce soit, veuillez contacter la succursale Microsoft desservant votre pays, dont l'adresse est fournie dans ce produit, ou crire : Microsoft Customer Sales and Service, One Microsoft Way, Redmond, Washington 98052-6399. - diff --git a/drivers/storage/class/disk/CMakeLists.txt b/drivers/storage/class/disk/CMakeLists.txt deleted file mode 100644 index eb2ff3fef4f..00000000000 --- a/drivers/storage/class/disk/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ - -include_directories(..) -add_library(disk MODULE disk.c disk.rc) -set_module_type(disk kernelmodedriver) -add_importlibs(disk class2 scsiport ntoskrnl hal) -add_cd_file(TARGET disk DESTINATION reactos/system32/drivers NO_CAB FOR all) -add_registry_inf(disk_reg.inf) -add_driver_inf(disk disk.inf) diff --git a/drivers/storage/class/disk/disk.c b/drivers/storage/class/disk/disk.c deleted file mode 100644 index 36df2d5e220..00000000000 --- a/drivers/storage/class/disk/disk.c +++ /dev/null @@ -1,5440 +0,0 @@ -/* - * PROJECT: ReactOS Storage Stack - * LICENSE: DDK - see license.txt in the root dir - * FILE: drivers/storage/disk/disk.c - * PURPOSE: Disk class driver - * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - - -#ifdef POOL_TAGGING -#ifdef ExAllocatePool -#undef ExAllocatePool -#endif -#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'DscS') -#endif - -typedef enum { - NotInitialized, - Initializing, - Initialized -} PARTITION_LIST_STATE; - -// -// Disk device data -// - -typedef struct _DISK_DATA { - - // - // Partition chain - // - - PDEVICE_EXTENSION NextPartition; - - // - // Disk signature (from MBR) - // - - ULONG Signature; - - // - // MBR checksum - // - - ULONG MbrCheckSum; - - // - // Number of hidden sectors for BPB. - // - - ULONG HiddenSectors; - - // - // Partition number of this device object - // - // This field is set during driver initialization or when the partition - // is created to identify a partition to the system. - // - - ULONG PartitionNumber; - - // - // This field is the ordinal of a partition as it appears on a disk. - // - - ULONG PartitionOrdinal; - - // - // Partition type of this device object - // - // This field is set by: - // - // 1) Initially set according to the partition list entry partition - // type returned by IoReadPartitionTable. - // - // 2) Subsequently set by the IOCTL_DISK_SET_PARTITION_INFORMATION - // I/O control function when IoSetPartitionInformation function - // successfully updates the partition type on the disk. - // - - UCHAR PartitionType; - - // - // Boot indicator - indicates whether this partition is a bootable (active) - // partition for this device - // - // This field is set according to the partition list entry boot indicator - // returned by IoReadPartitionTable. - // - - BOOLEAN BootIndicator; - - // - // DriveNotReady - indicates that the this device is currently not ready - // because there is no media in the device. - // - - BOOLEAN DriveNotReady; - - // - // State of PartitionList initialization - // - - PARTITION_LIST_STATE PartitionListState; - -#ifdef __REACTOS__ - // - // HACK so that we can use NT5+ NTOS functions with this NT4 driver - // for removable devices and avoid an infinite recursive loop between - // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable(). - // - ULONG UpdateRemovableGeometryCount; -#endif - -} DISK_DATA, *PDISK_DATA; - -// -// Define a general structure of identifying disk controllers with bad -// hardware. -// - -typedef struct _BAD_CONTROLLER_INFORMATION { - PCHAR InquiryString; - BOOLEAN DisableTaggedQueuing; - BOOLEAN DisableSynchronousTransfers; - BOOLEAN DisableDisconnects; - BOOLEAN DisableWriteCache; -}BAD_CONTROLLER_INFORMATION, *PBAD_CONTROLLER_INFORMATION; - -BAD_CONTROLLER_INFORMATION const ScsiDiskBadControllers[] = { - { "TOSHIBA MK538FB 60", TRUE, FALSE, FALSE, FALSE }, - { "CONNER CP3500", FALSE, TRUE, FALSE, FALSE }, - { "OLIVETTICP3500", FALSE, TRUE, FALSE, FALSE }, - { "SyQuest SQ5110 CHC", TRUE, TRUE, FALSE, FALSE }, - { "SEAGATE ST41601N 0102", FALSE, TRUE, FALSE, FALSE }, - { "SEAGATE ST3655N", FALSE, FALSE, FALSE, TRUE }, - { "SEAGATE ST3390N", FALSE, FALSE, FALSE, TRUE }, - { "SEAGATE ST12550N", FALSE, FALSE, FALSE, TRUE }, - { "SEAGATE ST32430N", FALSE, FALSE, FALSE, TRUE }, - { "SEAGATE ST31230N", FALSE, FALSE, FALSE, TRUE }, - { "SEAGATE ST15230N", FALSE, FALSE, FALSE, TRUE }, - { "FUJITSU M2652S-512", TRUE, FALSE, FALSE, FALSE }, - { "MAXTOR MXT-540SL I1.2", TRUE, FALSE, FALSE, FALSE }, - { "COMPAQ PD-1", FALSE, TRUE, FALSE, FALSE } -}; - - -#define NUMBER_OF_BAD_CONTROLLERS (sizeof(ScsiDiskBadControllers) / sizeof(BAD_CONTROLLER_INFORMATION)) -#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA) - -#define MODE_DATA_SIZE 192 -#define VALUE_BUFFER_SIZE 2048 -#define SCSI_DISK_TIMEOUT 10 -#define PARTITION0_LIST_SIZE 4 - - -NTSTATUS -NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ); - -BOOLEAN -NTAPI -ScsiDiskDeviceVerification( - IN PINQUIRYDATA InquiryData - ); - -BOOLEAN -NTAPI -FindScsiDisks( - IN PDRIVER_OBJECT DriveObject, - IN PUNICODE_STRING RegistryPath, - IN PCLASS_INIT_DATA InitializationData, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber - ); - -NTSTATUS -NTAPI -ScsiDiskCreateClose ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiDiskReadWriteVerification( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -ScsiDiskDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -NTAPI -ScsiDiskProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ); - -NTSTATUS -NTAPI -ScsiDiskShutdownFlush( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -NTAPI -DisableWriteCache( - IN PDEVICE_OBJECT DeviceObject, - IN PSCSI_INQUIRY_DATA LunInfo - ); - -BOOLEAN -NTAPI -ScsiDiskModeSelect( - IN PDEVICE_OBJECT DeviceObject, - IN PCHAR ModeSelectBuffer, - IN ULONG Length, - IN BOOLEAN SavePage - ); - -BOOLEAN -NTAPI -IsFloppyDevice( - IN PDEVICE_OBJECT DeviceObject - ); - -BOOLEAN -NTAPI -CalculateMbrCheckSum( - IN PDEVICE_EXTENSION DeviceExtension, - OUT PULONG Checksum - ); - -BOOLEAN -NTAPI -EnumerateBusKey( - IN PDEVICE_EXTENSION DeviceExtension, - HANDLE BusKey, - PULONG DiskNumber - ); - -VOID -NTAPI -UpdateGeometry( - IN PDEVICE_EXTENSION DeviceExtension - ); - -NTSTATUS -NTAPI -UpdateRemovableGeometry ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -NTAPI -CreateDiskDeviceObject( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber, - IN PULONG DeviceCount, - IN PIO_SCSI_CAPABILITIES PortCapabilities, - IN PSCSI_INQUIRY_DATA LunInfo, - IN PCLASS_INIT_DATA InitData - ); - -NTSTATUS -NTAPI -CreatePartitionDeviceObjects( - IN PDEVICE_OBJECT PhysicalDeviceObject, - IN PUNICODE_STRING RegistryPath - ); - -VOID -NTAPI -UpdateDeviceObjects( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -NTAPI -ScanForSpecial( - PDEVICE_OBJECT DeviceObject, - PSCSI_INQUIRY_DATA LunInfo, - PIO_SCSI_CAPABILITIES PortCapabilities - ); - -VOID -NTAPI -ResetScsiBus( - IN PDEVICE_OBJECT DeviceObject - ); - -NTSTATUS -NTAPI -ScsiDiskFileSystemControl(PDEVICE_OBJECT DeviceObject, - PIRP Irp); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGE, DriverEntry) -#pragma alloc_text(PAGE, FindScsiDisks) -#pragma alloc_text(PAGE, CreateDiskDeviceObject) -#pragma alloc_text(PAGE, CalculateMbrCheckSum) -#pragma alloc_text(PAGE, EnumerateBusKey) -#pragma alloc_text(PAGE, UpdateGeometry) -#pragma alloc_text(PAGE, IsFloppyDevice) -#pragma alloc_text(PAGE, ScanForSpecial) -#pragma alloc_text(PAGE, ScsiDiskDeviceControl) -#pragma alloc_text(PAGE, ScsiDiskModeSelect) -#endif - - -NTSTATUS -NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) - -/*++ - -Routine Description: - - This routine initializes the SCSI hard disk class driver. - -Arguments: - - DriverObject - Pointer to driver object created by system. - - RegistryPath - Pointer to the name of the services node for this driver. - -Return Value: - - The function value is the final status from the initialization operation. - ---*/ - -{ - CLASS_INIT_DATA InitializationData; - - // - // Zero InitData - // - - RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA)); - - // - // Set sizes - // - - InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA); - InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE; - - InitializationData.DeviceType = FILE_DEVICE_DISK; - InitializationData.DeviceCharacteristics = 0; - - // - // Set entry points - // - - InitializationData.ClassError = ScsiDiskProcessError; - InitializationData.ClassReadWriteVerification = ScsiDiskReadWriteVerification; - InitializationData.ClassFindDevices = FindScsiDisks; - InitializationData.ClassFindDeviceCallBack = ScsiDiskDeviceVerification; - InitializationData.ClassDeviceControl = ScsiDiskDeviceControl; - InitializationData.ClassShutdownFlush = ScsiDiskShutdownFlush; - InitializationData.ClassCreateClose = NULL; - - // - // Call the class init routine - // - - return ScsiClassInitialize( DriverObject, RegistryPath, &InitializationData); - -} // end DriverEntry() - - - -BOOLEAN -NTAPI -ScsiDiskDeviceVerification( - IN PINQUIRYDATA InquiryData - ) - -/*++ - -Routine Description: - - This routine checks InquiryData for the correct device type and qualifier. - -Arguments: - - InquiryData - Pointer to the inquiry data for the device in question. - -Return Value: - - True is returned if the correct device type is found. - ---*/ -{ - - if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) || - (InquiryData->DeviceType == OPTICAL_DEVICE)) && - InquiryData->DeviceTypeQualifier == 0) { - - return TRUE; - - } else { - return FALSE; - } -} - - -BOOLEAN -NTAPI -FindScsiDisks( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN PCLASS_INIT_DATA InitializationData, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber - ) - -/*++ - -Routine Description: - - This routine gets a port drivers capabilities, obtains the - inquiry data, searches the SCSI bus for the port driver and creates - the device objects for the disks found. - -Arguments: - - DriverObject - Pointer to driver object created by system. - - PortDeviceObject - Device object use to send requests to port driver. - - PortNumber - Number for port driver. Used to pass on to - CreateDiskDeviceObjects() and create device objects. - -Return Value: - - True is returned if one disk was found and successfully created. - ---*/ - -{ - PIO_SCSI_CAPABILITIES portCapabilities; - PULONG diskCount; - PCONFIGURATION_INFORMATION configurationInformation; - PCHAR buffer; - PSCSI_INQUIRY_DATA lunInfo; - PSCSI_ADAPTER_BUS_INFO adapterInfo; - PINQUIRYDATA inquiryData; - ULONG scsiBus; - ULONG adapterDisk; - NTSTATUS status; - BOOLEAN foundOne = FALSE; - - PAGED_CODE(); - - // - // Call port driver to get adapter capabilities. - // - - status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities); - - if (!NT_SUCCESS(status)) { - DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n")); - return(FALSE); - } - - // - // Call port driver to get inquiry information to find disks. - // - - status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer); - - if (!NT_SUCCESS(status)) { - DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n")); - return(FALSE); - } - - // - // Do a quick scan of the devices on this adapter to determine how many - // disks are on this adapter. This is used to determine the number of - // SRB zone elements to allocate. - // - - adapterInfo = (PVOID) buffer; - - adapterDisk = ScsiClassFindUnclaimedDevices(InitializationData, adapterInfo); - - // - // Allocate a zone of SRB for disks on this adapter. - // - - if (adapterDisk == 0) { - - // - // No free disks were found. - // - - return(FALSE); - } - - // - // Get the number of disks already initialized. - // - - configurationInformation = IoGetConfigurationInformation(); - diskCount = &configurationInformation->DiskCount; - - // - // For each SCSI bus this adapter supports ... - // - - for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) { - - // - // Get the SCSI bus scan data for this bus. - // - - lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset); - - // - // Search list for unclaimed disk devices. - // - - while (adapterInfo->BusData[scsiBus].InquiryDataOffset) { - - inquiryData = (PVOID)lunInfo->InquiryData; - - if (((inquiryData->DeviceType == DIRECT_ACCESS_DEVICE) || - (inquiryData->DeviceType == OPTICAL_DEVICE)) && - inquiryData->DeviceTypeQualifier == 0 && - (!lunInfo->DeviceClaimed)) { - - DebugPrint((1, - "FindScsiDevices: Vendor string is %.24s\n", - inquiryData->VendorId)); - - // - // Create device objects for disk - // - - status = CreateDiskDeviceObject(DriverObject, - RegistryPath, - PortDeviceObject, - PortNumber, - diskCount, - portCapabilities, - lunInfo, - InitializationData); - - if (NT_SUCCESS(status)) { - - // - // Increment system disk device count. - // - - (*diskCount)++; - foundOne = TRUE; - - } - } - - // - // Get next LunInfo. - // - - if (lunInfo->NextInquiryDataOffset == 0) { - break; - } - - lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset); - - } - } - - // - // Buffer is allocated by ScsiClassGetInquiryData and must be free returning. - // - - ExFreePool(buffer); - - return(foundOne); - -} // end FindScsiDisks() - - -NTSTATUS -NTAPI -CreateDiskDeviceObject( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber, - IN PULONG DeviceCount, - IN PIO_SCSI_CAPABILITIES PortCapabilities, - IN PSCSI_INQUIRY_DATA LunInfo, - IN PCLASS_INIT_DATA InitData - ) - -/*++ - -Routine Description: - - This routine creates an object for the physical device and then searches - the device for partitions and creates an object for each partition. - -Arguments: - - DriverObject - Pointer to driver object created by system. - - PortDeviceObject - Miniport device object. - - PortNumber - port number. Used in creating disk objects. - - DeviceCount - Number of previously installed devices. - - PortCapabilities - Capabilities of this SCSI port. - - LunInfo - LUN specific information. - -Return Value: - - NTSTATUS - ---*/ -{ - CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH]; - STRING ntNameString; - UNICODE_STRING ntUnicodeString; - OBJECT_ATTRIBUTES objectAttributes; - HANDLE handle; - NTSTATUS status; - PDEVICE_OBJECT deviceObject = NULL; - //PDEVICE_OBJECT physicalDevice; - PDISK_GEOMETRY_EX diskGeometry = NULL; - PDEVICE_EXTENSION deviceExtension = NULL; - //PDEVICE_EXTENSION physicalDeviceExtension; - UCHAR pathId = LunInfo->PathId; - UCHAR targetId = LunInfo->TargetId; - UCHAR lun = LunInfo->Lun; - //BOOLEAN writeCache; - PVOID senseData = NULL; - //ULONG srbFlags; - ULONG timeOut = 0; - BOOLEAN srbListInitialized = FALSE; - - - PAGED_CODE(); - - // - // Set up an object directory to contain the objects for this - // device and all its partitions. - // - - sprintf(ntNameBuffer, - "\\Device\\Harddisk%lu", - *DeviceCount); - - RtlInitString(&ntNameString, - ntNameBuffer); - - status = RtlAnsiStringToUnicodeString(&ntUnicodeString, - &ntNameString, - TRUE); - - if (!NT_SUCCESS(status)) { - return(status); - } - - InitializeObjectAttributes(&objectAttributes, - &ntUnicodeString, - OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, - NULL, - NULL); - - status = ZwCreateDirectoryObject(&handle, - DIRECTORY_ALL_ACCESS, - &objectAttributes); - - RtlFreeUnicodeString(&ntUnicodeString); - - if (!NT_SUCCESS(status)) { - - DebugPrint((1, - "CreateDiskDeviceObjects: Could not create directory %s\n", - ntNameBuffer)); - - return(status); - } - - // - // Claim the device. - // - - status = ScsiClassClaimDevice(PortDeviceObject, - LunInfo, - FALSE, - &PortDeviceObject); - - if (!NT_SUCCESS(status)) { - ZwMakeTemporaryObject(handle); - ZwClose(handle); - return status; - } - - // - // Create a device object for this device. Each physical disk will - // have at least one device object. The required device object - // describes the entire device. Its directory path is - // \Device\HarddiskN\Partition0, where N = device number. - // - - sprintf(ntNameBuffer, - "\\Device\\Harddisk%lu\\Partition0", - *DeviceCount); - - - status = ScsiClassCreateDeviceObject(DriverObject, - ntNameBuffer, - NULL, - &deviceObject, - InitData); - - if (!NT_SUCCESS(status)) { - - DebugPrint((1, - "CreateDiskDeviceObjects: Can not create device object %s\n", - ntNameBuffer)); - - goto CreateDiskDeviceObjectsExit; - } - - // - // Indicate that IRPs should include MDLs for data transfers. - // - - deviceObject->Flags |= DO_DIRECT_IO; - - // - // Check if this is during initialization. If not indicate that - // system initialization already took place and this disk is ready - // to be accessed. - // - - if (!RegistryPath) { - deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - } - - // - // Check for removable media support. - // - - if (((PINQUIRYDATA)LunInfo->InquiryData)->RemovableMedia) { - deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; - } - - // - // Set up required stack size in device object. - // - - deviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1; - - deviceExtension = deviceObject->DeviceExtension; - - // - // Allocate spinlock for split request completion. - // - - KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock); - - // - // Initialize lock count to zero. The lock count is used to - // disable the ejection mechanism on devices that support - // removable media. Only the lock count in the physical - // device extension is used. - // - - deviceExtension->LockCount = 0; - - // - // Save system disk number. - // - - deviceExtension->DeviceNumber = *DeviceCount; - - // - // Copy port device object pointer to the device extension. - // - - deviceExtension->PortDeviceObject = PortDeviceObject; - - // - // Set the alignment requirements for the device based on the - // host adapter requirements - // - - if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) { - deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement; - } - - // - // This is the physical device object. - // - - //physicalDevice = deviceObject; - //physicalDeviceExtension = deviceExtension; - - // - // Save address of port driver capabilities. - // - - deviceExtension->PortCapabilities = PortCapabilities; - - // - // Build the lookaside list for srb's for the physical disk. Should only - // need a couple. - // - - ScsiClassInitializeSrbLookasideList(deviceExtension, - PARTITION0_LIST_SIZE); - - srbListInitialized = TRUE; - - // - // Initialize the srb flags. - // - - if (((PINQUIRYDATA)LunInfo->InquiryData)->CommandQueue && - PortCapabilities->TaggedQueuing) { - - deviceExtension->SrbFlags = SRB_FLAGS_QUEUE_ACTION_ENABLE; - - } else { - - deviceExtension->SrbFlags = 0; - - } - - // - // Allow queued requests if this is not removable media. - // - - if (!(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) { - - deviceExtension->SrbFlags |= SRB_FLAGS_NO_QUEUE_FREEZE; - - } - - // - // Look for controller that require special flags. - // - - ScanForSpecial(deviceObject, - LunInfo, - PortCapabilities); - - //srbFlags = deviceExtension->SrbFlags; - - // - // Allocate buffer for drive geometry. - // - - diskGeometry = ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY_EX)); - - if (diskGeometry == NULL) { - - DebugPrint((1, - "CreateDiskDeviceObjects: Can not allocate disk geometry buffer\n")); - status = STATUS_INSUFFICIENT_RESOURCES; - goto CreateDiskDeviceObjectsExit; - } - - deviceExtension->DiskGeometry = diskGeometry; - - // - // Allocate request sense buffer. - // - - senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE); - - if (senseData == NULL) { - - // - // The buffer can not be allocated. - // - - DebugPrint((1, - "CreateDiskDeviceObjects: Can not allocate request sense buffer\n")); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto CreateDiskDeviceObjectsExit; - } - - // - // Set the sense data pointer in the device extension. - // - - deviceExtension->SenseData = senseData; - - // - // Physical device object will describe the entire - // device, starting at byte offset 0. - // - - deviceExtension->StartingOffset.QuadPart = (LONGLONG)(0); - - // - // TargetId/LUN describes a device location on the SCSI bus. - // This information comes from the inquiry buffer. - // - - deviceExtension->PortNumber = (UCHAR)PortNumber; - deviceExtension->PathId = pathId; - deviceExtension->TargetId = targetId; - deviceExtension->Lun = lun; - - // - // Set timeout value in seconds. - // - - timeOut = ScsiClassQueryTimeOutRegistryValue(RegistryPath); - if (timeOut) { - deviceExtension->TimeOutValue = timeOut; - } else { - deviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT; - } - - // - // Back pointer to device object. - // - - deviceExtension->DeviceObject = deviceObject; - - // - // If this is a removable device, then make sure it is not a floppy. - // Perform a mode sense command to determine the media type. Note - // IsFloppyDevice also checks for write cache enabled. - // - -#if 0 - if (IsFloppyDevice(deviceObject) && deviceObject->Characteristics & FILE_REMOVABLE_MEDIA && - (((PINQUIRYDATA)LunInfo->InquiryData)->DeviceType == DIRECT_ACCESS_DEVICE)) { - - status = STATUS_NO_SUCH_DEVICE; - goto CreateDiskDeviceObjectsExit; - } -#endif - - DisableWriteCache(deviceObject,LunInfo); - - //writeCache = deviceExtension->DeviceFlags & DEV_WRITE_CACHE; - - // - // NOTE: At this point one device object has been successfully created. - // from here on out return success. - // - - // - // Do READ CAPACITY. This SCSI command - // returns the number of bytes on a device. - // Device extension is updated with device size. - // - - status = ScsiClassReadDriveCapacity(deviceObject); - - // - // If the read capacity failed then just return, unless this is a - // removable disk where a device object partition needs to be created. - // - - if (!NT_SUCCESS(status) && - !(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) { - - DebugPrint((1, - "CreateDiskDeviceObjects: Can't read capacity for device %s\n", - ntNameBuffer)); - - return(STATUS_SUCCESS); - - } else { - - // - // Make sure the volume verification bit is off so that - // IoReadPartitionTable will work. - // - - deviceObject->Flags &= ~DO_VERIFY_VOLUME; - } - - status = CreatePartitionDeviceObjects(deviceObject, RegistryPath); - - if (NT_SUCCESS(status)) - return STATUS_SUCCESS; - - -CreateDiskDeviceObjectsExit: - - // - // Release the device since an error occurred. - // - - ScsiClassClaimDevice(PortDeviceObject, - LunInfo, - TRUE, - NULL); - - if (diskGeometry != NULL) { - ExFreePool(diskGeometry); - } - - if (senseData != NULL) { - ExFreePool(senseData); - } - - if (deviceObject != NULL) { - - if (srbListInitialized) { - ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead); - } - - IoDeleteDevice(deviceObject); - } - - // - // Delete directory and return. - // - - if (!NT_SUCCESS(status)) { - ZwMakeTemporaryObject(handle); - } - - ZwClose(handle); - - return(status); - -} // end CreateDiskDeviceObjects() - - -VOID -NTAPI -ReportToMountMgr( - IN PDEVICE_OBJECT DiskDeviceObject - ) - -/*++ - -Routine Description: - - This routine reports the creation of a disk device object to the - MountMgr to fake PnP. - -Arguments: - - DiskDeviceObject - Pointer to the created disk device. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS status; - UNICODE_STRING mountMgrDevice; - PDEVICE_OBJECT deviceObject; - PFILE_OBJECT fileObject; - PMOUNTMGR_TARGET_NAME mountTarget; - ULONG diskLen; - PDEVICE_EXTENSION deviceExtension; - PIRP irp; - KEVENT event; - IO_STATUS_BLOCK ioStatus; - - // - // First, get MountMgr DeviceObject. - // - - RtlInitUnicodeString(&mountMgrDevice, MOUNTMGR_DEVICE_NAME); - status = IoGetDeviceObjectPointer(&mountMgrDevice, FILE_READ_ATTRIBUTES, - &fileObject, &deviceObject); - - if (!NT_SUCCESS(status)) { - - DebugPrint((1, - "ReportToMountMgr: Can't get MountMgr pointers %lx\n", - status)); - - return; - } - - deviceExtension = DiskDeviceObject->DeviceExtension; - diskLen = deviceExtension->DeviceName.Length; - - // - // Allocate input buffer to report our partition device. - // - - mountTarget = ExAllocatePool(NonPagedPool, - sizeof(MOUNTMGR_TARGET_NAME) + diskLen); - - if (!mountTarget) { - - DebugPrint((1, - "ReportToMountMgr: Allocation of mountTarget failed\n")); - - ObDereferenceObject(fileObject); - return; - } - - mountTarget->DeviceNameLength = diskLen; - RtlCopyMemory(mountTarget->DeviceName, deviceExtension->DeviceName.Buffer, diskLen); - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Build the IRP used to communicate with the MountMgr. - // - - irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, - deviceObject, - mountTarget, - sizeof(MOUNTMGR_TARGET_NAME) + diskLen, - NULL, - 0, - FALSE, - &event, - &ioStatus); - - if (!irp) { - - DebugPrint((1, - "ReportToMountMgr: Allocation of irp failed\n")); - - ExFreePool(mountTarget); - ObDereferenceObject(fileObject); - return; - } - - // - // Call the MountMgr. - // - - status = IoCallDriver(deviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - // - // We're done. - // - - DPRINT1("Reported to the MountMgr: %lx\n", status); - - ExFreePool(mountTarget); - ObDereferenceObject(fileObject); - - return; -} - - -NTSTATUS -NTAPI -CreatePartitionDeviceObjects( - IN PDEVICE_OBJECT PhysicalDeviceObject, - IN PUNICODE_STRING RegistryPath - ) -{ - CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH]; - ULONG partitionNumber = 0; - NTSTATUS status; - PDEVICE_OBJECT deviceObject = NULL; - PDISK_GEOMETRY_EX diskGeometry = NULL; - PDRIVE_LAYOUT_INFORMATION partitionList = NULL; - PDEVICE_EXTENSION deviceExtension; - PDEVICE_EXTENSION physicalDeviceExtension; - PCLASS_INIT_DATA initData = NULL; - PDISK_DATA diskData; - PDISK_DATA physicalDiskData; - ULONG bytesPerSector; - UCHAR sectorShift; - ULONG srbFlags; - ULONG dmByteSkew = 0; - PULONG dmSkew; - BOOLEAN dmActive = FALSE; - ULONG numberListElements = 0; - - - // - // Get physical device geometry information for partition table reads. - // - - physicalDeviceExtension = PhysicalDeviceObject->DeviceExtension; - diskGeometry = physicalDeviceExtension->DiskGeometry; - bytesPerSector = diskGeometry->Geometry.BytesPerSector; - - // - // Make sure sector size is not zero. - // - - if (bytesPerSector == 0) { - - // - // Default sector size for disk is 512. - // - - bytesPerSector = diskGeometry->Geometry.BytesPerSector = 512; - } - - sectorShift = physicalDeviceExtension->SectorShift; - - // - // Set pointer to disk data area that follows device extension. - // - - diskData = (PDISK_DATA)(physicalDeviceExtension + 1); - diskData->PartitionListState = Initializing; - - // - // Determine is DM Driver is loaded on an IDE drive that is - // under control of Atapi - this could be either a crashdump or - // an Atapi device is sharing the controller with an IDE disk. - // - - HalExamineMBR(PhysicalDeviceObject, - physicalDeviceExtension->DiskGeometry->Geometry.BytesPerSector, - (ULONG)0x54, - (PVOID)&dmSkew); - - if (dmSkew) { - - // - // Update the device extension, so that the call to IoReadPartitionTable - // will get the correct information. Any I/O to this disk will have - // to be skewed by *dmSkew sectors aka DMByteSkew. - // - - physicalDeviceExtension->DMSkew = *dmSkew; - physicalDeviceExtension->DMActive = TRUE; - physicalDeviceExtension->DMByteSkew = physicalDeviceExtension->DMSkew * bytesPerSector; - - // - // Save away the information that we need, since this deviceExtension will soon be - // blown away. - // - - dmActive = TRUE; - dmByteSkew = physicalDeviceExtension->DMByteSkew; - - } - -#ifdef __REACTOS__ - // - // HACK so that we can use NT5+ NTOS functions with this NT4 driver - // for removable devices and avoid an infinite recursive loop between - // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable(). - // - diskData->UpdateRemovableGeometryCount = 0; -#endif - - // - // Create objects for all the partitions on the device. - // - - status = IoReadPartitionTable(PhysicalDeviceObject, - physicalDeviceExtension->DiskGeometry->Geometry.BytesPerSector, - TRUE, - (PVOID)&partitionList); - - // - // If the I/O read partition table failed and this is a removable device, - // then fix up the partition list to make it look like there is one - // zero length partition. - // - DPRINT("IoReadPartitionTable() status: 0x%08X\n", status); - if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) && - PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - - if (!NT_SUCCESS(status)) { - - // - // Remember this disk is not ready. - // - - diskData->DriveNotReady = TRUE; - - } else { - - // - // Free the partition list allocated by IoReadPartitionTable. - // - - ExFreePool(partitionList); - } - - // - // Allocate and zero a partition list. - // - - partitionList = ExAllocatePool(NonPagedPool, sizeof(*partitionList)); - - - if (partitionList != NULL) { - - RtlZeroMemory( partitionList, sizeof( *partitionList )); - - // - // Set the partition count to one and the status to success - // so one device object will be created. Set the partition type - // to a bogus value. - // - - partitionList->PartitionCount = 1; - - status = STATUS_SUCCESS; - } - } - - if (NT_SUCCESS(status)) { - - // - // Record disk signature. - // - - diskData->Signature = partitionList->Signature; - - // - // If disk signature is zero, then calculate the MBR checksum. - // - - if (!diskData->Signature) { - - if (!CalculateMbrCheckSum(physicalDeviceExtension, - &diskData->MbrCheckSum)) { - - DebugPrint((1, - "SCSIDISK: Can't calculate MBR checksum for disk %x\n", - physicalDeviceExtension->DeviceNumber)); - } else { - - DebugPrint((2, - "SCSIDISK: MBR checksum for disk %x is %x\n", - physicalDeviceExtension->DeviceNumber, - diskData->MbrCheckSum)); - } - } - - // - // Check the registry and determine if the BIOS knew about this drive. If - // it did then update the geometry with the BIOS information. - // - - UpdateGeometry(physicalDeviceExtension); - - srbFlags = physicalDeviceExtension->SrbFlags; - - initData = ExAllocatePool(NonPagedPool, sizeof(CLASS_INIT_DATA)); - if (!initData) - { - DebugPrint((1, - "Disk.CreatePartitionDeviceObjects - Allocation of initData failed\n")); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto CreatePartitionDeviceObjectsExit; - } - - RtlZeroMemory(initData, sizeof(CLASS_INIT_DATA)); - - initData->InitializationDataSize = sizeof(CLASS_INIT_DATA); - initData->DeviceExtensionSize = DEVICE_EXTENSION_SIZE; - initData->DeviceType = FILE_DEVICE_DISK; - initData->DeviceCharacteristics = PhysicalDeviceObject->Characteristics; - initData->ClassError = physicalDeviceExtension->ClassError; - initData->ClassReadWriteVerification = physicalDeviceExtension->ClassReadWriteVerification; - initData->ClassFindDevices = physicalDeviceExtension->ClassFindDevices; - initData->ClassDeviceControl = physicalDeviceExtension->ClassDeviceControl; - initData->ClassShutdownFlush = physicalDeviceExtension->ClassShutdownFlush; - initData->ClassCreateClose = physicalDeviceExtension->ClassCreateClose; - initData->ClassStartIo = physicalDeviceExtension->ClassStartIo; - - // - // Create device objects for the device partitions (if any). - // PartitionCount includes physical device partition 0, - // so only one partition means no objects to create. - // - - DebugPrint((2, - "CreateDiskDeviceObjects: Number of partitions is %d\n", - partitionList->PartitionCount)); - - for (partitionNumber = 0; partitionNumber < - partitionList->PartitionCount; partitionNumber++) { - - // - // Create partition object and set up partition parameters. - // - - sprintf(ntNameBuffer, - "\\Device\\Harddisk%lu\\Partition%lu", - physicalDeviceExtension->DeviceNumber, - partitionNumber + 1); - - DebugPrint((2, - "CreateDiskDeviceObjects: Create device object %s\n", - ntNameBuffer)); - - status = ScsiClassCreateDeviceObject(PhysicalDeviceObject->DriverObject, - ntNameBuffer, - PhysicalDeviceObject, - &deviceObject, - initData); - - if (!NT_SUCCESS(status)) { - - DebugPrint((1, "CreateDiskDeviceObjects: Can't create device object for %s\n", ntNameBuffer)); - - break; - } - - // - // Set up device object fields. - // - - deviceObject->Flags |= DO_DIRECT_IO; - - // - // Check if this is during initialization. If not indicate that - // system initialization already took place and this disk is ready - // to be accessed. - // - - if (!RegistryPath) { - deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - } - - deviceObject->StackSize = (CCHAR)physicalDeviceExtension->PortDeviceObject->StackSize + 1; - - // - // Set up device extension fields. - // - - deviceExtension = deviceObject->DeviceExtension; - - if (dmActive) { - - // - // Restore any saved DM values. - // - - deviceExtension->DMByteSkew = dmByteSkew; - deviceExtension->DMSkew = *dmSkew; - deviceExtension->DMActive = TRUE; - - } - - // - // Link new device extension to previous disk data - // to support dynamic partitioning. - // - - diskData->NextPartition = deviceExtension; - - // - // Get pointer to new disk data. - // - - diskData = (PDISK_DATA)(deviceExtension + 1); - - // - // Set next partition pointer to NULL in case this is the - // last partition. - // - - diskData->NextPartition = NULL; - - // - // Allocate spinlock for zoning for split-request completion. - // - - KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock); - - // - // Copy port device object pointer to device extension. - // - - deviceExtension->PortDeviceObject = physicalDeviceExtension->PortDeviceObject; - - // - // Set the alignment requirements for the device based on the - // host adapter requirements - // - - if (physicalDeviceExtension->PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) { - deviceObject->AlignmentRequirement = physicalDeviceExtension->PortDeviceObject->AlignmentRequirement; - } - - - if (srbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) { - numberListElements = 30; - } else { - numberListElements = 8; - } - - // - // Build the lookaside list for srb's for this partition based on - // whether the adapter and disk can do tagged queueing. - // - - ScsiClassInitializeSrbLookasideList(deviceExtension, - numberListElements); - - deviceExtension->SrbFlags = srbFlags; - - // - // Set the sense-data pointer in the device extension. - // - - deviceExtension->SenseData = physicalDeviceExtension->SenseData; - deviceExtension->PortCapabilities = physicalDeviceExtension->PortCapabilities; - deviceExtension->DiskGeometry = diskGeometry; - diskData->PartitionOrdinal = diskData->PartitionNumber = partitionNumber + 1; - diskData->PartitionType = partitionList->PartitionEntry[partitionNumber].PartitionType; - diskData->BootIndicator = partitionList->PartitionEntry[partitionNumber].BootIndicator; - - DebugPrint((2, "CreateDiskDeviceObjects: Partition type is %x\n", - diskData->PartitionType)); - - deviceExtension->StartingOffset = partitionList->PartitionEntry[partitionNumber].StartingOffset; - deviceExtension->PartitionLength = partitionList->PartitionEntry[partitionNumber].PartitionLength; - diskData->HiddenSectors = partitionList->PartitionEntry[partitionNumber].HiddenSectors; - deviceExtension->PortNumber = physicalDeviceExtension->PortNumber; - deviceExtension->PathId = physicalDeviceExtension->PathId; - deviceExtension->TargetId = physicalDeviceExtension->TargetId; - deviceExtension->Lun = physicalDeviceExtension->Lun; - - // - // Check for removable media support. - // - - if (PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; - } - - // - // Set timeout value in seconds. - // - - deviceExtension->TimeOutValue = physicalDeviceExtension->TimeOutValue; - deviceExtension->DiskGeometry->Geometry.BytesPerSector = bytesPerSector; - deviceExtension->SectorShift = sectorShift; - deviceExtension->DeviceObject = deviceObject; - deviceExtension->DeviceFlags |= physicalDeviceExtension->DeviceFlags; - - // - // Now we're done, report to the MountMgr. - // This is a HACK required to have the driver - // handle the associated DosDevices. - // - - ReportToMountMgr(deviceObject); - - } // end for (partitionNumber) ... - - // - // Free the buffer allocated by reading the - // partition table. - // - - ExFreePool(partitionList); - - if (dmSkew) { - ExFreePool(dmSkew); - } - - } else { - -CreatePartitionDeviceObjectsExit: - - if (partitionList) { - ExFreePool(partitionList); - } - if (initData) { - ExFreePool(initData); - } - - if (dmSkew) { - ExFreePool(dmSkew); - } - - return status; - - } // end if...else - - - physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1); - physicalDiskData->PartitionListState = Initialized; - - return(STATUS_SUCCESS); - - -} // end CreatePartitionDeviceObjects() - - -NTSTATUS -NTAPI -ScsiDiskReadWriteVerification( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - I/O System entry for read and write requests to SCSI disks. - -Arguments: - - DeviceObject - Pointer to driver object created by system. - Irp - IRP involved. - -Return Value: - - NT Status - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - ULONG transferByteCount = currentIrpStack->Parameters.Read.Length; - LARGE_INTEGER startingOffset; - - // - // HACK: How can we end here with null sector size?! - // - - if (deviceExtension->DiskGeometry->Geometry.BytesPerSector == 0) { - DPRINT1("Hack! Received invalid sector size\n"); - deviceExtension->DiskGeometry->Geometry.BytesPerSector = 512; - } - - // - // Verify parameters of this request. - // Check that ending sector is within partition and - // that number of bytes to transfer is a multiple of - // the sector size. - // - - startingOffset.QuadPart = (currentIrpStack->Parameters.Read.ByteOffset.QuadPart + - transferByteCount); - - if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) || - (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1))) { - - // - // This error maybe caused by the fact that the drive is not ready. - // - - if (((PDISK_DATA)(deviceExtension + 1))->DriveNotReady) { - - // - // Flag this as a user error so that a popup is generated. - // - - Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - - } else { - - // - // Note fastfat depends on this parameter to determine when to - // remount do to a sector size change. - // - - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - } - - if (startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) { - DPRINT1("Reading beyond partition end! startingOffset: %I64d, PartitionLength: %I64d\n", startingOffset.QuadPart, deviceExtension->PartitionLength.QuadPart); - } - - if (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1)) { - DPRINT1("Not reading sectors! TransferByteCount: %lu, BytesPerSector: %lu\n", transferByteCount, deviceExtension->DiskGeometry->Geometry.BytesPerSector); - } - - if (Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) { - DPRINT1("Failing due to device not ready!\n"); - } - - return STATUS_INVALID_PARAMETER; - } - - return STATUS_SUCCESS; - -} // end ScsiDiskReadWrite() - - -NTSTATUS -NTAPI -ScsiDiskDeviceControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ) - -/*++ - -Routine Description: - - I/O system entry for device controls to SCSI disks. - -Arguments: - - DeviceObject - Pointer to driver object created by system. - Irp - IRP involved. - -Return Value: - - Status is returned. - ---*/ - -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PDISK_DATA diskData = (PDISK_DATA)(deviceExtension + 1); - PSCSI_REQUEST_BLOCK srb; - PCDB cdb; - PMODE_PARAMETER_HEADER modeData; - PIRP irp2; - ULONG length; - NTSTATUS status; - KEVENT event; - IO_STATUS_BLOCK ioStatus; - - PAGED_CODE(); - - srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE); - - if (srb == NULL) { - - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - // - // Write zeros to Srb. - // - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - cdb = (PCDB)srb->Cdb; - - switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { - - case SMART_GET_VERSION: { - - ULONG_PTR buffer; - PSRB_IO_CONTROL srbControl; - PGETVERSIONINPARAMS versionParams; - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(GETVERSIONINPARAMS)) { - status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Create notification event object to be used to signal the - // request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - srbControl = ExAllocatePool(NonPagedPool, - sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS)); - - if (!srbControl) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // fill in srbControl fields - // - - srbControl->HeaderLength = sizeof(SRB_IO_CONTROL); - RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8); - srbControl->Timeout = deviceExtension->TimeOutValue; - srbControl->Length = sizeof(GETVERSIONINPARAMS); - srbControl->ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION; - - // - // Point to the 'buffer' portion of the SRB_CONTROL - // - - buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength; - - // - // Ensure correct target is set in the cmd parameters. - // - - versionParams = (PGETVERSIONINPARAMS)buffer; - versionParams->bIDEDeviceMap = deviceExtension->TargetId; - - // - // Copy the IOCTL parameters to the srb control buffer area. - // - - RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(GETVERSIONINPARAMS)); - - - irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT, - deviceExtension->PortDeviceObject, - srbControl, - sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS), - srbControl, - sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS), - FALSE, - &event, - &ioStatus); - - if (irp2 == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // Call the port driver with the request and wait for it to complete. - // - - status = IoCallDriver(deviceExtension->PortDeviceObject, irp2); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - // - // If successful, copy the data received into the output buffer. - // This should only fail in the event that the IDE driver is older than this driver. - // - - if (NT_SUCCESS(status)) { - - buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength; - - RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, sizeof(GETVERSIONINPARAMS)); - Irp->IoStatus.Information = sizeof(GETVERSIONINPARAMS); - } - - ExFreePool(srbControl); - break; - } - - case SMART_RCV_DRIVE_DATA: { - - PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer); - ULONG controlCode = 0; - PSRB_IO_CONTROL srbControl; - ULONG_PTR buffer; - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - (sizeof(SENDCMDINPARAMS) - 1)) { - status = STATUS_INVALID_PARAMETER; - break; - - } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - (sizeof(SENDCMDOUTPARAMS) + 512 - 1)) { - status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Create notification event object to be used to signal the - // request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - if (cmdInParameters->irDriveRegs.bCommandReg == ID_CMD) { - - length = IDENTIFY_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS); - controlCode = IOCTL_SCSI_MINIPORT_IDENTIFY; - - } else if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) { - switch (cmdInParameters->irDriveRegs.bFeaturesReg) { - case READ_ATTRIBUTES: - controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS; - length = READ_ATTRIBUTE_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS); - break; - case READ_THRESHOLDS: - controlCode = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS; - length = READ_THRESHOLD_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS); - break; - default: - status = STATUS_INVALID_PARAMETER; - break; - } - } else { - - status = STATUS_INVALID_PARAMETER; - } - - if (controlCode == 0) { - status = STATUS_INVALID_PARAMETER; - break; - } - - srbControl = ExAllocatePool(NonPagedPool, - sizeof(SRB_IO_CONTROL) + length); - - if (!srbControl) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // fill in srbControl fields - // - - srbControl->HeaderLength = sizeof(SRB_IO_CONTROL); - RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8); - srbControl->Timeout = deviceExtension->TimeOutValue; - srbControl->Length = length; - srbControl->ControlCode = controlCode; - - // - // Point to the 'buffer' portion of the SRB_CONTROL - // - - buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength; - - // - // Ensure correct target is set in the cmd parameters. - // - - cmdInParameters->bDriveNumber = deviceExtension->TargetId; - - // - // Copy the IOCTL parameters to the srb control buffer area. - // - - RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1); - - irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT, - deviceExtension->PortDeviceObject, - srbControl, - sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1, - srbControl, - sizeof(SRB_IO_CONTROL) + length, - FALSE, - &event, - &ioStatus); - - if (irp2 == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // Call the port driver with the request and wait for it to complete. - // - - status = IoCallDriver(deviceExtension->PortDeviceObject, irp2); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - // - // If successful, copy the data received into the output buffer - // - - buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength; - - if (NT_SUCCESS(status)) { - - RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, length - 1); - Irp->IoStatus.Information = length - 1; - - } else { - - RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, (sizeof(SENDCMDOUTPARAMS) - 1)); - Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) - 1; - - } - - ExFreePool(srbControl); - break; - - } - - case SMART_SEND_DRIVE_COMMAND: { - - PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer); - PSRB_IO_CONTROL srbControl; - ULONG controlCode = 0; - ULONG_PTR buffer; - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - (sizeof(SENDCMDINPARAMS) - 1)) { - status = STATUS_INVALID_PARAMETER; - break; - - } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - (sizeof(SENDCMDOUTPARAMS) - 1)) { - status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Create notification event object to be used to signal the - // request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - length = 0; - - if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) { - switch (cmdInParameters->irDriveRegs.bFeaturesReg) { - - case ENABLE_SMART: - controlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART; - break; - - case DISABLE_SMART: - controlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART; - break; - - case RETURN_SMART_STATUS: - - // - // Ensure bBuffer is at least 2 bytes (to hold the values of - // cylinderLow and cylinderHigh). - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - (sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS))) { - - status = STATUS_INVALID_PARAMETER; - break; - } - - controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS; - length = sizeof(IDEREGS); - break; - - case ENABLE_DISABLE_AUTOSAVE: - controlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE; - break; - - case SAVE_ATTRIBUTE_VALUES: - controlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES; - break; - - case EXECUTE_OFFLINE_DIAGS: - controlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS; - break; - - default: - status = STATUS_INVALID_PARAMETER; - break; - } - } else { - - status = STATUS_INVALID_PARAMETER; - } - - if (controlCode == 0) { - status = STATUS_INVALID_PARAMETER; - break; - } - - length += (sizeof(SENDCMDOUTPARAMS) > sizeof(SENDCMDINPARAMS)) ? sizeof(SENDCMDOUTPARAMS) : sizeof(SENDCMDINPARAMS); - srbControl = ExAllocatePool(NonPagedPool, - sizeof(SRB_IO_CONTROL) + length); - - if (!srbControl) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // fill in srbControl fields - // - - srbControl->HeaderLength = sizeof(SRB_IO_CONTROL); - RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8); - srbControl->Timeout = deviceExtension->TimeOutValue; - srbControl->Length = length; - - // - // Point to the 'buffer' portion of the SRB_CONTROL - // - - buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength; - - // - // Ensure correct target is set in the cmd parameters. - // - - cmdInParameters->bDriveNumber = deviceExtension->TargetId; - - // - // Copy the IOCTL parameters to the srb control buffer area. - // - - RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1); - - srbControl->ControlCode = controlCode; - - irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT, - deviceExtension->PortDeviceObject, - srbControl, - sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1, - srbControl, - sizeof(SRB_IO_CONTROL) + length, - FALSE, - &event, - &ioStatus); - - if (irp2 == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // Call the port driver with the request and wait for it to complete. - // - - status = IoCallDriver(deviceExtension->PortDeviceObject, irp2); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - status = ioStatus.Status; - } - - // - // Copy the data received into the output buffer. Since the status buffer - // contains error information also, always perform this copy. IO will will - // either pass this back to the app, or zero it, in case of error. - // - - buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength; - - // - // Update the return buffer size based on the sub-command. - // - - if (cmdInParameters->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) { - length = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS); - } else { - length = sizeof(SENDCMDOUTPARAMS) - 1; - } - - RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, length); - Irp->IoStatus.Information = length; - - ExFreePool(srbControl); - break; - - } - - case IOCTL_DISK_GET_DRIVE_GEOMETRY: - case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: - { - - PDEVICE_EXTENSION physicalDeviceExtension; - PDISK_DATA physicalDiskData; - BOOLEAN removable = FALSE; - BOOLEAN listInitialized = FALSE; - ULONG copyLength; - - if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) { - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) { - status = STATUS_BUFFER_TOO_SMALL; - break; - } - - copyLength = sizeof(DISK_GEOMETRY); - } else { - ASSERT(irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX); - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(DISK_GEOMETRY_EX, Data)) { - status = STATUS_BUFFER_TOO_SMALL; - break; - } - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(DISK_GEOMETRY_EX)) { - copyLength = sizeof(DISK_GEOMETRY_EX); - } else { - copyLength = FIELD_OFFSET(DISK_GEOMETRY_EX, Data); - } - } - - status = STATUS_SUCCESS; - - physicalDeviceExtension = deviceExtension->PhysicalDevice->DeviceExtension; - physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1); - - removable = (BOOLEAN)DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA; - listInitialized = (physicalDiskData->PartitionListState == Initialized); - - if (removable || (!listInitialized)) - { - // - // Issue ReadCapacity to update device extension - // with information for current media. - // - - status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice); - - } - - if (removable) { - - if (!NT_SUCCESS(status)) { - - // - // Note the drive is not ready. - // - - diskData->DriveNotReady = TRUE; - - break; - } - - // - // Note the drive is now ready. - // - - diskData->DriveNotReady = FALSE; - - } else if (NT_SUCCESS(status)) { - - // ReadDriveCapacity was alright, create Partition Objects - - if (physicalDiskData->PartitionListState == NotInitialized) { - status = CreatePartitionDeviceObjects(deviceExtension->PhysicalDevice, NULL); - } - } - - if (NT_SUCCESS(status)) { - - // - // Copy drive geometry information from device extension. - // - - RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, - deviceExtension->DiskGeometry, - copyLength); - - status = STATUS_SUCCESS; - Irp->IoStatus.Information = copyLength; - } - - break; - - } - - case IOCTL_DISK_VERIFY: - - { - - PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer; - LARGE_INTEGER byteOffset; - ULONG sectorOffset; - USHORT sectorCount; - - // - // Validate buffer length. - // - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(VERIFY_INFORMATION)) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - // - // Verify sectors - // - - srb->CdbLength = 10; - - cdb->CDB10.OperationCode = SCSIOP_VERIFY; - - // - // Add disk offset to starting sector. - // - - byteOffset.QuadPart = deviceExtension->StartingOffset.QuadPart + - verifyInfo->StartingOffset.QuadPart; - - // - // Convert byte offset to sector offset. - // - - sectorOffset = (ULONG)(byteOffset.QuadPart >> deviceExtension->SectorShift); - - // - // Convert ULONG byte count to USHORT sector count. - // - - sectorCount = (USHORT)(verifyInfo->Length >> deviceExtension->SectorShift); - - // - // Move little endian values into CDB in big endian format. - // - - cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)§orOffset)->Byte3; - cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)§orOffset)->Byte2; - cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)§orOffset)->Byte1; - cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)§orOffset)->Byte0; - - cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)§orCount)->Byte1; - cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)§orCount)->Byte0; - - // - // The verify command is used by the NT FORMAT utility and - // requests are sent down for 5% of the volume size. The - // request timeout value is calculated based on the number of - // sectors verified. - // - - srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) * - deviceExtension->TimeOutValue; - - status = ScsiClassSendSrbAsynchronous(DeviceObject, - srb, - Irp, - NULL, - 0, - FALSE); - - return(status); - - } - - case IOCTL_DISK_GET_PARTITION_INFO: - - // - // Return the information about the partition specified by the device - // object. Note that no information is ever returned about the size - // or partition type of the physical disk, as this doesn't make any - // sense. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(PARTITION_INFORMATION)) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - // - // Update the geometry in case it has changed. - // - - status = UpdateRemovableGeometry (DeviceObject, Irp); - - if (!NT_SUCCESS(status)) { - - // - // Note the drive is not ready. - // - - diskData->DriveNotReady = TRUE; - break; - } - - // - // Note the drive is now ready. - // - - diskData->DriveNotReady = FALSE; - - // - // Handle the case were we query the whole disk - // - - if (diskData->PartitionNumber == 0) { - - PPARTITION_INFORMATION outputBuffer; - - outputBuffer = - (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->PartitionType = PARTITION_ENTRY_UNUSED; - outputBuffer->StartingOffset = deviceExtension->StartingOffset; - outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart; - outputBuffer->HiddenSectors = 0; - outputBuffer->PartitionNumber = diskData->PartitionNumber; - outputBuffer->BootIndicator = FALSE; - outputBuffer->RewritePartition = FALSE; - outputBuffer->RecognizedPartition = FALSE; - - status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION); - - } else { - - PPARTITION_INFORMATION outputBuffer; - - // - // We query a single partition here - // FIXME: this can only work for MBR-based disks, check for this! - // - - outputBuffer = - (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->PartitionType = diskData->PartitionType; - outputBuffer->StartingOffset = deviceExtension->StartingOffset; - outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart; - outputBuffer->HiddenSectors = diskData->HiddenSectors; - outputBuffer->PartitionNumber = diskData->PartitionNumber; - outputBuffer->BootIndicator = diskData->BootIndicator; - outputBuffer->RewritePartition = FALSE; - outputBuffer->RecognizedPartition = - IsRecognizedPartition(diskData->PartitionType); - - status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION); - } - - break; - - case IOCTL_DISK_GET_PARTITION_INFO_EX: - - // - // Return the information about the partition specified by the device - // object. Note that no information is ever returned about the size - // or partition type of the physical disk, as this doesn't make any - // sense. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(PARTITION_INFORMATION_EX)) { - - status = STATUS_INFO_LENGTH_MISMATCH; - - } -#if 0 // HACK: ReactOS partition numbers must be wrong - else if (diskData->PartitionNumber == 0) { - - // - // Partition zero is not a partition so this is not a - // reasonable request. - // - - status = STATUS_INVALID_DEVICE_REQUEST; - - } -#endif - else { - - PPARTITION_INFORMATION_EX outputBuffer; - - if (diskData->PartitionNumber == 0) { - DPRINT1("HACK: Handling partition 0 request!\n"); - //ASSERT(FALSE); - } - - // - // Update the geometry in case it has changed. - // - - status = UpdateRemovableGeometry (DeviceObject, Irp); - - if (!NT_SUCCESS(status)) { - - // - // Note the drive is not ready. - // - - diskData->DriveNotReady = TRUE; - break; - } - - // - // Note the drive is now ready. - // - - diskData->DriveNotReady = FALSE; - - if (diskData->PartitionType == 0 && (diskData->PartitionNumber > 0)) { - - status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - - outputBuffer = - (PPARTITION_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer; - - // - // FIXME: hack of the year, assume that partition is MBR - // Thing that can obviously be wrong... - // - - outputBuffer->PartitionStyle = PARTITION_STYLE_MBR; - outputBuffer->Mbr.PartitionType = diskData->PartitionType; - outputBuffer->StartingOffset = deviceExtension->StartingOffset; - outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart; - outputBuffer->Mbr.HiddenSectors = diskData->HiddenSectors; - outputBuffer->PartitionNumber = diskData->PartitionNumber; - outputBuffer->Mbr.BootIndicator = diskData->BootIndicator; - outputBuffer->RewritePartition = FALSE; - outputBuffer->Mbr.RecognizedPartition = - IsRecognizedPartition(diskData->PartitionType); - - status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX); - } - - break; - - case IOCTL_DISK_SET_PARTITION_INFO: - - if (diskData->PartitionNumber == 0) { - - status = STATUS_UNSUCCESSFUL; - - } else { - - PSET_PARTITION_INFORMATION inputBuffer = - (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; - - // - // Validate buffer length. - // - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(SET_PARTITION_INFORMATION)) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - // - // The HAL routines IoGet- and IoSetPartitionInformation were - // developed before support of dynamic partitioning and therefore - // don't distinguish between partition ordinal (that is the order - // of a partition on a disk) and the partition number. (The - // partition number is assigned to a partition to identify it to - // the system.) Use partition ordinals for these legacy calls. - // - - status = IoSetPartitionInformation( - deviceExtension->PhysicalDevice, - deviceExtension->DiskGeometry->Geometry.BytesPerSector, - diskData->PartitionOrdinal, - inputBuffer->PartitionType); - - if (NT_SUCCESS(status)) { - - diskData->PartitionType = inputBuffer->PartitionType; - } - } - - break; - - case IOCTL_DISK_GET_DRIVE_LAYOUT: - - // - // Return the partition layout for the physical drive. Note that - // the layout is returned for the actual physical drive, regardless - // of which partition was specified for the request. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(DRIVE_LAYOUT_INFORMATION)) { - status = STATUS_INFO_LENGTH_MISMATCH; - - } else { - - PDRIVE_LAYOUT_INFORMATION partitionList; - PDEVICE_EXTENSION physicalExtension = deviceExtension; - PPARTITION_INFORMATION partitionEntry; - PDISK_DATA diskData; - ULONG tempSize; - ULONG i; - - // - // Read partition information. - // - - status = IoReadPartitionTable(deviceExtension->PhysicalDevice, - deviceExtension->DiskGeometry->Geometry.BytesPerSector, - FALSE, - &partitionList); - - if (!NT_SUCCESS(status)) { - break; - } - - // - // The disk layout has been returned in the partitionList - // buffer. Determine its size and, if the data will fit - // into the intermediary buffer, return it. - // - - tempSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,PartitionEntry[0]); - tempSize += partitionList->PartitionCount * - sizeof(PARTITION_INFORMATION); - - if (tempSize > - irpStack->Parameters.DeviceIoControl.OutputBufferLength) { - - status = STATUS_BUFFER_TOO_SMALL; - ExFreePool(partitionList); - break; - } - - // - // Walk partition list to associate partition numbers with - // partition entries. - // - - for (i = 0; i < partitionList->PartitionCount; i++) { - - // - // Walk partition chain anchored at physical disk extension. - // - - deviceExtension = physicalExtension; - diskData = (PDISK_DATA)(deviceExtension + 1); - - do { - - deviceExtension = diskData->NextPartition; - - // - // Check if this is the last partition in the chain. - // - - if (!deviceExtension) { - break; - } - - // - // Get the partition device extension from disk data. - // - - diskData = (PDISK_DATA)(deviceExtension + 1); - - // - // Check if this partition is not currently being used. - // - - if (!deviceExtension->PartitionLength.QuadPart) { - continue; - } - - partitionEntry = &partitionList->PartitionEntry[i]; - - // - // Check if empty, or describes extended partition or hasn't changed. - // - - if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED || - IsContainerPartition(partitionEntry->PartitionType)) { - continue; - } - - // - // Check if new partition starts where this partition starts. - // - - if (partitionEntry->StartingOffset.QuadPart != - deviceExtension->StartingOffset.QuadPart) { - continue; - } - - // - // Check if partition length is the same. - // - - if (partitionEntry->PartitionLength.QuadPart == - deviceExtension->PartitionLength.QuadPart) { - - // - // Partitions match. Update partition number. - // - - partitionEntry->PartitionNumber = - diskData->PartitionNumber; - break; - } - - } while (TRUE); - } - - // - // Copy partition information to system buffer. - // - - RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, - partitionList, - tempSize); - status = STATUS_SUCCESS; - Irp->IoStatus.Information = tempSize; - - // - // Finally, free the buffer allocated by reading the - // partition table. - // - - ExFreePool(partitionList); - } - - break; - - case IOCTL_DISK_SET_DRIVE_LAYOUT: - - { - - // - // Update the disk with new partition information. - // - - PDRIVE_LAYOUT_INFORMATION partitionList = Irp->AssociatedIrp.SystemBuffer; - - // - // Validate buffer length. - // - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(DRIVE_LAYOUT_INFORMATION)) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - length = sizeof(DRIVE_LAYOUT_INFORMATION) + - (partitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION); - - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - length) { - - status = STATUS_BUFFER_TOO_SMALL; - break; - } - - // - // Verify that device object is for physical disk. - // - - if (deviceExtension->PhysicalDevice->DeviceExtension != deviceExtension) { - status = STATUS_INVALID_PARAMETER; - break; - } - - // - // Walk through partition table comparing partitions to - // existing partitions to create, delete and change - // device objects as necessary. - // - - UpdateDeviceObjects(DeviceObject, - Irp); - - // - // Write changes to disk. - // - - status = IoWritePartitionTable( - deviceExtension->DeviceObject, - deviceExtension->DiskGeometry->Geometry.BytesPerSector, - deviceExtension->DiskGeometry->Geometry.SectorsPerTrack, - deviceExtension->DiskGeometry->Geometry.TracksPerCylinder, - partitionList); - } - - // - // Update IRP with bytes returned. - // - - if (NT_SUCCESS(status)) { - Irp->IoStatus.Information = length; - } - - break; - - case IOCTL_DISK_REASSIGN_BLOCKS: - - // - // Map defective blocks to new location on disk. - // - - { - - PREASSIGN_BLOCKS badBlocks = Irp->AssociatedIrp.SystemBuffer; - ULONG bufferSize; - ULONG blockNumber; - ULONG blockCount; - - // - // Validate buffer length. - // - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(REASSIGN_BLOCKS)) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - bufferSize = sizeof(REASSIGN_BLOCKS) + - (badBlocks->Count - 1) * sizeof(ULONG); - - if (irpStack->Parameters.DeviceIoControl.InputBufferLength < - bufferSize) { - - status = STATUS_INFO_LENGTH_MISMATCH; - break; - } - - // - // Build the data buffer to be transferred in the input buffer. - // The format of the data to the device is: - // - // 2 bytes Reserved - // 2 bytes Length - // x * 4 btyes Block Address - // - // All values are big endian. - // - - badBlocks->Reserved = 0; - blockCount = badBlocks->Count; - - // - // Convert # of entries to # of bytes. - // - - blockCount *= 4; - badBlocks->Count = (USHORT) ((blockCount >> 8) & 0XFF); - badBlocks->Count |= (USHORT) ((blockCount << 8) & 0XFF00); - - // - // Convert back to number of entries. - // - - blockCount /= 4; - - for (; blockCount > 0; blockCount--) { - - blockNumber = badBlocks->BlockNumber[blockCount-1]; - - REVERSE_BYTES((PFOUR_BYTE) &badBlocks->BlockNumber[blockCount-1], - (PFOUR_BYTE) &blockNumber); - } - - srb->CdbLength = 6; - - cdb->CDB6GENERIC.OperationCode = SCSIOP_REASSIGN_BLOCKS; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - - status = ScsiClassSendSrbSynchronous(DeviceObject, - srb, - badBlocks, - bufferSize, - TRUE); - - Irp->IoStatus.Status = status; - Irp->IoStatus.Information = 0; - ExFreePool(srb); - IoCompleteRequest(Irp, IO_DISK_INCREMENT); - } - - return(status); - - case IOCTL_DISK_IS_WRITABLE: - - // - // Determine if the device is writable. - // - - modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE); - - if (modeData == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - RtlZeroMemory(modeData, MODE_DATA_SIZE); - - length = ScsiClassModeSense(DeviceObject, - (PCHAR) modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - // - // Retry the request in case of a check condition. - // - - length = ScsiClassModeSense(DeviceObject, - (PCHAR) modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - status = STATUS_IO_DEVICE_ERROR; - ExFreePool(modeData); - break; - } - } - - if (modeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT) { - status = STATUS_MEDIA_WRITE_PROTECTED; - } else { - status = STATUS_SUCCESS; - } - - ExFreePool(modeData); - break; - - case IOCTL_DISK_INTERNAL_SET_VERIFY: - - // - // If the caller is kernel mode, set the verify bit. - // - - if (Irp->RequestorMode == KernelMode) { - DeviceObject->Flags |= DO_VERIFY_VOLUME; - } - status = STATUS_SUCCESS; - break; - - case IOCTL_DISK_INTERNAL_CLEAR_VERIFY: - - // - // If the caller is kernel mode, clear the verify bit. - // - - if (Irp->RequestorMode == KernelMode) { - DeviceObject->Flags &= ~DO_VERIFY_VOLUME; - } - status = STATUS_SUCCESS; - break; - - case IOCTL_DISK_FIND_NEW_DEVICES: - - // - // Search for devices that have been powered on since the last - // device search or system initialization. - // - - DebugPrint((3,"CdRomDeviceControl: Find devices\n")); - status = DriverEntry(DeviceObject->DriverObject, - NULL); - - Irp->IoStatus.Status = status; - ExFreePool(srb); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; - - case IOCTL_DISK_MEDIA_REMOVAL: - - // - // If the disk is not removable then don't allow this command. - // - - if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) { - status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - - // - // Fall through and let the class driver process the request. - // - - case IOCTL_DISK_GET_LENGTH_INFO: - - // - // Validate buffer length. - // - - if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(GET_LENGTH_INFORMATION)) { - status = STATUS_BUFFER_TOO_SMALL; - - } else { - - PGET_LENGTH_INFORMATION lengthInformation = Irp->AssociatedIrp.SystemBuffer; - - // - // Update the geometry in case it has changed. - // - - status = UpdateRemovableGeometry (DeviceObject, Irp); - - if (!NT_SUCCESS(status)) { - - // - // Note the drive is not ready. - // - - diskData->DriveNotReady = TRUE; - break; - } - - // - // Note the drive is now ready. - // - - diskData->DriveNotReady = FALSE; - - // - // Output data, and return - // - - lengthInformation->Length.QuadPart = deviceExtension->PartitionLength.QuadPart; - status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); - } - - break; - - default: - - // - // Free the Srb, since it is not needed. - // - - ExFreePool(srb); - - // - // Pass the request to the common device control routine. - // - - return(ScsiClassDeviceControl(DeviceObject, Irp)); - - break; - - } // end switch( ... - - Irp->IoStatus.Status = status; - - if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) { - - IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); - } - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - ExFreePool(srb); - return(status); - -} // end ScsiDiskDeviceControl() - -NTSTATUS -NTAPI -ScsiDiskShutdownFlush ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This routine is called for a shutdown and flush IRPs. These are sent by the - system before it actually shuts down or when the file system does a flush. - A synchronize cache command is sent to the device if it is write caching. - If the device is removable an unlock command will be sent. This routine - will sent a shutdown or flush Srb to the port driver. - -Arguments: - - DriverObject - Pointer to device object to being shutdown by system. - - Irp - IRP involved. - -Return Value: - - NT Status - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION irpStack; - PSCSI_REQUEST_BLOCK srb; - NTSTATUS status; - PCDB cdb; - - // - // Allocate SCSI request block. - // - - srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); - - if (srb == NULL) { - - // - // Set the status and complete the request. - // - - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - // - // Write length to SRB. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set SCSI bus address. - // - - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - - // - // Set timeout value and mark the request as not being a tagged request. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue * 4; - srb->QueueTag = SP_UNTAGGED; - srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; - srb->SrbFlags = deviceExtension->SrbFlags; - - // - // If the write cache is enabled then send a synchronize cache request. - // - - if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) { - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->CdbLength = 10; - - srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE; - - status = ScsiClassSendSrbSynchronous(DeviceObject, - srb, - NULL, - 0, - TRUE); - - DebugPrint((1, "ScsiDiskShutdownFlush: Synchronize cache sent. Status = %lx\n", status )); - } - - // - // Unlock the device if it is removable and this is a shutdown. - // - - irpStack = IoGetCurrentIrpStackLocation(Irp); - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA && - irpStack->MajorFunction == IRP_MJ_SHUTDOWN) { - - srb->CdbLength = 6; - cdb = (PVOID) srb->Cdb; - cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL; - cdb->MEDIA_REMOVAL.Prevent = FALSE; - - // - // Set timeout value. - // - - srb->TimeOutValue = deviceExtension->TimeOutValue; - status = ScsiClassSendSrbSynchronous(DeviceObject, - srb, - NULL, - 0, - TRUE); - - DebugPrint((1, "ScsiDiskShutdownFlush: Unlock device request sent. Status = %lx\n", status )); - } - - srb->CdbLength = 0; - - // - // Save a few parameters in the current stack location. - // - - srb->Function = irpStack->MajorFunction == IRP_MJ_SHUTDOWN ? - SRB_FUNCTION_SHUTDOWN : SRB_FUNCTION_FLUSH; - - // - // Set the retry count to zero. - // - - irpStack->Parameters.Others.Argument4 = (PVOID) 0; - - // - // Set up IoCompletion routine address. - // - - IoSetCompletionRoutine(Irp, ScsiClassIoComplete, srb, TRUE, TRUE, TRUE); - - // - // Get next stack location and - // set major function code. - // - - irpStack = IoGetNextIrpStackLocation(Irp); - - irpStack->MajorFunction = IRP_MJ_SCSI; - - // - // Set up SRB for execute scsi request. - // Save SRB address in next stack for port driver. - // - - irpStack->Parameters.Scsi.Srb = srb; - - // - // Set up Irp Address. - // - - srb->OriginalRequest = Irp; - - // - // Call the port driver to process the request. - // - - return(IoCallDriver(deviceExtension->PortDeviceObject, Irp)); - -} // end ScsiDiskShutdown() - - -BOOLEAN -NTAPI -IsFloppyDevice( - PDEVICE_OBJECT DeviceObject - ) -/*++ - -Routine Description: - - The routine performs the necessary functions to determine if a device is - really a floppy rather than a harddisk. This is done by a mode sense - command. First, a check is made to see if the media type is set. Second - a check is made for the flexible parameters mode page. Also a check is - made to see if the write cache is enabled. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - -Return Value: - - Return TRUE if the indicated device is a floppy. - ---*/ -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PVOID modeData; - PUCHAR pageData; - ULONG length; - - PAGED_CODE(); - - modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE); - - if (modeData == NULL) { - return(FALSE); - } - - RtlZeroMemory(modeData, MODE_DATA_SIZE); - - length = ScsiClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - // - // Retry the request in case of a check condition. - // - - length = ScsiClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - ExFreePool(modeData); - return(FALSE); - - } - } - - // - // If the length is greater than length indicated by the mode data reset - // the data to the mode data. - // - - if (length > (ULONG) ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) { - length = ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1; - } - - // - // Look for the flexible disk mode page. - // - - pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE); - - if (pageData != NULL) { - - DebugPrint((1, "Scsidisk: Flexible disk page found, This is a floppy.\n")); - ExFreePool(modeData); - return(TRUE); - } - - // - // Check to see if the write cache is enabled. - // - - pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_CACHING, TRUE); - - // - // Assume that write cache is disabled or not supported. - // - - deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE; - - // - // Check if valid caching page exists. - // - - if (pageData != NULL) { - - // - // Check if write cache is disabled. - // - - if (((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable) { - - DebugPrint((1, - "SCSIDISK: Disk write cache enabled\n")); - - // - // Check if forced unit access (FUA) is supported. - // - - if (((PMODE_PARAMETER_HEADER)modeData)->DeviceSpecificParameter & MODE_DSP_FUA_SUPPORTED) { - - deviceExtension->DeviceFlags |= DEV_WRITE_CACHE; - - } else { - - DebugPrint((1, - "SCSIDISK: Disk does not support FUA or DPO\n")); - - // - // TODO: Log this. - // - - } - } - } - - ExFreePool(modeData); - return(FALSE); - -} // end IsFloppyDevice() - - -BOOLEAN -NTAPI -ScsiDiskModeSelect( - IN PDEVICE_OBJECT DeviceObject, - IN PCHAR ModeSelectBuffer, - IN ULONG Length, - IN BOOLEAN SavePage - ) - -/*++ - -Routine Description: - - This routine sends a mode select command. - -Arguments: - - DeviceObject - Supplies the device object associated with this request. - - ModeSelectBuffer - Supplies a buffer containing the page data. - - Length - Supplies the length in bytes of the mode select buffer. - - SavePage - Indicates that parameters should be written to disk. - -Return Value: - - Length of the transferred data is returned. - ---*/ -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PCDB cdb; - SCSI_REQUEST_BLOCK srb; - ULONG retries = 1; - ULONG length2; - NTSTATUS status; - ULONG_PTR buffer; - PMODE_PARAMETER_BLOCK blockDescriptor; - - PAGED_CODE(); - - length2 = Length + sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK); - - // - // Allocate buffer for mode select header, block descriptor, and mode page. - // - - buffer = (ULONG_PTR)ExAllocatePool(NonPagedPoolCacheAligned,length2); - - RtlZeroMemory((PVOID)buffer, length2); - - // - // Set length in header to size of mode page. - // - - ((PMODE_PARAMETER_HEADER)buffer)->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK); - - blockDescriptor = (PMODE_PARAMETER_BLOCK)(buffer + 1); - - // - // Set size - // - - blockDescriptor->BlockLength[1]=0x02; - - // - // Copy mode page to buffer. - // - - RtlCopyMemory((PVOID)(buffer + 3), ModeSelectBuffer, Length); - - // - // Zero SRB. - // - - RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); - - // - // Build the MODE SELECT CDB. - // - - srb.CdbLength = 6; - cdb = (PCDB)srb.Cdb; - - // - // Set timeout value from device extension. - // - - srb.TimeOutValue = deviceExtension->TimeOutValue * 2; - - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.SPBit = SavePage; - cdb->MODE_SELECT.PFBit = 1; - cdb->MODE_SELECT.ParameterListLength = (UCHAR)(length2); - -Retry: - - status = ScsiClassSendSrbSynchronous(DeviceObject, - &srb, - (PVOID)buffer, - length2, - TRUE); - - - if (status == STATUS_VERIFY_REQUIRED) { - - // - // Routine ScsiClassSendSrbSynchronous does not retry requests returned with - // this status. - // - - if (retries--) { - - // - // Retry request. - // - - goto Retry; - } - - } else if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) { - status = STATUS_SUCCESS; - } - - ExFreePool((PVOID)buffer); - - if (NT_SUCCESS(status)) { - return(TRUE); - } else { - return(FALSE); - } - -} // end SciDiskModeSelect() - - -VOID -NTAPI -DisableWriteCache( - IN PDEVICE_OBJECT DeviceObject, - IN PSCSI_INQUIRY_DATA LunInfo - ) - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData; - BAD_CONTROLLER_INFORMATION const *controller; - ULONG j,length; - PVOID modeData; - PUCHAR pageData; - - for (j = 0; j < NUMBER_OF_BAD_CONTROLLERS; j++) { - - controller = &ScsiDiskBadControllers[j]; - - if (!controller->DisableWriteCache || strncmp(controller->InquiryString, (PCCHAR)InquiryData->VendorId, strlen(controller->InquiryString))) { - continue; - } - - DebugPrint((1, "ScsiDisk.DisableWriteCache, Found bad controller! %s\n", controller->InquiryString)); - - modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE); - - if (modeData == NULL) { - - DebugPrint((1, - "ScsiDisk.DisableWriteCache: Check for write-cache enable failed\n")); - return; - } - - RtlZeroMemory(modeData, MODE_DATA_SIZE); - - length = ScsiClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - // - // Retry the request in case of a check condition. - // - - length = ScsiClassModeSense(DeviceObject, - modeData, - MODE_DATA_SIZE, - MODE_SENSE_RETURN_ALL); - - if (length < sizeof(MODE_PARAMETER_HEADER)) { - - - DebugPrint((1, - "ScsiDisk.DisableWriteCache: Mode Sense failed\n")); - - ExFreePool(modeData); - return; - - } - } - - // - // If the length is greater than length indicated by the mode data reset - // the data to the mode data. - // - - if (length > (ULONG) ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) { - length = ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1; - } - - // - // Check to see if the write cache is enabled. - // - - pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_CACHING, TRUE); - - // - // Assume that write cache is disabled or not supported. - // - - deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE; - - // - // Check if valid caching page exists. - // - - if (pageData != NULL) { - - BOOLEAN savePage = FALSE; - - savePage = (BOOLEAN)(((PMODE_CACHING_PAGE)pageData)->PageSavable); - - // - // Check if write cache is disabled. - // - - if (((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable) { - - PIO_ERROR_LOG_PACKET errorLogEntry; - LONG errorCode; - - - // - // Disable write cache and ensure necessary fields are zeroed. - // - - ((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable = FALSE; - ((PMODE_CACHING_PAGE)pageData)->Reserved = 0; - ((PMODE_CACHING_PAGE)pageData)->PageSavable = 0; - ((PMODE_CACHING_PAGE)pageData)->Reserved2 = 0; - - // - // Extract length from caching page. - // - - length = ((PMODE_CACHING_PAGE)pageData)->PageLength; - - // - // Compensate for page code and page length. - // - - length += 2; - - // - // Issue mode select to set the parameter. - // - - if (ScsiDiskModeSelect(DeviceObject, - (PCHAR)pageData, - length, - savePage)) { - - DebugPrint((1, - "SCSIDISK: Disk write cache disabled\n")); - - deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE; - errorCode = IO_WRITE_CACHE_DISABLED; - - } else { - if (ScsiDiskModeSelect(DeviceObject, - (PCHAR)pageData, - length, - savePage)) { - - DebugPrint((1, - "SCSIDISK: Disk write cache disabled\n")); - - - deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE; - errorCode = IO_WRITE_CACHE_DISABLED; - - } else { - - DebugPrint((1, - "SCSIDISK: Mode select to disable write cache failed\n")); - - deviceExtension->DeviceFlags |= DEV_WRITE_CACHE; - errorCode = IO_WRITE_CACHE_ENABLED; - } - } - - // - // Log the appropriate informational or error entry. - // - - errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( - DeviceObject, - sizeof(IO_ERROR_LOG_PACKET) + 3 - * sizeof(ULONG)); - - if (errorLogEntry != NULL) { - - errorLogEntry->FinalStatus = STATUS_SUCCESS; - errorLogEntry->ErrorCode = errorCode; - errorLogEntry->SequenceNumber = 0; - errorLogEntry->MajorFunctionCode = IRP_MJ_SCSI; - errorLogEntry->IoControlCode = 0; - errorLogEntry->RetryCount = 0; - errorLogEntry->UniqueErrorValue = 0x1; - errorLogEntry->DumpDataSize = 3 * sizeof(ULONG); - errorLogEntry->DumpData[0] = LunInfo->PathId; - errorLogEntry->DumpData[1] = LunInfo->TargetId; - errorLogEntry->DumpData[2] = LunInfo->Lun; - - // - // Write the error log packet. - // - - IoWriteErrorLogEntry(errorLogEntry); - } - } - } - - // - // Found device so exit the loop and return. - // - - break; - } - - return; -} - - -BOOLEAN -NTAPI -CalculateMbrCheckSum( - IN PDEVICE_EXTENSION DeviceExtension, - OUT PULONG Checksum - ) - -/*++ - -Routine Description: - - Read MBR and calculate checksum. - -Arguments: - - DeviceExtension - Supplies a pointer to the device information for disk. - Checksum - Memory location to return MBR checksum. - -Return Value: - - Returns TRUE if checksum is valid. - ---*/ -{ - LARGE_INTEGER sectorZero; - PIRP irp; - IO_STATUS_BLOCK ioStatus; - KEVENT event; - NTSTATUS status; - ULONG sectorSize; - PULONG mbr; - ULONG i; - - PAGED_CODE(); - sectorZero.QuadPart = (LONGLONG) 0; - - // - // Create notification event object to be used to signal the inquiry - // request completion. - // - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Get sector size. - // - - sectorSize = DeviceExtension->DiskGeometry->Geometry.BytesPerSector; - - // - // Make sure sector size is at least 512 bytes. - // - - if (sectorSize < 512) { - sectorSize = 512; - } - - // - // Allocate buffer for sector read. - // - - mbr = ExAllocatePool(NonPagedPoolCacheAligned, sectorSize); - - if (!mbr) { - return FALSE; - } - - // - // Build IRP to read MBR. - // - - irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, - DeviceExtension->DeviceObject, - mbr, - sectorSize, - §orZero, - &event, - &ioStatus ); - - if (!irp) { - ExFreePool(mbr); - return FALSE; - } - - // - // Pass request to port driver and wait for request to complete. - // - - status = IoCallDriver(DeviceExtension->DeviceObject, - irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, - Suspended, - KernelMode, - FALSE, - NULL); - status = ioStatus.Status; - } - - if (!NT_SUCCESS(status)) { - ExFreePool(mbr); - return FALSE; - } - - // - // Calculate MBR checksum. - // - - *Checksum = 0; - - for (i = 0; i < 128; i++) { - *Checksum += mbr[i]; - } - - *Checksum = ~*Checksum + 1; - - ExFreePool(mbr); - return TRUE; -} - - -BOOLEAN -NTAPI -EnumerateBusKey( - IN PDEVICE_EXTENSION DeviceExtension, - HANDLE BusKey, - PULONG DiskNumber - ) - -/*++ - -Routine Description: - - The routine queries the registry to determine if this disk is visible to - the BIOS. If the disk is visible to the BIOS, then the geometry information - is updated. - -Arguments: - - DeviceExtension - Supplies a pointer to the device information for disk. - Signature - Unique identifier recorded in MBR. - BusKey - Handle of bus key. - DiskNumber - Returns ordinal of disk as BIOS sees it. - -Return Value: - - TRUE is disk signature matched. - ---*/ -{ - PDISK_DATA diskData = (PDISK_DATA)(DeviceExtension + 1); - BOOLEAN diskFound = FALSE; - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING unicodeString; - UNICODE_STRING identifier; - ULONG busNumber; - ULONG adapterNumber; - ULONG diskNumber; - HANDLE adapterKey; - HANDLE spareKey; - HANDLE diskKey; - HANDLE targetKey; - NTSTATUS status; - STRING string; - STRING anotherString; - ULONG length; - UCHAR buffer[20]; - PKEY_VALUE_FULL_INFORMATION keyData; - - PAGED_CODE(); - - for (busNumber = 0; ; busNumber++) { - - // - // Open controller name key. - // - - sprintf((PCHAR)buffer, - "%lu", - busNumber); - - RtlInitString(&string, - (PCSZ)buffer); - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &string, - TRUE); - - if (!NT_SUCCESS(status)){ - break; - } - - InitializeObjectAttributes(&objectAttributes, - &unicodeString, - OBJ_CASE_INSENSITIVE, - BusKey, - (PSECURITY_DESCRIPTOR)NULL); - - status = ZwOpenKey(&spareKey, - KEY_READ, - &objectAttributes); - - RtlFreeUnicodeString(&unicodeString); - - if (!NT_SUCCESS(status)) { - break; - } - - // - // Open up controller ordinal key. - // - - RtlInitUnicodeString(&unicodeString, L"DiskController"); - InitializeObjectAttributes(&objectAttributes, - &unicodeString, - OBJ_CASE_INSENSITIVE, - spareKey, - (PSECURITY_DESCRIPTOR)NULL); - - status = ZwOpenKey(&adapterKey, - KEY_READ, - &objectAttributes); - - // - // This could fail even with additional adapters of this type - // to search. - // - - if (!NT_SUCCESS(status)) { - continue; - } - - for (adapterNumber = 0; ; adapterNumber++) { - - // - // Open disk key. - // - - sprintf((PCHAR)buffer, - "%lu\\DiskPeripheral", - adapterNumber); - - RtlInitString(&string, - (PCSZ)buffer); - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &string, - TRUE); - - if (!NT_SUCCESS(status)){ - break; - } - - InitializeObjectAttributes(&objectAttributes, - &unicodeString, - OBJ_CASE_INSENSITIVE, - adapterKey, - (PSECURITY_DESCRIPTOR)NULL); - - status = ZwOpenKey(&diskKey, - KEY_READ, - &objectAttributes); - - RtlFreeUnicodeString(&unicodeString); - - if (!NT_SUCCESS(status)) { - break; - } - - for (diskNumber = 0; ; diskNumber++) { - - sprintf((PCHAR)buffer, - "%lu", - diskNumber); - - RtlInitString(&string, - (PCSZ)buffer); - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &string, - TRUE); - - if (!NT_SUCCESS(status)){ - break; - } - - InitializeObjectAttributes(&objectAttributes, - &unicodeString, - OBJ_CASE_INSENSITIVE, - diskKey, - (PSECURITY_DESCRIPTOR)NULL); - - status = ZwOpenKey(&targetKey, - KEY_READ, - &objectAttributes); - - RtlFreeUnicodeString(&unicodeString); - - if (!NT_SUCCESS(status)) { - break; - } - - // - // Allocate buffer for registry query. - // - - keyData = ExAllocatePool(PagedPool, VALUE_BUFFER_SIZE); - - if (keyData == NULL) { - ZwClose(targetKey); - continue; - } - - // - // Get disk peripheral identifier. - // - - RtlInitUnicodeString(&unicodeString, L"Identifier"); - status = ZwQueryValueKey(targetKey, - &unicodeString, - KeyValueFullInformation, - keyData, - VALUE_BUFFER_SIZE, - &length); - - ZwClose(targetKey); - - if (!NT_SUCCESS(status)) { - ExFreePool(keyData); - continue; - } - - if (keyData->DataLength < 9*sizeof(WCHAR)) { - // - // the data is too short to use (we subtract 9 chars in normal path) - // - DebugPrint((1, "EnumerateBusKey: Saved data was invalid, " - "not enough data in registry!\n")); - ExFreePool(keyData); - continue; - } - - // - // Complete unicode string. - // - - identifier.Buffer = - (PWSTR)((PUCHAR)keyData + keyData->DataOffset); - identifier.Length = (USHORT)keyData->DataLength; - identifier.MaximumLength = (USHORT)keyData->DataLength; - - // - // Convert unicode identifier to ansi string. - // - - status = - RtlUnicodeStringToAnsiString(&anotherString, - &identifier, - TRUE); - - if (!NT_SUCCESS(status)) { - ExFreePool(keyData); - continue; - } - - // - // If checksum is zero, then the MBR is valid and - // the signature is meaningful. - // - - if (diskData->MbrCheckSum) { - - // - // Convert checksum to ansi string. - // - - sprintf((PCHAR)buffer, "%08lx", diskData->MbrCheckSum); - - } else { - - // - // Convert signature to ansi string. - // - - sprintf((PCHAR)buffer, "%08lx", diskData->Signature); - - // - // Make string point at signature. Can't use scan - // functions because they are not exported for driver use. - // - - anotherString.Buffer+=9; - } - - // - // Convert to ansi string. - // - - RtlInitString(&string, - (PCSZ)buffer); - - - // - // Make string lengths equal. - // - - anotherString.Length = string.Length; - - // - // Check if strings match. - // - - if (RtlCompareString(&string, - &anotherString, - TRUE) == 0) { - - diskFound = TRUE; - *DiskNumber = diskNumber; - } - - ExFreePool(keyData); - - // - // Readjust identifier string if necessary. - // - - if (!diskData->MbrCheckSum) { - anotherString.Buffer-=9; - } - - RtlFreeAnsiString(&anotherString); - - if (diskFound) { - break; - } - } - - ZwClose(diskKey); - } - - ZwClose(adapterKey); - } - - ZwClose(BusKey); - return diskFound; - -} // end EnumerateBusKey() - - -VOID -NTAPI -UpdateGeometry( - IN PDEVICE_EXTENSION DeviceExtension - ) -/*++ - -Routine Description: - - The routine queries the registry to determine if this disk is visible to - the BIOS. If the disk is visible to the BIOS, then the geometry information - is updated. - -Arguments: - - DeviceExtension - Supplies a pointer to the device information for disk. - -Return Value: - - None. - ---*/ - -{ - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING unicodeString; - NTSTATUS status; - HANDLE hardwareKey; - HANDLE busKey; - PCM_INT13_DRIVE_PARAMETER driveParameters; - PCM_FULL_RESOURCE_DESCRIPTOR resourceDescriptor; - PKEY_VALUE_FULL_INFORMATION keyData; - ULONG diskNumber; - PUCHAR buffer; - ULONG length; - ULONG numberOfDrives; - ULONG cylinders; - ULONG sectors; - ULONG sectorsPerTrack; - ULONG tracksPerCylinder; - BOOLEAN foundEZHooker; - PVOID tmpPtr; - - PAGED_CODE(); - - // - // Initialize the object for the key. - // - - InitializeObjectAttributes(&objectAttributes, - DeviceExtension->DeviceObject->DriverObject->HardwareDatabase, - OBJ_CASE_INSENSITIVE, - NULL, - (PSECURITY_DESCRIPTOR) NULL); - - // - // Create the hardware base key. - // - - status = ZwOpenKey(&hardwareKey, - KEY_READ, - &objectAttributes); - - - if (!NT_SUCCESS(status)) { - DebugPrint((1, "ScsiDisk UpdateParameters: Cannot open hardware data. Name: %wZ\n", DeviceExtension->DeviceObject->DriverObject->HardwareDatabase)); - return; - } - - - // - // Get disk BIOS geometry information. - // - - RtlInitUnicodeString(&unicodeString, L"Configuration Data"); - - keyData = ExAllocatePool(PagedPool, VALUE_BUFFER_SIZE); - - if (keyData == NULL) { - ZwClose(hardwareKey); - return; - } - - status = ZwQueryValueKey(hardwareKey, - &unicodeString, - KeyValueFullInformation, - keyData, - VALUE_BUFFER_SIZE, - &length); - - if (!NT_SUCCESS(status)) { - DebugPrint((1, - "SCSIDISK: ExtractBiosGeometry: Can't query configuration data (%x)\n", - status)); - ZwClose(hardwareKey); - ExFreePool(keyData); - return; - } - - // - // Open EISA bus key. - // - - RtlInitUnicodeString(&unicodeString, L"EisaAdapter"); - - InitializeObjectAttributes(&objectAttributes, - &unicodeString, - OBJ_CASE_INSENSITIVE, - hardwareKey, - (PSECURITY_DESCRIPTOR)NULL); - - status = ZwOpenKey(&busKey, - KEY_READ, - &objectAttributes); - - if (!NT_SUCCESS(status)) { - goto openMultiKey; - } - - DebugPrint((3, - "SCSIDISK: UpdateGeometry: Opened EisaAdapter key\n")); - if (EnumerateBusKey(DeviceExtension, - busKey, - &diskNumber)) { - - ZwClose(hardwareKey); - goto diskMatched; - } - -openMultiKey: - - // - // Open Multifunction bus key. - // - - RtlInitUnicodeString(&unicodeString, L"MultifunctionAdapter"); - - InitializeObjectAttributes(&objectAttributes, - &unicodeString, - OBJ_CASE_INSENSITIVE, - hardwareKey, - (PSECURITY_DESCRIPTOR)NULL); - - status = ZwOpenKey(&busKey, - KEY_READ, - &objectAttributes); - - ZwClose(hardwareKey); - if (NT_SUCCESS(status)) { - DebugPrint((3, - "SCSIDISK: UpdateGeometry: Opened MultifunctionAdapter key\n")); - if (EnumerateBusKey(DeviceExtension, - busKey, - &diskNumber)) { - - goto diskMatched; - } - } - - ExFreePool(keyData); - return; - -diskMatched: - - resourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)keyData + - keyData->DataOffset); - - // - // Check that the data is long enough to hold a full resource descriptor, - // and that the last resource list is device-specific and long enough. - // - - if (keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR) || - resourceDescriptor->PartialResourceList.Count == 0 || - resourceDescriptor->PartialResourceList.PartialDescriptors[0].Type != - CmResourceTypeDeviceSpecific || - resourceDescriptor->PartialResourceList.PartialDescriptors[0] - .u.DeviceSpecificData.DataSize < sizeof(ULONG)) { - - DebugPrint((1, "SCSIDISK: ExtractBiosGeometry: BIOS header data too small or invalid\n")); - ExFreePool(keyData); - return; - } - - length = - resourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize; - - // - // Point to the BIOS data. The BIOS data is located after the first - // partial Resource list which should be device specific data. - // - - buffer = (PUCHAR) keyData + keyData->DataOffset + - sizeof(CM_FULL_RESOURCE_DESCRIPTOR); - - - numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER); - - // - // Use the defaults if the drive number is greater than the - // number of drives detected by the BIOS. - // - - if (numberOfDrives <= diskNumber) { - ExFreePool(keyData); - return; - } - - // - // Point to the array of drive parameters. - // - - driveParameters = (PCM_INT13_DRIVE_PARAMETER) buffer + diskNumber; - cylinders = driveParameters->MaxCylinders + 1; - sectorsPerTrack = driveParameters->SectorsPerTrack; - tracksPerCylinder = driveParameters->MaxHeads +1; - - // - // Calculate the actual number of sectors. - // - - sectors = (ULONG)(DeviceExtension->PartitionLength.QuadPart >> - DeviceExtension->SectorShift); - -#if DBG - if (sectors >= cylinders * tracksPerCylinder * sectorsPerTrack) { - DebugPrint((1, "ScsiDisk: UpdateGeometry: Disk smaller than BIOS indicated\n" - "SCSIDISK: Sectors: %x, Cylinders: %x, Track per Cylinder: %x Sectors per track: %x\n", - sectors, cylinders, tracksPerCylinder, sectorsPerTrack)); - } -#endif - - // - // Since the BIOS may not report the full drive, recalculate the drive - // size based on the volume size and the BIOS values for tracks per - // cylinder and sectors per track.. - // - - length = tracksPerCylinder * sectorsPerTrack; - - if (length == 0) { - - // - // The BIOS information is bogus. - // - - DebugPrint((1, "ScsiDisk UpdateParameters: sectorPerTrack zero\n")); - ExFreePool(keyData); - return; - } - - cylinders = sectors / length; - - // - // Update the actual geometry information. - // - - DeviceExtension->DiskGeometry->Geometry.SectorsPerTrack = sectorsPerTrack; - DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder = tracksPerCylinder; - DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)cylinders; - DeviceExtension->DiskGeometry->DiskSize.QuadPart = (LONGLONG)cylinders * tracksPerCylinder * sectorsPerTrack * - DeviceExtension->DiskGeometry->Geometry.BytesPerSector; - - DebugPrint((3, - "SCSIDISK: UpdateGeometry: BIOS spt %x, #heads %x, #cylinders %x\n", - sectorsPerTrack, - tracksPerCylinder, - cylinders)); - - ExFreePool(keyData); - - foundEZHooker = FALSE; - - if (!DeviceExtension->DMActive) { - - HalExamineMBR(DeviceExtension->DeviceObject, - DeviceExtension->DiskGeometry->Geometry.BytesPerSector, - (ULONG)0x55, - &tmpPtr - ); - - if (tmpPtr) { - - ExFreePool(tmpPtr); - foundEZHooker = TRUE; - - } - - } - - if (DeviceExtension->DMActive || foundEZHooker) { - - while (cylinders > 1024) { - - tracksPerCylinder = tracksPerCylinder*2; - cylinders = cylinders/2; - - } - - // - // int 13 values are always 1 less. - // - - tracksPerCylinder -= 1; - cylinders -= 1; - - // - // DM reserves the CE cylinder - // - - cylinders -= 1; - - DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = cylinders + 1; - DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder = tracksPerCylinder + 1; - - DeviceExtension->PartitionLength.QuadPart = - DeviceExtension->DiskGeometry->DiskSize.QuadPart = - DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart * - DeviceExtension->DiskGeometry->Geometry.SectorsPerTrack * - DeviceExtension->DiskGeometry->Geometry.BytesPerSector * - DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder; - - if (DeviceExtension->DMActive) { - - DeviceExtension->DMByteSkew = DeviceExtension->DMSkew * DeviceExtension->DiskGeometry->Geometry.BytesPerSector; - - } - - } else { - - DeviceExtension->DMByteSkew = 0; - - } - - return; - -} // end UpdateGeometry() - - - -NTSTATUS -NTAPI -UpdateRemovableGeometry ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This routines updates the size and starting offset of the device. This is - used when the media on the device may have changed thereby changing the - size of the device. If this is the physical device then a - ScsiClassReadDriveCapacity is done; otherewise, a read partition table is done. - -Arguments: - - DeviceObject - Supplies the device object whos size needs to be updated. - - Irp - Supplies a reference where the status can be updated. - -Return Value: - - Returns the status of the operation. - ---*/ -{ - - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PDRIVE_LAYOUT_INFORMATION partitionList; - NTSTATUS status; - PDISK_DATA diskData; - ULONG partitionNumber; - - // - // Determine if the size of the partition may have changed because - // the media has changed. - // - - if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) { - - return(STATUS_SUCCESS); - - } - - // - // If this request is for partition zero then do a read drive - // capacity otherwise do a I/O read partition table. - // - - diskData = (PDISK_DATA) (deviceExtension + 1); - - // - // Read the drive capacity. If that fails, give up. - // - - status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice); - - if (!NT_SUCCESS(status)) { - return(status); - } - -#ifdef __REACTOS__ - // - // HACK so that we can use NT5+ NTOS functions with this NT4 driver - // for removable devices and avoid an infinite recursive loop between - // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable(). - // - // Check whether the update-count is greater or equal than one - // (and increase it) and if so, reset it and return success. - if (diskData->UpdateRemovableGeometryCount++ >= 1) - { - diskData->UpdateRemovableGeometryCount = 0; - return(STATUS_SUCCESS); - } -#endif - - // - // Read the partition table again. - // - - status = IoReadPartitionTable(deviceExtension->PhysicalDevice, - deviceExtension->DiskGeometry->Geometry.BytesPerSector, - TRUE, - &partitionList); - -#ifdef __REACTOS__ - // - // HACK so that we can use NT5+ NTOS functions with this NT4 driver - // for removable devices and avoid an infinite recursive loop between - // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable(). - // - // Inconditionally reset the update-count. - diskData->UpdateRemovableGeometryCount = 0; -#endif - - if (!NT_SUCCESS(status)) { - - // - // Fail the request. - // - - return(status); - } - - if (diskData->PartitionNumber != 0 && - diskData->PartitionNumber <= partitionList->PartitionCount ) { - - partitionNumber = diskData->PartitionNumber - 1; - - // - // Update the partition information for this partition. - // - - diskData->PartitionType = - partitionList->PartitionEntry[partitionNumber].PartitionType; - - diskData->BootIndicator = - partitionList->PartitionEntry[partitionNumber].BootIndicator; - - deviceExtension->StartingOffset = - partitionList->PartitionEntry[partitionNumber].StartingOffset; - - deviceExtension->PartitionLength = - partitionList->PartitionEntry[partitionNumber].PartitionLength; - - diskData->HiddenSectors = - partitionList->PartitionEntry[partitionNumber].HiddenSectors; - - deviceExtension->SectorShift = ((PDEVICE_EXTENSION) - deviceExtension->PhysicalDevice->DeviceExtension)->SectorShift; - - } else if (diskData->PartitionNumber != 0) { - - // - // The partition does not exist. Zero all the data. - // - - diskData->PartitionType = 0; - diskData->BootIndicator = 0; - diskData->HiddenSectors = 0; - deviceExtension->StartingOffset.QuadPart = (LONGLONG)0; - deviceExtension->PartitionLength.QuadPart = (LONGLONG)0; - } - - // - // Free the partition list allocate by I/O read partition table. - // - - ExFreePool(partitionList); - - - return(STATUS_SUCCESS); -} - - -VOID -NTAPI -ScsiDiskProcessError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ) -/*++ - -Routine Description: - - This routine checks the type of error. If the error indicates an underrun - then indicate the request should be retried. - -Arguments: - - DeviceObject - Supplies a pointer to the device object. - - Srb - Supplies a pointer to the failing Srb. - - Status - Status with which the IRP will be completed. - - Retry - Indication of whether the request will be retried. - -Return Value: - - None. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - - if (*Status == STATUS_DATA_OVERRUN && - ( Srb->Cdb[0] == SCSIOP_WRITE || Srb->Cdb[0] == SCSIOP_READ)) { - - *Retry = TRUE; - - // - // Update the error count for the device. - // - - deviceExtension->ErrorCount++; - } - - if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_ERROR && - Srb->ScsiStatus == SCSISTAT_BUSY) { - - // - // The disk drive should never be busy this long. Reset the scsi bus - // maybe this will clear the condition. - // - - ResetScsiBus(DeviceObject); - - // - // Update the error count for the device. - // - - deviceExtension->ErrorCount++; - } -} - -VOID -NTAPI -ScanForSpecial( - PDEVICE_OBJECT DeviceObject, - PSCSI_INQUIRY_DATA LunInfo, - PIO_SCSI_CAPABILITIES PortCapabilities - ) - -/*++ - -Routine Description: - - This function checks to see if an SCSI logical unit requires special - flags to be set. - -Arguments: - - DeviceObject - Supplies the device object to be tested. - - InquiryData - Supplies the inquiry data returned by the device of interest. - - PortCapabilities - Supplies the capabilities of the device object. - -Return Value: - - None. - ---*/ - -{ - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData; - BAD_CONTROLLER_INFORMATION const *controller; - ULONG j; - - for (j = 0; j < NUMBER_OF_BAD_CONTROLLERS; j++) { - - controller = &ScsiDiskBadControllers[j]; - - if (strncmp(controller->InquiryString, (PCCHAR)InquiryData->VendorId, strlen(controller->InquiryString))) { - continue; - } - - DebugPrint((1, "ScsiDisk ScanForSpecial, Found bad controller! %s\n", controller->InquiryString)); - - // - // Found a listed controller. Determine what must be done. - // - - if (controller->DisableTaggedQueuing) { - - // - // Disable tagged queuing. - // - - deviceExtension->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE; - } - - if (controller->DisableSynchronousTransfers) { - - // - // Disable synchronous data transfers. - // - - deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; - - } - - if (controller->DisableDisconnects) { - - // - // Disable disconnects. - // - - deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT; - - } - - // - // Found device so exit the loop and return. - // - - break; - } - - // - // Set the StartUnit flag appropriately. - // - - if (DeviceObject->DeviceType == FILE_DEVICE_DISK) { - deviceExtension->DeviceFlags |= DEV_SAFE_START_UNIT; - - if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { - if (_strnicmp((PCCHAR)InquiryData->VendorId, "iomega", strlen("iomega"))) { - deviceExtension->DeviceFlags &= ~DEV_SAFE_START_UNIT; - } - } - } - - return; -} - -VOID -NTAPI -ResetScsiBus( - IN PDEVICE_OBJECT DeviceObject - ) - -/*++ - -Routine Description: - - This command sends a reset bus command to the SCSI port driver. - -Arguments: - - DeviceObject - The device object for the logical unit with - hardware problem. - -Return Value: - - None. - ---*/ -{ - PIO_STACK_LOCATION irpStack; - PIRP irp; - PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; - PSCSI_REQUEST_BLOCK srb; - PCOMPLETION_CONTEXT context; - - DebugPrint((1, "ScsiDisk ResetScsiBus: Sending reset bus request to port driver.\n")); - - // - // Allocate Srb from nonpaged pool. - // - - context = ExAllocatePool(NonPagedPoolMustSucceed, - sizeof(COMPLETION_CONTEXT)); - - // - // Save the device object in the context for use by the completion - // routine. - // - - context->DeviceObject = DeviceObject; - srb = &context->Srb; - - // - // Zero out srb. - // - - RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE); - - // - // Write length to SRB. - // - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - - // - // Set up SCSI bus address. - // - - srb->PathId = deviceExtension->PathId; - srb->TargetId = deviceExtension->TargetId; - srb->Lun = deviceExtension->Lun; - - srb->Function = SRB_FUNCTION_RESET_BUS; - - // - // Build the asynchronous request to be sent to the port driver. - // Since this routine is called from a DPC the IRP should always be - // available. - // - - irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - - IoSetCompletionRoutine(irp, - (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion, - context, - TRUE, - TRUE, - TRUE); - - irpStack = IoGetNextIrpStackLocation(irp); - - irpStack->MajorFunction = IRP_MJ_SCSI; - - srb->OriginalRequest = irp; - - // - // Store the SRB address in next stack for port driver. - // - - irpStack->Parameters.Scsi.Srb = srb; - - // - // Call the port driver with the IRP. - // - - IoCallDriver(deviceExtension->PortDeviceObject, irp); - - return; - -} // end ResetScsiBus() - - -VOID -NTAPI -UpdateDeviceObjects( - IN PDEVICE_OBJECT PhysicalDisk, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This routine creates, deletes and changes device objects when - the IOCTL_SET_DRIVE_LAYOUT is called. This routine also updates - the drive layout information for the user. It is possible to - call this routine even in the GET_LAYOUT case because RewritePartition - will be false. - -Arguments: - - DeviceObject - Device object for physical disk. - Irp - IO Request Packet (IRP). - -Return Value: - - None. - ---*/ -{ - PDEVICE_EXTENSION physicalExtension = PhysicalDisk->DeviceExtension; - PDRIVE_LAYOUT_INFORMATION partitionList = Irp->AssociatedIrp.SystemBuffer; - ULONG partition; - ULONG partitionNumber; - ULONG partitionCount; - ULONG lastPartition; - ULONG partitionOrdinal; - PPARTITION_INFORMATION partitionEntry; - CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH]; - STRING ntNameString; - UNICODE_STRING ntUnicodeString; - PDEVICE_OBJECT deviceObject; - PDEVICE_EXTENSION deviceExtension; - PDISK_DATA diskData; - NTSTATUS status; - ULONG numberListElements; - BOOLEAN found; - - partitionCount = ((partitionList->PartitionCount + 3) / 4) * 4; - - // - // Zero all of the partition numbers. - // - - for (partition = 0; partition < partitionCount; partition++) { - partitionEntry = &partitionList->PartitionEntry[partition]; - partitionEntry->PartitionNumber = 0; - } - - // - // Walk through chain of partitions for this disk to determine - // which existing partitions have no match. - // - - deviceExtension = physicalExtension; - diskData = (PDISK_DATA)(deviceExtension + 1); - lastPartition = 0; - - do { - - deviceExtension = diskData->NextPartition; - - // - // Check if this is the last partition in the chain. - // - - if (!deviceExtension) { - break; - } - - // - // Get the partition device extension from disk data. - // - - diskData = (PDISK_DATA)(deviceExtension + 1); - - // - // Check for highest partition number this far. - // - - if (diskData->PartitionNumber > lastPartition) { - lastPartition = diskData->PartitionNumber; - } - - // - // Check if this partition is not currently being used. - // - - if (!deviceExtension->PartitionLength.QuadPart) { - continue; - } - - // - // Loop through partition information to look for match. - // - - found = FALSE; - partitionOrdinal = 0; - - for (partition = 0; partition < partitionCount; partition++) { - - // - // Get partition descriptor. - // - - partitionEntry = &partitionList->PartitionEntry[partition]; - - // - // Check if empty, or describes extended partition or hasn't changed. - // - - if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED || - IsContainerPartition(partitionEntry->PartitionType)) { - continue; - } - - // - // Advance partition ordinal. - // - - partitionOrdinal++; - - // - // Check if new partition starts where this partition starts. - // - - if (partitionEntry->StartingOffset.QuadPart != - deviceExtension->StartingOffset.QuadPart) { - continue; - } - - // - // Check if partition length is the same. - // - - if (partitionEntry->PartitionLength.QuadPart == - deviceExtension->PartitionLength.QuadPart) { - - DebugPrint((3, - "UpdateDeviceObjects: Found match for \\Harddisk%d\\Partition%d\n", - physicalExtension->DeviceNumber, - diskData->PartitionNumber)); - - // - // Indicate match is found and set partition number - // in user buffer. - // - - found = TRUE; - partitionEntry->PartitionNumber = diskData->PartitionNumber; - break; - } - } - - if (found) { - - // - // A match is found. - // - - diskData = (PDISK_DATA)(deviceExtension + 1); - - // - // If this partition is marked for update then update partition type. - // - - if (partitionEntry->RewritePartition) { - diskData->PartitionType = partitionEntry->PartitionType; - } - - // - // Update partitional ordinal for calls to HAL routine - // IoSetPartitionInformation. - // - - diskData->PartitionOrdinal = partitionOrdinal; - - DebugPrint((1, - "UpdateDeviceObjects: Disk %d ordinal %d is partition %d\n", - physicalExtension->DeviceNumber, - diskData->PartitionOrdinal, - diskData->PartitionNumber)); - - } else { - - // - // no match was found, indicate this partition is gone. - // - - DebugPrint((1, - "UpdateDeviceObjects: Deleting \\Device\\Harddisk%x\\Partition%x\n", - physicalExtension->DeviceNumber, - diskData->PartitionNumber)); - - deviceExtension->PartitionLength.QuadPart = (LONGLONG) 0; - } - - } while (TRUE); - - // - // Walk through partition loop to find new partitions and set up - // device extensions to describe them. In some cases new device - // objects will be created. - // - - partitionOrdinal = 0; - - for (partition = 0; - partition < partitionCount; - partition++) { - - // - // Get partition descriptor. - // - - partitionEntry = &partitionList->PartitionEntry[partition]; - - // - // Check if empty, or describes an extended partition. - // - - if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED || - IsContainerPartition(partitionEntry->PartitionType)) { - continue; - } - - // - // Keep track of position on the disk for calls to IoSetPartitionInformation. - // - - partitionOrdinal++; - - // - // Check if this entry should be rewritten. - // - - if (!partitionEntry->RewritePartition) { - continue; - } - - if (partitionEntry->PartitionNumber) { - - // - // Partition is an exact match with an existing partition, but is - // being written anyway. - // - - continue; - } - - // - // Check first if existing device object is available by - // walking partition extension list. - // - - partitionNumber = 0; - deviceExtension = physicalExtension; - diskData = (PDISK_DATA)(deviceExtension + 1); - - do { - - // - // Get next partition device extension from disk data. - // - - deviceExtension = diskData->NextPartition; - - if (!deviceExtension) { - break; - } - - diskData = (PDISK_DATA)(deviceExtension + 1); - - // - // A device object is free if the partition length is set to zero. - // - - if (!deviceExtension->PartitionLength.QuadPart) { - partitionNumber = diskData->PartitionNumber; - break; - } - - } while (TRUE); - - // - // If partition number is still zero then a new device object - // must be created. - // - - if (partitionNumber == 0) { - - lastPartition++; - partitionNumber = lastPartition; - - // - // Get or create partition object and set up partition parameters. - // - - sprintf(ntNameBuffer, - "\\Device\\Harddisk%lu\\Partition%lu", - physicalExtension->DeviceNumber, - partitionNumber); - - RtlInitString(&ntNameString, - ntNameBuffer); - - status = RtlAnsiStringToUnicodeString(&ntUnicodeString, - &ntNameString, - TRUE); - - if (!NT_SUCCESS(status)) { - continue; - } - - DebugPrint((3, - "UpdateDeviceObjects: Create device object %s\n", - ntNameBuffer)); - - // - // This is a new name. Create the device object to represent it. - // - - status = IoCreateDevice(PhysicalDisk->DriverObject, - DEVICE_EXTENSION_SIZE, - &ntUnicodeString, - FILE_DEVICE_DISK, - 0, - FALSE, - &deviceObject); - - if (!NT_SUCCESS(status)) { - DebugPrint((1, - "UpdateDeviceObjects: Can't create device %s\n", - ntNameBuffer)); - RtlFreeUnicodeString(&ntUnicodeString); - continue; - } - - // - // Set up device object fields. - // - - deviceObject->Flags |= DO_DIRECT_IO; - deviceObject->StackSize = PhysicalDisk->StackSize; - - // - // Set up device extension fields. - // - - deviceExtension = deviceObject->DeviceExtension; - - // - // Copy physical disk extension to partition extension. - // - - RtlMoveMemory(deviceExtension, - physicalExtension, - sizeof(DEVICE_EXTENSION)); - - // - // Initialize the new S-List. - // - - if (deviceExtension->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) { - numberListElements = 30; - } else { - numberListElements = 8; - } - - // - // Build the lookaside list for srb's for this partition based on - // whether the adapter and disk can do tagged queueing. - // - - ScsiClassInitializeSrbLookasideList(deviceExtension, - numberListElements); - - // - // Allocate spinlock for zoning for split-request completion. - // - - KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock); - - // - // Write back partition number used in creating object name. - // - - partitionEntry->PartitionNumber = partitionNumber; - - // - // Clear flags initializing bit. - // - - deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - // - // Point back at device object. - // - - deviceExtension->DeviceObject = deviceObject; - - RtlFreeUnicodeString(&ntUnicodeString); - - // - // Link to end of partition chain using previous disk data. - // - - diskData->NextPartition = deviceExtension; - - // - // Get new disk data and zero next partition pointer. - // - - diskData = (PDISK_DATA)(deviceExtension + 1); - diskData->NextPartition = NULL; - - } else { - - // - // Set pointer to disk data area that follows device extension. - // - - diskData = (PDISK_DATA)(deviceExtension + 1); - - DebugPrint((1, - "UpdateDeviceObjects: Used existing device object \\Device\\Harddisk%x\\Partition%x\n", - physicalExtension->DeviceNumber, - partitionNumber)); - } - - // - // Update partition information in partition device extension. - // - - diskData->PartitionNumber = partitionNumber; - diskData->PartitionType = partitionEntry->PartitionType; - diskData->BootIndicator = partitionEntry->BootIndicator; - deviceExtension->StartingOffset = partitionEntry->StartingOffset; - deviceExtension->PartitionLength = partitionEntry->PartitionLength; - diskData->HiddenSectors = partitionEntry->HiddenSectors; - diskData->PartitionOrdinal = partitionOrdinal; - - DebugPrint((1, - "UpdateDeviceObjects: Ordinal %d is partition %d\n", - diskData->PartitionOrdinal, - diskData->PartitionNumber)); - - // - // Update partition number passed in to indicate the - // device name for this partition. - // - - partitionEntry->PartitionNumber = partitionNumber; - } - -} // end UpdateDeviceObjects() - diff --git a/drivers/storage/class/disk/disk.inf b/drivers/storage/class/disk/disk.inf deleted file mode 100644 index d0497a8873b..00000000000 --- a/drivers/storage/class/disk/disk.inf +++ /dev/null @@ -1,136 +0,0 @@ -; DISK.INF - -; Installation of DISK DRIVESs - -[Version] -Signature = "$Windows NT$" -;Signature = "$ReactOS$" -LayoutFile = layout.inf -Class = DiskDrive -ClassGUID = {4D36E967-E325-11CE-BFC1-08002BE10318} -Provider = %ReactOS% -DriverVer = 10/19/1999,5.00.2157.1 - -[DestinationDirs] -disk_CopyFiles.NT = 12 -storprop_CopyFiles.NT = 11 - -[ClassInstall32.NT] -AddReg = DiskClass.NT.AddReg -Copyfiles = storprop_CopyFiles.NT - -[DiskClass.NT.AddReg] -HKR, , , 0, %DiskClassName% -HKR, , Installer32, 0, "storprop.dll,DiskClassInstaller" -HKR, , Icon, 0, "-53" -HKR, , NoInstallClass, 0, 1 -HKR, , SilentInstall, 0, 1 - -[Manufacturer] -%GenericMfg% = GenericMfg - -[GenericMfg] -%Disk.DeviceDesc% = disk_Inst,GenDisk -%OpticalDisk.DeviceDesc% = disk_Inst,GenOptical - -;----------------------------- DISK DRIVER ----------------------------- - -[disk_Inst.NT] -CopyFiles = disk_CopyFiles.NT - -[disk_Inst.NT.Services] -AddService = disk, 2, disk_Service_Inst - -[disk_Service_Inst] -DisplayName = %Disk.ServiceDesc% -ServiceType = 1 -StartType = 0 -ErrorControl = 1 -ServiceBinary = %12%\disk.sys - -[disk_CopyFiles.NT] -disk.sys - -;---------------------------- DISK INSTALLER ---------------------------- - -[storprop_CopyFiles.NT] -storprop.dll - -;-------------------------------- STRINGS ------------------------------- - -[Strings] -ReactOS = "ReactOS Team" -GenericMfg = "(Generic Disk Drives)" -DiskClassName = "Disk Drives" -Disk.DeviceDesc = "Disk Drive" -OpticalDisk.DeviceDesc = "Optical Disk Drive" -Disk.ServiceDesc = "Disk Driver" - -[Strings.0405] -GenericMfg = "(Obecné diskové jednotky)" -DiskClassName = "Diskové jednotky" -Disk.DeviceDesc = "Disková jednotka" -OpticalDisk.DeviceDesc = "Optická disková jednotka" -Disk.ServiceDesc = "Ovladač disku" - -[Strings.0a] -ReactOS = "Equipo de ReactOS" -GenericMfg = "(Unidades de disco genéricas)" -DiskClassName = "Unidades de disco" -Disk.DeviceDesc = "Unidad de disco" -OpticalDisk.DeviceDesc = "Unidad de disco óptico" -Disk.ServiceDesc = "Controlador de disco" - -[Strings.040C] -ReactOS = "Equipe ReactOS" -GenericMfg = "(Pilotes de disque génériques)" -DiskClassName = "Lecteurs de disques" -Disk.DeviceDesc = "Lecteurs de disques" -OpticalDisk.DeviceDesc = "Lecteurs de disques optiques" -Disk.ServiceDesc = "Pilotes de disques" - -[Strings.0415] -ReactOS = "Zespół ReactOS" -GenericMfg = "(Standardowy dysk twardy)" -DiskClassName = "Dyski twarde" -Disk.DeviceDesc = "Dysk twardy" -OpticalDisk.DeviceDesc = "Dysk optyczny" -Disk.ServiceDesc = "Sterownik dysku" - -[Strings.0418] -ReactOS = "Echipa ReactOS" -GenericMfg = "(dispozitiv disc generic)" -DiskClassName = "Dispozitive disc" -Disk.DeviceDesc = "Dispozitiv disc" -OpticalDisk.DeviceDesc = "Dispozitiv disc optic" -Disk.ServiceDesc = "Modúl-pilot de disc" - -[Strings.0419] -ReactOS = "Команда ReactOS" -GenericMfg = "(Стандартные дисковые накопители)" -DiskClassName = "Дисковые устройства" -Disk.DeviceDesc = "Дисковое устройство" -OpticalDisk.DeviceDesc = "Оптическое дисковое устройство" -Disk.ServiceDesc = "Драйвер диска" - -[Strings.041f] -ReactOS = "ReactOS Takımı" -GenericMfg = "(Umûmî Disk Sürücüleri)" -DiskClassName = "Disk Sürücüleri" -Disk.DeviceDesc = "Disk Sürücüsü" -OpticalDisk.DeviceDesc = "Optik Disk Sürücüsü" -Disk.ServiceDesc = "Disk Sürücüsü" - -[Strings.0422] -ReactOS = "Команда ReactOS" -GenericMfg = "(Стандартні приводи дисків)" -DiskClassName = "Дискові приводи" -Disk.DeviceDesc = "Дисковий привід" -OpticalDisk.DeviceDesc = "Оптичний привід дисків" -Disk.ServiceDesc = "Драйвер диску" - -[Strings.0804] -GenericMfg = "(通用磁盘驱动器)" -Disk.DeviceDesc = "磁盘驱动器" -OpticalDisk.DeviceDesc = "光盘驱动器" -Disk.ServiceDesc = "磁盘驱动器" diff --git a/drivers/storage/class/disk/disk.rc b/drivers/storage/class/disk/disk.rc deleted file mode 100644 index 22cf04d2ce5..00000000000 --- a/drivers/storage/class/disk/disk.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "Disk Class Driver" -#define REACTOS_STR_INTERNAL_NAME "disk" -#define REACTOS_STR_ORIGINAL_FILENAME "disk.sys" -#include diff --git a/drivers/storage/class/disk/disk_reg.inf b/drivers/storage/class/disk/disk_reg.inf deleted file mode 100644 index 0e265c0e333..00000000000 --- a/drivers/storage/class/disk/disk_reg.inf +++ /dev/null @@ -1,7 +0,0 @@ -; Disk class driver -[AddReg] -HKLM,"SYSTEM\CurrentControlSet\Services\Disk","ErrorControl",0x00010001,0x00000000 -HKLM,"SYSTEM\CurrentControlSet\Services\Disk","Group",0x00000000,"SCSI Class" -HKLM,"SYSTEM\CurrentControlSet\Services\Disk","ImagePath",0x00020000,"system32\drivers\disk.sys" -HKLM,"SYSTEM\CurrentControlSet\Services\Disk","Start",0x00010001,0x00000000 -HKLM,"SYSTEM\CurrentControlSet\Services\Disk","Type",0x00010001,0x00000001 diff --git a/drivers/storage/class/disk/license.txt b/drivers/storage/class/disk/license.txt deleted file mode 100644 index 28ba760a5ad..00000000000 --- a/drivers/storage/class/disk/license.txt +++ /dev/null @@ -1,53 +0,0 @@ -Window NT Device Driver Kit -END-USER LICENSE AGREEMENT FOR MICROSOFT SOFTWARE - -IMPORTANT-READ CAREFULLY: This Microsoft End-User License Agreement ("EULA") is a legal agreement between you (either an individual or a single entity) and Microsoft Corporation for the Microsoft software product identified above, which includes computer software and associated media and printed materials, and may include "online" or electronic documentation ("SOFTWARE PRODUCT" or "SOFTWARE"). By installing, copying, or otherwise using the SOFTWARE PRODUCT, you agree to be bound by the terms of this EULA. If you do not agree to the terms of this EULA, promptly return the unused SOFTWARE PRODUCT to the place from which you obtained it for a full refund, or if you received the SOFTWARE PRODUCT as part of a subscription or other service from Microsoft, you may cancel the subscription and receive a refund of a prorata portion of the subscription price. - -SOFTWARE PRODUCT LICENSE -The SOFTWARE PRODUCT is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. The SOFTWARE PRODUCT is licensed, not sold. To develop Windows NT(tm) device drivers, you will need to utilize two computers, one for development and one for debugging. - -1. GRANT OF LICENSE. This EULA grants you the following limited, non-exclusive rights: -* SOFTWARE PRODUCT. (a) You may make two (2) copies of the SOFTWARE PRODUCT for installation and use on two (2) computers, one for use in development and one for use in debugging to design, develop, and test your software product(s), including but not limited to device driver(s) and other software products, for use with Microsoft(r) Windows(r) or Windows NT ("Software Product"). You may make an additional copy of the Windows NT Workstation operating system (licensed and provided separately) for use on a single computer used for debugging purposes. -* Microsoft Developer Network Subscriber. If you acquired the SOFTWARE PRODUCT through a subscription to the Microsoft Developer Network, and you are either an individual developer or an individual designated within a single entity, you are granted the following additional rights with respect to the SOFTWARE PRODUCT: (a) you may make and use copies of the SOFTWARE PRODUCT on up to ten (10) separate computers, provided that you are the only individual using the SOFTWARE PRODUCT on each such computer, and (b) if you are a single entity, you may designate one individual within your organization to have the right to use the SOFTWARE PRODUCT in the manner described herein. -* SAMPLE CODE. You may modify the sample source code ("Sample Code") to design, develop and test your Software Product, and reproduce and distribute the Sample Code with such modifications in source and object code forms, provided that you comply with the Distribution Requirements described below. -* DISTRIBUTION REQUIREMENTS. You may copy and redistribute the Sample Code as described above, provided that (a) you distribute the Sample Code only in conjunction with and as a part of your Software Product; (b) you do not make any statements to the effect or which imply that your Software Product is "certified" by Microsoft or that its performance is guaranteed by Microsoft; (c) you do not use Microsoft's name, logo, or trademarks to market your Software Product; (d) you include a valid copyright notice on your Software Product; and (e) you indemnify, hold harmless, and defend Microsoft from and against any claims or lawsuits, including attorneys' fees, that arise or result from the use or distribution of your Software Product. Contact Microsoft for the applicable royalties due and other licensing terms for all other uses and/or distribution of the Sample Code -* Microsoft reserves all rights not expressly granted to you. - -2. COPYRIGHT. All right, title, and copyrights in and to the SOFTWARE PRODUCT (including but not limited to any images, photographs, animations, video, audio, music, text, and "applets" incorporated into the SOFTWARE PRODUCT), and any copies of the SOFTWARE PRODUCT, are owned by Microsoft or its suppliers. The SOFTWARE PRODUCT is protected by copyright laws and international treaty provisions. Therefore, you must treat the SOFTWARE PRODUCT like any other copyrighted material except that you may either (a) make one copy of the SOFTWARE PRODUCT solely for backup or archival purposes, or (b) install the SOFTWARE PRODUCT on a single computer, provided you keep the original solely for backup or archival purposes. You may not copy the printed materials accompanying the SOFTWARE PRODUCT. - -3. PRERELEASE CODE. The SOFTWARE PRODUCT may contain PRERELEASE CODE that is not at the level of performance and compatibility of the final, generally available, product offering. These portions of the SOFTWARE PRODUCT may not operate correctly and may be substantially modified prior to first commercial shipment. Microsoft is not obligated to make this or any later version of the SOFTWARE PRODUCT commercially available. Microsoft grants you the right to distribute test versions of your Application created using the PRERELEASE CODE provided you comply with the Distribution Requirements described in Section 1 and the following additional provisions: (a) you must mark the test version of your Application "BETA" and (b) you are solely responsible for updating your customers with versions of your Application that operate satisfactorily with the final commercial release of the PRERELEASE CODE. - -4. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS. -( Limitations on Reverse Engineering, Decompilation, and Disassembly. You may not reverse-engineer, decompile, or disassemble the SOFTWARE PRODUCT, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation. -( Rental. You may not rent or lease the SOFTWARE PRODUCT. -( Software Transfer. You may permanently transfer all of your rights under this EULA, provided you retain no copies, you transfer all of the SOFTWARE PRODUCT (including all component parts, the media and printed materials, any upgrades, this EULA, and, if applicable, the Certificate of Authenticity), and the recipient agrees to the terms of this EULA. If the SOFTWARE PRODUCT is an upgrade, any transfer must include all prior versions of the SOFTWARE PRODUCT. -( Termination. Without prejudice to any other rights, Microsoft may terminate this EULA if you fail to comply with the terms and conditions of this EULA. In such event, you must destroy all copies of the SOFTWARE PRODUCT and all of its component parts. - -5. EXPORT RESTRICTIONS. You agree that neither you nor your customers intend to or will, directly or indirectly, export or transmit (a) the SOFTWARE PRODUCT or related documentation and technical data or (b) your Application as described in Section 1 of this Agreement (or any part thereof), or process, or service that is the direct product of the SOFTWARE PRODUCT to any country to which such export or transmission is restricted by any applicable U.S. regulation or statute, without the prior written consent, if required, of the Bureau of Export Administration of the U.S. Department of Commerce, or such other governmental entity as may have jurisdiction over such export or transmission. - -NO WARRANTIES. To the maximum extent permitted by applicable law, Microsoft expressly disclaims any warranty for the SOFTWARE PRODUCT. The SOFTWARE PRODUCT and any related documentation are provided "as is" without warranty of any kind, either express or implied, including, without limitation, the implied warranties of merchantability or fitness for a particular purpose. The entire risk arising out of use or performance of the SOFTWARE PRODUCT remains with you. - -LIMITATION OF LIABILITY. Microsoft's entire liability and your exclusive remedy under this EULA shall not exceed one hundred dollars (US$100.00). - -NO LIABILITY FOR CONSEQUENTIAL DAMAGES. To the maximum extent permitted by applicable law, in no event shall Microsoft or its suppliers be liable for any damages whatsoever (including, without limitation, damages for loss of business profit, business interruption, loss of business information, or any other pecuniary loss) arising out of the use or inability to use this Microsoft product, even if Microsoft has been advised of the possibility of such damages. Because some states/jurisdictions do not allow the exclusion or limitation of liability for consequential or incidental damages, the above limitation may not apply to you. - -U.S. GOVERNMENT RESTRICTED RIGHTS.The SOFTWARE and documentation are provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and (2) of the Commercial Computer Software -- Restricted Rights at 48 CFR 52.227-19, as applicable. Manufacturer is Microsoft Corporation/One Microsoft Way/Redmond, WA 98052-6399. - -If you acquired this product in the United States, this Agreement is governed by the laws of the State of Washington. If you acquired this product outside the United States, local law may apply. - -Should you have any questions concerning this Agreement, if you desire rights to use the product beyond what is listed here, or if you desire to contact Microsoft for any reason, please contact your local Microsoft subsidiary or sales office or write to: Microsoft Sales and Service, One Microsoft Way, Redmond, WA 98052-6399. - -Si vous avez acquis votre produit Microsoft au CANADA, la garantie limite suivante vous concerne : - -GARANTIE LIMITE - -EXCLUSION DE GARANTIES. Microsoft renonce entirement toute garantie pour le LOGICIEL. Le LOGICIEL et toute autre documentation s'y rapportant sont fournis comme tels sans aucune garantie quelle qu'elle soit, expresse ou implicite, y compris, mais ne se limitant pas, aux garanties implicites de la qualit marchande ou un usage particulier. Le risque total dcoulant de l'utilisation ou de la performance du LOGICIEL est entre vos mains. - -RESPONSABILIT LIMITE. La seule obligation de Microsoft et votre recours exclusif concernant ce contrat n'excderont pas cent dollars (US$100.00). - -ABSENCE DE RESPONSABILIT POUR LES DOMMAGES INDIRECTS. Microsoft ou ses fournisseurs ne pourront tre tenus responsables en aucune circonstance de tout dommage quel qu'il soit (y compris mais non de faon limitative aux dommages directs ou indirects causs par la perte de bnfices commerciaux, l'interruption des affaires, la perte d'information commerciale ou toute autre perte pcuniaire) rsultant de l'utilisation ou de l'impossibilit d'utilisation de ce produit, et ce, mme si la socit Microsoft a t avise de l'ventualit de tels dommages. Certains tats/juridictions ne permettent pas l'exclusion ou la limitation de responsabilit relative aux dommages indirects ou conscutifs, et la limitation ci-dessus peut ne pas s'appliquer votre gard. - -La prsente Convention est rgie par les lois de la province d'Ontario, Canada. Chacune des parties la prsente reconnat irrvocablement la comptence des tribunaux de la province d'Ontario et consent instituer tout litige qui pourrait dcouler de la prsente auprs des tribunaux situs dans le district judiciaire de York, province d'Ontario. - -Au cas o vous auriez des questions concernant cette licence ou que vous dsiriez vous mettre en rapport avec Microsoft pour quelque raison que ce soit, veuillez contacter la succursale Microsoft desservant votre pays, dont l'adresse est fournie dans ce produit, ou crire : Microsoft Customer Sales and Service, One Microsoft Way, Redmond, Washington 98052-6399. - diff --git a/drivers/storage/class/include/class2.h b/drivers/storage/class/include/class2.h deleted file mode 100644 index e1e0cf01ef7..00000000000 --- a/drivers/storage/class/include/class2.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: services/storage/include/class2.h - * PURPOSE: SCSI class driver definitions - * PROGRAMMER: Eric Kohl - */ - -#pragma once - -#include -#include - -#define MAXIMUM_RETRIES 15 -#define RETRY_WAIT 2000000 /* 200 ms in units of 100 ns */ - -// -// Indicates that the device has write caching enabled. -// - -#define DEV_WRITE_CACHE 0x00000001 - - -// -// Build SCSI 1 or SCSI 2 CDBs -// - -#define DEV_USE_SCSI1 0x00000002 - -// -// Indicates whether is is safe to send StartUnit commands -// to this device. It will only be off for some removeable devices. -// - -#define DEV_SAFE_START_UNIT 0x00000004 - -// -// Indicates whether it is unsafe to send SCSIOP_MECHANISM_STATUS commands to -// this device. Some devices don't like these 12 byte commands -// - -#define DEV_NO_12BYTE_CDB 0x00000008 - - -struct _CLASS_INIT_DATA; - -typedef VOID -(NTAPI *PCLASS_ERROR)(IN PDEVICE_OBJECT DeviceObject, - IN PSCSI_REQUEST_BLOCK Srb, - IN OUT NTSTATUS *Status, - IN OUT BOOLEAN *Retry); - -typedef BOOLEAN -(NTAPI *PCLASS_DEVICE_CALLBACK)(IN PINQUIRYDATA); - -typedef NTSTATUS -(NTAPI *PCLASS_READ_WRITE)(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -typedef BOOLEAN -(NTAPI *PCLASS_FIND_DEVICES)(IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN struct _CLASS_INIT_DATA *InitializationData, - IN PDEVICE_OBJECT PortDeviceObject, - IN ULONG PortNumber); - -typedef NTSTATUS -(NTAPI *PCLASS_DEVICE_CONTROL)(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -typedef NTSTATUS -(NTAPI *PCLASS_SHUTDOWN_FLUSH)(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -typedef NTSTATUS -(NTAPI *PCLASS_CREATE_CLOSE)(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - - -typedef struct _CLASS_INIT_DATA -{ - ULONG InitializationDataSize; - ULONG DeviceExtensionSize; - DEVICE_TYPE DeviceType; - ULONG DeviceCharacteristics; - PCLASS_ERROR ClassError; - PCLASS_READ_WRITE ClassReadWriteVerification; - PCLASS_DEVICE_CALLBACK ClassFindDeviceCallBack; - PCLASS_FIND_DEVICES ClassFindDevices; - PCLASS_DEVICE_CONTROL ClassDeviceControl; - PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush; - PCLASS_CREATE_CLOSE ClassCreateClose; - PDRIVER_STARTIO ClassStartIo; -} CLASS_INIT_DATA, *PCLASS_INIT_DATA; - - -typedef struct _DEVICE_EXTENSION -{ - PDEVICE_OBJECT DeviceObject; - PDEVICE_OBJECT PortDeviceObject; - LARGE_INTEGER PartitionLength; - LARGE_INTEGER StartingOffset; - ULONG DMByteSkew; - ULONG DMSkew; - BOOLEAN DMActive; - PCLASS_ERROR ClassError; - PCLASS_READ_WRITE ClassReadWriteVerification; - PCLASS_FIND_DEVICES ClassFindDevices; - PCLASS_DEVICE_CONTROL ClassDeviceControl; - PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush; - PCLASS_CREATE_CLOSE ClassCreateClose; - PDRIVER_STARTIO ClassStartIo; - PIO_SCSI_CAPABILITIES PortCapabilities; - PDISK_GEOMETRY_EX DiskGeometry; - PDEVICE_OBJECT PhysicalDevice; - PSENSE_DATA SenseData; - ULONG TimeOutValue; - ULONG DeviceNumber; - ULONG SrbFlags; - ULONG ErrorCount; - KSPIN_LOCK SplitRequestSpinLock; - NPAGED_LOOKASIDE_LIST SrbLookasideListHead; - LONG LockCount; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR SectorShift; - UCHAR ReservedByte; - USHORT DeviceFlags; - PKEVENT MediaChangeEvent; - HANDLE MediaChangeEventHandle; - BOOLEAN MediaChangeNoMedia; - ULONG MediaChangeCount; - UNICODE_STRING DeviceName; -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; - - -typedef struct _COMPLETION_CONTEXT -{ - PDEVICE_OBJECT DeviceObject; - SCSI_REQUEST_BLOCK Srb; -} COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT; - - -/* FUNCTIONS ****************************************************************/ - -IO_COMPLETION_ROUTINE ScsiClassAsynchronousCompletion; -NTSTATUS NTAPI -ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context); - -VOID NTAPI -ScsiClassBuildRequest(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS NTAPI -ScsiClassClaimDevice(IN PDEVICE_OBJECT PortDeviceObject, - IN PSCSI_INQUIRY_DATA LunInfo, - IN BOOLEAN Release, - OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL); - -NTSTATUS NTAPI -ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, - IN PCCHAR ObjectNameBuffer, - IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, - IN OUT PDEVICE_OBJECT *DeviceObject, - IN PCLASS_INIT_DATA InitializationData); - -NTSTATUS NTAPI -ScsiClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -PVOID NTAPI -ScsiClassFindModePage(IN PCHAR ModeSenseBuffer, - IN ULONG Length, - IN UCHAR PageMode, - IN BOOLEAN Use6Byte); - -ULONG NTAPI -ScsiClassFindUnclaimedDevices(IN PCLASS_INIT_DATA InitializationData, - OUT PSCSI_ADAPTER_BUS_INFO AdapterInformation); - -NTSTATUS NTAPI -ScsiClassGetCapabilities(IN PDEVICE_OBJECT PortDeviceObject, - OUT PIO_SCSI_CAPABILITIES *PortCapabilities); - -NTSTATUS NTAPI -ScsiClassGetInquiryData(IN PDEVICE_OBJECT PortDeviceObject, - OUT PSCSI_ADAPTER_BUS_INFO *ConfigInfo); - -ULONG NTAPI -ScsiClassInitialize(IN PVOID Argument1, - IN PVOID Argument2, - IN PCLASS_INIT_DATA InitializationData); - -VOID NTAPI -ScsiClassInitializeSrbLookasideList(IN PDEVICE_EXTENSION DeviceExtension, - IN ULONG NumberElements); - -NTSTATUS NTAPI -ScsiClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -BOOLEAN NTAPI -ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject, - IN PSCSI_REQUEST_BLOCK Srb, - IN UCHAR MajorFunctionCode, - IN ULONG IoDeviceCode, - IN ULONG RetryCount, - OUT NTSTATUS *Status); - -NTSTATUS NTAPI -ScsiClassIoComplete(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context); - -NTSTATUS NTAPI -ScsiClassIoCompleteAssociated(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context); - -ULONG NTAPI -ScsiClassModeSense(IN PDEVICE_OBJECT DeviceObject, - IN PCHAR ModeSenseBuffer, - IN ULONG Length, - IN UCHAR PageMode); - -ULONG NTAPI -ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath); - -NTSTATUS NTAPI -ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject); - -VOID NTAPI -ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject); - -NTSTATUS NTAPI -ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - PIRP Irp, - PVOID BufferAddress, - ULONG BufferLength, - BOOLEAN WriteToDevice); - -NTSTATUS NTAPI -ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - PVOID BufferAddress, - ULONG BufferLength, - BOOLEAN WriteToDevice); - -VOID NTAPI -ScsiClassSplitRequest(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN ULONG MaximumBytes); - -NTSTATUS -NTAPI -ScsiClassCheckVerifyComplete( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -/* EOF */ diff --git a/drivers/storage/inc/class.h b/drivers/storage/inc/class.h deleted file mode 100644 index eaf4045b468..00000000000 --- a/drivers/storage/inc/class.h +++ /dev/null @@ -1,374 +0,0 @@ -/*++ - -Copyright (c) 1991 Microsoft Corporation - -Module Name: - - class.h - -Abstract: - - These are the structures and defines that are used in the - SCSI class drivers. - -Author: - - Mike Glass (mglass) - Jeff Havens (jhavens) - -Revision History: - ---*/ - -#ifndef _CLASS_ - -#include -#include -#include -#include -#include -#include "ntddscsi.h" -#include - -// begin_ntminitape - -#if DBG - -#define DebugPrint(x) ScsiDebugPrint x - -#else - -#define DebugPrint(x) - -#endif // DBG - -// end_ntminitape - -#ifdef POOL_TAGGING -#undef ExAllocatePool -#undef ExAllocatePoolWithQuota -#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'HscS') -#define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,'HscS') -#endif - -#define MAXIMUM_RETRIES 4 - -typedef -VOID -(*PCLASS_ERROR) ( - IN PDEVICE_OBJECT DeviceObject, - IN PSCSI_REQUEST_BLOCK Srb, - IN OUT NTSTATUS *Status, - IN OUT BOOLEAN *Retry - ); - -typedef struct _DEVICE_EXTENSION { - - // - // Back pointer to device object - // - - PDEVICE_OBJECT DeviceObject; - - // - // Pointer to port device object - // - - PDEVICE_OBJECT PortDeviceObject; - - // - // Length of partition in bytes - // - - LARGE_INTEGER PartitionLength; - - // - // Number of bytes before start of partition - // - - LARGE_INTEGER StartingOffset; - - // - // Bytes to skew all requests, since DM Driver has been placed on an IDE drive. - // - - ULONG DMByteSkew; - - // - // Sectors to skew all requests. - // - - ULONG DMSkew; - - // - // Flag to indicate whether DM driver has been located on an IDE drive. - // - - BOOLEAN DMActive; - - // - // Pointer to the specific class error routine. - // - - PCLASS_ERROR ClassError; - - // - // SCSI port driver capabilities - // - - PIO_SCSI_CAPABILITIES PortCapabilities; - - // - // Buffer for drive parameters returned in IO device control. - // - - PDISK_GEOMETRY DiskGeometry; - - // - // Back pointer to device object of physical device - // - - PDEVICE_OBJECT PhysicalDevice; - - // - // Request Sense Buffer - // - - PSENSE_DATA SenseData; - - // - // Request timeout in seconds; - // - - ULONG TimeOutValue; - - // - // System device number - // - - ULONG DeviceNumber; - - // - // Add default Srb Flags. - // - - ULONG SrbFlags; - - // - // Total number of SCSI protocol errors on the device. - // - - ULONG ErrorCount; - - // - // Spinlock for split requests - // - - KSPIN_LOCK SplitRequestSpinLock; - - // - // Zone header and spin lock for zoned SRB requests. - // - - PZONE_HEADER SrbZone; - - PKSPIN_LOCK SrbZoneSpinLock; - - // - // Lock count for removable media. - // - - LONG LockCount; - - // - // Scsi port number - // - - UCHAR PortNumber; - - // - // SCSI path id - // - - UCHAR PathId; - - // - // SCSI bus target id - // - - UCHAR TargetId; - - // - // SCSI bus logical unit number - // - - UCHAR Lun; - - // - // Log2 of sector size - // - - UCHAR SectorShift; - - // - // Flag to indicate that the device has write caching enabled. - // - - BOOLEAN WriteCache; - - // - // Build SCSI 1 or SCSI 2 CDBs - // - - BOOLEAN UseScsi1; - -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; - -// -// Define context structure for asynchronous completions. -// - -typedef struct _COMPLETION_CONTEXT { - PDEVICE_OBJECT DeviceObject; - SCSI_REQUEST_BLOCK Srb; -}COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT; - - -NTSTATUS -ScsiClassGetCapabilities( - IN PDEVICE_OBJECT PortDeviceObject, - OUT PIO_SCSI_CAPABILITIES *PortCapabilities - ); - -NTSTATUS -ScsiClassGetInquiryData( - IN PDEVICE_OBJECT PortDeviceObject, - IN PSCSI_ADAPTER_BUS_INFO *ConfigInfo - ); - -NTSTATUS -ScsiClassReadDriveCapacity( - IN PDEVICE_OBJECT DeviceObject - ); - -VOID -ScsiClassReleaseQueue( - IN PDEVICE_OBJECT DeviceObject - ); - -NTSTATUS -ScsiClassRemoveDevice( - IN PDEVICE_OBJECT PortDeviceObject, - IN UCHAR PathId, - IN UCHAR TargetId, - IN UCHAR Lun - ); - -NTSTATUS -ScsiClassAsynchronousCompletion( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Context - ); - -VOID -ScsiClassSplitRequest( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN ULONG MaximumBytes - ); - -NTSTATUS -ScsiClassDeviceControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ); - -NTSTATUS -ScsiClassIoComplete( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -NTSTATUS -ScsiClassIoCompleteAssociated( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ); - -BOOLEAN -ScsiClassInterpretSenseInfo( - IN PDEVICE_OBJECT DeviceObject, - IN PSCSI_REQUEST_BLOCK Srb, - IN UCHAR MajorFunctionCode, - IN ULONG IoDeviceCode, - IN ULONG RetryCount, - OUT NTSTATUS *Status - ); - -NTSTATUS -ScsiClassSendSrbSynchronous( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - PVOID BufferAddress, - ULONG BufferLength, - BOOLEAN WriteToDevice - ); - -NTSTATUS -ScsiClassSendSrbAsynchronous( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - PIRP Irp, - PVOID BufferAddress, - ULONG BufferLength, - BOOLEAN WriteToDevice - ); - -VOID -ScsiClassBuildRequest( - PDEVICE_OBJECT DeviceObject, - PIRP Irp - ); - -ULONG -ScsiClassModeSense( - IN PDEVICE_OBJECT DeviceObject, - IN PCHAR ModeSenseBuffer, - IN ULONG Length, - IN UCHAR PageMode - ); - -BOOLEAN -ScsiClassModeSelect( - IN PDEVICE_OBJECT DeviceObject, - IN PCHAR ModeSelectBuffer, - IN ULONG Length, - IN BOOLEAN SavePage - ); - -PVOID -ScsiClassFindModePage( - IN PCHAR ModeSenseBuffer, - IN ULONG Length, - IN UCHAR PageMode - ); - -NTSTATUS -ScsiClassClaimDevice( - IN PDEVICE_OBJECT PortDeviceObject, - IN PSCSI_INQUIRY_DATA LunInfo, - IN BOOLEAN Release, - OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL - ); - -NTSTATUS -ScsiClassInternalIoControl ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -#endif /* _CLASS_ */ - diff --git a/drivers/storage/inc/ide.h b/drivers/storage/inc/ide.h deleted file mode 100644 index b8688d17299..00000000000 --- a/drivers/storage/inc/ide.h +++ /dev/null @@ -1,495 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, 1999 - 1999 - -Module Name: - - ide.h - -Abstract: - - These are the structures and defines that are used in the - PCI IDE mini drivers. - -Revision History: - ---*/ - - -#if !defined (___ide_h___) -#define ___ide_h___ - -#include "ideuser.h" - -#define MAX_IDE_DEVICE 2 -#define MAX_IDE_LINE 2 -#define MAX_IDE_CHANNEL 2 - -// -// Some miniports need this structure. -// IdentifyData is passed to the miniport in -// the XfermodeSelect structure -// - -// -// IDENTIFY data -// - -#pragma pack (1) -typedef struct _IDENTIFY_DATA { - USHORT GeneralConfiguration; // 00 00 - USHORT NumCylinders; // 02 1 - USHORT Reserved1; // 04 2 - USHORT NumHeads; // 06 3 - USHORT UnformattedBytesPerTrack; // 08 4 - USHORT UnformattedBytesPerSector; // 0A 5 - USHORT NumSectorsPerTrack; // 0C 6 - USHORT VendorUnique1[3]; // 0E 7-9 - UCHAR SerialNumber[20]; // 14 10-19 - USHORT BufferType; // 28 20 - USHORT BufferSectorSize; // 2A 21 - USHORT NumberOfEccBytes; // 2C 22 - UCHAR FirmwareRevision[8]; // 2E 23-26 - UCHAR ModelNumber[40]; // 36 27-46 - UCHAR MaximumBlockTransfer; // 5E 47 - UCHAR VendorUnique2; // 5F - USHORT DoubleWordIo; // 60 48 - USHORT Capabilities; // 62 49 - USHORT Reserved2; // 64 50 - UCHAR VendorUnique3; // 66 51 - UCHAR PioCycleTimingMode; // 67 - UCHAR VendorUnique4; // 68 52 - UCHAR DmaCycleTimingMode; // 69 - USHORT TranslationFieldsValid:3; // 6A 53 - USHORT Reserved3:13; - USHORT NumberOfCurrentCylinders; // 6C 54 - USHORT NumberOfCurrentHeads; // 6E 55 - USHORT CurrentSectorsPerTrack; // 70 56 - ULONG CurrentSectorCapacity; // 72 57-58 - USHORT CurrentMultiSectorSetting; // 59 - ULONG UserAddressableSectors; // 60-61 - USHORT SingleWordDMASupport : 8; // 62 - USHORT SingleWordDMAActive : 8; - USHORT MultiWordDMASupport : 8; // 63 - USHORT MultiWordDMAActive : 8; - USHORT AdvancedPIOModes : 8; // 64 - USHORT Reserved4 : 8; - USHORT MinimumMWXferCycleTime; // 65 - USHORT RecommendedMWXferCycleTime; // 66 - USHORT MinimumPIOCycleTime; // 67 - USHORT MinimumPIOCycleTimeIORDY; // 68 - USHORT Reserved5[11]; // 69-79 - USHORT MajorRevision; // 80 - USHORT MinorRevision; // 81 - USHORT Reserved6; // 82 - USHORT CommandSetSupport; // 83 - USHORT Reserved6a[2]; // 84-85 - USHORT CommandSetActive; // 86 - USHORT Reserved6b; // 87 - USHORT UltraDMASupport : 8; // 88 - USHORT UltraDMAActive : 8; // - USHORT Reserved7[11]; // 89-99 - ULONG Max48BitLBA[2]; // 100-103 - USHORT Reserved7a[22]; // 104-125 - USHORT LastLun:3; // 126 - USHORT Reserved8:13; - USHORT MediaStatusNotification:2; // 127 - USHORT Reserved9:6; - USHORT DeviceWriteProtect:1; - USHORT Reserved10:7; - USHORT Reserved11[128]; // 128-255 -} IDENTIFY_DATA, *PIDENTIFY_DATA; - -// -// Identify data without the Reserved4. -// - -//typedef struct _IDENTIFY_DATA2 { -// USHORT GeneralConfiguration; // 00 00 -// USHORT NumCylinders; // 02 1 -// USHORT Reserved1; // 04 2 -// USHORT NumHeads; // 06 3 -// USHORT UnformattedBytesPerTrack; // 08 4 -// USHORT UnformattedBytesPerSector; // 0A 5 -// USHORT NumSectorsPerTrack; // 0C 6 -// USHORT VendorUnique1[3]; // 0E 7-9 -// UCHAR SerialNumber[20]; // 14 10-19 -// USHORT BufferType; // 28 20 -// USHORT BufferSectorSize; // 2A 21 -// USHORT NumberOfEccBytes; // 2C 22 -// UCHAR FirmwareRevision[8]; // 2E 23-26 -// UCHAR ModelNumber[40]; // 36 27-46 -// UCHAR MaximumBlockTransfer; // 5E 47 -// UCHAR VendorUnique2; // 5F -// USHORT DoubleWordIo; // 60 48 -// USHORT Capabilities; // 62 49 -// USHORT Reserved2; // 64 50 -// UCHAR VendorUnique3; // 66 51 -// UCHAR PioCycleTimingMode; // 67 -// UCHAR VendorUnique4; // 68 52 -// UCHAR DmaCycleTimingMode; // 69 -// USHORT TranslationFieldsValid:3; // 6A 53 -// USHORT Reserved3:13; -// USHORT NumberOfCurrentCylinders; // 6C 54 -// USHORT NumberOfCurrentHeads; // 6E 55 -// USHORT CurrentSectorsPerTrack; // 70 56 -// ULONG CurrentSectorCapacity; // 72 57-58 -// USHORT CurrentMultiSectorSetting; // 59 -// ULONG UserAddressableSectors; // 60-61 -// USHORT SingleWordDMASupport : 8; // 62 -// USHORT SingleWordDMAActive : 8; -// USHORT MultiWordDMASupport : 8; // 63 -// USHORT MultiWordDMAActive : 8; -// USHORT AdvancedPIOModes : 8; // 64 -// USHORT Reserved4 : 8; -// USHORT MinimumMWXferCycleTime; // 65 -// USHORT RecommendedMWXferCycleTime; // 66 -// USHORT MinimumPIOCycleTime; // 67 -// USHORT MinimumPIOCycleTimeIORDY; // 68 -// USHORT Reserved5[11]; // 69-79 -// USHORT MajorRevision; // 80 -// USHORT MinorRevision; // 81 -// USHORT Reserved6[6]; // 82-87 -// USHORT UltraDMASupport : 8; // 88 -// USHORT UltraDMAActive : 8; // -// USHORT Reserved7[37]; // 89-125 -// USHORT LastLun:3; // 126 -// USHORT Reserved8:13; -// USHORT MediaStatusNotification:2; // 127 -// USHORT Reserved9:6; -// USHORT DeviceWriteProtect:1; -// USHORT Reserved10:7; -//} IDENTIFY_DATA2, *PIDENTIFY_DATA2; -#pragma pack () - -#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA) - - -// -// The structure is passed to pci ide mini driver -// TransferModeSelect callback for selecting -// proper transfer mode the the devices connected -// to the given IDE channel -// -typedef struct _PCIIDE_TRANSFER_MODE_SELECT { - - // - // Input Parameters - // - - // - // IDE Channel Number. 0 or 1 - // - ULONG Channel; - - // - // Indicate whether devices are present - // - BOOLEAN DevicePresent[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // Indicate whether devices are ATA harddisk - // - BOOLEAN FixedDisk[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // Indicate whether devices support IO Ready Line - // - BOOLEAN IoReadySupported[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // Indicate the data transfer modes devices support - // - ULONG DeviceTransferModeSupported[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // Indicate devices' best timings for PIO, single word DMA, - // multiword DMA, and Ultra DMA modes - // - ULONG BestPioCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE]; - ULONG BestSwDmaCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE]; - ULONG BestMwDmaCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE]; - ULONG BestUDmaCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // Indicate devices' current data transfer modes - // - ULONG DeviceTransferModeCurrent[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // The user's choice. This will allow pciidex to - // default to a transfer mode indicated by the mini driver - // - ULONG UserChoiceTransferMode[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // This enables UDMA66 on the intel chipsets - // - ULONG EnableUDMA66; - - // - //Some miniports need this - // The miniport will save this data in their deviceExtension - // - IDENTIFY_DATA IdentifyData[MAX_IDE_DEVICE]; - - - // - // Output Parameters - // - - // - // Indicate devices' data transfer modes chosen by - // the pcii ide mini drive - // - ULONG DeviceTransferModeSelected[MAX_IDE_DEVICE * MAX_IDE_LINE]; - - // - // Transfermode timings - // - PULONG TransferModeTimingTable; - ULONG TransferModeTableLength; - -} PCIIDE_TRANSFER_MODE_SELECT, *PPCIIDE_TRANSFER_MODE_SELECT; - -// -// possible ide channel state -// - -typedef enum { - ChannelDisabled = 0, - ChannelEnabled, - ChannelStateUnknown -} IDE_CHANNEL_STATE; - - -// -// Prototype for different PCI IDE mini driver -// callbacks -// -typedef IDE_CHANNEL_STATE - (*PCIIDE_CHANNEL_ENABLED) ( - IN PVOID DeviceExtension, - IN ULONG Channel - ); - -typedef BOOLEAN - (*PCIIDE_SYNC_ACCESS_REQUIRED) ( - IN PVOID DeviceExtension - ); - -typedef NTSTATUS - (*PCIIDE_TRANSFER_MODE_SELECT_FUNC) ( - IN PVOID DeviceExtension, - IN OUT PPCIIDE_TRANSFER_MODE_SELECT TransferModeSelect - ); - -typedef ULONG - (*PCIIDE_USEDMA_FUNC)( - IN PVOID deviceExtension, - IN PVOID cdbCmd, - IN UCHAR targetID - ); - -typedef NTSTATUS - (*PCIIDE_UDMA_MODES_SUPPORTED) ( - IDENTIFY_DATA IdentifyData, - PULONG BestXferMode, - PULONG CurrentMode - ); -// -// This structure is for the PCI IDE mini driver to -// return its properties -// -typedef struct _IDE_CONTROLLER_PROPERTIES { - - // - // sizeof (IDE_CONTROLLER_PROPERTIES) - // - ULONG Size; - - // - // Indicate the amount of memory PCI IDE mini driver - // needs for its private data - // - ULONG ExtensionSize; - - // - // Indicate all the data transfer modes the PCI IDE - // controller supports - // - ULONG SupportedTransferMode[MAX_IDE_CHANNEL][MAX_IDE_DEVICE]; - - // - // callback to query whether a IDE channel is enabled - // - PCIIDE_CHANNEL_ENABLED PciIdeChannelEnabled; - - // - // callback to query whether both IDE channels requires - // synchronized access. (one channel at a time) - // - PCIIDE_SYNC_ACCESS_REQUIRED PciIdeSyncAccessRequired; - - // - // callback to select proper transfer modes for the - // given devices - // - PCIIDE_TRANSFER_MODE_SELECT_FUNC PciIdeTransferModeSelect; - - // - // at the end of a ATA data transfer, ignores busmaster - // status active bit. Normally, it should be FALSE - // - BOOLEAN IgnoreActiveBitForAtaDevice; - - // - // always clear the busmaster interrupt on every interrupt - // generated by the device. Normally, it should be FALSE - // - BOOLEAN AlwaysClearBusMasterInterrupt; - - // - // callback to determine whether DMA should be used or not - // called for every IO - // - PCIIDE_USEDMA_FUNC PciIdeUseDma; - - - // - // if the miniport needs a different alignment - // - ULONG AlignmentRequirement; - - ULONG DefaultPIO; - - // - // retrieves the supported udma modes from the Identify data - // - PCIIDE_UDMA_MODES_SUPPORTED PciIdeUdmaModesSupported; - -} IDE_CONTROLLER_PROPERTIES, *PIDE_CONTROLLER_PROPERTIES; - -// -// callback to query PCI IDE controller properties -// -typedef -NTSTATUS (*PCONTROLLER_PROPERTIES) ( - IN PVOID DeviceExtension, - IN PIDE_CONTROLLER_PROPERTIES ControllerProperties - ); - - -// -// To initialize PCI IDE mini driver -// -NTSTATUS -PciIdeXInitialize( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath, - IN PCONTROLLER_PROPERTIES PciIdeGetControllerProperties, - IN ULONG ExtensionSize - ); - -// -// To query PCI IDE config space data -// -NTSTATUS -PciIdeXGetBusData( - IN PVOID DeviceExtension, - IN PVOID Buffer, - IN ULONG ConfigDataOffset, - IN ULONG BufferLength - ); - -// -// To save PCI IDE config space data -// -NTSTATUS -PciIdeXSetBusData( - IN PVOID DeviceExtension, - IN PVOID Buffer, - IN PVOID DataMask, - IN ULONG ConfigDataOffset, - IN ULONG BufferLength - ); - - -#pragma pack(1) -typedef struct _PCIIDE_CONFIG_HEADER { - - USHORT VendorID; // (ro) - USHORT DeviceID; // (ro) - - // - // Command - // - union { - - struct { - - USHORT IoAccessEnable:1; // Device control - USHORT MemAccessEnable:1; - USHORT MasterEnable:1; - USHORT SpecialCycle:1; - USHORT MemWriteInvalidateEnable:1; - USHORT VgaPaletteSnoopEnable:1; - USHORT ParityErrorResponse:1; - USHORT WaitCycleEnable:1; - USHORT SystemErrorEnable:1; - USHORT FastBackToBackEnable:1; - USHORT CommandReserved:6; - } b; - - USHORT w; - - } Command; - - - USHORT Status; - UCHAR RevisionID; // (ro) - - // - // Program Interface - // - UCHAR Chan0OpMode:1; - UCHAR Chan0Programmable:1; - UCHAR Chan1OpMode:1; - UCHAR Chan1Programmable:1; - UCHAR ProgIfReserved:3; - UCHAR MasterIde:1; - - UCHAR SubClass; // (ro) - UCHAR BaseClass; // (ro) - UCHAR CacheLineSize; // (ro+) - UCHAR LatencyTimer; // (ro+) - UCHAR HeaderType; // (ro) - UCHAR BIST; // Built in self test - - struct _PCI_HEADER_TYPE_0 type0; - -} PCIIDE_CONFIG_HEADER, *PPCIIDE_CONFIG_HEADER; -#pragma pack() - -// -// Debug Print -// -#if DBG - -VOID -PciIdeXDebugPrint( - _In_ ULONG DebugPrintLevel, - _In_z_ _Printf_format_string_ PCCHAR DebugMessage, - ... - ); - -#define PciIdeXDebugPrint(x) PciIdeXDebugPrint x - -#else - -#define PciIdeXDebugPrint(x) - -#endif // DBG - -#endif // ___ide_h___ - diff --git a/drivers/storage/inc/ideuser.h b/drivers/storage/inc/ideuser.h deleted file mode 100644 index 622cdb89ed9..00000000000 --- a/drivers/storage/inc/ideuser.h +++ /dev/null @@ -1,132 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, 1999 - 1999 - -Module Name: - - ideuser.h - -Abstract: - - These are the structures and defines that are used in the - PCI IDE mini drivers. - -Revision History: - ---*/ - -#if !defined (___ideuser_h___) -#define ___ideuser_h___ - - -#define PIO_MODE0 (1 << 0) -#define PIO_MODE1 (1 << 1) -#define PIO_MODE2 (1 << 2) -#define PIO_MODE3 (1 << 3) -#define PIO_MODE4 (1 << 4) - -#define SWDMA_MODE0 (1 << 5) -#define SWDMA_MODE1 (1 << 6) -#define SWDMA_MODE2 (1 << 7) - -#define MWDMA_MODE0 (1 << 8) -#define MWDMA_MODE1 (1 << 9) -#define MWDMA_MODE2 (1 << 10) - -#define UDMA_MODE0 (1 << 11) -#define UDMA_MODE1 (1 << 12) -#define UDMA_MODE2 (1 << 13) -#define UDMA_MODE3 (1 << 14) -#define UDMA_MODE4 (1 << 15) -#define UDMA_MODE5 (1 << 16) - -#define PIO_SUPPORT (PIO_MODE0 | PIO_MODE1 | PIO_MODE2 | PIO_MODE3 | PIO_MODE4) -#define SWDMA_SUPPORT (SWDMA_MODE0 | SWDMA_MODE1 | SWDMA_MODE2) -#define MWDMA_SUPPORT (MWDMA_MODE0 | MWDMA_MODE1 | MWDMA_MODE2) -#define UDMA33_SUPPORT (UDMA_MODE0 | UDMA_MODE1 | UDMA_MODE2) -#define UDMA66_SUPPORT (UDMA_MODE3 | UDMA_MODE4) -#define UDMA100_SUPPORT (UDMA_MODE5 ) -#define UDMA_SUPPORT (UNINITIALIZED_TRANSFER_MODE & (~(PIO_SUPPORT | SWDMA_SUPPORT | MWDMA_SUPPORT))) - -#define DMA_SUPPORT (SWDMA_SUPPORT | MWDMA_SUPPORT | UDMA_SUPPORT) -#define ALL_MODE_SUPPORT (PIO_SUPPORT | DMA_SUPPORT) - -#define PIO0 0 -#define PIO1 1 -#define PIO2 2 -#define PIO3 3 -#define PIO4 4 -#define SWDMA0 5 -#define SWDMA1 6 -#define SWDMA2 7 -#define MWDMA0 8 -#define MWDMA1 9 -#define MWDMA2 10 -#define UDMA0 11 - -#define MAX_XFER_MODE 17 -#define UNINITIALIZED_CYCLE_TIME 0xffffffff -#define UNINITIALIZED_TRANSFER_MODE 0x7fffffff -#define IS_DEFAULT(mode) (!(mode & 0x80000000)) - -#define GenTransferModeMask(i, mode) {\ - ULONG temp=0xffffffff; \ - mode |= (temp >> (31-(i)));\ -} - -// -// mode should not be 0 -// -#define GetHighestTransferMode(mode, i) {\ - ULONG temp=(mode); \ - ASSERT(temp); \ - i=0; \ - while ( temp) { \ - temp = (temp >> 1);\ - i++;\ - } \ - i--; \ -} - -#define GetHighestDMATransferMode(mode, i) {\ - ULONG temp=mode >> 5;\ - i=5; \ - while ( temp) { \ - temp = (temp >> 1); \ - i++; \ - } \ - i--; \ -} -#define GetHighestPIOTransferMode(mode, i) { \ - ULONG temp = (mode & PIO_SUPPORT); \ - i=0; \ - temp = temp >> 1; \ - while (temp) { \ - temp = temp >> 1; \ - i++; \ - } \ -} - -#define SetDefaultTiming(timingTable, length) {\ - timingTable[0]=PIO_MODE0_CYCLE_TIME; \ - timingTable[1]=PIO_MODE1_CYCLE_TIME; \ - timingTable[2]=PIO_MODE2_CYCLE_TIME; \ - timingTable[3]=PIO_MODE3_CYCLE_TIME; \ - timingTable[4]=PIO_MODE4_CYCLE_TIME; \ - timingTable[5]=SWDMA_MODE0_CYCLE_TIME; \ - timingTable[6]=SWDMA_MODE1_CYCLE_TIME; \ - timingTable[7]=SWDMA_MODE2_CYCLE_TIME; \ - timingTable[8]=MWDMA_MODE0_CYCLE_TIME; \ - timingTable[9]=MWDMA_MODE1_CYCLE_TIME; \ - timingTable[10]=MWDMA_MODE2_CYCLE_TIME; \ - timingTable[11]=UDMA_MODE0_CYCLE_TIME; \ - timingTable[12]=UDMA_MODE1_CYCLE_TIME; \ - timingTable[13]=UDMA_MODE2_CYCLE_TIME; \ - timingTable[14]=UDMA_MODE3_CYCLE_TIME; \ - timingTable[15]=UDMA_MODE4_CYCLE_TIME; \ - timingTable[16]=UDMA_MODE5_CYCLE_TIME; \ - length = MAX_XFER_MODE; \ -} - -#endif // ___ideuser_h___ - diff --git a/drivers/storage/inc/physlogi.h b/drivers/storage/inc/physlogi.h deleted file mode 100644 index cc366c867b2..00000000000 --- a/drivers/storage/inc/physlogi.h +++ /dev/null @@ -1,115 +0,0 @@ -/*++ - -Copyright (c) 1992 Microsoft Corporation - -Module Name: - - physlogi.h - -Abstract: - - This file contains structures and defines that are used - specifically for the tape drivers. Contains #define's, - function protypes, etc. for use in calling functions in - physlogi.c that do physical to pseudo-logical and pseudo- - logical to physical tape block address/position translation. - -Author: - - Mike Colandreo (Maynard) - -Revision History: - ---*/ - -// begin_ntminitape - -// -// defines for QIC tape density codes -// - -#define QIC_XX 0 // ???? -#define QIC_24 5 // 0x05 -#define QIC_120 15 // 0x0F -#define QIC_150 16 // 0x10 -#define QIC_525 17 // 0x11 -#define QIC_1350 18 // 0x12 -#define QIC_1000 21 // 0x15 -#define QIC_1000C 30 // 0x1E -#define QIC_2100 31 // 0x1F -#define QIC_2GB 34 // 0x22 -#define QIC_5GB 40 // 0x28 - -// -// defines for QIC tape media codes -// - -#define DCXXXX 0 -#define DC300 1 -#define DC300XLP 2 -#define DC615 3 -#define DC600 4 -#define DC6037 5 -#define DC6150 6 -#define DC6250 7 -#define DC6320 8 -#define DC6525 9 -#define DC9135SL 33 //0x21 -#define DC9210 34 //0x22 -#define DC9135 35 //0x23 -#define DC9100 36 //0x24 -#define DC9120 37 //0x25 -#define DC9120SL 38 //0x26 -#define DC9164 39 //0x27 -#define DCXXXXFW 48 //0x30 -#define DC9200SL 49 //0x31 -#define DC9210XL 50 //0x32 -#define DC10GB 51 //0x33 -#define DC9200 52 //0x34 -#define DC9120XL 53 //0x35 -#define DC9210SL 54 //0x36 -#define DC9164XL 55 //0x37 -#define DC9200XL 64 //0x40 -#define DC9400 65 //0x41 -#define DC9500 66 //0x42 -#define DC9500SL 70 //0x46 - -// -// defines for translation reference point -// - -#define NOT_FROM_BOT 0 -#define FROM_BOT 1 - -// -// info/structure returned by/from -// TapeLogicalBlockToPhysicalBlock( ) -// - -typedef struct _TAPE_PHYS_POSITION { - ULONG SeekBlockAddress; - ULONG SpaceBlockCount; -} TAPE_PHYS_POSITION, PTAPE_PHYS_POSITION; - -// -// function prototypes -// - -TAPE_PHYS_POSITION -TapeClassLogicalBlockToPhysicalBlock( - IN UCHAR DensityCode, - IN ULONG LogicalBlockAddress, - IN ULONG BlockLength, - IN BOOLEAN FromBOT - ); - -ULONG -TapeClassPhysicalBlockToLogicalBlock( - IN UCHAR DensityCode, - IN ULONG PhysicalBlockAddress, - IN ULONG BlockLength, - IN BOOLEAN FromBOT - ); - -// end_ntminitape - diff --git a/drivers/storage/inc/rbc.h b/drivers/storage/inc/rbc.h deleted file mode 100644 index fc867ebebd4..00000000000 --- a/drivers/storage/inc/rbc.h +++ /dev/null @@ -1,180 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, 1998 - 1999 - -Module Name: - - rbc.h - -Abstract: - - These are the structures and defines used in the Reduced Block Command set - -Authors: - - George Chrysanthakopoulos(georgioc) - April 1998 - -Revision History: - - Dan Knudson (DanKn), 23 Sep 1999 - updated per rev 10 of RBC spec - ---*/ -#ifndef _NTRBC_ -#define _NTRBC_ - -#include "scsi.h" - -// -// Command Descriptor Block. encapsulated under the bus/protocol specific request block -// - -typedef union _CDB_RBC { - - // - // format unit - // - - struct _FORMAT_RBC { - UCHAR OperationCode; - UCHAR VendorSpecific; - UCHAR Increment : 1; - UCHAR Percent_Time : 1; - UCHAR Reserved1 : 1; - UCHAR VendorSpecific1 : 5; - UCHAR Reserved2[2]; - UCHAR Control; - } FORMAT_RBC, *PFORMAT_RBC; - - // - // prevent/allow medium removal - // - - struct _MEDIA_REMOVAL_RBC { - UCHAR OperationCode; - UCHAR Reserved[3]; - - UCHAR Prevent : 1; - UCHAR Persistent : 1; - UCHAR Reserved3 : 6; - - UCHAR Control; - } MEDIA_REMOVAL_RBC, *PMEDIA_REMOVAL_RBC; - - // - // START_STOP_UNIT - // - - struct _START_STOP_RBC { - UCHAR OperationCode; - UCHAR Immediate: 1; - UCHAR Reserved1 : 7; - UCHAR Reserved2[2]; - UCHAR Start : 1; - UCHAR LoadEject : 1; - UCHAR Reserved3 : 2; - UCHAR PowerConditions : 4; - UCHAR Control; - } START_STOP_RBC, *PSTART_STOP_RBC; - - struct _SYNCHRONIZE_CACHE_RBC { - - UCHAR OperationCode; // 0x35 - UCHAR Reserved[8]; - UCHAR Control; - - } SYNCHRONIZE_CACHE_RBC, *PSYNCHRONIZE_CACHE_RBC; - - -} CDB_RBC, *PCDB_RBC; - - -// -// START_STOP_UNIT Power Condition descriptions -// - -#define START_STOP_RBC_POWER_CND_NO_CHANGE 0 -#define START_STOP_RBC_POWER_CND_ACTIVE 1 -#define START_STOP_RBC_POWER_CND_IDLE 2 -#define START_STOP_RBC_POWER_CND_STANDBY 3 -#define START_STOP_RBC_POWER_CND_SLEEP 5 -#define START_STOP_RBC_POWER_CND_DEVICE_CTRL 7 - - -// -// Mode Sense/Select page constants. -// - -#define MODE_PAGE_RBC_DEVICE_PARAMETERS 0x06 - - -// -// DeviceType field in inquiry Data -// - -#define RBC_DEVICE 0x0E - -// -// Define Device Capabilities page. -// - -typedef struct _MODE_RBC_DEVICE_PARAMETERS_PAGE { - UCHAR PageCode : 6; - UCHAR Reserved : 1; - UCHAR PageSavable : 1; - UCHAR PageLength; - UCHAR WriteCacheDisable : 1; - UCHAR Reserved1 : 7; - UCHAR LogicalBlockSize[2]; - UCHAR NumberOfLogicalBlocks[5]; - UCHAR PowerPerformance; - UCHAR LockDisabled : 1; - UCHAR FormatDisabled : 1; - UCHAR WriteDisabled : 1; - UCHAR ReadDisabled : 1; - UCHAR Reserved2 : 4; - UCHAR Reserved3; - -}MODE_RBC_DEVICE_PARAMETERS_PAGE, *PMODE_RBC_DEVICE_PARAMETERS_PAGE; - -typedef struct _MODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE { - - MODE_PARAMETER_HEADER Header; - MODE_RBC_DEVICE_PARAMETERS_PAGE Page; - -}MODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE, - *PMODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE; - - -// -// unsolicited status sense code qualifier values -// - -#define RBC_UNSOLICITED_STATUS 0x02 -#define RBC_UNSOLICITED_SENSE_KEY 0x06 - -#define RBC_UNSOLICITED_SC_PWR_STATE_CHNG 0xFF -#define RBC_UNSOLICITED_SC_EVENT_STATUS 0xFE - -#define RBC_UNSOLICITED_CLASS_ASQ_DEVICE 0x06 -#define RBC_UNSOLICITED_CLASS_ASQ_MEDIA 0x04 -#define RBC_UNSOLICITED_CLASS_ASQ_POWER 0x02 - - - - -// -// Translation routine used to convert SCSI requests that differ from RBC -// - -NTSTATUS -Rbc_Scsi_Conversion( - IN PSCSI_REQUEST_BLOCK Srb, - IN PSCSI_REQUEST_BLOCK *OriginalSrb, - IN PMODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE RbcHeaderAndPage, - IN BOOLEAN OutgoingRequest, - IN BOOLEAN RemovableMedia - ); - - -#endif - diff --git a/drivers/storage/inc/tape.h b/drivers/storage/inc/tape.h deleted file mode 100644 index 9a39dbe8611..00000000000 --- a/drivers/storage/inc/tape.h +++ /dev/null @@ -1,312 +0,0 @@ -/*++ - -Copyright (c) 1992 Microsoft Corporation - -Module Name: - - tape.h - -Abstract: - - These are the structures and defines that are used in the - SCSI tape class drivers. The tape class driver is separated - into two modules. Tape.c contains code common to all tape - class drivers including the driver's major entry points. - The major entry point names each begin with the prefix - 'ScsiTape.' The second module is the device specific code. - It provides support for a set of functions. Each device - specific function name is prefixed by 'Tape.' - -Author: - - Mike Glass - -Revision History: - ---*/ - -#include "scsi.h" -#include "class.h" - -// -// Define the maximum inquiry data length. -// - -#define MAXIMUM_TAPE_INQUIRY_DATA 252 - -// -// Tape device data -// - -typedef struct _TAPE_DATA { - ULONG Flags; - ULONG CurrentPartition; - PVOID DeviceSpecificExtension; - PSCSI_INQUIRY_DATA InquiryData; -} TAPE_DATA, *PTAPE_DATA; - -#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(TAPE_DATA) - - -// -// Define Device Configuration Page -// - -typedef struct _MODE_DEVICE_CONFIGURATION_PAGE { - - UCHAR PageCode : 6; - UCHAR Reserved1 : 1; - UCHAR PS : 1; - UCHAR PageLength; - UCHAR ActiveFormat : 5; - UCHAR CAFBit : 1; - UCHAR CAPBit : 1; - UCHAR Reserved2 : 1; - UCHAR ActivePartition; - UCHAR WriteBufferFullRatio; - UCHAR ReadBufferEmptyRatio; - UCHAR WriteDelayTime[2]; - UCHAR REW : 1; - UCHAR RBO : 1; - UCHAR SOCF : 2; - UCHAR AVC : 1; - UCHAR RSmk : 1; - UCHAR BIS : 1; - UCHAR DBR : 1; - UCHAR GapSize; - UCHAR Reserved3 : 3; - UCHAR SEW : 1; - UCHAR EEG : 1; - UCHAR EODdefined : 3; - UCHAR BufferSize[3]; - UCHAR DCAlgorithm; - UCHAR Reserved4; - -} MODE_DEVICE_CONFIGURATION_PAGE, *PMODE_DEVICE_CONFIGURATION_PAGE; - -// -// Define Medium Partition Page -// - -typedef struct _MODE_MEDIUM_PARTITION_PAGE { - - UCHAR PageCode : 6; - UCHAR Reserved1 : 1; - UCHAR PSBit : 1; - UCHAR PageLength; - UCHAR MaximumAdditionalPartitions; - UCHAR AdditionalPartitionDefined; - UCHAR Reserved2 : 3; - UCHAR PSUMBit : 2; - UCHAR IDPBit : 1; - UCHAR SDPBit : 1; - UCHAR FDPBit : 1; - UCHAR MediumFormatRecognition; - UCHAR Reserved3[2]; - UCHAR Partition0Size[2]; - UCHAR Partition1Size[2]; - -} MODE_MEDIUM_PARTITION_PAGE, *PMODE_MEDIUM_PARTITION_PAGE; - -// -// Define Data Compression Page -// - -typedef struct _MODE_DATA_COMPRESSION_PAGE { - - UCHAR PageCode : 6; - UCHAR Reserved1 : 2; - UCHAR PageLength; - UCHAR Reserved2 : 6; - UCHAR DCC : 1; - UCHAR DCE : 1; - UCHAR Reserved3 : 5; - UCHAR RED : 2; - UCHAR DDE : 1; - UCHAR CompressionAlgorithm[4]; - UCHAR DecompressionAlgorithm[4]; - UCHAR Reserved4[4]; - -} MODE_DATA_COMPRESSION_PAGE, *PMODE_DATA_COMPRESSION_PAGE; - -// -// Mode parameter list header and medium partition page - -// used in creating partitions -// - -typedef struct _MODE_MEDIUM_PART_PAGE { - - MODE_PARAMETER_HEADER ParameterListHeader; - MODE_MEDIUM_PARTITION_PAGE MediumPartPage; - -} MODE_MEDIUM_PART_PAGE, *PMODE_MEDIUM_PART_PAGE; - - -// -// Mode parameters for retrieving tape or media information -// - -typedef struct _MODE_TAPE_MEDIA_INFORMATION { - - MODE_PARAMETER_HEADER ParameterListHeader; - MODE_PARAMETER_BLOCK ParameterListBlock; - MODE_MEDIUM_PARTITION_PAGE MediumPartPage; - -} MODE_TAPE_MEDIA_INFORMATION, *PMODE_TAPE_MEDIA_INFORMATION; - -// -// Mode parameter list header and device configuration page - -// used in retrieving device configuration information -// - -typedef struct _MODE_DEVICE_CONFIG_PAGE { - - MODE_PARAMETER_HEADER ParameterListHeader; - MODE_DEVICE_CONFIGURATION_PAGE DeviceConfigPage; - -} MODE_DEVICE_CONFIG_PAGE, *PMODE_DEVICE_CONFIG_PAGE; - - -// -// Mode parameter list header and data compression page - -// used in retrieving data compression information -// - -typedef struct _MODE_DATA_COMPRESS_PAGE { - - MODE_PARAMETER_HEADER ParameterListHeader; - MODE_DATA_COMPRESSION_PAGE DataCompressPage; - -} MODE_DATA_COMPRESS_PAGE, *PMODE_DATA_COMPRESS_PAGE; - - - -// -// The following routines are the exported entry points for -// all tape class drivers. Note all these routines name start -// with 'ScsiTape.' -// - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ); - -NTSTATUS -ScsiTapeInitialize( - IN PDRIVER_OBJECT DriverObject - ); - -NTSTATUS -ScsiTapeCreate ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -ScsiTapeReadWrite ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -ScsiTapeDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - - - -// -// The following routines are provided by the tape -// device-specific module. Each routine name is -// prefixed with 'Tape.' - -NTSTATUS -TapeCreatePartition( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeErase( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -VOID -TapeError( - PDEVICE_OBJECT DeviceObject, - PSCSI_REQUEST_BLOCK Srb, - NTSTATUS *Status, - BOOLEAN *Retry - ); - -NTSTATUS -TapeGetDriveParameters( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeGetMediaParameters( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeGetPosition( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeGetStatus( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapePrepare( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeReadWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeSetDriveParameters( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeSetMediaParameters( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -NTSTATUS -TapeSetPosition( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - -BOOLEAN -TapeVerifyInquiry( - IN PSCSI_INQUIRY_DATA LunInfo - ); - -NTSTATUS -TapeWriteMarks( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp - ); - - -