[FDC]
authorEric Kohl <eric.kohl@reactos.org>
Thu, 28 Nov 2013 20:32:37 +0000 (20:32 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Thu, 28 Nov 2013 20:32:37 +0000 (20:32 +0000)
Enumerate all BIOS-detected floppy drives which are attached to the current controller.

svn path=/trunk/; revision=61116

reactos/drivers/storage/fdc/fdc/fdc.h
reactos/drivers/storage/fdc/fdc/fdo.c

index f0cc493..538ddef 100644 (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;
 
 
index 3b36fe0..71a7d1a 100644 (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;
 }