- Synchronize up to trunk's revision r57864.
[reactos.git] / drivers / bus / pcix / pci / config.c
1 /*
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
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <pci.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 BOOLEAN PciAssignBusNumbers;
18
19 /* FUNCTIONS ******************************************************************/
20
21 UCHAR
22 NTAPI
23 PciGetAdjustedInterruptLine(IN PPCI_PDO_EXTENSION PdoExtension)
24 {
25 UCHAR InterruptLine = 0, PciInterruptLine;
26 ULONG Length;
27
28 /* Does the device have an interrupt pin? */
29 if (PdoExtension->InterruptPin)
30 {
31 /* Find the associated line on the parent bus */
32 Length = HalGetBusDataByOffset(PCIConfiguration,
33 PdoExtension->ParentFdoExtension->BaseBus,
34 PdoExtension->Slot.u.AsULONG,
35 &PciInterruptLine,
36 FIELD_OFFSET(PCI_COMMON_HEADER,
37 u.type0.InterruptLine),
38 sizeof(UCHAR));
39 if (Length) InterruptLine = PciInterruptLine;
40 }
41
42 /* Either keep the original interrupt line, or the one on the master bus */
43 return InterruptLine ? PdoExtension->RawInterruptLine : InterruptLine;
44 }
45
46 VOID
47 NTAPI
48 PciReadWriteConfigSpace(IN PPCI_FDO_EXTENSION DeviceExtension,
49 IN PCI_SLOT_NUMBER Slot,
50 IN PVOID Buffer,
51 IN ULONG Offset,
52 IN ULONG Length,
53 IN BOOLEAN Read)
54 {
55 PPCI_BUS_INTERFACE_STANDARD PciInterface;
56 PBUS_HANDLER BusHandler;
57 PPCIBUSDATA BusData;
58 PciReadWriteConfig HalFunction;
59
60 /* Only the root FDO can access configuration space */
61 ASSERT(PCI_IS_ROOT_FDO(DeviceExtension->BusRootFdoExtension));
62
63 /* Get the ACPI-compliant PCI interface */
64 PciInterface = DeviceExtension->BusRootFdoExtension->PciBusInterface;
65 if (PciInterface)
66 {
67 /* Currently this driver only supports the legacy HAL interface */
68 UNIMPLEMENTED;
69 while (TRUE);
70 }
71 else
72 {
73 /* Make sure there's a registered HAL bus handler */
74 ASSERT(DeviceExtension->BusHandler);
75
76 /* PCI Bus Number assignment is only valid on ACPI systems */
77 ASSERT(!PciAssignBusNumbers);
78
79 /* Grab the HAL PCI Bus Handler data */
80 BusHandler = (PBUS_HANDLER)DeviceExtension->BusHandler;
81 BusData = (PPCIBUSDATA)BusHandler->BusData;
82
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);
86 }
87 }
88
89 VOID
90 NTAPI
91 PciWriteDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension,
92 IN PVOID Buffer,
93 IN ULONG Offset,
94 IN ULONG Length)
95 {
96 /* Call the generic worker function */
97 PciReadWriteConfigSpace(DeviceExtension->ParentFdoExtension,
98 DeviceExtension->Slot,
99 Buffer,
100 Offset,
101 Length,
102 FALSE);
103 }
104
105 VOID
106 NTAPI
107 PciReadDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension,
108 IN PVOID Buffer,
109 IN ULONG Offset,
110 IN ULONG Length)
111 {
112 /* Call the generic worker function */
113 PciReadWriteConfigSpace(DeviceExtension->ParentFdoExtension,
114 DeviceExtension->Slot,
115 Buffer,
116 Offset,
117 Length,
118 TRUE);
119 }
120
121 VOID
122 NTAPI
123 PciReadSlotConfig(IN PPCI_FDO_EXTENSION DeviceExtension,
124 IN PCI_SLOT_NUMBER Slot,
125 IN PVOID Buffer,
126 IN ULONG Offset,
127 IN ULONG Length)
128 {
129 /* Call the generic worker function */
130 PciReadWriteConfigSpace(DeviceExtension, Slot, Buffer, Offset, Length, TRUE);
131 }
132
133 NTSTATUS
134 NTAPI
135 PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension)
136 {
137 PDEVICE_OBJECT AttachedDevice;
138 IO_STATUS_BLOCK IoStatusBlock;
139 KEVENT Event;
140 NTSTATUS Status;
141 PIRP Irp;
142 PIO_STACK_LOCATION IoStackLocation;
143 PPCI_BUS_INTERFACE_STANDARD PciInterface;
144 PAGED_CODE();
145 ASSERT(PCI_IS_ROOT_FDO(FdoExtension));
146
147 /* Allocate space for the inteface */
148 PciInterface = ExAllocatePoolWithTag(NonPagedPool,
149 sizeof(PCI_BUS_INTERFACE_STANDARD),
150 PCI_POOL_TAG);
151 if (!PciInterface) return STATUS_INSUFFICIENT_RESOURCES;
152
153 /* Get the device the PDO is attached to, should be the Root (ACPI) */
154 AttachedDevice = IoGetAttachedDeviceReference(FdoExtension->PhysicalDeviceObject);
155
156 /* Build an IRP for this request */
157 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
158 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
159 AttachedDevice,
160 NULL,
161 0,
162 NULL,
163 &Event,
164 &IoStatusBlock);
165 if (Irp)
166 {
167 /* Initialize the default PnP response */
168 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
169 Irp->IoStatus.Information = 0;
170
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;
180
181 /* Send it to the root PDO */
182 Status = IoCallDriver(AttachedDevice, Irp);
183 if (Status == STATUS_PENDING)
184 {
185 /* Wait for completion */
186 KeWaitForSingleObject(&Event,
187 Executive,
188 KernelMode,
189 FALSE,
190 NULL);
191 Status = Irp->IoStatus.Status;
192 }
193
194 /* Check if an interface was returned */
195 if (!NT_SUCCESS(Status))
196 {
197 /* No interface was returned by the root PDO */
198 FdoExtension->PciBusInterface = NULL;
199 ExFreePoolWithTag(PciInterface, 0);
200 }
201 else
202 {
203 /* An interface was returned, save it */
204 FdoExtension->PciBusInterface = PciInterface;
205 }
206
207 /* Dereference the device object because we took a reference earlier */
208 ObDereferenceObject(AttachedDevice);
209 }
210 else
211 {
212 /* Failure path, dereference the device object and set failure code */
213 if (AttachedDevice) ObDereferenceObject(AttachedDevice);
214 ExFreePoolWithTag(PciInterface, 0);
215 Status = STATUS_INSUFFICIENT_RESOURCES;
216 }
217
218 /* Return status code to caller */
219 return Status;
220 }
221
222 NTSTATUS
223 NTAPI
224 PciGetConfigHandlers(IN PPCI_FDO_EXTENSION FdoExtension)
225 {
226 PBUS_HANDLER BusHandler;
227 NTSTATUS Status;
228 ASSERT(FdoExtension->BusHandler == NULL);
229
230 /* Check if this is the FDO for the root bus */
231 if (PCI_IS_ROOT_FDO(FdoExtension))
232 {
233 /* Query the PCI Bus Interface that ACPI exposes */
234 ASSERT(FdoExtension->PciBusInterface == NULL);
235 Status = PciQueryForPciBusInterface(FdoExtension);
236 if (!NT_SUCCESS(Status))
237 {
238 /* No ACPI, so Bus Numbers should be maintained by BIOS */
239 ASSERT(!PciAssignBusNumbers);
240 }
241 else
242 {
243 /* ACPI detected, PCI Bus Driver will reconfigure bus numbers*/
244 PciAssignBusNumbers = TRUE;
245 }
246 }
247 else
248 {
249 /* Check if the root bus already has the interface set up */
250 if (FdoExtension->BusRootFdoExtension->PciBusInterface)
251 {
252 /* Nothing for this FDO to do */
253 return STATUS_SUCCESS;
254 }
255
256 /* Fail into case below so we can query the HAL interface */
257 Status = STATUS_NOT_SUPPORTED;
258 }
259
260 /* If the ACPI PCI Bus Interface couldn't be obtained, try the HAL */
261 if (!NT_SUCCESS(Status))
262 {
263 /* Bus number assignment should be static */
264 ASSERT(Status == STATUS_NOT_SUPPORTED);
265 ASSERT(!PciAssignBusNumbers);
266
267 /* Call the HAL to obtain the bus handler for PCI */
268 BusHandler = HalReferenceHandlerForBus(PCIBus, FdoExtension->BaseBus);
269 FdoExtension->BusHandler = BusHandler;
270
271 /* Fail if the HAL does not have a PCI Bus Handler for this bus */
272 if (!BusHandler) return STATUS_INVALID_DEVICE_REQUEST;
273 }
274
275 /* Appropriate interface was obtained */
276 return STATUS_SUCCESS;
277 }
278
279 /* EOF */