1 /* 2 * PROJECT: ReactOS HAL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: hal/halx86/legacy/bus/bushndlr.c 5 * PURPOSE: Generic HAL Bus Handler Support 6 * PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org) 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <hal.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* GLOBALS ********************************************************************/ 16 17 KSPIN_LOCK HalpBusDatabaseSpinLock; 18 KEVENT HalpBusDatabaseEvent; 19 LIST_ENTRY HalpAllBusHandlers; 20 PARRAY HalpBusTable; 21 PARRAY HalpConfigTable; 22 23 /* PRIVATE FUNCTIONS **********************************************************/ 24 25 PARRAY 26 NTAPI 27 HalpAllocateArray(IN ULONG ArraySize) 28 { 29 PARRAY Array; 30 ULONG Size; 31 32 /* Compute array size */ 33 if (ArraySize == MAXULONG) ArraySize = 0; 34 Size = ArraySize * sizeof(PARRAY) + sizeof(ARRAY); 35 36 /* Allocate the array */ 37 Array = ExAllocatePoolWithTag(NonPagedPool, 38 Size, 39 TAG_BUS_HANDLER); 40 if (!Array) KeBugCheckEx(HAL_MEMORY_ALLOCATION, Size, 0, (ULONG_PTR)__FILE__, __LINE__); 41 42 /* Initialize it */ 43 Array->ArraySize = ArraySize; 44 RtlZeroMemory(Array->Element, sizeof(PVOID) * (ArraySize + 1)); 45 return Array; 46 } 47 48 VOID 49 NTAPI 50 HalpGrowArray(IN PARRAY *CurrentArray, 51 IN PARRAY *NewArray) 52 { 53 PVOID Tmp; 54 55 /* Check if the current array doesn't exist yet, or if it's smaller than the new one */ 56 if (!(*CurrentArray) || ((*NewArray)->ArraySize > (*CurrentArray)->ArraySize)) 57 { 58 /* Does it exist (and can it fit?) */ 59 if (*CurrentArray) 60 { 61 /* Copy the current array into the new one */ 62 RtlCopyMemory(&(*NewArray)->Element, 63 &(*CurrentArray)->Element, 64 sizeof(PVOID) * ((*CurrentArray)->ArraySize + 1)); 65 } 66 67 /* Swap the pointers (XOR swap would be more l33t) */ 68 Tmp = *CurrentArray; 69 *CurrentArray = *NewArray; 70 *NewArray = Tmp; 71 } 72 } 73 74 PBUS_HANDLER 75 FASTCALL 76 HalpLookupHandler(IN PARRAY Array, 77 IN ULONG Type, 78 IN ULONG Number, 79 IN BOOLEAN AddReference) 80 { 81 PHAL_BUS_HANDLER Bus; 82 PBUS_HANDLER Handler = NULL; 83 84 /* Make sure the entry exists */ 85 if (Array->ArraySize >= Type) 86 { 87 /* Retrieve it */ 88 Array = Array->Element[Type]; 89 90 /* Make sure the entry array exists */ 91 if ((Array) && (Array->ArraySize >= Number)) 92 { 93 /* Retrieve the bus and its handler */ 94 Bus = Array->Element[Number]; 95 Handler = &Bus->Handler; 96 97 /* Reference the handler if needed */ 98 if (AddReference) Bus->ReferenceCount++; 99 } 100 } 101 102 /* Return the handler */ 103 return Handler; 104 } 105 106 ULONG 107 NTAPI 108 HalpNoBusData(IN PBUS_HANDLER BusHandler, 109 IN PBUS_HANDLER RootHandler, 110 IN ULONG SlotNumber, 111 IN PVOID Buffer, 112 IN ULONG Offset, 113 IN ULONG Length) 114 { 115 /* Not implemented */ 116 DPRINT1("STUB GetSetBusData\n"); 117 return 0; 118 } 119 120 NTSTATUS 121 NTAPI 122 HalpNoAdjustResourceList(IN PBUS_HANDLER BusHandler, 123 IN PBUS_HANDLER RootHandler, 124 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList) 125 { 126 DPRINT1("STUB Adjustment\n"); 127 return STATUS_UNSUCCESSFUL; 128 } 129 130 NTSTATUS 131 NTAPI 132 HalpNoAssignSlotResources(IN PBUS_HANDLER BusHandler, 133 IN PBUS_HANDLER RootHandler, 134 IN PUNICODE_STRING RegistryPath, 135 IN PUNICODE_STRING DriverClassName OPTIONAL, 136 IN PDRIVER_OBJECT DriverObject, 137 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 138 IN ULONG SlotNumber, 139 IN OUT PCM_RESOURCE_LIST *AllocatedResources) 140 { 141 DPRINT1("STUB Assignment\n"); 142 return STATUS_NOT_SUPPORTED; 143 } 144 145 VOID 146 FASTCALL 147 HaliReferenceBusHandler(IN PBUS_HANDLER Handler) 148 { 149 PHAL_BUS_HANDLER Bus; 150 151 /* Find and reference the bus handler */ 152 Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler); 153 Bus->ReferenceCount++; 154 } 155 156 VOID 157 FASTCALL 158 HaliDereferenceBusHandler(IN PBUS_HANDLER Handler) 159 { 160 PHAL_BUS_HANDLER Bus; 161 162 /* Find and dereference the bus handler */ 163 Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler); 164 Bus->ReferenceCount--; 165 ASSERT(Bus->ReferenceCount != 0); 166 } 167 168 PBUS_HANDLER 169 FASTCALL 170 HaliHandlerForBus(IN INTERFACE_TYPE InterfaceType, 171 IN ULONG BusNumber) 172 { 173 /* Lookup the interface in the bus table */ 174 return HalpLookupHandler(HalpBusTable, InterfaceType, BusNumber, FALSE); 175 } 176 177 PBUS_HANDLER 178 FASTCALL 179 HaliHandlerForConfigSpace(IN BUS_DATA_TYPE ConfigType, 180 IN ULONG BusNumber) 181 { 182 /* Lookup the configuration in the configuration table */ 183 return HalpLookupHandler(HalpConfigTable, ConfigType, BusNumber, FALSE); 184 } 185 186 PBUS_HANDLER 187 FASTCALL 188 HaliReferenceHandlerForBus(IN INTERFACE_TYPE InterfaceType, 189 IN ULONG BusNumber) 190 { 191 /* Lookup the interface in the bus table, and reference the handler */ 192 return HalpLookupHandler(HalpBusTable, InterfaceType, BusNumber, TRUE); 193 } 194 195 PBUS_HANDLER 196 FASTCALL 197 HaliReferenceHandlerForConfigSpace(IN BUS_DATA_TYPE ConfigType, 198 IN ULONG BusNumber) 199 { 200 /* Lookup the configuration in the configuration table and add a reference */ 201 return HalpLookupHandler(HalpConfigTable, ConfigType, BusNumber, TRUE); 202 } 203 204 PBUS_HANDLER 205 NTAPI 206 HalpContextToBusHandler(IN ULONG_PTR ContextValue) 207 { 208 PLIST_ENTRY NextEntry; 209 PHAL_BUS_HANDLER BusHandler, ThisHandler; 210 211 /* Start lookup */ 212 NextEntry = HalpAllBusHandlers.Flink; 213 ThisHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers); 214 if (ContextValue) 215 { 216 /* If the list is empty, quit */ 217 if (IsListEmpty(&HalpAllBusHandlers)) return NULL; 218 219 /* Otherwise, scan the list */ 220 BusHandler = CONTAINING_RECORD(ContextValue, HAL_BUS_HANDLER, Handler); 221 do 222 { 223 /* Check if we've reached the right one */ 224 ThisHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers); 225 if (ThisHandler == BusHandler) break; 226 227 /* Try the next one */ 228 NextEntry = NextEntry->Flink; 229 } while (NextEntry != &HalpAllBusHandlers); 230 } 231 232 /* If we looped back to the end, we didn't find anything */ 233 if (NextEntry == &HalpAllBusHandlers) return NULL; 234 235 /* Otherwise return the handler */ 236 return &ThisHandler->Handler; 237 } 238 239 #ifndef _MINIHAL_ 240 NTSTATUS 241 NTAPI 242 HaliRegisterBusHandler(IN INTERFACE_TYPE InterfaceType, 243 IN BUS_DATA_TYPE ConfigType, 244 IN ULONG BusNumber, 245 IN INTERFACE_TYPE ParentBusType, 246 IN ULONG ParentBusNumber, 247 IN ULONG ExtraData, 248 IN PINSTALL_BUS_HANDLER InstallCallback, 249 OUT PBUS_HANDLER *ReturnedBusHandler) 250 { 251 PHAL_BUS_HANDLER Bus, OldHandler = NULL; 252 PHAL_BUS_HANDLER* BusEntry; 253 //PVOID CodeHandle; 254 PARRAY InterfaceArray, InterfaceBusNumberArray, ConfigArray, ConfigBusNumberArray; 255 PBUS_HANDLER ParentHandler; 256 KIRQL OldIrql; 257 NTSTATUS Status; 258 259 /* Make sure we have a valid handler */ 260 ASSERT((InterfaceType != InterfaceTypeUndefined) || 261 (ConfigType != ConfigurationSpaceUndefined)); 262 263 /* Allocate the bus handler */ 264 Bus = ExAllocatePoolWithTag(NonPagedPool, 265 sizeof(HAL_BUS_HANDLER) + ExtraData, 266 TAG_BUS_HANDLER); 267 if (!Bus) return STATUS_INSUFFICIENT_RESOURCES; 268 269 /* Return the handler */ 270 *ReturnedBusHandler = &Bus->Handler; 271 272 /* FIXME: Fix the kernel first. Don't page us out */ 273 //CodeHandle = MmLockPagableDataSection(&HaliRegisterBusHandler); 274 275 /* Synchronize with anyone else */ 276 KeWaitForSingleObject(&HalpBusDatabaseEvent, 277 WrExecutive, 278 KernelMode, 279 FALSE, 280 NULL); 281 282 /* Check for unknown/root bus */ 283 if (BusNumber == -1) 284 { 285 /* We must have an interface */ 286 ASSERT(InterfaceType != InterfaceTypeUndefined); 287 288 /* Find the right bus */ 289 BusNumber = 0; 290 while (HaliHandlerForBus(InterfaceType, BusNumber)) BusNumber++; 291 } 292 293 /* Allocate arrays for the handler */ 294 InterfaceArray = HalpAllocateArray(InterfaceType); 295 InterfaceBusNumberArray = HalpAllocateArray(BusNumber); 296 ConfigArray = HalpAllocateArray(ConfigType); 297 ConfigBusNumberArray = HalpAllocateArray(BusNumber); 298 299 /* Only proceed if all allocations succeeded */ 300 if ((InterfaceArray) && (InterfaceBusNumberArray) && (ConfigArray) && (ConfigBusNumberArray)) 301 { 302 /* Find the parent handler if any */ 303 ParentHandler = HaliReferenceHandlerForBus(ParentBusType, ParentBusNumber); 304 305 /* Initialize the handler */ 306 RtlZeroMemory(Bus, sizeof(HAL_BUS_HANDLER) + ExtraData); 307 Bus->ReferenceCount = 1; 308 309 /* Fill out bus data */ 310 Bus->Handler.BusNumber = BusNumber; 311 Bus->Handler.InterfaceType = InterfaceType; 312 Bus->Handler.ConfigurationType = ConfigType; 313 Bus->Handler.ParentHandler = ParentHandler; 314 315 /* Fill out dummy handlers */ 316 Bus->Handler.GetBusData = HalpNoBusData; 317 Bus->Handler.SetBusData = HalpNoBusData; 318 Bus->Handler.AdjustResourceList = HalpNoAdjustResourceList; 319 Bus->Handler.AssignSlotResources = HalpNoAssignSlotResources; 320 321 /* Make space for extra data */ 322 if (ExtraData) Bus->Handler.BusData = Bus + 1; 323 324 /* Check for a parent handler */ 325 if (ParentHandler) 326 { 327 /* Inherit the parent routines */ 328 Bus->Handler.GetBusData = ParentHandler->GetBusData; 329 Bus->Handler.SetBusData = ParentHandler->SetBusData; 330 Bus->Handler.AdjustResourceList = ParentHandler->AdjustResourceList; 331 Bus->Handler.AssignSlotResources = ParentHandler->AssignSlotResources; 332 Bus->Handler.TranslateBusAddress = ParentHandler->TranslateBusAddress; 333 Bus->Handler.GetInterruptVector = ParentHandler->GetInterruptVector; 334 } 335 336 /* We don't support this yet */ 337 ASSERT(!InstallCallback); 338 339 /* Lock the buses */ 340 KeAcquireSpinLock(&HalpBusDatabaseSpinLock, &OldIrql); 341 342 /* Make space for the interface */ 343 HalpGrowArray(&HalpBusTable, &InterfaceArray); 344 345 /* Check if we really have an interface */ 346 if (InterfaceType != InterfaceTypeUndefined) 347 { 348 /* Make space for the association */ 349 HalpGrowArray((PARRAY*)&HalpBusTable->Element[InterfaceType], 350 &InterfaceBusNumberArray); 351 352 /* Get the bus handler pointer */ 353 BusEntry = (PHAL_BUS_HANDLER*)&((PARRAY)HalpBusTable->Element[InterfaceType])->Element[BusNumber]; 354 355 /* Check if there was already a handler there, and set the new one */ 356 if (*BusEntry) OldHandler = *BusEntry; 357 *BusEntry = Bus; 358 } 359 360 /* Now add a space for the configuration space */ 361 HalpGrowArray(&HalpConfigTable, &ConfigArray); 362 363 /* Check if we really have one */ 364 if (ConfigType != ConfigurationSpaceUndefined) 365 { 366 /* Make space for this association */ 367 HalpGrowArray((PARRAY*)&HalpConfigTable->Element[ConfigType], 368 &ConfigBusNumberArray); 369 370 /* Get the bus handler pointer */ 371 BusEntry = (PHAL_BUS_HANDLER*)&((PARRAY)HalpConfigTable->Element[ConfigType])->Element[BusNumber]; 372 if (*BusEntry) 373 { 374 /* Get the old entry, but make sure it's the same we had before */ 375 ASSERT((OldHandler == NULL) || (OldHandler == *BusEntry)); 376 OldHandler = *BusEntry; 377 } 378 379 /* Set the new entry */ 380 *BusEntry = Bus; 381 } 382 383 /* Link the adapter */ 384 InsertTailList(&HalpAllBusHandlers, &Bus->AllHandlers); 385 386 /* Remove the old linkage */ 387 Bus = OldHandler; 388 if (Bus) RemoveEntryList(&Bus->AllHandlers); 389 390 /* Release the lock */ 391 KeReleaseSpinLock(&HalpBusDatabaseSpinLock, OldIrql); 392 Status = STATUS_SUCCESS; 393 } 394 else 395 { 396 /* Fail */ 397 Status = STATUS_INSUFFICIENT_RESOURCES; 398 } 399 400 /* Signal the event */ 401 KeSetEvent(&HalpBusDatabaseEvent, 0, FALSE); 402 403 /* FIXME: Fix the kernel first. Re-page the function */ 404 //MmUnlockPagableImageSection(CodeHandle); 405 406 /* Free all allocations */ 407 if (Bus) ExFreePoolWithTag(Bus, TAG_BUS_HANDLER); 408 if (InterfaceArray) ExFreePoolWithTag(InterfaceArray, TAG_BUS_HANDLER); 409 if (InterfaceBusNumberArray) ExFreePoolWithTag(InterfaceBusNumberArray, TAG_BUS_HANDLER); 410 if (ConfigArray) ExFreePoolWithTag(ConfigArray, TAG_BUS_HANDLER); 411 if (ConfigBusNumberArray) ExFreePoolWithTag(ConfigBusNumberArray, TAG_BUS_HANDLER); 412 413 /* And we're done */ 414 return Status; 415 } 416 #endif 417 418 VOID 419 NTAPI 420 HalpInitBusHandler(VOID) 421 { 422 /* Setup the bus lock */ 423 KeInitializeSpinLock(&HalpBusDatabaseSpinLock); 424 425 /* Setup the bus event */ 426 KeInitializeEvent(&HalpBusDatabaseEvent, SynchronizationEvent, TRUE); 427 428 /* Setup the bus configuration and bus table */ 429 HalpBusTable = HalpAllocateArray(0); 430 HalpConfigTable = HalpAllocateArray(0); 431 432 /* Setup the bus list */ 433 InitializeListHead(&HalpAllBusHandlers); 434 435 /* Setup the HAL Dispatch routines */ 436 #ifndef _MINIHAL_ 437 HalRegisterBusHandler = HaliRegisterBusHandler; 438 HalHandlerForBus = HaliHandlerForBus; 439 HalHandlerForConfigSpace = HaliHandlerForConfigSpace; 440 HalReferenceHandlerForBus = HaliReferenceHandlerForBus; 441 HalReferenceBusHandler = HaliReferenceBusHandler; 442 HalDereferenceBusHandler = HaliDereferenceBusHandler; 443 #endif 444 HalPciAssignSlotResources = HalpAssignSlotResources; 445 HalPciTranslateBusAddress = HaliTranslateBusAddress; /* PCI Driver can override */ 446 if (!HalFindBusAddressTranslation) HalFindBusAddressTranslation = HaliFindBusAddressTranslation; 447 } 448 449 /* EOF */ 450