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
);
207 HaliRegisterBusHandler(IN INTERFACE_TYPE InterfaceType
,
208 IN BUS_DATA_TYPE ConfigType
,
210 IN INTERFACE_TYPE ParentBusType
,
211 IN ULONG ParentBusNumber
,
213 IN PINSTALL_BUS_HANDLER InstallCallback
,
214 OUT PBUS_HANDLER
*ReturnedBusHandler
)
216 PHAL_BUS_HANDLER Bus
, OldHandler
= NULL
;
217 PHAL_BUS_HANDLER
* BusEntry
;
219 PARRAY InterfaceArray
, InterfaceBusNumberArray
, ConfigArray
, ConfigBusNumberArray
;
220 PBUS_HANDLER ParentHandler
;
224 /* Make sure we have a valid handler */
225 ASSERT((InterfaceType
!= InterfaceTypeUndefined
) ||
226 (ConfigType
!= ConfigurationSpaceUndefined
));
228 /* Allocate the bus handler */
229 Bus
= ExAllocatePoolWithTag(NonPagedPool
,
230 sizeof(HAL_BUS_HANDLER
) + ExtraData
,
232 if (!Bus
) return STATUS_INSUFFICIENT_RESOURCES
;
234 /* Return the handler */
235 *ReturnedBusHandler
= &Bus
->Handler
;
237 /* FIXME: Fix the kernel first. Don't page us out */
238 //CodeHandle = MmLockPagableDataSection(&HaliRegisterBusHandler);
240 /* Synchronize with anyone else */
241 KeWaitForSingleObject(&HalpBusDatabaseEvent
,
247 /* Check for unknown/root bus */
250 /* We must have an interface */
251 ASSERT(InterfaceType
!= InterfaceTypeUndefined
);
253 /* Find the right bus */
255 while (HaliHandlerForBus(InterfaceType
, BusNumber
)) BusNumber
++;
258 /* Allocate arrays for the handler */
259 InterfaceArray
= HalpAllocateArray(InterfaceType
);
260 InterfaceBusNumberArray
= HalpAllocateArray(BusNumber
);
261 ConfigArray
= HalpAllocateArray(ConfigType
);
262 ConfigBusNumberArray
= HalpAllocateArray(BusNumber
);
264 /* Only proceed if all allocations succeeded */
265 if ((InterfaceArray
) && (InterfaceBusNumberArray
) && (ConfigArray
) && (ConfigBusNumberArray
))
267 /* Find the parent handler if any */
268 ParentHandler
= HaliReferenceHandlerForBus(ParentBusType
, ParentBusNumber
);
270 /* Initialize the handler */
271 RtlZeroMemory(Bus
, sizeof(HAL_BUS_HANDLER
) + ExtraData
);
272 Bus
->ReferenceCount
= 1;
274 /* Fill out bus data */
275 Bus
->Handler
.BusNumber
= BusNumber
;
276 Bus
->Handler
.InterfaceType
= InterfaceType
;
277 Bus
->Handler
.ConfigurationType
= ConfigType
;
278 Bus
->Handler
.ParentHandler
= ParentHandler
;
280 /* Fill out dummy handlers */
281 Bus
->Handler
.GetBusData
= HalpNoBusData
;
282 Bus
->Handler
.SetBusData
= HalpNoBusData
;
283 Bus
->Handler
.AdjustResourceList
= HalpNoAdjustResourceList
;
284 Bus
->Handler
.AssignSlotResources
= HalpNoAssignSlotResources
;
286 /* Make space for extra data */
287 if (ExtraData
) Bus
->Handler
.BusData
= Bus
+ 1;
289 /* Check for a parent handler */
292 /* Inherit the parent routines */
293 Bus
->Handler
.GetBusData
= ParentHandler
->GetBusData
;
294 Bus
->Handler
.SetBusData
= ParentHandler
->SetBusData
;
295 Bus
->Handler
.AdjustResourceList
= ParentHandler
->AdjustResourceList
;
296 Bus
->Handler
.AssignSlotResources
= ParentHandler
->AssignSlotResources
;
297 Bus
->Handler
.TranslateBusAddress
= ParentHandler
->TranslateBusAddress
;
298 Bus
->Handler
.GetInterruptVector
= ParentHandler
->GetInterruptVector
;
301 /* We don't support this yet */
302 ASSERT(!InstallCallback
);
305 KeAcquireSpinLock(&HalpBusDatabaseSpinLock
, &OldIrql
);
307 /* Make space for the interface */
308 HalpGrowArray(&HalpBusTable
, &InterfaceArray
);
310 /* Check if we really have an interface */
311 if (InterfaceType
!= InterfaceTypeUndefined
)
313 /* Make space for the association */
314 HalpGrowArray((PARRAY
*)&HalpBusTable
->Element
[InterfaceType
],
315 &InterfaceBusNumberArray
);
317 /* Get the bus handler pointer */
318 BusEntry
= (PHAL_BUS_HANDLER
*)&((PARRAY
)HalpBusTable
->Element
[InterfaceType
])->Element
[BusNumber
];
320 /* Check if there was already a handler there, and set the new one */
321 if (*BusEntry
) OldHandler
= *BusEntry
;
325 /* Now add a space for the configuration space */
326 HalpGrowArray(&HalpConfigTable
, &ConfigArray
);
328 /* Check if we really have one */
329 if (ConfigType
!= ConfigurationSpaceUndefined
)
331 /* Make space for this association */
332 HalpGrowArray((PARRAY
*)&HalpConfigTable
->Element
[ConfigType
],
333 &ConfigBusNumberArray
);
335 /* Get the bus handler pointer */
336 BusEntry
= (PHAL_BUS_HANDLER
*)&((PARRAY
)HalpConfigTable
->Element
[ConfigType
])->Element
[BusNumber
];
339 /* Get the old entry, but make sure it's the same we had before */
340 ASSERT((OldHandler
== NULL
) || (OldHandler
== *BusEntry
));
341 OldHandler
= *BusEntry
;
344 /* Set the new entry */
348 /* Link the adapter */
349 InsertTailList(&HalpAllBusHandlers
, &Bus
->AllHandlers
);
351 /* Remove the old linkage */
353 if (Bus
) RemoveEntryList(&Bus
->AllHandlers
);
355 /* Release the lock */
356 KeReleaseSpinLock(&HalpBusDatabaseSpinLock
, OldIrql
);
357 Status
= STATUS_SUCCESS
;
362 Status
= STATUS_INSUFFICIENT_RESOURCES
;
365 /* Signal the event */
366 KeSetEvent(&HalpBusDatabaseEvent
, 0, FALSE
);
368 /* FIXME: Fix the kernel first. Re-page the function */
369 //MmUnlockPagableImageSection(CodeHandle);
371 /* Free all allocations */
372 if (Bus
) ExFreePool(Bus
);
373 if (InterfaceArray
) ExFreePool(InterfaceArray
);
374 if (InterfaceBusNumberArray
) ExFreePool(InterfaceBusNumberArray
);
375 if (ConfigArray
) ExFreePool(ConfigArray
);
376 if (ConfigBusNumberArray
) ExFreePool(ConfigBusNumberArray
);
385 HalpInitBusHandler(VOID
)
387 /* Setup the bus lock */
388 KeInitializeSpinLock(&HalpBusDatabaseSpinLock
);
390 /* Setup the bus event */
391 KeInitializeEvent(&HalpBusDatabaseEvent
, SynchronizationEvent
, TRUE
);
393 /* Setup the bus configuration and bus table */
394 HalpBusTable
= HalpAllocateArray(0);
395 HalpConfigTable
= HalpAllocateArray(0);
397 /* Setup the bus list */
398 InitializeListHead(&HalpAllBusHandlers
);
400 /* Setup the HAL Dispatch routines */
402 HalRegisterBusHandler
= HaliRegisterBusHandler
;
403 HalHandlerForBus
= HaliHandlerForBus
;
404 HalHandlerForConfigSpace
= HaliHandlerForConfigSpace
;
405 HalReferenceHandlerForBus
= HaliReferenceHandlerForBus
;
406 HalReferenceBusHandler
= HaliReferenceBusHandler
;
407 HalDereferenceBusHandler
= HaliDereferenceBusHandler
;
409 HalPciAssignSlotResources
= HalpAssignSlotResources
;
410 /* FIXME: Fix later */
412 HalPciTranslateBusAddress
= HaliTranslateBusAddress
;
413 if (!HalFindBusAddressTranslation
) HalFindBusAddressTranslation
= HaliFindBusAddressTranslation
;
415 /* These should be written by the PCI driver later, but we give defaults */
416 HalPciTranslateBusAddress
= HalpTranslateBusAddress
;
417 HalFindBusAddressTranslation
= HalpFindBusAddressTranslation
;