3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/bus/pcibus.c
5 * PURPOSE: PCI Bus Support (Configuration Space, Resource Allocation)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice
[2] = {{{{0}}}};
19 BOOLEAN HalpPCIConfigInitialized
;
20 ULONG HalpMinPciBus
, HalpMaxPciBus
;
21 KSPIN_LOCK HalpPCIConfigLock
;
22 PCI_CONFIG_HANDLER PCIConfigHandler
;
24 /* PCI Operation Matrix */
25 UCHAR PCIDeref
[4][4] =
27 {0, 1, 2, 2}, // ULONG-aligned offset
28 {1, 1, 1, 1}, // UCHAR-aligned offset
29 {2, 1, 2, 2}, // USHORT-aligned offset
30 {1, 1, 1, 1} // UCHAR-aligned offset
34 PCI_CONFIG_HANDLER PCIConfigHandlerType1
=
37 (FncSync
)HalpPCISynchronizeType1
,
38 (FncReleaseSync
)HalpPCIReleaseSynchronzationType1
,
42 (FncConfigIO
)HalpPCIReadUlongType1
,
43 (FncConfigIO
)HalpPCIReadUcharType1
,
44 (FncConfigIO
)HalpPCIReadUshortType1
49 (FncConfigIO
)HalpPCIWriteUlongType1
,
50 (FncConfigIO
)HalpPCIWriteUcharType1
,
51 (FncConfigIO
)HalpPCIWriteUshortType1
56 PCI_CONFIG_HANDLER PCIConfigHandlerType2
=
59 (FncSync
)HalpPCISynchronizeType2
,
60 (FncReleaseSync
)HalpPCIReleaseSynchronizationType2
,
64 (FncConfigIO
)HalpPCIReadUlongType2
,
65 (FncConfigIO
)HalpPCIReadUcharType2
,
66 (FncConfigIO
)HalpPCIReadUshortType2
71 (FncConfigIO
)HalpPCIWriteUlongType2
,
72 (FncConfigIO
)HalpPCIWriteUcharType2
,
73 (FncConfigIO
)HalpPCIWriteUshortType2
77 PCIPBUSDATA HalpFakePciBusData
=
93 BUS_HANDLER HalpFakePciBusHandler
=
105 (PGETSETBUSDATA
)HalpGetPCIData
,
106 (PGETSETBUSDATA
)HalpSetPCIData
,
108 HalpAssignPCISlotResources
,
113 /* TYPE 1 FUNCTIONS **********************************************************/
117 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler
,
118 IN PCI_SLOT_NUMBER Slot
,
120 IN PPCI_TYPE1_CFG_BITS PciCfg1
)
122 /* Setup the PCI Configuration Register */
123 PciCfg1
->u
.AsULONG
= 0;
124 PciCfg1
->u
.bits
.BusNumber
= BusHandler
->BusNumber
;
125 PciCfg1
->u
.bits
.DeviceNumber
= Slot
.u
.bits
.DeviceNumber
;
126 PciCfg1
->u
.bits
.FunctionNumber
= Slot
.u
.bits
.FunctionNumber
;
127 PciCfg1
->u
.bits
.Enable
= TRUE
;
129 /* Acquire the lock */
130 KeRaiseIrql(HIGH_LEVEL
, Irql
);
131 KiAcquireSpinLock(&HalpPCIConfigLock
);
136 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler
,
139 PCI_TYPE1_CFG_BITS PciCfg1
;
141 /* Clear the PCI Configuration Register */
142 PciCfg1
.u
.AsULONG
= 0;
143 WRITE_PORT_ULONG(((PPCIPBUSDATA
)BusHandler
->BusData
)->Config
.Type1
.Address
,
146 /* Release the lock */
147 KiReleaseSpinLock(&HalpPCIConfigLock
);
151 TYPE1_READ(HalpPCIReadUcharType1
, UCHAR
)
152 TYPE1_READ(HalpPCIReadUshortType1
, USHORT
)
153 TYPE1_READ(HalpPCIReadUlongType1
, ULONG
)
154 TYPE1_WRITE(HalpPCIWriteUcharType1
, UCHAR
)
155 TYPE1_WRITE(HalpPCIWriteUshortType1
, USHORT
)
156 TYPE1_WRITE(HalpPCIWriteUlongType1
, ULONG
)
158 /* TYPE 2 FUNCTIONS **********************************************************/
162 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler
,
163 IN PCI_SLOT_NUMBER Slot
,
165 IN PPCI_TYPE2_ADDRESS_BITS PciCfg
)
167 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
168 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
170 /* Setup the configuration register */
171 PciCfg
->u
.AsUSHORT
= 0;
172 PciCfg
->u
.bits
.Agent
= (USHORT
)Slot
.u
.bits
.DeviceNumber
;
173 PciCfg
->u
.bits
.AddressBase
= (USHORT
)BusData
->Config
.Type2
.Base
;
175 /* Acquire the lock */
176 KeRaiseIrql(HIGH_LEVEL
, Irql
);
177 KiAcquireSpinLock(&HalpPCIConfigLock
);
179 /* Setup the CSE Register */
180 PciCfg2Cse
.u
.AsUCHAR
= 0;
181 PciCfg2Cse
.u
.bits
.Enable
= TRUE
;
182 PciCfg2Cse
.u
.bits
.FunctionNumber
= (UCHAR
)Slot
.u
.bits
.FunctionNumber
;
183 PciCfg2Cse
.u
.bits
.Key
= -1;
185 /* Write the bus number and CSE */
186 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
,
187 (UCHAR
)BusHandler
->BusNumber
);
188 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
193 HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler
,
196 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
197 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
199 /* Clear CSE and bus number */
200 PciCfg2Cse
.u
.AsUCHAR
= 0;
201 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
202 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
, 0);
204 /* Release the lock */
205 KiReleaseSpinLock(&HalpPCIConfigLock
);
209 TYPE2_READ(HalpPCIReadUcharType2
, UCHAR
)
210 TYPE2_READ(HalpPCIReadUshortType2
, USHORT
)
211 TYPE2_READ(HalpPCIReadUlongType2
, ULONG
)
212 TYPE2_WRITE(HalpPCIWriteUcharType2
, UCHAR
)
213 TYPE2_WRITE(HalpPCIWriteUshortType2
, USHORT
)
214 TYPE2_WRITE(HalpPCIWriteUlongType2
, ULONG
)
216 /* PCI CONFIGURATION SPACE ***************************************************/
220 HalpPCIConfig(IN PBUS_HANDLER BusHandler
,
221 IN PCI_SLOT_NUMBER Slot
,
225 IN FncConfigIO
*ConfigIO
)
231 /* Synchronize the operation */
232 PCIConfigHandler
.Synchronize(BusHandler
, Slot
, &OldIrql
, State
);
234 /* Loop every increment */
237 /* Find out the type of read/write we need to do */
238 i
= PCIDeref
[Offset
% sizeof(ULONG
)][Length
% sizeof(ULONG
)];
240 /* Do the read/write and return the number of bytes */
241 i
= ConfigIO
[i
]((PPCIPBUSDATA
)BusHandler
->BusData
,
246 /* Increment the buffer position and offset, and decrease the length */
252 /* Release the lock and PCI bus */
253 PCIConfigHandler
.ReleaseSynchronzation(BusHandler
, OldIrql
);
258 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler
,
259 IN PCI_SLOT_NUMBER Slot
,
264 /* Validate the PCI Slot */
265 if (!HalpValidPCISlot(BusHandler
, Slot
))
267 /* Fill the buffer with invalid data */
268 RtlFillMemory(Buffer
, Length
, -1);
272 /* Send the request */
273 HalpPCIConfig(BusHandler
,
278 PCIConfigHandler
.ConfigRead
);
284 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler
,
285 IN PCI_SLOT_NUMBER Slot
,
290 /* Validate the PCI Slot */
291 if (HalpValidPCISlot(BusHandler
, Slot
))
293 /* Send the request */
294 HalpPCIConfig(BusHandler
,
299 PCIConfigHandler
.ConfigWrite
);
305 HalpValidPCISlot(IN PBUS_HANDLER BusHandler
,
306 IN PCI_SLOT_NUMBER Slot
)
308 PCI_SLOT_NUMBER MultiSlot
;
309 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
313 /* Simple validation */
314 if (Slot
.u
.bits
.Reserved
) return FALSE
;
315 if (Slot
.u
.bits
.DeviceNumber
>= BusData
->MaxDevice
) return FALSE
;
317 /* Function 0 doesn't need checking */
318 if (!Slot
.u
.bits
.FunctionNumber
) return TRUE
;
320 /* Functions 0+ need Multi-Function support, so check the slot */
321 Device
= Slot
.u
.bits
.DeviceNumber
;
323 MultiSlot
.u
.bits
.FunctionNumber
= 0;
325 /* Send function 0 request to get the header back */
326 HalpReadPCIConfig(BusHandler
,
329 FIELD_OFFSET(PCI_COMMON_CONFIG
, HeaderType
),
332 /* Now make sure the header is multi-function */
333 if (!(HeaderType
& PCI_MULTIFUNCTION
) || (HeaderType
== 0xFF)) return FALSE
;
337 /* HAL PCI CALLBACKS *********************************************************/
341 HalpGetPCIData(IN PBUS_HANDLER BusHandler
,
342 IN PBUS_HANDLER RootHandler
,
343 IN PCI_SLOT_NUMBER Slot
,
348 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
349 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
353 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
354 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
355 * video card, so it appears to be present on 1:0:0 - 1:31:0.
356 * We hack around these problems by indicating "device not present" for devices
357 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
358 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
359 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
360 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
362 DPRINT("Blacklisted PCI slot\n");
363 if (0 == Offset
&& 2 <= Length
)
365 *(PUSHORT
)Buffer
= PCI_INVALID_VENDORID
;
372 /* Normalize the length */
373 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
375 /* Check if this is a vendor-specific read */
376 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
378 /* Read the header */
379 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
381 /* Make sure the vendor is valid */
382 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
386 /* Read the entire header */
387 Len
= PCI_COMMON_HDR_LENGTH
;
388 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
390 /* Validate the vendor ID */
391 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
)
393 /* It's invalid, but we want to return this much */
394 PciConfig
->VendorID
= PCI_INVALID_VENDORID
;
395 Len
= sizeof(USHORT
);
398 /* Now check if there's space left */
399 if (Len
< Offset
) return 0;
401 /* There is, so return what's after the offset and normalize */
403 if (Len
> Length
) Len
= Length
;
405 /* Copy the data into the caller's buffer */
406 RtlMoveMemory(Buffer
, PciBuffer
+ Offset
, Len
);
408 /* Update buffer and offset, decrement total length */
410 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Len
);
414 /* Now we still have something to copy */
417 /* Check if it's vendor-specific data */
418 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
421 HalpReadPCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
426 /* Update the total length read */
432 HalpSetPCIData(IN PBUS_HANDLER BusHandler
,
433 IN PBUS_HANDLER RootHandler
,
434 IN PCI_SLOT_NUMBER Slot
,
439 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
440 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
444 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
445 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
446 * video card, so it appears to be present on 1:0:0 - 1:31:0.
447 * We hack around these problems by indicating "device not present" for devices
448 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
449 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
450 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
451 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
453 DPRINT1("Trying to set data on blacklisted PCI slot\n");
458 /* Normalize the length */
459 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
461 /* Check if this is a vendor-specific read */
462 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
464 /* Read the header */
465 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
467 /* Make sure the vendor is valid */
468 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
472 /* Read the entire header and validate the vendor ID */
473 Len
= PCI_COMMON_HDR_LENGTH
;
474 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
475 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
477 /* Return what's after the offset and normalize */
479 if (Len
> Length
) Len
= Length
;
481 /* Copy the specific caller data */
482 RtlMoveMemory(PciBuffer
+ Offset
, Buffer
, Len
);
484 /* Write the actual configuration data */
485 HalpWritePCIConfig(BusHandler
, Slot
, PciBuffer
+ Offset
, Offset
, Len
);
487 /* Update buffer and offset, decrement total length */
489 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Len
);
493 /* Now we still have something to copy */
496 /* Check if it's vendor-specific data */
497 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
500 HalpWritePCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
505 /* Update the total length read */
511 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock
,
512 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
514 DPRINT1("Unimplemented!\n");
515 return STATUS_NOT_IMPLEMENTED
;
520 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
522 DPRINT1("Unimplemented!\n");
523 return STATUS_NOT_IMPLEMENTED
;
528 HalpRegisterPciDebuggingDeviceInfo(VOID
)
530 BOOLEAN Found
= FALSE
;
534 /* Loop PCI debugging devices */
535 for (i
= 0; i
< 2; i
++)
537 /* Reserved bit is set if we found one */
538 if (HalpPciDebuggingDevice
[i
].u
.bits
.Reserved1
)
545 /* Bail out if there aren't any */
549 DPRINT1("You have implemented the KD routines for searching PCI debugger"
550 "devices, but you have forgotten to implement this routine\n");
555 PciSize(ULONG Base
, ULONG Mask
)
557 ULONG Size
= Mask
& Base
; /* Find the significant bits */
558 Size
= Size
& ~(Size
- 1); /* Get the lowest of them to find the decode size */
564 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler
,
565 IN PBUS_HANDLER RootHandler
,
566 IN PUNICODE_STRING RegistryPath
,
567 IN PUNICODE_STRING DriverClassName OPTIONAL
,
568 IN PDRIVER_OBJECT DriverObject
,
569 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
571 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
573 PCI_COMMON_CONFIG PciConfig
;
575 SIZE_T ResourceCount
;
576 ULONG Size
[PCI_TYPE0_ADDRESSES
];
577 NTSTATUS Status
= STATUS_SUCCESS
;
579 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
580 PCI_SLOT_NUMBER SlotNumber
;
583 /* FIXME: Should handle 64-bit addresses */
585 /* Read configuration data */
586 SlotNumber
.u
.AsULONG
= Slot
;
587 HalpReadPCIConfig(BusHandler
, SlotNumber
, &PciConfig
, 0, PCI_COMMON_HDR_LENGTH
);
589 /* Check if we read it correctly */
590 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
591 return STATUS_NO_SUCH_DEVICE
;
593 /* Read the PCI configuration space for the device and store base address and
594 size information in temporary storage. Count the number of valid base addresses */
596 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
598 if (0xffffffff == PciConfig
.u
.type0
.BaseAddresses
[Address
])
599 PciConfig
.u
.type0
.BaseAddresses
[Address
] = 0;
601 /* Memory resource */
602 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
606 Offset
= (UCHAR
)FIELD_OFFSET(PCI_COMMON_CONFIG
, u
.type0
.BaseAddresses
[Address
]);
608 /* Write 0xFFFFFFFF there */
609 WriteBuffer
= 0xffffffff;
610 HalpWritePCIConfig(BusHandler
, SlotNumber
, &WriteBuffer
, Offset
, sizeof(ULONG
));
612 /* Read that figure back from the config space */
613 HalpReadPCIConfig(BusHandler
, SlotNumber
, &Size
[Address
], Offset
, sizeof(ULONG
));
615 /* Write back initial value */
616 HalpWritePCIConfig(BusHandler
, SlotNumber
, &PciConfig
.u
.type0
.BaseAddresses
[Address
], Offset
, sizeof(ULONG
));
620 /* Interrupt resource */
621 if (0 != PciConfig
.u
.type0
.InterruptLine
)
624 /* Allocate output buffer and initialize */
625 *AllocatedResources
= ExAllocatePoolWithTag(
627 sizeof(CM_RESOURCE_LIST
) +
628 (ResourceCount
- 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
631 if (NULL
== *AllocatedResources
)
632 return STATUS_NO_MEMORY
;
634 (*AllocatedResources
)->Count
= 1;
635 (*AllocatedResources
)->List
[0].InterfaceType
= PCIBus
;
636 (*AllocatedResources
)->List
[0].BusNumber
= BusHandler
->BusNumber
;
637 (*AllocatedResources
)->List
[0].PartialResourceList
.Version
= 1;
638 (*AllocatedResources
)->List
[0].PartialResourceList
.Revision
= 1;
639 (*AllocatedResources
)->List
[0].PartialResourceList
.Count
= ResourceCount
;
640 Descriptor
= (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
;
642 /* Store configuration information */
643 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
645 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
647 if (PCI_ADDRESS_MEMORY_SPACE
==
648 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
650 Descriptor
->Type
= CmResourceTypeMemory
;
651 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
652 Descriptor
->Flags
= CM_RESOURCE_MEMORY_READ_WRITE
; /* FIXME Just a guess */
653 Descriptor
->u
.Memory
.Start
.QuadPart
= (PciConfig
.u
.type0
.BaseAddresses
[Address
] & PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
654 Descriptor
->u
.Memory
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
656 else if (PCI_ADDRESS_IO_SPACE
==
657 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
659 Descriptor
->Type
= CmResourceTypePort
;
660 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
661 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
; /* FIXME Just a guess */
662 Descriptor
->u
.Port
.Start
.QuadPart
= PciConfig
.u
.type0
.BaseAddresses
[Address
] &= PCI_ADDRESS_IO_ADDRESS_MASK
;
663 Descriptor
->u
.Port
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_IO_ADDRESS_MASK
& 0xffff);
668 return STATUS_UNSUCCESSFUL
;
674 if (0 != PciConfig
.u
.type0
.InterruptLine
)
676 Descriptor
->Type
= CmResourceTypeInterrupt
;
677 Descriptor
->ShareDisposition
= CmResourceShareShared
; /* FIXME Just a guess */
678 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
; /* FIXME Just a guess */
679 Descriptor
->u
.Interrupt
.Level
= PciConfig
.u
.type0
.InterruptLine
;
680 Descriptor
->u
.Interrupt
.Vector
= PciConfig
.u
.type0
.InterruptLine
;
681 Descriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
686 ASSERT(Descriptor
== (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
+ ResourceCount
);
688 /* FIXME: Should store the resources in the registry resource map */
695 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler
,
697 IN PCI_SLOT_NUMBER SlotNumber
,
702 BUS_HANDLER BusHandler
;
703 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)Buffer
;
705 /* Setup fake PCI Bus handler */
706 RtlCopyMemory(&BusHandler
, &HalpFakePciBusHandler
, sizeof(BUS_HANDLER
));
707 BusHandler
.BusNumber
= BusNumber
;
709 /* Read configuration data */
710 HalpReadPCIConfig(&BusHandler
, SlotNumber
, Buffer
, Offset
, Length
);
712 /* Check if caller only wanted at least Vendor ID */
716 if (PciData
->VendorID
!= PCI_INVALID_VENDORID
)
718 /* Check if this is the new maximum bus number */
719 if (HalpMaxPciBus
< BusHandler
.BusNumber
)
722 HalpMaxPciBus
= BusHandler
.BusNumber
;
731 PPCI_REGISTRY_INFO_INTERNAL
733 HalpQueryPciRegistryInfo(VOID
)
737 OBJECT_ATTRIBUTES ObjectAttributes
;
738 UNICODE_STRING KeyName
, ConfigName
, IdentName
;
739 HANDLE KeyHandle
, BusKeyHandle
, CardListHandle
;
741 UCHAR KeyBuffer
[sizeof(CM_FULL_RESOURCE_DESCRIPTOR
) + 100];
742 PKEY_VALUE_FULL_INFORMATION ValueInfo
= (PVOID
)KeyBuffer
;
743 UCHAR PartialKeyBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
744 sizeof(PCI_CARD_DESCRIPTOR
)];
745 PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo
= (PVOID
)PartialKeyBuffer
;
746 KEY_FULL_INFORMATION KeyInformation
;
749 ULONG i
, ElementCount
;
750 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
751 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
752 PPCI_REGISTRY_INFO PciRegInfo
;
753 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
754 PPCI_CARD_DESCRIPTOR CardDescriptor
;
756 /* Setup the object attributes for the key */
757 RtlInitUnicodeString(&KeyName
,
758 L
"\\Registry\\Machine\\Hardware\\Description\\"
759 L
"System\\MultiFunctionAdapter");
760 InitializeObjectAttributes(&ObjectAttributes
,
762 OBJ_CASE_INSENSITIVE
,
767 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
768 if (!NT_SUCCESS(Status
)) return NULL
;
770 /* Setup the receiving string */
771 KeyName
.Buffer
= NameBuffer
;
772 KeyName
.MaximumLength
= sizeof(NameBuffer
);
774 /* Setup the configuration and identifier key names */
775 RtlInitUnicodeString(&ConfigName
, L
"Configuration Data");
776 RtlInitUnicodeString(&IdentName
, L
"Identifier");
778 /* Keep looping for each ID */
779 for (i
= 0; TRUE
; i
++)
781 /* Setup the key name */
782 RtlIntegerToUnicodeString(i
, 10, &KeyName
);
783 InitializeObjectAttributes(&ObjectAttributes
,
785 OBJ_CASE_INSENSITIVE
,
790 Status
= ZwOpenKey(&BusKeyHandle
, KEY_READ
, &ObjectAttributes
);
791 if (!NT_SUCCESS(Status
))
793 /* None left, fail */
798 /* Read the registry data */
799 Status
= ZwQueryValueKey(BusKeyHandle
,
801 KeyValueFullInformation
,
805 if (!NT_SUCCESS(Status
))
807 /* Failed, try the next one */
808 ZwClose(BusKeyHandle
);
812 /* Get the PCI Tag and validate it */
813 Tag
= (PWSTR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
814 if ((Tag
[0] != L
'P') ||
819 /* Not a valid PCI entry, skip it */
820 ZwClose(BusKeyHandle
);
824 /* Now read our PCI structure */
825 Status
= ZwQueryValueKey(BusKeyHandle
,
827 KeyValueFullInformation
,
831 ZwClose(BusKeyHandle
);
832 if (!NT_SUCCESS(Status
)) continue;
834 /* We read it OK! Get the actual resource descriptors */
835 FullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
836 ((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
837 PartialDescriptor
= (PCM_PARTIAL_RESOURCE_DESCRIPTOR
)
838 ((ULONG_PTR
)FullDescriptor
->
839 PartialResourceList
.PartialDescriptors
);
841 /* Check if this is our PCI Registry Information */
842 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
844 /* It is, stop searching */
852 /* Save the PCI information for later */
853 PciRegInfo
= (PPCI_REGISTRY_INFO
)(PartialDescriptor
+ 1);
855 /* Assume no Card List entries */
858 /* Set up for checking the PCI Card List key */
859 RtlInitUnicodeString(&KeyName
,
860 L
"\\Registry\\Machine\\System\\CurrentControlSet\\"
861 L
"Control\\PnP\\PCI\\CardList");
862 InitializeObjectAttributes(&ObjectAttributes
,
864 OBJ_CASE_INSENSITIVE
,
868 /* Attempt to open it */
869 Status
= ZwOpenKey(&CardListHandle
, KEY_READ
, &ObjectAttributes
);
870 if (NT_SUCCESS(Status
))
872 /* It exists, so let's query it */
873 Status
= ZwQueryKey(CardListHandle
,
876 sizeof(KEY_FULL_INFORMATION
),
878 if (!NT_SUCCESS(Status
))
880 /* Failed to query, so no info */
881 PciRegistryInfo
= NULL
;
885 /* Allocate the full structure */
887 ExAllocatePoolWithTag(NonPagedPool
,
888 sizeof(PCI_REGISTRY_INFO_INTERNAL
) +
889 (KeyInformation
.Values
*
890 sizeof(PCI_CARD_DESCRIPTOR
)),
894 /* Get the first card descriptor entry */
895 CardDescriptor
= (PPCI_CARD_DESCRIPTOR
)(PciRegistryInfo
+ 1);
897 /* Loop all the values */
898 for (i
= 0; i
< KeyInformation
.Values
; i
++)
900 /* Attempt to get the value */
901 Status
= ZwEnumerateValueKey(CardListHandle
,
903 KeyValuePartialInformation
,
905 sizeof(PartialKeyBuffer
),
907 if (!NT_SUCCESS(Status
))
909 /* Something went wrong, stop the search */
913 /* Make sure it is correctly sized */
914 if (PartialValueInfo
->DataLength
== sizeof(PCI_CARD_DESCRIPTOR
))
916 /* Sure is, copy it over */
917 *CardDescriptor
= *(PPCI_CARD_DESCRIPTOR
)
918 PartialValueInfo
->Data
;
920 /* One more Card List entry */
923 /* Move to the next descriptor */
924 CardDescriptor
= (CardDescriptor
+ 1);
930 /* Close the Card List key */
931 ZwClose(CardListHandle
);
935 /* No key, no Card List */
936 PciRegistryInfo
= NULL
;
939 /* Check if we failed to get the full structure */
940 if (!PciRegistryInfo
)
942 /* Just allocate the basic structure then */
943 PciRegistryInfo
= ExAllocatePoolWithTag(NonPagedPool
,
944 sizeof(PCI_REGISTRY_INFO_INTERNAL
),
946 if (!PciRegistryInfo
) return NULL
;
949 /* Save the info we got */
950 PciRegistryInfo
->MajorRevision
= PciRegInfo
->MajorRevision
;
951 PciRegistryInfo
->MinorRevision
= PciRegInfo
->MinorRevision
;
952 PciRegistryInfo
->NoBuses
= PciRegInfo
->NoBuses
;
953 PciRegistryInfo
->HardwareMechanism
= PciRegInfo
->HardwareMechanism
;
954 PciRegistryInfo
->ElementCount
= ElementCount
;
957 return PciRegistryInfo
;
965 HalpInitializePciStubs(VOID
)
967 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
969 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)HalpFakePciBusHandler
.BusData
;
974 /* Query registry information */
975 PciRegistryInfo
= HalpQueryPciRegistryInfo();
976 if (!PciRegistryInfo
)
983 /* Get the type and free the info structure */
984 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
985 ExFreePool(PciRegistryInfo
);
988 /* Initialize the PCI lock */
989 KeInitializeSpinLock(&HalpPCIConfigLock
);
991 /* Check the type of PCI bus */
997 /* Copy the Type 1 handler data */
998 RtlCopyMemory(&PCIConfigHandler
,
999 &PCIConfigHandlerType1
,
1000 sizeof(PCIConfigHandler
));
1002 /* Set correct I/O Ports */
1003 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
1004 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
1007 /* Type 2 PCI Bus */
1010 /* Copy the Type 1 handler data */
1011 RtlCopyMemory(&PCIConfigHandler
,
1012 &PCIConfigHandlerType2
,
1013 sizeof (PCIConfigHandler
));
1015 /* Set correct I/O Ports */
1016 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
1017 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
1018 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
1020 /* Only 16 devices supported, not 32 */
1021 BusData
->MaxDevice
= 16;
1027 DbgPrint("HAL: Unknown PCI type\n");
1030 /* Loop all possible buses */
1031 for (i
= 0; i
< 256; i
++)
1033 /* Loop all devices */
1034 for (j
.u
.AsULONG
= 0; j
.u
.AsULONG
< 32; j
.u
.AsULONG
++)
1036 /* Query the interface */
1037 if (HaliPciInterfaceReadConfig(NULL
,
1044 /* Validate the vendor ID */
1045 if ((USHORT
)VendorId
!= PCI_INVALID_VENDORID
)
1047 /* Set this as the maximum ID */
1056 HalpPCIConfigInitialized
= TRUE
;