Add config interface start (PciReadWriteConfigSpace, PciReadSlotConfig)
[reactos.git] / reactos / 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 VOID
22 NTAPI
23 PciReadWriteConfigSpace(IN PPCI_FDO_EXTENSION DeviceExtension,
24 IN PCI_SLOT_NUMBER Slot,
25 IN PVOID Buffer,
26 IN ULONG Offset,
27 IN ULONG Length,
28 IN BOOLEAN Read)
29 {
30 PPCI_BUS_INTERFACE_STANDARD PciInterface;
31 PBUS_HANDLER BusHandler;
32 PPCIBUSDATA BusData;
33 PciReadWriteConfig HalFunction;
34
35 /* Only the root FDO can access configuration space */
36 ASSERT(PCI_IS_ROOT_FDO(DeviceExtension->BusRootFdoExtension));
37
38 /* Get the ACPI-compliant PCI interface */
39 PciInterface = DeviceExtension->BusRootFdoExtension->PciBusInterface;
40 if (PciInterface)
41 {
42 /* Currently this driver only supports the legacy HAL interface */
43 UNIMPLEMENTED;
44 while (TRUE);
45 }
46 else
47 {
48 /* Make sure there's a registered HAL bus handler */
49 ASSERT(DeviceExtension->BusHandler);
50
51 /* PCI Bus Number assignment is only valid on ACPI systems */
52 ASSERT(!PciAssignBusNumbers);
53
54 /* Grab the HAL PCI Bus Handler data */
55 BusHandler = (PBUS_HANDLER)DeviceExtension->BusHandler;
56 BusData = (PPCIBUSDATA)BusHandler->BusData;
57
58 /* Choose the appropriate read or write function, and call it */
59 HalFunction = Read ? BusData->ReadConfig : BusData->WriteConfig;
60 HalFunction(BusHandler, Slot, Buffer, Offset, Length);
61 }
62 }
63
64 VOID
65 NTAPI
66 PciReadSlotConfig(IN PPCI_FDO_EXTENSION DeviceExtension,
67 IN PCI_SLOT_NUMBER Slot,
68 IN PVOID Buffer,
69 IN ULONG Offset,
70 IN ULONG Length)
71 {
72 /* Call the generic worker function */
73 PciReadWriteConfigSpace(DeviceExtension, Slot, Buffer, Offset, Length, TRUE);
74 }
75
76 NTSTATUS
77 NTAPI
78 PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension)
79 {
80 PDEVICE_OBJECT AttachedDevice;
81 IO_STATUS_BLOCK IoStatusBlock;
82 KEVENT Event;
83 NTSTATUS Status;
84 PIRP Irp;
85 PIO_STACK_LOCATION IoStackLocation;
86 PPCI_BUS_INTERFACE_STANDARD PciInterface;
87 PAGED_CODE();
88 ASSERT(PCI_IS_ROOT_FDO(FdoExtension));
89
90 /* Allocate space for the inteface */
91 PciInterface = ExAllocatePoolWithTag(NonPagedPool,
92 sizeof(PCI_BUS_INTERFACE_STANDARD),
93 PCI_POOL_TAG);
94 if (!PciInterface) return STATUS_INSUFFICIENT_RESOURCES;
95
96 /* Get the device the PDO is attached to, should be the Root (ACPI) */
97 AttachedDevice = IoGetAttachedDeviceReference(FdoExtension->PhysicalDeviceObject);
98
99 /* Build an IRP for this request */
100 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
101 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
102 AttachedDevice,
103 NULL,
104 0,
105 NULL,
106 &Event,
107 &IoStatusBlock);
108 if (Irp)
109 {
110 /* Initialize the default PnP response */
111 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
112 Irp->IoStatus.Information = 0;
113
114 /* Make it a Query Interface IRP */
115 IoStackLocation = IoGetNextIrpStackLocation(Irp);
116 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_PNP);
117 IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
118 IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_PCI_BUS_INTERFACE_STANDARD;
119 IoStackLocation->Parameters.QueryInterface.Size = sizeof(GUID_PCI_BUS_INTERFACE_STANDARD);
120 IoStackLocation->Parameters.QueryInterface.Version = PCI_BUS_INTERFACE_STANDARD_VERSION;
121 IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)PciInterface;
122 IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL;
123
124 /* Send it to the root PDO */
125 Status = IoCallDriver(AttachedDevice, Irp);
126 if (Status == STATUS_PENDING)
127 {
128 /* Wait for completion */
129 KeWaitForSingleObject(&Event,
130 Executive,
131 KernelMode,
132 FALSE,
133 NULL);
134 Status = Irp->IoStatus.Status;
135 }
136
137 /* Check if an interface was returned */
138 if (!NT_SUCCESS(Status))
139 {
140 /* No interface was returned by the root PDO */
141 FdoExtension->PciBusInterface = NULL;
142 ExFreePoolWithTag(PciInterface, 0);
143 }
144 else
145 {
146 /* An interface was returned, save it */
147 FdoExtension->PciBusInterface = PciInterface;
148 }
149
150 /* Dereference the device object because we took a reference earlier */
151 ObfDereferenceObject(AttachedDevice);
152 }
153 else
154 {
155 /* Failure path, dereference the device object and set failure code */
156 if (AttachedDevice) ObfDereferenceObject(AttachedDevice);
157 ExFreePoolWithTag(PciInterface, 0);
158 Status = STATUS_INSUFFICIENT_RESOURCES;
159 }
160
161 /* Return status code to caller */
162 return Status;
163 }
164
165 NTSTATUS
166 NTAPI
167 PciGetConfigHandlers(IN PPCI_FDO_EXTENSION FdoExtension)
168 {
169 PBUS_HANDLER BusHandler;
170 NTSTATUS Status;
171 ASSERT(FdoExtension->BusHandler == NULL);
172
173 /* Check if this is the FDO for the root bus */
174 if (PCI_IS_ROOT_FDO(FdoExtension))
175 {
176 /* Query the PCI Bus Interface that ACPI exposes */
177 ASSERT(FdoExtension->PciBusInterface == NULL);
178 Status = PciQueryForPciBusInterface(FdoExtension);
179 if (!NT_SUCCESS(Status))
180 {
181 /* No ACPI, so Bus Numbers should be maintained by BIOS */
182 ASSERT(!PciAssignBusNumbers);
183 }
184 else
185 {
186 /* ACPI detected, PCI Bus Driver will reconfigure bus numbers*/
187 PciAssignBusNumbers = TRUE;
188 }
189 }
190 else
191 {
192 /* Check if the root bus already has the interface set up */
193 if (FdoExtension->BusRootFdoExtension->PciBusInterface)
194 {
195 /* Nothing for this FDO to do */
196 return STATUS_SUCCESS;
197 }
198
199 /* Fail into case below so we can query the HAL interface */
200 Status = STATUS_NOT_SUPPORTED;
201 }
202
203 /* If the ACPI PCI Bus Interface couldn't be obtained, try the HAL */
204 if (!NT_SUCCESS(Status))
205 {
206 /* Bus number assignment should be static */
207 ASSERT(Status == STATUS_NOT_SUPPORTED);
208 ASSERT(!PciAssignBusNumbers);
209
210 /* Call the HAL to obtain the bus handler for PCI */
211 BusHandler = HalReferenceHandlerForBus(PCIBus, FdoExtension->BaseBus);
212 FdoExtension->BusHandler = BusHandler;
213
214 /* Fail if the HAL does not have a PCI Bus Handler for this bus */
215 if (!BusHandler) return STATUS_INVALID_DEVICE_REQUEST;
216 }
217
218 /* Appropriate interface was obtained */
219 return STATUS_SUCCESS;
220 }
221
222 /* EOF */