Sync with trunk (r48008)
[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 NTSTATUS
22 NTAPI
23 PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension)
24 {
25 PDEVICE_OBJECT AttachedDevice;
26 IO_STATUS_BLOCK IoStatusBlock;
27 KEVENT Event;
28 NTSTATUS Status;
29 PIRP Irp;
30 PIO_STACK_LOCATION IoStackLocation;
31 PPCI_BUS_INTERFACE_STANDARD PciInterface;
32 PAGED_CODE();
33 ASSERT(PCI_IS_ROOT_FDO(FdoExtension));
34
35 /* Allocate space for the inteface */
36 PciInterface = ExAllocatePoolWithTag(NonPagedPool,
37 sizeof(PCI_BUS_INTERFACE_STANDARD),
38 PCI_POOL_TAG);
39 if (!PciInterface) return STATUS_INSUFFICIENT_RESOURCES;
40
41 /* Get the device the PDO is attached to, should be the Root (ACPI) */
42 AttachedDevice = IoGetAttachedDeviceReference(FdoExtension->PhysicalDeviceObject);
43
44 /* Build an IRP for this request */
45 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
46 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
47 AttachedDevice,
48 NULL,
49 0,
50 NULL,
51 &Event,
52 &IoStatusBlock);
53 if (Irp)
54 {
55 /* Initialize the default PnP response */
56 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
57 Irp->IoStatus.Information = 0;
58
59 /* Make it a Query Interface IRP */
60 IoStackLocation = IoGetNextIrpStackLocation(Irp);
61 ASSERT(IoStackLocation->MajorFunction == IRP_MJ_PNP);
62 IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
63 IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_PCI_BUS_INTERFACE_STANDARD;
64 IoStackLocation->Parameters.QueryInterface.Size = sizeof(GUID_PCI_BUS_INTERFACE_STANDARD);
65 IoStackLocation->Parameters.QueryInterface.Version = PCI_BUS_INTERFACE_STANDARD_VERSION;
66 IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)PciInterface;
67 IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL;
68
69 /* Send it to the root PDO */
70 Status = IoCallDriver(AttachedDevice, Irp);
71 if (Status == STATUS_PENDING)
72 {
73 /* Wait for completion */
74 KeWaitForSingleObject(&Event,
75 Executive,
76 KernelMode,
77 FALSE,
78 NULL);
79 Status = Irp->IoStatus.Status;
80 }
81
82 /* Check if an interface was returned */
83 if (!NT_SUCCESS(Status))
84 {
85 /* No interface was returned by the root PDO */
86 FdoExtension->PciBusInterface = NULL;
87 ExFreePoolWithTag(PciInterface, 0);
88 }
89 else
90 {
91 /* An interface was returned, save it */
92 FdoExtension->PciBusInterface = PciInterface;
93 }
94
95 /* Dereference the device object because we took a reference earlier */
96 ObfDereferenceObject(AttachedDevice);
97 }
98 else
99 {
100 /* Failure path, dereference the device object and set failure code */
101 if (AttachedDevice) ObfDereferenceObject(AttachedDevice);
102 ExFreePoolWithTag(PciInterface, 0);
103 Status = STATUS_INSUFFICIENT_RESOURCES;
104 }
105
106 /* Return status code to caller */
107 return Status;
108 }
109
110 NTSTATUS
111 NTAPI
112 PciGetConfigHandlers(IN PPCI_FDO_EXTENSION FdoExtension)
113 {
114 PBUS_HANDLER BusHandler;
115 NTSTATUS Status;
116 ASSERT(FdoExtension->BusHandler == NULL);
117
118 /* Check if this is the FDO for the root bus */
119 if (PCI_IS_ROOT_FDO(FdoExtension))
120 {
121 /* Query the PCI Bus Interface that ACPI exposes */
122 ASSERT(FdoExtension->PciBusInterface == NULL);
123 Status = PciQueryForPciBusInterface(FdoExtension);
124 if (!NT_SUCCESS(Status))
125 {
126 /* No ACPI, so Bus Numbers should be maintained by BIOS */
127 ASSERT(!PciAssignBusNumbers);
128 }
129 else
130 {
131 /* ACPI detected, PCI Bus Driver will reconfigure bus numbers*/
132 PciAssignBusNumbers = TRUE;
133 }
134 }
135 else
136 {
137 /* Check if the root bus already has the interface set up */
138 if (FdoExtension->BusRootFdoExtension->PciBusInterface)
139 {
140 /* Nothing for this FDO to do */
141 return STATUS_SUCCESS;
142 }
143
144 /* Fail into case below so we can query the HAL interface */
145 Status = STATUS_NOT_SUPPORTED;
146 }
147
148 /* If the ACPI PCI Bus Interface couldn't be obtained, try the HAL */
149 if (!NT_SUCCESS(Status))
150 {
151 /* Bus number assignment should be static */
152 ASSERT(Status == STATUS_NOT_SUPPORTED);
153 ASSERT(!PciAssignBusNumbers);
154
155 /* Call the HAL to obtain the bus handler for PCI */
156 BusHandler = HalReferenceHandlerForBus(PCIBus, FdoExtension->BaseBus);
157 FdoExtension->BusHandler = BusHandler;
158
159 /* Fail if the HAL does not have a PCI Bus Handler for this bus */
160 if (!BusHandler) return STATUS_INVALID_DEVICE_REQUEST;
161 }
162
163 /* Appropriate interface was obtained */
164 return STATUS_SUCCESS;
165 }
166
167 /* EOF */