2 * PROJECT: ReactOS ISA PnP Bus driver
4 * PURPOSE: PDO-specific code
5 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
16 IsaPdoQueryDeviceRelations(
17 IN PISAPNP_PDO_EXTENSION PdoExt
,
19 IN PIO_STACK_LOCATION IrpSp
)
21 PDEVICE_RELATIONS DeviceRelations
;
23 if (IrpSp
->Parameters
.QueryDeviceRelations
.Type
== RemovalRelations
&&
24 PdoExt
->Common
.Self
== PdoExt
->FdoExt
->DataPortPdo
)
26 return IsaPnpFillDeviceRelations(PdoExt
->FdoExt
, Irp
, FALSE
);
29 if (IrpSp
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
30 return Irp
->IoStatus
.Status
;
32 DeviceRelations
= ExAllocatePool(PagedPool
, sizeof(*DeviceRelations
));
34 return STATUS_NO_MEMORY
;
36 DeviceRelations
->Count
= 1;
37 DeviceRelations
->Objects
[0] = PdoExt
->Common
.Self
;
38 ObReferenceObject(PdoExt
->Common
.Self
);
40 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
42 return STATUS_SUCCESS
;
47 IsaPdoQueryCapabilities(
48 IN PISAPNP_PDO_EXTENSION PdoExt
,
50 IN PIO_STACK_LOCATION IrpSp
)
52 PDEVICE_CAPABILITIES DeviceCapabilities
;
53 PISAPNP_LOGICAL_DEVICE LogDev
= PdoExt
->IsaPnpDevice
;
56 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
57 if (DeviceCapabilities
->Version
!= 1)
58 return STATUS_REVISION_MISMATCH
;
62 DeviceCapabilities
->UniqueID
= TRUE
;
63 DeviceCapabilities
->Address
= LogDev
->CSN
;
67 DeviceCapabilities
->UniqueID
= FALSE
;
68 DeviceCapabilities
->RawDeviceOK
= TRUE
;
69 DeviceCapabilities
->SilentInstall
= TRUE
;
72 for (i
= 0; i
< POWER_SYSTEM_MAXIMUM
; i
++)
73 DeviceCapabilities
->DeviceState
[i
] = PowerDeviceD3
;
74 DeviceCapabilities
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
76 return STATUS_SUCCESS
;
81 IsaPdoQueryPnpDeviceState(
82 IN PISAPNP_PDO_EXTENSION PdoExt
,
84 IN PIO_STACK_LOCATION IrpSp
)
86 Irp
->IoStatus
.Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
87 return STATUS_SUCCESS
;
93 IN PISAPNP_PDO_EXTENSION PdoExt
,
95 IN PIO_STACK_LOCATION IrpSp
)
97 PUNICODE_STRING Source
;
100 switch (IrpSp
->Parameters
.QueryId
.IdType
)
102 case BusQueryDeviceID
:
103 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
104 Source
= &PdoExt
->DeviceID
;
107 case BusQueryHardwareIDs
:
108 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
109 Source
= &PdoExt
->HardwareIDs
;
112 case BusQueryCompatibleIDs
:
113 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
114 Source
= &PdoExt
->CompatibleIDs
;
117 case BusQueryInstanceID
:
118 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
119 Source
= &PdoExt
->InstanceID
;
123 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n",
124 IrpSp
->Parameters
.QueryId
.IdType
);
125 return Irp
->IoStatus
.Status
;
129 return Irp
->IoStatus
.Status
;
131 Buffer
= ExAllocatePool(PagedPool
, Source
->MaximumLength
);
133 return STATUS_NO_MEMORY
;
135 RtlCopyMemory(Buffer
, Source
->Buffer
, Source
->MaximumLength
);
136 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
137 return STATUS_SUCCESS
;
142 IsaPdoQueryResources(
143 IN PISAPNP_PDO_EXTENSION PdoExt
,
145 IN PIO_STACK_LOCATION IrpSp
)
148 PCM_RESOURCE_LIST ResourceList
;
150 if (!PdoExt
->ResourceList
)
151 return Irp
->IoStatus
.Status
;
153 ListSize
= PdoExt
->ResourceListSize
;
154 ResourceList
= ExAllocatePool(PagedPool
, ListSize
);
156 return STATUS_NO_MEMORY
;
158 RtlCopyMemory(ResourceList
, PdoExt
->ResourceList
, ListSize
);
159 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
160 return STATUS_SUCCESS
;
165 IsaPdoQueryResourceRequirements(
166 IN PISAPNP_PDO_EXTENSION PdoExt
,
168 IN PIO_STACK_LOCATION IrpSp
)
171 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
173 if (!PdoExt
->RequirementsList
)
174 return Irp
->IoStatus
.Status
;
176 ListSize
= PdoExt
->RequirementsList
->ListSize
;
177 RequirementsList
= ExAllocatePool(PagedPool
, ListSize
);
178 if (!RequirementsList
)
179 return STATUS_NO_MEMORY
;
181 RtlCopyMemory(RequirementsList
, PdoExt
->RequirementsList
, ListSize
);
182 Irp
->IoStatus
.Information
= (ULONG_PTR
)RequirementsList
;
183 return STATUS_SUCCESS
;
190 IN PISAPNP_FDO_EXTENSION FdoExt
,
191 IN PIO_STACK_LOCATION IrpSp
)
193 PCM_RESOURCE_LIST ResourceList
= IrpSp
->Parameters
.StartDevice
.AllocatedResources
;
194 NTSTATUS Status
= STATUS_INSUFFICIENT_RESOURCES
;
198 if (!ResourceList
|| ResourceList
->Count
!= 1)
200 DPRINT1("No resource list (%p) or bad count (%d)\n", ResourceList
, ResourceList
? ResourceList
->Count
: 0);
201 return STATUS_INSUFFICIENT_RESOURCES
;
203 if (ResourceList
->List
[0].PartialResourceList
.Version
!= 1
204 || ResourceList
->List
[0].PartialResourceList
.Revision
!= 1)
206 DPRINT1("Bad resource list version (%d.%d)\n", ResourceList
->List
[0].PartialResourceList
.Version
, ResourceList
->List
[0].PartialResourceList
.Revision
);
207 return STATUS_REVISION_MISMATCH
;
209 for (i
= 0; i
< ResourceList
->List
[0].PartialResourceList
.Count
; i
++)
211 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
= &ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
212 if (PartialDescriptor
->Type
== CmResourceTypePort
&& PartialDescriptor
->u
.Port
.Length
> 1 && !FdoExt
->ReadDataPort
)
214 PUCHAR ReadDataPort
= ULongToPtr(PartialDescriptor
->u
.Port
.Start
.u
.LowPart
+ 3);
215 if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort
)))
217 /* we detected some ISAPNP cards */
218 FdoExt
->ReadDataPort
= ReadDataPort
;
219 KeAcquireSpinLock(&FdoExt
->Lock
, &OldIrql
);
220 Status
= IsaHwFillDeviceList(FdoExt
);
221 KeReleaseSpinLock(&FdoExt
->Lock
, OldIrql
);
222 if (FdoExt
->DeviceCount
> 0)
224 IoInvalidateDeviceRelations(FdoExt
->Pdo
, BusRelations
);
225 IoInvalidateDeviceRelations(FdoExt
->DataPortPdo
, RemovalRelations
);
230 /* mark read data port as started, even if no card has been detected */
231 Status
= STATUS_SUCCESS
;
241 IsaPdoOnRepeaterComplete(
242 IN PDEVICE_OBJECT Tdo
,
246 PIO_STACK_LOCATION SubStack
= IoGetCurrentIrpStackLocation(SubIrp
);
247 PIRP Irp
= (PIRP
)SubStack
->Parameters
.Others
.Argument1
;
248 ObDereferenceObject(Tdo
);
250 if (SubIrp
->IoStatus
.Status
== STATUS_NOT_SUPPORTED
)
254 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
259 Irp
->IoStatus
= SubIrp
->IoStatus
;
263 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
264 return STATUS_MORE_PROCESSING_REQUIRED
;
270 IN PISAPNP_PDO_EXTENSION PdoExt
,
272 IN BOOLEAN NeedsVote
)
274 PDEVICE_OBJECT Fdo
= PdoExt
->FdoExt
->Common
.Self
;
275 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
277 PDEVICE_OBJECT Tdo
= IoGetAttachedDeviceReference(Fdo
);
278 PIRP SubIrp
= IoAllocateIrp(Tdo
->StackSize
+ 1, FALSE
);
279 PIO_STACK_LOCATION SubStack
= IoGetNextIrpStackLocation(SubIrp
);
281 SubStack
->DeviceObject
= Tdo
;
282 SubStack
->Parameters
.Others
.Argument1
= (PVOID
)Irp
;
284 IoSetNextIrpStackLocation(SubIrp
);
285 SubStack
= IoGetNextIrpStackLocation(SubIrp
);
286 RtlCopyMemory(SubStack
, Stack
, FIELD_OFFSET(IO_STACK_LOCATION
, CompletionRoutine
));
287 SubStack
->Control
= 0;
288 IoSetCompletionRoutine(SubIrp
, IsaPdoOnRepeaterComplete
, (PVOID
)(ULONG_PTR
)NeedsVote
, TRUE
, TRUE
, TRUE
);
290 SubIrp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
291 IoMarkIrpPending(Irp
);
292 IoCallDriver(Tdo
, SubIrp
);
293 return STATUS_PENDING
;
299 IN PISAPNP_PDO_EXTENSION PdoExt
,
301 IN PIO_STACK_LOCATION IrpSp
)
303 NTSTATUS Status
= Irp
->IoStatus
.Status
;
305 switch (IrpSp
->MinorFunction
)
307 case IRP_MN_START_DEVICE
:
308 if (PdoExt
->IsaPnpDevice
)
309 Status
= IsaHwActivateDevice(PdoExt
->IsaPnpDevice
);
311 Status
= IsaPdoStartReadPort(PdoExt
->FdoExt
, IrpSp
);
313 if (NT_SUCCESS(Status
))
314 PdoExt
->Common
.State
= dsStarted
;
317 case IRP_MN_STOP_DEVICE
:
318 if (PdoExt
->IsaPnpDevice
)
319 Status
= IsaHwDeactivateDevice(PdoExt
->IsaPnpDevice
);
321 Status
= STATUS_SUCCESS
;
323 if (NT_SUCCESS(Status
))
324 PdoExt
->Common
.State
= dsStopped
;
327 case IRP_MN_QUERY_DEVICE_RELATIONS
:
328 Status
= IsaPdoQueryDeviceRelations(PdoExt
, Irp
, IrpSp
);
331 case IRP_MN_QUERY_CAPABILITIES
:
332 Status
= IsaPdoQueryCapabilities(PdoExt
, Irp
, IrpSp
);
335 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
336 if (PdoExt
->Common
.Self
== PdoExt
->FdoExt
->DataPortPdo
)
337 Status
= IsaPdoQueryPnpDeviceState(PdoExt
, Irp
, IrpSp
);
340 case IRP_MN_QUERY_RESOURCES
:
341 Status
= IsaPdoQueryResources(PdoExt
, Irp
, IrpSp
);
344 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
345 Status
= IsaPdoQueryResourceRequirements(PdoExt
, Irp
, IrpSp
);
348 case IRP_MN_QUERY_ID
:
349 Status
= IsaPdoQueryId(PdoExt
, Irp
, IrpSp
);
352 case IRP_MN_QUERY_REMOVE_DEVICE
:
353 case IRP_MN_REMOVE_DEVICE
:
354 case IRP_MN_CANCEL_REMOVE_DEVICE
:
355 case IRP_MN_QUERY_STOP_DEVICE
:
356 case IRP_MN_CANCEL_STOP_DEVICE
:
357 case IRP_MN_QUERY_DEVICE_TEXT
:
358 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
359 case IRP_MN_SURPRISE_REMOVAL
:
360 Status
= STATUS_SUCCESS
;
363 case IRP_MN_READ_CONFIG
:
364 case IRP_MN_WRITE_CONFIG
:
366 case IRP_MN_SET_LOCK
:
367 case IRP_MN_QUERY_BUS_INFORMATION
:
368 case IRP_MN_DEVICE_USAGE_NOTIFICATION
:
369 return IsaPdoRepeatRequest(PdoExt
, Irp
, TRUE
);
372 DPRINT1("Unknown PnP code: %x\n", IrpSp
->MinorFunction
);
376 Irp
->IoStatus
.Status
= Status
;
377 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);