3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/pci.c
5 * PURPOSE: PCI Bus Support (Configuration Space, Resource Allocation)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 BOOLEAN HalpPCIConfigInitialized
;
18 ULONG HalpMinPciBus
, HalpMaxPciBus
;
19 KSPIN_LOCK HalpPCIConfigLock
;
20 PCI_CONFIG_HANDLER PCIConfigHandler
;
22 /* PCI Operation Matrix */
23 UCHAR PCIDeref
[4][4] =
25 {0, 1, 2, 2}, // ULONG-aligned offset
26 {1, 1, 1, 1}, // UCHAR-aligned offset
27 {2, 1, 2, 2}, // USHORT-aligned offset
28 {1, 1, 1, 1} // UCHAR-aligned offset
32 PCI_CONFIG_HANDLER PCIConfigHandlerType1
=
35 (FncSync
)HalpPCISynchronizeType1
,
36 (FncReleaseSync
)HalpPCIReleaseSynchronzationType1
,
40 (FncConfigIO
)HalpPCIReadUlongType1
,
41 (FncConfigIO
)HalpPCIReadUcharType1
,
42 (FncConfigIO
)HalpPCIReadUshortType1
47 (FncConfigIO
)HalpPCIWriteUlongType1
,
48 (FncConfigIO
)HalpPCIWriteUcharType1
,
49 (FncConfigIO
)HalpPCIWriteUshortType1
54 PCI_CONFIG_HANDLER PCIConfigHandlerType2
=
57 (FncSync
)HalpPCISynchronizeType2
,
58 (FncReleaseSync
)HalpPCIReleaseSynchronizationType2
,
62 (FncConfigIO
)HalpPCIReadUlongType2
,
63 (FncConfigIO
)HalpPCIReadUcharType2
,
64 (FncConfigIO
)HalpPCIReadUshortType2
69 (FncConfigIO
)HalpPCIWriteUlongType2
,
70 (FncConfigIO
)HalpPCIWriteUcharType2
,
71 (FncConfigIO
)HalpPCIWriteUshortType2
75 PCIPBUSDATA HalpFakePciBusData
=
91 BUS_HANDLER HalpFakePciBusHandler
=
105 HalpAssignPCISlotResources
,
110 /* TYPE 1 FUNCTIONS **********************************************************/
114 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler
,
115 IN PCI_SLOT_NUMBER Slot
,
117 IN PPCI_TYPE1_CFG_BITS PciCfg1
)
119 /* Setup the PCI Configuration Register */
120 PciCfg1
->u
.AsULONG
= 0;
121 PciCfg1
->u
.bits
.BusNumber
= BusHandler
->BusNumber
;
122 PciCfg1
->u
.bits
.DeviceNumber
= Slot
.u
.bits
.DeviceNumber
;
123 PciCfg1
->u
.bits
.FunctionNumber
= Slot
.u
.bits
.FunctionNumber
;
124 PciCfg1
->u
.bits
.Enable
= TRUE
;
126 /* Acquire the lock */
127 *Irql
= KfRaiseIrql(HIGH_LEVEL
);
128 KiAcquireSpinLock(&HalpPCIConfigLock
);
133 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler
,
136 PCI_TYPE1_CFG_BITS PciCfg1
;
138 /* Clear the PCI Configuration Register */
139 PciCfg1
.u
.AsULONG
= 0;
140 WRITE_PORT_ULONG(((PPCIPBUSDATA
)BusHandler
->BusData
)->Config
.Type1
.Address
,
143 /* Release the lock */
144 KiReleaseSpinLock(&HalpPCIConfigLock
);
148 TYPE1_READ(HalpPCIReadUcharType1
, UCHAR
)
149 TYPE1_READ(HalpPCIReadUshortType1
, USHORT
)
150 TYPE1_READ(HalpPCIReadUlongType1
, ULONG
)
151 TYPE1_WRITE(HalpPCIWriteUcharType1
, UCHAR
)
152 TYPE1_WRITE(HalpPCIWriteUshortType1
, USHORT
)
153 TYPE1_WRITE(HalpPCIWriteUlongType1
, ULONG
)
155 /* TYPE 2 FUNCTIONS **********************************************************/
159 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler
,
160 IN PCI_SLOT_NUMBER Slot
,
162 IN PPCI_TYPE2_ADDRESS_BITS PciCfg
)
164 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
165 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
167 /* Setup the configuration register */
168 PciCfg
->u
.AsUSHORT
= 0;
169 PciCfg
->u
.bits
.Agent
= (USHORT
)Slot
.u
.bits
.DeviceNumber
;
170 PciCfg
->u
.bits
.AddressBase
= (USHORT
)BusData
->Config
.Type2
.Base
;
172 /* Acquire the lock */
173 *Irql
= KfRaiseIrql(HIGH_LEVEL
);
174 KiAcquireSpinLock(&HalpPCIConfigLock
);
176 /* Setup the CSE Register */
177 PciCfg2Cse
.u
.AsUCHAR
= 0;
178 PciCfg2Cse
.u
.bits
.Enable
= TRUE
;
179 PciCfg2Cse
.u
.bits
.FunctionNumber
= (UCHAR
)Slot
.u
.bits
.FunctionNumber
;
180 PciCfg2Cse
.u
.bits
.Key
= -1;
182 /* Write the bus number and CSE */
183 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
,
184 (UCHAR
)BusHandler
->BusNumber
);
185 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
190 HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler
,
193 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
194 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
196 /* Clear CSE and bus number */
197 PciCfg2Cse
.u
.AsUCHAR
= 0;
198 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
199 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
, 0);
201 /* Release the lock */
202 KiReleaseSpinLock(&HalpPCIConfigLock
);
206 TYPE2_READ(HalpPCIReadUcharType2
, UCHAR
)
207 TYPE2_READ(HalpPCIReadUshortType2
, USHORT
)
208 TYPE2_READ(HalpPCIReadUlongType2
, ULONG
)
209 TYPE2_WRITE(HalpPCIWriteUcharType2
, UCHAR
)
210 TYPE2_WRITE(HalpPCIWriteUshortType2
, USHORT
)
211 TYPE2_WRITE(HalpPCIWriteUlongType2
, ULONG
)
213 /* PCI CONFIGURATION SPACE ***************************************************/
217 HalpPCIConfig(IN PBUS_HANDLER BusHandler
,
218 IN PCI_SLOT_NUMBER Slot
,
222 IN FncConfigIO
*ConfigIO
)
228 /* Synchronize the operation */
229 PCIConfigHandler
.Synchronize(BusHandler
, Slot
, &OldIrql
, State
);
231 /* Loop every increment */
234 /* Find out the type of read/write we need to do */
235 i
= PCIDeref
[Offset
% sizeof(ULONG
)][Length
% sizeof(ULONG
)];
237 /* Do the read/write and return the number of bytes */
238 i
= ConfigIO
[i
]((PPCIPBUSDATA
)BusHandler
->BusData
,
243 /* Increment the buffer position and offset, and decrease the length */
249 /* Release the lock and PCI bus */
250 PCIConfigHandler
.ReleaseSynchronzation(BusHandler
, OldIrql
);
255 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler
,
256 IN PCI_SLOT_NUMBER Slot
,
261 /* Validate the PCI Slot */
262 if (!HalpValidPCISlot(BusHandler
, Slot
))
264 /* Fill the buffer with invalid data */
265 RtlFillMemory(Buffer
, Length
, -1);
269 /* Send the request */
270 HalpPCIConfig(BusHandler
,
275 PCIConfigHandler
.ConfigRead
);
281 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler
,
282 IN PCI_SLOT_NUMBER Slot
,
287 /* Validate the PCI Slot */
288 if (HalpValidPCISlot(BusHandler
, Slot
))
290 /* Send the request */
291 HalpPCIConfig(BusHandler
,
296 PCIConfigHandler
.ConfigWrite
);
302 HalpValidPCISlot(IN PBUS_HANDLER BusHandler
,
303 IN PCI_SLOT_NUMBER Slot
)
305 PCI_SLOT_NUMBER MultiSlot
;
306 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
310 /* Simple validation */
311 if (Slot
.u
.bits
.Reserved
) return FALSE
;
312 if (Slot
.u
.bits
.DeviceNumber
>= BusData
->MaxDevice
) return FALSE
;
314 /* Function 0 doesn't need checking */
315 if (!Slot
.u
.bits
.FunctionNumber
) return TRUE
;
317 /* Functions 0+ need Multi-Function support, so check the slot */
318 Device
= Slot
.u
.bits
.DeviceNumber
;
320 MultiSlot
.u
.bits
.FunctionNumber
= 0;
322 /* Send function 0 request to get the header back */
323 HalpReadPCIConfig(BusHandler
,
326 FIELD_OFFSET(PCI_COMMON_CONFIG
, HeaderType
),
329 /* Now make sure the header is multi-function */
330 if (!(HeaderType
& PCI_MULTIFUNCTION
) || (HeaderType
== 0xFF)) return FALSE
;
334 /* HAL PCI CALLBACKS *********************************************************/
338 HalpGetPCIData(IN PBUS_HANDLER BusHandler
,
339 IN PBUS_HANDLER RootHandler
,
340 IN PCI_SLOT_NUMBER Slot
,
345 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
346 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
350 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
351 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
352 * video card, so it appears to be present on 1:0:0 - 1:31:0.
353 * We hack around these problems by indicating "device not present" for devices
354 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
355 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
356 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
357 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
359 DPRINT("Blacklisted PCI slot\n");
360 if (0 == Offset
&& 2 <= Length
)
362 *(PUSHORT
)Buffer
= PCI_INVALID_VENDORID
;
369 /* Normalize the length */
370 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
372 /* Check if this is a vendor-specific read */
373 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
375 /* Read the header */
376 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
378 /* Make sure the vendor is valid */
379 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
383 /* Read the entire header */
384 Len
= PCI_COMMON_HDR_LENGTH
;
385 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
387 /* Validate the vendor ID */
388 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
)
390 /* It's invalid, but we want to return this much */
391 PciConfig
->VendorID
= PCI_INVALID_VENDORID
;
392 Len
= sizeof(USHORT
);
395 /* Now check if there's space left */
396 if (Len
< Offset
) return 0;
398 /* There is, so return what's after the offset and normalize */
400 if (Len
> Length
) Len
= Length
;
402 /* Copy the data into the caller's buffer */
403 RtlMoveMemory(Buffer
, PciBuffer
+ Offset
, Len
);
405 /* Update buffer and offset, decrement total length */
411 /* Now we still have something to copy */
414 /* Check if it's vendor-specific data */
415 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
418 HalpReadPCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
423 /* Update the total length read */
429 HalpSetPCIData(IN PBUS_HANDLER BusHandler
,
430 IN PBUS_HANDLER RootHandler
,
431 IN PCI_SLOT_NUMBER Slot
,
436 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
437 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
441 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
442 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
443 * video card, so it appears to be present on 1:0:0 - 1:31:0.
444 * We hack around these problems by indicating "device not present" for devices
445 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
446 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
447 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
448 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
450 DPRINT1("Trying to set data on blacklisted PCI slot\n");
455 /* Normalize the length */
456 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
458 /* Check if this is a vendor-specific read */
459 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
461 /* Read the header */
462 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
464 /* Make sure the vendor is valid */
465 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
469 /* Read the entire header and validate the vendor ID */
470 Len
= PCI_COMMON_HDR_LENGTH
;
471 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
472 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
474 /* Return what's after the offset and normalize */
476 if (Len
> Length
) Len
= Length
;
478 /* Copy the specific caller data */
479 RtlMoveMemory(PciBuffer
+ Offset
, Buffer
, Len
);
481 /* Write the actual configuration data */
482 HalpWritePCIConfig(BusHandler
, Slot
, PciBuffer
+ Offset
, Offset
, Len
);
484 /* Update buffer and offset, decrement total length */
490 /* Now we still have something to copy */
493 /* Check if it's vendor-specific data */
494 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
497 HalpWritePCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
502 /* Update the total length read */
508 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock
,
509 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
511 DPRINT1("Unimplemented!\n");
512 return STATUS_NOT_IMPLEMENTED
;
517 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
519 DPRINT1("Unimplemented!\n");
520 return STATUS_NOT_IMPLEMENTED
;
524 PciSize(ULONG Base
, ULONG Mask
)
526 ULONG Size
= Mask
& Base
; /* Find the significant bits */
527 Size
= Size
& ~(Size
- 1); /* Get the lowest of them to find the decode size */
533 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler
,
534 IN PBUS_HANDLER RootHandler
,
535 IN PUNICODE_STRING RegistryPath
,
536 IN PUNICODE_STRING DriverClassName OPTIONAL
,
537 IN PDRIVER_OBJECT DriverObject
,
538 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
540 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
542 PCI_COMMON_CONFIG PciConfig
;
544 SIZE_T ResourceCount
;
545 ULONG Size
[PCI_TYPE0_ADDRESSES
];
546 NTSTATUS Status
= STATUS_SUCCESS
;
548 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
549 PCI_SLOT_NUMBER SlotNumber
;
552 /* FIXME: Should handle 64-bit addresses */
554 /* Read configuration data */
555 SlotNumber
.u
.AsULONG
= Slot
;
556 HalpReadPCIConfig(BusHandler
, SlotNumber
, &PciConfig
, 0, PCI_COMMON_HDR_LENGTH
);
558 /* Check if we read it correctly */
559 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
560 return STATUS_NO_SUCH_DEVICE
;
562 /* Read the PCI configuration space for the device and store base address and
563 size information in temporary storage. Count the number of valid base addresses */
565 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
567 if (0xffffffff == PciConfig
.u
.type0
.BaseAddresses
[Address
])
568 PciConfig
.u
.type0
.BaseAddresses
[Address
] = 0;
570 /* Memory resource */
571 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
575 Offset
= FIELD_OFFSET(PCI_COMMON_CONFIG
, u
.type0
.BaseAddresses
[Address
]);
577 /* Write 0xFFFFFFFF there */
578 WriteBuffer
= 0xffffffff;
579 HalpWritePCIConfig(BusHandler
, SlotNumber
, &WriteBuffer
, Offset
, sizeof(ULONG
));
581 /* Read that figure back from the config space */
582 HalpReadPCIConfig(BusHandler
, SlotNumber
, &Size
[Address
], Offset
, sizeof(ULONG
));
584 /* Write back initial value */
585 HalpWritePCIConfig(BusHandler
, SlotNumber
, &PciConfig
.u
.type0
.BaseAddresses
[Address
], Offset
, sizeof(ULONG
));
589 /* Interrupt resource */
590 if (0 != PciConfig
.u
.type0
.InterruptLine
)
593 /* Allocate output buffer and initialize */
594 *AllocatedResources
= ExAllocatePoolWithTag(
596 sizeof(CM_RESOURCE_LIST
) +
597 (ResourceCount
- 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
600 if (NULL
== *AllocatedResources
)
601 return STATUS_NO_MEMORY
;
603 (*AllocatedResources
)->Count
= 1;
604 (*AllocatedResources
)->List
[0].InterfaceType
= PCIBus
;
605 (*AllocatedResources
)->List
[0].BusNumber
= BusHandler
->BusNumber
;
606 (*AllocatedResources
)->List
[0].PartialResourceList
.Version
= 1;
607 (*AllocatedResources
)->List
[0].PartialResourceList
.Revision
= 1;
608 (*AllocatedResources
)->List
[0].PartialResourceList
.Count
= ResourceCount
;
609 Descriptor
= (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
;
611 /* Store configuration information */
612 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
614 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
616 if (/*PCI_BASE_ADDRESS_SPACE_MEMORY*/ 0 ==
617 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
619 Descriptor
->Type
= CmResourceTypeMemory
;
620 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
621 Descriptor
->Flags
= CM_RESOURCE_MEMORY_READ_WRITE
; /* FIXME Just a guess */
622 Descriptor
->u
.Memory
.Start
.QuadPart
= (PciConfig
.u
.type0
.BaseAddresses
[Address
] & PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
623 Descriptor
->u
.Memory
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
625 else if (PCI_ADDRESS_IO_SPACE
==
626 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
628 Descriptor
->Type
= CmResourceTypePort
;
629 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
630 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
; /* FIXME Just a guess */
631 Descriptor
->u
.Port
.Start
.QuadPart
= PciConfig
.u
.type0
.BaseAddresses
[Address
] &= PCI_ADDRESS_IO_ADDRESS_MASK
;
632 Descriptor
->u
.Port
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_IO_ADDRESS_MASK
& 0xffff);
637 return STATUS_UNSUCCESSFUL
;
643 if (0 != PciConfig
.u
.type0
.InterruptLine
)
645 Descriptor
->Type
= CmResourceTypeInterrupt
;
646 Descriptor
->ShareDisposition
= CmResourceShareShared
; /* FIXME Just a guess */
647 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
; /* FIXME Just a guess */
648 Descriptor
->u
.Interrupt
.Level
= PciConfig
.u
.type0
.InterruptLine
;
649 Descriptor
->u
.Interrupt
.Vector
= PciConfig
.u
.type0
.InterruptLine
;
650 Descriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
655 ASSERT(Descriptor
== (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
+ ResourceCount
);
657 /* FIXME: Should store the resources in the registry resource map */
664 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler
,
666 IN PCI_SLOT_NUMBER SlotNumber
,
671 BUS_HANDLER BusHandler
;
672 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)Buffer
;
674 /* Setup fake PCI Bus handler */
675 RtlCopyMemory(&BusHandler
, &HalpFakePciBusHandler
, sizeof(BUS_HANDLER
));
676 BusHandler
.BusNumber
= BusNumber
;
678 /* Read configuration data */
679 HalpReadPCIConfig(&BusHandler
, SlotNumber
, Buffer
, Offset
, Length
);
681 /* Check if caller only wanted at least Vendor ID */
685 if (PciData
->VendorID
!= PCI_INVALID_VENDORID
)
687 /* Check if this is the new maximum bus number */
688 if (HalpMaxPciBus
< BusHandler
.BusNumber
)
691 HalpMaxPciBus
= BusHandler
.BusNumber
;
700 PPCI_REGISTRY_INFO_INTERNAL
702 HalpQueryPciRegistryInfo(VOID
)
705 OBJECT_ATTRIBUTES ObjectAttributes
;
706 UNICODE_STRING KeyName
, ConfigName
, IdentName
;
707 HANDLE KeyHandle
, BusKeyHandle
;
709 UCHAR KeyBuffer
[sizeof(PPCI_REGISTRY_INFO
) + 100];
710 PKEY_VALUE_FULL_INFORMATION ValueInfo
= (PVOID
)KeyBuffer
;
714 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
715 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
716 PPCI_REGISTRY_INFO PciRegInfo
;
717 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
719 /* Setup the object attributes for the key */
720 RtlInitUnicodeString(&KeyName
,
721 L
"\\Registry\\Machine\\Hardware\\Description\\"
722 L
"System\\MultiFunctionAdapter");
723 InitializeObjectAttributes(&ObjectAttributes
,
725 OBJ_CASE_INSENSITIVE
,
730 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
731 if (!NT_SUCCESS(Status
)) return NULL
;
733 /* Setup the receiving string */
734 KeyName
.Buffer
= NameBuffer
;
735 KeyName
.MaximumLength
= sizeof(NameBuffer
);
737 /* Setup the configuration and identifier key names */
738 RtlInitUnicodeString(&ConfigName
, L
"ConfigurationData");
739 RtlInitUnicodeString(&IdentName
, L
"Identifier");
741 /* Keep looping for each ID */
742 for (i
= 0; TRUE
; i
++)
744 /* Setup the key name */
745 RtlIntegerToUnicodeString(i
, 10, &KeyName
);
746 InitializeObjectAttributes(&ObjectAttributes
,
748 OBJ_CASE_INSENSITIVE
,
753 Status
= ZwOpenKey(&BusKeyHandle
, KEY_READ
, &ObjectAttributes
);
754 if (!NT_SUCCESS(Status
))
756 /* None left, fail */
761 /* Read the registry data */
762 Status
= ZwQueryValueKey(BusKeyHandle
,
764 KeyValueFullInformation
,
768 if (!NT_SUCCESS(Status
))
770 /* Failed, try the next one */
771 ZwClose(BusKeyHandle
);
775 /* Get the PCI Tag and validate it */
776 Tag
= (PWSTR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
777 if ((Tag
[0] != L
'P') ||
782 /* Not a valid PCI entry, skip it */
783 ZwClose(BusKeyHandle
);
787 /* Now read our PCI structure */
788 Status
= ZwQueryValueKey(BusKeyHandle
,
790 KeyValueFullInformation
,
794 ZwClose(BusKeyHandle
);
795 if (!NT_SUCCESS(Status
)) continue;
797 /* We read it OK! Get the actual resource descriptors */
798 FullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
799 ((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
800 PartialDescriptor
= (PCM_PARTIAL_RESOURCE_DESCRIPTOR
)
801 ((ULONG_PTR
)FullDescriptor
->
802 PartialResourceList
.PartialDescriptors
);
804 /* Check if this is our PCI Registry Information */
805 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
810 /* FIXME: Check PnP\PCI\CardList */
812 /* Get the PCI information */
813 PciRegInfo
= (PPCI_REGISTRY_INFO
)(PartialDescriptor
+ 1);
815 /* Allocate the return structure */
816 PciRegistryInfo
= ExAllocatePoolWithTag(NonPagedPool
,
817 sizeof(PCI_REGISTRY_INFO_INTERNAL
),
819 if (!PciRegistryInfo
) return NULL
;
822 PciRegistryInfo
->HardwareMechanism
= PciRegInfo
->HardwareMechanism
;
823 PciRegistryInfo
->NoBuses
= PciRegInfo
->NoBuses
;
824 PciRegistryInfo
->MajorRevision
= PciRegInfo
->MajorRevision
;
825 PciRegistryInfo
->MinorRevision
= PciRegInfo
->MinorRevision
;
826 PciRegistryInfo
->ElementCount
= 0;
833 HalpInitializePciStubs(VOID
)
835 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
837 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)HalpFakePciBusHandler
.BusData
;
842 /* Query registry information */
843 PciRegistryInfo
= HalpQueryPciRegistryInfo();
844 if (!PciRegistryInfo
)
851 /* Get the type and free the info structure */
852 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
853 ExFreePool(PciRegistryInfo
);
856 /* Initialize the PCI lock */
857 KeInitializeSpinLock(&HalpPCIConfigLock
);
859 /* Check the type of PCI bus */
865 /* Copy the Type 1 handler data */
866 RtlCopyMemory(&PCIConfigHandler
,
867 &PCIConfigHandlerType1
,
868 sizeof(PCIConfigHandler
));
870 /* Set correct I/O Ports */
871 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
872 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
878 /* Copy the Type 1 handler data */
879 RtlCopyMemory(&PCIConfigHandler
,
880 &PCIConfigHandlerType2
,
881 sizeof (PCIConfigHandler
));
883 /* Set correct I/O Ports */
884 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
885 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
886 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
888 /* Only 16 devices supported, not 32 */
889 BusData
->MaxDevice
= 16;
895 DbgPrint("HAL: Unnkown PCI type\n");
898 /* Loop all possible buses */
899 for (i
= 0; i
< 256; i
++)
901 /* Loop all devices */
902 for (j
.u
.AsULONG
= 0; j
.u
.AsULONG
< 32; j
.u
.AsULONG
++)
904 /* Query the interface */
905 if (HaliPciInterfaceReadConfig(NULL
,
912 /* Validate the vendor ID */
913 if ((USHORT
)VendorId
!= PCI_INVALID_VENDORID
)
915 /* Set this as the maximum ID */
924 HalpPCIConfigInitialized
= TRUE
;
929 HalpInitializePciBus(VOID
)
931 /* Initialize the stubs */
932 HalpInitializePciStubs();
934 /* FIXME: Initialize NMI Crash Flag */