2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/pci/config.c
5 * PURPOSE: PCI Configuration Space Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 BOOLEAN PciAssignBusNumbers
;
19 /* FUNCTIONS ******************************************************************/
23 PciGetAdjustedInterruptLine(IN PPCI_PDO_EXTENSION PdoExtension
)
25 UCHAR InterruptLine
= 0, PciInterruptLine
;
28 /* Does the device have an interrupt pin? */
29 if (PdoExtension
->InterruptPin
)
31 /* Find the associated line on the parent bus */
32 Length
= HalGetBusDataByOffset(PCIConfiguration
,
33 PdoExtension
->ParentFdoExtension
->BaseBus
,
34 PdoExtension
->Slot
.u
.AsULONG
,
36 FIELD_OFFSET(PCI_COMMON_HEADER
,
37 u
.type0
.InterruptLine
),
39 if (Length
) InterruptLine
= PciInterruptLine
;
42 /* Either keep the original interrupt line, or the one on the master bus */
43 return InterruptLine
? PdoExtension
->RawInterruptLine
: InterruptLine
;
48 PciReadWriteConfigSpace(IN PPCI_FDO_EXTENSION DeviceExtension
,
49 IN PCI_SLOT_NUMBER Slot
,
55 PPCI_BUS_INTERFACE_STANDARD PciInterface
;
56 PBUS_HANDLER BusHandler
;
58 PciReadWriteConfig HalFunction
;
60 /* Only the root FDO can access configuration space */
61 ASSERT(PCI_IS_ROOT_FDO(DeviceExtension
->BusRootFdoExtension
));
63 /* Get the ACPI-compliant PCI interface */
64 PciInterface
= DeviceExtension
->BusRootFdoExtension
->PciBusInterface
;
67 /* Currently this driver only supports the legacy HAL interface */
73 /* Make sure there's a registered HAL bus handler */
74 ASSERT(DeviceExtension
->BusHandler
);
76 /* PCI Bus Number assignment is only valid on ACPI systems */
77 ASSERT(!PciAssignBusNumbers
);
79 /* Grab the HAL PCI Bus Handler data */
80 BusHandler
= (PBUS_HANDLER
)DeviceExtension
->BusHandler
;
81 BusData
= (PPCIBUSDATA
)BusHandler
->BusData
;
83 /* Choose the appropriate read or write function, and call it */
84 HalFunction
= Read
? BusData
->ReadConfig
: BusData
->WriteConfig
;
85 HalFunction(BusHandler
, Slot
, Buffer
, Offset
, Length
);
91 PciWriteDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension
,
96 /* Call the generic worker function */
97 PciReadWriteConfigSpace(DeviceExtension
->ParentFdoExtension
,
98 DeviceExtension
->Slot
,
107 PciReadDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension
,
112 /* Call the generic worker function */
113 PciReadWriteConfigSpace(DeviceExtension
->ParentFdoExtension
,
114 DeviceExtension
->Slot
,
123 PciReadSlotConfig(IN PPCI_FDO_EXTENSION DeviceExtension
,
124 IN PCI_SLOT_NUMBER Slot
,
129 /* Call the generic worker function */
130 PciReadWriteConfigSpace(DeviceExtension
, Slot
, Buffer
, Offset
, Length
, TRUE
);
135 PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension
)
137 PDEVICE_OBJECT AttachedDevice
;
138 IO_STATUS_BLOCK IoStatusBlock
;
142 PIO_STACK_LOCATION IoStackLocation
;
143 PPCI_BUS_INTERFACE_STANDARD PciInterface
;
145 ASSERT(PCI_IS_ROOT_FDO(FdoExtension
));
147 /* Allocate space for the inteface */
148 PciInterface
= ExAllocatePoolWithTag(NonPagedPool
,
149 sizeof(PCI_BUS_INTERFACE_STANDARD
),
151 if (!PciInterface
) return STATUS_INSUFFICIENT_RESOURCES
;
153 /* Get the device the PDO is attached to, should be the Root (ACPI) */
154 AttachedDevice
= IoGetAttachedDeviceReference(FdoExtension
->PhysicalDeviceObject
);
156 /* Build an IRP for this request */
157 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
158 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
167 /* Initialize the default PnP response */
168 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
169 Irp
->IoStatus
.Information
= 0;
171 /* Make it a Query Interface IRP */
172 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
173 ASSERT(IoStackLocation
->MajorFunction
== IRP_MJ_PNP
);
174 IoStackLocation
->MinorFunction
= IRP_MN_QUERY_INTERFACE
;
175 IoStackLocation
->Parameters
.QueryInterface
.InterfaceType
= &GUID_PCI_BUS_INTERFACE_STANDARD
;
176 IoStackLocation
->Parameters
.QueryInterface
.Size
= sizeof(GUID_PCI_BUS_INTERFACE_STANDARD
);
177 IoStackLocation
->Parameters
.QueryInterface
.Version
= PCI_BUS_INTERFACE_STANDARD_VERSION
;
178 IoStackLocation
->Parameters
.QueryInterface
.Interface
= (PINTERFACE
)PciInterface
;
179 IoStackLocation
->Parameters
.QueryInterface
.InterfaceSpecificData
= NULL
;
181 /* Send it to the root PDO */
182 Status
= IoCallDriver(AttachedDevice
, Irp
);
183 if (Status
== STATUS_PENDING
)
185 /* Wait for completion */
186 KeWaitForSingleObject(&Event
,
191 Status
= Irp
->IoStatus
.Status
;
194 /* Check if an interface was returned */
195 if (!NT_SUCCESS(Status
))
197 /* No interface was returned by the root PDO */
198 FdoExtension
->PciBusInterface
= NULL
;
199 ExFreePoolWithTag(PciInterface
, 0);
203 /* An interface was returned, save it */
204 FdoExtension
->PciBusInterface
= PciInterface
;
207 /* Dereference the device object because we took a reference earlier */
208 ObfDereferenceObject(AttachedDevice
);
212 /* Failure path, dereference the device object and set failure code */
213 if (AttachedDevice
) ObfDereferenceObject(AttachedDevice
);
214 ExFreePoolWithTag(PciInterface
, 0);
215 Status
= STATUS_INSUFFICIENT_RESOURCES
;
218 /* Return status code to caller */
224 PciGetConfigHandlers(IN PPCI_FDO_EXTENSION FdoExtension
)
226 PBUS_HANDLER BusHandler
;
228 ASSERT(FdoExtension
->BusHandler
== NULL
);
230 /* Check if this is the FDO for the root bus */
231 if (PCI_IS_ROOT_FDO(FdoExtension
))
233 /* Query the PCI Bus Interface that ACPI exposes */
234 ASSERT(FdoExtension
->PciBusInterface
== NULL
);
235 Status
= PciQueryForPciBusInterface(FdoExtension
);
236 if (!NT_SUCCESS(Status
))
238 /* No ACPI, so Bus Numbers should be maintained by BIOS */
239 ASSERT(!PciAssignBusNumbers
);
243 /* ACPI detected, PCI Bus Driver will reconfigure bus numbers*/
244 PciAssignBusNumbers
= TRUE
;
249 /* Check if the root bus already has the interface set up */
250 if (FdoExtension
->BusRootFdoExtension
->PciBusInterface
)
252 /* Nothing for this FDO to do */
253 return STATUS_SUCCESS
;
256 /* Fail into case below so we can query the HAL interface */
257 Status
= STATUS_NOT_SUPPORTED
;
260 /* If the ACPI PCI Bus Interface couldn't be obtained, try the HAL */
261 if (!NT_SUCCESS(Status
))
263 /* Bus number assignment should be static */
264 ASSERT(Status
== STATUS_NOT_SUPPORTED
);
265 ASSERT(!PciAssignBusNumbers
);
267 /* Call the HAL to obtain the bus handler for PCI */
268 BusHandler
= HalReferenceHandlerForBus(PCIBus
, FdoExtension
->BaseBus
);
269 FdoExtension
->BusHandler
= BusHandler
;
271 /* Fail if the HAL does not have a PCI Bus Handler for this bus */
272 if (!BusHandler
) return STATUS_INVALID_DEVICE_REQUEST
;
275 /* Appropriate interface was obtained */
276 return STATUS_SUCCESS
;