3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/bus/bushndlr.c
5 * PURPOSE: Generic HAL Bus Handler Support
6 * PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org)
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 KSPIN_LOCK HalpBusDatabaseSpinLock
;
18 KEVENT HalpBusDatabaseEvent
;
19 LIST_ENTRY HalpAllBusHandlers
;
21 PARRAY HalpConfigTable
;
23 /* PRIVATE FUNCTIONS **********************************************************/
27 HalpAllocateArray(IN ULONG ArraySize
)
32 /* Compute array size */
33 if (ArraySize
== MAXULONG
) ArraySize
= 0;
34 Size
= ArraySize
* sizeof(PARRAY
) + sizeof(ARRAY
);
36 /* Allocate the array */
37 Array
= ExAllocatePoolWithTag(NonPagedPool
,
40 if (!Array
) KeBugCheckEx(HAL_MEMORY_ALLOCATION
, Size
, 0, (ULONG_PTR
)__FILE__
, __LINE__
);
43 Array
->ArraySize
= ArraySize
;
44 RtlZeroMemory(Array
->Element
, sizeof(PVOID
) * (ArraySize
+ 1));
50 HalpGrowArray(IN PARRAY
*CurrentArray
,
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
))
58 /* Does it exist (and can it fit?) */
61 /* Copy the current array into the new one */
62 RtlCopyMemory(&(*NewArray
)->Element
,
63 &(*CurrentArray
)->Element
,
64 sizeof(PVOID
) * ((*CurrentArray
)->ArraySize
+ 1));
67 /* Swap the pointers (XOR swap would be more l33t) */
69 *CurrentArray
= *NewArray
;
76 HalpLookupHandler(IN PARRAY Array
,
79 IN BOOLEAN AddReference
)
82 PBUS_HANDLER Handler
= NULL
;
84 /* Make sure the entry exists */
85 if (Array
->ArraySize
>= Type
)
88 Array
= Array
->Element
[Type
];
90 /* Make sure the entry array exists */
91 if ((Array
) && (Array
->ArraySize
>= Number
))
93 /* Retrieve the bus and its handler */
94 Bus
= Array
->Element
[Number
];
95 Handler
= &Bus
->Handler
;
97 /* Reference the handler if needed */
98 if (AddReference
) Bus
->ReferenceCount
++;
102 /* Return the handler */
108 HalpNoBusData(IN PBUS_HANDLER BusHandler
,
109 IN PBUS_HANDLER RootHandler
,
115 /* Not implemented */
116 DPRINT1("STUB GetSetBusData\n");
122 HalpNoAdjustResourceList(IN PBUS_HANDLER BusHandler
,
123 IN PBUS_HANDLER RootHandler
,
124 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST
*pResourceList
)
126 DPRINT1("STUB Adjustment\n");
127 return STATUS_UNSUCCESSFUL
;
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
,
139 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
141 DPRINT1("STUB Assignment\n");
142 return STATUS_NOT_SUPPORTED
;
147 HaliReferenceBusHandler(IN PBUS_HANDLER Handler
)
149 PHAL_BUS_HANDLER Bus
;
151 /* Find and reference the bus handler */
152 Bus
= CONTAINING_RECORD(Handler
, HAL_BUS_HANDLER
, Handler
);
153 Bus
->ReferenceCount
++;
158 HaliDereferenceBusHandler(IN PBUS_HANDLER Handler
)
160 PHAL_BUS_HANDLER Bus
;
162 /* Find and dereference the bus handler */
163 Bus
= CONTAINING_RECORD(Handler
, HAL_BUS_HANDLER
, Handler
);
164 Bus
->ReferenceCount
--;
165 ASSERT(Bus
->ReferenceCount
!= 0);
170 HaliHandlerForBus(IN INTERFACE_TYPE InterfaceType
,
173 /* Lookup the interface in the bus table */
174 return HalpLookupHandler(HalpBusTable
, InterfaceType
, BusNumber
, FALSE
);
179 HaliHandlerForConfigSpace(IN BUS_DATA_TYPE ConfigType
,
182 /* Lookup the configuration in the configuration table */
183 return HalpLookupHandler(HalpConfigTable
, ConfigType
, BusNumber
, FALSE
);
188 HaliReferenceHandlerForBus(IN INTERFACE_TYPE InterfaceType
,
191 /* Lookup the interface in the bus table, and reference the handler */
192 return HalpLookupHandler(HalpBusTable
, InterfaceType
, BusNumber
, TRUE
);
197 HaliReferenceHandlerForConfigSpace(IN BUS_DATA_TYPE ConfigType
,
200 /* Lookup the configuration in the configuration table and add a reference */
201 return HalpLookupHandler(HalpConfigTable
, ConfigType
, BusNumber
, TRUE
);
206 HalpContextToBusHandler(IN ULONG_PTR ContextValue
)
208 PLIST_ENTRY NextEntry
;
209 PHAL_BUS_HANDLER BusHandler
, ThisHandler
;
212 NextEntry
= HalpAllBusHandlers
.Flink
;
213 ThisHandler
= CONTAINING_RECORD(NextEntry
, HAL_BUS_HANDLER
, AllHandlers
);
216 /* If the list is empty, quit */
217 if (IsListEmpty(&HalpAllBusHandlers
)) return NULL
;
219 /* Otherwise, scan the list */
220 BusHandler
= CONTAINING_RECORD(ContextValue
, HAL_BUS_HANDLER
, Handler
);
223 /* Check if we've reached the right one */
224 ThisHandler
= CONTAINING_RECORD(NextEntry
, HAL_BUS_HANDLER
, AllHandlers
);
225 if (ThisHandler
== BusHandler
) break;
227 /* Try the next one */
228 NextEntry
= NextEntry
->Flink
;
229 } while (NextEntry
!= &HalpAllBusHandlers
);
232 /* If we looped back to the end, we didn't find anything */
233 if (NextEntry
== &HalpAllBusHandlers
) return NULL
;
235 /* Otherwise return the handler */
236 return &ThisHandler
->Handler
;
242 HaliRegisterBusHandler(IN INTERFACE_TYPE InterfaceType
,
243 IN BUS_DATA_TYPE ConfigType
,
245 IN INTERFACE_TYPE ParentBusType
,
246 IN ULONG ParentBusNumber
,
248 IN PINSTALL_BUS_HANDLER InstallCallback
,
249 OUT PBUS_HANDLER
*ReturnedBusHandler
)
251 PHAL_BUS_HANDLER Bus
, OldHandler
= NULL
;
252 PHAL_BUS_HANDLER
* BusEntry
;
254 PARRAY InterfaceArray
, InterfaceBusNumberArray
, ConfigArray
, ConfigBusNumberArray
;
255 PBUS_HANDLER ParentHandler
;
259 /* Make sure we have a valid handler */
260 ASSERT((InterfaceType
!= InterfaceTypeUndefined
) ||
261 (ConfigType
!= ConfigurationSpaceUndefined
));
263 /* Allocate the bus handler */
264 Bus
= ExAllocatePoolWithTag(NonPagedPool
,
265 sizeof(HAL_BUS_HANDLER
) + ExtraData
,
267 if (!Bus
) return STATUS_INSUFFICIENT_RESOURCES
;
269 /* Return the handler */
270 *ReturnedBusHandler
= &Bus
->Handler
;
272 /* FIXME: Fix the kernel first. Don't page us out */
273 //CodeHandle = MmLockPagableDataSection(&HaliRegisterBusHandler);
275 /* Synchronize with anyone else */
276 KeWaitForSingleObject(&HalpBusDatabaseEvent
,
282 /* Check for unknown/root bus */
285 /* We must have an interface */
286 ASSERT(InterfaceType
!= InterfaceTypeUndefined
);
288 /* Find the right bus */
290 while (HaliHandlerForBus(InterfaceType
, BusNumber
)) BusNumber
++;
293 /* Allocate arrays for the handler */
294 InterfaceArray
= HalpAllocateArray(InterfaceType
);
295 InterfaceBusNumberArray
= HalpAllocateArray(BusNumber
);
296 ConfigArray
= HalpAllocateArray(ConfigType
);
297 ConfigBusNumberArray
= HalpAllocateArray(BusNumber
);
299 /* Only proceed if all allocations succeeded */
300 if ((InterfaceArray
) && (InterfaceBusNumberArray
) && (ConfigArray
) && (ConfigBusNumberArray
))
302 /* Find the parent handler if any */
303 ParentHandler
= HaliReferenceHandlerForBus(ParentBusType
, ParentBusNumber
);
305 /* Initialize the handler */
306 RtlZeroMemory(Bus
, sizeof(HAL_BUS_HANDLER
) + ExtraData
);
307 Bus
->ReferenceCount
= 1;
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
;
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
;
321 /* Make space for extra data */
322 if (ExtraData
) Bus
->Handler
.BusData
= Bus
+ 1;
324 /* Check for a parent handler */
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
;
336 /* We don't support this yet */
337 ASSERT(!InstallCallback
);
340 KeAcquireSpinLock(&HalpBusDatabaseSpinLock
, &OldIrql
);
342 /* Make space for the interface */
343 HalpGrowArray(&HalpBusTable
, &InterfaceArray
);
345 /* Check if we really have an interface */
346 if (InterfaceType
!= InterfaceTypeUndefined
)
348 /* Make space for the association */
349 HalpGrowArray((PARRAY
*)&HalpBusTable
->Element
[InterfaceType
],
350 &InterfaceBusNumberArray
);
352 /* Get the bus handler pointer */
353 BusEntry
= (PHAL_BUS_HANDLER
*)&((PARRAY
)HalpBusTable
->Element
[InterfaceType
])->Element
[BusNumber
];
355 /* Check if there was already a handler there, and set the new one */
356 if (*BusEntry
) OldHandler
= *BusEntry
;
360 /* Now add a space for the configuration space */
361 HalpGrowArray(&HalpConfigTable
, &ConfigArray
);
363 /* Check if we really have one */
364 if (ConfigType
!= ConfigurationSpaceUndefined
)
366 /* Make space for this association */
367 HalpGrowArray((PARRAY
*)&HalpConfigTable
->Element
[ConfigType
],
368 &ConfigBusNumberArray
);
370 /* Get the bus handler pointer */
371 BusEntry
= (PHAL_BUS_HANDLER
*)&((PARRAY
)HalpConfigTable
->Element
[ConfigType
])->Element
[BusNumber
];
374 /* Get the old entry, but make sure it's the same we had before */
375 ASSERT((OldHandler
== NULL
) || (OldHandler
== *BusEntry
));
376 OldHandler
= *BusEntry
;
379 /* Set the new entry */
383 /* Link the adapter */
384 InsertTailList(&HalpAllBusHandlers
, &Bus
->AllHandlers
);
386 /* Remove the old linkage */
388 if (Bus
) RemoveEntryList(&Bus
->AllHandlers
);
390 /* Release the lock */
391 KeReleaseSpinLock(&HalpBusDatabaseSpinLock
, OldIrql
);
392 Status
= STATUS_SUCCESS
;
397 Status
= STATUS_INSUFFICIENT_RESOURCES
;
400 /* Signal the event */
401 KeSetEvent(&HalpBusDatabaseEvent
, 0, FALSE
);
403 /* FIXME: Fix the kernel first. Re-page the function */
404 //MmUnlockPagableImageSection(CodeHandle);
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
);
420 HalpInitBusHandler(VOID
)
422 /* Setup the bus lock */
423 KeInitializeSpinLock(&HalpBusDatabaseSpinLock
);
425 /* Setup the bus event */
426 KeInitializeEvent(&HalpBusDatabaseEvent
, SynchronizationEvent
, TRUE
);
428 /* Setup the bus configuration and bus table */
429 HalpBusTable
= HalpAllocateArray(0);
430 HalpConfigTable
= HalpAllocateArray(0);
432 /* Setup the bus list */
433 InitializeListHead(&HalpAllBusHandlers
);
435 /* Setup the HAL Dispatch routines */
437 HalRegisterBusHandler
= HaliRegisterBusHandler
;
438 HalHandlerForBus
= HaliHandlerForBus
;
439 HalHandlerForConfigSpace
= HaliHandlerForConfigSpace
;
440 HalReferenceHandlerForBus
= HaliReferenceHandlerForBus
;
441 HalReferenceBusHandler
= HaliReferenceBusHandler
;
442 HalDereferenceBusHandler
= HaliDereferenceBusHandler
;
444 HalPciAssignSlotResources
= HalpAssignSlotResources
;
445 HalPciTranslateBusAddress
= HaliTranslateBusAddress
; /* PCI Driver can override */
446 if (!HalFindBusAddressTranslation
) HalFindBusAddressTranslation
= HaliFindBusAddressTranslation
;