Synchronize with trunk r58606.
[reactos.git] / drivers / bus / pcix / hookhal.c
1 /*
2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/hookhal.c
5 * PURPOSE: HAL Bus Handler Dispatch Routine Support
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 pHalTranslateBusAddress PcipSavedTranslateBusAddress;
18 pHalAssignSlotResources PcipSavedAssignSlotResources;
19
20 /* FUNCTIONS ******************************************************************/
21
22 BOOLEAN
23 NTAPI
24 PciTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
25 IN ULONG BusNumber,
26 IN PHYSICAL_ADDRESS BusAddress,
27 OUT PULONG AddressSpace,
28 OUT PPHYSICAL_ADDRESS TranslatedAddress)
29 {
30 /* FIXME: Broken translation */
31 UNIMPLEMENTED;
32 TranslatedAddress->QuadPart = BusAddress.QuadPart;
33 return TRUE;
34 }
35
36 PPCI_PDO_EXTENSION
37 NTAPI
38 PciFindPdoByLocation(IN ULONG BusNumber,
39 IN ULONG SlotNumber)
40 {
41 PPCI_FDO_EXTENSION DeviceExtension;
42 PPCI_PDO_EXTENSION PdoExtension;
43 PCI_SLOT_NUMBER PciSlot;
44 PciSlot.u.AsULONG = SlotNumber;
45
46 /* Acquire the global lock */
47 KeEnterCriticalRegion();
48 KeWaitForSingleObject(&PciGlobalLock, Executive, KernelMode, FALSE, NULL);
49
50 /* Now search for the extension */
51 DeviceExtension = (PPCI_FDO_EXTENSION)PciFdoExtensionListHead.Next;
52 while (DeviceExtension)
53 {
54 /* If we found it, break out */
55 if (DeviceExtension->BaseBus == BusNumber) break;
56
57 /* Move to the next device */
58 DeviceExtension = (PPCI_FDO_EXTENSION)DeviceExtension->List.Next;
59 }
60
61 /* Release the global lock */
62 KeSetEvent(&PciGlobalLock, IO_NO_INCREMENT, FALSE);
63 KeLeaveCriticalRegion();
64
65 /* Check if the device extension for the bus was found */
66 if (!DeviceExtension)
67 {
68 /* It wasn't, bail out */
69 DPRINT1("Pci: Could not find PCI bus FDO. Bus Number = 0x%x\n", BusNumber);
70 return NULL;
71 }
72
73 /* Acquire this device's lock */
74 KeEnterCriticalRegion();
75 KeWaitForSingleObject(&DeviceExtension->ChildListLock,
76 Executive,
77 KernelMode,
78 FALSE,
79 NULL);
80
81 /* Loop every child PDO */
82 for (PdoExtension = DeviceExtension->ChildPdoList;
83 PdoExtension;
84 PdoExtension = PdoExtension->Next)
85 {
86 /* Check if the function number and header data matches */
87 if ((PdoExtension->Slot.u.bits.FunctionNumber == PciSlot.u.bits.FunctionNumber) &&
88 (PdoExtension->Slot.u.bits.DeviceNumber == PciSlot.u.bits.DeviceNumber))
89 {
90 /* This is considered to be the same PDO */
91 ASSERT(PdoExtension->Slot.u.AsULONG == PciSlot.u.AsULONG);
92 break;
93 }
94 }
95
96 /* Release this device's lock */
97 KeSetEvent(&DeviceExtension->ChildListLock, IO_NO_INCREMENT, FALSE);
98 KeLeaveCriticalRegion();
99
100 /* Check if we found something */
101 if (!PdoExtension)
102 {
103 /* Let the debugger know */
104 DPRINT1("Pci: Could not find PDO for device @ %x.%x.%x\n",
105 BusNumber,
106 PciSlot.u.bits.DeviceNumber,
107 PciSlot.u.bits.FunctionNumber);
108 }
109
110 /* If the search found something, this is non-NULL, otherwise it's NULL */
111 return PdoExtension;
112 }
113
114 NTSTATUS
115 NTAPI
116 PciAssignSlotResources(IN PUNICODE_STRING RegistryPath,
117 IN PUNICODE_STRING DriverClassName OPTIONAL,
118 IN PDRIVER_OBJECT DriverObject,
119 IN PDEVICE_OBJECT DeviceObject,
120 IN INTERFACE_TYPE BusType,
121 IN ULONG BusNumber,
122 IN ULONG SlotNumber,
123 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
124 {
125 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList = NULL;
126 PCM_RESOURCE_LIST Resources = NULL;
127 PCI_COMMON_HEADER PciData;
128 PPCI_PDO_EXTENSION PdoExtension;
129 NTSTATUS Status;
130 PDEVICE_OBJECT ExistingDeviceObject;
131 PAGED_CODE();
132 ASSERT(PcipSavedAssignSlotResources);
133 ASSERT(BusType == PCIBus);
134
135 /* Assume no resources */
136 *AllocatedResources = NULL;
137
138 /* Find the PDO for this slot and make sure it exists and is started */
139 PdoExtension = PciFindPdoByLocation(BusNumber, SlotNumber);
140 if (!PdoExtension) return STATUS_DEVICE_DOES_NOT_EXIST;
141 if (PdoExtension->DeviceState == PciNotStarted) return STATUS_INVALID_OWNER;
142
143 /* Acquire the global lock while we attempt to assign resources */
144 KeEnterCriticalRegion();
145 KeWaitForSingleObject(&PciGlobalLock, Executive, KernelMode, FALSE, NULL);
146 do
147 {
148 /* Make sure we're not on the PDO for some reason */
149 ASSERT(DeviceObject != PdoExtension->PhysicalDeviceObject);
150
151 /* Read the PCI header and cache the routing information */
152 PciReadDeviceConfig(PdoExtension, &PciData, 0, PCI_COMMON_HDR_LENGTH);
153 Status = PciCacheLegacyDeviceRouting(DeviceObject,
154 BusNumber,
155 SlotNumber,
156 PciData.u.type0.InterruptLine,
157 PciData.u.type0.InterruptPin,
158 PciData.BaseClass,
159 PciData.SubClass,
160 PdoExtension->ParentFdoExtension->
161 PhysicalDeviceObject,
162 PdoExtension,
163 &ExistingDeviceObject);
164 if (NT_SUCCESS(Status))
165 {
166 /* Manually build the requirements for this device, and mark it legacy */
167 Status = PciBuildRequirementsList(PdoExtension,
168 &PciData,
169 &RequirementsList);
170 PdoExtension->LegacyDriver = TRUE;
171 if (NT_SUCCESS(Status))
172 {
173 /* Now call the legacy Pnp function to actually assign resources */
174 Status = IoAssignResources(RegistryPath,
175 DriverClassName,
176 DriverObject,
177 DeviceObject,
178 RequirementsList,
179 &Resources);
180 if (NT_SUCCESS(Status))
181 {
182 /* Resources are ready, so enable all decodes */
183 PdoExtension->CommandEnables |= (PCI_ENABLE_IO_SPACE |
184 PCI_ENABLE_MEMORY_SPACE |
185 PCI_ENABLE_BUS_MASTER);
186
187 /* Compute new resource settings based on what PnP assigned */
188 PciComputeNewCurrentSettings(PdoExtension, Resources);
189
190 /* Set these new resources on the device */
191 Status = PciSetResources(PdoExtension, TRUE, TRUE);
192 if (NT_SUCCESS(Status))
193 {
194 /* Some work needs to happen here to handle this */
195 ASSERT(Resources->Count == 1);
196 //ASSERT(PartialList->Count > 0);
197
198 UNIMPLEMENTED;
199
200 /* Return the allocated resources, and success */
201 *AllocatedResources = Resources;
202 Resources = NULL;
203 Status = STATUS_SUCCESS;
204 }
205 }
206 else
207 {
208 /* If assignment failed, no resources should exist */
209 ASSERT(Resources == NULL);
210 }
211
212 /* If assignment succeeed, then we are done */
213 if (NT_SUCCESS(Status)) break;
214 }
215
216 /* Otherwise, cache the new routing */
217 PciCacheLegacyDeviceRouting(ExistingDeviceObject,
218 BusNumber,
219 SlotNumber,
220 PciData.u.type0.InterruptLine,
221 PciData.u.type0.InterruptPin,
222 PciData.BaseClass,
223 PciData.SubClass,
224 PdoExtension->ParentFdoExtension->
225 PhysicalDeviceObject,
226 PdoExtension,
227 NULL);
228 }
229 } while (0);
230
231 /* Release the lock */
232 KeSetEvent(&PciGlobalLock, 0, 0);
233 KeLeaveCriticalRegion();
234
235 /* Free any temporary resource data and return the status */
236 if (RequirementsList) ExFreePoolWithTag(RequirementsList, 0);
237 if (Resources) ExFreePoolWithTag(Resources, 0);
238 return Status;
239 }
240
241 VOID
242 NTAPI
243 PciHookHal(VOID)
244 {
245 /* Save the old HAL routines */
246 ASSERT(PcipSavedAssignSlotResources == NULL);
247 ASSERT(PcipSavedTranslateBusAddress == NULL);
248 PcipSavedAssignSlotResources = HalPciAssignSlotResources;
249 PcipSavedTranslateBusAddress = HalPciTranslateBusAddress;
250
251 /* Take over the HAL's Bus Handler functions */
252 // HalPciAssignSlotResources = PciAssignSlotResources;
253 HalPciTranslateBusAddress = PciTranslateBusAddress;
254 }
255
256 /* EOF */