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