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
)
519 /* Validate the level first */
520 if (BusInterruptLevel
< 1) return 0;
522 /* PCI has its IRQs on top of ISA IRQs, so pass it on to the ISA handler */
523 return HalGetInterruptVector(Isa
,
533 HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler
,
534 IN PBUS_HANDLER RootHandler
,
535 IN PCI_SLOT_NUMBER SlotNumber
,
536 IN PPCI_COMMON_CONFIG PciData
)
544 HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler
,
545 IN PBUS_HANDLER RootHandler
,
546 IN PCI_SLOT_NUMBER SlotNumber
,
547 IN PPCI_COMMON_CONFIG PciNewData
,
548 IN PPCI_COMMON_CONFIG PciOldData
)
556 HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler
,
557 IN PBUS_HANDLER RootHandler
,
558 IN PCI_SLOT_NUMBER PciSlot
,
559 OUT PSUPPORTED_RANGE
*Range
)
563 return STATUS_SUCCESS
;
568 HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock
,
569 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
571 DPRINT1("Unimplemented!\n");
572 return STATUS_NOT_IMPLEMENTED
;
577 HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
)
579 DPRINT1("Unimplemented!\n");
580 return STATUS_NOT_IMPLEMENTED
;
585 HalpRegisterPciDebuggingDeviceInfo(VOID
)
587 BOOLEAN Found
= FALSE
;
591 /* Loop PCI debugging devices */
592 for (i
= 0; i
< 2; i
++)
594 /* Reserved bit is set if we found one */
595 if (HalpPciDebuggingDevice
[i
].u
.bits
.Reserved1
)
602 /* Bail out if there aren't any */
606 DPRINT1("You have implemented the KD routines for searching PCI debugger"
607 "devices, but you have forgotten to implement this routine\n");
612 PciSize(ULONG Base
, ULONG Mask
)
614 ULONG Size
= Mask
& Base
; /* Find the significant bits */
615 Size
= Size
& ~(Size
- 1); /* Get the lowest of them to find the decode size */
621 HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler
,
622 IN PBUS_HANDLER RootHandler
,
623 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST
*pResourceList
)
625 /* Not yet supported */
626 DbgPrint("HAL: PCI Resource List Adjustment not implemented!");
628 return STATUS_UNSUCCESSFUL
;
633 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler
,
634 IN PBUS_HANDLER RootHandler
,
635 IN PUNICODE_STRING RegistryPath
,
636 IN PUNICODE_STRING DriverClassName OPTIONAL
,
637 IN PDRIVER_OBJECT DriverObject
,
638 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
640 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
642 PCI_COMMON_CONFIG PciConfig
;
644 SIZE_T ResourceCount
;
645 ULONG Size
[PCI_TYPE0_ADDRESSES
];
646 NTSTATUS Status
= STATUS_SUCCESS
;
648 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
649 PCI_SLOT_NUMBER SlotNumber
;
651 DPRINT1("WARNING: PCI Slot Resource Assignment is FOOBAR\n");
653 /* FIXME: Should handle 64-bit addresses */
655 /* Read configuration data */
656 SlotNumber
.u
.AsULONG
= Slot
;
657 HalpReadPCIConfig(BusHandler
, SlotNumber
, &PciConfig
, 0, PCI_COMMON_HDR_LENGTH
);
659 /* Check if we read it correctly */
660 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
661 return STATUS_NO_SUCH_DEVICE
;
663 /* Read the PCI configuration space for the device and store base address and
664 size information in temporary storage. Count the number of valid base addresses */
666 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
668 if (0xffffffff == PciConfig
.u
.type0
.BaseAddresses
[Address
])
669 PciConfig
.u
.type0
.BaseAddresses
[Address
] = 0;
671 /* Memory resource */
672 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
676 Offset
= (UCHAR
)FIELD_OFFSET(PCI_COMMON_CONFIG
, u
.type0
.BaseAddresses
[Address
]);
678 /* Write 0xFFFFFFFF there */
679 WriteBuffer
= 0xffffffff;
680 HalpWritePCIConfig(BusHandler
, SlotNumber
, &WriteBuffer
, Offset
, sizeof(ULONG
));
682 /* Read that figure back from the config space */
683 HalpReadPCIConfig(BusHandler
, SlotNumber
, &Size
[Address
], Offset
, sizeof(ULONG
));
685 /* Write back initial value */
686 HalpWritePCIConfig(BusHandler
, SlotNumber
, &PciConfig
.u
.type0
.BaseAddresses
[Address
], Offset
, sizeof(ULONG
));
690 /* Interrupt resource */
691 if (0 != PciConfig
.u
.type0
.InterruptLine
)
694 /* Allocate output buffer and initialize */
695 *AllocatedResources
= ExAllocatePoolWithTag(
697 sizeof(CM_RESOURCE_LIST
) +
698 (ResourceCount
- 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
),
701 if (NULL
== *AllocatedResources
)
702 return STATUS_NO_MEMORY
;
704 (*AllocatedResources
)->Count
= 1;
705 (*AllocatedResources
)->List
[0].InterfaceType
= PCIBus
;
706 (*AllocatedResources
)->List
[0].BusNumber
= BusHandler
->BusNumber
;
707 (*AllocatedResources
)->List
[0].PartialResourceList
.Version
= 1;
708 (*AllocatedResources
)->List
[0].PartialResourceList
.Revision
= 1;
709 (*AllocatedResources
)->List
[0].PartialResourceList
.Count
= ResourceCount
;
710 Descriptor
= (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
;
712 /* Store configuration information */
713 for (Address
= 0; Address
< PCI_TYPE0_ADDRESSES
; Address
++)
715 if (0 != PciConfig
.u
.type0
.BaseAddresses
[Address
])
717 if (PCI_ADDRESS_MEMORY_SPACE
==
718 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
720 Descriptor
->Type
= CmResourceTypeMemory
;
721 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
722 Descriptor
->Flags
= CM_RESOURCE_MEMORY_READ_WRITE
; /* FIXME Just a guess */
723 Descriptor
->u
.Memory
.Start
.QuadPart
= (PciConfig
.u
.type0
.BaseAddresses
[Address
] & PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
724 Descriptor
->u
.Memory
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_MEMORY_ADDRESS_MASK
);
726 else if (PCI_ADDRESS_IO_SPACE
==
727 (PciConfig
.u
.type0
.BaseAddresses
[Address
] & 0x1))
729 Descriptor
->Type
= CmResourceTypePort
;
730 Descriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
; /* FIXME I have no idea... */
731 Descriptor
->Flags
= CM_RESOURCE_PORT_IO
; /* FIXME Just a guess */
732 Descriptor
->u
.Port
.Start
.QuadPart
= PciConfig
.u
.type0
.BaseAddresses
[Address
] &= PCI_ADDRESS_IO_ADDRESS_MASK
;
733 Descriptor
->u
.Port
.Length
= PciSize(Size
[Address
], PCI_ADDRESS_IO_ADDRESS_MASK
& 0xffff);
738 return STATUS_UNSUCCESSFUL
;
744 if (0 != PciConfig
.u
.type0
.InterruptLine
)
746 Descriptor
->Type
= CmResourceTypeInterrupt
;
747 Descriptor
->ShareDisposition
= CmResourceShareShared
; /* FIXME Just a guess */
748 Descriptor
->Flags
= CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
; /* FIXME Just a guess */
749 Descriptor
->u
.Interrupt
.Level
= PciConfig
.u
.type0
.InterruptLine
;
750 Descriptor
->u
.Interrupt
.Vector
= PciConfig
.u
.type0
.InterruptLine
;
751 Descriptor
->u
.Interrupt
.Affinity
= 0xFFFFFFFF;
756 ASSERT(Descriptor
== (*AllocatedResources
)->List
[0].PartialResourceList
.PartialDescriptors
+ ResourceCount
);
758 /* FIXME: Should store the resources in the registry resource map */
765 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler
,
767 IN PCI_SLOT_NUMBER SlotNumber
,
772 BUS_HANDLER BusHandler
;
774 /* Setup fake PCI Bus handler */
775 RtlCopyMemory(&BusHandler
, &HalpFakePciBusHandler
, sizeof(BUS_HANDLER
));
776 BusHandler
.BusNumber
= BusNumber
;
778 /* Read configuration data */
779 HalpReadPCIConfig(&BusHandler
, SlotNumber
, Buffer
, Offset
, Length
);
785 PPCI_REGISTRY_INFO_INTERNAL
787 HalpQueryPciRegistryInfo(VOID
)
791 OBJECT_ATTRIBUTES ObjectAttributes
;
792 UNICODE_STRING KeyName
, ConfigName
, IdentName
;
793 HANDLE KeyHandle
, BusKeyHandle
, CardListHandle
;
795 UCHAR KeyBuffer
[sizeof(CM_FULL_RESOURCE_DESCRIPTOR
) + 100];
796 PKEY_VALUE_FULL_INFORMATION ValueInfo
= (PVOID
)KeyBuffer
;
797 UCHAR PartialKeyBuffer
[sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
798 sizeof(PCI_CARD_DESCRIPTOR
)];
799 PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo
= (PVOID
)PartialKeyBuffer
;
800 KEY_FULL_INFORMATION KeyInformation
;
803 ULONG i
, ElementCount
;
804 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
805 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
806 PPCI_REGISTRY_INFO PciRegInfo
;
807 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
808 PPCI_CARD_DESCRIPTOR CardDescriptor
;
810 /* Setup the object attributes for the key */
811 RtlInitUnicodeString(&KeyName
,
812 L
"\\Registry\\Machine\\Hardware\\Description\\"
813 L
"System\\MultiFunctionAdapter");
814 InitializeObjectAttributes(&ObjectAttributes
,
816 OBJ_CASE_INSENSITIVE
,
821 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
822 if (!NT_SUCCESS(Status
)) return NULL
;
824 /* Setup the receiving string */
825 KeyName
.Buffer
= NameBuffer
;
826 KeyName
.MaximumLength
= sizeof(NameBuffer
);
828 /* Setup the configuration and identifier key names */
829 RtlInitUnicodeString(&ConfigName
, L
"Configuration Data");
830 RtlInitUnicodeString(&IdentName
, L
"Identifier");
832 /* Keep looping for each ID */
833 for (i
= 0; TRUE
; i
++)
835 /* Setup the key name */
836 RtlIntegerToUnicodeString(i
, 10, &KeyName
);
837 InitializeObjectAttributes(&ObjectAttributes
,
839 OBJ_CASE_INSENSITIVE
,
844 Status
= ZwOpenKey(&BusKeyHandle
, KEY_READ
, &ObjectAttributes
);
845 if (!NT_SUCCESS(Status
))
847 /* None left, fail */
852 /* Read the registry data */
853 Status
= ZwQueryValueKey(BusKeyHandle
,
855 KeyValueFullInformation
,
859 if (!NT_SUCCESS(Status
))
861 /* Failed, try the next one */
862 ZwClose(BusKeyHandle
);
866 /* Get the PCI Tag and validate it */
867 Tag
= (PWSTR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
868 if ((Tag
[0] != L
'P') ||
873 /* Not a valid PCI entry, skip it */
874 ZwClose(BusKeyHandle
);
878 /* Now read our PCI structure */
879 Status
= ZwQueryValueKey(BusKeyHandle
,
881 KeyValueFullInformation
,
885 ZwClose(BusKeyHandle
);
886 if (!NT_SUCCESS(Status
)) continue;
888 /* We read it OK! Get the actual resource descriptors */
889 FullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
890 ((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
);
891 PartialDescriptor
= (PCM_PARTIAL_RESOURCE_DESCRIPTOR
)
892 ((ULONG_PTR
)FullDescriptor
->
893 PartialResourceList
.PartialDescriptors
);
895 /* Check if this is our PCI Registry Information */
896 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
898 /* It is, stop searching */
906 /* Save the PCI information for later */
907 PciRegInfo
= (PPCI_REGISTRY_INFO
)(PartialDescriptor
+ 1);
909 /* Assume no Card List entries */
912 /* Set up for checking the PCI Card List key */
913 RtlInitUnicodeString(&KeyName
,
914 L
"\\Registry\\Machine\\System\\CurrentControlSet\\"
915 L
"Control\\PnP\\PCI\\CardList");
916 InitializeObjectAttributes(&ObjectAttributes
,
918 OBJ_CASE_INSENSITIVE
,
922 /* Attempt to open it */
923 Status
= ZwOpenKey(&CardListHandle
, KEY_READ
, &ObjectAttributes
);
924 if (NT_SUCCESS(Status
))
926 /* It exists, so let's query it */
927 Status
= ZwQueryKey(CardListHandle
,
930 sizeof(KEY_FULL_INFORMATION
),
932 if (!NT_SUCCESS(Status
))
934 /* Failed to query, so no info */
935 PciRegistryInfo
= NULL
;
939 /* Allocate the full structure */
941 ExAllocatePoolWithTag(NonPagedPool
,
942 sizeof(PCI_REGISTRY_INFO_INTERNAL
) +
943 (KeyInformation
.Values
*
944 sizeof(PCI_CARD_DESCRIPTOR
)),
948 /* Get the first card descriptor entry */
949 CardDescriptor
= (PPCI_CARD_DESCRIPTOR
)(PciRegistryInfo
+ 1);
951 /* Loop all the values */
952 for (i
= 0; i
< KeyInformation
.Values
; i
++)
954 /* Attempt to get the value */
955 Status
= ZwEnumerateValueKey(CardListHandle
,
957 KeyValuePartialInformation
,
959 sizeof(PartialKeyBuffer
),
961 if (!NT_SUCCESS(Status
))
963 /* Something went wrong, stop the search */
967 /* Make sure it is correctly sized */
968 if (PartialValueInfo
->DataLength
== sizeof(PCI_CARD_DESCRIPTOR
))
970 /* Sure is, copy it over */
971 *CardDescriptor
= *(PPCI_CARD_DESCRIPTOR
)
972 PartialValueInfo
->Data
;
974 /* One more Card List entry */
977 /* Move to the next descriptor */
978 CardDescriptor
= (CardDescriptor
+ 1);
984 /* Close the Card List key */
985 ZwClose(CardListHandle
);
989 /* No key, no Card List */
990 PciRegistryInfo
= NULL
;
993 /* Check if we failed to get the full structure */
994 if (!PciRegistryInfo
)
996 /* Just allocate the basic structure then */
997 PciRegistryInfo
= ExAllocatePoolWithTag(NonPagedPool
,
998 sizeof(PCI_REGISTRY_INFO_INTERNAL
),
1000 if (!PciRegistryInfo
) return NULL
;
1003 /* Save the info we got */
1004 PciRegistryInfo
->MajorRevision
= PciRegInfo
->MajorRevision
;
1005 PciRegistryInfo
->MinorRevision
= PciRegInfo
->MinorRevision
;
1006 PciRegistryInfo
->NoBuses
= PciRegInfo
->NoBuses
;
1007 PciRegistryInfo
->HardwareMechanism
= PciRegInfo
->HardwareMechanism
;
1008 PciRegistryInfo
->ElementCount
= ElementCount
;
1011 return PciRegistryInfo
;
1019 HalpInitializePciStubs(VOID
)
1021 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
1023 PPCIPBUSDATA BusData
= (PPCIPBUSDATA
)HalpFakePciBusHandler
.BusData
;
1027 ULONG MaxPciBusNumber
;
1029 /* Query registry information */
1030 PciRegistryInfo
= HalpQueryPciRegistryInfo();
1031 if (!PciRegistryInfo
)
1036 /* Force a manual bus scan later */
1037 MaxPciBusNumber
= MAXULONG
;
1041 /* Get the PCI type */
1042 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
1044 /* Get MaxPciBusNumber and make it 0-based */
1045 MaxPciBusNumber
= PciRegistryInfo
->NoBuses
- 1;
1047 /* Free the info structure */
1048 ExFreePool(PciRegistryInfo
);
1051 /* Initialize the PCI lock */
1052 KeInitializeSpinLock(&HalpPCIConfigLock
);
1054 /* Check the type of PCI bus */
1057 /* Type 1 PCI Bus */
1060 /* Copy the Type 1 handler data */
1061 RtlCopyMemory(&PCIConfigHandler
,
1062 &PCIConfigHandlerType1
,
1063 sizeof(PCIConfigHandler
));
1065 /* Set correct I/O Ports */
1066 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
1067 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
1070 /* Type 2 PCI Bus */
1073 /* Copy the Type 2 handler data */
1074 RtlCopyMemory(&PCIConfigHandler
,
1075 &PCIConfigHandlerType2
,
1076 sizeof (PCIConfigHandler
));
1078 /* Set correct I/O Ports */
1079 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
1080 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
1081 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
1083 /* Only 16 devices supported, not 32 */
1084 BusData
->MaxDevice
= 16;
1090 DbgPrint("HAL: Unknown PCI type\n");
1093 /* Run a forced bus scan if needed */
1094 if (MaxPciBusNumber
== MAXULONG
)
1096 /* Initialize the max bus number to 0xFF */
1097 HalpMaxPciBus
= 0xFF;
1099 /* Initialize the counter */
1100 MaxPciBusNumber
= 0;
1102 /* Loop all possible buses */
1103 for (i
= 0; i
< HalpMaxPciBus
; i
++)
1105 /* Loop all devices */
1106 for (j
.u
.AsULONG
= 0; j
.u
.AsULONG
< BusData
->MaxDevice
; j
.u
.AsULONG
++)
1108 /* Query the interface */
1109 if (HaliPciInterfaceReadConfig(NULL
,
1116 /* Validate the vendor ID */
1117 if ((USHORT
)VendorId
!= PCI_INVALID_VENDORID
)
1119 /* Set this as the maximum ID */
1120 MaxPciBusNumber
= i
;
1128 /* Set the real max bus number */
1129 HalpMaxPciBus
= MaxPciBusNumber
;
1132 HalpPCIConfigInitialized
= TRUE
;