Windows NT 4.0 source code leak
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.

1641 lines
37 KiB

4 years ago
  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. NTSTATUS
  112. HalpNoDeviceControl (
  113. IN PHAL_DEVICE_CONTROL_CONTEXT Context
  114. );
  115. PDEVICE_HANDLER_OBJECT
  116. HalpNoReferenceDeviceHandler (
  117. IN PBUS_HANDLER BusHandler,
  118. IN PBUS_HANDLER RootHandler,
  119. IN ULONG SlotNumber
  120. );
  121. ULONG
  122. HalpNoGetDeviceData (
  123. IN PBUS_HANDLER BusHandler,
  124. IN PBUS_HANDLER RootHandler,
  125. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  126. IN ULONG DataType,
  127. IN PVOID Buffer,
  128. IN ULONG Offset,
  129. IN ULONG Length
  130. );
  131. ULONG
  132. HalpNoSetDeviceData (
  133. IN PBUS_HANDLER BusHandler,
  134. IN PBUS_HANDLER RootHandler,
  135. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  136. IN ULONG DataType,
  137. IN PVOID Buffer,
  138. IN ULONG Offset,
  139. IN ULONG Length
  140. );
  141. //
  142. // Prototypes for DeviceControls
  143. //
  144. typedef struct _SYNCHRONOUS_REQUEST {
  145. NTSTATUS Status;
  146. KEVENT Event;
  147. } SYNCHRONOUS_REQUEST, *PSYNCHRONOUS_REQUEST;
  148. #ifdef ALLOC_PRAGMA
  149. #pragma alloc_text(INIT,HalpInitBusHandler)
  150. #pragma alloc_text(PAGELK,HaliRegisterBusHandler)
  151. #pragma alloc_text(PAGELK,HalpAllocateArray)
  152. #pragma alloc_text(PAGELK,HalpGrowArray)
  153. #pragma alloc_text(PAGE,HalAdjustResourceList)
  154. #pragma alloc_text(PAGE,HalAssignSlotResources)
  155. #pragma alloc_text(PAGE,HalGetInterruptVector)
  156. #pragma alloc_text(PAGE,HalpNoAssignSlotResources)
  157. #pragma alloc_text(PAGE,HalpNoQueryBusSlots)
  158. #pragma alloc_text(PAGE,HalpNoReferenceDeviceHandler)
  159. #pragma alloc_text(PAGE,HaliQueryBusSlots)
  160. #pragma alloc_text(PAGE,HalpQueryInstalledBusInformation)
  161. #ifdef _PNP_POWER_
  162. #pragma alloc_text(PAGELK,HaliSuspendHibernateSystem)
  163. #endif
  164. #endif
  165. VOID
  166. HalpInitBusHandler (
  167. VOID
  168. )
  169. /*++
  170. Routine Description:
  171. Initializes global BusHandler data
  172. --*/
  173. {
  174. //
  175. // Initialize bus handler spinlock used to synchronize against
  176. // buses additions while array lookups are done
  177. //
  178. KeInitializeSpinLock (&HalpBusDatabaseSpinLock);
  179. //
  180. // Initialize bus handler synchronzation event used to serialize
  181. // bus additions from < DPC_LVEL
  182. //
  183. KeInitializeEvent (&HalpBusDatabaseEvent, SynchronizationEvent, TRUE);
  184. //
  185. // Initialize global arrays
  186. //
  187. HalpBusTable = HalpAllocateArray (0);
  188. HalpConfigTable = HalpAllocateArray (0);
  189. InitializeListHead (&HalpAllBusHandlers);
  190. //
  191. // Fill in HAL API handlers
  192. //
  193. HalRegisterBusHandler = HaliRegisterBusHandler;
  194. HalHandlerForBus = HaliHandlerForBus;
  195. HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
  196. HalQueryBusSlots = HaliQueryBusSlots;
  197. HalDeviceControl = HaliDeviceControl;
  198. HalCompleteDeviceControl = HaliCompleteDeviceControl;
  199. HalReferenceHandlerForBus = HaliReferenceHandlerForBus;
  200. HalReferenceBusHandler = HaliReferenceBusHandler;
  201. HalDereferenceBusHandler = HaliDereferenceBusHandler;
  202. }
  203. NTSTATUS
  204. HaliRegisterBusHandler (
  205. IN INTERFACE_TYPE InterfaceType,
  206. IN BUS_DATA_TYPE ConfigType,
  207. IN ULONG BusNumber,
  208. IN INTERFACE_TYPE ParentBusType,
  209. IN ULONG ParentBusNumber,
  210. IN ULONG SizeofBusExtensionData,
  211. IN PINSTALL_BUS_HANDLER InstallBusHandler,
  212. OUT PBUS_HANDLER *ReturnedBusHandler
  213. )
  214. /*++
  215. Routine Description:
  216. Adds a BusHandler for InterfaceType,BusNumber and for ConfigType,BusNumber.
  217. Bus specific or Configuration space specific APIs are routed to the
  218. bus or configuration specific handlers added by this routine.
  219. Arguments:
  220. InterfaceType - Identifies the bus type
  221. InterfaceTypeUndefined if no interface type for this
  222. handler.
  223. ConfigType - Identifies the configuration space type
  224. ConfigurationSpaceUndefined if no configuration space
  225. type for this handler.
  226. BusNumber - Identifies the instance of the bus & config space.
  227. -1 if the next available bus number for this bus
  228. should be used.
  229. ParentBusType - If this bus is a child of a bus, then ParentBusType
  230. ParentBusNumber and ParentBusNumber identifies that bus.
  231. ParentBusType is -1 if no parent bus.
  232. SizeofBusExetensionData - Sizeof bus specific exentsion data required.
  233. InstallBusHandler - Function to call to get the bus specific handlers
  234. added to the bus handler structure.
  235. Return Value:
  236. success; otherwise error code of failure.
  237. --*/
  238. {
  239. PHAL_BUS_HANDLER Bus, *pBusHandler, OldHandler;
  240. PBUS_HANDLER ParentHandler;
  241. KIRQL OldIrql;
  242. NTSTATUS Status;
  243. PARRAY InterfaceArray, InterfaceBusNumberArray;
  244. PARRAY ConfigArray, ConfigBusNumberArray;
  245. PVOID CodeLockHandle;
  246. //
  247. // Must add the handler to at least one table
  248. //
  249. ASSERT (InterfaceType != InterfaceTypeUndefined || ConfigType != ConfigurationSpaceUndefined);
  250. Status = STATUS_SUCCESS;
  251. OldHandler = NULL;
  252. //
  253. // Allocate storage for new bus handler structure
  254. //
  255. Bus = (PHAL_BUS_HANDLER)
  256. ExAllocatePoolWithTag (
  257. NonPagedPool,
  258. sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData,
  259. 'HsuB'
  260. );
  261. if (!Bus) {
  262. return STATUS_INSUFFICIENT_RESOURCES;
  263. }
  264. //
  265. // Lock pagable code down
  266. //
  267. CodeLockHandle = MmLockPagableCodeSection (&HaliRegisterBusHandler);
  268. //
  269. // Synchronize adding new bus handlers
  270. //
  271. *ReturnedBusHandler = &Bus->Handler;
  272. KeWaitForSingleObject (
  273. &HalpBusDatabaseEvent,
  274. WrExecutive,
  275. KernelMode,
  276. FALSE,
  277. NULL
  278. );
  279. //
  280. // If BusNumber not defined, use next available number for this BusType
  281. //
  282. if (BusNumber == -1) {
  283. ASSERT (InterfaceType != InterfaceTypeUndefined);
  284. BusNumber = 0;
  285. while (HaliHandlerForBus (InterfaceType, BusNumber)) {
  286. BusNumber++;
  287. }
  288. }
  289. //
  290. // Allocate memory for each array in case any index needs to grow
  291. //
  292. InterfaceArray = HalpAllocateArray (InterfaceType);
  293. InterfaceBusNumberArray = HalpAllocateArray (BusNumber);
  294. ConfigArray = HalpAllocateArray (ConfigType);
  295. ConfigBusNumberArray = HalpAllocateArray (BusNumber);
  296. if (!Bus ||
  297. !InterfaceArray ||
  298. !InterfaceBusNumberArray ||
  299. !ConfigArray ||
  300. !ConfigBusNumberArray) {
  301. Status = STATUS_INSUFFICIENT_RESOURCES;
  302. }
  303. if (NT_SUCCESS(Status)) {
  304. //
  305. // Lookup parent handler (if any)
  306. //
  307. ParentHandler = HaliReferenceHandlerForBus (ParentBusType, ParentBusNumber);
  308. //
  309. // Initialize new bus handlers values
  310. //
  311. RtlZeroMemory (Bus, sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData);
  312. Bus->ReferenceCount = 1;
  313. Bus->Handler.BusNumber = BusNumber;
  314. Bus->Handler.InterfaceType = InterfaceType;
  315. Bus->Handler.ConfigurationType = ConfigType;
  316. Bus->Handler.ParentHandler = ParentHandler;
  317. //
  318. // Set to dumby handlers
  319. //
  320. Bus->Handler.GetBusData = HalpNoBusData;
  321. Bus->Handler.SetBusData = HalpNoBusData;
  322. Bus->Handler.AdjustResourceList = HalpNoAdjustResourceList;
  323. Bus->Handler.AssignSlotResources = HalpNoAssignSlotResources;
  324. Bus->Handler.QueryBusSlots = HalpNoQueryBusSlots;
  325. Bus->Handler.ReferenceDeviceHandler = HalpNoReferenceDeviceHandler;
  326. Bus->Handler.DeviceControl = HalpNoDeviceControl;
  327. Bus->Handler.GetDeviceData = HalpNoGetDeviceData;
  328. Bus->Handler.SetDeviceData = HalpNoSetDeviceData;
  329. if (SizeofBusExtensionData) {
  330. Bus->Handler.BusData = Bus + 1;
  331. }
  332. //
  333. // If bus has a parent, inherit handlers from parent as default
  334. //
  335. if (ParentHandler) {
  336. Bus->Handler.GetBusData = ParentHandler->GetBusData;
  337. Bus->Handler.SetBusData = ParentHandler->SetBusData;
  338. Bus->Handler.AdjustResourceList = ParentHandler->AdjustResourceList;
  339. Bus->Handler.AssignSlotResources = ParentHandler->AssignSlotResources;
  340. Bus->Handler.TranslateBusAddress = ParentHandler->TranslateBusAddress;
  341. Bus->Handler.GetInterruptVector = ParentHandler->GetInterruptVector;
  342. Bus->Handler.QueryBusSlots = ParentHandler->QueryBusSlots;
  343. Bus->Handler.ReferenceDeviceHandler = ParentHandler->ReferenceDeviceHandler;
  344. Bus->Handler.DeviceControl = ParentHandler->DeviceControl;
  345. Bus->Handler.GetDeviceData = ParentHandler->GetDeviceData;
  346. Bus->Handler.SetDeviceData = ParentHandler->SetDeviceData;
  347. }
  348. //
  349. // Install bus specific handlers
  350. //
  351. if (InstallBusHandler) {
  352. Status = InstallBusHandler (&Bus->Handler);
  353. }
  354. if (NT_SUCCESS(Status)) {
  355. //
  356. // Might change addresses of some arrays synchronize
  357. // with routing handlers
  358. //
  359. LockBusDatabase (&OldIrql);
  360. //
  361. // Grow HalpBusTable if needed
  362. //
  363. HalpGrowArray (&HalpBusTable, &InterfaceArray);
  364. if (InterfaceType != InterfaceTypeUndefined) {
  365. //
  366. // Grow HalpBusTable if needed
  367. //
  368. HalpGrowArray (
  369. (PARRAY *) &HalpBusTable->Element[InterfaceType],
  370. &InterfaceBusNumberArray
  371. );
  372. //
  373. // Get registered handler for InterfaceType,BusNumber
  374. //
  375. pBusHandler = &((PHAL_BUS_HANDLER)
  376. ((PARRAY) HalpBusTable->Element[InterfaceType])->Element[BusNumber]);
  377. //
  378. // If handler already defiend, remove the old one
  379. //
  380. if (*pBusHandler) {
  381. OldHandler = *pBusHandler;
  382. }
  383. //
  384. // Set new handler for supplied InterfaceType,BusNumber
  385. //
  386. *pBusHandler = Bus;
  387. }
  388. //
  389. // Grow HalpConfigTable if needed
  390. //
  391. HalpGrowArray (&HalpConfigTable, &ConfigArray);
  392. if (ConfigType != ConfigurationSpaceUndefined) {
  393. //
  394. // Grow HalpConfigTable if needed
  395. //
  396. HalpGrowArray (
  397. (PARRAY *) &HalpConfigTable->Element[ConfigType],
  398. &ConfigBusNumberArray
  399. );
  400. //
  401. // Get registered handler for ConfigType,BusNumber
  402. //
  403. pBusHandler = &((PHAL_BUS_HANDLER)
  404. ((PARRAY) HalpConfigTable->Element[ConfigType])->Element[BusNumber]);
  405. if (*pBusHandler) {
  406. ASSERT (OldHandler == NULL || OldHandler == *pBusHandler);
  407. OldHandler = *pBusHandler;
  408. }
  409. //
  410. // Set new handler for supplied ConfigType,BusNumber
  411. //
  412. *pBusHandler = Bus;
  413. }
  414. //
  415. // Add new bus handler to list of all installed handlers
  416. //
  417. InsertTailList (&HalpAllBusHandlers, &Bus->AllHandlers);
  418. //
  419. // Remove old bus handler
  420. //
  421. Bus = OldHandler;
  422. if (Bus) {
  423. RemoveEntryList (&Bus->AllHandlers);
  424. }
  425. //
  426. // Lookup array modification complete, release lock
  427. //
  428. UnlockBusDatabase (OldIrql);
  429. } else {
  430. if (ParentHandler) {
  431. HaliDereferenceBusHandler (ParentHandler);
  432. }
  433. }
  434. }
  435. //
  436. // Bus addition modifications complete, set event
  437. //
  438. KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
  439. //
  440. // Unlock pagable code
  441. //
  442. MmUnlockPagableImageSection (CodeLockHandle);
  443. //
  444. // Free memory which is not in use
  445. //
  446. if (Bus) {
  447. ExFreePool (Bus);
  448. }
  449. if (InterfaceArray) {
  450. ExFreePool (InterfaceArray);
  451. }
  452. if (InterfaceBusNumberArray) {
  453. ExFreePool (InterfaceBusNumberArray);
  454. }
  455. if (ConfigArray) {
  456. ExFreePool (ConfigArray);
  457. }
  458. if (ConfigBusNumberArray) {
  459. ExFreePool (ConfigBusNumberArray);
  460. }
  461. #ifdef _PNP_POWER_
  462. //
  463. // A bus was added to the system, notify the BusInsertionCheck callback
  464. // of this bus
  465. //
  466. if (NT_SUCCESS(Status) && InterfaceType != InterfaceTypeUndefined) {
  467. ExNotifyCallback (
  468. HalCallback.BusCheck,
  469. (PVOID) InterfaceType,
  470. (PVOID) BusNumber
  471. );
  472. }
  473. #endif
  474. return Status;
  475. }
  476. PARRAY
  477. HalpAllocateArray (
  478. IN ULONG ArraySize
  479. )
  480. /*++
  481. Routine Description:
  482. Allocate an array of size ArraySize.
  483. Arguments:
  484. ArraySize - Size of array in elements
  485. Return Value:
  486. pointer to ARRAY
  487. --*/
  488. {
  489. PARRAY Array;
  490. if (ArraySize == -1) {
  491. ArraySize = 0;
  492. }
  493. Array = ExAllocatePoolWithTag (
  494. NonPagedPool,
  495. ARRAY_SIZE_IN_BYTES(ArraySize),
  496. 'HsuB'
  497. );
  498. //
  499. // Initialize array
  500. //
  501. Array->ArraySize = ArraySize;
  502. RtlZeroMemory (Array->Element, sizeof(PVOID) * (ArraySize+1));
  503. return Array;
  504. }
  505. VOID
  506. HalpGrowArray (
  507. IN PARRAY *CurrentArray,
  508. IN PARRAY *NewArray
  509. )
  510. /*++
  511. Routine Description:
  512. If NewArray is larger then CurrentArray, then the CurrentArray
  513. is grown to the sizeof NewArray by swapping the pointers and
  514. moving the arrays contents.
  515. Arguments:
  516. CurrentArray - Address of the current array pointer
  517. NewArray - Address of the new array pointer
  518. --*/
  519. {
  520. PVOID Tmp;
  521. if (!*CurrentArray || (*NewArray)->ArraySize > (*CurrentArray)->ArraySize) {
  522. //
  523. // Copy current array ontop of new array
  524. //
  525. if (*CurrentArray) {
  526. RtlCopyMemory (&(*NewArray)->Element,
  527. &(*CurrentArray)->Element,
  528. sizeof(PVOID) * ((*CurrentArray)->ArraySize + 1)
  529. );
  530. }
  531. //
  532. // swap current with new such that the new array is the current
  533. // one, and the old memory will be freed back to pool
  534. //
  535. Tmp = *CurrentArray;
  536. *CurrentArray = *NewArray;
  537. *NewArray = Tmp;
  538. }
  539. }
  540. PBUS_HANDLER
  541. FASTCALL
  542. HalpLookupHandler (
  543. IN PARRAY Array,
  544. IN ULONG Type,
  545. IN ULONG Number,
  546. IN BOOLEAN AddReference
  547. )
  548. {
  549. PHAL_BUS_HANDLER Bus;
  550. PBUS_HANDLER Handler;
  551. KIRQL OldIrql;
  552. LockBusDatabase (&OldIrql);
  553. //
  554. // Index by type
  555. //
  556. Handler = NULL;
  557. if (Array->ArraySize >= Type) {
  558. Array = (PARRAY) Array->Element[Type];
  559. //
  560. // Index by instance numberr
  561. //
  562. if (Array && Array->ArraySize >= Number) {
  563. Bus = (PHAL_BUS_HANDLER) Array->Element[Number];
  564. Handler = &Bus->Handler;
  565. if (AddReference) {
  566. Bus->ReferenceCount += 1;
  567. }
  568. }
  569. }
  570. UnlockBusDatabase (OldIrql);
  571. return Handler;
  572. }
  573. VOID
  574. FASTCALL
  575. HaliReferenceBusHandler (
  576. IN PBUS_HANDLER Handler
  577. )
  578. /*++
  579. Routine Description:
  580. --*/
  581. {
  582. KIRQL OldIrql;
  583. PHAL_BUS_HANDLER Bus;
  584. LockBusDatabase (&OldIrql);
  585. Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
  586. Bus->ReferenceCount += 1;
  587. UnlockBusDatabase (OldIrql);
  588. }
  589. VOID
  590. FASTCALL
  591. HaliDereferenceBusHandler (
  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. // BUGBUG: for now totally removing a bus is not supported
  605. ASSERT (Bus->ReferenceCount != 0);
  606. }
  607. PBUS_HANDLER
  608. FASTCALL
  609. HaliHandlerForBus (
  610. IN INTERFACE_TYPE InterfaceType,
  611. IN ULONG BusNumber
  612. )
  613. /*++
  614. Routine Description:
  615. Returns the BusHandler structure InterfaceType,BusNumber
  616. or NULL if no such handler exists.
  617. --*/
  618. {
  619. return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, FALSE);
  620. }
  621. PBUS_HANDLER
  622. FASTCALL
  623. HaliHandlerForConfigSpace (
  624. IN BUS_DATA_TYPE ConfigType,
  625. IN ULONG BusNumber
  626. )
  627. /*++
  628. Routine Description:
  629. Returns the BusHandler structure ConfigType,BusNumber
  630. or NULL if no such handler exists.
  631. --*/
  632. {
  633. return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, FALSE);
  634. }
  635. PBUS_HANDLER
  636. FASTCALL
  637. HaliReferenceHandlerForBus (
  638. IN INTERFACE_TYPE InterfaceType,
  639. IN ULONG BusNumber
  640. )
  641. /*++
  642. Routine Description:
  643. Returns the BusHandler structure InterfaceType,BusNumber
  644. or NULL if no such handler exists.
  645. --*/
  646. {
  647. return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, TRUE);
  648. }
  649. PBUS_HANDLER
  650. FASTCALL
  651. HaliReferenceHandlerForConfigSpace (
  652. IN BUS_DATA_TYPE ConfigType,
  653. IN ULONG BusNumber
  654. )
  655. /*++
  656. Routine Description:
  657. Returns the BusHandler structure ConfigType,BusNumber
  658. or NULL if no such handler exists.
  659. --*/
  660. {
  661. return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, TRUE);
  662. }
  663. NTSTATUS
  664. HalpQueryInstalledBusInformation (
  665. OUT PVOID Buffer,
  666. IN ULONG BufferLength,
  667. OUT PULONG ReturnedLength
  668. )
  669. /*++
  670. Routine Description:
  671. Returns an array HAL_BUS_INFORMATION, one for each
  672. bus handler installed.
  673. Arguments:
  674. Buffer - output buffer
  675. BufferLength - length of buffer on input
  676. ReturnedLength - The length of data returned
  677. Return Value:
  678. STATUS_SUCCESS
  679. STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
  680. currently needed.
  681. --*/
  682. {
  683. PHAL_BUS_INFORMATION Info;
  684. PHAL_BUS_HANDLER Handler;
  685. ULONG i, j;
  686. ULONG Length;
  687. NTSTATUS Status;
  688. PARRAY Array;
  689. PAGED_CODE ();
  690. //
  691. // Synchronize adding new bus handlers
  692. //
  693. KeWaitForSingleObject (
  694. &HalpBusDatabaseEvent,
  695. WrExecutive,
  696. KernelMode,
  697. FALSE,
  698. NULL
  699. );
  700. //
  701. // Determine sizeof return buffer
  702. //
  703. Length = 0;
  704. for (i=0; i <= HalpBusTable->ArraySize; i++) {
  705. Array = (PARRAY) HalpBusTable->Element[i];
  706. if (Array) {
  707. Length += sizeof (HAL_BUS_INFORMATION) *
  708. (Array->ArraySize + 1);
  709. }
  710. }
  711. //
  712. // Return size of buffer returning, or size of buffer needed
  713. //
  714. *ReturnedLength = Length;
  715. //
  716. // Fill in the return buffer
  717. //
  718. if (Length <= BufferLength) {
  719. Info = (PHAL_BUS_INFORMATION) Buffer;
  720. for (i=0; i <= HalpBusTable->ArraySize; i++) {
  721. Array = (PARRAY) HalpBusTable->Element[i];
  722. if (Array) {
  723. for (j=0; j <= Array->ArraySize; j++) {
  724. Handler = (PHAL_BUS_HANDLER) Array->Element[j];
  725. if (Handler) {
  726. Info->BusType = Handler->Handler.InterfaceType;
  727. Info->ConfigurationType = Handler->Handler.ConfigurationType;
  728. Info->BusNumber = Handler->Handler.BusNumber;
  729. Info->Reserved = 0;
  730. Info += 1;
  731. }
  732. }
  733. }
  734. }
  735. Status = STATUS_SUCCESS;
  736. } else {
  737. //
  738. // Return buffer too small
  739. //
  740. Status = STATUS_BUFFER_TOO_SMALL;
  741. }
  742. KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
  743. return Status;
  744. }
  745. //
  746. // Default dispatchers to BusHandlers
  747. //
  748. ULONG
  749. HalGetBusData(
  750. IN BUS_DATA_TYPE BusDataType,
  751. IN ULONG BusNumber,
  752. IN ULONG SlotNumber,
  753. IN PVOID Buffer,
  754. IN ULONG Length
  755. )
  756. {
  757. return HalGetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
  758. }
  759. ULONG
  760. HalGetBusDataByOffset (
  761. IN BUS_DATA_TYPE BusDataType,
  762. IN ULONG BusNumber,
  763. IN ULONG SlotNumber,
  764. IN PVOID Buffer,
  765. IN ULONG Offset,
  766. IN ULONG Length
  767. )
  768. /*++
  769. Routine Description:
  770. Dispatcher for GetBusData
  771. --*/
  772. {
  773. PBUS_HANDLER Handler;
  774. NTSTATUS Status;
  775. Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
  776. if (!Handler) {
  777. return 0;
  778. }
  779. Status = Handler->GetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
  780. HaliDereferenceBusHandler (Handler);
  781. return Status;
  782. }
  783. ULONG
  784. HalSetBusData(
  785. IN BUS_DATA_TYPE BusDataType,
  786. IN ULONG BusNumber,
  787. IN ULONG SlotNumber,
  788. IN PVOID Buffer,
  789. IN ULONG Length
  790. )
  791. {
  792. return HalSetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
  793. }
  794. ULONG
  795. HalSetBusDataByOffset(
  796. IN BUS_DATA_TYPE BusDataType,
  797. IN ULONG BusNumber,
  798. IN ULONG SlotNumber,
  799. IN PVOID Buffer,
  800. IN ULONG Offset,
  801. IN ULONG Length
  802. )
  803. /*++
  804. Routine Description:
  805. Dispatcher for SetBusData
  806. --*/
  807. {
  808. PBUS_HANDLER Handler;
  809. NTSTATUS Status;
  810. Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
  811. if (!Handler) {
  812. return 0;
  813. }
  814. Status = Handler->SetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
  815. HaliDereferenceBusHandler (Handler);
  816. return Status;
  817. }
  818. NTSTATUS
  819. HalAdjustResourceList (
  820. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
  821. )
  822. /*++
  823. Routine Description:
  824. Dispatcher for AdjustResourceList
  825. --*/
  826. {
  827. PBUS_HANDLER Handler;
  828. NTSTATUS Status;
  829. Handler = HaliReferenceHandlerForBus (
  830. (*pResourceList)->InterfaceType,
  831. (*pResourceList)->BusNumber
  832. );
  833. if (!Handler) {
  834. return STATUS_SUCCESS;
  835. }
  836. Status = Handler->AdjustResourceList (Handler, Handler, pResourceList);
  837. HaliDereferenceBusHandler (Handler);
  838. return Status;
  839. }
  840. NTSTATUS
  841. HalAssignSlotResources (
  842. IN PUNICODE_STRING RegistryPath,
  843. IN PUNICODE_STRING DriverClassName OPTIONAL,
  844. IN PDRIVER_OBJECT DriverObject,
  845. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  846. IN INTERFACE_TYPE BusType,
  847. IN ULONG BusNumber,
  848. IN ULONG SlotNumber,
  849. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  850. )
  851. /*++
  852. Routine Description:
  853. Dispatcher for AssignSlotResources
  854. --*/
  855. {
  856. PBUS_HANDLER Handler;
  857. NTSTATUS Status;
  858. Handler = HaliReferenceHandlerForBus (BusType, BusNumber);
  859. if (!Handler) {
  860. return STATUS_NOT_FOUND;
  861. }
  862. Status = Handler->AssignSlotResources (
  863. Handler,
  864. Handler,
  865. RegistryPath,
  866. DriverClassName,
  867. DriverObject,
  868. DeviceObject,
  869. SlotNumber,
  870. AllocatedResources
  871. );
  872. HaliDereferenceBusHandler (Handler);
  873. return Status;
  874. }
  875. ULONG
  876. HalGetInterruptVector(
  877. IN INTERFACE_TYPE InterfaceType,
  878. IN ULONG BusNumber,
  879. IN ULONG BusInterruptLevel,
  880. IN ULONG BusInterruptVector,
  881. OUT PKIRQL Irql,
  882. OUT PKAFFINITY Affinity
  883. )
  884. /*++
  885. Routine Description:
  886. Dispatcher for GetInterruptVector
  887. --*/
  888. {
  889. PBUS_HANDLER Handler;
  890. ULONG Vector;
  891. Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
  892. *Irql = 0;
  893. *Affinity = 0;
  894. if (!Handler) {
  895. return 0;
  896. }
  897. Vector = Handler->GetInterruptVector (Handler, Handler,
  898. BusInterruptLevel, BusInterruptVector, Irql, Affinity);
  899. HaliDereferenceBusHandler (Handler);
  900. return Vector;
  901. }
  902. BOOLEAN
  903. HalTranslateBusAddress(
  904. IN INTERFACE_TYPE InterfaceType,
  905. IN ULONG BusNumber,
  906. IN PHYSICAL_ADDRESS BusAddress,
  907. IN OUT PULONG AddressSpace,
  908. OUT PPHYSICAL_ADDRESS TranslatedAddress
  909. )
  910. /*++
  911. Routine Description:
  912. Dispatcher for TranslateBusAddress
  913. --*/
  914. {
  915. PBUS_HANDLER Handler;
  916. BOOLEAN Status;
  917. Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
  918. if (!Handler) {
  919. return FALSE;
  920. }
  921. Status = Handler->TranslateBusAddress (Handler, Handler,
  922. BusAddress, AddressSpace, TranslatedAddress);
  923. HaliDereferenceBusHandler (Handler);
  924. return Status;
  925. }
  926. NTSTATUS
  927. HaliQueryBusSlots (
  928. IN PBUS_HANDLER BusHandler,
  929. IN ULONG BufferSize,
  930. OUT PULONG SlotNumbers,
  931. OUT PULONG ReturnedLength
  932. )
  933. /*++
  934. Routine Description:
  935. Dispatcher for QueryBusSlots
  936. --*/
  937. {
  938. PAGED_CODE();
  939. return BusHandler->QueryBusSlots (BusHandler, BusHandler,
  940. BufferSize, SlotNumbers, ReturnedLength);
  941. }
  942. NTSTATUS
  943. HaliDeviceControl (
  944. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  945. IN PDEVICE_OBJECT DeviceObject,
  946. IN ULONG ControlCode,
  947. IN OUT PVOID Buffer OPTIONAL,
  948. IN OUT PULONG BufferLength OPTIONAL,
  949. IN PVOID CompletionContext,
  950. IN PDEVICE_CONTROL_COMPLETION CompletionRoutine
  951. )
  952. /*++
  953. Routine Description:
  954. Allocates and initializes a HalDeviceControlContext and then dispatches
  955. that context to the appriopate bus handler.
  956. --*/
  957. {
  958. NTSTATUS Status;
  959. PHAL_DEVICE_CONTROL_CONTEXT pContext;
  960. HAL_DEVICE_CONTROL_CONTEXT Context;
  961. SYNCHRONOUS_REQUEST SyncRequest;
  962. //
  963. // Initialize local DeviceControl context
  964. //
  965. Context.DeviceControl.DeviceHandler = DeviceHandler;
  966. Context.DeviceControl.DeviceObject = DeviceObject;
  967. Context.DeviceControl.ControlCode = ControlCode;
  968. Context.DeviceControl.Buffer = Buffer;
  969. Context.DeviceControl.BufferLength = BufferLength;
  970. Context.DeviceControl.Context = CompletionContext;
  971. Context.CompletionRoutine = CompletionRoutine;
  972. Context.Handler = DeviceHandler->BusHandler;
  973. Context.RootHandler = DeviceHandler->BusHandler;
  974. //
  975. // Allocate HalDeviceControlContext structure
  976. // (for now, just do it from pool)
  977. //
  978. pContext = ExAllocatePoolWithTag (
  979. NonPagedPool,
  980. sizeof (HAL_DEVICE_CONTROL_CONTEXT) +
  981. Context.Handler->DeviceControlExtensionSize,
  982. 'sLAH'
  983. );
  984. if (pContext) {
  985. //
  986. // Initialize HalDeviceControlContext
  987. //
  988. RtlCopyMemory (pContext, &Context, sizeof (HAL_DEVICE_CONTROL_CONTEXT));
  989. pContext->BusExtensionData = NULL;
  990. if (pContext->Handler->DeviceControlExtensionSize) {
  991. pContext->BusExtensionData = pContext + 1;
  992. }
  993. if (!Context.CompletionRoutine) {
  994. //
  995. // There's no completion routine, associate an event to make it a
  996. // synchronous request
  997. //
  998. KeInitializeEvent (&SyncRequest.Event, SynchronizationEvent, FALSE);
  999. pContext->DeviceControl.Context = &SyncRequest;
  1000. }
  1001. //
  1002. // If there's no buffer length, pass in a zero
  1003. //
  1004. if (!pContext->DeviceControl.BufferLength) {
  1005. pContext->DeviceControl.BufferLength = pContext->HalReserved;
  1006. pContext->HalReserved[0] = 0;
  1007. }
  1008. //
  1009. // Allocated context complete, dispatch it to the appopiate bus handler
  1010. //
  1011. pContext->DeviceControl.Status = STATUS_PENDING;
  1012. Status = Context.Handler->DeviceControl(pContext);
  1013. //
  1014. // If the DeviceControl is pending and this is a synchronous call
  1015. // wait for it to complete
  1016. //
  1017. if (Status == STATUS_PENDING && CompletionRoutine == NULL) {
  1018. //
  1019. // Wait for it to complete
  1020. //
  1021. KeWaitForSingleObject (
  1022. &SyncRequest.Event,
  1023. WrExecutive,
  1024. KernelMode,
  1025. FALSE,
  1026. NULL
  1027. );
  1028. //
  1029. // Return results
  1030. //
  1031. Status = SyncRequest.Status;
  1032. ASSERT (Status != STATUS_PENDING);
  1033. }
  1034. return Status;
  1035. } else {
  1036. //
  1037. // Out of memory
  1038. //
  1039. Status = STATUS_INSUFFICIENT_RESOURCES;
  1040. }
  1041. //
  1042. // Immediate error, complete request with local context
  1043. // structure with error code
  1044. //
  1045. if (CompletionRoutine) {
  1046. Context.DeviceControl.Status = Status;
  1047. CompletionRoutine (&Context.DeviceControl);
  1048. }
  1049. return Status;
  1050. }
  1051. NTSTATUS
  1052. HaliCompleteDeviceControl (
  1053. IN PHAL_DEVICE_CONTROL_CONTEXT Context
  1054. )
  1055. {
  1056. NTSTATUS Status;
  1057. PSYNCHRONOUS_REQUEST SyncRequest;
  1058. //
  1059. // Get results
  1060. //
  1061. Status = Context->DeviceControl.Status;
  1062. if (Context->CompletionRoutine) {
  1063. //
  1064. // Notify completion routine
  1065. //
  1066. Context->CompletionRoutine (&Context->DeviceControl);
  1067. } else {
  1068. //
  1069. // This is a synchronous request, return the status, and set
  1070. // the event
  1071. //
  1072. SyncRequest = (PSYNCHRONOUS_REQUEST) Context->DeviceControl.Context;
  1073. SyncRequest->Status = Context->DeviceControl.Status;
  1074. KeSetEvent (&SyncRequest->Event, 0, FALSE);
  1075. }
  1076. //
  1077. // Free context structure
  1078. //
  1079. ExFreePool (Context);
  1080. return Status;
  1081. }
  1082. //
  1083. // Null handlers
  1084. //
  1085. ULONG HalpNoBusData (
  1086. IN PVOID BusHandler,
  1087. IN PVOID RootHandler,
  1088. IN ULONG SlotNumber,
  1089. IN PVOID Buffer,
  1090. IN ULONG Offset,
  1091. IN ULONG Length
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. Stub handler for buses which do not have a configuration space
  1096. --*/
  1097. {
  1098. return 0;
  1099. }
  1100. NTSTATUS
  1101. HalpNoAdjustResourceList (
  1102. IN PVOID BusHandler,
  1103. IN PVOID RootHandler,
  1104. IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. Stub handler for buses which do not have a configuration space
  1109. --*/
  1110. {
  1111. PAGED_CODE ();
  1112. return STATUS_UNSUCCESSFUL;
  1113. }
  1114. NTSTATUS
  1115. HalpNoAssignSlotResources (
  1116. IN PVOID BusHandler,
  1117. IN PVOID RootHandler,
  1118. IN PUNICODE_STRING RegistryPath,
  1119. IN PUNICODE_STRING DriverClassName OPTIONAL,
  1120. IN PDRIVER_OBJECT DriverObject,
  1121. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  1122. IN ULONG SlotNumber,
  1123. IN OUT PCM_RESOURCE_LIST *AllocatedResources
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. Stub handler for buses which do not have a configuration space
  1128. --*/
  1129. {
  1130. PAGED_CODE ();
  1131. return STATUS_NOT_SUPPORTED;
  1132. }
  1133. NTSTATUS
  1134. HalpNoQueryBusSlots (
  1135. IN PVOID BusHandler,
  1136. IN PVOID RootHandler,
  1137. IN ULONG BufferSize,
  1138. OUT PULONG SlotNumbers,
  1139. OUT PULONG ReturnedLength
  1140. )
  1141. {
  1142. PAGED_CODE ();
  1143. return STATUS_NOT_SUPPORTED;
  1144. }
  1145. NTSTATUS
  1146. HalpNoDeviceControl (
  1147. IN PHAL_DEVICE_CONTROL_CONTEXT Context
  1148. )
  1149. {
  1150. Context->DeviceControl.Status = STATUS_NOT_SUPPORTED;
  1151. return HaliCompleteDeviceControl (Context);
  1152. }
  1153. PDEVICE_HANDLER_OBJECT
  1154. HalpNoReferenceDeviceHandler (
  1155. IN PBUS_HANDLER BusHandler,
  1156. IN PBUS_HANDLER RootHandler,
  1157. IN ULONG SlotNumber
  1158. )
  1159. {
  1160. return NULL;
  1161. }
  1162. ULONG
  1163. HalpNoGetDeviceData (
  1164. IN PBUS_HANDLER BusHandler,
  1165. IN PBUS_HANDLER RootHandler,
  1166. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  1167. IN ULONG DataType,
  1168. IN PVOID Buffer,
  1169. IN ULONG Offset,
  1170. IN ULONG Length
  1171. )
  1172. {
  1173. return 0;
  1174. }
  1175. ULONG
  1176. HalpNoSetDeviceData (
  1177. IN PBUS_HANDLER BusHandler,
  1178. IN PBUS_HANDLER RootHandler,
  1179. IN PDEVICE_HANDLER_OBJECT DeviceHandler,
  1180. IN ULONG DataType,
  1181. IN PVOID Buffer,
  1182. IN ULONG Offset,
  1183. IN ULONG Length
  1184. )
  1185. {
  1186. return 0;
  1187. }
  1188. #ifdef _PNP_POWER_
  1189. NTSTATUS
  1190. HaliSuspendHibernateSystem (
  1191. IN PTIME_FIELDS ResumeTime OPTIONAL,
  1192. IN PHIBERNATE_CALLBACK SystemCallback
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This function is invokved by the to suspend or hibernate the system.
  1197. By this point all device drivers have been turned off. All bus
  1198. extenders are notified, and then a platform specific suspend function
  1199. is called.
  1200. Arguments:
  1201. ResumeTime - Time to set resume alarm
  1202. SystemCallback - If NULL, suspend; else call this function.
  1203. Return Value:
  1204. SUCCESS if machine was suspended/hibernated.
  1205. --*/
  1206. {
  1207. KIRQL OldIrql;
  1208. PHAL_BUS_HANDLER Handler;
  1209. PLIST_ENTRY HibernateLink, ResumeLink;
  1210. NTSTATUS Status;
  1211. LockBusDatabase (&OldIrql);
  1212. ASSERT (OldIrql == HIGH_LEVEL);
  1213. //
  1214. // Notify bus handlers in reserved order for which they were installed
  1215. //
  1216. Status = STATUS_SUCCESS;
  1217. for (HibernateLink = HalpAllBusHandlers.Blink;
  1218. HibernateLink != &HalpAllBusHandlers && NT_SUCCESS(Status);
  1219. HibernateLink = HibernateLink->Blink) {
  1220. //
  1221. // Give this handler hibernate notification
  1222. //
  1223. Handler = CONTAINING_RECORD(HibernateLink, HAL_BUS_HANDLER, AllHandlers);
  1224. if (Handler->Handler.HibernateBus) {
  1225. Status = Handler->Handler.HibernateBus (
  1226. &Handler->Handler,
  1227. &Handler->Handler
  1228. );
  1229. }
  1230. }
  1231. //
  1232. // Suspend or Hibernate the system now
  1233. //
  1234. if (NT_SUCCESS (Status)) {
  1235. Status = HalpSuspendHibernateSystem (ResumeTime, SystemCallback);
  1236. }
  1237. //
  1238. // Notify bus handlers which were hibernated to restore state
  1239. //
  1240. for (ResumeLink = HibernateLink->Flink;
  1241. ResumeLink != &HalpAllBusHandlers;
  1242. ResumeLink = ResumeLink->Flink) {
  1243. //
  1244. // Give this handler resume notification
  1245. //
  1246. Handler = CONTAINING_RECORD(ResumeLink, HAL_BUS_HANDLER, AllHandlers);
  1247. if (Handler->Handler.ResumeBus) {
  1248. Handler->Handler.ResumeBus (
  1249. &Handler->Handler,
  1250. &Handler->Handler
  1251. );
  1252. }
  1253. }
  1254. UnlockBusDatabase (OldIrql);
  1255. return Status;
  1256. }
  1257. #endif