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