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)
16 IN PDEVICE_OBJECT DeviceObject
,
18 OUT ULONG_PTR
* Information
)
20 PPDO_DEVICE_EXTENSION DeviceExtension
;
21 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
25 UNICODE_STRING SourceString
;
26 UNICODE_STRING String
;
29 IdType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryId
.IdType
;
30 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
31 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceExtension
->ControllerFdo
->DeviceExtension
;
35 case BusQueryDeviceID
:
37 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
38 RtlInitUnicodeString(&SourceString
, L
"PCIIDE\\IDEChannel");
41 case BusQueryHardwareIDs
:
43 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
45 switch (FdoDeviceExtension
->VendorId
)
48 Index
+= swprintf(&Buffer
[Index
], L
"Compaq-%04x", FdoDeviceExtension
->DeviceId
) + 1;
51 Index
+= swprintf(&Buffer
[Index
], L
"SiS-%04x", FdoDeviceExtension
->DeviceId
) + 1;
54 Index
+= swprintf(&Buffer
[Index
], L
"WinBond-%04x", FdoDeviceExtension
->DeviceId
) + 1;
57 Index
+= swprintf(&Buffer
[Index
], L
"CMD-%04x", FdoDeviceExtension
->DeviceId
) + 1;
61 switch (FdoDeviceExtension
->DeviceId
)
64 Index
+= swprintf(&Buffer
[Index
], L
"Intel-PIIX") + 1;
67 Index
+= swprintf(&Buffer
[Index
], L
"Intel-PIIX3") + 1;
70 Index
+= swprintf(&Buffer
[Index
], L
"Intel-PIIX4") + 1;
73 Index
+= swprintf(&Buffer
[Index
], L
"Intel-%04x", FdoDeviceExtension
->DeviceId
) + 1;
81 if (DeviceExtension
->Channel
== 0)
82 Index
+= swprintf(&Buffer
[Index
], L
"Primary_IDE_Channel") + 1;
84 Index
+= swprintf(&Buffer
[Index
], L
"Secondary_IDE_Channel") + 1;
85 Index
+= swprintf(&Buffer
[Index
], L
"*PNP0600") + 1;
86 Buffer
[Index
] = UNICODE_NULL
;
87 SourceString
.Length
= SourceString
.MaximumLength
= Index
* sizeof(WCHAR
);
88 SourceString
.Buffer
= Buffer
;
91 case BusQueryCompatibleIDs
:
93 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
95 Index
+= swprintf(&Buffer
[Index
], L
"*PNP0600") + 1;
96 Buffer
[Index
] = UNICODE_NULL
;
97 SourceString
.Length
= SourceString
.MaximumLength
= Index
* sizeof(WCHAR
);
98 SourceString
.Buffer
= Buffer
;
101 case BusQueryInstanceID
:
103 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
104 swprintf(Buffer
, L
"%lu", DeviceExtension
->Channel
);
105 RtlInitUnicodeString(&SourceString
, Buffer
);
109 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
111 return STATUS_NOT_SUPPORTED
;
114 Status
= DuplicateUnicodeString(
115 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
118 *Information
= (ULONG_PTR
)String
.Buffer
;
124 IN PDEVICE_OBJECT DeviceObject
,
125 OUT PULONG CommandPortBase
,
126 OUT PULONG ControlPortBase
,
127 OUT PULONG BusMasterPortBase
,
128 OUT PULONG InterruptVector
)
130 PPDO_DEVICE_EXTENSION DeviceExtension
;
131 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
134 PCI_COMMON_CONFIG PciConfig
;
135 NTSTATUS ret
= STATUS_UNSUCCESSFUL
;
137 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
138 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceExtension
->ControllerFdo
->DeviceExtension
;
139 BaseIndex
= DeviceExtension
->Channel
* 2;
141 BytesRead
= (*FdoDeviceExtension
->BusInterface
->GetBusData
)(
142 FdoDeviceExtension
->BusInterface
->Context
,
143 PCI_WHICHSPACE_CONFIG
,
146 PCI_COMMON_HDR_LENGTH
);
147 if (BytesRead
!= PCI_COMMON_HDR_LENGTH
)
148 return STATUS_IO_DEVICE_ERROR
;
150 /* We have found a known native pci ide controller */
151 if ((PciConfig
.ProgIf
& 0x80) && (PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_SPACE
))
153 DPRINT("Found IDE Bus Master controller!\n");
154 *BusMasterPortBase
= PciConfig
.u
.type0
.BaseAddresses
[4] & PCI_ADDRESS_IO_ADDRESS_MASK
;
155 DPRINT(" IDE Bus Master Registers at IO %lx\n", *BusMasterPortBase
);
159 *BusMasterPortBase
= 0;
162 if ((PciConfig
.ProgIf
>> BaseIndex
) & 0x1)
165 if ((PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 0] & PCI_ADDRESS_IO_SPACE
) &&
166 (PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 1] & PCI_ADDRESS_IO_SPACE
))
168 /* Channel is enabled */
169 *CommandPortBase
= PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 0] & PCI_ADDRESS_IO_ADDRESS_MASK
;
170 *ControlPortBase
= PciConfig
.u
.type0
.BaseAddresses
[BaseIndex
+ 1] & PCI_ADDRESS_IO_ADDRESS_MASK
;
171 *InterruptVector
= PciConfig
.u
.type0
.InterruptLine
;
172 ret
= STATUS_SUCCESS
;
177 /* Compatibility mode */
178 switch (DeviceExtension
->Channel
)
181 if (IoGetConfigurationInformation()->AtDiskPrimaryAddressClaimed
)
182 ret
= STATUS_INSUFFICIENT_RESOURCES
;
185 *CommandPortBase
= 0x1F0;
186 *ControlPortBase
= 0x3F6;
187 *InterruptVector
= 14;
188 ret
= STATUS_SUCCESS
;
192 if (IoGetConfigurationInformation()->AtDiskSecondaryAddressClaimed
)
193 ret
= STATUS_INSUFFICIENT_RESOURCES
;
196 *CommandPortBase
= 0x170;
197 *ControlPortBase
= 0x376;
198 *InterruptVector
= 15;
199 ret
= STATUS_SUCCESS
;
209 PciIdeXPdoQueryResourceRequirements(
210 IN PDEVICE_OBJECT DeviceObject
,
212 OUT ULONG_PTR
* Information
)
214 ULONG CommandPortBase
;
215 ULONG ControlPortBase
;
216 ULONG BusMasterPortBase
;
217 ULONG InterruptVector
;
219 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
;
220 PIO_RESOURCE_DESCRIPTOR Descriptor
;
223 Status
= GetCurrentResources(DeviceObject
, &CommandPortBase
,
224 &ControlPortBase
, &BusMasterPortBase
, &InterruptVector
);
225 if (!NT_SUCCESS(Status
))
228 DPRINT("IDE Channel %lu: IO %x and %x, BM %lx, Irq %lu\n",
229 ((PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->Channel
,
230 CommandPortBase
, ControlPortBase
,
231 BusMasterPortBase
, InterruptVector
);
233 /* FIXME: what to do with BusMasterPortBase? */
235 ListSize
= sizeof(IO_RESOURCE_REQUIREMENTS_LIST
)
236 + 2 * sizeof(IO_RESOURCE_DESCRIPTOR
);
237 RequirementsList
= ExAllocatePool(PagedPool
, ListSize
);
238 if (!RequirementsList
)
239 return STATUS_INSUFFICIENT_RESOURCES
;
241 RtlZeroMemory(RequirementsList
, ListSize
);
242 RequirementsList
->ListSize
= ListSize
;
243 RequirementsList
->AlternativeLists
= 1;
245 RequirementsList
->List
[0].Version
= 1;
246 RequirementsList
->List
[0].Revision
= 1;
247 RequirementsList
->List
[0].Count
= 3;
249 Descriptor
= &RequirementsList
->List
[0].Descriptors
[0];
251 /* Command port base */
252 Descriptor
->Option
= 0; /* Required */
253 Descriptor
->Type
= CmResourceTypePort
;
254 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
255 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
|
256 CM_RESOURCE_PORT_16_BIT_DECODE
|
257 CM_RESOURCE_PORT_POSITIVE_DECODE
;
258 Descriptor
->u
.Port
.Length
= 7;
259 Descriptor
->u
.Port
.Alignment
= 1;
260 Descriptor
->u
.Port
.MinimumAddress
.QuadPart
= (ULONGLONG
)CommandPortBase
;
261 Descriptor
->u
.Port
.MaximumAddress
.QuadPart
= (ULONGLONG
)(CommandPortBase
+ 7 - 1);
264 /* Control port base */
265 Descriptor
->Option
= 0; /* Required */
266 Descriptor
->Type
= CmResourceTypePort
;
267 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
268 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
|
269 CM_RESOURCE_PORT_16_BIT_DECODE
|
270 CM_RESOURCE_PORT_POSITIVE_DECODE
;
271 Descriptor
->u
.Port
.Length
= 1;
272 Descriptor
->u
.Port
.Alignment
= 1;
273 Descriptor
->u
.Port
.MinimumAddress
.QuadPart
= (ULONGLONG
)ControlPortBase
;
274 Descriptor
->u
.Port
.MaximumAddress
.QuadPart
= (ULONGLONG
)(ControlPortBase
+ 1 - 1);
278 Descriptor
->Option
= 0; /* Required */
279 Descriptor
->Type
= CmResourceTypeInterrupt
;
280 Descriptor
->ShareDisposition
= CmResourceShareShared
;
281 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
;
282 Descriptor
->u
.Interrupt
.MinimumVector
= InterruptVector
;
283 Descriptor
->u
.Interrupt
.MaximumVector
= InterruptVector
;
285 *Information
= (ULONG_PTR
)RequirementsList
;
286 return STATUS_SUCCESS
;
290 PciIdeXPdoQueryDeviceText(
291 IN PDEVICE_OBJECT DeviceObject
,
293 OUT ULONG_PTR
* Information
)
295 PPDO_DEVICE_EXTENSION DeviceExtension
;
296 ULONG DeviceTextType
;
298 UNICODE_STRING String
;
300 DeviceTextType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryDeviceText
.DeviceTextType
;
301 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
303 switch (DeviceTextType
)
305 case DeviceTextDescription
:
306 case DeviceTextLocationInformation
:
308 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / %S\n",
309 DeviceTextType
== DeviceTextDescription
? L
"DeviceTextDescription" : L
"DeviceTextLocationInformation");
310 if (DeviceExtension
->Channel
== 0)
311 SourceString
= L
"Primary channel";
313 SourceString
= L
"Secondary channel";
317 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n", DeviceTextType
);
319 return STATUS_NOT_SUPPORTED
;
322 if (RtlCreateUnicodeString(&String
, SourceString
))
324 *Information
= (ULONG_PTR
)String
.Buffer
;
325 return STATUS_SUCCESS
;
328 return STATUS_INSUFFICIENT_RESOURCES
;
332 PciIdeXPdoQueryDeviceRelations(
333 IN PDEVICE_OBJECT DeviceObject
,
334 OUT PDEVICE_RELATIONS
* pDeviceRelations
)
336 PFDO_DEVICE_EXTENSION DeviceExtension
;
337 PDEVICE_RELATIONS DeviceRelations
;
339 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
340 ASSERT(DeviceExtension
->Common
.IsFDO
);
342 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(
344 sizeof(DEVICE_RELATIONS
));
345 if (!DeviceRelations
)
346 return STATUS_INSUFFICIENT_RESOURCES
;
348 ObReferenceObject(DeviceObject
);
349 DeviceRelations
->Count
= 1;
350 DeviceRelations
->Objects
[0] = DeviceObject
;
352 *pDeviceRelations
= DeviceRelations
;
353 return STATUS_SUCCESS
;
357 PciIdeXPdoPnpDispatch(
358 IN PDEVICE_OBJECT DeviceObject
,
362 PIO_STACK_LOCATION Stack
;
363 ULONG_PTR Information
= Irp
->IoStatus
.Information
;
366 Stack
= IoGetCurrentIrpStackLocation(Irp
);
367 MinorFunction
= Stack
->MinorFunction
;
369 switch (MinorFunction
)
372 * Those are required:
373 * IRP_MN_START_DEVICE (done)
374 * IRP_MN_QUERY_STOP_DEVICE
376 * IRP_MN_CANCEL_STOP_DEVICE
377 * IRP_MN_QUERY_REMOVE_DEVICE
378 * IRP_MN_REMOVE_DEVICE
379 * IRP_MN_CANCEL_REMOVE_DEVICE
380 * IRP_MN_SURPRISE_REMOVAL
381 * IRP_MN_QUERY_CAPABILITIES (done)
382 * IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelations (done)
383 * IRP_MN_QUERY_ID / BusQueryDeviceID (done)
384 * Those may be required/optional:
385 * IRP_MN_DEVICE_USAGE_NOTIFICATION
386 * IRP_MN_QUERY_RESOURCES
387 * IRP_MN_QUERY_RESOURCE_REQUIREMENTS (done)
388 * IRP_MN_QUERY_DEVICE_TEXT
389 * IRP_MN_QUERY_BUS_INFORMATION
390 * IRP_MN_QUERY_INTERFACE
392 * IRP_MN_WRITE_CONFIG
395 * Those are optional:
396 * IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations
397 * IRP_MN_QUERY_ID / BusQueryHardwareIDs (done)
398 * IRP_MN_QUERY_ID / BusQueryCompatibleIDs (done)
399 * IRP_MN_QUERY_ID / BusQueryInstanceID (done)
401 case IRP_MN_START_DEVICE
: /* 0x00 */
403 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
404 Status
= STATUS_SUCCESS
;
407 case IRP_MN_QUERY_REMOVE_DEVICE
: /* 0x01 */
409 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
410 Status
= STATUS_UNSUCCESSFUL
;
413 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
415 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
417 case TargetDeviceRelation
:
419 PDEVICE_RELATIONS DeviceRelations
= NULL
;
420 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
421 Status
= PciIdeXPdoQueryDeviceRelations(DeviceObject
, &DeviceRelations
);
422 Information
= (ULONG_PTR
)DeviceRelations
;
427 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
428 Stack
->Parameters
.QueryDeviceRelations
.Type
);
430 Status
= STATUS_NOT_SUPPORTED
;
436 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
438 PDEVICE_CAPABILITIES DeviceCapabilities
;
440 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
442 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)Stack
->Parameters
.DeviceCapabilities
.Capabilities
;
443 /* FIXME: capabilities can change with connected device */
444 DeviceCapabilities
->LockSupported
= FALSE
;
445 DeviceCapabilities
->EjectSupported
= FALSE
;
446 DeviceCapabilities
->Removable
= TRUE
;
447 DeviceCapabilities
->DockDevice
= FALSE
;
448 DeviceCapabilities
->UniqueID
= FALSE
;
449 DeviceCapabilities
->SilentInstall
= FALSE
;
450 DeviceCapabilities
->RawDeviceOK
= FALSE
;
451 DeviceCapabilities
->SurpriseRemovalOK
= TRUE
;
452 DeviceCapabilities
->HardwareDisabled
= FALSE
; /* FIXME */
453 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
454 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
; /* FIXME */
455 for (i
= 0; i
< PowerSystemMaximum
; i
++)
456 DeviceCapabilities
->DeviceState
[i
] = PowerDeviceD3
; /* FIXME */
457 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
458 DeviceCapabilities
->D1Latency
= 0; /* FIXME */
459 DeviceCapabilities
->D2Latency
= 0; /* FIXME */
460 DeviceCapabilities
->D3Latency
= 0; /* FIXME */
461 Status
= STATUS_SUCCESS
;
464 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
466 /* This IRP is optional; do nothing */
467 Information
= Irp
->IoStatus
.Information
;
468 Status
= Irp
->IoStatus
.Status
;
471 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
473 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
474 Status
= PciIdeXPdoQueryResourceRequirements(DeviceObject
, Irp
, &Information
);
477 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
479 Status
= PciIdeXPdoQueryDeviceText(DeviceObject
, Irp
, &Information
);
482 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
484 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
485 Information
= Irp
->IoStatus
.Information
;
486 Status
= Irp
->IoStatus
.Status
;
489 case IRP_MN_QUERY_ID
: /* 0x13 */
491 Status
= PciIdeXPdoQueryId(DeviceObject
, Irp
, &Information
);
494 case IRP_MN_QUERY_PNP_DEVICE_STATE
: /* 0x14 */
496 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
497 Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
498 Status
= STATUS_SUCCESS
;
501 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
503 PPNP_BUS_INFORMATION BusInfo
;
504 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
506 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
508 Status
= STATUS_INSUFFICIENT_RESOURCES
;
512 &BusInfo->BusTypeGuid,
513 &GUID_DEVINTERFACE_XXX,
515 BusInfo
->LegacyBusType
= PNPBus
;
516 BusInfo
->BusNumber
= 0; /* FIXME */
517 Information
= (ULONG_PTR
)BusInfo
;
518 Status
= STATUS_SUCCESS
;
524 /* We can't forward request to the lower driver, because
525 * we are a Pdo, so we don't have lower driver... */
526 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction
);
528 Information
= Irp
->IoStatus
.Information
;
529 Status
= Irp
->IoStatus
.Status
;
533 Irp
->IoStatus
.Information
= Information
;
534 Irp
->IoStatus
.Status
= Status
;
535 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);