2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Serial enumerator driver
4 * FILE: drivers/bus/serenum/fdo.c
5 * PURPOSE: IRP_MJ_PNP operations for FDOs
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
16 IN PDRIVER_OBJECT DriverObject
,
17 IN PDEVICE_OBJECT Pdo
)
20 PFDO_DEVICE_EXTENSION DeviceExtension
;
23 TRACE_(SERENUM
, "SerenumAddDevice called. Pdo = %p\n", Pdo
);
25 /* Create new device object */
26 Status
= IoCreateDevice(DriverObject
,
27 sizeof(FDO_DEVICE_EXTENSION
),
29 FILE_DEVICE_BUS_EXTENDER
,
30 FILE_DEVICE_SECURE_OPEN
,
33 if (!NT_SUCCESS(Status
))
35 WARN_(SERENUM
, "IoCreateDevice() failed with status 0x%08lx\n", Status
);
38 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
39 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
41 /* Register device interface */
42 Status
= IoRegisterDeviceInterface(
44 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
,
46 &DeviceExtension
->SerenumInterfaceName
);
47 if (!NT_SUCCESS(Status
))
49 WARN_(SERENUM
, "IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
54 DeviceExtension
->Common
.IsFDO
= TRUE
;
55 DeviceExtension
->Common
.PnpState
= dsStopped
;
56 DeviceExtension
->Pdo
= Pdo
;
57 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
, SERENUM_TAG
, 0, 0);
58 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
59 if (!NT_SUCCESS(Status
))
61 WARN_(SERENUM
, "IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
65 if (DeviceExtension
->LowerDevice
->Flags
& DO_POWER_PAGABLE
)
66 Fdo
->Flags
|= DO_POWER_PAGABLE
;
67 if (DeviceExtension
->LowerDevice
->Flags
& DO_BUFFERED_IO
)
68 Fdo
->Flags
|= DO_BUFFERED_IO
;
69 if (DeviceExtension
->LowerDevice
->Flags
& DO_DIRECT_IO
)
70 Fdo
->Flags
|= DO_DIRECT_IO
;
71 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
73 return STATUS_SUCCESS
;
77 SerenumFdoStartDevice(
78 IN PDEVICE_OBJECT DeviceObject
,
81 PFDO_DEVICE_EXTENSION DeviceExtension
;
84 TRACE_(SERENUM
, "SerenumFdoStartDevice() called\n");
85 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
87 ASSERT(DeviceExtension
->Common
.PnpState
== dsStopped
);
89 Status
= IoSetDeviceInterfaceState(&DeviceExtension
->SerenumInterfaceName
, TRUE
);
90 if (!NT_SUCCESS(Status
))
92 WARN_(SERENUM
, "IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status
);
96 DeviceExtension
->Common
.PnpState
= dsStarted
;
98 return STATUS_SUCCESS
;
102 SerenumFdoQueryBusRelations(
103 IN PDEVICE_OBJECT DeviceObject
,
104 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
106 PFDO_DEVICE_EXTENSION DeviceExtension
;
107 PDEVICE_RELATIONS DeviceRelations
;
110 NTSTATUS Status
= STATUS_SUCCESS
;
112 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
113 ASSERT(DeviceExtension
->Common
.IsFDO
);
115 /* Do enumeration if needed */
116 if (!(DeviceExtension
->Flags
& FLAG_ENUMERATION_DONE
))
118 ASSERT(DeviceExtension
->AttachedPdo
== NULL
);
119 /* Detect plug-and-play devices */
120 Status
= SerenumDetectPnpDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
121 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
123 /* Detect legacy devices */
124 Status
= SerenumDetectLegacyDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
125 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
126 Status
= STATUS_SUCCESS
;
128 DeviceExtension
->Flags
|= FLAG_ENUMERATION_DONE
;
130 NumPDO
= (DeviceExtension
->AttachedPdo
!= NULL
? 1 : 0);
132 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(
134 sizeof(DEVICE_RELATIONS
) + sizeof(PDEVICE_OBJECT
) * (NumPDO
- 1),
136 if (!DeviceRelations
)
137 return STATUS_INSUFFICIENT_RESOURCES
;
139 /* Fill returned structure */
140 DeviceRelations
->Count
= NumPDO
;
141 for (i
= 0; i
< NumPDO
; i
++)
143 ObReferenceObject(DeviceExtension
->AttachedPdo
);
144 DeviceRelations
->Objects
[i
] = DeviceExtension
->AttachedPdo
;
147 *pDeviceRelations
= DeviceRelations
;
153 IN PDEVICE_OBJECT DeviceObject
,
157 PIO_STACK_LOCATION Stack
;
158 ULONG_PTR Information
= 0;
161 Stack
= IoGetCurrentIrpStackLocation(Irp
);
162 MinorFunction
= Stack
->MinorFunction
;
164 switch (MinorFunction
)
166 /* FIXME: do all these minor functions
167 IRP_MN_QUERY_REMOVE_DEVICE 0x1
168 IRP_MN_REMOVE_DEVICE 0x2
169 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
170 IRP_MN_STOP_DEVICE 0x4
171 IRP_MN_QUERY_STOP_DEVICE 0x5
172 IRP_MN_CANCEL_STOP_DEVICE 0x6
173 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
174 IRP_MN_QUERY_INTERFACE (optional) 0x8
175 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
176 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
177 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
178 IRP_MN_SURPRISE_REMOVAL 0x17
180 case IRP_MN_START_DEVICE
: /* 0x0 */
182 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
183 /* Call lower driver */
184 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
185 if (NT_SUCCESS(Status
))
186 Status
= SerenumFdoStartDevice(DeviceObject
, Irp
);
189 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x7 */
191 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
195 PDEVICE_RELATIONS DeviceRelations
= NULL
;
196 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
197 Status
= SerenumFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
198 Information
= (ULONG_PTR
)DeviceRelations
;
202 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
203 Stack
->Parameters
.QueryDeviceRelations
.Type
);
204 return ForwardIrpAndForget(DeviceObject
, Irp
);
208 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0xd */
210 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
211 return ForwardIrpAndForget(DeviceObject
, Irp
);
215 TRACE_(SERENUM
, "IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
216 return ForwardIrpAndForget(DeviceObject
, Irp
);
220 Irp
->IoStatus
.Information
= Information
;
221 Irp
->IoStatus
.Status
= Status
;
222 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);