Enumerate all BIOS-detected floppy drives which are attached to the current controller.

svn path=/trunk/; revision=61116
This commit is contained in:
Eric Kohl 2013-11-28 20:32:37 +00:00
parent fa67f52657
commit b6c0091383
2 changed files with 195 additions and 4 deletions

View file

@ -9,6 +9,60 @@
#include <ntddk.h>
#include <debug.h>
#define MAX_DEVICE_NAME 255
#define MAX_ARC_PATH_LEN 255
#define MAX_DRIVES_PER_CONTROLLER 4
#define MAX_CONTROLLERS 4
struct _CONTROLLER_INFO;
typedef struct _DRIVE_INFO
{
struct _CONTROLLER_INFO *ControllerInfo;
UCHAR UnitNumber; /* 0,1,2,3 */
LARGE_INTEGER MotorStartTime;
PDEVICE_OBJECT DeviceObject;
CM_FLOPPY_DEVICE_DATA FloppyDeviceData;
// DISK_GEOMETRY DiskGeometry;
UCHAR BytesPerSectorCode;
WCHAR SymLinkBuffer[MAX_DEVICE_NAME];
WCHAR ArcPathBuffer[MAX_ARC_PATH_LEN];
ULONG DiskChangeCount;
BOOLEAN Initialized;
} DRIVE_INFO, *PDRIVE_INFO;
typedef struct _CONTROLLER_INFO
{
BOOLEAN Populated;
BOOLEAN Initialized;
ULONG ControllerNumber;
INTERFACE_TYPE InterfaceType;
ULONG BusNumber;
ULONG Level;
KIRQL MappedLevel;
ULONG Vector;
ULONG MappedVector;
KINTERRUPT_MODE InterruptMode;
PUCHAR BaseAddress;
ULONG Dma;
ULONG MapRegisters;
PVOID MapRegisterBase;
BOOLEAN Master;
KEVENT SynchEvent;
KDPC Dpc;
PKINTERRUPT InterruptObject;
PADAPTER_OBJECT AdapterObject;
UCHAR NumberOfDrives;
BOOLEAN ImpliedSeeks;
DRIVE_INFO DriveInfo[MAX_DRIVES_PER_CONTROLLER];
PDRIVE_INFO CurrentDrive;
BOOLEAN Model30;
KEVENT MotorStoppedEvent;
KTIMER MotorTimer;
KDPC MotorStopDpc;
BOOLEAN StopDpcQueued;
} CONTROLLER_INFO, *PCONTROLLER_INFO;
typedef struct _COMMON_DEVICE_EXTENSION
{
@ -23,6 +77,8 @@ typedef struct _FDO_DEVICE_EXTENSION
PDEVICE_OBJECT Fdo;
PDEVICE_OBJECT Pdo;
CONTROLLER_INFO ControllerInfo;
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;

View file

@ -134,7 +134,7 @@ FdcFdoStartDevice(
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorTranslated;
// PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorTranslated;
ULONG i;
DPRINT1("FdcFdoStartDevice called\n");
@ -172,7 +172,7 @@ FdcFdoStartDevice(
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
{
PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
PartialDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[i];
// PartialDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[i];
switch (PartialDescriptor->Type)
{
@ -180,12 +180,24 @@ FdcFdoStartDevice(
DPRINT1("Port: 0x%lx (%lu)\n",
PartialDescriptor->u.Port.Start.u.LowPart,
PartialDescriptor->u.Port.Length);
if (PartialDescriptor->u.Port.Length >= 6)
DeviceExtension->ControllerInfo.BaseAddress = (PUCHAR)PartialDescriptor->u.Port.Start.u.LowPart;
break;
case CmResourceTypeInterrupt:
DPRINT1("Interrupt: Level %lu Vector %lu\n",
PartialDescriptorTranslated->u.Interrupt.Level,
PartialDescriptorTranslated->u.Interrupt.Vector);
PartialDescriptor->u.Interrupt.Level,
PartialDescriptor->u.Interrupt.Vector);
/*
Dirql = (KIRQL)PartialDescriptorTranslated->u.Interrupt.Level;
Vector = PartialDescriptorTranslated->u.Interrupt.Vector;
Affinity = PartialDescriptorTranslated->u.Interrupt.Affinity;
if (PartialDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
InterruptMode = Latched;
else
InterruptMode = LevelSensitive;
ShareInterrupt = (PartialDescriptorTranslated->ShareDisposition == CmResourceShareShared);
*/
break;
case CmResourceTypeDma:
@ -199,13 +211,136 @@ FdcFdoStartDevice(
}
static
NTSTATUS
NTAPI
FdcFdoConfigCallback(
PVOID Context,
PUNICODE_STRING PathName,
INTERFACE_TYPE BusType,
ULONG BusNumber,
PKEY_VALUE_FULL_INFORMATION *BusInformation,
CONFIGURATION_TYPE ControllerType,
ULONG ControllerNumber,
PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
CONFIGURATION_TYPE PeripheralType,
ULONG PeripheralNumber,
PKEY_VALUE_FULL_INFORMATION *PeripheralInformation)
{
PKEY_VALUE_FULL_INFORMATION ControllerFullDescriptor;
PCM_FULL_RESOURCE_DESCRIPTOR ControllerResourceDescriptor;
PKEY_VALUE_FULL_INFORMATION PeripheralFullDescriptor;
PCM_FULL_RESOURCE_DESCRIPTOR PeripheralResourceDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
PCM_FLOPPY_DEVICE_DATA FloppyDeviceData;
PFDO_DEVICE_EXTENSION DeviceExtension;
PDRIVE_INFO DriveInfo;
BOOLEAN ControllerFound = FALSE;
ULONG i;
DPRINT1("FdcFdoConfigCallback() called\n");
DeviceExtension = (PFDO_DEVICE_EXTENSION)Context;
/* Get the controller resources */
ControllerFullDescriptor = ControllerInformation[IoQueryDeviceConfigurationData];
ControllerResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)ControllerFullDescriptor +
ControllerFullDescriptor->DataOffset);
for(i = 0; i < ControllerResourceDescriptor->PartialResourceList.Count; i++)
{
PartialDescriptor = &ControllerResourceDescriptor->PartialResourceList.PartialDescriptors[i];
if (PartialDescriptor->Type == CmResourceTypePort)
{
if ((PUCHAR)PartialDescriptor->u.Port.Start.LowPart == DeviceExtension->ControllerInfo.BaseAddress)
ControllerFound = TRUE;
}
}
/* Leave, if the enumerated controller is not the one represented by the FDO */
if (ControllerFound == FALSE)
return STATUS_SUCCESS;
/* Get the peripheral resources */
PeripheralFullDescriptor = PeripheralInformation[IoQueryDeviceConfigurationData];
PeripheralResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)PeripheralFullDescriptor +
PeripheralFullDescriptor->DataOffset);
DeviceExtension->ControllerInfo.NumberOfDrives = 0;
/* learn about drives attached to controller */
for(i = 0; i < PeripheralResourceDescriptor->PartialResourceList.Count; i++)
{
PartialDescriptor = &PeripheralResourceDescriptor->PartialResourceList.PartialDescriptors[i];
if (PartialDescriptor->Type != CmResourceTypeDeviceSpecific)
continue;
FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)(PartialDescriptor + 1);
DriveInfo = &DeviceExtension->ControllerInfo.DriveInfo[i];
DriveInfo->ControllerInfo = &DeviceExtension->ControllerInfo;
DriveInfo->UnitNumber = i;
DriveInfo->FloppyDeviceData.MaxDensity = FloppyDeviceData->MaxDensity;
DriveInfo->FloppyDeviceData.MountDensity = FloppyDeviceData->MountDensity;
DriveInfo->FloppyDeviceData.StepRateHeadUnloadTime = FloppyDeviceData->StepRateHeadUnloadTime;
DriveInfo->FloppyDeviceData.HeadLoadTime = FloppyDeviceData->HeadLoadTime;
DriveInfo->FloppyDeviceData.MotorOffTime = FloppyDeviceData->MotorOffTime;
DriveInfo->FloppyDeviceData.SectorLengthCode = FloppyDeviceData->SectorLengthCode;
DriveInfo->FloppyDeviceData.SectorPerTrack = FloppyDeviceData->SectorPerTrack;
DriveInfo->FloppyDeviceData.ReadWriteGapLength = FloppyDeviceData->ReadWriteGapLength;
DriveInfo->FloppyDeviceData.FormatGapLength = FloppyDeviceData->FormatGapLength;
DriveInfo->FloppyDeviceData.FormatFillCharacter = FloppyDeviceData->FormatFillCharacter;
DriveInfo->FloppyDeviceData.HeadSettleTime = FloppyDeviceData->HeadSettleTime;
DriveInfo->FloppyDeviceData.MotorSettleTime = FloppyDeviceData->MotorSettleTime;
DriveInfo->FloppyDeviceData.MaximumTrackValue = FloppyDeviceData->MaximumTrackValue;
DriveInfo->FloppyDeviceData.DataTransferLength = FloppyDeviceData->DataTransferLength;
/* Once it's all set up, acknowledge its existance in the controller info object */
DeviceExtension->ControllerInfo.NumberOfDrives++;
}
DeviceExtension->ControllerInfo.Populated = TRUE;
DPRINT1("Detected %lu floppy drives!\n",
DeviceExtension->ControllerInfo.NumberOfDrives);
return STATUS_SUCCESS;
}
static
NTSTATUS
FdcFdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS *DeviceRelations)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
INTERFACE_TYPE InterfaceType = Isa;
CONFIGURATION_TYPE ControllerType = DiskController;
CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral;
NTSTATUS Status;
DPRINT1("FdcFdoQueryBusRelations() called\n");
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Status = IoQueryDeviceDescription(&InterfaceType,
NULL,
&ControllerType,
NULL,
&PeripheralType,
NULL,
FdcFdoConfigCallback,
DeviceExtension);
if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND))
{
return Status;
}
return STATUS_SUCCESS;
}