2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: PCI IDE bus driver extension
4 * FILE: drivers/storage/pciidex/pdo.c
5 * PURPOSE: IRP_MJ_PNP operations for PDOs
6 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
18 IN PDEVICE_OBJECT DeviceObject
,
20 OUT ULONG_PTR
* Information
)
22 PPDO_DEVICE_EXTENSION DeviceExtension
;
23 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
27 UNICODE_STRING SourceString
;
28 UNICODE_STRING String
;
31 IdType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryId
.IdType
;
32 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
33 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceExtension
->ControllerFdo
->DeviceExtension
;
37 case BusQueryDeviceID
:
39 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
40 RtlInitUnicodeString(&SourceString
, L
"PCIIDE\\IDEChannel");
43 case BusQueryHardwareIDs
:
45 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
47 switch (FdoDeviceExtension
->VendorId
)
50 Index
+= swprintf(&Buffer
[Index
], L
"Compaq-%04x", FdoDeviceExtension
->DeviceId
) + 1;
53 Index
+= swprintf(&Buffer
[Index
], L
"SiS-%04x", FdoDeviceExtension
->DeviceId
) + 1;
56 Index
+= swprintf(&Buffer
[Index
], L
"WinBond-%04x", FdoDeviceExtension
->DeviceId
) + 1;
59 Index
+= swprintf(&Buffer
[Index
], L
"CMD-%04x", FdoDeviceExtension
->DeviceId
) + 1;
63 switch (FdoDeviceExtension
->DeviceId
)
66 Index
+= swprintf(&Buffer
[Index
], L
"Intel-PIIX") + 1;
69 Index
+= swprintf(&Buffer
[Index
], L
"Intel-PIIX3") + 1;
72 Index
+= swprintf(&Buffer
[Index
], L
"Intel-PIIX4") + 1;
75 Index
+= swprintf(&Buffer
[Index
], L
"Intel-%04x", FdoDeviceExtension
->DeviceId
) + 1;
83 if (DeviceExtension
->Channel
== 0)
84 Index
+= swprintf(&Buffer
[Index
], L
"Primary_IDE_Channel") + 1;
86 Index
+= swprintf(&Buffer
[Index
], L
"Secondary_IDE_Channel") + 1;
87 Index
+= swprintf(&Buffer
[Index
], L
"*PNP0600") + 1;
88 Buffer
[Index
] = UNICODE_NULL
;
89 SourceString
.Length
= SourceString
.MaximumLength
= Index
* sizeof(WCHAR
);
90 SourceString
.Buffer
= Buffer
;
93 case BusQueryCompatibleIDs
:
95 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
97 Index
+= swprintf(&Buffer
[Index
], L
"*PNP0600") + 1;
98 Buffer
[Index
] = UNICODE_NULL
;
99 SourceString
.Length
= SourceString
.MaximumLength
= Index
* sizeof(WCHAR
);
100 SourceString
.Buffer
= Buffer
;
103 case BusQueryInstanceID
:
105 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
106 swprintf(Buffer
, L
"%lu", DeviceExtension
->Channel
);
107 RtlInitUnicodeString(&SourceString
, Buffer
);
111 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
113 return STATUS_NOT_SUPPORTED
;
116 Status
= DuplicateUnicodeString(
117 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
120 *Information
= (ULONG_PTR
)String
.Buffer
;
126 IN PDEVICE_OBJECT DeviceObject
,
127 OUT PULONG CommandPortBase
,
128 OUT PULONG ControlPortBase
,
129 OUT PULONG BusMasterPortBase
,
130 OUT PULONG InterruptVector
)
132 PPDO_DEVICE_EXTENSION DeviceExtension
;
133 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
136 PCI_COMMON_CONFIG PciConfig
;
137 NTSTATUS ret
= STATUS_UNSUCCESSFUL
;
139 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
140 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceExtension
->ControllerFdo
->DeviceExtension
;
141 BaseIndex
= DeviceExtension
->Channel
* 2;
143 BytesRead
= (*FdoDeviceExtension
->BusInterface
->GetBusData
)(
144 FdoDeviceExtension
->BusInterface
->Context
,
145 PCI_WHICHSPACE_CONFIG
,
148 PCI_COMMON_HDR_LENGTH
);
149 if (BytesRead
!= PCI_COMMON_HDR_LENGTH
)
150 return STATUS_IO_DEVICE_ERROR
;
152 /* We have found a known native pci ide controller */
153 if ((PciConfig
.ProgIf
& 0x80) && (PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_SPACE
))
155 DPRINT("Found IDE Bus Master controller!\n");
156 *BusMasterPortBase
= PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_ADDRESS_MASK
;
157 DPRINT(" IDE Bus Master Registers at IO %lx\n", *BusMasterPortBase
);
161 *BusMasterPortBase
= 0;
164 if ((PciConfig
.ProgIf
>> BaseIndex
) & 0x1)
167 if ((PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 0] & PCI_ADDRESS_IO_SPACE
) &&
168 (PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 1] & PCI_ADDRESS_IO_SPACE
))
170 /* Channel is enabled */
171 *CommandPortBase
= PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 0] & PCI_ADDRESS_IO_ADDRESS_MASK
;
172 *ControlPortBase
= PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 1] & PCI_ADDRESS_IO_ADDRESS_MASK
;
173 *InterruptVector
= PciConfig
.u
.type0
.InterruptLine
;
174 ret
= STATUS_SUCCESS
;
179 /* Compatibility mode */
180 switch (DeviceExtension
->Channel
)
183 if (IoGetConfigurationInformation()->AtDiskPrimaryAddressClaimed
)
184 ret
= STATUS_INSUFFICIENT_RESOURCES
;
187 *CommandPortBase
= 0x1F0;
188 *ControlPortBase
= 0x3F6;
189 *InterruptVector
= 14;
190 ret
= STATUS_SUCCESS
;
194 if (IoGetConfigurationInformation()->AtDiskSecondaryAddressClaimed
)
195 ret
= STATUS_INSUFFICIENT_RESOURCES
;
198 *CommandPortBase
= 0x170;
199 *ControlPortBase
= 0x376;
200 *InterruptVector
= 15;
201 ret
= STATUS_SUCCESS
;
211 PciIdeXPdoQueryResourceRequirements(
212 IN PDEVICE_OBJECT DeviceObject
,
214 OUT ULONG_PTR
* Information
)
216 ULONG CommandPortBase
;
217 ULONG ControlPortBase
;
218 ULONG BusMasterPortBase
;
219 ULONG InterruptVector
;
221 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
222 PIO_RESOURCE_DESCRIPTOR Descriptor
;
225 Status
= GetCurrentResources(DeviceObject
, &CommandPortBase
,
226 &ControlPortBase
, &BusMasterPortBase
, &InterruptVector
);
227 if (!NT_SUCCESS(Status
))
230 DPRINT("IDE Channel %lu: IO %x and %x, BM %lx, Irq %lu\n",
231 ((PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->Channel
,
232 CommandPortBase
, ControlPortBase
,
233 BusMasterPortBase
, InterruptVector
);
235 /* FIXME: what to do with BusMasterPortBase? */
237 ListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
)
238 + 2 * sizeof(IO_RESOURCE_DESCRIPTOR
);
239 RequirementsList
= ExAllocatePool(PagedPool
, ListSize
);
240 if (!RequirementsList
)
241 return STATUS_INSUFFICIENT_RESOURCES
;
243 RtlZeroMemory(RequirementsList
, ListSize
);
244 RequirementsList
->ListSize
= ListSize
;
245 RequirementsList
->AlternativeLists
= 1;
247 RequirementsList
->List
[0].Version
= 1;
248 RequirementsList
->List
[0].Revision
= 1;
249 RequirementsList
->List
[0].Count
= 3;
251 Descriptor
= &RequirementsList
->List
[0].Descriptors
[0];
253 /* Command port base */
254 Descriptor
->Option
= 0; /* Required */
255 Descriptor
->Type
= CmResourceTypePort
;
256 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
257 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
|
258 CM_RESOURCE_PORT_16_BIT_DECODE
|
259 CM_RESOURCE_PORT_POSITIVE_DECODE
;
260 Descriptor
->u
.Port
.Length
= 7;
261 Descriptor
->u
.Port
.Alignment
= 1;
262 Descriptor
->u
.Port
.MinimumAddress
.QuadPart
= (ULONGLONG
)CommandPortBase
;
263 Descriptor
->u
.Port
.MaximumAddress
.QuadPart
= (ULONGLONG
)(CommandPortBase
+ 7 - 1);
266 /* Control port base */
267 Descriptor
->Option
= 0; /* Required */
268 Descriptor
->Type
= CmResourceTypePort
;
269 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
270 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
|
271 CM_RESOURCE_PORT_16_BIT_DECODE
|
272 CM_RESOURCE_PORT_POSITIVE_DECODE
;
273 Descriptor
->u
.Port
.Length
= 1;
274 Descriptor
->u
.Port
.Alignment
= 1;
275 Descriptor
->u
.Port
.MinimumAddress
.QuadPart
= (ULONGLONG
)ControlPortBase
;
276 Descriptor
->u
.Port
.MaximumAddress
.QuadPart
= (ULONGLONG
)(ControlPortBase
+ 1 - 1);
280 Descriptor
->Option
= 0; /* Required */
281 Descriptor
->Type
= CmResourceTypeInterrupt
;
282 Descriptor
->ShareDisposition
= CmResourceShareShared
;
283 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
;
284 Descriptor
->u
.Interrupt
.MinimumVector
= InterruptVector
;
285 Descriptor
->u
.Interrupt
.MaximumVector
= InterruptVector
;
287 *Information
= (ULONG_PTR
)RequirementsList
;
288 return STATUS_SUCCESS
;
292 PciIdeXPdoQueryDeviceText(
293 IN PDEVICE_OBJECT DeviceObject
,
295 OUT ULONG_PTR
* Information
)
297 PPDO_DEVICE_EXTENSION DeviceExtension
;
298 ULONG DeviceTextType
;
300 UNICODE_STRING String
;
302 DeviceTextType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryDeviceText
.DeviceTextType
;
303 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
305 switch (DeviceTextType
)
307 case DeviceTextDescription
:
308 case DeviceTextLocationInformation
:
310 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / %S\n",
311 DeviceTextType
== DeviceTextDescription
? L
"DeviceTextDescription" : L
"DeviceTextLocationInformation");
312 if (DeviceExtension
->Channel
== 0)
313 SourceString
= L
"Primary channel";
315 SourceString
= L
"Secondary channel";
319 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n", DeviceTextType
);
321 return STATUS_NOT_SUPPORTED
;
324 if (RtlCreateUnicodeString(&String
, SourceString
))
326 *Information
= (ULONG_PTR
)String
.Buffer
;
327 return STATUS_SUCCESS
;
330 return STATUS_INSUFFICIENT_RESOURCES
;
334 PciIdeXPdoQueryDeviceRelations(
335 IN PDEVICE_OBJECT DeviceObject
,
336 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
338 PFDO_DEVICE_EXTENSION DeviceExtension
;
339 PDEVICE_RELATIONS DeviceRelations
;
341 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
342 ASSERT(DeviceExtension
->Common
.IsFDO
);
344 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(
346 sizeof(DEVICE_RELATIONS
));
347 if (!DeviceRelations
)
348 return STATUS_INSUFFICIENT_RESOURCES
;
350 ObReferenceObject(DeviceObject
);
351 DeviceRelations
->Count
= 1;
352 DeviceRelations
->Objects
[0] = DeviceObject
;
354 *pDeviceRelations
= DeviceRelations
;
355 return STATUS_SUCCESS
;
359 PciIdeXPdoPnpDispatch(
360 IN PDEVICE_OBJECT DeviceObject
,
364 PIO_STACK_LOCATION Stack
;
365 ULONG_PTR Information
= Irp
->IoStatus
.Information
;
368 Stack
= IoGetCurrentIrpStackLocation(Irp
);
369 MinorFunction
= Stack
->MinorFunction
;
371 switch (MinorFunction
)
374 * Those are required:
375 * IRP_MN_START_DEVICE (done)
376 * IRP_MN_QUERY_STOP_DEVICE
378 * IRP_MN_CANCEL_STOP_DEVICE
379 * IRP_MN_QUERY_REMOVE_DEVICE
380 * IRP_MN_REMOVE_DEVICE
381 * IRP_MN_CANCEL_REMOVE_DEVICE
382 * IRP_MN_SURPRISE_REMOVAL
383 * IRP_MN_QUERY_CAPABILITIES (done)
384 * IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelations (done)
385 * IRP_MN_QUERY_ID / BusQueryDeviceID (done)
386 * Those may be required/optional:
387 * IRP_MN_DEVICE_USAGE_NOTIFICATION
388 * IRP_MN_QUERY_RESOURCES
389 * IRP_MN_QUERY_RESOURCE_REQUIREMENTS (done)
390 * IRP_MN_QUERY_DEVICE_TEXT
391 * IRP_MN_QUERY_BUS_INFORMATION
392 * IRP_MN_QUERY_INTERFACE
394 * IRP_MN_WRITE_CONFIG
397 * Those are optional:
398 * IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations
399 * IRP_MN_QUERY_ID / BusQueryHardwareIDs (done)
400 * IRP_MN_QUERY_ID / BusQueryCompatibleIDs (done)
401 * IRP_MN_QUERY_ID / BusQueryInstanceID (done)
403 case IRP_MN_START_DEVICE
: /* 0x00 */
405 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
406 Status
= STATUS_SUCCESS
;
409 case IRP_MN_QUERY_REMOVE_DEVICE
: /* 0x01 */
411 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
412 Status
= STATUS_UNSUCCESSFUL
;
415 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
417 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
419 case TargetDeviceRelation
:
421 PDEVICE_RELATIONS DeviceRelations
= NULL
;
422 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
423 Status
= PciIdeXPdoQueryDeviceRelations(DeviceObject
, &DeviceRelations
);
424 Information
= (ULONG_PTR
)DeviceRelations
;
429 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
430 Stack
->Parameters
.QueryDeviceRelations
.Type
);
432 Status
= STATUS_NOT_SUPPORTED
;
438 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
440 PDEVICE_CAPABILITIES DeviceCapabilities
;
442 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
444 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)Stack
->Parameters
.DeviceCapabilities
.Capabilities
;
445 /* FIXME: capabilities can change with connected device */
446 DeviceCapabilities
->LockSupported
= FALSE
;
447 DeviceCapabilities
->EjectSupported
= FALSE
;
448 DeviceCapabilities
->Removable
= TRUE
;
449 DeviceCapabilities
->DockDevice
= FALSE
;
450 DeviceCapabilities
->UniqueID
= FALSE
;
451 DeviceCapabilities
->SilentInstall
= FALSE
;
452 DeviceCapabilities
->RawDeviceOK
= FALSE
;
453 DeviceCapabilities
->SurpriseRemovalOK
= TRUE
;
454 DeviceCapabilities
->HardwareDisabled
= FALSE
; /* FIXME */
455 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
456 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
; /* FIXME */
457 for (i
= 0; i
< PowerSystemMaximum
; i
++)
458 DeviceCapabilities
->DeviceState
[i
] = PowerDeviceD3
; /* FIXME */
459 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
460 DeviceCapabilities
->D1Latency
= 0; /* FIXME */
461 DeviceCapabilities
->D2Latency
= 0; /* FIXME */
462 DeviceCapabilities
->D3Latency
= 0; /* FIXME */
463 Status
= STATUS_SUCCESS
;
466 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
468 /* This IRP is optional; do nothing */
469 Information
= Irp
->IoStatus
.Information
;
470 Status
= Irp
->IoStatus
.Status
;
473 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
475 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
476 Status
= PciIdeXPdoQueryResourceRequirements(DeviceObject
, Irp
, &Information
);
479 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
481 Status
= PciIdeXPdoQueryDeviceText(DeviceObject
, Irp
, &Information
);
484 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
486 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
487 Information
= Irp
->IoStatus
.Information
;
488 Status
= Irp
->IoStatus
.Status
;
491 case IRP_MN_QUERY_ID
: /* 0x13 */
493 Status
= PciIdeXPdoQueryId(DeviceObject
, Irp
, &Information
);
496 case IRP_MN_QUERY_PNP_DEVICE_STATE
: /* 0x14 */
498 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
499 Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
500 Status
= STATUS_SUCCESS
;
503 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
505 PPNP_BUS_INFORMATION BusInfo
;
506 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
508 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
510 Status
= STATUS_INSUFFICIENT_RESOURCES
;
514 &BusInfo->BusTypeGuid,
515 &GUID_DEVINTERFACE_XXX,
517 BusInfo
->LegacyBusType
= PNPBus
;
518 BusInfo
->BusNumber
= 0; /* FIXME */
519 Information
= (ULONG_PTR
)BusInfo
;
520 Status
= STATUS_SUCCESS
;
526 /* We can't forward request to the lower driver, because
527 * we are a Pdo, so we don't have lower driver... */
528 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction
);
530 Information
= Irp
->IoStatus
.Information
;
531 Status
= Irp
->IoStatus
.Status
;
535 Irp
->IoStatus
.Information
= Information
;
536 Irp
->IoStatus
.Status
= Status
;
537 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);