📄 floppy.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
floppy.c
Abstract:
This is the NEC PD756 (aka AT, aka ISA, aka ix86) and Intel 82077
(aka MIPS) floppy diskette driver for NT.
Environment:
Kernel mode only.
--*/
//
// Include files.
//
#include "stdio.h"
#include "ntddk.h" // various NT definitions
#include "ntdddisk.h" // disk device driver I/O control codes
#include "ntddfdc.h" // fdc I/O control codes and parameters
#include "initguid.h"
#include "mountdev.h"
#include "acpiioct.h"
#include <flo_data.h> // this driver's data declarations
//
// This is the actual definition of FloppyDebugLevel.
// Note that it is only defined if this is a "debug"
// build.
//
#if DBG
extern ULONG FloppyDebugLevel = 0;
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,DriverEntry)
#pragma alloc_text(PAGE,FloppyAddDevice)
#pragma alloc_text(PAGE,FloppyPnp)
#pragma alloc_text(PAGE,FloppyPower)
#pragma alloc_text(PAGE,FlConfigCallBack)
#pragma alloc_text(PAGE,FlInitializeControllerHardware)
#pragma alloc_text(PAGE,FlInterpretError)
#pragma alloc_text(PAGE,FlDatarateSpecifyConfigure)
#pragma alloc_text(PAGE,FlRecalibrateDrive)
#pragma alloc_text(PAGE,FlDetermineMediaType)
#pragma alloc_text(PAGE,FlCheckBootSector)
#pragma alloc_text(PAGE,FlConsolidateMediaTypeWithBootSector)
#pragma alloc_text(PAGE,FlIssueCommand)
#pragma alloc_text(PAGE,FlReadWriteTrack)
#pragma alloc_text(PAGE,FlReadWrite)
#pragma alloc_text(PAGE,FlFormat)
#pragma alloc_text(PAGE,FlFinishOperation)
#pragma alloc_text(PAGE,FlStartDrive)
#pragma alloc_text(PAGE,FloppyThread)
#pragma alloc_text(PAGE,FlAllocateIoBuffer)
#pragma alloc_text(PAGE,FlFreeIoBuffer)
#pragma alloc_text(PAGE,FloppyCreateClose)
#pragma alloc_text(PAGE,FloppyDeviceControl)
#pragma alloc_text(PAGE,FloppyReadWrite)
#pragma alloc_text(PAGE,FlCheckFormatParameters)
#pragma alloc_text(PAGE,FlFdcDeviceIo)
#pragma alloc_text(PAGE,FlHdbit)
#endif
#ifdef POOL_TAGGING
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'polF')
#endif
// #define KEEP_COUNTERS 1
#ifdef KEEP_COUNTERS
ULONG FloppyUsedSeek = 0;
ULONG FloppyNoSeek = 0;
#endif
//
// Used for paging the driver.
//
ULONG PagingReferenceCount = 0;
PFAST_MUTEX PagingMutex = NULL;
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine is the driver's entry point, called by the I/O system
to load the driver. The driver's entry points are initialized and
a mutex to control paging is initialized.
In DBG mode, this routine also examines the registry for special
debug parameters.
Arguments:
DriverObject - a pointer to the object that represents this device
driver.
RegistryPath - a pointer to this driver's key in the Services tree.
Return Value:
STATUS_SUCCESS unless we can't allocate a mutex.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
#if DBG
//
// We use this to query into the registry as to whether we
// should break at driver entry.
//
RTL_QUERY_REGISTRY_TABLE paramTable[3];
ULONG zero = 0;
ULONG one = 1;
ULONG debugLevel = 0;
ULONG shouldBreak = 0;
ULONG notConfigurable = 0;
PWCHAR path;
ULONG pathLength;
//
// Since the registry path parameter is a "counted" UNICODE string, it
// might not be zero terminated. For a very short time allocate memory
// to hold the registry path zero terminated so that we can use it to
// delve into the registry.
//
// NOTE NOTE!!!! This is not an architected way of breaking into
// a driver. It happens to work for this driver because the author
// likes to do things this way.
//
pathLength = RegistryPath->Length + sizeof(WCHAR);
if ( path = ExAllocatePool(PagedPool, pathLength) ) {
RtlZeroMemory( ¶mTable[0], sizeof(paramTable) );
RtlZeroMemory( path, pathLength);
RtlMoveMemory( path, RegistryPath->Buffer, RegistryPath->Length );
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = L"BreakOnEntry";
paramTable[0].EntryContext = &shouldBreak;
paramTable[0].DefaultType = REG_DWORD;
paramTable[0].DefaultData = &zero;
paramTable[0].DefaultLength = sizeof(ULONG);
paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[1].Name = L"DebugLevel";
paramTable[1].EntryContext = &debugLevel;
paramTable[1].DefaultType = REG_DWORD;
paramTable[1].DefaultData = &zero;
paramTable[1].DefaultLength = sizeof(ULONG);
if (!NT_SUCCESS(RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
path,
¶mTable[0],
NULL,
NULL))) {
shouldBreak = 0;
debugLevel = 0;
}
ExFreePool( path );
}
FloppyDebugLevel = debugLevel;
if ( shouldBreak ) {
DbgBreakPoint();
}
#endif
FloppyDump(FLOPSHOW, ("Floppy: DriverEntry\n") );
//
// Initialize the driver object with this driver's entry points.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FloppyReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = FloppyReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FloppyDeviceControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = FloppyPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = FloppyPower;
DriverObject->DriverUnload = FloppyUnload;
DriverObject->DriverExtension->AddDevice = FloppyAddDevice;
//
// Allocate and initialize a mutex for paging the driver.
//
PagingMutex = ExAllocatePool( NonPagedPool, sizeof(FAST_MUTEX) );
if ( PagingMutex == NULL ) {
return STATUS_INSUFFICIENT_RESOURCES;
}
ExInitializeFastMutex(PagingMutex);
//
// Now page out the driver and wait for a call to FloppyAddDevice.
//
MmPageEntireDriver(DriverEntry);
DriveMediaLimits =
(IsNEC_98 ? (PDRIVE_MEDIA_LIMITS)&_DriveMediaLimits_NEC98[0] : &_DriveMediaLimits[0]);
DriveMediaConstants =
(IsNEC_98 ? (PDRIVE_MEDIA_CONSTANTS)&_DriveMediaConstants_NEC98[0] : &_DriveMediaConstants[0]);
return ntStatus;
}
VOID
FloppyUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Unload the driver from the system. The paging mutex is freed before
final unload.
Arguments:
DriverObject - a pointer to the object that represents this device
driver.
Return Value:
none
--*/
{
FloppyDump( FLOPSHOW, ("FloppyUnload:\n"));
//
// The device object(s) should all be gone by now.
//
ASSERT( DriverObject->DeviceObject == NULL );
//
// Free the paging mutex that was allocated in DriverEntry.
//
ExFreePool( PagingMutex );
return;
}
NTSTATUS
FloppyAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN OUT PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine is the driver's pnp add device entry point. It is
called by the pnp manager to initialize the driver.
Add device creates and initializes a device object for this FDO and
attaches to the underlying PDO.
Arguments:
DriverObject - a pointer to the object that represents this device
driver.
PhysicalDeviceObject - a pointer to the underlying PDO to which this
new device will attach.
Return Value:
If we successfully create a device object, STATUS_SUCCESS is
returned. Otherwise, return the appropriate error code.
--*/
{
NTSTATUS ntStatus;
PDEVICE_OBJECT deviceObject;
PDISKETTE_EXTENSION disketteExtension;
FDC_INFO fdcInfo;
UCHAR arcNameBuffer[256];
STRING arcNameString;
WCHAR deviceNameBuffer[20];
UNICODE_STRING deviceName;
ntStatus = STATUS_SUCCESS;
FloppyDump( FLOPSHOW, ("FloppyAddDevice: CreateDeviceObject\n"));
//
// Get some device information from the underlying PDO.
//
fdcInfo.BufferCount = 0;
fdcInfo.BufferSize = 0;
ntStatus = FlFdcDeviceIo( PhysicalDeviceObject,
IOCTL_DISK_INTERNAL_GET_FDC_INFO,
&fdcInfo );
if ( NT_SUCCESS(ntStatus) ) {
USHORT i = 0;
//
// Create a device. We will use the first available device name for
// this device.
//
do {
swprintf( deviceNameBuffer, L"\\Device\\Floppy%d", i++ );
RtlInitUnicodeString( &deviceName, deviceNameBuffer );
ntStatus = IoCreateDevice( DriverObject,
sizeof( DISKETTE_EXTENSION ),
&deviceName,
FILE_DEVICE_DISK,
(FILE_REMOVABLE_MEDIA |
FILE_FLOPPY_DISKETTE |
FILE_DEVICE_SECURE_OPEN),
FALSE,
&deviceObject );
} while ( ntStatus == STATUS_OBJECT_NAME_COLLISION );
if ( NT_SUCCESS(ntStatus) ) {
disketteExtension = (PDISKETTE_EXTENSION)deviceObject->DeviceExtension;
//
// Save the device name.
//
FloppyDump( FLOPSHOW | FLOPPNP,
("FloppyAddDevice - Device Object Name - %S\n", deviceNameBuffer) );
disketteExtension->DeviceName.Buffer = ExAllocatePool( PagedPool, deviceName.Length );
if ( disketteExtension->DeviceName.Buffer == NULL ) {
IoDeleteDevice( deviceObject );
return STATUS_INSUFFICIENT_RESOURCES;
}
disketteExtension->DeviceName.Length = 0;
disketteExtension->DeviceName.MaximumLength = deviceName.Length;
RtlCopyUnicodeString( &disketteExtension->DeviceName, &deviceName );
IoGetConfigurationInformation()->FloppyCount++;
//
// 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
// if it's not system initialization time; that's fine. The ARC
// name looks something like \ArcName\multi(0)disk(0)rdisk(0).
//
sprintf( arcNameBuffer,
"%s(%d)disk(%d)fdisk(%d)",
"\\ArcName\\multi",
fdcInfo.BusNumber,
fdcInfo.ControllerNumber,
fdcInfo.PeripheralNumber );
RtlInitString( &arcNameString, arcNameBuffer );
ntStatus = RtlAnsiStringToUnicodeString( &disketteExtension->ArcName,
&arcNameString,
TRUE );
if ( NT_SUCCESS( ntStatus ) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -