Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1755 lines
42 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. bushnd.c
  5. Abstract:
  6. Functions which take either BusType-BusNumber or ConfigType-BusNumberm
  7. and route to a the appropiate registered handler.
  8. Author:
  9. Ken Reneris (kenr) July-28-1994
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "halp.h"
  15. typedef struct _ARRAY {
  16. ULONG ArraySize;
  17. PVOID Element[]; // must be last field
  18. } ARRAY, *PARRAY;
  19. #define ARRAY_SIZE_IN_BYTES(a) ( (a + 1) * sizeof(PARRAY) + \
  20. FIELD_OFFSET(ARRAY, Element) )
  21. typedef struct _HAL_BUS_HANDLER {
  22. LIST_ENTRY AllHandlers;
  23. ULONG ReferenceCount;
  24. BUS_HANDLER Handler;
  25. } HAL_BUS_HANDLER, *PHAL_BUS_HANDLER;
  26. //
  27. // Event to serialize with adding new buses
  28. //
  29. KEVENT HalpBusDatabaseEvent;
  30. //
  31. // Lock to serialize routing functions from accessing handler arrays while
  32. // new buses are added
  33. //
  34. KSPIN_LOCK HalpBusDatabaseSpinLock;
  35. //
  36. // HalpBusTable - pointers to BusHandlers mapped by InterfaceType,BusNumber
  37. //
  38. PARRAY HalpBusTable;
  39. //
  40. // HalpConfigTable - pointers to BusHandlers mapped by ConfigType,BusNumber
  41. //
  42. PARRAY HalpConfigTable;
  43. //
  44. // List of all installed bus handlers
  45. //
  46. LIST_ENTRY HalpAllBusHandlers;
  47. //
  48. // Lock is high_level since some routed functions can occurs at ISR time
  49. //
  50. #define LockBusDatabase(oldirql) \
  51. KeRaiseIrql(HIGH_LEVEL, oldirql); \
  52. KiAcquireSpinLock(&HalpBusDatabaseSpinLock);
  53. #define UnlockBusDatabase(oldirql) \
  54. KiReleaseSpinLock(&HalpBusDatabaseSpinLock); \
  55. KeLowerIrql(oldirql);
  56. #ifdef _PNP_POWER_
  57. extern HAL_CALLBACKS HalCallback;
  58. #endif
  59. //
  60. // Internal prototypes
  61. //
  62. PARRAY
  63. HalpAllocateArray (
  64. IN ULONG Type
  65. );
  66. VOID
  67. HalpGrowArray (
  68. IN PARRAY *CurrentArray,
  69. IN PARRAY *NewArray
  70. );
  71. NTSTATUS
  72. HalpQueryInstalledBusInformation (
  73. OUT PVOID Buffer,
  74. IN ULONG BufferLength,
  75. OUT PULONG ReturnedLength
  76. );
  77. ULONG
  78. HalpNoBusData (
  79. IN PVOID BusHandler,
  80. IN PVOID RootHandler,
  81. IN ULONG SlotNumber,
  82. IN PVOID Buffer,
  83. IN ULONG Offset,
  84. IN ULONG Length
  85. );
  86. NTSTATUS
  87. HalpNoAdjustResourceList (
  88. IN PVOID BusHandler,
  89. IN PVOID RootHandler,
  90. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
  91. );
  92. NTSTATUS
  93. HalpNoAssignSlotResources (
  94. IN PVOID BusHandler,
  95. IN PVOID RootHandler,
  96. IN PUNICODE_STRING RegistryPath,
  97. IN PUNICODE_STRING DriverClassName OPTIONAL,
  98. IN PDRIVER_OBJECT DriverObject,
  99. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  100. IN ULONG SlotNumber,
  101. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  102. );
  103. NTSTATUS
  104. HalpNoQueryBusSlots (
  105. IN PVOID BusHandler,
  106. IN PVOID RootHandler,
  107. IN ULONG BufferSize,
  108. OUT PULONG SlotNumbers,
  109. OUT PULONG ReturnedLength
  110. );
  111. PDEVICE_HANDLER_OBJECT
  112. HalpNoReferenceDeviceHandler (
  113. IN PBUS_HANDLER BusHandler,
  114. IN PBUS_HANDLER RootHandler,
  115. IN ULONG SlotNumber
  116. );
  117. ULONG
  118. HalpNoGetDeviceData (
  119. IN PBUS_HANDLER BusHandler,
  120. IN PBUS_HANDLER RootHandler,
  121. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  122. IN ULONG DataType,
  123. IN PVOID Buffer,
  124. IN ULONG Offset,
  125. IN ULONG Length
  126. );
  127. ULONG
  128. HalpNoSetDeviceData (
  129. IN PBUS_HANDLER BusHandler,
  130. IN PBUS_HANDLER RootHandler,
  131. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  132. IN ULONG DataType,
  133. IN PVOID Buffer,
  134. IN ULONG Offset,
  135. IN ULONG Length
  136. );
  137. BOOLEAN
  138. HaliTranslateBusAddress(
  139. IN INTERFACE_TYPE InterfaceType,
  140. IN ULONG BusNumber,
  141. IN PHYSICAL_ADDRESS BusAddress,
  142. IN OUT PULONG AddressSpace,
  143. OUT PPHYSICAL_ADDRESS TranslatedAddress
  144. );
  145. NTSTATUS
  146. HalpAssignSlotResources (
  147. IN PUNICODE_STRING RegistryPath,
  148. IN PUNICODE_STRING DriverClassName OPTIONAL,
  149. IN PDRIVER_OBJECT DriverObject,
  150. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  151. IN INTERFACE_TYPE BusType,
  152. IN ULONG BusNumber,
  153. IN ULONG SlotNumber,
  154. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  155. );
  156. BOOLEAN
  157. HaliFindBusAddressTranslation(
  158. IN PHYSICAL_ADDRESS BusAddress,
  159. IN OUT PULONG AddressSpace,
  160. OUT PPHYSICAL_ADDRESS TranslatedAddress,
  161. IN OUT PULONG_PTR Context,
  162. IN BOOLEAN NextBus
  163. );
  164. #ifdef ALLOC_PRAGMA
  165. #pragma alloc_text(INIT,HalpInitBusHandler)
  166. #pragma alloc_text(PAGELK,HaliRegisterBusHandler)
  167. #pragma alloc_text(PAGELK,HalpAllocateArray)
  168. #pragma alloc_text(PAGELK,HalpGrowArray)
  169. #pragma alloc_text(PAGE,HalAdjustResourceList)
  170. #pragma alloc_text(PAGE,HalAssignSlotResources)
  171. #pragma alloc_text(PAGE,HalpAssignSlotResources)
  172. #pragma alloc_text(PAGE,HalGetInterruptVector)
  173. #pragma alloc_text(PAGE,HalpNoAdjustResourceList)
  174. #pragma alloc_text(PAGE,HalpNoAssignSlotResources)
  175. #pragma alloc_text(PAGE,HalpNoQueryBusSlots)
  176. #pragma alloc_text(PAGE,HalpNoReferenceDeviceHandler)
  177. //#pragma alloc_text(PAGE,HaliQueryBusSlots)
  178. #pragma alloc_text(PAGE,HalpQueryInstalledBusInformation)
  179. #ifdef _PNP_POWER_
  180. #pragma alloc_text(PAGELK,HaliSuspendHibernateSystem)
  181. #endif
  182. #endif
  183. VOID
  184. HalpInitBusHandler (
  185. VOID
  186. )
  187. /*++
  188. Routine Description:
  189. Initializes global BusHandler data
  190. --*/
  191. {
  192. //
  193. // Initialize bus handler spinlock used to synchronize against
  194. // buses additions while array lookups are done
  195. //
  196. KeInitializeSpinLock (&HalpBusDatabaseSpinLock);
  197. //
  198. // Initialize bus handler synchronzation event used to serialize
  199. // bus additions from < DPC_LVEL
  200. //
  201. KeInitializeEvent (&HalpBusDatabaseEvent, SynchronizationEvent, TRUE);
  202. //
  203. // Initialize global arrays
  204. //
  205. HalpBusTable = HalpAllocateArray (0);
  206. HalpConfigTable = HalpAllocateArray (0);
  207. InitializeListHead (&HalpAllBusHandlers);
  208. //
  209. // Fill in HAL API handlers
  210. //
  211. HalRegisterBusHandler = HaliRegisterBusHandler;
  212. HalHandlerForBus = HaliHandlerForBus;
  213. HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
  214. //HalQueryBusSlots = HaliQueryBusSlots;
  215. HalReferenceHandlerForBus = HaliReferenceHandlerForBus;
  216. HalReferenceBusHandler = HaliReferenceBusHandler;
  217. HalDereferenceBusHandler = HaliDereferenceBusHandler;
  218. HALPDISPATCH->HalPciTranslateBusAddress = HaliTranslateBusAddress;
  219. #if !defined(NO_LEGACY_DRIVERS)
  220. HALPDISPATCH->HalPciAssignSlotResources = HalpAssignSlotResources;
  221. #endif // NO_LEGACY_DRIVERS
  222. //
  223. // Supply the "Bus Handler" version of this routine only
  224. // if this HAL didn't already provide a different version.
  225. //
  226. if (!HALPDISPATCH->HalFindBusAddressTranslation) {
  227. HALPDISPATCH->HalFindBusAddressTranslation =
  228. HaliFindBusAddressTranslation;
  229. }
  230. }
  231. NTSTATUS
  232. HaliRegisterBusHandler (
  233. IN INTERFACE_TYPE InterfaceType,
  234. IN BUS_DATA_TYPE ConfigType,
  235. IN ULONG BusNumber,
  236. IN INTERFACE_TYPE ParentBusType,
  237. IN ULONG ParentBusNumber,
  238. IN ULONG SizeofBusExtensionData,
  239. IN PINSTALL_BUS_HANDLER InstallBusHandler,
  240. OUT PBUS_HANDLER *ReturnedBusHandler
  241. )
  242. /*++
  243. Routine Description:
  244. Adds a BusHandler for InterfaceType,BusNumber and for ConfigType,BusNumber.
  245. Bus specific or Configuration space specific APIs are routed to the
  246. bus or configuration specific handlers added by this routine.
  247. Arguments:
  248. InterfaceType - Identifies the bus type
  249. InterfaceTypeUndefined if no interface type for this
  250. handler.
  251. ConfigType - Identifies the configuration space type
  252. ConfigurationSpaceUndefined if no configuration space
  253. type for this handler.
  254. BusNumber - Identifies the instance of the bus & config space.
  255. -1 if the next available bus number for this bus
  256. should be used.
  257. ParentBusType - If this bus is a child of a bus, then ParentBusType
  258. ParentBusNumber and ParentBusNumber identifies that bus.
  259. ParentBusType is -1 if no parent bus.
  260. SizeofBusExetensionData - Sizeof bus specific exentsion data required.
  261. InstallBusHandler - Function to call to get the bus specific handlers
  262. added to the bus handler structure.
  263. Return Value:
  264. success; otherwise error code of failure.
  265. --*/
  266. {
  267. PHAL_BUS_HANDLER Bus, *pBusHandler, OldHandler;
  268. PBUS_HANDLER ParentHandler;
  269. KIRQL OldIrql;
  270. NTSTATUS Status;
  271. PARRAY InterfaceArray, InterfaceBusNumberArray;
  272. PARRAY ConfigArray, ConfigBusNumberArray;
  273. PVOID CodeLockHandle;
  274. //
  275. // Must add the handler to at least one table
  276. //
  277. ASSERT (InterfaceType != InterfaceTypeUndefined || ConfigType != ConfigurationSpaceUndefined);
  278. Status = STATUS_SUCCESS;
  279. OldHandler = NULL;
  280. //
  281. // Allocate storage for new bus handler structure
  282. //
  283. Bus = (PHAL_BUS_HANDLER)
  284. ExAllocatePoolWithTag(
  285. NonPagedPool,
  286. sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData,
  287. HAL_POOL_TAG
  288. );
  289. if (!Bus) {
  290. return STATUS_INSUFFICIENT_RESOURCES;
  291. }
  292. //
  293. // Lock pagable code down
  294. //
  295. CodeLockHandle = MmLockPagableCodeSection (&HaliRegisterBusHandler);
  296. //
  297. // Synchronize adding new bus handlers
  298. //
  299. *ReturnedBusHandler = &Bus->Handler;
  300. KeWaitForSingleObject (
  301. &HalpBusDatabaseEvent,
  302. WrExecutive,
  303. KernelMode,
  304. FALSE,
  305. NULL
  306. );
  307. //
  308. // If BusNumber not defined, use next available number for this BusType
  309. //
  310. if (BusNumber == -1) {
  311. ASSERT (InterfaceType != InterfaceTypeUndefined);
  312. BusNumber = 0;
  313. while (HaliHandlerForBus (InterfaceType, BusNumber)) {
  314. BusNumber++;
  315. }
  316. }
  317. //
  318. // Allocate memory for each array in case any index needs to grow
  319. //
  320. InterfaceArray = HalpAllocateArray (InterfaceType);
  321. InterfaceBusNumberArray = HalpAllocateArray (BusNumber);
  322. ConfigArray = HalpAllocateArray (ConfigType);
  323. ConfigBusNumberArray = HalpAllocateArray (BusNumber);
  324. if (!Bus ||
  325. !InterfaceArray ||
  326. !InterfaceBusNumberArray ||
  327. !ConfigArray ||
  328. !ConfigBusNumberArray) {
  329. Status = STATUS_INSUFFICIENT_RESOURCES;
  330. }
  331. if (NT_SUCCESS(Status)) {
  332. //
  333. // Lookup parent handler (if any)
  334. //
  335. ParentHandler = HaliReferenceHandlerForBus (ParentBusType, ParentBusNumber);
  336. //
  337. // Initialize new bus handlers values
  338. //
  339. RtlZeroMemory (Bus, sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData);
  340. Bus->ReferenceCount = 1;
  341. Bus->Handler.BusNumber = BusNumber;
  342. Bus->Handler.InterfaceType = InterfaceType;
  343. Bus->Handler.ConfigurationType = ConfigType;
  344. Bus->Handler.ParentHandler = ParentHandler;
  345. //
  346. // Set to dumby handlers
  347. //
  348. Bus->Handler.GetBusData = HalpNoBusData;
  349. Bus->Handler.SetBusData = HalpNoBusData;
  350. Bus->Handler.AdjustResourceList = HalpNoAdjustResourceList;
  351. Bus->Handler.AssignSlotResources = HalpNoAssignSlotResources;
  352. if (SizeofBusExtensionData) {
  353. Bus->Handler.BusData = Bus + 1;
  354. }
  355. //
  356. // If bus has a parent, inherit handlers from parent as default
  357. //
  358. if (ParentHandler) {
  359. Bus->Handler.GetBusData = ParentHandler->GetBusData;
  360. Bus->Handler.SetBusData = ParentHandler->SetBusData;
  361. Bus->Handler.AdjustResourceList = ParentHandler->AdjustResourceList;
  362. Bus->Handler.AssignSlotResources = ParentHandler->AssignSlotResources;
  363. Bus->Handler.TranslateBusAddress = ParentHandler->TranslateBusAddress;
  364. Bus->Handler.GetInterruptVector = ParentHandler->GetInterruptVector;
  365. }
  366. //
  367. // Install bus specific handlers
  368. //
  369. if (InstallBusHandler) {
  370. Status = InstallBusHandler (&Bus->Handler);
  371. }
  372. if (NT_SUCCESS(Status)) {
  373. //
  374. // Might change addresses of some arrays synchronize
  375. // with routing handlers
  376. //
  377. LockBusDatabase (&OldIrql);
  378. //
  379. // Grow HalpBusTable if needed
  380. //
  381. HalpGrowArray (&HalpBusTable, &InterfaceArray);
  382. if (InterfaceType != InterfaceTypeUndefined) {
  383. //
  384. // Grow HalpBusTable if needed
  385. //
  386. HalpGrowArray (
  387. (PARRAY *) &HalpBusTable->Element[InterfaceType],
  388. &InterfaceBusNumberArray
  389. );
  390. //
  391. // Get registered handler for InterfaceType,BusNumber
  392. //
  393. pBusHandler = &((PHAL_BUS_HANDLER)
  394. ((PARRAY) HalpBusTable->Element[InterfaceType])->Element[BusNumber]);
  395. //
  396. // If handler already defiend, remove the old one
  397. //
  398. if (*pBusHandler) {
  399. OldHandler = *pBusHandler;
  400. }
  401. //
  402. // Set new handler for supplied InterfaceType,BusNumber
  403. //
  404. *pBusHandler = Bus;
  405. }
  406. //
  407. // Grow HalpConfigTable if needed
  408. //
  409. HalpGrowArray (&HalpConfigTable, &ConfigArray);
  410. if (ConfigType != ConfigurationSpaceUndefined) {
  411. //
  412. // Grow HalpConfigTable if needed
  413. //
  414. HalpGrowArray (
  415. (PARRAY *) &HalpConfigTable->Element[ConfigType],
  416. &ConfigBusNumberArray
  417. );
  418. //
  419. // Get registered handler for ConfigType,BusNumber
  420. //
  421. pBusHandler = &((PHAL_BUS_HANDLER)
  422. ((PARRAY) HalpConfigTable->Element[ConfigType])->Element[BusNumber]);
  423. if (*pBusHandler) {
  424. ASSERT (OldHandler == NULL || OldHandler == *pBusHandler);
  425. OldHandler = *pBusHandler;
  426. }
  427. //
  428. // Set new handler for supplied ConfigType,BusNumber
  429. //
  430. *pBusHandler = Bus;
  431. }
  432. //
  433. // Add new bus handler to list of all installed handlers
  434. //
  435. InsertTailList (&HalpAllBusHandlers, &Bus->AllHandlers);
  436. //
  437. // Remove old bus handler
  438. //
  439. Bus = OldHandler;
  440. if (Bus) {
  441. RemoveEntryList (&Bus->AllHandlers);
  442. }
  443. //
  444. // Lookup array modification complete, release lock
  445. //
  446. UnlockBusDatabase (OldIrql);
  447. } else {
  448. if (ParentHandler) {
  449. HaliDereferenceBusHandler (ParentHandler);
  450. }
  451. }
  452. }
  453. //
  454. // Bus addition modifications complete, set event
  455. //
  456. KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
  457. //
  458. // Unlock pagable code
  459. //
  460. MmUnlockPagableImageSection (CodeLockHandle);
  461. //
  462. // Free memory which is not in use
  463. //
  464. if (Bus) {
  465. ExFreePool (Bus);
  466. }
  467. if (InterfaceArray) {
  468. ExFreePool (InterfaceArray);
  469. }
  470. if (InterfaceBusNumberArray) {
  471. ExFreePool (InterfaceBusNumberArray);
  472. }
  473. if (ConfigArray) {
  474. ExFreePool (ConfigArray);
  475. }
  476. if (ConfigBusNumberArray) {
  477. ExFreePool (ConfigBusNumberArray);
  478. }
  479. return Status;
  480. }
  481. PARRAY
  482. HalpAllocateArray (
  483. IN ULONG ArraySize
  484. )
  485. /*++
  486. Routine Description:
  487. Allocate an array of size ArraySize.
  488. Arguments:
  489. ArraySize - Size of array in elements
  490. Return Value:
  491. pointer to ARRAY
  492. --*/
  493. {
  494. PARRAY Array;
  495. if (ArraySize == -1) {
  496. ArraySize = 0;
  497. }
  498. Array = ExAllocatePoolWithTag (
  499. NonPagedPool,
  500. ARRAY_SIZE_IN_BYTES(ArraySize),
  501. HAL_POOL_TAG
  502. );
  503. if (!Array) {
  504. //
  505. // This allocation was critical.
  506. //
  507. KeBugCheckEx(HAL_MEMORY_ALLOCATION,
  508. ARRAY_SIZE_IN_BYTES(ArraySize),
  509. 0,
  510. (ULONG_PTR)__FILE__,
  511. __LINE__
  512. );
  513. }
  514. //
  515. // Initialize array
  516. //
  517. Array->ArraySize = ArraySize;
  518. RtlZeroMemory (Array->Element, sizeof(PVOID) * (ArraySize+1));
  519. return Array;
  520. }
  521. VOID
  522. HalpGrowArray (
  523. IN PARRAY *CurrentArray,
  524. IN PARRAY *NewArray
  525. )
  526. /*++
  527. Routine Description:
  528. If NewArray is larger then CurrentArray, then the CurrentArray
  529. is grown to the sizeof NewArray by swapping the pointers and
  530. moving the arrays contents.
  531. Arguments:
  532. CurrentArray - Address of the current array pointer
  533. NewArray - Address of the new array pointer
  534. --*/
  535. {
  536. PVOID Tmp;
  537. if (!*CurrentArray || (*NewArray)->ArraySize > (*CurrentArray)->ArraySize) {
  538. //
  539. // Copy current array ontop of new array
  540. //
  541. if (*CurrentArray) {
  542. RtlCopyMemory (&(*NewArray)->Element,
  543. &(*CurrentArray)->Element,
  544. sizeof(PVOID) * ((*CurrentArray)->ArraySize + 1)
  545. );
  546. }
  547. //
  548. // swap current with new such that the new array is the current
  549. // one, and the old memory will be freed back to pool
  550. //
  551. Tmp = *CurrentArray;
  552. *CurrentArray = *NewArray;
  553. *NewArray = Tmp;
  554. }
  555. }
  556. PBUS_HANDLER
  557. FASTCALL
  558. HalpLookupHandler (
  559. IN PARRAY Array,
  560. IN ULONG Type,
  561. IN ULONG Number,
  562. IN BOOLEAN AddReference
  563. )
  564. {
  565. PHAL_BUS_HANDLER Bus;
  566. PBUS_HANDLER Handler;
  567. KIRQL OldIrql;
  568. LockBusDatabase (&OldIrql);
  569. //
  570. // Index by type
  571. //
  572. Handler = NULL;
  573. if (Array->ArraySize >= Type) {
  574. Array = (PARRAY) Array->Element[Type];
  575. //
  576. // Index by instance numberr
  577. //
  578. if (Array && Array->ArraySize >= Number) {
  579. Bus = (PHAL_BUS_HANDLER) Array->Element[Number];
  580. Handler = &Bus->Handler;
  581. if (AddReference) {
  582. Bus->ReferenceCount += 1;
  583. }
  584. }
  585. }
  586. UnlockBusDatabase (OldIrql);
  587. return Handler;
  588. }
  589. VOID
  590. FASTCALL
  591. HaliReferenceBusHandler (
  592. IN PBUS_HANDLER Handler
  593. )
  594. /*++
  595. Routine Description:
  596. --*/
  597. {
  598. KIRQL OldIrql;
  599. PHAL_BUS_HANDLER Bus;
  600. LockBusDatabase (&OldIrql);
  601. Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
  602. Bus->ReferenceCount += 1;
  603. UnlockBusDatabase (OldIrql);
  604. }
  605. VOID
  606. FASTCALL
  607. HaliDereferenceBusHandler (
  608. IN PBUS_HANDLER Handler
  609. )
  610. /*++
  611. Routine Description:
  612. --*/
  613. {
  614. KIRQL OldIrql;
  615. PHAL_BUS_HANDLER Bus;
  616. LockBusDatabase (&OldIrql);
  617. Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
  618. Bus->ReferenceCount -= 1;
  619. UnlockBusDatabase (OldIrql);
  620. // for now totally removing a bus is not supported
  621. ASSERT (Bus->ReferenceCount != 0);
  622. }
  623. PBUS_HANDLER
  624. FASTCALL
  625. HaliHandlerForBus (
  626. IN INTERFACE_TYPE InterfaceType,
  627. IN ULONG BusNumber
  628. )
  629. /*++
  630. Routine Description:
  631. Returns the BusHandler structure InterfaceType,BusNumber
  632. or NULL if no such handler exists.
  633. --*/
  634. {
  635. return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, FALSE);
  636. }
  637. PBUS_HANDLER
  638. FASTCALL
  639. HaliHandlerForConfigSpace (
  640. IN BUS_DATA_TYPE ConfigType,
  641. IN ULONG BusNumber
  642. )
  643. /*++
  644. Routine Description:
  645. Returns the BusHandler structure ConfigType,BusNumber
  646. or NULL if no such handler exists.
  647. --*/
  648. {
  649. return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, FALSE);
  650. }
  651. PBUS_HANDLER
  652. FASTCALL
  653. HaliReferenceHandlerForBus (
  654. IN INTERFACE_TYPE InterfaceType,
  655. IN ULONG BusNumber
  656. )
  657. /*++
  658. Routine Description:
  659. Returns the BusHandler structure InterfaceType,BusNumber
  660. or NULL if no such handler exists.
  661. --*/
  662. {
  663. return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, TRUE);
  664. }
  665. PBUS_HANDLER
  666. FASTCALL
  667. HaliReferenceHandlerForConfigSpace (
  668. IN BUS_DATA_TYPE ConfigType,
  669. IN ULONG BusNumber
  670. )
  671. /*++
  672. Routine Description:
  673. Returns the BusHandler structure ConfigType,BusNumber
  674. or NULL if no such handler exists.
  675. --*/
  676. {
  677. return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, TRUE);
  678. }
  679. NTSTATUS
  680. HalpQueryInstalledBusInformation (
  681. OUT PVOID Buffer,
  682. IN ULONG BufferLength,
  683. OUT PULONG ReturnedLength
  684. )
  685. /*++
  686. Routine Description:
  687. Returns an array HAL_BUS_INFORMATION, one for each
  688. bus handler installed.
  689. Arguments:
  690. Buffer - output buffer
  691. BufferLength - length of buffer on input
  692. ReturnedLength - The length of data returned
  693. Return Value:
  694. STATUS_SUCCESS
  695. STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
  696. currently needed.
  697. --*/
  698. {
  699. PHAL_BUS_INFORMATION Info;
  700. PHAL_BUS_HANDLER Handler;
  701. ULONG i, j;
  702. ULONG Length;
  703. NTSTATUS Status;
  704. PARRAY Array;
  705. PAGED_CODE ();
  706. //
  707. // Synchronize adding new bus handlers
  708. //
  709. KeWaitForSingleObject (
  710. &HalpBusDatabaseEvent,
  711. WrExecutive,
  712. KernelMode,
  713. FALSE,
  714. NULL
  715. );
  716. //
  717. // Determine sizeof return buffer
  718. //
  719. Length = 0;
  720. for (i=0; i <= HalpBusTable->ArraySize; i++) {
  721. Array = (PARRAY) HalpBusTable->Element[i];
  722. if (Array) {
  723. Length += sizeof (HAL_BUS_INFORMATION) *
  724. (Array->ArraySize + 1);
  725. }
  726. }
  727. //
  728. // Return size of buffer returning, or size of buffer needed
  729. //
  730. *ReturnedLength = Length;
  731. //
  732. // Fill in the return buffer
  733. //
  734. if (Length <= BufferLength) {
  735. Info = (PHAL_BUS_INFORMATION) Buffer;
  736. for (i=0; i <= HalpBusTable->ArraySize; i++) {
  737. Array = (PARRAY) HalpBusTable->Element[i];
  738. if (Array) {
  739. for (j=0; j <= Array->ArraySize; j++) {
  740. Handler = (PHAL_BUS_HANDLER) Array->Element[j];
  741. if (Handler) {
  742. Info->BusType = Handler->Handler.InterfaceType;
  743. Info->ConfigurationType = Handler->Handler.ConfigurationType;
  744. Info->BusNumber = Handler->Handler.BusNumber;
  745. Info->Reserved = 0;
  746. Info += 1;
  747. }
  748. }
  749. }
  750. }
  751. Status = STATUS_SUCCESS;
  752. } else {
  753. //
  754. // Return buffer too small
  755. //
  756. Status = STATUS_BUFFER_TOO_SMALL;
  757. }
  758. KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
  759. return Status;
  760. }
  761. //
  762. // Default dispatchers to BusHandlers
  763. //
  764. ULONG
  765. HalGetBusData(
  766. IN BUS_DATA_TYPE BusDataType,
  767. IN ULONG BusNumber,
  768. IN ULONG SlotNumber,
  769. IN PVOID Buffer,
  770. IN ULONG Length
  771. )
  772. {
  773. return HalGetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
  774. }
  775. ULONG
  776. HalGetBusDataByOffset (
  777. IN BUS_DATA_TYPE BusDataType,
  778. IN ULONG BusNumber,
  779. IN ULONG SlotNumber,
  780. IN PVOID Buffer,
  781. IN ULONG Offset,
  782. IN ULONG Length
  783. )
  784. /*++
  785. Routine Description:
  786. Dispatcher for GetBusData
  787. --*/
  788. {
  789. PBUS_HANDLER Handler;
  790. NTSTATUS Status;
  791. Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
  792. if (!Handler) {
  793. return 0;
  794. }
  795. Status = Handler->GetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
  796. HaliDereferenceBusHandler (Handler);
  797. return Status;
  798. }
  799. ULONG
  800. HalSetBusData(
  801. IN BUS_DATA_TYPE BusDataType,
  802. IN ULONG BusNumber,
  803. IN ULONG SlotNumber,
  804. IN PVOID Buffer,
  805. IN ULONG Length
  806. )
  807. {
  808. return HalSetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
  809. }
  810. ULONG
  811. HalSetBusDataByOffset(
  812. IN BUS_DATA_TYPE BusDataType,
  813. IN ULONG BusNumber,
  814. IN ULONG SlotNumber,
  815. IN PVOID Buffer,
  816. IN ULONG Offset,
  817. IN ULONG Length
  818. )
  819. /*++
  820. Routine Description:
  821. Dispatcher for SetBusData
  822. --*/
  823. {
  824. PBUS_HANDLER Handler;
  825. NTSTATUS Status;
  826. Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
  827. if (!Handler) {
  828. return 0;
  829. }
  830. Status = Handler->SetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
  831. HaliDereferenceBusHandler (Handler);
  832. return Status;
  833. }
  834. #if !defined(NO_LEGACY_DRIVERS)
  835. NTSTATUS
  836. HalAdjustResourceList (
  837. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
  838. )
  839. /*++
  840. Routine Description:
  841. Dispatcher for AdjustResourceList
  842. --*/
  843. {
  844. PBUS_HANDLER Handler;
  845. NTSTATUS Status;
  846. PAGED_CODE ();
  847. Handler = HaliReferenceHandlerForBus (
  848. (*pResourceList)->InterfaceType,
  849. (*pResourceList)->BusNumber
  850. );
  851. if (!Handler) {
  852. return STATUS_SUCCESS;
  853. }
  854. Status = Handler->AdjustResourceList (Handler, Handler, pResourceList);
  855. HaliDereferenceBusHandler (Handler);
  856. return Status;
  857. }
  858. NTSTATUS
  859. HalAssignSlotResources (
  860. IN PUNICODE_STRING RegistryPath,
  861. IN PUNICODE_STRING DriverClassName OPTIONAL,
  862. IN PDRIVER_OBJECT DriverObject,
  863. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  864. IN INTERFACE_TYPE BusType,
  865. IN ULONG BusNumber,
  866. IN ULONG SlotNumber,
  867. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  868. )
  869. {
  870. PAGED_CODE ();
  871. if (BusType == PCIBus) {
  872. //
  873. // Call through the HAL private dispatch table
  874. // for PCI-related translations. This is part
  875. // of transitioning the HAL out of the bus
  876. // management business.
  877. //
  878. return HALPDISPATCH->HalPciAssignSlotResources(RegistryPath,
  879. DriverClassName,
  880. DriverObject,
  881. DeviceObject,
  882. BusType,
  883. BusNumber,
  884. SlotNumber,
  885. AllocatedResources);
  886. } else {
  887. return HalpAssignSlotResources(RegistryPath,
  888. DriverClassName,
  889. DriverObject,
  890. DeviceObject,
  891. BusType,
  892. BusNumber,
  893. SlotNumber,
  894. AllocatedResources);
  895. }
  896. }
  897. NTSTATUS
  898. HalpAssignSlotResources (
  899. IN PUNICODE_STRING RegistryPath,
  900. IN PUNICODE_STRING DriverClassName OPTIONAL,
  901. IN PDRIVER_OBJECT DriverObject,
  902. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  903. IN INTERFACE_TYPE BusType,
  904. IN ULONG BusNumber,
  905. IN ULONG SlotNumber,
  906. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  907. )
  908. /*++
  909. Routine Description:
  910. Dispatcher for AssignSlotResources
  911. --*/
  912. {
  913. PBUS_HANDLER Handler;
  914. NTSTATUS Status;
  915. PAGED_CODE ();
  916. Handler = HaliReferenceHandlerForBus (BusType, BusNumber);
  917. if (!Handler) {
  918. return STATUS_NOT_FOUND;
  919. }
  920. Status = Handler->AssignSlotResources (
  921. Handler,
  922. Handler,
  923. RegistryPath,
  924. DriverClassName,
  925. DriverObject,
  926. DeviceObject,
  927. SlotNumber,
  928. AllocatedResources
  929. );
  930. HaliDereferenceBusHandler (Handler);
  931. return Status;
  932. }
  933. ULONG
  934. HalGetInterruptVector(
  935. IN INTERFACE_TYPE InterfaceType,
  936. IN ULONG BusNumber,
  937. IN ULONG BusInterruptLevel,
  938. IN ULONG BusInterruptVector,
  939. OUT PKIRQL Irql,
  940. OUT PKAFFINITY Affinity
  941. )
  942. /*++
  943. Routine Description:
  944. Dispatcher for GetInterruptVector
  945. --*/
  946. {
  947. PBUS_HANDLER Handler;
  948. ULONG Vector;
  949. PAGED_CODE ();
  950. Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
  951. *Irql = 0;
  952. *Affinity = 0;
  953. if (!Handler) {
  954. return 0;
  955. }
  956. Vector = Handler->GetInterruptVector (Handler, Handler,
  957. BusInterruptLevel, BusInterruptVector, Irql, Affinity);
  958. HaliDereferenceBusHandler (Handler);
  959. return Vector;
  960. }
  961. #endif // NO_LEGACY_DRIVERS
  962. BOOLEAN
  963. HalTranslateBusAddress(
  964. IN INTERFACE_TYPE InterfaceType,
  965. IN ULONG BusNumber,
  966. IN PHYSICAL_ADDRESS BusAddress,
  967. IN OUT PULONG AddressSpace,
  968. OUT PPHYSICAL_ADDRESS TranslatedAddress
  969. )
  970. {
  971. if (InterfaceType == PCIBus) {
  972. //
  973. // Call through the HAL private dispatch table
  974. // for PCI-related translations. This is part
  975. // of transitioning the HAL out of the bus
  976. // management business.
  977. //
  978. return HALPDISPATCH->HalPciTranslateBusAddress(InterfaceType,
  979. BusNumber,
  980. BusAddress,
  981. AddressSpace,
  982. TranslatedAddress);
  983. } else {
  984. return HaliTranslateBusAddress(InterfaceType,
  985. BusNumber,
  986. BusAddress,
  987. AddressSpace,
  988. TranslatedAddress);
  989. }
  990. }
  991. BOOLEAN
  992. HaliTranslateBusAddress(
  993. IN INTERFACE_TYPE InterfaceType,
  994. IN ULONG BusNumber,
  995. IN PHYSICAL_ADDRESS BusAddress,
  996. IN OUT PULONG AddressSpace,
  997. OUT PPHYSICAL_ADDRESS TranslatedAddress
  998. )
  999. /*++
  1000. Routine Description:
  1001. Dispatcher for TranslateBusAddress
  1002. --*/
  1003. {
  1004. PBUS_HANDLER Handler;
  1005. BOOLEAN Status;
  1006. Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
  1007. if (!Handler || !Handler->TranslateBusAddress) {
  1008. return FALSE;
  1009. }
  1010. Status = Handler->TranslateBusAddress (Handler, Handler,
  1011. BusAddress, AddressSpace, TranslatedAddress);
  1012. HaliDereferenceBusHandler (Handler);
  1013. return Status;
  1014. }
  1015. //
  1016. // Null handlers
  1017. //
  1018. ULONG HalpNoBusData (
  1019. IN PVOID BusHandler,
  1020. IN PVOID RootHandler,
  1021. IN ULONG SlotNumber,
  1022. IN PVOID Buffer,
  1023. IN ULONG Offset,
  1024. IN ULONG Length
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. Stub handler for buses which do not have a configuration space
  1029. --*/
  1030. {
  1031. return 0;
  1032. }
  1033. NTSTATUS
  1034. HalpNoAdjustResourceList (
  1035. IN PVOID BusHandler,
  1036. IN PVOID RootHandler,
  1037. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. Stub handler for buses which do not have a configuration space
  1042. --*/
  1043. {
  1044. PAGED_CODE ();
  1045. return STATUS_UNSUCCESSFUL;
  1046. }
  1047. NTSTATUS
  1048. HalpNoAssignSlotResources (
  1049. IN PVOID BusHandler,
  1050. IN PVOID RootHandler,
  1051. IN PUNICODE_STRING RegistryPath,
  1052. IN PUNICODE_STRING DriverClassName OPTIONAL,
  1053. IN PDRIVER_OBJECT DriverObject,
  1054. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  1055. IN ULONG SlotNumber,
  1056. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  1057. )
  1058. /*++
  1059. Routine Description:
  1060. Stub handler for buses which do not have a configuration space
  1061. --*/
  1062. {
  1063. PAGED_CODE ();
  1064. return STATUS_NOT_SUPPORTED;
  1065. }
  1066. NTSTATUS
  1067. HalpNoQueryBusSlots (
  1068. IN PVOID BusHandler,
  1069. IN PVOID RootHandler,
  1070. IN ULONG BufferSize,
  1071. OUT PULONG SlotNumbers,
  1072. OUT PULONG ReturnedLength
  1073. )
  1074. {
  1075. PAGED_CODE ();
  1076. return STATUS_NOT_SUPPORTED;
  1077. }
  1078. PDEVICE_HANDLER_OBJECT
  1079. HalpNoReferenceDeviceHandler (
  1080. IN PBUS_HANDLER BusHandler,
  1081. IN PBUS_HANDLER RootHandler,
  1082. IN ULONG SlotNumber
  1083. )
  1084. {
  1085. PAGED_CODE ();
  1086. return NULL;
  1087. }
  1088. ULONG
  1089. HalpNoGetDeviceData (
  1090. IN PBUS_HANDLER BusHandler,
  1091. IN PBUS_HANDLER RootHandler,
  1092. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  1093. IN ULONG DataType,
  1094. IN PVOID Buffer,
  1095. IN ULONG Offset,
  1096. IN ULONG Length
  1097. )
  1098. {
  1099. return 0;
  1100. }
  1101. ULONG
  1102. HalpNoSetDeviceData (
  1103. IN PBUS_HANDLER BusHandler,
  1104. IN PBUS_HANDLER RootHandler,
  1105. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  1106. IN ULONG DataType,
  1107. IN PVOID Buffer,
  1108. IN ULONG Offset,
  1109. IN ULONG Length
  1110. )
  1111. {
  1112. return 0;
  1113. }
  1114. PBUS_HANDLER
  1115. HalpContextToBusHandler(
  1116. IN ULONG_PTR Context
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. Convert a context into a pointer to a bus handler. Not really
  1121. a big deal as the context IS a pointer to a bus handler,... or
  1122. possibly null in which case we want the first bus handler.
  1123. For the sake of paranoia, we run down the list of bus handlers
  1124. to find a match for the incoming context. This is because context
  1125. is supplied by something outside the HAL.
  1126. Arguments:
  1127. Context ULONG_PTR either NULL or a value from which
  1128. a pointer to a bus handler can be derived.
  1129. Return Value:
  1130. Pointer to a bus handler or NULL if the incoming context was not
  1131. valid.
  1132. --*/
  1133. {
  1134. PLIST_ENTRY OldHalBusHandler;
  1135. PLIST_ENTRY NewHalBusHandler;
  1136. NewHalBusHandler = HalpAllBusHandlers.Flink;
  1137. if (Context) {
  1138. //
  1139. // Caller supplied a handler, convert to a HAL_BUS_HANDLER.
  1140. //
  1141. OldHalBusHandler = &CONTAINING_RECORD((PBUS_HANDLER)Context,
  1142. HAL_BUS_HANDLER,
  1143. Handler)->AllHandlers;
  1144. while (NewHalBusHandler != &HalpAllBusHandlers) {
  1145. if (NewHalBusHandler == OldHalBusHandler) {
  1146. //
  1147. // Match.
  1148. //
  1149. break;
  1150. }
  1151. NewHalBusHandler = NewHalBusHandler->Flink;
  1152. }
  1153. }
  1154. if (NewHalBusHandler == &HalpAllBusHandlers) {
  1155. //
  1156. // If at end of list, either the incoming value wasn't
  1157. // on the list or this list is empty.
  1158. //
  1159. #if DBG
  1160. DbgPrint("HAL: HalpContextToBusHandler, invalid context.\n");
  1161. #endif
  1162. return NULL;
  1163. }
  1164. return &CONTAINING_RECORD(NewHalBusHandler,
  1165. HAL_BUS_HANDLER,
  1166. AllHandlers)->Handler;
  1167. }
  1168. #if 0 // PLJ
  1169. PBUS_HANDLER
  1170. HalpGetNextBusHandler(
  1171. IN PBUS_HANDLER Previous
  1172. )
  1173. {
  1174. PLIST_ENTRY OldHalBusHandler;
  1175. PLIST_ENTRY NewHalBusHandler;
  1176. PBUS_HANDLER Next;
  1177. NewHalBusHandler = HalpAllBusHandlers.Flink;
  1178. if (Previous != NULL) {
  1179. //
  1180. // Caller supplied a handler, convert to a HAL_BUS_HANDLER.
  1181. //
  1182. OldHalBusHandler = &CONTAINING_RECORD(Previous,
  1183. HAL_BUS_HANDLER,
  1184. Handler)->AllHandlers;
  1185. //
  1186. // Paranoia (should probably be DBG only but there isn't
  1187. // that many handlers and we don't do this all that often.
  1188. //
  1189. {
  1190. PLIST_ENTRY ThisIteration = NULL;
  1191. while (NewHalBusHandler != &HalpAllBusHandlers) {
  1192. ThisIteration = NewHalBusHandler;
  1193. NewHalBusHandler = NewHalBusHandler->Flink;
  1194. if (ThisIteration == OldHalBusHandler) {
  1195. //
  1196. // Match.
  1197. //
  1198. break;
  1199. }
  1200. }
  1201. //
  1202. // If at end of list, either the incoming value wasn't
  1203. // on the list it was the last thing on the list, either
  1204. // way, there is no next entry.
  1205. //
  1206. #if DBG
  1207. if (ThisIteration != OldHalBusHandler) {
  1208. DbgPrint("HAL: HalpGetNextBusHandler, previous handler invalid.\n");
  1209. }
  1210. #endif
  1211. }
  1212. }
  1213. if (NewHalBusHandler == &HalpAllBusHandlers) {
  1214. return NULL;
  1215. }
  1216. return &CONTAINING_RECORD(NewHalBusHandler,
  1217. HAL_BUS_HANDLER,
  1218. AllHandlers)->Handler;
  1219. }
  1220. #endif
  1221. BOOLEAN
  1222. HaliFindBusAddressTranslation(
  1223. IN PHYSICAL_ADDRESS BusAddress,
  1224. IN OUT PULONG AddressSpace,
  1225. OUT PPHYSICAL_ADDRESS TranslatedAddress,
  1226. IN OUT PULONG_PTR Context,
  1227. IN BOOLEAN NextBus
  1228. )
  1229. /*++
  1230. Routine Description:
  1231. This routine performs a very similar function to HalTranslateBusAddress
  1232. except that InterfaceType and BusNumber are not known by the caller.
  1233. This function will walk all busses known by the HAL looking for a
  1234. valid translation for the input BusAddress of type AddressSpace.
  1235. This function is recallable using the input/output Context parameter.
  1236. On the first call to this routine for a given translation the ULONG_PTR
  1237. Context should be NULL. Note: Not the address of it but the contents.
  1238. If the caller decides the returned translation is not the desired
  1239. translation, it calls this routine again passing Context in as it
  1240. was returned on the previous call. This allows this routine to
  1241. traverse the bus structures until the correct translation is found
  1242. and is provided because on multiple bus systems, it is possible for
  1243. the same resource to exist in the independent address spaces of
  1244. multiple busses.
  1245. Note: This routine is not called directly, it is called through
  1246. the HALPDISPATCH table. If a HAL implements a simpler version of
  1247. this function (eg generic PC/AT boxes don't actually need translation,
  1248. those HALs substitute their own version of this routine. This
  1249. routine is not otherwise exported from the HAL.
  1250. Arguments:
  1251. BusAddress Address to be translated.
  1252. AddressSpace 0 = Memory
  1253. 1 = IO (There are other possibilities).
  1254. N.B. This argument is a pointer, the value
  1255. will be modified if the translated address
  1256. is of a different address space type from
  1257. the untranslated bus address.
  1258. TranslatedAddress Pointer to where the translated address
  1259. should be stored.
  1260. Context Pointer to a ULONG_PTR. On the initial call,
  1261. for a given BusAddress, it should contain
  1262. 0. It will be modified by this routine,
  1263. on subsequent calls for the same BusAddress
  1264. the value should be handed in again,
  1265. unmodified by the caller.
  1266. NextBus FALSE if we should attempt this translation
  1267. on the same bus as indicated by Context,
  1268. TRUE if we should be looking for another
  1269. bus.
  1270. Return Value:
  1271. TRUE if translation was successful,
  1272. FALSE otherwise.
  1273. --*/
  1274. {
  1275. PLIST_ENTRY HalBusHandler;
  1276. PBUS_HANDLER Handler;
  1277. //
  1278. // First, make sure the context parameter was supplied. (paranoia).
  1279. //
  1280. if (!Context) {
  1281. ASSERT(Context);
  1282. return FALSE;
  1283. }
  1284. ASSERT(*Context || (NextBus == TRUE));
  1285. //
  1286. // Note: The Context is really a PBUS_HANDLER, but,
  1287. // HalpContextToBusHandler is paranoid. If the incoming
  1288. // Context isn't what we expect, we won't use it as a
  1289. // pointer.
  1290. //
  1291. Handler = HalpContextToBusHandler(*Context);
  1292. if (!Handler) {
  1293. ASSERT(Handler);
  1294. return FALSE;
  1295. }
  1296. if (NextBus == FALSE) {
  1297. //
  1298. // Attempt translation on THIS bus (and ONLY this bus).
  1299. //
  1300. ASSERT(Handler == (PBUS_HANDLER)*Context);
  1301. if (HalTranslateBusAddress(
  1302. Handler->InterfaceType,
  1303. Handler->BusNumber,
  1304. BusAddress,
  1305. AddressSpace,
  1306. TranslatedAddress)) {
  1307. *Context = (ULONG_PTR)Handler;
  1308. return TRUE;
  1309. }
  1310. return FALSE;
  1311. }
  1312. HalBusHandler = &CONTAINING_RECORD(Handler,
  1313. HAL_BUS_HANDLER,
  1314. Handler)->AllHandlers;
  1315. //
  1316. // Handler is either the bus that came in in Context or the
  1317. // first bus if *Context was null. If *Context wasn't NULL,
  1318. // we want the next bus.
  1319. //
  1320. if (*Context) {
  1321. HalBusHandler = HalBusHandler->Flink;
  1322. }
  1323. //
  1324. // Examine each remaining bus looking for one that will translate
  1325. // this address.
  1326. //
  1327. while (HalBusHandler != &HalpAllBusHandlers) {
  1328. //
  1329. // This is gross, having gone to all the trouble to find
  1330. // the handler, it seems a pity to break it out into parameters
  1331. // used to search for this handler.
  1332. //
  1333. // Use HalTranslateAddress to find out if this translation
  1334. // works on this handler.
  1335. //
  1336. Handler = &CONTAINING_RECORD(HalBusHandler,
  1337. HAL_BUS_HANDLER,
  1338. AllHandlers)->Handler;
  1339. if (HalTranslateBusAddress(
  1340. Handler->InterfaceType,
  1341. Handler->BusNumber,
  1342. BusAddress,
  1343. AddressSpace,
  1344. TranslatedAddress)) {
  1345. *Context = (ULONG_PTR)Handler;
  1346. return TRUE;
  1347. }
  1348. //
  1349. // Try next handler.
  1350. //
  1351. HalBusHandler = HalBusHandler->Flink;
  1352. }
  1353. //
  1354. // Didn't find another handler this translation works with. Set
  1355. // the Context such that we don't do the scan again (unless the
  1356. // caller resets it) and indicate failure.
  1357. //
  1358. *Context = 1;
  1359. return FALSE;
  1360. }