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 *******************************************************************/
19 PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice
[2] = {{{{0}}}};
21 BOOLEAN HalpPCIConfigInitialized
;
22 ULONG HalpMinPciBus
, HalpMaxPciBus
;
23 KSPIN_LOCK HalpPCIConfigLock
;
24 PCI_CONFIG_HANDLER PCIConfigHandler
;
26 /* PCI Operation Matrix */
27 UCHAR PCIDeref
[4][4] =
29 {0, 1, 2, 2}, // ULONG-aligned offset
30 {1, 1, 1, 1}, // UCHAR-aligned offset
31 {2, 1, 2, 2}, // USHORT-aligned offset
32 {1, 1, 1, 1} // UCHAR-aligned offset
36 PCI_CONFIG_HANDLER PCIConfigHandlerType1
=
39 (FncSync
)HalpPCISynchronizeType1
,
40 (FncReleaseSync
)HalpPCIReleaseSynchronzationType1
,
44 (FncConfigIO
)HalpPCIReadUlongType1
,
45 (FncConfigIO
)HalpPCIReadUcharType1
,
46 (FncConfigIO
)HalpPCIReadUshortType1
51 (FncConfigIO
)HalpPCIWriteUlongType1
,
52 (FncConfigIO
)HalpPCIWriteUcharType1
,
53 (FncConfigIO
)HalpPCIWriteUshortType1
58 PCI_CONFIG_HANDLER PCIConfigHandlerType2
=
61 (FncSync
)HalpPCISynchronizeType2
,
62 (FncReleaseSync
)HalpPCIReleaseSynchronizationType2
,
66 (FncConfigIO
)HalpPCIReadUlongType2
,
67 (FncConfigIO
)HalpPCIReadUcharType2
,
68 (FncConfigIO
)HalpPCIReadUshortType2
73 (FncConfigIO
)HalpPCIWriteUlongType2
,
74 (FncConfigIO
)HalpPCIWriteUcharType2
,
75 (FncConfigIO
)HalpPCIWriteUshortType2
79 PCIPBUSDATA HalpFakePciBusData
=
95 BUS_HANDLER HalpFakePciBusHandler
=
107 (PGETSETBUSDATA
)HalpGetPCIData
,
108 (PGETSETBUSDATA
)HalpSetPCIData
,
110 HalpAssignPCISlotResources
,
115 /* TYPE 1 FUNCTIONS **********************************************************/
119 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler
,
120 IN PCI_SLOT_NUMBER Slot
,
122 IN PPCI_TYPE1_CFG_BITS PciCfg1
)
124 /* Setup the PCI Configuration Register */
125 PciCfg1
->u
.AsULONG
= 0;
126 PciCfg1
->u
.bits
.BusNumber
= BusHandler
->BusNumber
;
127 PciCfg1
->u
.bits
.DeviceNumber
= Slot
.u
.bits
.DeviceNumber
;
128 PciCfg1
->u
.bits
.FunctionNumber
= Slot
.u
.bits
.FunctionNumber
;
129 PciCfg1
->u
.bits
.Enable
= TRUE
;
131 /* Acquire the lock */
132 KeRaiseIrql(HIGH_LEVEL
, Irql
);
133 KiAcquireSpinLock(&HalpPCIConfigLock
);
138 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler
,
141 PCI_TYPE1_CFG_BITS PciCfg1
;
143 /* Clear the PCI Configuration Register */
144 PciCfg1
.u
.AsULONG
= 0;
145 WRITE_PORT_ULONG(((PPCIPBUSDATA
)BusHandler
->BusData
)->Config
.Type1
.Address
,
148 /* Release the lock */
149 KiReleaseSpinLock(&HalpPCIConfigLock
);
153 TYPE1_READ(HalpPCIReadUcharType1
, UCHAR
)
154 TYPE1_READ(HalpPCIReadUshortType1
, USHORT
)
155 TYPE1_READ(HalpPCIReadUlongType1
, ULONG
)
156 TYPE1_WRITE(HalpPCIWriteUcharType1
, UCHAR
)
157 TYPE1_WRITE(HalpPCIWriteUshortType1
, USHORT
)
158 TYPE1_WRITE(HalpPCIWriteUlongType1
, ULONG
)
160 /* TYPE 2 FUNCTIONS **********************************************************/
164 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler
,
165 IN PCI_SLOT_NUMBER Slot
,
167 IN PPCI_TYPE2_ADDRESS_BITS PciCfg
)
169 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
170 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
172 /* Setup the configuration register */
173 PciCfg
->u
.AsUSHORT
= 0;
174 PciCfg
->u
.bits
.Agent
= (USHORT
)Slot
.u
.bits
.DeviceNumber
;
175 PciCfg
->u
.bits
.AddressBase
= (USHORT
)BusData
->Config
.Type2
.Base
;
177 /* Acquire the lock */
178 KeRaiseIrql(HIGH_LEVEL
, Irql
);
179 KiAcquireSpinLock(&HalpPCIConfigLock
);
181 /* Setup the CSE Register */
182 PciCfg2Cse
.u
.AsUCHAR
= 0;
183 PciCfg2Cse
.u
.bits
.Enable
= TRUE
;
184 PciCfg2Cse
.u
.bits
.FunctionNumber
= (UCHAR
)Slot
.u
.bits
.FunctionNumber
;
185 PciCfg2Cse
.u
.bits
.Key
= -1;
187 /* Write the bus number and CSE */
188 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
,
189 (UCHAR
)BusHandler
->BusNumber
);
190 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
195 HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler
,
198 PCI_TYPE2_CSE_BITS PciCfg2Cse
;
199 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
201 /* Clear CSE and bus number */
202 PciCfg2Cse
.u
.AsUCHAR
= 0;
203 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.CSE
, PciCfg2Cse
.u
.AsUCHAR
);
204 WRITE_PORT_UCHAR(BusData
->Config
.Type2
.Forward
, 0);
206 /* Release the lock */
207 KiReleaseSpinLock(&HalpPCIConfigLock
);
211 TYPE2_READ(HalpPCIReadUcharType2
, UCHAR
)
212 TYPE2_READ(HalpPCIReadUshortType2
, USHORT
)
213 TYPE2_READ(HalpPCIReadUlongType2
, ULONG
)
214 TYPE2_WRITE(HalpPCIWriteUcharType2
, UCHAR
)
215 TYPE2_WRITE(HalpPCIWriteUshortType2
, USHORT
)
216 TYPE2_WRITE(HalpPCIWriteUlongType2
, ULONG
)
218 /* PCI CONFIGURATION SPACE ***************************************************/
222 HalpPCIConfig(IN PBUS_HANDLER BusHandler
,
223 IN PCI_SLOT_NUMBER Slot
,
227 IN FncConfigIO
*ConfigIO
)
233 /* Synchronize the operation */
234 PCIConfigHandler
.Synchronize(BusHandler
, Slot
, &OldIrql
, State
);
236 /* Loop every increment */
239 /* Find out the type of read/write we need to do */
240 i
= PCIDeref
[Offset
% sizeof(ULONG
)][Length
% sizeof(ULONG
)];
242 /* Do the read/write and return the number of bytes */
243 i
= ConfigIO
[i
]((PPCIPBUSDATA
)BusHandler
->BusData
,
248 /* Increment the buffer position and offset, and decrease the length */
254 /* Release the lock and PCI bus */
255 PCIConfigHandler
.ReleaseSynchronzation(BusHandler
, OldIrql
);
260 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler
,
261 IN PCI_SLOT_NUMBER Slot
,
266 /* Validate the PCI Slot */
267 if (!HalpValidPCISlot(BusHandler
, Slot
))
269 /* Fill the buffer with invalid data */
270 RtlFillMemory(Buffer
, Length
, -1);
274 /* Send the request */
275 HalpPCIConfig(BusHandler
,
280 PCIConfigHandler
.ConfigRead
);
286 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler
,
287 IN PCI_SLOT_NUMBER Slot
,
292 /* Validate the PCI Slot */
293 if (HalpValidPCISlot(BusHandler
, Slot
))
295 /* Send the request */
296 HalpPCIConfig(BusHandler
,
301 PCIConfigHandler
.ConfigWrite
);
307 HalpValidPCISlot(IN PBUS_HANDLER BusHandler
,
308 IN PCI_SLOT_NUMBER Slot
)
310 PCI_SLOT_NUMBER MultiSlot
;
311 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)BusHandler
->BusData
;
315 /* Simple validation */
316 if (Slot
.u
.bits
.Reserved
) return FALSE
;
317 if (Slot
.u
.bits
.DeviceNumber
>= BusData
->MaxDevice
) return FALSE
;
319 /* Function 0 doesn't need checking */
320 if (!Slot
.u
.bits
.FunctionNumber
) return TRUE
;
322 /* Functions 0+ need Multi-Function support, so check the slot */
323 Device
= Slot
.u
.bits
.DeviceNumber
;
325 MultiSlot
.u
.bits
.FunctionNumber
= 0;
327 /* Send function 0 request to get the header back */
328 HalpReadPCIConfig(BusHandler
,
331 FIELD_OFFSET(PCI_COMMON_CONFIG
, HeaderType
),
334 /* Now make sure the header is multi-function */
335 if (!(HeaderType
& PCI_MULTIFUNCTION
) || (HeaderType
== 0xFF)) return FALSE
;
339 /* HAL PCI CALLBACKS *********************************************************/
343 HalpGetPCIData(IN PBUS_HANDLER BusHandler
,
344 IN PBUS_HANDLER RootHandler
,
345 IN PCI_SLOT_NUMBER Slot
,
350 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
351 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
355 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
356 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
357 * video card, so it appears to be present on 1:0:0 - 1:31:0.
358 * We hack around these problems by indicating "device not present" for devices
359 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
360 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
361 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
362 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
364 DPRINT("Blacklisted PCI slot\n");
365 if (0 == Offset
&& sizeof(USHORT
) <= Length
)
367 *(PUSHORT
)Buffer
= PCI_INVALID_VENDORID
;
368 return sizeof(USHORT
);
374 /* Normalize the length */
375 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
377 /* Check if this is a vendor-specific read */
378 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
380 /* Read the header */
381 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
383 /* Make sure the vendor is valid */
384 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
388 /* Read the entire header */
389 Len
= PCI_COMMON_HDR_LENGTH
;
390 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
392 /* Validate the vendor ID */
393 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
)
395 /* It's invalid, but we want to return this much */
396 Len
= sizeof(USHORT
);
399 /* Now check if there's space left */
400 if (Len
< Offset
) return 0;
402 /* There is, so return what's after the offset and normalize */
404 if (Len
> Length
) Len
= Length
;
406 /* Copy the data into the caller's buffer */
407 RtlMoveMemory(Buffer
, PciBuffer
+ Offset
, Len
);
409 /* Update buffer and offset, decrement total length */
411 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Len
);
415 /* Now we still have something to copy */
418 /* Check if it's vendor-specific data */
419 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
422 HalpReadPCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
427 /* Update the total length read */
433 HalpSetPCIData(IN PBUS_HANDLER BusHandler
,
434 IN PBUS_HANDLER RootHandler
,
435 IN PCI_SLOT_NUMBER Slot
,
440 UCHAR PciBuffer
[PCI_COMMON_HDR_LENGTH
];
441 PPCI_COMMON_CONFIG PciConfig
= (PPCI_COMMON_CONFIG
)PciBuffer
;
445 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
446 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
447 * video card, so it appears to be present on 1:0:0 - 1:31:0.
448 * We hack around these problems by indicating "device not present" for devices
449 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
450 if ((0 == BusHandler
->BusNumber
&& 0 == Slot
.u
.bits
.DeviceNumber
&&
451 (1 == Slot
.u
.bits
.FunctionNumber
|| 2 == Slot
.u
.bits
.FunctionNumber
)) ||
452 (1 == BusHandler
->BusNumber
&& 0 != Slot
.u
.bits
.DeviceNumber
))
454 DPRINT1("Trying to set data on blacklisted PCI slot\n");
459 /* Normalize the length */
460 if (Length
> sizeof(PCI_COMMON_CONFIG
)) Length
= sizeof(PCI_COMMON_CONFIG
);
462 /* Check if this is a vendor-specific read */
463 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
465 /* Read the header */
466 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, sizeof(ULONG
));
468 /* Make sure the vendor is valid */
469 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
473 /* Read the entire header and validate the vendor ID */
474 Len
= PCI_COMMON_HDR_LENGTH
;
475 HalpReadPCIConfig(BusHandler
, Slot
, PciConfig
, 0, Len
);
476 if (PciConfig
->VendorID
== PCI_INVALID_VENDORID
) return 0;
478 /* Return what's after the offset and normalize */
480 if (Len
> Length
) Len
= Length
;
482 /* Copy the specific caller data */
483 RtlMoveMemory(PciBuffer
+ Offset
, Buffer
, Len
);
485 /* Write the actual configuration data */
486 HalpWritePCIConfig(BusHandler
, Slot
, PciBuffer
+ Offset
, Offset
, Len
);
488 /* Update buffer and offset, decrement total length */
490 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ Len
);
494 /* Now we still have something to copy */
497 /* Check if it's vendor-specific data */
498 if (Offset
>= PCI_COMMON_HDR_LENGTH
)
501 HalpWritePCIConfig(BusHandler
, Slot
, Buffer
, Offset
, Length
);
506 /* Update the total length read */
512 HalpGetPCIIntOnISABus(IN PBUS_HANDLER BusHandler
,
513 IN PBUS_HANDLER RootHandler
,
514 IN ULONG BusInterruptLevel
,
515 IN ULONG BusInterruptVector
,
517 OUT PKAFFINITY Affinity
)
526 HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler
,
527 IN PBUS_HANDLER RootHandler
,
528 IN PCI_SLOT_NUMBER SlotNumber
,
529 IN PPCI_COMMON_CONFIG PciData
)
537 HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler
,
538 IN PBUS_HANDLER RootHandler
,
539 IN PCI_SLOT_NUMBER SlotNumber
,
540 IN PPCI_COMMON_CONFIG PciNewData
,
541 IN PPCI_COMMON_CONFIG PciOldData
)
549 HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler
,
550 IN PBUS_HANDLER RootHandler
,
551 IN PCI_SLOT_NUMBER PciSlot
,
552 OUT PSUPPORTED_RANGE
*Range
)
556 return STATUS_SUCCESS
;
561 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock
,
562 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
564 DPRINT1("Unimplemented!\n");
565 return STATUS_NOT_IMPLEMENTED
;
570 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
572 DPRINT1("Unimplemented!\n");
573 return STATUS_NOT_IMPLEMENTED
;
578 HalpRegisterPciDebuggingDeviceInfo(VOID
)
580 BOOLEAN Found
= FALSE
;
584 /* Loop PCI debugging devices */
585 for (i
= 0; i
< 2; i
++)
587 /* Reserved bit is set if we found one */
588 if (HalpPciDebuggingDevice
[i
].u
.bits
.Reserved1
)
595 /* Bail out if there aren't any */
599 DPRINT1("You have implemented the KD routines for searching PCI debugger"
600 "devices, but you have forgotten to implement this routine\n");
605 PciSize(ULONG Base
, ULONG Mask
)
607 ULONG Size
= Mask
& Base
; /* Find the significant bits */
608 Size
= Size
& ~(Size
- 1); /* Get the lowest of them to find the decode size */
614 HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler
,
615 IN PBUS_HANDLER RootHandler
,
616 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST
*pResourceList
)
618 /* Not yet supported */
619 DbgPrint("HAL: PCI Resource List Adjustment not implemented!");
621 return STATUS_UNSUCCESSFUL
;
626 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler
,
627 IN PBUS_HANDLER RootHandler
,
628 IN PUNICODE_STRING RegistryPath
,
629 IN PUNICODE_STRING DriverClassName OPTIONAL
,
630 IN PDRIVER_OBJECT DriverObject
,
631 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
633 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
635 PCI_COMMON_CONFIG PciConfig
;
637 SIZE_T ResourceCount
;
638 ULONG Size
[PCI_TYPE0_ADDRESSES
];
639 NTSTATUS Status
= STATUS_SUCCESS
;
641 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
642 PCI_SLOT_NUMBER SlotNumber
;
645 /* FIXME: Should handle 64-bit addresses */
647 /* Read configuration data */
648 SlotNumber
.u
.AsULONG
= Slot
;
649 HalpReadPCIConfig(BusHandler
, SlotNumber
, &PciConfig
, 0, PCI_COMMON_HDR_LENGTH
);
651 /* Check if we read it correctly */
652 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
653 return STATUS_NO_SUCH_DEVICE
;
655 /* Read the PCI configuration space for the device and store base address and
656 size information in temporary storage. Count the number of valid base addresses */
658 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
660 if (0xffffffff == PciConfig
.u
.type0
.BaseAddresses
[Address
])
661 PciConfig
.u
.type0
.BaseAddresses
[Address
] = 0;
663 /* Memory resource */
664 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
668 Offset
= (UCHAR
)FIELD_OFFSET(PCI_COMMON_CONFIG
, u
.type0
.BaseAddresses
[Address
]);
670 /* Write 0xFFFFFFFF there */
671 WriteBuffer
= 0xffffffff;
672 HalpWritePCIConfig(BusHandler
, SlotNumber
, &WriteBuffer
, Offset
, sizeof(ULONG
));
674 /* Read that figure back from the config space */
675 HalpReadPCIConfig(BusHandler
, SlotNumber
, &Size
[Address
], Offset
, sizeof(ULONG
));
677 /* Write back initial value */
678 HalpWritePCIConfig(BusHandler
, SlotNumber
, &PciConfig
.u
.type0
.BaseAddresses
[Address
], Offset
, sizeof(ULONG
));
682 /* Interrupt resource */
683 if (0 != PciConfig
.u
.type0
.InterruptLine
)
686 /* Allocate output buffer and initialize */
687 *AllocatedResources
= ExAllocatePoolWithTag(
689 sizeof(CM_RESOURCE_LIST
) +
690 (ResourceCount
- 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
693 if (NULL
== *AllocatedResources
)
694 return STATUS_NO_MEMORY
;
696 (*AllocatedResources
)->Count
= 1;
697 (*AllocatedResources
)->List
[0].InterfaceType
= PCIBus
;
698 (*AllocatedResources
)->List
[0].BusNumber
= BusHandler
->BusNumber
;
699 (*AllocatedResources
)->List
[0].PartialResourceList
.Version
= 1;
700 (*AllocatedResources
)->List
[0].PartialResourceList
.Revision
= 1;
701 (*AllocatedResources
)->List
[0].PartialResourceList
.Count
= ResourceCount
;
702 Descriptor
= (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
;
704 /* Store configuration information */
705 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
707 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
709 if (PCI_ADDRESS_MEMORY_SPACE
==
710 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
712 Descriptor
->Type
= CmResourceTypeMemory
;
713 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
714 Descriptor
->Flags
= CM_RESOURCE_MEMORY_READ_WRITE
; /* FIXME Just a guess */
715 Descriptor
->u
.Memory
.Start
.QuadPart
= (PciConfig
.u
.type0
.BaseAddresses
[Address
] & PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
716 Descriptor
->u
.Memory
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
718 else if (PCI_ADDRESS_IO_SPACE
==
719 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
721 Descriptor
->Type
= CmResourceTypePort
;
722 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
723 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
; /* FIXME Just a guess */
724 Descriptor
->u
.Port
.Start
.QuadPart
= PciConfig
.u
.type0
.BaseAddresses
[Address
] &= PCI_ADDRESS_IO_ADDRESS_MASK
;
725 Descriptor
->u
.Port
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_IO_ADDRESS_MASK
& 0xffff);
730 return STATUS_UNSUCCESSFUL
;
736 if (0 != PciConfig
.u
.type0
.InterruptLine
)
738 Descriptor
->Type
= CmResourceTypeInterrupt
;
739 Descriptor
->ShareDisposition
= CmResourceShareShared
; /* FIXME Just a guess */
740 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
; /* FIXME Just a guess */
741 Descriptor
->u
.Interrupt
.Level
= PciConfig
.u
.type0
.InterruptLine
;
742 Descriptor
->u
.Interrupt
.Vector
= PciConfig
.u
.type0
.InterruptLine
;
743 Descriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
748 ASSERT(Descriptor
== (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
+ ResourceCount
);
750 /* FIXME: Should store the resources in the registry resource map */
757 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler
,
759 IN PCI_SLOT_NUMBER SlotNumber
,
764 BUS_HANDLER BusHandler
;
766 /* Setup fake PCI Bus handler */
767 RtlCopyMemory(&BusHandler
, &HalpFakePciBusHandler
, sizeof(BUS_HANDLER
));
768 BusHandler
.BusNumber
= BusNumber
;
770 /* Read configuration data */
771 HalpReadPCIConfig(&BusHandler
, SlotNumber
, Buffer
, Offset
, Length
);
777 PPCI_REGISTRY_INFO_INTERNAL
779 HalpQueryPciRegistryInfo(VOID
)
783 OBJECT_ATTRIBUTES ObjectAttributes
;
784 UNICODE_STRING KeyName
, ConfigName
, IdentName
;
785 HANDLE KeyHandle
, BusKeyHandle
, CardListHandle
;
787 UCHAR KeyBuffer
[sizeof(CM_FULL_RESOURCE_DESCRIPTOR
) + 100];
788 PKEY_VALUE_FULL_INFORMATION ValueInfo
= (PVOID
)KeyBuffer
;
789 UCHAR PartialKeyBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
790 sizeof(PCI_CARD_DESCRIPTOR
)];
791 PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo
= (PVOID
)PartialKeyBuffer
;
792 KEY_FULL_INFORMATION KeyInformation
;
795 ULONG i
, ElementCount
;
796 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
797 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
798 PPCI_REGISTRY_INFO PciRegInfo
;
799 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
800 PPCI_CARD_DESCRIPTOR CardDescriptor
;
802 /* Setup the object attributes for the key */
803 RtlInitUnicodeString(&KeyName
,
804 L
"\\Registry\\Machine\\Hardware\\Description\\"
805 L
"System\\MultiFunctionAdapter");
806 InitializeObjectAttributes(&ObjectAttributes
,
808 OBJ_CASE_INSENSITIVE
,
813 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
814 if (!NT_SUCCESS(Status
)) return NULL
;
816 /* Setup the receiving string */
817 KeyName
.Buffer
= NameBuffer
;
818 KeyName
.MaximumLength
= sizeof(NameBuffer
);
820 /* Setup the configuration and identifier key names */
821 RtlInitUnicodeString(&ConfigName
, L
"Configuration Data");
822 RtlInitUnicodeString(&IdentName
, L
"Identifier");
824 /* Keep looping for each ID */
825 for (i
= 0; TRUE
; i
++)
827 /* Setup the key name */
828 RtlIntegerToUnicodeString(i
, 10, &KeyName
);
829 InitializeObjectAttributes(&ObjectAttributes
,
831 OBJ_CASE_INSENSITIVE
,
836 Status
= ZwOpenKey(&BusKeyHandle
, KEY_READ
, &ObjectAttributes
);
837 if (!NT_SUCCESS(Status
))
839 /* None left, fail */
844 /* Read the registry data */
845 Status
= ZwQueryValueKey(BusKeyHandle
,
847 KeyValueFullInformation
,
851 if (!NT_SUCCESS(Status
))
853 /* Failed, try the next one */
854 ZwClose(BusKeyHandle
);
858 /* Get the PCI Tag and validate it */
859 Tag
= (PWSTR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
860 if ((Tag
[0] != L
'P') ||
865 /* Not a valid PCI entry, skip it */
866 ZwClose(BusKeyHandle
);
870 /* Now read our PCI structure */
871 Status
= ZwQueryValueKey(BusKeyHandle
,
873 KeyValueFullInformation
,
877 ZwClose(BusKeyHandle
);
878 if (!NT_SUCCESS(Status
)) continue;
880 /* We read it OK! Get the actual resource descriptors */
881 FullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
882 ((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
883 PartialDescriptor
= (PCM_PARTIAL_RESOURCE_DESCRIPTOR
)
884 ((ULONG_PTR
)FullDescriptor
->
885 PartialResourceList
.PartialDescriptors
);
887 /* Check if this is our PCI Registry Information */
888 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
890 /* It is, stop searching */
898 /* Save the PCI information for later */
899 PciRegInfo
= (PPCI_REGISTRY_INFO
)(PartialDescriptor
+ 1);
901 /* Assume no Card List entries */
904 /* Set up for checking the PCI Card List key */
905 RtlInitUnicodeString(&KeyName
,
906 L
"\\Registry\\Machine\\System\\CurrentControlSet\\"
907 L
"Control\\PnP\\PCI\\CardList");
908 InitializeObjectAttributes(&ObjectAttributes
,
910 OBJ_CASE_INSENSITIVE
,
914 /* Attempt to open it */
915 Status
= ZwOpenKey(&CardListHandle
, KEY_READ
, &ObjectAttributes
);
916 if (NT_SUCCESS(Status
))
918 /* It exists, so let's query it */
919 Status
= ZwQueryKey(CardListHandle
,
922 sizeof(KEY_FULL_INFORMATION
),
924 if (!NT_SUCCESS(Status
))
926 /* Failed to query, so no info */
927 PciRegistryInfo
= NULL
;
931 /* Allocate the full structure */
933 ExAllocatePoolWithTag(NonPagedPool
,
934 sizeof(PCI_REGISTRY_INFO_INTERNAL
) +
935 (KeyInformation
.Values
*
936 sizeof(PCI_CARD_DESCRIPTOR
)),
940 /* Get the first card descriptor entry */
941 CardDescriptor
= (PPCI_CARD_DESCRIPTOR
)(PciRegistryInfo
+ 1);
943 /* Loop all the values */
944 for (i
= 0; i
< KeyInformation
.Values
; i
++)
946 /* Attempt to get the value */
947 Status
= ZwEnumerateValueKey(CardListHandle
,
949 KeyValuePartialInformation
,
951 sizeof(PartialKeyBuffer
),
953 if (!NT_SUCCESS(Status
))
955 /* Something went wrong, stop the search */
959 /* Make sure it is correctly sized */
960 if (PartialValueInfo
->DataLength
== sizeof(PCI_CARD_DESCRIPTOR
))
962 /* Sure is, copy it over */
963 *CardDescriptor
= *(PPCI_CARD_DESCRIPTOR
)
964 PartialValueInfo
->Data
;
966 /* One more Card List entry */
969 /* Move to the next descriptor */
970 CardDescriptor
= (CardDescriptor
+ 1);
976 /* Close the Card List key */
977 ZwClose(CardListHandle
);
981 /* No key, no Card List */
982 PciRegistryInfo
= NULL
;
985 /* Check if we failed to get the full structure */
986 if (!PciRegistryInfo
)
988 /* Just allocate the basic structure then */
989 PciRegistryInfo
= ExAllocatePoolWithTag(NonPagedPool
,
990 sizeof(PCI_REGISTRY_INFO_INTERNAL
),
992 if (!PciRegistryInfo
) return NULL
;
995 /* Save the info we got */
996 PciRegistryInfo
->MajorRevision
= PciRegInfo
->MajorRevision
;
997 PciRegistryInfo
->MinorRevision
= PciRegInfo
->MinorRevision
;
998 PciRegistryInfo
->NoBuses
= PciRegInfo
->NoBuses
;
999 PciRegistryInfo
->HardwareMechanism
= PciRegInfo
->HardwareMechanism
;
1000 PciRegistryInfo
->ElementCount
= ElementCount
;
1003 return PciRegistryInfo
;
1011 HalpInitializePciStubs(VOID
)
1013 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
1015 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)HalpFakePciBusHandler
.BusData
;
1019 ULONG MaxPciBusNumber
;
1021 /* Query registry information */
1022 PciRegistryInfo
= HalpQueryPciRegistryInfo();
1023 if (!PciRegistryInfo
)
1028 /* Force a manual bus scan later */
1029 MaxPciBusNumber
= MAXULONG
;
1033 /* Get the PCI type */
1034 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
1036 /* Get MaxPciBusNumber and make it 0-based */
1037 MaxPciBusNumber
= PciRegistryInfo
->NoBuses
- 1;
1039 /* Free the info structure */
1040 ExFreePool(PciRegistryInfo
);
1043 /* Initialize the PCI lock */
1044 KeInitializeSpinLock(&HalpPCIConfigLock
);
1046 /* Check the type of PCI bus */
1049 /* Type 1 PCI Bus */
1052 /* Copy the Type 1 handler data */
1053 RtlCopyMemory(&PCIConfigHandler
,
1054 &PCIConfigHandlerType1
,
1055 sizeof(PCIConfigHandler
));
1057 /* Set correct I/O Ports */
1058 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
1059 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
1062 /* Type 2 PCI Bus */
1065 /* Copy the Type 2 handler data */
1066 RtlCopyMemory(&PCIConfigHandler
,
1067 &PCIConfigHandlerType2
,
1068 sizeof (PCIConfigHandler
));
1070 /* Set correct I/O Ports */
1071 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
1072 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
1073 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
1075 /* Only 16 devices supported, not 32 */
1076 BusData
->MaxDevice
= 16;
1082 DbgPrint("HAL: Unknown PCI type\n");
1085 /* Run a forced bus scan if needed */
1086 if (MaxPciBusNumber
== MAXULONG
)
1088 /* Initialize the max bus number to 0xFF */
1089 HalpMaxPciBus
= 0xFF;
1091 /* Initialize the counter */
1092 MaxPciBusNumber
= 0;
1094 /* Loop all possible buses */
1095 for (i
= 0; i
< HalpMaxPciBus
; i
++)
1097 /* Loop all devices */
1098 for (j
.u
.AsULONG
= 0; j
.u
.AsULONG
< BusData
->MaxDevice
; j
.u
.AsULONG
++)
1100 /* Query the interface */
1101 if (HaliPciInterfaceReadConfig(NULL
,
1108 /* Validate the vendor ID */
1109 if ((USHORT
)VendorId
!= PCI_INVALID_VENDORID
)
1111 /* Set this as the maximum ID */
1112 MaxPciBusNumber
= i
;
1120 /* Set the real max bus number */
1121 HalpMaxPciBus
= MaxPciBusNumber
;
1124 HalpPCIConfigInitialized
= TRUE
;