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 extern BOOLEAN HalpPciLockSettings
;
20 PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice
[2] = {{{{0}}}};
22 BOOLEAN HalpPCIConfigInitialized
;
23 ULONG HalpMinPciBus
, HalpMaxPciBus
;
24 KSPIN_LOCK HalpPCIConfigLock
;
25 PCI_CONFIG_HANDLER PCIConfigHandler
;
27 /* PCI Operation Matrix */
28 UCHAR PCIDeref
[4][4] =
30 {0, 1, 2, 2}, // ULONG-aligned offset
31 {1, 1, 1, 1}, // UCHAR-aligned offset
32 {2, 1, 2, 2}, // USHORT-aligned offset
33 {1, 1, 1, 1} // UCHAR-aligned offset
37 PCI_CONFIG_HANDLER PCIConfigHandlerType1
=
40 (FncSync
)HalpPCISynchronizeType1
,
41 (FncReleaseSync
)HalpPCIReleaseSynchronzationType1
,
45 (FncConfigIO
)HalpPCIReadUlongType1
,
46 (FncConfigIO
)HalpPCIReadUcharType1
,
47 (FncConfigIO
)HalpPCIReadUshortType1
52 (FncConfigIO
)HalpPCIWriteUlongType1
,
53 (FncConfigIO
)HalpPCIWriteUcharType1
,
54 (FncConfigIO
)HalpPCIWriteUshortType1
59 PCI_CONFIG_HANDLER PCIConfigHandlerType2
=
62 (FncSync
)HalpPCISynchronizeType2
,
63 (FncReleaseSync
)HalpPCIReleaseSynchronizationType2
,
67 (FncConfigIO
)HalpPCIReadUlongType2
,
68 (FncConfigIO
)HalpPCIReadUcharType2
,
69 (FncConfigIO
)HalpPCIReadUshortType2
74 (FncConfigIO
)HalpPCIWriteUlongType2
,
75 (FncConfigIO
)HalpPCIWriteUcharType2
,
76 (FncConfigIO
)HalpPCIWriteUshortType2
80 PCIPBUSDATA HalpFakePciBusData
=
96 BUS_HANDLER HalpFakePciBusHandler
=
108 (PGETSETBUSDATA
)HalpGetPCIData
,
109 (PGETSETBUSDATA
)HalpSetPCIData
,
111 HalpAssignPCISlotResources
,
116 /* TYPE 1 FUNCTIONS **********************************************************/
120 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler
,
121 IN PCI_SLOT_NUMBER Slot
,
123 IN PPCI_TYPE1_CFG_BITS PciCfg1
)
125 /* Setup the PCI Configuration Register */
126 PciCfg1
->u
.AsULONG
= 0;
127 PciCfg1
->u
.bits
.BusNumber
= BusHandler
->BusNumber
;
128 PciCfg1
->u
.bits
.DeviceNumber
= Slot
.u
.bits
.DeviceNumber
;
129 PciCfg1
->u
.bits
.FunctionNumber
= Slot
.u
.bits
.FunctionNumber
;
130 PciCfg1
->u
.bits
.Enable
= TRUE
;
132 /* Acquire the lock */
133 KeRaiseIrql(HIGH_LEVEL
, Irql
);
134 KiAcquireSpinLock(&HalpPCIConfigLock
);
139 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler
,
142 PCI_TYPE1_CFG_BITS PciCfg1
;
144 /* Clear the PCI Configuration Register */
145 PciCfg1
.u
.AsULONG
= 0;
146 WRITE_PORT_ULONG(((PPCIPBUSDATA
)BusHandler
->BusData
)->Config
.Type1
.Address
,
149 /* Release the lock */
150 KiReleaseSpinLock(&HalpPCIConfigLock
);
154 TYPE1_READ(HalpPCIReadUcharType1
, UCHAR
)
155 TYPE1_READ(HalpPCIReadUshortType1
, USHORT
)
156 TYPE1_READ(HalpPCIReadUlongType1
, ULONG
)
157 TYPE1_WRITE(HalpPCIWriteUcharType1
, UCHAR
)
158 TYPE1_WRITE(HalpPCIWriteUshortType1
, USHORT
)
159 TYPE1_WRITE(HalpPCIWriteUlongType1
, ULONG
)
161 /* TYPE 2 FUNCTIONS **********************************************************/
165 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler
,
166 IN PCI_SLOT_NUMBER Slot
,
168 IN PPCI_TYPE2_ADDRESS_BITS PciCfg
)
170 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
171 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
173 /* Setup the configuration register */
174 PciCfg
->u
.AsUSHORT
= 0;
175 PciCfg
->u
.bits
.Agent
= (USHORT
)Slot
.u
.bits
.DeviceNumber
;
176 PciCfg
->u
.bits
.AddressBase
= (USHORT
)BusData
->Config
.Type2
.Base
;
178 /* Acquire the lock */
179 KeRaiseIrql(HIGH_LEVEL
, Irql
);
180 KiAcquireSpinLock(&HalpPCIConfigLock
);
182 /* Setup the CSE Register */
183 PciCfg2Cse
.u
.AsUCHAR
= 0;
184 PciCfg2Cse
.u
.bits
.Enable
= TRUE
;
185 PciCfg2Cse
.u
.bits
.FunctionNumber
= (UCHAR
)Slot
.u
.bits
.FunctionNumber
;
186 PciCfg2Cse
.u
.bits
.Key
= -1;
188 /* Write the bus number and CSE */
189 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
,
190 (UCHAR
)BusHandler
->BusNumber
);
191 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
196 HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler
,
199 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
200 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
202 /* Clear CSE and bus number */
203 PciCfg2Cse
.u
.AsUCHAR
= 0;
204 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
205 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
, 0);
207 /* Release the lock */
208 KiReleaseSpinLock(&HalpPCIConfigLock
);
212 TYPE2_READ(HalpPCIReadUcharType2
, UCHAR
)
213 TYPE2_READ(HalpPCIReadUshortType2
, USHORT
)
214 TYPE2_READ(HalpPCIReadUlongType2
, ULONG
)
215 TYPE2_WRITE(HalpPCIWriteUcharType2
, UCHAR
)
216 TYPE2_WRITE(HalpPCIWriteUshortType2
, USHORT
)
217 TYPE2_WRITE(HalpPCIWriteUlongType2
, ULONG
)
219 /* PCI CONFIGURATION SPACE ***************************************************/
223 HalpPCIConfig(IN PBUS_HANDLER BusHandler
,
224 IN PCI_SLOT_NUMBER Slot
,
228 IN FncConfigIO
*ConfigIO
)
234 /* Synchronize the operation */
235 PCIConfigHandler
.Synchronize(BusHandler
, Slot
, &OldIrql
, State
);
237 /* Loop every increment */
240 /* Find out the type of read/write we need to do */
241 i
= PCIDeref
[Offset
% sizeof(ULONG
)][Length
% sizeof(ULONG
)];
243 /* Do the read/write and return the number of bytes */
244 i
= ConfigIO
[i
]((PPCIPBUSDATA
)BusHandler
->BusData
,
249 /* Increment the buffer position and offset, and decrease the length */
255 /* Release the lock and PCI bus */
256 PCIConfigHandler
.ReleaseSynchronzation(BusHandler
, OldIrql
);
261 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler
,
262 IN PCI_SLOT_NUMBER Slot
,
267 /* Validate the PCI Slot */
268 if (!HalpValidPCISlot(BusHandler
, Slot
))
270 /* Fill the buffer with invalid data */
271 RtlFillMemory(Buffer
, Length
, -1);
275 /* Send the request */
276 HalpPCIConfig(BusHandler
,
281 PCIConfigHandler
.ConfigRead
);
287 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler
,
288 IN PCI_SLOT_NUMBER Slot
,
293 /* Validate the PCI Slot */
294 if (HalpValidPCISlot(BusHandler
, Slot
))
296 /* Send the request */
297 HalpPCIConfig(BusHandler
,
302 PCIConfigHandler
.ConfigWrite
);
308 HalpValidPCISlot(IN PBUS_HANDLER BusHandler
,
309 IN PCI_SLOT_NUMBER Slot
)
311 PCI_SLOT_NUMBER MultiSlot
;
312 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
316 /* Simple validation */
317 if (Slot
.u
.bits
.Reserved
) return FALSE
;
318 if (Slot
.u
.bits
.DeviceNumber
>= BusData
->MaxDevice
) return FALSE
;
320 /* Function 0 doesn't need checking */
321 if (!Slot
.u
.bits
.FunctionNumber
) return TRUE
;
323 /* Functions 0+ need Multi-Function support, so check the slot */
324 Device
= Slot
.u
.bits
.DeviceNumber
;
326 MultiSlot
.u
.bits
.FunctionNumber
= 0;
328 /* Send function 0 request to get the header back */
329 HalpReadPCIConfig(BusHandler
,
332 FIELD_OFFSET(PCI_COMMON_CONFIG
, HeaderType
),
335 /* Now make sure the header is multi-function */
336 if (!(HeaderType
& PCI_MULTIFUNCTION
) || (HeaderType
== 0xFF)) return FALSE
;
340 /* HAL PCI CALLBACKS *********************************************************/
344 HalpGetPCIData(IN PBUS_HANDLER BusHandler
,
345 IN PBUS_HANDLER RootHandler
,
346 IN PCI_SLOT_NUMBER Slot
,
351 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
352 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
356 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
357 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
358 * video card, so it appears to be present on 1:0:0 - 1:31:0.
359 * We hack around these problems by indicating "device not present" for devices
360 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
361 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
362 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
363 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
365 DPRINT("Blacklisted PCI slot\n");
366 if (0 == Offset
&& sizeof(USHORT
) <= Length
)
368 *(PUSHORT
)Buffer
= PCI_INVALID_VENDORID
;
369 return sizeof(USHORT
);
375 /* Normalize the length */
376 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
378 /* Check if this is a vendor-specific read */
379 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
381 /* Read the header */
382 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
384 /* Make sure the vendor is valid */
385 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
389 /* Read the entire header */
390 Len
= PCI_COMMON_HDR_LENGTH
;
391 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
393 /* Validate the vendor ID */
394 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
)
396 /* It's invalid, but we want to return this much */
397 Len
= sizeof(USHORT
);
400 /* Now check if there's space left */
401 if (Len
< Offset
) return 0;
403 /* There is, so return what's after the offset and normalize */
405 if (Len
> Length
) Len
= Length
;
407 /* Copy the data into the caller's buffer */
408 RtlMoveMemory(Buffer
, PciBuffer
+ Offset
, Len
);
410 /* Update buffer and offset, decrement total length */
412 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Len
);
416 /* Now we still have something to copy */
419 /* Check if it's vendor-specific data */
420 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
423 HalpReadPCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
428 /* Update the total length read */
434 HalpSetPCIData(IN PBUS_HANDLER BusHandler
,
435 IN PBUS_HANDLER RootHandler
,
436 IN PCI_SLOT_NUMBER Slot
,
441 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
442 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
446 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
447 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
448 * video card, so it appears to be present on 1:0:0 - 1:31:0.
449 * We hack around these problems by indicating "device not present" for devices
450 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
451 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
452 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
453 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
455 DPRINT1("Trying to set data on blacklisted PCI slot\n");
460 /* Normalize the length */
461 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
463 /* Check if this is a vendor-specific read */
464 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
466 /* Read the header */
467 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
469 /* Make sure the vendor is valid */
470 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
474 /* Read the entire header and validate the vendor ID */
475 Len
= PCI_COMMON_HDR_LENGTH
;
476 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
477 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
479 /* Return what's after the offset and normalize */
481 if (Len
> Length
) Len
= Length
;
483 /* Copy the specific caller data */
484 RtlMoveMemory(PciBuffer
+ Offset
, Buffer
, Len
);
486 /* Write the actual configuration data */
487 HalpWritePCIConfig(BusHandler
, Slot
, PciBuffer
+ Offset
, Offset
, Len
);
489 /* Update buffer and offset, decrement total length */
491 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Len
);
495 /* Now we still have something to copy */
498 /* Check if it's vendor-specific data */
499 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
502 HalpWritePCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
507 /* Update the total length read */
513 HalpGetPCIIntOnISABus(IN PBUS_HANDLER BusHandler
,
514 IN PBUS_HANDLER RootHandler
,
515 IN ULONG BusInterruptLevel
,
516 IN ULONG BusInterruptVector
,
518 OUT PKAFFINITY Affinity
)
520 /* Validate the level first */
521 if (BusInterruptLevel
< 1) return 0;
523 /* PCI has its IRQs on top of ISA IRQs, so pass it on to the ISA handler */
524 return HalGetInterruptVector(Isa
,
534 HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler
,
535 IN PBUS_HANDLER RootHandler
,
536 IN PCI_SLOT_NUMBER SlotNumber
,
537 IN PPCI_COMMON_CONFIG PciData
)
545 HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler
,
546 IN PBUS_HANDLER RootHandler
,
547 IN PCI_SLOT_NUMBER SlotNumber
,
548 IN PPCI_COMMON_CONFIG PciNewData
,
549 IN PPCI_COMMON_CONFIG PciOldData
)
557 HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler
,
558 IN PBUS_HANDLER RootHandler
,
559 IN PCI_SLOT_NUMBER PciSlot
,
560 OUT PSUPPORTED_RANGE
*Range
)
562 PCI_COMMON_HEADER PciData
;
564 /* Read PCI configuration data */
565 HalGetBusData(PCIConfiguration
,
566 BusHandler
->BusNumber
,
569 PCI_COMMON_HDR_LENGTH
);
571 /* Make sure it's a real device */
572 if (PciData
.VendorID
== PCI_INVALID_VENDORID
) return STATUS_UNSUCCESSFUL
;
574 /* Allocate the supported range structure */
575 *Range
= ExAllocatePoolWithTag(PagedPool
, sizeof(SUPPORTED_RANGE
), TAG_HAL
);
576 if (!*Range
) return STATUS_INSUFFICIENT_RESOURCES
;
579 RtlZeroMemory(*Range
, sizeof(SUPPORTED_RANGE
));
582 /* If the PCI device has no IRQ, nothing to do */
583 if (!PciData
.u
.type0
.InterruptPin
) return STATUS_SUCCESS
;
585 /* FIXME: The PCI IRQ Routing Miniport should be called */
587 /* Also if the INT# seems bogus, nothing to do either */
588 if ((PciData
.u
.type0
.InterruptLine
== 0) ||
589 (PciData
.u
.type0
.InterruptLine
== 255))
592 return STATUS_SUCCESS
;
595 /* Otherwise, the INT# should be valid, return it to the caller */
596 (*Range
)->Base
= PciData
.u
.type0
.InterruptLine
;
597 (*Range
)->Limit
= PciData
.u
.type0
.InterruptLine
;
598 return STATUS_SUCCESS
;
604 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock
,
605 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
607 DPRINT1("Unimplemented!\n");
608 return STATUS_NOT_IMPLEMENTED
;
614 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
616 DPRINT1("Unimplemented!\n");
617 return STATUS_NOT_IMPLEMENTED
;
623 HalpRegisterPciDebuggingDeviceInfo(VOID
)
625 BOOLEAN Found
= FALSE
;
629 /* Loop PCI debugging devices */
630 for (i
= 0; i
< 2; i
++)
632 /* Reserved bit is set if we found one */
633 if (HalpPciDebuggingDevice
[i
].u
.bits
.Reserved1
)
640 /* Bail out if there aren't any */
644 DPRINT1("You have implemented the KD routines for searching PCI debugger"
645 "devices, but you have forgotten to implement this routine\n");
650 PciSize(ULONG Base
, ULONG Mask
)
652 ULONG Size
= Mask
& Base
; /* Find the significant bits */
653 Size
= Size
& ~(Size
- 1); /* Get the lowest of them to find the decode size */
659 HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler
,
660 IN PBUS_HANDLER RootHandler
,
661 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST
*pResourceList
)
663 PPCIPBUSDATA BusData
;
664 PCI_SLOT_NUMBER SlotNumber
;
665 PSUPPORTED_RANGE Interrupt
;
668 /* Get PCI bus data */
669 BusData
= BusHandler
->BusData
;
670 SlotNumber
.u
.AsULONG
= (*pResourceList
)->SlotNumber
;
672 /* Get the IRQ supported range */
673 Status
= BusData
->GetIrqRange(BusHandler
, RootHandler
, SlotNumber
, &Interrupt
);
674 if (!NT_SUCCESS(Status
)) return Status
;
676 /* Handle the /PCILOCK feature */
677 if (HalpPciLockSettings
)
679 /* /PCILOCK is not yet supported */
684 /* Now create the correct resource list based on the supported bus ranges */
686 Status
= HaliAdjustResourceListRange(BusHandler
->BusAddresses
,
690 DPRINT1("HAL: No PCI Resource Adjustment done! Hardware may malfunction\n");
691 Status
= STATUS_SUCCESS
;
694 /* Return to caller */
695 ExFreePool(Interrupt
);
701 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler
,
702 IN PBUS_HANDLER RootHandler
,
703 IN PUNICODE_STRING RegistryPath
,
704 IN PUNICODE_STRING DriverClassName OPTIONAL
,
705 IN PDRIVER_OBJECT DriverObject
,
706 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
708 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
710 PCI_COMMON_CONFIG PciConfig
;
712 SIZE_T ResourceCount
;
713 ULONG Size
[PCI_TYPE0_ADDRESSES
];
714 NTSTATUS Status
= STATUS_SUCCESS
;
716 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
717 PCI_SLOT_NUMBER SlotNumber
;
719 DPRINT1("WARNING: PCI Slot Resource Assignment is FOOBAR\n");
721 /* FIXME: Should handle 64-bit addresses */
723 /* Read configuration data */
724 SlotNumber
.u
.AsULONG
= Slot
;
725 HalpReadPCIConfig(BusHandler
, SlotNumber
, &PciConfig
, 0, PCI_COMMON_HDR_LENGTH
);
727 /* Check if we read it correctly */
728 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
729 return STATUS_NO_SUCH_DEVICE
;
731 /* Read the PCI configuration space for the device and store base address and
732 size information in temporary storage. Count the number of valid base addresses */
734 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
736 if (0xffffffff == PciConfig
.u
.type0
.BaseAddresses
[Address
])
737 PciConfig
.u
.type0
.BaseAddresses
[Address
] = 0;
739 /* Memory resource */
740 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
744 Offset
= (UCHAR
)FIELD_OFFSET(PCI_COMMON_CONFIG
, u
.type0
.BaseAddresses
[Address
]);
746 /* Write 0xFFFFFFFF there */
747 WriteBuffer
= 0xffffffff;
748 HalpWritePCIConfig(BusHandler
, SlotNumber
, &WriteBuffer
, Offset
, sizeof(ULONG
));
750 /* Read that figure back from the config space */
751 HalpReadPCIConfig(BusHandler
, SlotNumber
, &Size
[Address
], Offset
, sizeof(ULONG
));
753 /* Write back initial value */
754 HalpWritePCIConfig(BusHandler
, SlotNumber
, &PciConfig
.u
.type0
.BaseAddresses
[Address
], Offset
, sizeof(ULONG
));
758 /* Interrupt resource */
759 if (0 != PciConfig
.u
.type0
.InterruptPin
&&
760 0 != PciConfig
.u
.type0
.InterruptLine
&&
761 0xFF != PciConfig
.u
.type0
.InterruptLine
)
764 /* Allocate output buffer and initialize */
765 *AllocatedResources
= ExAllocatePoolWithTag(
767 sizeof(CM_RESOURCE_LIST
) +
768 (ResourceCount
- 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
771 if (NULL
== *AllocatedResources
)
772 return STATUS_NO_MEMORY
;
774 (*AllocatedResources
)->Count
= 1;
775 (*AllocatedResources
)->List
[0].InterfaceType
= PCIBus
;
776 (*AllocatedResources
)->List
[0].BusNumber
= BusHandler
->BusNumber
;
777 (*AllocatedResources
)->List
[0].PartialResourceList
.Version
= 1;
778 (*AllocatedResources
)->List
[0].PartialResourceList
.Revision
= 1;
779 (*AllocatedResources
)->List
[0].PartialResourceList
.Count
= ResourceCount
;
780 Descriptor
= (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
;
782 /* Store configuration information */
783 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
785 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
787 if (PCI_ADDRESS_MEMORY_SPACE
==
788 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
790 Descriptor
->Type
= CmResourceTypeMemory
;
791 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
792 Descriptor
->Flags
= CM_RESOURCE_MEMORY_READ_WRITE
; /* FIXME Just a guess */
793 Descriptor
->u
.Memory
.Start
.QuadPart
= (PciConfig
.u
.type0
.BaseAddresses
[Address
] & PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
794 Descriptor
->u
.Memory
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
796 else if (PCI_ADDRESS_IO_SPACE
==
797 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
799 Descriptor
->Type
= CmResourceTypePort
;
800 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
801 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
; /* FIXME Just a guess */
802 Descriptor
->u
.Port
.Start
.QuadPart
= PciConfig
.u
.type0
.BaseAddresses
[Address
] &= PCI_ADDRESS_IO_ADDRESS_MASK
;
803 Descriptor
->u
.Port
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_IO_ADDRESS_MASK
& 0xffff);
808 return STATUS_UNSUCCESSFUL
;
814 if (0 != PciConfig
.u
.type0
.InterruptPin
&&
815 0 != PciConfig
.u
.type0
.InterruptLine
&&
816 0xFF != PciConfig
.u
.type0
.InterruptLine
)
818 Descriptor
->Type
= CmResourceTypeInterrupt
;
819 Descriptor
->ShareDisposition
= CmResourceShareShared
; /* FIXME Just a guess */
820 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
; /* FIXME Just a guess */
821 Descriptor
->u
.Interrupt
.Level
= PciConfig
.u
.type0
.InterruptLine
;
822 Descriptor
->u
.Interrupt
.Vector
= PciConfig
.u
.type0
.InterruptLine
;
823 Descriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
828 ASSERT(Descriptor
== (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
+ ResourceCount
);
830 /* FIXME: Should store the resources in the registry resource map */
837 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler
,
839 IN PCI_SLOT_NUMBER SlotNumber
,
844 BUS_HANDLER BusHandler
;
846 /* Setup fake PCI Bus handler */
847 RtlCopyMemory(&BusHandler
, &HalpFakePciBusHandler
, sizeof(BUS_HANDLER
));
848 BusHandler
.BusNumber
= BusNumber
;
850 /* Read configuration data */
851 HalpReadPCIConfig(&BusHandler
, SlotNumber
, Buffer
, Offset
, Length
);
857 PPCI_REGISTRY_INFO_INTERNAL
860 HalpQueryPciRegistryInfo(VOID
)
864 OBJECT_ATTRIBUTES ObjectAttributes
;
865 UNICODE_STRING KeyName
, ConfigName
, IdentName
;
866 HANDLE KeyHandle
, BusKeyHandle
, CardListHandle
;
868 UCHAR KeyBuffer
[sizeof(CM_FULL_RESOURCE_DESCRIPTOR
) + 100];
869 PKEY_VALUE_FULL_INFORMATION ValueInfo
= (PVOID
)KeyBuffer
;
870 UCHAR PartialKeyBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
871 sizeof(PCI_CARD_DESCRIPTOR
)];
872 PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo
= (PVOID
)PartialKeyBuffer
;
873 KEY_FULL_INFORMATION KeyInformation
;
876 ULONG i
, ElementCount
;
877 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
878 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
879 PPCI_REGISTRY_INFO PciRegInfo
;
880 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
881 PPCI_CARD_DESCRIPTOR CardDescriptor
;
883 /* Setup the object attributes for the key */
884 RtlInitUnicodeString(&KeyName
,
885 L
"\\Registry\\Machine\\Hardware\\Description\\"
886 L
"System\\MultiFunctionAdapter");
887 InitializeObjectAttributes(&ObjectAttributes
,
889 OBJ_CASE_INSENSITIVE
,
894 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
895 if (!NT_SUCCESS(Status
)) return NULL
;
897 /* Setup the receiving string */
898 KeyName
.Buffer
= NameBuffer
;
899 KeyName
.MaximumLength
= sizeof(NameBuffer
);
901 /* Setup the configuration and identifier key names */
902 RtlInitUnicodeString(&ConfigName
, L
"Configuration Data");
903 RtlInitUnicodeString(&IdentName
, L
"Identifier");
905 /* Keep looping for each ID */
906 for (i
= 0; TRUE
; i
++)
908 /* Setup the key name */
909 RtlIntegerToUnicodeString(i
, 10, &KeyName
);
910 InitializeObjectAttributes(&ObjectAttributes
,
912 OBJ_CASE_INSENSITIVE
,
917 Status
= ZwOpenKey(&BusKeyHandle
, KEY_READ
, &ObjectAttributes
);
918 if (!NT_SUCCESS(Status
))
920 /* None left, fail */
925 /* Read the registry data */
926 Status
= ZwQueryValueKey(BusKeyHandle
,
928 KeyValueFullInformation
,
932 if (!NT_SUCCESS(Status
))
934 /* Failed, try the next one */
935 ZwClose(BusKeyHandle
);
939 /* Get the PCI Tag and validate it */
940 Tag
= (PWSTR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
941 if ((Tag
[0] != L
'P') ||
946 /* Not a valid PCI entry, skip it */
947 ZwClose(BusKeyHandle
);
951 /* Now read our PCI structure */
952 Status
= ZwQueryValueKey(BusKeyHandle
,
954 KeyValueFullInformation
,
958 ZwClose(BusKeyHandle
);
959 if (!NT_SUCCESS(Status
)) continue;
961 /* We read it OK! Get the actual resource descriptors */
962 FullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
963 ((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
964 PartialDescriptor
= (PCM_PARTIAL_RESOURCE_DESCRIPTOR
)
965 ((ULONG_PTR
)FullDescriptor
->
966 PartialResourceList
.PartialDescriptors
);
968 /* Check if this is our PCI Registry Information */
969 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
971 /* It is, stop searching */
979 /* Save the PCI information for later */
980 PciRegInfo
= (PPCI_REGISTRY_INFO
)(PartialDescriptor
+ 1);
982 /* Assume no Card List entries */
985 /* Set up for checking the PCI Card List key */
986 RtlInitUnicodeString(&KeyName
,
987 L
"\\Registry\\Machine\\System\\CurrentControlSet\\"
988 L
"Control\\PnP\\PCI\\CardList");
989 InitializeObjectAttributes(&ObjectAttributes
,
991 OBJ_CASE_INSENSITIVE
,
995 /* Attempt to open it */
996 Status
= ZwOpenKey(&CardListHandle
, KEY_READ
, &ObjectAttributes
);
997 if (NT_SUCCESS(Status
))
999 /* It exists, so let's query it */
1000 Status
= ZwQueryKey(CardListHandle
,
1003 sizeof(KEY_FULL_INFORMATION
),
1005 if (!NT_SUCCESS(Status
))
1007 /* Failed to query, so no info */
1008 PciRegistryInfo
= NULL
;
1012 /* Allocate the full structure */
1014 ExAllocatePoolWithTag(NonPagedPool
,
1015 sizeof(PCI_REGISTRY_INFO_INTERNAL
) +
1016 (KeyInformation
.Values
*
1017 sizeof(PCI_CARD_DESCRIPTOR
)),
1019 if (PciRegistryInfo
)
1021 /* Get the first card descriptor entry */
1022 CardDescriptor
= (PPCI_CARD_DESCRIPTOR
)(PciRegistryInfo
+ 1);
1024 /* Loop all the values */
1025 for (i
= 0; i
< KeyInformation
.Values
; i
++)
1027 /* Attempt to get the value */
1028 Status
= ZwEnumerateValueKey(CardListHandle
,
1030 KeyValuePartialInformation
,
1032 sizeof(PartialKeyBuffer
),
1034 if (!NT_SUCCESS(Status
))
1036 /* Something went wrong, stop the search */
1040 /* Make sure it is correctly sized */
1041 if (PartialValueInfo
->DataLength
== sizeof(PCI_CARD_DESCRIPTOR
))
1043 /* Sure is, copy it over */
1044 *CardDescriptor
= *(PPCI_CARD_DESCRIPTOR
)
1045 PartialValueInfo
->Data
;
1047 /* One more Card List entry */
1050 /* Move to the next descriptor */
1051 CardDescriptor
= (CardDescriptor
+ 1);
1057 /* Close the Card List key */
1058 ZwClose(CardListHandle
);
1062 /* No key, no Card List */
1063 PciRegistryInfo
= NULL
;
1066 /* Check if we failed to get the full structure */
1067 if (!PciRegistryInfo
)
1069 /* Just allocate the basic structure then */
1070 PciRegistryInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1071 sizeof(PCI_REGISTRY_INFO_INTERNAL
),
1073 if (!PciRegistryInfo
) return NULL
;
1076 /* Save the info we got */
1077 PciRegistryInfo
->MajorRevision
= PciRegInfo
->MajorRevision
;
1078 PciRegistryInfo
->MinorRevision
= PciRegInfo
->MinorRevision
;
1079 PciRegistryInfo
->NoBuses
= PciRegInfo
->NoBuses
;
1080 PciRegistryInfo
->HardwareMechanism
= PciRegInfo
->HardwareMechanism
;
1081 PciRegistryInfo
->ElementCount
= ElementCount
;
1084 return PciRegistryInfo
;
1093 HalpInitializePciStubs(VOID
)
1095 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
1097 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)HalpFakePciBusHandler
.BusData
;
1101 ULONG MaxPciBusNumber
;
1103 /* Query registry information */
1104 PciRegistryInfo
= HalpQueryPciRegistryInfo();
1105 if (!PciRegistryInfo
)
1110 /* Force a manual bus scan later */
1111 MaxPciBusNumber
= MAXULONG
;
1115 /* Get the PCI type */
1116 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
1118 /* Get MaxPciBusNumber and make it 0-based */
1119 MaxPciBusNumber
= PciRegistryInfo
->NoBuses
- 1;
1121 /* Free the info structure */
1122 ExFreePoolWithTag(PciRegistryInfo
, TAG_HAL
);
1125 /* Initialize the PCI lock */
1126 KeInitializeSpinLock(&HalpPCIConfigLock
);
1128 /* Check the type of PCI bus */
1131 /* Type 1 PCI Bus */
1134 /* Copy the Type 1 handler data */
1135 RtlCopyMemory(&PCIConfigHandler
,
1136 &PCIConfigHandlerType1
,
1137 sizeof(PCIConfigHandler
));
1139 /* Set correct I/O Ports */
1140 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
1141 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
1144 /* Type 2 PCI Bus */
1147 /* Copy the Type 2 handler data */
1148 RtlCopyMemory(&PCIConfigHandler
,
1149 &PCIConfigHandlerType2
,
1150 sizeof (PCIConfigHandler
));
1152 /* Set correct I/O Ports */
1153 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
1154 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
1155 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
1157 /* Only 16 devices supported, not 32 */
1158 BusData
->MaxDevice
= 16;
1164 DbgPrint("HAL: Unknown PCI type\n");
1167 /* Run a forced bus scan if needed */
1168 if (MaxPciBusNumber
== MAXULONG
)
1170 /* Initialize the max bus number to 0xFF */
1171 HalpMaxPciBus
= 0xFF;
1173 /* Initialize the counter */
1174 MaxPciBusNumber
= 0;
1176 /* Loop all possible buses */
1177 for (i
= 0; i
< HalpMaxPciBus
; i
++)
1179 /* Loop all devices */
1180 for (j
.u
.AsULONG
= 0; j
.u
.AsULONG
< BusData
->MaxDevice
; j
.u
.AsULONG
++)
1182 /* Query the interface */
1183 if (HaliPciInterfaceReadConfig(NULL
,
1190 /* Validate the vendor ID */
1191 if ((USHORT
)VendorId
!= PCI_INVALID_VENDORID
)
1193 /* Set this as the maximum ID */
1194 MaxPciBusNumber
= i
;
1202 /* Set the real max bus number */
1203 HalpMaxPciBus
= MaxPciBusNumber
;
1206 HalpPCIConfigInitialized
= TRUE
;