1*c1f22c88SEric Kohl /* 2*c1f22c88SEric Kohl * PROJECT: ReactOS Floppy Disk Controller Driver 3*c1f22c88SEric Kohl * LICENSE: GNU GPLv2 only as published by the Free Software Foundation 4*c1f22c88SEric Kohl * FILE: drivers/storage/fdc/fdc/fdo.c 5*c1f22c88SEric Kohl * PURPOSE: Functional Device Object routines 6*c1f22c88SEric Kohl * PROGRAMMERS: Eric Kohl 7*c1f22c88SEric Kohl */ 8*c1f22c88SEric Kohl 9*c1f22c88SEric Kohl /* INCLUDES *******************************************************************/ 10*c1f22c88SEric Kohl 11*c1f22c88SEric Kohl #include "fdc.h" 12*c1f22c88SEric Kohl 13*c1f22c88SEric Kohl #include <stdio.h> 14*c1f22c88SEric Kohl #define NDEBUG 15*c1f22c88SEric Kohl #include <debug.h> 16*c1f22c88SEric Kohl 17*c1f22c88SEric Kohl /* FUNCTIONS ******************************************************************/ 18*c1f22c88SEric Kohl 19*c1f22c88SEric Kohl static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion; 20*c1f22c88SEric Kohl 21*c1f22c88SEric Kohl static 22*c1f22c88SEric Kohl NTSTATUS 23*c1f22c88SEric Kohl NTAPI 24*c1f22c88SEric Kohl ForwardIrpAndWaitCompletion( 25*c1f22c88SEric Kohl IN PDEVICE_OBJECT DeviceObject, 26*c1f22c88SEric Kohl IN PIRP Irp, 27*c1f22c88SEric Kohl IN PVOID Context) 28*c1f22c88SEric Kohl { 29*c1f22c88SEric Kohl if (Irp->PendingReturned) 30*c1f22c88SEric Kohl KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); 31*c1f22c88SEric Kohl return STATUS_MORE_PROCESSING_REQUIRED; 32*c1f22c88SEric Kohl } 33*c1f22c88SEric Kohl 34*c1f22c88SEric Kohl 35*c1f22c88SEric Kohl NTSTATUS 36*c1f22c88SEric Kohl ForwardIrpAndWait( 37*c1f22c88SEric Kohl IN PDEVICE_OBJECT DeviceObject, 38*c1f22c88SEric Kohl IN PIRP Irp) 39*c1f22c88SEric Kohl { 40*c1f22c88SEric Kohl PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; 41*c1f22c88SEric Kohl KEVENT Event; 42*c1f22c88SEric Kohl NTSTATUS Status; 43*c1f22c88SEric Kohl 44*c1f22c88SEric Kohl ASSERT(LowerDevice); 45*c1f22c88SEric Kohl 46*c1f22c88SEric Kohl KeInitializeEvent(&Event, NotificationEvent, FALSE); 47*c1f22c88SEric Kohl IoCopyCurrentIrpStackLocationToNext(Irp); 48*c1f22c88SEric Kohl 49*c1f22c88SEric Kohl DPRINT("Calling lower device %p\n", LowerDevice); 50*c1f22c88SEric Kohl IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE); 51*c1f22c88SEric Kohl 52*c1f22c88SEric Kohl Status = IoCallDriver(LowerDevice, Irp); 53*c1f22c88SEric Kohl if (Status == STATUS_PENDING) 54*c1f22c88SEric Kohl { 55*c1f22c88SEric Kohl Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 56*c1f22c88SEric Kohl if (NT_SUCCESS(Status)) 57*c1f22c88SEric Kohl Status = Irp->IoStatus.Status; 58*c1f22c88SEric Kohl } 59*c1f22c88SEric Kohl 60*c1f22c88SEric Kohl return Status; 61*c1f22c88SEric Kohl } 62*c1f22c88SEric Kohl 63*c1f22c88SEric Kohl 64*c1f22c88SEric Kohl NTSTATUS 65*c1f22c88SEric Kohl NTAPI 66*c1f22c88SEric Kohl ForwardIrpAndForget( 67*c1f22c88SEric Kohl IN PDEVICE_OBJECT DeviceObject, 68*c1f22c88SEric Kohl IN PIRP Irp) 69*c1f22c88SEric Kohl { 70*c1f22c88SEric Kohl PDEVICE_OBJECT LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; 71*c1f22c88SEric Kohl 72*c1f22c88SEric Kohl ASSERT(LowerDevice); 73*c1f22c88SEric Kohl 74*c1f22c88SEric Kohl IoSkipCurrentIrpStackLocation(Irp); 75*c1f22c88SEric Kohl return IoCallDriver(LowerDevice, Irp); 76*c1f22c88SEric Kohl } 77*c1f22c88SEric Kohl 78*c1f22c88SEric Kohl 79*c1f22c88SEric Kohl 80*c1f22c88SEric Kohl 81*c1f22c88SEric Kohl static 82*c1f22c88SEric Kohl NTSTATUS 83*c1f22c88SEric Kohl FdcFdoStartDevice( 84*c1f22c88SEric Kohl IN PDEVICE_OBJECT DeviceObject, 85*c1f22c88SEric Kohl IN PCM_RESOURCE_LIST ResourceList, 86*c1f22c88SEric Kohl IN PCM_RESOURCE_LIST ResourceListTranslated) 87*c1f22c88SEric Kohl { 88*c1f22c88SEric Kohl PFDO_DEVICE_EXTENSION DeviceExtension; 89*c1f22c88SEric Kohl PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 90*c1f22c88SEric Kohl // PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorTranslated; 91*c1f22c88SEric Kohl ULONG i; 92*c1f22c88SEric Kohl 93*c1f22c88SEric Kohl DPRINT("FdcFdoStartDevice called\n"); 94*c1f22c88SEric Kohl 95*c1f22c88SEric Kohl DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 96*c1f22c88SEric Kohl 97*c1f22c88SEric Kohl ASSERT(DeviceExtension); 98*c1f22c88SEric Kohl 99*c1f22c88SEric Kohl if (ResourceList == NULL || 100*c1f22c88SEric Kohl ResourceListTranslated == NULL) 101*c1f22c88SEric Kohl { 102*c1f22c88SEric Kohl DPRINT1("No allocated resources sent to driver\n"); 103*c1f22c88SEric Kohl return STATUS_INSUFFICIENT_RESOURCES; 104*c1f22c88SEric Kohl } 105*c1f22c88SEric Kohl 106*c1f22c88SEric Kohl if (ResourceList->Count != 1) 107*c1f22c88SEric Kohl { 108*c1f22c88SEric Kohl DPRINT1("Wrong number of allocated resources sent to driver\n"); 109*c1f22c88SEric Kohl return STATUS_INSUFFICIENT_RESOURCES; 110*c1f22c88SEric Kohl } 111*c1f22c88SEric Kohl 112*c1f22c88SEric Kohl if (ResourceList->List[0].PartialResourceList.Version != 1 || 113*c1f22c88SEric Kohl ResourceList->List[0].PartialResourceList.Revision != 1 || 114*c1f22c88SEric Kohl ResourceListTranslated->List[0].PartialResourceList.Version != 1 || 115*c1f22c88SEric Kohl ResourceListTranslated->List[0].PartialResourceList.Revision != 1) 116*c1f22c88SEric Kohl { 117*c1f22c88SEric Kohl DPRINT1("Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n", 118*c1f22c88SEric Kohl ResourceList->List[0].PartialResourceList.Version, 119*c1f22c88SEric Kohl ResourceList->List[0].PartialResourceList.Revision, 120*c1f22c88SEric Kohl ResourceListTranslated->List[0].PartialResourceList.Version, 121*c1f22c88SEric Kohl ResourceListTranslated->List[0].PartialResourceList.Revision); 122*c1f22c88SEric Kohl return STATUS_REVISION_MISMATCH; 123*c1f22c88SEric Kohl } 124*c1f22c88SEric Kohl 125*c1f22c88SEric Kohl for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++) 126*c1f22c88SEric Kohl { 127*c1f22c88SEric Kohl PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i]; 128*c1f22c88SEric Kohl // PartialDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[i]; 129*c1f22c88SEric Kohl 130*c1f22c88SEric Kohl switch (PartialDescriptor->Type) 131*c1f22c88SEric Kohl { 132*c1f22c88SEric Kohl case CmResourceTypePort: 133*c1f22c88SEric Kohl DPRINT("Port: 0x%lx (%lu)\n", 134*c1f22c88SEric Kohl PartialDescriptor->u.Port.Start.u.LowPart, 135*c1f22c88SEric Kohl PartialDescriptor->u.Port.Length); 136*c1f22c88SEric Kohl if (PartialDescriptor->u.Port.Length >= 6) 137*c1f22c88SEric Kohl DeviceExtension->ControllerInfo.BaseAddress = (PUCHAR)(ULONG_PTR)PartialDescriptor->u.Port.Start.QuadPart; 138*c1f22c88SEric Kohl break; 139*c1f22c88SEric Kohl 140*c1f22c88SEric Kohl case CmResourceTypeInterrupt: 141*c1f22c88SEric Kohl DPRINT("Interrupt: Level %lu Vector %lu\n", 142*c1f22c88SEric Kohl PartialDescriptor->u.Interrupt.Level, 143*c1f22c88SEric Kohl PartialDescriptor->u.Interrupt.Vector); 144*c1f22c88SEric Kohl /* 145*c1f22c88SEric Kohl Dirql = (KIRQL)PartialDescriptorTranslated->u.Interrupt.Level; 146*c1f22c88SEric Kohl Vector = PartialDescriptorTranslated->u.Interrupt.Vector; 147*c1f22c88SEric Kohl Affinity = PartialDescriptorTranslated->u.Interrupt.Affinity; 148*c1f22c88SEric Kohl if (PartialDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) 149*c1f22c88SEric Kohl InterruptMode = Latched; 150*c1f22c88SEric Kohl else 151*c1f22c88SEric Kohl InterruptMode = LevelSensitive; 152*c1f22c88SEric Kohl ShareInterrupt = (PartialDescriptorTranslated->ShareDisposition == CmResourceShareShared); 153*c1f22c88SEric Kohl */ 154*c1f22c88SEric Kohl break; 155*c1f22c88SEric Kohl 156*c1f22c88SEric Kohl case CmResourceTypeDma: 157*c1f22c88SEric Kohl DPRINT("Dma: Channel %lu\n", 158*c1f22c88SEric Kohl PartialDescriptor->u.Dma.Channel); 159*c1f22c88SEric Kohl break; 160*c1f22c88SEric Kohl } 161*c1f22c88SEric Kohl } 162*c1f22c88SEric Kohl 163*c1f22c88SEric Kohl return STATUS_SUCCESS; 164*c1f22c88SEric Kohl } 165*c1f22c88SEric Kohl 166*c1f22c88SEric Kohl 167*c1f22c88SEric Kohl static 168*c1f22c88SEric Kohl NTSTATUS 169*c1f22c88SEric Kohl NTAPI 170*c1f22c88SEric Kohl FdcFdoConfigCallback( 171*c1f22c88SEric Kohl PVOID Context, 172*c1f22c88SEric Kohl PUNICODE_STRING PathName, 173*c1f22c88SEric Kohl INTERFACE_TYPE BusType, 174*c1f22c88SEric Kohl ULONG BusNumber, 175*c1f22c88SEric Kohl PKEY_VALUE_FULL_INFORMATION *BusInformation, 176*c1f22c88SEric Kohl CONFIGURATION_TYPE ControllerType, 177*c1f22c88SEric Kohl ULONG ControllerNumber, 178*c1f22c88SEric Kohl PKEY_VALUE_FULL_INFORMATION *ControllerInformation, 179*c1f22c88SEric Kohl CONFIGURATION_TYPE PeripheralType, 180*c1f22c88SEric Kohl ULONG PeripheralNumber, 181*c1f22c88SEric Kohl PKEY_VALUE_FULL_INFORMATION *PeripheralInformation) 182*c1f22c88SEric Kohl { 183*c1f22c88SEric Kohl PKEY_VALUE_FULL_INFORMATION ControllerFullDescriptor; 184*c1f22c88SEric Kohl PCM_FULL_RESOURCE_DESCRIPTOR ControllerResourceDescriptor; 185*c1f22c88SEric Kohl PKEY_VALUE_FULL_INFORMATION PeripheralFullDescriptor; 186*c1f22c88SEric Kohl PCM_FULL_RESOURCE_DESCRIPTOR PeripheralResourceDescriptor; 187*c1f22c88SEric Kohl PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 188*c1f22c88SEric Kohl PCM_FLOPPY_DEVICE_DATA FloppyDeviceData; 189*c1f22c88SEric Kohl PFDO_DEVICE_EXTENSION DeviceExtension; 190*c1f22c88SEric Kohl PDRIVE_INFO DriveInfo; 191*c1f22c88SEric Kohl BOOLEAN ControllerFound = FALSE; 192*c1f22c88SEric Kohl ULONG i; 193*c1f22c88SEric Kohl 194*c1f22c88SEric Kohl DPRINT("FdcFdoConfigCallback() called\n"); 195*c1f22c88SEric Kohl 196*c1f22c88SEric Kohl DeviceExtension = (PFDO_DEVICE_EXTENSION)Context; 197*c1f22c88SEric Kohl 198*c1f22c88SEric Kohl /* Get the controller resources */ 199*c1f22c88SEric Kohl ControllerFullDescriptor = ControllerInformation[IoQueryDeviceConfigurationData]; 200*c1f22c88SEric Kohl ControllerResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)ControllerFullDescriptor + 201*c1f22c88SEric Kohl ControllerFullDescriptor->DataOffset); 202*c1f22c88SEric Kohl 203*c1f22c88SEric Kohl for(i = 0; i < ControllerResourceDescriptor->PartialResourceList.Count; i++) 204*c1f22c88SEric Kohl { 205*c1f22c88SEric Kohl PartialDescriptor = &ControllerResourceDescriptor->PartialResourceList.PartialDescriptors[i]; 206*c1f22c88SEric Kohl 207*c1f22c88SEric Kohl if (PartialDescriptor->Type == CmResourceTypePort) 208*c1f22c88SEric Kohl { 209*c1f22c88SEric Kohl if ((PUCHAR)(ULONG_PTR)PartialDescriptor->u.Port.Start.QuadPart == DeviceExtension->ControllerInfo.BaseAddress) 210*c1f22c88SEric Kohl ControllerFound = TRUE; 211*c1f22c88SEric Kohl } 212*c1f22c88SEric Kohl } 213*c1f22c88SEric Kohl 214*c1f22c88SEric Kohl /* Leave, if the enumerated controller is not the one represented by the FDO */ 215*c1f22c88SEric Kohl if (ControllerFound == FALSE) 216*c1f22c88SEric Kohl return STATUS_SUCCESS; 217*c1f22c88SEric Kohl 218*c1f22c88SEric Kohl /* Get the peripheral resources */ 219*c1f22c88SEric Kohl PeripheralFullDescriptor = PeripheralInformation[IoQueryDeviceConfigurationData]; 220*c1f22c88SEric Kohl PeripheralResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)PeripheralFullDescriptor + 221*c1f22c88SEric Kohl PeripheralFullDescriptor->DataOffset); 222*c1f22c88SEric Kohl 223*c1f22c88SEric Kohl /* learn about drives attached to controller */ 224*c1f22c88SEric Kohl for(i = 0; i < PeripheralResourceDescriptor->PartialResourceList.Count; i++) 225*c1f22c88SEric Kohl { 226*c1f22c88SEric Kohl PartialDescriptor = &PeripheralResourceDescriptor->PartialResourceList.PartialDescriptors[i]; 227*c1f22c88SEric Kohl 228*c1f22c88SEric Kohl if (PartialDescriptor->Type != CmResourceTypeDeviceSpecific) 229*c1f22c88SEric Kohl continue; 230*c1f22c88SEric Kohl 231*c1f22c88SEric Kohl FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)(PartialDescriptor + 1); 232*c1f22c88SEric Kohl 233*c1f22c88SEric Kohl DriveInfo = &DeviceExtension->ControllerInfo.DriveInfo[DeviceExtension->ControllerInfo.NumberOfDrives]; 234*c1f22c88SEric Kohl 235*c1f22c88SEric Kohl DriveInfo->ControllerInfo = &DeviceExtension->ControllerInfo; 236*c1f22c88SEric Kohl DriveInfo->UnitNumber = DeviceExtension->ControllerInfo.NumberOfDrives; 237*c1f22c88SEric Kohl DriveInfo->PeripheralNumber = PeripheralNumber; 238*c1f22c88SEric Kohl 239*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.MaxDensity = FloppyDeviceData->MaxDensity; 240*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.MountDensity = FloppyDeviceData->MountDensity; 241*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.StepRateHeadUnloadTime = FloppyDeviceData->StepRateHeadUnloadTime; 242*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.HeadLoadTime = FloppyDeviceData->HeadLoadTime; 243*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.MotorOffTime = FloppyDeviceData->MotorOffTime; 244*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.SectorLengthCode = FloppyDeviceData->SectorLengthCode; 245*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.SectorPerTrack = FloppyDeviceData->SectorPerTrack; 246*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.ReadWriteGapLength = FloppyDeviceData->ReadWriteGapLength; 247*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.FormatGapLength = FloppyDeviceData->FormatGapLength; 248*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.FormatFillCharacter = FloppyDeviceData->FormatFillCharacter; 249*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.HeadSettleTime = FloppyDeviceData->HeadSettleTime; 250*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.MotorSettleTime = FloppyDeviceData->MotorSettleTime; 251*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.MaximumTrackValue = FloppyDeviceData->MaximumTrackValue; 252*c1f22c88SEric Kohl DriveInfo->FloppyDeviceData.DataTransferLength = FloppyDeviceData->DataTransferLength; 253*c1f22c88SEric Kohl 254*c1f22c88SEric Kohl /* Once it's all set up, acknowledge its existence in the controller info object */ 255*c1f22c88SEric Kohl DeviceExtension->ControllerInfo.NumberOfDrives++; 256*c1f22c88SEric Kohl } 257*c1f22c88SEric Kohl 258*c1f22c88SEric Kohl DeviceExtension->ControllerInfo.Populated = TRUE; 259*c1f22c88SEric Kohl 260*c1f22c88SEric Kohl DPRINT("Detected %lu floppy drives!\n", 261*c1f22c88SEric Kohl DeviceExtension->ControllerInfo.NumberOfDrives); 262*c1f22c88SEric Kohl 263*c1f22c88SEric Kohl return STATUS_SUCCESS; 264*c1f22c88SEric Kohl } 265*c1f22c88SEric Kohl 266*c1f22c88SEric Kohl 267*c1f22c88SEric Kohl static 268*c1f22c88SEric Kohl NTSTATUS 269*c1f22c88SEric Kohl PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs) 270*c1f22c88SEric Kohl { 271*c1f22c88SEric Kohl WCHAR Buffer[256]; 272*c1f22c88SEric Kohl UNICODE_STRING BufferU; 273*c1f22c88SEric Kohl ULONG Index; 274*c1f22c88SEric Kohl 275*c1f22c88SEric Kohl Index = 0; 276*c1f22c88SEric Kohl Index += swprintf(&Buffer[Index], 277*c1f22c88SEric Kohl L"FDC\\GENERIC_FLOPPY_DRIVE"); 278*c1f22c88SEric Kohl Index++; 279*c1f22c88SEric Kohl 280*c1f22c88SEric Kohl Buffer[Index] = UNICODE_NULL; 281*c1f22c88SEric Kohl 282*c1f22c88SEric Kohl BufferU.Length = BufferU.MaximumLength = (USHORT) Index * sizeof(WCHAR); 283*c1f22c88SEric Kohl BufferU.Buffer = Buffer; 284*c1f22c88SEric Kohl 285*c1f22c88SEric Kohl return DuplicateUnicodeString(0, &BufferU, HardwareIDs); 286*c1f22c88SEric Kohl } 287*c1f22c88SEric Kohl 288*c1f22c88SEric Kohl 289*c1f22c88SEric Kohl static 290*c1f22c88SEric Kohl NTSTATUS 291*c1f22c88SEric Kohl PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs) 292*c1f22c88SEric Kohl { 293*c1f22c88SEric Kohl WCHAR Buffer[256]; 294*c1f22c88SEric Kohl UNICODE_STRING BufferU; 295*c1f22c88SEric Kohl ULONG Index; 296*c1f22c88SEric Kohl 297*c1f22c88SEric Kohl Index = 0; 298*c1f22c88SEric Kohl Index += swprintf(&Buffer[Index], 299*c1f22c88SEric Kohl L"GenFloppyDisk"); 300*c1f22c88SEric Kohl Index++; 301*c1f22c88SEric Kohl 302*c1f22c88SEric Kohl Buffer[Index] = UNICODE_NULL; 303*c1f22c88SEric Kohl 304*c1f22c88SEric Kohl BufferU.Length = BufferU.MaximumLength = (USHORT)Index * sizeof(WCHAR); 305*c1f22c88SEric Kohl BufferU.Buffer = Buffer; 306*c1f22c88SEric Kohl 307*c1f22c88SEric Kohl return DuplicateUnicodeString(0, &BufferU, CompatibleIDs); 308*c1f22c88SEric Kohl } 309*c1f22c88SEric Kohl 310*c1f22c88SEric Kohl 311*c1f22c88SEric Kohl static 312*c1f22c88SEric Kohl NTSTATUS 313*c1f22c88SEric Kohl PciCreateInstanceIDString(PUNICODE_STRING InstanceID, 314*c1f22c88SEric Kohl ULONG PeripheralNumber) 315*c1f22c88SEric Kohl { 316*c1f22c88SEric Kohl WCHAR Buffer[3]; 317*c1f22c88SEric Kohl 318*c1f22c88SEric Kohl swprintf(Buffer, L"%02X", PeripheralNumber & 0xff); 319*c1f22c88SEric Kohl 320*c1f22c88SEric Kohl return RtlCreateUnicodeString(InstanceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 321*c1f22c88SEric Kohl } 322*c1f22c88SEric Kohl 323*c1f22c88SEric Kohl 324*c1f22c88SEric Kohl static 325*c1f22c88SEric Kohl NTSTATUS 326*c1f22c88SEric Kohl FdcFdoQueryBusRelations( 327*c1f22c88SEric Kohl IN PDEVICE_OBJECT DeviceObject, 328*c1f22c88SEric Kohl OUT PDEVICE_RELATIONS *DeviceRelations) 329*c1f22c88SEric Kohl { 330*c1f22c88SEric Kohl PFDO_DEVICE_EXTENSION FdoDeviceExtension; 331*c1f22c88SEric Kohl PPDO_DEVICE_EXTENSION PdoDeviceExtension; 332*c1f22c88SEric Kohl INTERFACE_TYPE InterfaceType = Isa; 333*c1f22c88SEric Kohl CONFIGURATION_TYPE ControllerType = DiskController; 334*c1f22c88SEric Kohl CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral; 335*c1f22c88SEric Kohl PDEVICE_RELATIONS Relations; 336*c1f22c88SEric Kohl PDRIVE_INFO DriveInfo; 337*c1f22c88SEric Kohl PDEVICE_OBJECT Pdo; 338*c1f22c88SEric Kohl WCHAR DeviceNameBuffer[80]; 339*c1f22c88SEric Kohl UNICODE_STRING DeviceName; 340*c1f22c88SEric Kohl ULONG DeviceNumber = 0; 341*c1f22c88SEric Kohl ULONG Size; 342*c1f22c88SEric Kohl ULONG i; 343*c1f22c88SEric Kohl NTSTATUS Status; 344*c1f22c88SEric Kohl 345*c1f22c88SEric Kohl DPRINT("FdcFdoQueryBusRelations() called\n"); 346*c1f22c88SEric Kohl 347*c1f22c88SEric Kohl FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 348*c1f22c88SEric Kohl 349*c1f22c88SEric Kohl Status = IoQueryDeviceDescription(&InterfaceType, 350*c1f22c88SEric Kohl NULL, 351*c1f22c88SEric Kohl &ControllerType, 352*c1f22c88SEric Kohl NULL, 353*c1f22c88SEric Kohl &PeripheralType, 354*c1f22c88SEric Kohl NULL, 355*c1f22c88SEric Kohl FdcFdoConfigCallback, 356*c1f22c88SEric Kohl FdoDeviceExtension); 357*c1f22c88SEric Kohl if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_ENTRIES)) 358*c1f22c88SEric Kohl return Status; 359*c1f22c88SEric Kohl 360*c1f22c88SEric Kohl Size = sizeof(DEVICE_RELATIONS) + 361*c1f22c88SEric Kohl sizeof(Relations->Objects) * (FdoDeviceExtension->ControllerInfo.NumberOfDrives - 1); 362*c1f22c88SEric Kohl Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size); 363*c1f22c88SEric Kohl if (Relations == NULL) 364*c1f22c88SEric Kohl { 365*c1f22c88SEric Kohl return STATUS_INSUFFICIENT_RESOURCES; 366*c1f22c88SEric Kohl } 367*c1f22c88SEric Kohl 368*c1f22c88SEric Kohl Relations->Count = FdoDeviceExtension->ControllerInfo.NumberOfDrives; 369*c1f22c88SEric Kohl 370*c1f22c88SEric Kohl for (i = 0; i < FdoDeviceExtension->ControllerInfo.NumberOfDrives; i++) 371*c1f22c88SEric Kohl { 372*c1f22c88SEric Kohl DriveInfo = &FdoDeviceExtension->ControllerInfo.DriveInfo[i]; 373*c1f22c88SEric Kohl 374*c1f22c88SEric Kohl if (DriveInfo->DeviceObject == NULL) 375*c1f22c88SEric Kohl { 376*c1f22c88SEric Kohl do 377*c1f22c88SEric Kohl { 378*c1f22c88SEric Kohl swprintf(DeviceNameBuffer, L"\\Device\\FloppyPDO%lu", DeviceNumber++); 379*c1f22c88SEric Kohl RtlInitUnicodeString(&DeviceName, DeviceNameBuffer); 380*c1f22c88SEric Kohl DPRINT("Device name: %S\n", DeviceNameBuffer); 381*c1f22c88SEric Kohl 382*c1f22c88SEric Kohl /* Create physical device object */ 383*c1f22c88SEric Kohl Status = IoCreateDevice(FdoDeviceExtension->Common.DeviceObject->DriverObject, 384*c1f22c88SEric Kohl sizeof(PDO_DEVICE_EXTENSION), 385*c1f22c88SEric Kohl &DeviceName, 386*c1f22c88SEric Kohl FILE_DEVICE_MASS_STORAGE, 387*c1f22c88SEric Kohl FILE_DEVICE_SECURE_OPEN, 388*c1f22c88SEric Kohl FALSE, 389*c1f22c88SEric Kohl &Pdo); 390*c1f22c88SEric Kohl } 391*c1f22c88SEric Kohl while (Status == STATUS_OBJECT_NAME_COLLISION); 392*c1f22c88SEric Kohl 393*c1f22c88SEric Kohl if (!NT_SUCCESS(Status)) 394*c1f22c88SEric Kohl { 395*c1f22c88SEric Kohl DPRINT1("PDO creation failed (Status 0x%08lx)\n", Status); 396*c1f22c88SEric Kohl goto done; 397*c1f22c88SEric Kohl } 398*c1f22c88SEric Kohl 399*c1f22c88SEric Kohl DPRINT("PDO created: %S\n", DeviceNameBuffer); 400*c1f22c88SEric Kohl 401*c1f22c88SEric Kohl DriveInfo->DeviceObject = Pdo; 402*c1f22c88SEric Kohl 403*c1f22c88SEric Kohl PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension; 404*c1f22c88SEric Kohl RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION)); 405*c1f22c88SEric Kohl 406*c1f22c88SEric Kohl PdoDeviceExtension->Common.IsFDO = FALSE; 407*c1f22c88SEric Kohl PdoDeviceExtension->Common.DeviceObject = Pdo; 408*c1f22c88SEric Kohl 409*c1f22c88SEric Kohl PdoDeviceExtension->Fdo = FdoDeviceExtension->Common.DeviceObject; 410*c1f22c88SEric Kohl PdoDeviceExtension->DriveInfo = DriveInfo; 411*c1f22c88SEric Kohl 412*c1f22c88SEric Kohl Pdo->Flags |= DO_DIRECT_IO; 413*c1f22c88SEric Kohl Pdo->Flags |= DO_POWER_PAGABLE; 414*c1f22c88SEric Kohl Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 415*c1f22c88SEric Kohl 416*c1f22c88SEric Kohl /* Add Device ID string */ 417*c1f22c88SEric Kohl RtlCreateUnicodeString(&PdoDeviceExtension->DeviceId, 418*c1f22c88SEric Kohl L"FDC\\GENERIC_FLOPPY_DRIVE"); 419*c1f22c88SEric Kohl DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceId.Buffer); 420*c1f22c88SEric Kohl 421*c1f22c88SEric Kohl /* Add Hardware IDs string */ 422*c1f22c88SEric Kohl Status = PciCreateHardwareIDsString(&PdoDeviceExtension->HardwareIds); 423*c1f22c88SEric Kohl if (!NT_SUCCESS(Status)) 424*c1f22c88SEric Kohl { 425*c1f22c88SEric Kohl // ErrorStatus = Status; 426*c1f22c88SEric Kohl // ErrorOccurred = TRUE; 427*c1f22c88SEric Kohl break; 428*c1f22c88SEric Kohl } 429*c1f22c88SEric Kohl 430*c1f22c88SEric Kohl /* Add Compatible IDs string */ 431*c1f22c88SEric Kohl Status = PciCreateCompatibleIDsString(&PdoDeviceExtension->CompatibleIds); 432*c1f22c88SEric Kohl if (!NT_SUCCESS(Status)) 433*c1f22c88SEric Kohl { 434*c1f22c88SEric Kohl // ErrorStatus = Status; 435*c1f22c88SEric Kohl // ErrorOccurred = TRUE; 436*c1f22c88SEric Kohl break; 437*c1f22c88SEric Kohl } 438*c1f22c88SEric Kohl 439*c1f22c88SEric Kohl /* Add Instance ID string */ 440*c1f22c88SEric Kohl Status = PciCreateInstanceIDString(&PdoDeviceExtension->InstanceId, 441*c1f22c88SEric Kohl DriveInfo->PeripheralNumber); 442*c1f22c88SEric Kohl if (!NT_SUCCESS(Status)) 443*c1f22c88SEric Kohl { 444*c1f22c88SEric Kohl // ErrorStatus = Status; 445*c1f22c88SEric Kohl // ErrorOccurred = TRUE; 446*c1f22c88SEric Kohl break; 447*c1f22c88SEric Kohl } 448*c1f22c88SEric Kohl 449*c1f22c88SEric Kohl #if 0 450*c1f22c88SEric Kohl /* Add device description string */ 451*c1f22c88SEric Kohl Status = PciCreateDeviceDescriptionString(&PdoDeviceExtension->DeviceDescription, Device); 452*c1f22c88SEric Kohl if (!NT_SUCCESS(Status)) 453*c1f22c88SEric Kohl { 454*c1f22c88SEric Kohl // ErrorStatus = Status; 455*c1f22c88SEric Kohl // ErrorOccurred = TRUE; 456*c1f22c88SEric Kohl break; 457*c1f22c88SEric Kohl } 458*c1f22c88SEric Kohl 459*c1f22c88SEric Kohl /* Add device location string */ 460*c1f22c88SEric Kohl Status = PciCreateDeviceLocationString(&PdoDeviceExtension->DeviceLocation, Device); 461*c1f22c88SEric Kohl if (!NT_SUCCESS(Status)) 462*c1f22c88SEric Kohl { 463*c1f22c88SEric Kohl // ErrorStatus = Status; 464*c1f22c88SEric Kohl // ErrorOccurred = TRUE; 465*c1f22c88SEric Kohl break; 466*c1f22c88SEric Kohl } 467*c1f22c88SEric Kohl #endif 468*c1f22c88SEric Kohl } 469*c1f22c88SEric Kohl 470*c1f22c88SEric Kohl ObReferenceObject(DriveInfo->DeviceObject); 471*c1f22c88SEric Kohl Relations->Objects[i] = DriveInfo->DeviceObject; 472*c1f22c88SEric Kohl } 473*c1f22c88SEric Kohl 474*c1f22c88SEric Kohl done: 475*c1f22c88SEric Kohl if (NT_SUCCESS(Status)) 476*c1f22c88SEric Kohl { 477*c1f22c88SEric Kohl *DeviceRelations = Relations; 478*c1f22c88SEric Kohl } 479*c1f22c88SEric Kohl else 480*c1f22c88SEric Kohl { 481*c1f22c88SEric Kohl if (Relations != NULL) 482*c1f22c88SEric Kohl ExFreePool(Relations); 483*c1f22c88SEric Kohl } 484*c1f22c88SEric Kohl 485*c1f22c88SEric Kohl return Status; 486*c1f22c88SEric Kohl } 487*c1f22c88SEric Kohl 488*c1f22c88SEric Kohl 489*c1f22c88SEric Kohl NTSTATUS 490*c1f22c88SEric Kohl NTAPI 491*c1f22c88SEric Kohl FdcFdoPnp( 492*c1f22c88SEric Kohl IN PDEVICE_OBJECT DeviceObject, 493*c1f22c88SEric Kohl IN PIRP Irp) 494*c1f22c88SEric Kohl { 495*c1f22c88SEric Kohl PIO_STACK_LOCATION IrpSp; 496*c1f22c88SEric Kohl PDEVICE_RELATIONS DeviceRelations = NULL; 497*c1f22c88SEric Kohl ULONG_PTR Information = 0; 498*c1f22c88SEric Kohl NTSTATUS Status = STATUS_NOT_SUPPORTED; 499*c1f22c88SEric Kohl 500*c1f22c88SEric Kohl DPRINT("FdcFdoPnp()\n"); 501*c1f22c88SEric Kohl 502*c1f22c88SEric Kohl IrpSp = IoGetCurrentIrpStackLocation(Irp); 503*c1f22c88SEric Kohl 504*c1f22c88SEric Kohl switch (IrpSp->MinorFunction) 505*c1f22c88SEric Kohl { 506*c1f22c88SEric Kohl case IRP_MN_START_DEVICE: 507*c1f22c88SEric Kohl DPRINT(" IRP_MN_START_DEVICE received\n"); 508*c1f22c88SEric Kohl /* Call lower driver */ 509*c1f22c88SEric Kohl Status = ForwardIrpAndWait(DeviceObject, Irp); 510*c1f22c88SEric Kohl if (NT_SUCCESS(Status)) 511*c1f22c88SEric Kohl { 512*c1f22c88SEric Kohl Status = FdcFdoStartDevice(DeviceObject, 513*c1f22c88SEric Kohl IrpSp->Parameters.StartDevice.AllocatedResources, 514*c1f22c88SEric Kohl IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated); 515*c1f22c88SEric Kohl } 516*c1f22c88SEric Kohl break; 517*c1f22c88SEric Kohl 518*c1f22c88SEric Kohl case IRP_MN_QUERY_REMOVE_DEVICE: 519*c1f22c88SEric Kohl DPRINT(" IRP_MN_QUERY_REMOVE_DEVICE\n"); 520*c1f22c88SEric Kohl break; 521*c1f22c88SEric Kohl 522*c1f22c88SEric Kohl case IRP_MN_REMOVE_DEVICE: 523*c1f22c88SEric Kohl DPRINT(" IRP_MN_REMOVE_DEVICE received\n"); 524*c1f22c88SEric Kohl break; 525*c1f22c88SEric Kohl 526*c1f22c88SEric Kohl case IRP_MN_CANCEL_REMOVE_DEVICE: 527*c1f22c88SEric Kohl DPRINT(" IRP_MN_CANCEL_REMOVE_DEVICE\n"); 528*c1f22c88SEric Kohl break; 529*c1f22c88SEric Kohl 530*c1f22c88SEric Kohl case IRP_MN_STOP_DEVICE: 531*c1f22c88SEric Kohl DPRINT(" IRP_MN_STOP_DEVICE received\n"); 532*c1f22c88SEric Kohl break; 533*c1f22c88SEric Kohl 534*c1f22c88SEric Kohl case IRP_MN_QUERY_STOP_DEVICE: 535*c1f22c88SEric Kohl DPRINT(" IRP_MN_QUERY_STOP_DEVICE received\n"); 536*c1f22c88SEric Kohl break; 537*c1f22c88SEric Kohl 538*c1f22c88SEric Kohl case IRP_MN_CANCEL_STOP_DEVICE: 539*c1f22c88SEric Kohl DPRINT(" IRP_MN_CANCEL_STOP_DEVICE\n"); 540*c1f22c88SEric Kohl break; 541*c1f22c88SEric Kohl 542*c1f22c88SEric Kohl case IRP_MN_QUERY_DEVICE_RELATIONS: 543*c1f22c88SEric Kohl DPRINT(" IRP_MN_QUERY_DEVICE_RELATIONS\n"); 544*c1f22c88SEric Kohl 545*c1f22c88SEric Kohl switch (IrpSp->Parameters.QueryDeviceRelations.Type) 546*c1f22c88SEric Kohl { 547*c1f22c88SEric Kohl case BusRelations: 548*c1f22c88SEric Kohl DPRINT(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); 549*c1f22c88SEric Kohl Status = FdcFdoQueryBusRelations(DeviceObject, &DeviceRelations); 550*c1f22c88SEric Kohl Information = (ULONG_PTR)DeviceRelations; 551*c1f22c88SEric Kohl break; 552*c1f22c88SEric Kohl 553*c1f22c88SEric Kohl case RemovalRelations: 554*c1f22c88SEric Kohl DPRINT(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); 555*c1f22c88SEric Kohl return ForwardIrpAndForget(DeviceObject, Irp); 556*c1f22c88SEric Kohl 557*c1f22c88SEric Kohl default: 558*c1f22c88SEric Kohl DPRINT(" IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", 559*c1f22c88SEric Kohl IrpSp->Parameters.QueryDeviceRelations.Type); 560*c1f22c88SEric Kohl return ForwardIrpAndForget(DeviceObject, Irp); 561*c1f22c88SEric Kohl } 562*c1f22c88SEric Kohl break; 563*c1f22c88SEric Kohl 564*c1f22c88SEric Kohl case IRP_MN_SURPRISE_REMOVAL: 565*c1f22c88SEric Kohl DPRINT(" IRP_MN_SURPRISE_REMOVAL received\n"); 566*c1f22c88SEric Kohl break; 567*c1f22c88SEric Kohl 568*c1f22c88SEric Kohl default: 569*c1f22c88SEric Kohl DPRINT(" Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction); 570*c1f22c88SEric Kohl return ForwardIrpAndForget(DeviceObject, Irp); 571*c1f22c88SEric Kohl } 572*c1f22c88SEric Kohl 573*c1f22c88SEric Kohl Irp->IoStatus.Information = Information; 574*c1f22c88SEric Kohl Irp->IoStatus.Status = Status; 575*c1f22c88SEric Kohl IoCompleteRequest(Irp, IO_NO_INCREMENT); 576*c1f22c88SEric Kohl 577*c1f22c88SEric Kohl return Status; 578*c1f22c88SEric Kohl } 579*c1f22c88SEric Kohl 580*c1f22c88SEric Kohl /* EOF */ 581