📄 floppy.c
字号:
Arguments:
DriverObject - Pointer to driver object created by system.
Return Value:
NTSTATUS
--*/
{
CLASS_INIT_DATA InitializationData;
//
// Zero InitData
//
RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA));
//
// Set sizes
//
InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
InitializationData.FdoData.DeviceExtensionSize =
sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA);
InitializationData.FdoData.DeviceType = FILE_DEVICE_DISK;
InitializationData.FdoData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE;
//
// Set entry points
//
InitializationData.FdoData.ClassInitDevice = ScsiFlopInitDevice;
InitializationData.FdoData.ClassStartDevice = ScsiFlopStartDevice;
InitializationData.FdoData.ClassStopDevice = ScsiFlopStopDevice;
InitializationData.FdoData.ClassRemoveDevice = ScsiFlopRemoveDevice;
InitializationData.FdoData.ClassReadWriteVerification = ScsiFlopReadWriteVerification;
InitializationData.FdoData.ClassDeviceControl = ScsiFlopDeviceControl;
InitializationData.FdoData.ClassShutdownFlush = NULL;
InitializationData.FdoData.ClassCreateClose = NULL;
InitializationData.FdoData.ClassError = ScsiFlopProcessError;
InitializationData.ClassStartIo = NULL;
InitializationData.ClassAddDevice = ScsiFlopAddDevice;
InitializationData.ClassUnload = ScsiFlopUnload;
//
// Call the class init routine
//
return ClassInitialize( DriverObject, RegistryPath, &InitializationData);
} // end DriverEntry()
VOID
ScsiFlopUnload(
IN PDRIVER_OBJECT DriverObject
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER(DriverObject);
return;
}
NTSTATUS
ScsiFlopAddDevice (
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo
)
/*++
Routine Description:
This routine creates and initializes a new FDO for the corresponding
PDO. It may perform property queries on the FDO but cannot do any
media access operations.
Arguments:
DriverObject - Scsiscan class driver object.
Pdo - the physical device object we are being added to
Return Value:
status
--*/
{
PCONFIGURATION_INFORMATION configurationInformation;
NTSTATUS status;
ULONG floppyCount = IoGetConfigurationInformation()->FloppyCount;
//
// Get the number of disks already initialized.
//
status = CreateFlopDeviceObject(DriverObject, Pdo, floppyCount);
if (NT_SUCCESS(status)) {
//
// Increment system floppy device count.
//
IoGetConfigurationInformation()->FloppyCount++;
}
return status;
}
NTSTATUS
CreateFlopDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo,
IN ULONG DeviceCount
)
/*++
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 Floppys.
AdapterDescriptor - Pointer to structure returned by SCSI port
driver describing adapter capabilites (and limitations).
DeviceDescriptor - Pointer to configuration information for this device.
Return Value:
--*/
{
NTSTATUS status;
PDEVICE_OBJECT deviceObject;
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
PDISK_DATA diskData;
PVOID senseData;
BOOLEAN freeDevice = TRUE;
DebugPrint((3,"CreateFlopDeviceObject: Enter routine\n"));
//
// Try to claim the device.
//
status = ClassClaimDevice(Pdo,FALSE);
if (!NT_SUCCESS(status)) {
return(status);
}
DeviceCount--;
do {
UCHAR name[256];
//
// Create device object for this device.
//
DeviceCount++;
sprintf(name, "\\Device\\Floppy%d", DeviceCount);
status = ClassCreateDeviceObject(DriverObject,
name,
Pdo,
TRUE,
&deviceObject);
} while ((status == STATUS_OBJECT_NAME_COLLISION) ||
(status == STATUS_OBJECT_NAME_EXISTS));
if (!NT_SUCCESS(status)) {
DebugPrint((1,"CreateFlopDeviceObjects: Can not create device\n"));
goto CreateFlopDeviceObjectExit;
}
//
// Indicate that IRPs should include MDLs.
//
deviceObject->Flags |= DO_DIRECT_IO;
fdoExtension = deviceObject->DeviceExtension;
//
// Back pointer to device object.
//
fdoExtension->CommonExtension.DeviceObject = deviceObject;
//
// This is the physical device.
//
fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension;
//
// Reset the drive type.
//
diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
diskData->DriveType = DRIVE_TYPE_NONE;
diskData->IsDMF = FALSE;
// diskData->EnableDMF = TRUE;
//
// Initialize lock count to zero. The lock count is used to
// disable the ejection mechanism when media is mounted.
//
fdoExtension->LockCount = 0;
//
// Save system floppy number
//
fdoExtension->DeviceNumber = DeviceCount;
//
// Set the alignment requirements for the device based on the
// host adapter requirements
//
if (Pdo->AlignmentRequirement > deviceObject->AlignmentRequirement) {
deviceObject->AlignmentRequirement = Pdo->AlignmentRequirement;
}
//
// Clear the SrbFlags and disable synchronous transfers
//
fdoExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
//
// Finally, attach to the PDO
//
fdoExtension->LowerPdo = Pdo;
fdoExtension->CommonExtension.LowerDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, Pdo);
if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) {
status = STATUS_UNSUCCESSFUL;
goto CreateFlopDeviceObjectExit;
}
deviceObject->StackSize++;
//
// The device is initialized properly - mark it as such.
//
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
CreateFlopDeviceObjectExit:
if (deviceObject != NULL) {
IoDeleteDevice(deviceObject);
}
return status;
} // end CreateFlopDeviceObject()
NTSTATUS
ScsiFlopInitDevice(
IN PDEVICE_OBJECT Fdo
)
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
PDISK_DATA diskData = commonExtension->DriverData;
PVOID senseData = NULL;
ULONG timeOut;
BOOLEAN srbListInitialized = FALSE;
NTSTATUS status = STATUS_SUCCESS;
//
// Allocate request sense buffer.
//
senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
if (senseData == NULL) {
//
// The buffer cannot be allocated.
//
status = STATUS_INSUFFICIENT_RESOURCES;
return status;
}
//
// Set the sense data pointer in the device extension.
//
fdoExtension->SenseData = senseData;
//
// Build the lookaside list for srb's for this device.
//
ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION)fdoExtension,
SFLOPPY_SRB_LIST_SIZE);
srbListInitialized = TRUE;
//
// Register for media change notification
//
ClassInitializeMediaChangeDetection(fdoExtension,
"SFloppy");
//
// Set timeout value in seconds.
//
timeOut = ClassQueryTimeOutRegistryValue(Fdo);
if (timeOut) {
fdoExtension->TimeOutValue = timeOut;
} else {
fdoExtension->TimeOutValue = SCSI_FLOPPY_TIMEOUT;
}
//
// Floppies are not partitionable so starting offset is 0.
//
fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)0;
#if 0
if (!IsFloppyDevice(Fdo) ||
!(Fdo->Characteristics & FILE_REMOVABLE_MEDIA) ||
(fdoExtension->DeviceDescriptor->DeviceType != DIRECT_ACCESS_DEVICE)) {
ExFreePool(senseData);
status = STATUS_NO_SUCH_DEVICE;
return status;
}
#endif
RtlZeroMemory(&(fdoExtension->DiskGeometry),
sizeof(DISK_GEOMETRY));
//
// Determine the media type if possible. Set the current media type to
// Unknown so that determine media type will check the media.
//
fdoExtension->DiskGeometry.MediaType = Unknown;
#if 0
{
PUCHAR vendorId;
UCHAR vendorString[6] = {'I','N','S','I','T','E'};
vendorId = (PUCHAR)fdoExtension->DeviceDescriptor +
fdoExtension->DeviceDescriptor->VendorIdOffset;
if (!SFlopStringCmp(vendorId,vendorString,6)) {
diskData->EnableDMF = FALSE;
}
}
#endif
//
// Register interfaces for this device.
//
{
UNICODE_STRING interfaceName;
RtlInitUnicodeString(&interfaceName, NULL);
status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
(LPGUID) &FloppyClassGuid,
NULL,
&interfaceName);
if(NT_SUCCESS(status)) {
diskData->FloppyInterfaceString = interfaceName;
} else {
RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL);
DebugPrint((1, "ScsiFlopStartDevice: Unable to register device "
"interface for fdo %#p [%#08lx]\n",
Fdo, status));
}
}
return (STATUS_SUCCESS);
}
NTSTATUS
ScsiFlopStartDevice(
IN PDEVICE_OBJECT Fdo
)
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
SCSI_ADDRESS scsiAddress;
WCHAR ntNameBuffer[256];
UNICODE_STRING ntUnicodeString;
WCHAR arcNameBuffer[256];
UNICODE_STRING arcUnicodeString;
KEVENT event;
NTSTATUS status = STATUS_SUCCESS;
KeInitializeEvent(&event,SynchronizationEvent,FALSE);
DetermineMediaType(Fdo); // ignore unsuccessful here
//
// Create a symbolic link from the disk name to the corresponding
// ARC name, to be used if we're booting off the disk. This will
// fail if it's not system initialization time; that's fine. The
// ARC name looks something like \ArcName\scsi(0)Flop(0)fdisk(0).
// In order to get the address, we need to send a IOCTL_SCSI_GET_ADDRESS...
//
irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS,
Fdo,
NULL,
0,
&scsiAddress,
sizeof(scsiAddress),
FALSE,
&event,
&ioStatus);
if (irp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
swprintf(arcNameBuffer,
L"\\ArcName\\scsi(%d)disk(%d)fdisk(%d)",
scsiAddress.PortNumber,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -