Leaked source code of windows server 2003
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.

680 lines
16 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. acpiinit.c
  5. Abstract:
  6. ACPI OS Independent initialization routines
  7. Author:
  8. Jason Clark (JasonCl)
  9. Stephane Plante (SPlante)
  10. Environment:
  11. NT Kernel Model Driver only
  12. Revision History:
  13. --*/
  14. #include "pch.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE,ACPIInitialize)
  17. #pragma alloc_text(PAGE,ACPIInitializeAMLI)
  18. #pragma alloc_text(PAGE,ACPIInitializeDDB)
  19. #pragma alloc_text(PAGE,ACPIInitializeDDBs)
  20. #pragma alloc_text(PAGE,GetPBlkAddress)
  21. #endif
  22. #ifdef DBG
  23. #define VERIFY_IO_WRITES
  24. #endif
  25. //
  26. // Pointer to global ACPIInformation structure.
  27. //
  28. PACPIInformation AcpiInformation = NULL;
  29. //
  30. // Global structure for Pnp/QUERY_INTERFACE
  31. //
  32. ACPI_INTERFACE_STANDARD ACPIInterfaceTable;
  33. PNSOBJ ProcessorList[ACPI_SUPPORTED_PROCESSORS];
  34. PRSDTINFORMATION RsdtInformation;
  35. //
  36. // Remember how many contexts we have reserved for the interpreter
  37. //
  38. ULONG AMLIMaxCTObjs;
  39. BOOLEAN
  40. ACPIInitialize(
  41. PVOID Context
  42. )
  43. /*++
  44. Routine Description:
  45. This routine is called by the OS to detect ACPI, store interesting
  46. information in the global data structure, enables ACPI on the machine,
  47. and finally load the DSDT
  48. Arguments:
  49. Context - The context to back to the OS upon a callback. Typically a
  50. deviceObject
  51. Return Value:
  52. BOOLEAN
  53. - TRUE if ACPI was found
  54. - FALSE, otherwise
  55. --*/
  56. {
  57. BOOLEAN bool;
  58. NTSTATUS status;
  59. PRSDT rootSystemDescTable;
  60. PAGED_CODE();
  61. //
  62. // Initialize the interpreter
  63. //
  64. status = ACPIInitializeAMLI();
  65. if (!NT_SUCCESS(status)) {
  66. ACPIPrint( (
  67. ACPI_PRINT_CRITICAL,
  68. "ACPIInitialize: AMLI failed initialization 0x%08lx\n",
  69. status
  70. ) );
  71. ASSERTMSG(
  72. "ACPIInitialize: AMLI failed initialization\n",
  73. NT_SUCCESS(status)
  74. );
  75. KeBugCheckEx(
  76. ACPI_BIOS_ERROR,
  77. ACPI_SYSTEM_CANNOT_START_ACPI,
  78. 0,
  79. 0,
  80. 0
  81. );
  82. }
  83. //
  84. // Get the linear address of the RSDT of NULL if ACPI is not present on
  85. // the System
  86. //
  87. rootSystemDescTable = ACPILoadFindRSDT();
  88. if ( rootSystemDescTable == NULL ) {
  89. ACPIPrint( (
  90. ACPI_PRINT_CRITICAL,
  91. "ACPIInitialize: ACPI RSDT Not Found\n"
  92. ) );
  93. ASSERTMSG(
  94. "ACPIInitialize: ACPI RSDT Not Found\n",
  95. rootSystemDescTable
  96. );
  97. KeBugCheckEx(
  98. ACPI_BIOS_ERROR,
  99. ACPI_SYSTEM_CANNOT_START_ACPI,
  100. 1,
  101. 0,
  102. 0
  103. );
  104. }
  105. //
  106. // ACPI is alive and well on this machine.
  107. //
  108. ACPIPrint( (
  109. ACPI_PRINT_LOADING,
  110. "ACPIInitalize: ACPI RSDT found at %p \n",
  111. rootSystemDescTable
  112. ) );
  113. //
  114. // Initialize table used for MJ_PNP/MN_QUERY_INTERFACE requests
  115. //
  116. ACPIInterfaceTable.Size = sizeof (ACPIInterfaceTable);
  117. ACPIInterfaceTable.GpeConnectVector = ACPIVectorConnect;
  118. ACPIInterfaceTable.GpeDisconnectVector = ACPIVectorDisconnect;
  119. ACPIInterfaceTable.GpeEnableEvent = ACPIVectorEnable;
  120. ACPIInterfaceTable.GpeDisableEvent = ACPIVectorDisable;
  121. ACPIInterfaceTable.GpeClearStatus = ACPIVectorClear;
  122. ACPIInterfaceTable.RegisterForDeviceNotifications = ACPIRegisterForDeviceNotifications;
  123. ACPIInterfaceTable.UnregisterForDeviceNotifications = ACPIUnregisterForDeviceNotifications;
  124. ACPIInterfaceTable.InterfaceReference = AcpiNullReference;
  125. ACPIInterfaceTable.InterfaceDereference = AcpiNullReference;
  126. ACPIInterfaceTable.Context = Context;
  127. ACPIInterfaceTable.Version = 1;
  128. //
  129. // Initialize global data structures
  130. //
  131. KeInitializeSpinLock (&GpeTableLock);
  132. KeInitializeSpinLock (&NotifyHandlerLock);
  133. ProcessorList[0] = 0;
  134. RtlZeroMemory( ProcessorList, ACPI_SUPPORTED_PROCESSORS * sizeof(PNSOBJ) );
  135. //
  136. // Allocate some memory to hold the ACPI Information structure.
  137. //
  138. AcpiInformation = (PACPIInformation) ExAllocatePoolWithTag(
  139. NonPagedPool,
  140. sizeof(ACPIInformation),
  141. ACPI_SHARED_INFORMATION_POOLTAG
  142. );
  143. if ( AcpiInformation == NULL ) {
  144. ACPIPrint( (
  145. ACPI_PRINT_CRITICAL,
  146. "ACPIInitialize: Could not allocate AcpiInformation (x%x bytes)\n",
  147. sizeof(ACPIInformation)
  148. ) );
  149. ASSERTMSG(
  150. "ACPIInitialize: Could not allocate AcpiInformation\n",
  151. AcpiInformation
  152. );
  153. KeBugCheckEx(
  154. ACPI_BIOS_ERROR,
  155. ACPI_SYSTEM_CANNOT_START_ACPI,
  156. 2,
  157. 0,
  158. 0
  159. );
  160. }
  161. RtlZeroMemory( AcpiInformation, sizeof(ACPIInformation) );
  162. AcpiInformation->ACPIOnly = TRUE;
  163. AcpiInformation->RootSystemDescTable = rootSystemDescTable;
  164. //
  165. // Initialize queue, lock, and owner info for the Global Lock.
  166. // This must be done before we ever call the interpreter!
  167. //
  168. KeInitializeSpinLock( &AcpiInformation->GlobalLockQueueLock );
  169. InitializeListHead( &AcpiInformation->GlobalLockQueue );
  170. AcpiInformation->GlobalLockOwnerContext = NULL;
  171. AcpiInformation->GlobalLockOwnerDepth = 0;
  172. //
  173. // Initialize most of the remaining fields in the AcpiInformation structure.
  174. // This function will return FALSE in case of a problem finding the required
  175. // tables
  176. //
  177. status = ACPILoadProcessRSDT();
  178. if ( !NT_SUCCESS(status) ) {
  179. ACPIPrint( (
  180. ACPI_PRINT_CRITICAL,
  181. "ACPIInitialize: ACPILoadProcessRSDT = 0x%08lx\n",
  182. status
  183. ) );
  184. ASSERTMSG(
  185. "ACPIInitialize: ACPILoadProcessRSDT Failed\n",
  186. NT_SUCCESS(status)
  187. );
  188. KeBugCheckEx(
  189. ACPI_BIOS_ERROR,
  190. ACPI_SYSTEM_CANNOT_START_ACPI,
  191. 3,
  192. 0,
  193. 0
  194. );
  195. }
  196. //
  197. // Now switch the machine into ACPI mode and initialize
  198. // the ACPI registers.
  199. //
  200. ACPIEnableInitializeACPI( FALSE );
  201. //
  202. // At this point, we can load all of the DDBs. We need to load all of
  203. // these tables *before* we try to enable any GPEs or Interrupt Vectors
  204. //
  205. status = ACPIInitializeDDBs();
  206. if (!NT_SUCCESS(status)) {
  207. ACPIPrint( (
  208. ACPI_PRINT_CRITICAL,
  209. "ACPIInitialize: ACPIInitializeLoadDDBs = 0x%08lx\n",
  210. status
  211. ) );
  212. ASSERTMSG(
  213. "ACPIInitialize: ACPIInitializeLoadDDBs Failed\n",
  214. NT_SUCCESS(status)
  215. );
  216. KeBugCheckEx(
  217. ACPI_BIOS_ERROR,
  218. ACPI_SYSTEM_CANNOT_START_ACPI,
  219. 4,
  220. 0,
  221. 0
  222. );
  223. }
  224. //
  225. // Hook the SCI Vector
  226. //
  227. bool = OSInterruptVector(
  228. Context
  229. );
  230. if ( !bool ) {
  231. //
  232. // Ooops... We were unable to hook the SCI vector. Clean Up and
  233. // fail to load.
  234. //
  235. ACPIPrint( (
  236. ACPI_PRINT_CRITICAL,
  237. "ACPIInitialize: OSInterruptVector Failed!!\n"
  238. ) );
  239. ASSERTMSG(
  240. "ACPIInitialize: OSInterruptVector Failed!!\n",
  241. bool
  242. );
  243. KeBugCheckEx(
  244. ACPI_BIOS_ERROR,
  245. ACPI_SYSTEM_CANNOT_START_ACPI,
  246. 5,
  247. 0,
  248. 0
  249. );
  250. }
  251. return (TRUE);
  252. }
  253. NTSTATUS
  254. ACPIInitializeAMLI(
  255. VOID
  256. )
  257. /*++
  258. Routine Description:
  259. Called by ACPIInitialize to init the interpreter. We go and read
  260. some values from the registry to decide what to initialize the
  261. interpreter with
  262. Arguments:
  263. None
  264. Return Value:
  265. NTSTATUS
  266. --*/
  267. {
  268. NTSTATUS status;
  269. ULONG amliInitFlags;
  270. ULONG contextBlockSize;
  271. ULONG globalHeapBlockSize;
  272. ULONG timeSliceLength;
  273. ULONG timeSliceInterval;
  274. ULONG argSize;
  275. PAGED_CODE();
  276. //
  277. // Initialize AMLI
  278. //
  279. argSize = sizeof(amliInitFlags);
  280. status = OSReadRegValue(
  281. "AMLIInitFlags",
  282. (HANDLE) NULL,
  283. &amliInitFlags,
  284. &argSize
  285. );
  286. if (!NT_SUCCESS(status) ) {
  287. amliInitFlags = 0;
  288. }
  289. argSize = sizeof(contextBlockSize);
  290. status = OSReadRegValue(
  291. "AMLICtxtBlkSize",
  292. (HANDLE) NULL,
  293. &contextBlockSize,
  294. &argSize
  295. );
  296. if (!NT_SUCCESS(status) ) {
  297. contextBlockSize = 0;
  298. }
  299. argSize = sizeof(globalHeapBlockSize);
  300. status = OSReadRegValue(
  301. "AMLIGlobalHeapBlkSize",
  302. (HANDLE) NULL,
  303. &globalHeapBlockSize,
  304. &argSize
  305. );
  306. if (!NT_SUCCESS(status) ) {
  307. globalHeapBlockSize = 0;
  308. }
  309. argSize = sizeof(timeSliceLength);
  310. status = OSReadRegValue(
  311. "AMLITimeSliceLength",
  312. (HANDLE) NULL,
  313. &timeSliceLength,
  314. &argSize
  315. );
  316. if (!NT_SUCCESS(status) ) {
  317. timeSliceLength = 0;
  318. }
  319. argSize = sizeof(timeSliceInterval);
  320. status = OSReadRegValue(
  321. "AMLITimeSliceInterval",
  322. (HANDLE) NULL,
  323. &timeSliceInterval,
  324. &argSize
  325. );
  326. if (!NT_SUCCESS(status) ) {
  327. timeSliceInterval = 0;
  328. }
  329. argSize = sizeof(AMLIMaxCTObjs);
  330. status = OSReadRegValue(
  331. "AMLIMaxCTObjs",
  332. (HANDLE) NULL,
  333. &AMLIMaxCTObjs,
  334. &argSize
  335. );
  336. if (!NT_SUCCESS(status)) {
  337. AMLIMaxCTObjs = 0;
  338. }
  339. //
  340. // Allow the OSes to do some work once the interperter has been loaded
  341. //
  342. OSInitializeCallbacks();
  343. //
  344. // Initialize the interpreter
  345. //
  346. return AMLIInitialize(
  347. contextBlockSize,
  348. globalHeapBlockSize,
  349. amliInitFlags,
  350. timeSliceLength,
  351. timeSliceInterval,
  352. AMLIMaxCTObjs
  353. );
  354. }
  355. NTSTATUS
  356. ACPIInitializeDDB(
  357. IN ULONG Index
  358. )
  359. /*++
  360. Routine Description:
  361. This routine is called to load the specificied Differentiated Data Block
  362. Arguments:
  363. Index - Index of information in the RsdtInformation
  364. Return Value:
  365. NTSTATUS
  366. --*/
  367. {
  368. BOOLEAN success;
  369. HANDLE diffDataBlock = NULL;
  370. NTSTATUS status;
  371. PDSDT table;
  372. PAGED_CODE();
  373. //
  374. // Convert the index into a table entry
  375. //
  376. table = (PDSDT) (RsdtInformation->Tables[Index].Address);
  377. //
  378. // Make sure that the checksum of the table is correct
  379. //
  380. success = ACPILoadTableCheckSum( table, table->Header.Length );
  381. if (success == FALSE) {
  382. KeBugCheckEx(
  383. ACPI_BIOS_ERROR,
  384. ACPI_SYSTEM_CANNOT_START_ACPI,
  385. 7,
  386. (ULONG_PTR) table,
  387. table->Header.CreatorRev
  388. );
  389. }
  390. //
  391. // Now call the Interpreter to read the Differentiated System
  392. // Description Block and build the ACPI Name Space.
  393. //
  394. status = AMLILoadDDB( table, &diffDataBlock );
  395. if (NT_SUCCESS(status) ) {
  396. //
  397. // Remember that we have loaded this table and that we have a
  398. // handle to it
  399. //
  400. RsdtInformation->Tables[Index].Flags |= RSDTELEMENT_LOADED;
  401. RsdtInformation->Tables[Index].Handle = diffDataBlock;
  402. } else {
  403. ACPIPrint( (
  404. ACPI_PRINT_CRITICAL,
  405. "ACPIInitializeDDB: AMLILoadDDB failed 0x%8x\n",
  406. status
  407. ) );
  408. ASSERTMSG(
  409. "ACPIInitializeDDB: AMLILoadDDB failed to load DDB\n",
  410. 0
  411. );
  412. KeBugCheckEx(
  413. ACPI_BIOS_ERROR,
  414. ACPI_SYSTEM_CANNOT_START_ACPI,
  415. 8,
  416. (ULONG_PTR) table,
  417. table->Header.CreatorRev
  418. );
  419. }
  420. return STATUS_SUCCESS;
  421. }
  422. NTSTATUS
  423. ACPIInitializeDDBs(
  424. VOID
  425. )
  426. /*++
  427. Routine Description:
  428. This function looks that the RsdtInformation and attemps to load
  429. all of the possible Dynamic Data Blocks
  430. Arguments:
  431. None
  432. Return Value:
  433. NTSTATUS
  434. --*/
  435. {
  436. NTSTATUS status;
  437. ULONG index;
  438. ULONG numElements;
  439. PAGED_CODE();
  440. //
  441. // Get the number of elements to process
  442. //
  443. numElements = RsdtInformation->NumElements;
  444. if (numElements == 0) {
  445. ACPIPrint( (
  446. ACPI_PRINT_CRITICAL,
  447. "ACPInitializeDDBs: No tables found in RSDT\n"
  448. ) );
  449. ASSERTMSG(
  450. "ACPIInitializeDDBs: No tables found in RSDT\n",
  451. numElements != 0
  452. );
  453. return STATUS_ACPI_INVALID_TABLE;
  454. }
  455. //
  456. // We would not be here unless we found a DSDT. So we assume that the
  457. // *LAST* entry in the table points to the DSDT that we will load. Make
  458. // sure that we can in fact load it, and then do so
  459. //
  460. index = numElements - 1;
  461. if ( !(RsdtInformation->Tables[index].Flags & RSDTELEMENT_MAPPED) ||
  462. !(RsdtInformation->Tables[index].Flags & RSDTELEMENT_LOADABLE) ) {
  463. ACPIPrint( (
  464. ACPI_PRINT_CRITICAL,
  465. "ACPInitializeDDB: DSDT not mapped or loadable\n"
  466. ) );
  467. ASSERTMSG(
  468. "ACPIInitializeDDB: DSDT not mapped\n",
  469. (RsdtInformation->Tables[index].Flags & RSDTELEMENT_MAPPED)
  470. );
  471. ASSERTMSG(
  472. "ACPIInitializeDDB: DSDT not loadable\n",
  473. (RsdtInformation->Tables[index].Flags & RSDTELEMENT_LOADABLE)
  474. );
  475. return STATUS_ACPI_INVALID_TABLE;
  476. }
  477. status = ACPIInitializeDDB( index );
  478. if (!NT_SUCCESS(status)) {
  479. return status;
  480. }
  481. //
  482. // We have one fewer element to look at, so lets ignore the DSDT entry
  483. //
  484. numElements--;
  485. //
  486. // Loop for all elements in the table
  487. //
  488. for (index = 0; index < numElements; index++) {
  489. //
  490. // Is the entry mapped and loadable?
  491. //
  492. if ( (RsdtInformation->Tables[index].Flags & RSDTELEMENT_MAPPED) &&
  493. (RsdtInformation->Tables[index].Flags & RSDTELEMENT_LOADABLE) ) {
  494. //
  495. // Load the table
  496. //
  497. status = ACPIInitializeDDB( index );
  498. if (!NT_SUCCESS(status)) {
  499. return status;
  500. }
  501. }
  502. }
  503. //
  504. // If we got here, then everything is okay
  505. //
  506. return STATUS_SUCCESS;
  507. }
  508. ULONG
  509. GetPBlkAddress(
  510. IN UCHAR Processor
  511. )
  512. {
  513. ULONG pblk;
  514. NTSTATUS status;
  515. OBJDATA data;
  516. PNSOBJ pnsobj = NULL;
  517. PPROCESSOROBJ pobj = NULL;
  518. if (Processor >= ACPI_SUPPORTED_PROCESSORS) {
  519. return 0;
  520. }
  521. if (!ProcessorList[Processor]) {
  522. return 0;
  523. }
  524. status = AMLIEvalNameSpaceObject(
  525. ProcessorList[Processor],
  526. &data,
  527. 0,
  528. NULL
  529. );
  530. if ( !NT_SUCCESS(status) ) {
  531. ACPIBreakPoint ();
  532. return (0);
  533. }
  534. ASSERT (data.dwDataType == OBJTYPE_PROCESSOR);
  535. ASSERT (data.pbDataBuff != NULL);
  536. pblk = ((PROCESSOROBJ *)data.pbDataBuff)->dwPBlk;
  537. AMLIFreeDataBuffs(&data, 1);
  538. return (pblk);
  539. }