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)
14 IN PDRIVER_OBJECT DriverObject
,
15 IN PDEVICE_OBJECT Pdo
)
18 PFDO_DEVICE_EXTENSION DeviceExtension
;
21 TRACE_(SERENUM
, "SerenumAddDevice called. Pdo = %p\n", Pdo
);
23 /* Create new device object */
24 Status
= IoCreateDevice(DriverObject
,
25 sizeof(FDO_DEVICE_EXTENSION
),
27 FILE_DEVICE_BUS_EXTENDER
,
28 FILE_DEVICE_SECURE_OPEN
,
31 if (!NT_SUCCESS(Status
))
33 WARN_(SERENUM
, "IoCreateDevice() failed with status 0x%08lx\n", Status
);
36 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
37 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
39 /* Register device interface */
40 Status
= IoRegisterDeviceInterface(
42 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
,
44 &DeviceExtension
->SerenumInterfaceName
);
45 if (!NT_SUCCESS(Status
))
47 WARN_(SERENUM
, "IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status
);
52 DeviceExtension
->Common
.IsFDO
= TRUE
;
53 DeviceExtension
->Common
.PnpState
= dsStopped
;
54 DeviceExtension
->Pdo
= Pdo
;
55 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
, SERENUM_TAG
, 0, 0);
56 Status
= IoAttachDeviceToDeviceStackSafe(Fdo
, Pdo
, &DeviceExtension
->LowerDevice
);
57 if (!NT_SUCCESS(Status
))
59 WARN_(SERENUM
, "IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
63 if (DeviceExtension
->LowerDevice
->Flags
& DO_POWER_PAGABLE
)
64 Fdo
->Flags
|= DO_POWER_PAGABLE
;
65 if (DeviceExtension
->LowerDevice
->Flags
& DO_BUFFERED_IO
)
66 Fdo
->Flags
|= DO_BUFFERED_IO
;
67 if (DeviceExtension
->LowerDevice
->Flags
& DO_DIRECT_IO
)
68 Fdo
->Flags
|= DO_DIRECT_IO
;
69 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
71 return STATUS_SUCCESS
;
75 SerenumFdoStartDevice(
76 IN PDEVICE_OBJECT DeviceObject
,
79 PFDO_DEVICE_EXTENSION DeviceExtension
;
82 TRACE_(SERENUM
, "SerenumFdoStartDevice() called\n");
83 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
85 ASSERT(DeviceExtension
->Common
.PnpState
== dsStopped
);
87 Status
= IoSetDeviceInterfaceState(&DeviceExtension
->SerenumInterfaceName
, TRUE
);
88 if (!NT_SUCCESS(Status
))
90 WARN_(SERENUM
, "IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status
);
94 DeviceExtension
->Common
.PnpState
= dsStarted
;
96 return STATUS_SUCCESS
;
100 SerenumFdoQueryBusRelations(
101 IN PDEVICE_OBJECT DeviceObject
,
102 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
104 PFDO_DEVICE_EXTENSION DeviceExtension
;
105 PDEVICE_RELATIONS DeviceRelations
;
108 NTSTATUS Status
= STATUS_SUCCESS
;
110 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
111 ASSERT(DeviceExtension
->Common
.IsFDO
);
113 /* Do enumeration if needed */
114 if (!(DeviceExtension
->Flags
& FLAG_ENUMERATION_DONE
))
116 ASSERT(DeviceExtension
->AttachedPdo
== NULL
);
117 /* Detect plug-and-play devices */
118 Status
= SerenumDetectPnpDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
119 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
121 /* Detect legacy devices */
122 Status
= SerenumDetectLegacyDevice(DeviceObject
, DeviceExtension
->LowerDevice
);
123 if (Status
== STATUS_DEVICE_NOT_CONNECTED
)
124 Status
= STATUS_SUCCESS
;
126 DeviceExtension
->Flags
|= FLAG_ENUMERATION_DONE
;
128 NumPDO
= (DeviceExtension
->AttachedPdo
!= NULL
? 1 : 0);
130 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(
132 sizeof(DEVICE_RELATIONS
) + sizeof(PDEVICE_OBJECT
) * (NumPDO
- 1),
134 if (!DeviceRelations
)
135 return STATUS_INSUFFICIENT_RESOURCES
;
137 /* Fill returned structure */
138 DeviceRelations
->Count
= NumPDO
;
139 for (i
= 0; i
< NumPDO
; i
++)
141 ObReferenceObject(DeviceExtension
->AttachedPdo
);
142 DeviceRelations
->Objects
[i
] = DeviceExtension
->AttachedPdo
;
145 *pDeviceRelations
= DeviceRelations
;
151 IN PDEVICE_OBJECT DeviceObject
,
155 PIO_STACK_LOCATION Stack
;
156 ULONG_PTR Information
= 0;
159 Stack
= IoGetCurrentIrpStackLocation(Irp
);
160 MinorFunction
= Stack
->MinorFunction
;
162 switch (MinorFunction
)
164 /* FIXME: do all these minor functions
165 IRP_MN_QUERY_REMOVE_DEVICE 0x1
166 IRP_MN_REMOVE_DEVICE 0x2
167 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
168 IRP_MN_STOP_DEVICE 0x4
169 IRP_MN_QUERY_STOP_DEVICE 0x5
170 IRP_MN_CANCEL_STOP_DEVICE 0x6
171 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
172 IRP_MN_QUERY_INTERFACE (optional) 0x8
173 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
174 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
175 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
176 IRP_MN_SURPRISE_REMOVAL 0x17
178 case IRP_MN_START_DEVICE
: /* 0x0 */
180 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
181 /* Call lower driver */
182 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
183 if (NT_SUCCESS(Status
))
184 Status
= SerenumFdoStartDevice(DeviceObject
, Irp
);
187 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x7 */
189 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
193 PDEVICE_RELATIONS DeviceRelations
= NULL
;
194 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
195 Status
= SerenumFdoQueryBusRelations(DeviceObject
, &DeviceRelations
);
196 Information
= (ULONG_PTR
)DeviceRelations
;
200 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
201 Stack
->Parameters
.QueryDeviceRelations
.Type
);
202 return ForwardIrpAndForget(DeviceObject
, Irp
);
206 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0xd */
208 TRACE_(SERENUM
, "IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
209 return ForwardIrpAndForget(DeviceObject
, Irp
);
213 TRACE_(SERENUM
, "IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction
);
214 return ForwardIrpAndForget(DeviceObject
, Irp
);
218 Irp
->IoStatus
.Information
= Information
;
219 Irp
->IoStatus
.Status
= Status
;
220 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);