1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS PCI Bus Driver
3*c2c66affSColin Finck * LICENSE: BSD - See COPYING.ARM in the top level directory
4*c2c66affSColin Finck * FILE: drivers/bus/pci/fdo.c
5*c2c66affSColin Finck * PURPOSE: FDO Device Management
6*c2c66affSColin Finck * PROGRAMMERS: ReactOS Portable Systems Group
7*c2c66affSColin Finck */
8*c2c66affSColin Finck
9*c2c66affSColin Finck /* INCLUDES *******************************************************************/
10*c2c66affSColin Finck
11*c2c66affSColin Finck #include <pci.h>
12*c2c66affSColin Finck
13*c2c66affSColin Finck #define NDEBUG
14*c2c66affSColin Finck #include <debug.h>
15*c2c66affSColin Finck
16*c2c66affSColin Finck /* GLOBALS ********************************************************************/
17*c2c66affSColin Finck
18*c2c66affSColin Finck SINGLE_LIST_ENTRY PciFdoExtensionListHead;
19*c2c66affSColin Finck BOOLEAN PciBreakOnDefault;
20*c2c66affSColin Finck
21*c2c66affSColin Finck PCI_MN_DISPATCH_TABLE PciFdoDispatchPowerTable[] =
22*c2c66affSColin Finck {
23*c2c66affSColin Finck {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoWaitWake},
24*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
25*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoSetPowerState},
26*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryPower},
27*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
28*c2c66affSColin Finck };
29*c2c66affSColin Finck
30*c2c66affSColin Finck PCI_MN_DISPATCH_TABLE PciFdoDispatchPnpTable[] =
31*c2c66affSColin Finck {
32*c2c66affSColin Finck {IRP_UPWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpStartDevice},
33*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryRemoveDevice},
34*c2c66affSColin Finck {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoIrpRemoveDevice},
35*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpCancelRemoveDevice},
36*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpStopDevice},
37*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryStopDevice},
38*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpCancelStopDevice},
39*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryDeviceRelations},
40*c2c66affSColin Finck {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryInterface},
41*c2c66affSColin Finck {IRP_UPWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryCapabilities},
42*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
43*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
44*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
45*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
46*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
47*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
48*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
49*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
50*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
51*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
52*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
53*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
54*c2c66affSColin Finck {IRP_UPWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpDeviceUsageNotification},
55*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpSurpriseRemoval},
56*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciFdoIrpQueryLegacyBusInformation},
57*c2c66affSColin Finck {IRP_DOWNWARD, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
58*c2c66affSColin Finck };
59*c2c66affSColin Finck
60*c2c66affSColin Finck PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable =
61*c2c66affSColin Finck {
62*c2c66affSColin Finck IRP_MN_QUERY_LEGACY_BUS_INFORMATION,
63*c2c66affSColin Finck PciFdoDispatchPnpTable,
64*c2c66affSColin Finck IRP_MN_QUERY_POWER,
65*c2c66affSColin Finck PciFdoDispatchPowerTable,
66*c2c66affSColin Finck IRP_DOWNWARD,
67*c2c66affSColin Finck (PCI_DISPATCH_FUNCTION)PciIrpNotSupported,
68*c2c66affSColin Finck IRP_DOWNWARD,
69*c2c66affSColin Finck (PCI_DISPATCH_FUNCTION)PciIrpNotSupported
70*c2c66affSColin Finck };
71*c2c66affSColin Finck
72*c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
73*c2c66affSColin Finck
74*c2c66affSColin Finck NTSTATUS
75*c2c66affSColin Finck NTAPI
PciFdoIrpStartDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)76*c2c66affSColin Finck PciFdoIrpStartDevice(IN PIRP Irp,
77*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
78*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
79*c2c66affSColin Finck {
80*c2c66affSColin Finck NTSTATUS Status;
81*c2c66affSColin Finck PCM_RESOURCE_LIST Resources;
82*c2c66affSColin Finck PAGED_CODE();
83*c2c66affSColin Finck
84*c2c66affSColin Finck /* The device stack must be starting the FDO in a success path */
85*c2c66affSColin Finck if (!NT_SUCCESS(Irp->IoStatus.Status)) return STATUS_NOT_SUPPORTED;
86*c2c66affSColin Finck
87*c2c66affSColin Finck /* Attempt to switch the state machine to the started state */
88*c2c66affSColin Finck Status = PciBeginStateTransition(DeviceExtension, PciStarted);
89*c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
90*c2c66affSColin Finck
91*c2c66affSColin Finck /* Check for any boot-provided resources */
92*c2c66affSColin Finck Resources = IoStackLocation->Parameters.StartDevice.AllocatedResources;
93*c2c66affSColin Finck if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension)))
94*c2c66affSColin Finck {
95*c2c66affSColin Finck /* These resources would only be for non-root FDOs, unhandled for now */
96*c2c66affSColin Finck ASSERT(Resources->Count == 1);
97*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
98*c2c66affSColin Finck }
99*c2c66affSColin Finck
100*c2c66affSColin Finck /* Initialize the arbiter for this FDO */
101*c2c66affSColin Finck Status = PciInitializeArbiterRanges(DeviceExtension, Resources);
102*c2c66affSColin Finck if (!NT_SUCCESS(Status))
103*c2c66affSColin Finck {
104*c2c66affSColin Finck /* Cancel the transition if this failed */
105*c2c66affSColin Finck PciCancelStateTransition(DeviceExtension, PciStarted);
106*c2c66affSColin Finck return Status;
107*c2c66affSColin Finck }
108*c2c66affSColin Finck
109*c2c66affSColin Finck /* Again, check for boot-provided resources for non-root FDO */
110*c2c66affSColin Finck if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension)))
111*c2c66affSColin Finck {
112*c2c66affSColin Finck /* Unhandled for now */
113*c2c66affSColin Finck ASSERT(Resources->Count == 1);
114*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
115*c2c66affSColin Finck }
116*c2c66affSColin Finck
117*c2c66affSColin Finck /* Commit the transition to the started state */
118*c2c66affSColin Finck PciCommitStateTransition(DeviceExtension, PciStarted);
119*c2c66affSColin Finck return STATUS_SUCCESS;
120*c2c66affSColin Finck }
121*c2c66affSColin Finck
122*c2c66affSColin Finck NTSTATUS
123*c2c66affSColin Finck NTAPI
PciFdoIrpQueryRemoveDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)124*c2c66affSColin Finck PciFdoIrpQueryRemoveDevice(IN PIRP Irp,
125*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
126*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
127*c2c66affSColin Finck {
128*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
129*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
130*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
131*c2c66affSColin Finck
132*c2c66affSColin Finck UNIMPLEMENTED;
133*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
134*c2c66affSColin Finck }
135*c2c66affSColin Finck
136*c2c66affSColin Finck NTSTATUS
137*c2c66affSColin Finck NTAPI
PciFdoIrpRemoveDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)138*c2c66affSColin Finck PciFdoIrpRemoveDevice(IN PIRP Irp,
139*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
140*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
141*c2c66affSColin Finck {
142*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
143*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
144*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
145*c2c66affSColin Finck
146*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
147*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
148*c2c66affSColin Finck }
149*c2c66affSColin Finck
150*c2c66affSColin Finck NTSTATUS
151*c2c66affSColin Finck NTAPI
PciFdoIrpCancelRemoveDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)152*c2c66affSColin Finck PciFdoIrpCancelRemoveDevice(IN PIRP Irp,
153*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
154*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
155*c2c66affSColin Finck {
156*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
157*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
158*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
159*c2c66affSColin Finck
160*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
161*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
162*c2c66affSColin Finck }
163*c2c66affSColin Finck
164*c2c66affSColin Finck NTSTATUS
165*c2c66affSColin Finck NTAPI
PciFdoIrpStopDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)166*c2c66affSColin Finck PciFdoIrpStopDevice(IN PIRP Irp,
167*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
168*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
169*c2c66affSColin Finck {
170*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
171*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
172*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
173*c2c66affSColin Finck
174*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
175*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
176*c2c66affSColin Finck }
177*c2c66affSColin Finck
178*c2c66affSColin Finck NTSTATUS
179*c2c66affSColin Finck NTAPI
PciFdoIrpQueryStopDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)180*c2c66affSColin Finck PciFdoIrpQueryStopDevice(IN PIRP Irp,
181*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
182*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
183*c2c66affSColin Finck {
184*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
185*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
186*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
187*c2c66affSColin Finck
188*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
189*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
190*c2c66affSColin Finck }
191*c2c66affSColin Finck
192*c2c66affSColin Finck NTSTATUS
193*c2c66affSColin Finck NTAPI
PciFdoIrpCancelStopDevice(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)194*c2c66affSColin Finck PciFdoIrpCancelStopDevice(IN PIRP Irp,
195*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
196*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
197*c2c66affSColin Finck {
198*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
199*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
200*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
201*c2c66affSColin Finck
202*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
203*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
204*c2c66affSColin Finck }
205*c2c66affSColin Finck
206*c2c66affSColin Finck NTSTATUS
207*c2c66affSColin Finck NTAPI
PciFdoIrpQueryDeviceRelations(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)208*c2c66affSColin Finck PciFdoIrpQueryDeviceRelations(IN PIRP Irp,
209*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
210*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
211*c2c66affSColin Finck {
212*c2c66affSColin Finck NTSTATUS Status;
213*c2c66affSColin Finck PAGED_CODE();
214*c2c66affSColin Finck
215*c2c66affSColin Finck /* Are bus relations being queried? */
216*c2c66affSColin Finck if (IoStackLocation->Parameters.QueryDeviceRelations.Type != BusRelations)
217*c2c66affSColin Finck {
218*c2c66affSColin Finck /* The FDO is a bus, so only bus relations can be obtained */
219*c2c66affSColin Finck Status = STATUS_NOT_SUPPORTED;
220*c2c66affSColin Finck }
221*c2c66affSColin Finck else
222*c2c66affSColin Finck {
223*c2c66affSColin Finck /* Scan the PCI bus and build the device relations for the caller */
224*c2c66affSColin Finck Status = PciQueryDeviceRelations(DeviceExtension,
225*c2c66affSColin Finck (PDEVICE_RELATIONS*)
226*c2c66affSColin Finck &Irp->IoStatus.Information);
227*c2c66affSColin Finck }
228*c2c66affSColin Finck
229*c2c66affSColin Finck /* Return the enumeration status back */
230*c2c66affSColin Finck return Status;
231*c2c66affSColin Finck }
232*c2c66affSColin Finck
233*c2c66affSColin Finck NTSTATUS
234*c2c66affSColin Finck NTAPI
PciFdoIrpQueryInterface(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)235*c2c66affSColin Finck PciFdoIrpQueryInterface(IN PIRP Irp,
236*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
237*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
238*c2c66affSColin Finck {
239*c2c66affSColin Finck NTSTATUS Status;
240*c2c66affSColin Finck PAGED_CODE();
241*c2c66affSColin Finck ASSERT(DeviceExtension->ExtensionType == PciFdoExtensionType);
242*c2c66affSColin Finck
243*c2c66affSColin Finck /* Deleted extensions don't respond to IRPs */
244*c2c66affSColin Finck if (DeviceExtension->DeviceState == PciDeleted)
245*c2c66affSColin Finck {
246*c2c66affSColin Finck /* Hand it back to try to deal with it */
247*c2c66affSColin Finck return PciPassIrpFromFdoToPdo(DeviceExtension, Irp);
248*c2c66affSColin Finck }
249*c2c66affSColin Finck
250*c2c66affSColin Finck /* Query our driver for this interface */
251*c2c66affSColin Finck Status = PciQueryInterface(DeviceExtension,
252*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
253*c2c66affSColin Finck InterfaceType,
254*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
255*c2c66affSColin Finck Size,
256*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
257*c2c66affSColin Finck Version,
258*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
259*c2c66affSColin Finck InterfaceSpecificData,
260*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
261*c2c66affSColin Finck Interface,
262*c2c66affSColin Finck FALSE);
263*c2c66affSColin Finck if (NT_SUCCESS(Status))
264*c2c66affSColin Finck {
265*c2c66affSColin Finck /* We found it, let the PDO handle it */
266*c2c66affSColin Finck Irp->IoStatus.Status = Status;
267*c2c66affSColin Finck return PciPassIrpFromFdoToPdo(DeviceExtension, Irp);
268*c2c66affSColin Finck }
269*c2c66affSColin Finck else if (Status == STATUS_NOT_SUPPORTED)
270*c2c66affSColin Finck {
271*c2c66affSColin Finck /* Otherwise, we can't handle it, let someone else down the stack try */
272*c2c66affSColin Finck Status = PciCallDownIrpStack(DeviceExtension, Irp);
273*c2c66affSColin Finck if (Status == STATUS_NOT_SUPPORTED)
274*c2c66affSColin Finck {
275*c2c66affSColin Finck /* They can't either, try a last-resort interface lookup */
276*c2c66affSColin Finck Status = PciQueryInterface(DeviceExtension,
277*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
278*c2c66affSColin Finck InterfaceType,
279*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
280*c2c66affSColin Finck Size,
281*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
282*c2c66affSColin Finck Version,
283*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
284*c2c66affSColin Finck InterfaceSpecificData,
285*c2c66affSColin Finck IoStackLocation->Parameters.QueryInterface.
286*c2c66affSColin Finck Interface,
287*c2c66affSColin Finck TRUE);
288*c2c66affSColin Finck }
289*c2c66affSColin Finck }
290*c2c66affSColin Finck
291*c2c66affSColin Finck /* Has anyone claimed this interface yet? */
292*c2c66affSColin Finck if (Status == STATUS_NOT_SUPPORTED)
293*c2c66affSColin Finck {
294*c2c66affSColin Finck /* No, return the original IRP status */
295*c2c66affSColin Finck Status = Irp->IoStatus.Status;
296*c2c66affSColin Finck }
297*c2c66affSColin Finck else
298*c2c66affSColin Finck {
299*c2c66affSColin Finck /* Yes, set the new IRP status */
300*c2c66affSColin Finck Irp->IoStatus.Status = Status;
301*c2c66affSColin Finck }
302*c2c66affSColin Finck
303*c2c66affSColin Finck /* Complete this IRP */
304*c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
305*c2c66affSColin Finck return Status;
306*c2c66affSColin Finck }
307*c2c66affSColin Finck
308*c2c66affSColin Finck NTSTATUS
309*c2c66affSColin Finck NTAPI
PciFdoIrpQueryCapabilities(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)310*c2c66affSColin Finck PciFdoIrpQueryCapabilities(IN PIRP Irp,
311*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
312*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
313*c2c66affSColin Finck {
314*c2c66affSColin Finck PDEVICE_CAPABILITIES Capabilities;
315*c2c66affSColin Finck PAGED_CODE();
316*c2c66affSColin Finck ASSERT_FDO(DeviceExtension);
317*c2c66affSColin Finck
318*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
319*c2c66affSColin Finck
320*c2c66affSColin Finck /* Get the capabilities */
321*c2c66affSColin Finck Capabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities;
322*c2c66affSColin Finck
323*c2c66affSColin Finck /* Inherit wake levels and power mappings from the higher-up capabilities */
324*c2c66affSColin Finck DeviceExtension->PowerState.SystemWakeLevel = Capabilities->SystemWake;
325*c2c66affSColin Finck DeviceExtension->PowerState.DeviceWakeLevel = Capabilities->DeviceWake;
326*c2c66affSColin Finck RtlCopyMemory(DeviceExtension->PowerState.SystemStateMapping,
327*c2c66affSColin Finck Capabilities->DeviceState,
328*c2c66affSColin Finck sizeof(DeviceExtension->PowerState.SystemStateMapping));
329*c2c66affSColin Finck
330*c2c66affSColin Finck /* Dump the capabilities and return success */
331*c2c66affSColin Finck PciDebugDumpQueryCapabilities(Capabilities);
332*c2c66affSColin Finck return STATUS_SUCCESS;
333*c2c66affSColin Finck }
334*c2c66affSColin Finck
335*c2c66affSColin Finck NTSTATUS
336*c2c66affSColin Finck NTAPI
PciFdoIrpDeviceUsageNotification(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)337*c2c66affSColin Finck PciFdoIrpDeviceUsageNotification(IN PIRP Irp,
338*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
339*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
340*c2c66affSColin Finck {
341*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
342*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
343*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
344*c2c66affSColin Finck
345*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
346*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
347*c2c66affSColin Finck }
348*c2c66affSColin Finck
349*c2c66affSColin Finck NTSTATUS
350*c2c66affSColin Finck NTAPI
PciFdoIrpSurpriseRemoval(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)351*c2c66affSColin Finck PciFdoIrpSurpriseRemoval(IN PIRP Irp,
352*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
353*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
354*c2c66affSColin Finck {
355*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
356*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
357*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
358*c2c66affSColin Finck
359*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
360*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
361*c2c66affSColin Finck }
362*c2c66affSColin Finck
363*c2c66affSColin Finck NTSTATUS
364*c2c66affSColin Finck NTAPI
PciFdoIrpQueryLegacyBusInformation(IN PIRP Irp,IN PIO_STACK_LOCATION IoStackLocation,IN PPCI_FDO_EXTENSION DeviceExtension)365*c2c66affSColin Finck PciFdoIrpQueryLegacyBusInformation(IN PIRP Irp,
366*c2c66affSColin Finck IN PIO_STACK_LOCATION IoStackLocation,
367*c2c66affSColin Finck IN PPCI_FDO_EXTENSION DeviceExtension)
368*c2c66affSColin Finck {
369*c2c66affSColin Finck UNREFERENCED_PARAMETER(Irp);
370*c2c66affSColin Finck UNREFERENCED_PARAMETER(IoStackLocation);
371*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceExtension);
372*c2c66affSColin Finck
373*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
374*c2c66affSColin Finck return STATUS_NOT_SUPPORTED;
375*c2c66affSColin Finck }
376*c2c66affSColin Finck
377*c2c66affSColin Finck VOID
378*c2c66affSColin Finck NTAPI
PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension)379*c2c66affSColin Finck PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension)
380*c2c66affSColin Finck {
381*c2c66affSColin Finck ACPI_EVAL_INPUT_BUFFER InputBuffer;
382*c2c66affSColin Finck PACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
383*c2c66affSColin Finck ULONG Length;
384*c2c66affSColin Finck NTSTATUS Status;
385*c2c66affSColin Finck PAGED_CODE();
386*c2c66affSColin Finck
387*c2c66affSColin Finck /* We should receive 4 parameters, per the HPP specification */
388*c2c66affSColin Finck Length = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 4 * sizeof(ACPI_METHOD_ARGUMENT);
389*c2c66affSColin Finck
390*c2c66affSColin Finck /* Allocate the buffer to hold the parameters */
391*c2c66affSColin Finck OutputBuffer = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG);
392*c2c66affSColin Finck if (!OutputBuffer) return;
393*c2c66affSColin Finck
394*c2c66affSColin Finck /* Initialize the output and input buffers. The method is _HPP */
395*c2c66affSColin Finck RtlZeroMemory(OutputBuffer, Length);
396*c2c66affSColin Finck *(PULONG)InputBuffer.MethodName = 'PPH_';
397*c2c66affSColin Finck InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
398*c2c66affSColin Finck do
399*c2c66affSColin Finck {
400*c2c66affSColin Finck /* Send the IOCTL to the ACPI driver */
401*c2c66affSColin Finck Status = PciSendIoctl(FdoExtension->PhysicalDeviceObject,
402*c2c66affSColin Finck IOCTL_ACPI_EVAL_METHOD,
403*c2c66affSColin Finck &InputBuffer,
404*c2c66affSColin Finck sizeof(InputBuffer),
405*c2c66affSColin Finck OutputBuffer,
406*c2c66affSColin Finck Length);
407*c2c66affSColin Finck if (!NT_SUCCESS(Status))
408*c2c66affSColin Finck {
409*c2c66affSColin Finck /* The method failed, check if we can salvage data from parent */
410*c2c66affSColin Finck if (!PCI_IS_ROOT_FDO(FdoExtension))
411*c2c66affSColin Finck {
412*c2c66affSColin Finck /* Copy the root bus' hot plug parameters */
413*c2c66affSColin Finck FdoExtension->HotPlugParameters = FdoExtension->ParentFdoExtension->HotPlugParameters;
414*c2c66affSColin Finck }
415*c2c66affSColin Finck
416*c2c66affSColin Finck /* Nothing more to do on this path */
417*c2c66affSColin Finck break;
418*c2c66affSColin Finck }
419*c2c66affSColin Finck
420*c2c66affSColin Finck /* ACPI sent back some data. 4 parameters are expected in the output */
421*c2c66affSColin Finck if (OutputBuffer->Count != 4) break;
422*c2c66affSColin Finck
423*c2c66affSColin Finck /* HotPlug PCI Support not yet implemented */
424*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
425*c2c66affSColin Finck } while (FALSE);
426*c2c66affSColin Finck
427*c2c66affSColin Finck /* Free the buffer and return */
428*c2c66affSColin Finck ExFreePoolWithTag(OutputBuffer, 0);
429*c2c66affSColin Finck }
430*c2c66affSColin Finck
431*c2c66affSColin Finck VOID
432*c2c66affSColin Finck NTAPI
PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension,IN PDEVICE_OBJECT DeviceObject,IN PDEVICE_OBJECT PhysicalDeviceObject)433*c2c66affSColin Finck PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension,
434*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
435*c2c66affSColin Finck IN PDEVICE_OBJECT PhysicalDeviceObject)
436*c2c66affSColin Finck {
437*c2c66affSColin Finck /* Initialize the extension */
438*c2c66affSColin Finck RtlZeroMemory(FdoExtension, sizeof(PCI_FDO_EXTENSION));
439*c2c66affSColin Finck
440*c2c66affSColin Finck /* Setup the common fields */
441*c2c66affSColin Finck FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject;
442*c2c66affSColin Finck FdoExtension->FunctionalDeviceObject = DeviceObject;
443*c2c66affSColin Finck FdoExtension->ExtensionType = PciFdoExtensionType;
444*c2c66affSColin Finck FdoExtension->PowerState.CurrentSystemState = PowerSystemWorking;
445*c2c66affSColin Finck FdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
446*c2c66affSColin Finck FdoExtension->IrpDispatchTable = &PciFdoDispatchTable;
447*c2c66affSColin Finck
448*c2c66affSColin Finck /* Initialize the extension locks */
449*c2c66affSColin Finck KeInitializeEvent(&FdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE);
450*c2c66affSColin Finck KeInitializeEvent(&FdoExtension->ChildListLock, SynchronizationEvent, TRUE);
451*c2c66affSColin Finck
452*c2c66affSColin Finck /* Initialize the default state */
453*c2c66affSColin Finck PciInitializeState(FdoExtension);
454*c2c66affSColin Finck }
455*c2c66affSColin Finck
456*c2c66affSColin Finck NTSTATUS
457*c2c66affSColin Finck NTAPI
PciAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PhysicalDeviceObject)458*c2c66affSColin Finck PciAddDevice(IN PDRIVER_OBJECT DriverObject,
459*c2c66affSColin Finck IN PDEVICE_OBJECT PhysicalDeviceObject)
460*c2c66affSColin Finck {
461*c2c66affSColin Finck PCM_RESOURCE_LIST Descriptor;
462*c2c66affSColin Finck PDEVICE_OBJECT AttachedTo;
463*c2c66affSColin Finck PPCI_FDO_EXTENSION FdoExtension;
464*c2c66affSColin Finck PPCI_FDO_EXTENSION ParentExtension;
465*c2c66affSColin Finck PPCI_PDO_EXTENSION PdoExtension;
466*c2c66affSColin Finck PDEVICE_OBJECT DeviceObject;
467*c2c66affSColin Finck UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
468*c2c66affSColin Finck PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
469*c2c66affSColin Finck NTSTATUS Status;
470*c2c66affSColin Finck HANDLE KeyHandle;
471*c2c66affSColin Finck UNICODE_STRING ValueName;
472*c2c66affSColin Finck ULONG ResultLength;
473*c2c66affSColin Finck PAGED_CODE();
474*c2c66affSColin Finck DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n",
475*c2c66affSColin Finck PhysicalDeviceObject, &PhysicalDeviceObject->DriverObject->DriverName);
476*c2c66affSColin Finck
477*c2c66affSColin Finck /* Zero out variables so failure path knows what to do */
478*c2c66affSColin Finck AttachedTo = NULL;
479*c2c66affSColin Finck FdoExtension = NULL;
480*c2c66affSColin Finck PdoExtension = NULL;
481*c2c66affSColin Finck DeviceObject = NULL;
482*c2c66affSColin Finck
483*c2c66affSColin Finck do
484*c2c66affSColin Finck {
485*c2c66affSColin Finck /* Check if there's already a device extension for this bus */
486*c2c66affSColin Finck ParentExtension = PciFindParentPciFdoExtension(PhysicalDeviceObject,
487*c2c66affSColin Finck &PciGlobalLock);
488*c2c66affSColin Finck if (ParentExtension)
489*c2c66affSColin Finck {
490*c2c66affSColin Finck /* Make sure we find a real PDO */
491*c2c66affSColin Finck PdoExtension = PhysicalDeviceObject->DeviceExtension;
492*c2c66affSColin Finck ASSERT_PDO(PdoExtension);
493*c2c66affSColin Finck
494*c2c66affSColin Finck /* Make sure it's a PCI-to-PCI bridge */
495*c2c66affSColin Finck if ((PdoExtension->BaseClass != PCI_CLASS_BRIDGE_DEV) ||
496*c2c66affSColin Finck (PdoExtension->SubClass != PCI_SUBCLASS_BR_PCI_TO_PCI))
497*c2c66affSColin Finck {
498*c2c66affSColin Finck /* This should never happen */
499*c2c66affSColin Finck DPRINT1("PCI - PciAddDevice for Non-Root/Non-PCI-PCI bridge,\n"
500*c2c66affSColin Finck " Class %02x, SubClass %02x, will not add.\n",
501*c2c66affSColin Finck PdoExtension->BaseClass,
502*c2c66affSColin Finck PdoExtension->SubClass);
503*c2c66affSColin Finck ASSERT((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
504*c2c66affSColin Finck (PdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI));
505*c2c66affSColin Finck
506*c2c66affSColin Finck /* Enter the failure path */
507*c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_REQUEST;
508*c2c66affSColin Finck break;
509*c2c66affSColin Finck }
510*c2c66affSColin Finck
511*c2c66affSColin Finck /* Subordinate bus on the bridge */
512*c2c66affSColin Finck DPRINT1("PCI - AddDevice (new bus is child of bus 0x%x).\n",
513*c2c66affSColin Finck ParentExtension->BaseBus);
514*c2c66affSColin Finck
515*c2c66affSColin Finck /* Make sure PCI bus numbers are configured */
516*c2c66affSColin Finck if (!PciAreBusNumbersConfigured(PdoExtension))
517*c2c66affSColin Finck {
518*c2c66affSColin Finck /* This is a critical failure */
519*c2c66affSColin Finck DPRINT1("PCI - Bus numbers not configured for bridge (0x%x.0x%x.0x%x)\n",
520*c2c66affSColin Finck ParentExtension->BaseBus,
521*c2c66affSColin Finck PdoExtension->Slot.u.bits.DeviceNumber,
522*c2c66affSColin Finck PdoExtension->Slot.u.bits.FunctionNumber);
523*c2c66affSColin Finck
524*c2c66affSColin Finck /* Enter the failure path */
525*c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_REQUEST;
526*c2c66affSColin Finck break;
527*c2c66affSColin Finck }
528*c2c66affSColin Finck }
529*c2c66affSColin Finck
530*c2c66affSColin Finck /* Create the FDO for the bus */
531*c2c66affSColin Finck Status = IoCreateDevice(DriverObject,
532*c2c66affSColin Finck sizeof(PCI_FDO_EXTENSION),
533*c2c66affSColin Finck NULL,
534*c2c66affSColin Finck FILE_DEVICE_BUS_EXTENDER,
535*c2c66affSColin Finck 0,
536*c2c66affSColin Finck 0,
537*c2c66affSColin Finck &DeviceObject);
538*c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
539*c2c66affSColin Finck
540*c2c66affSColin Finck /* Initialize the extension for the FDO */
541*c2c66affSColin Finck FdoExtension = DeviceObject->DeviceExtension;
542*c2c66affSColin Finck PciInitializeFdoExtensionCommonFields(DeviceObject->DeviceExtension,
543*c2c66affSColin Finck DeviceObject,
544*c2c66affSColin Finck PhysicalDeviceObject);
545*c2c66affSColin Finck
546*c2c66affSColin Finck /* Attach to the root PDO */
547*c2c66affSColin Finck Status = STATUS_NO_SUCH_DEVICE;
548*c2c66affSColin Finck AttachedTo = IoAttachDeviceToDeviceStack(DeviceObject,
549*c2c66affSColin Finck PhysicalDeviceObject);
550*c2c66affSColin Finck ASSERT(AttachedTo != NULL);
551*c2c66affSColin Finck if (!AttachedTo) break;
552*c2c66affSColin Finck FdoExtension->AttachedDeviceObject = AttachedTo;
553*c2c66affSColin Finck
554*c2c66affSColin Finck /* Check if this is a child bus, or the root */
555*c2c66affSColin Finck if (ParentExtension)
556*c2c66affSColin Finck {
557*c2c66affSColin Finck /* The child inherits root data */
558*c2c66affSColin Finck FdoExtension->BaseBus = PdoExtension->Dependent.type1.SecondaryBus;
559*c2c66affSColin Finck FdoExtension->BusRootFdoExtension = ParentExtension->BusRootFdoExtension;
560*c2c66affSColin Finck PdoExtension->BridgeFdoExtension = FdoExtension;
561*c2c66affSColin Finck FdoExtension->ParentFdoExtension = ParentExtension;
562*c2c66affSColin Finck }
563*c2c66affSColin Finck else
564*c2c66affSColin Finck {
565*c2c66affSColin Finck /* Query the boot configuration */
566*c2c66affSColin Finck Status = PciGetDeviceProperty(PhysicalDeviceObject,
567*c2c66affSColin Finck DevicePropertyBootConfiguration,
568*c2c66affSColin Finck (PVOID*)&Descriptor);
569*c2c66affSColin Finck if (!NT_SUCCESS(Status))
570*c2c66affSColin Finck {
571*c2c66affSColin Finck /* No configuration has been set */
572*c2c66affSColin Finck Descriptor = NULL;
573*c2c66affSColin Finck }
574*c2c66affSColin Finck else
575*c2c66affSColin Finck {
576*c2c66affSColin Finck /* Root PDO in ReactOS does not assign boot resources */
577*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK("Encountered during setup\n");
578*c2c66affSColin Finck Descriptor = NULL;
579*c2c66affSColin Finck }
580*c2c66affSColin Finck
581*c2c66affSColin Finck if (Descriptor)
582*c2c66affSColin Finck {
583*c2c66affSColin Finck /* Root PDO in ReactOS does not assign boot resources */
584*c2c66affSColin Finck UNIMPLEMENTED_DBGBREAK();
585*c2c66affSColin Finck }
586*c2c66affSColin Finck else
587*c2c66affSColin Finck {
588*c2c66affSColin Finck /* Default configuration isn't the normal path on Windows */
589*c2c66affSColin Finck if (PciBreakOnDefault)
590*c2c66affSColin Finck {
591*c2c66affSColin Finck /* If a second bus is found and there's still no data, crash */
592*c2c66affSColin Finck KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL,
593*c2c66affSColin Finck 0xDEAD0010u,
594*c2c66affSColin Finck (ULONG_PTR)DeviceObject,
595*c2c66affSColin Finck 0,
596*c2c66affSColin Finck 0);
597*c2c66affSColin Finck }
598*c2c66affSColin Finck
599*c2c66affSColin Finck /* Warn that a default configuration will be used, and set bus 0 */
600*c2c66affSColin Finck DPRINT1("PCI Will use default configuration.\n");
601*c2c66affSColin Finck PciBreakOnDefault = TRUE;
602*c2c66affSColin Finck FdoExtension->BaseBus = 0;
603*c2c66affSColin Finck }
604*c2c66affSColin Finck
605*c2c66affSColin Finck /* This is the root bus */
606*c2c66affSColin Finck FdoExtension->BusRootFdoExtension = FdoExtension;
607*c2c66affSColin Finck }
608*c2c66affSColin Finck
609*c2c66affSColin Finck /* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */
610*c2c66affSColin Finck Status = PciGetConfigHandlers(FdoExtension);
611*c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
612*c2c66affSColin Finck
613*c2c66affSColin Finck /* Initialize all the supported PCI arbiters */
614*c2c66affSColin Finck Status = PciInitializeArbiters(FdoExtension);
615*c2c66affSColin Finck if (!NT_SUCCESS(Status)) break;
616*c2c66affSColin Finck
617*c2c66affSColin Finck /* This is a real FDO, insert it into the list */
618*c2c66affSColin Finck FdoExtension->Fake = FALSE;
619*c2c66affSColin Finck PciInsertEntryAtTail(&PciFdoExtensionListHead,
620*c2c66affSColin Finck FdoExtension,
621*c2c66affSColin Finck &PciGlobalLock);
622*c2c66affSColin Finck
623*c2c66affSColin Finck /* Open the device registry key so that we can query the errata flags */
624*c2c66affSColin Finck IoOpenDeviceRegistryKey(DeviceObject,
625*c2c66affSColin Finck PLUGPLAY_REGKEY_DEVICE,
626*c2c66affSColin Finck KEY_ALL_ACCESS,
627*c2c66affSColin Finck &KeyHandle),
628*c2c66affSColin Finck
629*c2c66affSColin Finck /* Open the value that contains errata flags for this bus instance */
630*c2c66affSColin Finck RtlInitUnicodeString(&ValueName, L"HackFlags");
631*c2c66affSColin Finck Status = ZwQueryValueKey(KeyHandle,
632*c2c66affSColin Finck &ValueName,
633*c2c66affSColin Finck KeyValuePartialInformation,
634*c2c66affSColin Finck ValueInfo,
635*c2c66affSColin Finck sizeof(Buffer),
636*c2c66affSColin Finck &ResultLength);
637*c2c66affSColin Finck ZwClose(KeyHandle);
638*c2c66affSColin Finck if (NT_SUCCESS(Status))
639*c2c66affSColin Finck {
640*c2c66affSColin Finck /* Make sure the data is of expected type and size */
641*c2c66affSColin Finck if ((ValueInfo->Type == REG_DWORD) &&
642*c2c66affSColin Finck (ValueInfo->DataLength == sizeof(ULONG)))
643*c2c66affSColin Finck {
644*c2c66affSColin Finck /* Read the flags for this bus */
645*c2c66affSColin Finck FdoExtension->BusHackFlags = *(PULONG)&ValueInfo->Data;
646*c2c66affSColin Finck }
647*c2c66affSColin Finck }
648*c2c66affSColin Finck
649*c2c66affSColin Finck /* Query ACPI for PCI HotPlug Support */
650*c2c66affSColin Finck PciGetHotPlugParameters(FdoExtension);
651*c2c66affSColin Finck
652*c2c66affSColin Finck /* The Bus FDO is now initialized */
653*c2c66affSColin Finck DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
654*c2c66affSColin Finck return STATUS_SUCCESS;
655*c2c66affSColin Finck } while (FALSE);
656*c2c66affSColin Finck
657*c2c66affSColin Finck /* This is the failure path */
658*c2c66affSColin Finck ASSERT(!NT_SUCCESS(Status));
659*c2c66affSColin Finck
660*c2c66affSColin Finck /* Check if the FDO extension exists */
661*c2c66affSColin Finck if (FdoExtension) DPRINT1("Should destroy secondaries\n");
662*c2c66affSColin Finck
663*c2c66affSColin Finck /* Delete device objects */
664*c2c66affSColin Finck if (AttachedTo) IoDetachDevice(AttachedTo);
665*c2c66affSColin Finck if (DeviceObject) IoDeleteDevice(DeviceObject);
666*c2c66affSColin Finck return Status;
667*c2c66affSColin Finck }
668*c2c66affSColin Finck
669*c2c66affSColin Finck /* EOF */
670