2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: PCI IDE bus driver extension
4 * FILE: drivers/storage/pciidex/fdo.c
5 * PURPOSE: IRP_MJ_PNP operations for FDOs
6 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
19 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
21 PBUS_INTERFACE_STANDARD BusInterface
= NULL
;
23 IO_STATUS_BLOCK IoStatus
;
25 PIO_STACK_LOCATION Stack
;
26 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
28 if (DeviceExtension
->BusInterface
)
30 DPRINT("We already have the bus interface\n");
34 BusInterface
= ExAllocatePool(PagedPool
, sizeof(BUS_INTERFACE_STANDARD
));
37 DPRINT("ExAllocatePool() failed\n");
38 Status
= STATUS_INSUFFICIENT_RESOURCES
;
42 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
43 Irp
= IoBuildSynchronousFsdRequest(
45 DeviceExtension
->LowerDevice
,
53 DPRINT("IoBuildSynchronousFsdRequest() failed\n");
54 Status
= STATUS_INSUFFICIENT_RESOURCES
;
58 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
59 Irp
->IoStatus
.Information
= 0;
61 Stack
= IoGetNextIrpStackLocation(Irp
);
62 Stack
->MajorFunction
= IRP_MJ_PNP
;
63 Stack
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
64 Stack
->Parameters
.QueryInterface
.InterfaceType
= (LPGUID
)&GUID_BUS_INTERFACE_STANDARD
;
65 Stack
->Parameters
.QueryInterface
.Version
= 1;
66 Stack
->Parameters
.QueryInterface
.Size
= sizeof(BUS_INTERFACE_STANDARD
);
67 Stack
->Parameters
.QueryInterface
.Interface
= (PINTERFACE
)BusInterface
;
68 Stack
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
70 Status
= IoCallDriver(DeviceExtension
->LowerDevice
, Irp
);
71 if (Status
== STATUS_PENDING
)
73 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
74 Status
= IoStatus
.Status
;
76 if (!NT_SUCCESS(Status
))
79 DeviceExtension
->BusInterface
= BusInterface
;
81 Status
= STATUS_SUCCESS
;
84 if (BusInterface
) ExFreePool(BusInterface
);
90 IN PFDO_DEVICE_EXTENSION DeviceExtension
)
92 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
94 if (DeviceExtension
->BusInterface
)
96 (*DeviceExtension
->BusInterface
->InterfaceDereference
)(
97 DeviceExtension
->BusInterface
->Context
);
98 DeviceExtension
->BusInterface
= NULL
;
99 Status
= STATUS_SUCCESS
;
107 IN PDRIVER_OBJECT DriverObject
,
108 IN PDEVICE_OBJECT Pdo
)
110 PPCIIDEX_DRIVER_EXTENSION DriverExtension
;
111 PFDO_DEVICE_EXTENSION DeviceExtension
;
114 PCI_COMMON_CONFIG PciConfig
;
117 DPRINT("PciIdeXAddDevice(%p %p)\n", DriverObject
, Pdo
);
119 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
120 ASSERT(DriverExtension
);
122 Status
= IoCreateDevice(
124 sizeof(FDO_DEVICE_EXTENSION
) + DriverExtension
->MiniControllerExtensionSize
,
126 FILE_DEVICE_BUS_EXTENDER
,
127 FILE_DEVICE_SECURE_OPEN
,
130 if (!NT_SUCCESS(Status
))
132 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
136 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
137 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
139 DeviceExtension
->Common
.IsFDO
= TRUE
;
141 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
142 if (!NT_SUCCESS(Status
))
144 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
148 Status
= GetBusInterface(DeviceExtension
);
149 if (!NT_SUCCESS(Status
))
151 DPRINT("GetBusInterface() failed with status 0x%08lx\n", Status
);
152 IoDetachDevice(DeviceExtension
->LowerDevice
);
156 BytesRead
= (*DeviceExtension
->BusInterface
->GetBusData
)(
157 DeviceExtension
->BusInterface
->Context
,
158 PCI_WHICHSPACE_CONFIG
,
161 PCI_COMMON_HDR_LENGTH
);
162 if (BytesRead
!= PCI_COMMON_HDR_LENGTH
)
164 DPRINT("BusInterface->GetBusData() failed()\n");
165 ReleaseBusInterface(DeviceExtension
);
166 IoDetachDevice(DeviceExtension
->LowerDevice
);
167 return STATUS_IO_DEVICE_ERROR
;
170 DeviceExtension
->VendorId
= PciConfig
.VendorID
;
171 DeviceExtension
->DeviceId
= PciConfig
.DeviceID
;
173 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
175 return STATUS_SUCCESS
;
178 static NTSTATUS NTAPI
179 PciIdeXUdmaModesSupported(
180 IN IDENTIFY_DATA IdentifyData
,
181 OUT PULONG BestXferMode
,
182 OUT PULONG CurrentXferMode
)
184 ULONG Best
= PIO_MODE0
;
185 ULONG Current
= PIO_MODE0
;
187 DPRINT("PciIdeXUdmaModesSupported(%lu, %p %p)\n",
188 IdentifyData
, BestXferMode
, CurrentXferMode
);
190 /* FIXME: if current mode is a PIO mode, how to get it?
191 * At the moment, PIO_MODE0 is always returned...
194 if (IdentifyData
.TranslationFieldsValid
& 0x2)
196 /* PIO modes and some DMA modes are supported */
197 if (IdentifyData
.AdvancedPIOModes
& 0x10)
199 else if (IdentifyData
.AdvancedPIOModes
& 0x8)
201 else if (IdentifyData
.AdvancedPIOModes
& 0x4)
203 else if (IdentifyData
.AdvancedPIOModes
& 0x2)
205 else if (IdentifyData
.AdvancedPIOModes
& 0x1)
208 if (IdentifyData
.SingleWordDMASupport
& 0x4)
210 else if (IdentifyData
.SingleWordDMASupport
& 0x2)
212 else if (IdentifyData
.SingleWordDMASupport
& 0x1)
215 if (IdentifyData
.SingleWordDMAActive
& 0x4)
216 Current
= SWDMA_MODE2
;
217 else if (IdentifyData
.SingleWordDMAActive
& 0x2)
218 Current
= SWDMA_MODE1
;
219 else if (IdentifyData
.SingleWordDMAActive
& 0x1)
220 Current
= SWDMA_MODE0
;
222 if (IdentifyData
.MultiWordDMASupport
& 0x4)
224 else if (IdentifyData
.MultiWordDMASupport
& 0x2)
226 else if (IdentifyData
.MultiWordDMASupport
& 0x1)
229 if (IdentifyData
.MultiWordDMAActive
& 0x4)
230 Current
= MWDMA_MODE2
;
231 else if (IdentifyData
.MultiWordDMAActive
& 0x2)
232 Current
= MWDMA_MODE1
;
233 else if (IdentifyData
.MultiWordDMAActive
& 0x1)
234 Current
= MWDMA_MODE0
;
237 if (IdentifyData
.TranslationFieldsValid
& 0x4)
239 /* UDMA modes are supported */
240 if (IdentifyData
.UltraDMAActive
& 0x10)
241 Current
= UDMA_MODE4
;
242 else if (IdentifyData
.UltraDMAActive
& 0x8)
243 Current
= UDMA_MODE3
;
244 else if (IdentifyData
.UltraDMAActive
& 0x4)
245 Current
= UDMA_MODE2
;
246 else if (IdentifyData
.UltraDMAActive
& 0x2)
247 Current
= UDMA_MODE1
;
248 else if (IdentifyData
.UltraDMAActive
& 0x1)
249 Current
= UDMA_MODE0
;
251 if (IdentifyData
.UltraDMASupport
& 0x10)
253 else if (IdentifyData
.UltraDMASupport
& 0x8)
255 else if (IdentifyData
.UltraDMASupport
& 0x4)
257 else if (IdentifyData
.UltraDMASupport
& 0x2)
259 else if (IdentifyData
.UltraDMASupport
& 0x1)
263 *BestXferMode
= Best
;
264 *CurrentXferMode
= Current
;
269 PciIdeXFdoStartDevice(
270 IN PDEVICE_OBJECT DeviceObject
,
273 PPCIIDEX_DRIVER_EXTENSION DriverExtension
;
274 PFDO_DEVICE_EXTENSION DeviceExtension
;
275 PCM_RESOURCE_LIST ResourceList
;
278 DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject
, Irp
);
280 DriverExtension
= IoGetDriverObjectExtension(DeviceObject
->DriverObject
, DeviceObject
->DriverObject
);
281 ASSERT(DriverExtension
);
282 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
283 ASSERT(DeviceExtension
);
284 ASSERT(DeviceExtension
->Common
.IsFDO
);
286 DeviceExtension
->Properties
.Size
= sizeof(IDE_CONTROLLER_PROPERTIES
);
287 DeviceExtension
->Properties
.ExtensionSize
= DriverExtension
->MiniControllerExtensionSize
;
288 Status
= DriverExtension
->HwGetControllerProperties(
289 DeviceExtension
->MiniControllerExtension
,
290 &DeviceExtension
->Properties
);
291 if (!NT_SUCCESS(Status
))
294 DriverExtension
->HwUdmaModesSupported
= DeviceExtension
->Properties
.PciIdeUdmaModesSupported
;
295 if (!DriverExtension
->HwUdmaModesSupported
)
296 /* This method is optional, so provide our own one */
297 DriverExtension
->HwUdmaModesSupported
= PciIdeXUdmaModesSupported
;
299 /* Get bus master port base, if any */
300 ResourceList
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.StartDevice
.AllocatedResources
;
302 && ResourceList
->Count
== 1
303 && ResourceList
->List
[0].PartialResourceList
.Count
== 1
304 && ResourceList
->List
[0].PartialResourceList
.Version
== 1
305 && ResourceList
->List
[0].PartialResourceList
.Revision
== 1
306 && ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[0].Type
== CmResourceTypePort
307 && ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[0].u
.Port
.Length
== 16)
309 DeviceExtension
->BusMasterPortBase
= ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[0].u
.Port
.Start
;
311 return STATUS_SUCCESS
;
315 PciIdeXFdoQueryBusRelations(
316 IN PDEVICE_OBJECT DeviceObject
,
317 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
319 PFDO_DEVICE_EXTENSION DeviceExtension
;
320 PDEVICE_RELATIONS DeviceRelations
= NULL
;
322 PPDO_DEVICE_EXTENSION PdoDeviceExtension
;
325 IDE_CHANNEL_STATE ChannelState
;
328 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
329 ASSERT(DeviceExtension
);
330 ASSERT(DeviceExtension
->Common
.IsFDO
);
332 for (i
= 0; i
< MAX_IDE_CHANNEL
; i
++)
334 if (DeviceExtension
->Pdo
[i
])
339 ChannelState
= DeviceExtension
->Properties
.PciIdeChannelEnabled(
340 DeviceExtension
->MiniControllerExtension
, i
);
341 if (ChannelState
== ChannelDisabled
)
343 DPRINT("Channel %lu is disabled\n", i
);
347 /* Need to create a PDO */
348 Status
= IoCreateDevice(
349 DeviceObject
->DriverObject
,
350 sizeof(PDO_DEVICE_EXTENSION
),
352 FILE_DEVICE_CONTROLLER
,
353 FILE_AUTOGENERATED_DEVICE_NAME
,
356 if (!NT_SUCCESS(Status
))
357 /* FIXME: handle error */
360 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)Pdo
->DeviceExtension
;
361 RtlZeroMemory(PdoDeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
362 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
363 PdoDeviceExtension
->Channel
= i
;
364 PdoDeviceExtension
->ControllerFdo
= DeviceObject
;
365 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
366 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
368 DeviceExtension
->Pdo
[i
] = Pdo
;
374 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(
376 sizeof(DEVICE_RELATIONS
));
380 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(
382 sizeof(DEVICE_RELATIONS
) + sizeof(PDEVICE_OBJECT
) * (PDOs
- 1));
384 if (!DeviceRelations
)
385 return STATUS_INSUFFICIENT_RESOURCES
;
387 DeviceRelations
->Count
= PDOs
;
388 for (i
= 0, j
= 0; i
< MAX_IDE_CHANNEL
; i
++)
390 if (DeviceExtension
->Pdo
[i
])
392 ObReferenceObject(DeviceExtension
->Pdo
[i
]);
393 DeviceRelations
->Objects
[j
++] = DeviceExtension
->Pdo
[i
];
397 *pDeviceRelations
= DeviceRelations
;
398 return STATUS_SUCCESS
;
402 PciIdeXFdoPnpDispatch(
403 IN PDEVICE_OBJECT DeviceObject
,
407 PIO_STACK_LOCATION Stack
;
408 ULONG_PTR Information
= Irp
->IoStatus
.Information
;
411 Stack
= IoGetCurrentIrpStackLocation(Irp
);
412 MinorFunction
= Stack
->MinorFunction
;
414 switch (MinorFunction
)
416 case IRP_MN_START_DEVICE
: /* 0x00 */
418 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
419 /* Call lower driver */
420 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
421 if (NT_SUCCESS(Status
))
422 Status
= PciIdeXFdoStartDevice(DeviceObject
, Irp
);
425 case IRP_MN_QUERY_REMOVE_DEVICE
: /* 0x01 */
427 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
428 Status
= STATUS_UNSUCCESSFUL
;
431 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
433 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
437 PDEVICE_RELATIONS DeviceRelations
= NULL
;
438 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
439 Status
= PciIdeXFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
440 Information
= (ULONG_PTR
)DeviceRelations
;
445 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
446 Stack
->Parameters
.QueryDeviceRelations
.Type
);
447 Status
= STATUS_NOT_IMPLEMENTED
;
453 case IRP_MN_QUERY_PNP_DEVICE_STATE
: /* 0x14 */
455 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
456 Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
457 Status
= STATUS_SUCCESS
;
460 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
462 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
463 return ForwardIrpAndForget(DeviceObject
, Irp
);
465 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
467 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
468 return ForwardIrpAndForget(DeviceObject
, Irp
);
472 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction
);
473 return ForwardIrpAndForget(DeviceObject
, Irp
);
477 Irp
->IoStatus
.Information
= Information
;
478 Irp
->IoStatus
.Status
= Status
;
479 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);