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.

999 lines
25 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. CmBatt.c
  5. Abstract:
  6. Control Method Battery Miniport Driver
  7. Author:
  8. Ron Mosgrove (Intel)
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "CmBattp.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE, CmBattSendDownStreamIrp)
  16. #pragma alloc_text(PAGE, CmBattGetUniqueId)
  17. #pragma alloc_text(PAGE, CmBattGetStaData)
  18. #pragma alloc_text(PAGE, CmBattSetTripPpoint)
  19. #endif
  20. #define EXPECTED_DATA_SIZE 512
  21. NTSTATUS
  22. CmBattSendDownStreamIrp(
  23. IN PDEVICE_OBJECT Pdo,
  24. IN ULONG Ioctl,
  25. IN PVOID InputBuffer,
  26. IN ULONG InputSize,
  27. IN PVOID OutputBuffer,
  28. IN ULONG OutputSize
  29. )
  30. /*++
  31. Routine Description:
  32. Called to send a request to the Pdo
  33. Arguments:
  34. Pdo - The request is sent to this device object
  35. Ioctl - the request
  36. InputBuffer - The incoming request
  37. InputSize - The size of the incoming request
  38. OutputBuffer - The answer
  39. OutputSize - The size of the answer buffer
  40. Return Value:
  41. NT Status of the operation
  42. --*/
  43. {
  44. IO_STATUS_BLOCK ioBlock;
  45. KEVENT event;
  46. NTSTATUS status;
  47. PIRP irp;
  48. PAGED_CODE();
  49. //
  50. // Initialize an event to wait on
  51. //
  52. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  53. //
  54. // Build the request
  55. //
  56. irp = IoBuildDeviceIoControlRequest(
  57. Ioctl,
  58. Pdo,
  59. InputBuffer,
  60. InputSize,
  61. OutputBuffer,
  62. OutputSize,
  63. FALSE,
  64. &event,
  65. &ioBlock
  66. );
  67. if (!irp) {
  68. CmBattPrint((CMBATT_ERROR | CMBATT_CM_EXE),
  69. ("CmBattSendDownStreamIrp: Failed to allocate Irp\n"));
  70. return STATUS_INSUFFICIENT_RESOURCES;
  71. }
  72. CmBattPrint(
  73. CMBATT_CM_EXE,
  74. ("CmBattSendDownStreamIrp: Irp %x [Tid] %x\n", irp, GetTid() )
  75. );
  76. //
  77. // Pass request to Pdo, always wait for completion routine
  78. //
  79. status = IoCallDriver(Pdo, irp);
  80. if (status == STATUS_PENDING) {
  81. //
  82. // Wait for the irp to be completed, then grab the real status code
  83. //
  84. KeWaitForSingleObject(
  85. &event,
  86. Executive,
  87. KernelMode,
  88. FALSE,
  89. NULL
  90. );
  91. status = ioBlock.Status;
  92. }
  93. //
  94. // Sanity check the data
  95. //
  96. if (OutputBuffer != NULL) {
  97. if ( ( (PACPI_EVAL_OUTPUT_BUFFER) OutputBuffer)->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
  98. ( (PACPI_EVAL_OUTPUT_BUFFER) OutputBuffer)->Count == 0) {
  99. status = STATUS_ACPI_INVALID_DATA;
  100. }
  101. }
  102. CmBattPrint(
  103. CMBATT_CM_EXE,
  104. ("CmBattSendDownStreamIrp: Irp %x completed %x! [Tid] %x\n",
  105. irp, status, GetTid() )
  106. );
  107. //
  108. // Done
  109. //
  110. return status;
  111. }
  112. NTSTATUS
  113. CmBattGetUniqueId(
  114. IN PDEVICE_OBJECT Pdo,
  115. OUT PULONG UniqueId
  116. )
  117. /*++
  118. Routine Description:
  119. Obtain the UID (unique ID) for a battery.
  120. Arguments:
  121. CmBatt - The extension for this device.
  122. UniqueId - Pointer to where the ID is stored.
  123. Return Value:
  124. NT Status of the operation
  125. --*/
  126. {
  127. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  128. ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  129. NTSTATUS status;
  130. PACPI_METHOD_ARGUMENT argument;
  131. PAGED_CODE();
  132. CmBattPrint(
  133. CMBATT_CM_EXE,
  134. ("CmBattGetUniqueId: Entered with Pdo %x Tid %x\n", Pdo, GetTid() )
  135. );
  136. ASSERT( UniqueId != NULL );
  137. *UniqueId = 0;
  138. //
  139. // Fill in the input data
  140. //
  141. inputBuffer.MethodNameAsUlong = CM_UID_METHOD;
  142. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  143. //
  144. // Send the request along
  145. //
  146. status = CmBattSendDownStreamIrp(
  147. Pdo,
  148. IOCTL_ACPI_EVAL_METHOD,
  149. &inputBuffer,
  150. sizeof(ACPI_EVAL_INPUT_BUFFER),
  151. &outputBuffer,
  152. sizeof(ACPI_EVAL_OUTPUT_BUFFER)
  153. );
  154. if (!NT_SUCCESS(status)) {
  155. CmBattPrint(
  156. (CMBATT_CM_EXE | CMBATT_BIOS),
  157. ("CmBattGetUniqueId: Failed _UID method - Status (0x%x)\n", status)
  158. );
  159. return status;
  160. }
  161. //
  162. // Grab the argument
  163. //
  164. argument = outputBuffer.Argument;
  165. status = GetDwordElement( argument, UniqueId );
  166. CmBattPrint(
  167. (CMBATT_CM_EXE | CMBATT_BIOS),
  168. ("CmBattGetUniqueId: _UID method returned 0x%x\n", *UniqueId)
  169. );
  170. return status;
  171. }
  172. NTSTATUS
  173. CmBattGetStaData(
  174. IN PDEVICE_OBJECT Pdo,
  175. OUT PULONG ReturnStatus
  176. )
  177. /*++
  178. Routine Description:
  179. Called to get a device status via the _STA method. Generic, works for
  180. any device with the _STA method (assuming caller has a Pdo).
  181. Arguments:
  182. Pdo - For the device.
  183. ReturnStatus - Pointer to where the status data is placed.
  184. Return Value:
  185. NT Status of the operation
  186. --*/
  187. {
  188. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  189. ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  190. NTSTATUS status;
  191. PACPI_METHOD_ARGUMENT argument;
  192. PAGED_CODE();
  193. CmBattPrint(
  194. CMBATT_CM_EXE,
  195. ("CmBattGetStaData: Entered with Pdo %x Tid %x\n", Pdo, GetTid() )
  196. );
  197. ASSERT( ReturnStatus != NULL );
  198. *ReturnStatus = 0x0;
  199. //
  200. // Fill in the input data
  201. //
  202. inputBuffer.MethodNameAsUlong = CM_STA_METHOD;
  203. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  204. //
  205. // Send the request along
  206. //
  207. status = CmBattSendDownStreamIrp(
  208. Pdo,
  209. IOCTL_ACPI_EVAL_METHOD,
  210. &inputBuffer,
  211. sizeof(ACPI_EVAL_INPUT_BUFFER),
  212. &outputBuffer,
  213. sizeof(ACPI_EVAL_OUTPUT_BUFFER)
  214. );
  215. if (!NT_SUCCESS(status)) {
  216. CmBattPrint(
  217. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  218. ("CmBattGetStaData: Failed _STA method - Status (0x%x)\n", status)
  219. );
  220. return STATUS_NO_SUCH_DEVICE;
  221. }
  222. //
  223. // Grab the argument
  224. //
  225. argument = outputBuffer.Argument;
  226. status = GetDwordElement( argument, ReturnStatus );
  227. CmBattPrint(
  228. (CMBATT_CM_EXE | CMBATT_BIOS),
  229. ("CmBattGetStaData: _STA method returned %x \n", *ReturnStatus )
  230. );
  231. return status;
  232. }
  233. NTSTATUS
  234. CmBattGetPsrData(
  235. IN PDEVICE_OBJECT Pdo,
  236. OUT PULONG ReturnStatus
  237. )
  238. /*++
  239. Routine Description:
  240. Called to get the AC adapter device status via the _PSR method.
  241. Arguments:
  242. Pdo - For the device.
  243. ReturnStatus - Pointer to where the status data is placed.
  244. Return Value:
  245. NT Status of the operation
  246. --*/
  247. {
  248. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  249. ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  250. NTSTATUS status;
  251. PACPI_METHOD_ARGUMENT argument;
  252. PAGED_CODE();
  253. CmBattPrint(
  254. CMBATT_CM_EXE,
  255. ("CmBattGetPsrData: Entered with Pdo %x Tid %x\n", Pdo, GetTid() )
  256. );
  257. ASSERT( ReturnStatus != NULL );
  258. *ReturnStatus = 0x0;
  259. //
  260. // Fill in the input data
  261. //
  262. inputBuffer.MethodNameAsUlong = CM_PSR_METHOD;
  263. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  264. //
  265. // Send the request along
  266. //
  267. status = CmBattSendDownStreamIrp(
  268. Pdo,
  269. IOCTL_ACPI_EVAL_METHOD,
  270. &inputBuffer,
  271. sizeof(ACPI_EVAL_INPUT_BUFFER),
  272. &outputBuffer,
  273. sizeof(ACPI_EVAL_OUTPUT_BUFFER)
  274. );
  275. if (!NT_SUCCESS(status)) {
  276. CmBattPrint(
  277. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  278. ("CmBattGetPsrData: Failed _PSR method - Status (0x%x)\n", status)
  279. );
  280. return status;
  281. }
  282. //
  283. // Get the value
  284. //
  285. argument = outputBuffer.Argument;
  286. status = GetDwordElement( argument, ReturnStatus );
  287. CmBattPrint(
  288. (CMBATT_CM_EXE | CMBATT_BIOS),
  289. ("CmBattGetPsrData: _PSR method returned %x \n", *ReturnStatus )
  290. );
  291. return status;
  292. }
  293. NTSTATUS
  294. CmBattSetTripPpoint(
  295. IN PCM_BATT CmBatt,
  296. IN ULONG TripPoint
  297. )
  298. /*++
  299. Routine Description:
  300. Called to set the tripPoint via the BTP control method.
  301. Arguments:
  302. CmBatt - The extension for this device.
  303. TripPoint - The desired alarm value
  304. Return Value:
  305. NT Status of the operation
  306. --*/
  307. {
  308. ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER inputBuffer;
  309. NTSTATUS status;
  310. PAGED_CODE();
  311. CmBattPrint(
  312. (CMBATT_CM_EXE | CMBATT_BIOS),
  313. ("CmBattSetTripPpoint: _BTP Alarm Value %x Device %x Tid %x\n",
  314. TripPoint, CmBatt->DeviceNumber, GetTid() )
  315. );
  316. //
  317. // Fill in the input data
  318. //
  319. inputBuffer.MethodNameAsUlong = CM_BTP_METHOD;
  320. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE;
  321. inputBuffer.IntegerArgument = TripPoint;
  322. //
  323. // Send the request along
  324. //
  325. status = CmBattSendDownStreamIrp(
  326. CmBatt->LowerDeviceObject,
  327. IOCTL_ACPI_EVAL_METHOD,
  328. &inputBuffer,
  329. sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER),
  330. NULL,
  331. 0
  332. );
  333. if (!NT_SUCCESS(status)) {
  334. CmBattPrint(
  335. (CMBATT_CM_EXE | CMBATT_BIOS),
  336. ("CmBattSetTripPpoint: Failed _BTP method on device %x - Status (0x%x)\n",
  337. CmBatt->DeviceNumber, status)
  338. );
  339. }
  340. //
  341. // Done
  342. //
  343. return status;
  344. }
  345. NTSTATUS
  346. CmBattGetBifData(
  347. IN PCM_BATT CmBatt,
  348. OUT PCM_BIF_BAT_INFO BifBuf
  349. )
  350. /*++
  351. Routine Description:
  352. Called to read the BIF package from ACPI
  353. Arguments:
  354. CmBatt - The extension for this device.
  355. BifBuf - Output buffer for the BIF data
  356. Return Value:
  357. NT Status of the operation
  358. --*/
  359. {
  360. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  361. NTSTATUS status;
  362. PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  363. PACPI_METHOD_ARGUMENT argument;
  364. CmBattPrint(
  365. CMBATT_CM_EXE,
  366. ("CmBattGetBifData: Buffer (0x%x) Device %x Tid %x\n",
  367. BifBuf, CmBatt->DeviceNumber, GetTid() )
  368. );
  369. //
  370. // Allocate a buffer for this
  371. //
  372. outputBuffer = ExAllocatePoolWithTag(
  373. PagedPool,
  374. EXPECTED_DATA_SIZE,
  375. 'MtaB'
  376. );
  377. if (!outputBuffer) {
  378. CmBattPrint(
  379. (CMBATT_ERROR | CMBATT_CM_EXE),
  380. ("CmBattGetBifData: Failed to allocate Buffer\n")
  381. );
  382. return STATUS_INSUFFICIENT_RESOURCES;
  383. }
  384. //
  385. // Clear the buffers
  386. //
  387. RtlZeroMemory(outputBuffer, EXPECTED_DATA_SIZE);
  388. RtlZeroMemory(BifBuf, sizeof(CM_BIF_BAT_INFO));
  389. //
  390. // Set the request data
  391. //
  392. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  393. inputBuffer.MethodNameAsUlong = CM_BIF_METHOD;
  394. //
  395. // Send the request along
  396. //
  397. status = CmBattSendDownStreamIrp(
  398. CmBatt->LowerDeviceObject,
  399. IOCTL_ACPI_EVAL_METHOD,
  400. &inputBuffer,
  401. sizeof(ACPI_EVAL_INPUT_BUFFER),
  402. outputBuffer,
  403. EXPECTED_DATA_SIZE
  404. );
  405. if (!NT_SUCCESS(status)) {
  406. CmBattPrint(
  407. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  408. ("CmBattGetBifData: Failed _BIF method on device %x - Status (0x%x)\n",
  409. CmBatt->DeviceNumber, status)
  410. );
  411. goto CmBattGetBifDataExit;
  412. }
  413. //
  414. // Sanity check the return count
  415. //
  416. if (outputBuffer->Count != NUMBER_OF_BIF_ELEMENTS) {
  417. //
  418. // Package did not contain the correct number of elements to be a BIF
  419. //
  420. CmBattPrint(
  421. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  422. ("CmBattGetBifData: _BIF returned %d elements. BIF requires %d\n",
  423. outputBuffer->Count,
  424. NUMBER_OF_BIF_ELEMENTS)
  425. );
  426. status = STATUS_ACPI_INVALID_DATA;
  427. goto CmBattGetBifDataExit;
  428. }
  429. //
  430. // Look at the return arguments
  431. //
  432. argument = outputBuffer->Argument;
  433. //
  434. // Parse the package data that is returned. This should look like:
  435. //
  436. status = GetDwordElement (argument, &BifBuf->PowerUnit);
  437. if (!NT_SUCCESS (status)) {
  438. CmBattPrint(
  439. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  440. ("CmBattGetBifData: Failed to get PowerUnit\n")
  441. );
  442. goto CmBattGetBifDataExit;
  443. }
  444. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  445. status = GetDwordElement (argument, &BifBuf->DesignCapacity);
  446. if (!NT_SUCCESS (status)) {
  447. CmBattPrint(
  448. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  449. ("CmBattGetBifData: Failed to get DesignCapacity\n")
  450. );
  451. goto CmBattGetBifDataExit;
  452. }
  453. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  454. status = GetDwordElement (argument, &BifBuf->LastFullChargeCapacity);
  455. if (!NT_SUCCESS (status)) {
  456. CmBattPrint(
  457. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  458. ("CmBattGetBifData: Failed to get LastFullChargeCapacity\n")
  459. );
  460. goto CmBattGetBifDataExit;
  461. }
  462. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  463. status = GetDwordElement (argument, &BifBuf->BatteryTechnology);
  464. if (!NT_SUCCESS (status)) {
  465. CmBattPrint(
  466. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  467. ("CmBattGetBifData: Failed to get BatteryTechnology\n")
  468. );
  469. goto CmBattGetBifDataExit;
  470. }
  471. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  472. status = GetDwordElement (argument, &BifBuf->DesignVoltage);
  473. if (!NT_SUCCESS (status)) {
  474. CmBattPrint(
  475. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  476. ("CmBattGetBifData: Failed to get DesignVoltage\n")
  477. );
  478. goto CmBattGetBifDataExit;
  479. }
  480. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  481. status = GetDwordElement (argument, &BifBuf->DesignCapacityOfWarning);
  482. if (!NT_SUCCESS (status)) {
  483. CmBattPrint(
  484. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  485. ("CmBattGetBifData: Failed to get DesignCapacityOfWarning\n")
  486. );
  487. goto CmBattGetBifDataExit;
  488. }
  489. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  490. status = GetDwordElement (argument, &BifBuf->DesignCapacityOfLow);
  491. if (!NT_SUCCESS (status)) {
  492. CmBattPrint(
  493. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  494. ("CmBattGetBifData: Failed to get DesignCapacityOfLow\n")
  495. );
  496. goto CmBattGetBifDataExit;
  497. }
  498. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  499. status = GetDwordElement (argument, &BifBuf->BatteryCapacityGran_1);
  500. if (!NT_SUCCESS (status)) {
  501. CmBattPrint(
  502. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  503. ("CmBattGetBifData: Failed to get BatteryCapacityGran_1\n")
  504. );
  505. goto CmBattGetBifDataExit;
  506. }
  507. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  508. status = GetDwordElement (argument, &BifBuf->BatteryCapacityGran_2);
  509. if (!NT_SUCCESS (status)) {
  510. CmBattPrint(
  511. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  512. ("CmBattGetBifData: Failed to get BatteryCapacityGran_2\n")
  513. );
  514. goto CmBattGetBifDataExit;
  515. }
  516. RtlZeroMemory (&BifBuf->ModelNumber[0], CM_MAX_STRING_LENGTH);
  517. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  518. status = GetStringElement (argument, &BifBuf->ModelNumber[0]);
  519. if (!NT_SUCCESS (status)) {
  520. CmBattPrint(
  521. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  522. ("CmBattGetBifData: Failed to get ModelNumber\n")
  523. );
  524. goto CmBattGetBifDataExit;
  525. }
  526. RtlZeroMemory (&BifBuf->SerialNumber[0], CM_MAX_STRING_LENGTH);
  527. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  528. status = GetStringElement (argument, &BifBuf->SerialNumber[0]);
  529. if (!NT_SUCCESS (status)) {
  530. CmBattPrint(
  531. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  532. ("CmBattGetBifData: Failed to get SerialNumber\n")
  533. );
  534. goto CmBattGetBifDataExit;
  535. }
  536. RtlZeroMemory (&BifBuf->BatteryType[0], CM_MAX_STRING_LENGTH);
  537. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  538. status = GetStringElement (argument, &BifBuf->BatteryType[0]);
  539. if (!NT_SUCCESS (status)) {
  540. CmBattPrint(
  541. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  542. ("CmBattGetBifData: Failed to get BatteryType\n")
  543. );
  544. goto CmBattGetBifDataExit;
  545. }
  546. RtlZeroMemory (&BifBuf->OEMInformation[0], CM_MAX_STRING_LENGTH);
  547. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  548. //
  549. // This returns an ASCIIZ string normally,
  550. // but returns integer 0x00 if OEMInformation isn't supported.
  551. //
  552. if (argument->Type == ACPI_METHOD_ARGUMENT_INTEGER) {
  553. if (argument->Argument != 0) {
  554. CmBattPrint(
  555. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  556. ("CmBattGetBifData: Failed to get OEMInformation\n")
  557. );
  558. goto CmBattGetBifDataExit;
  559. }
  560. BifBuf->OEMInformation[0] = 0;
  561. status = STATUS_SUCCESS;
  562. } else {
  563. status = GetStringElement (argument, &BifBuf->OEMInformation[0]);
  564. if (!NT_SUCCESS (status)) {
  565. CmBattPrint(
  566. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  567. ("CmBattGetBifData: OEMInformation not supported\n")
  568. );
  569. }
  570. }
  571. CmBattGetBifDataExit:
  572. //
  573. // Done
  574. //
  575. ExFreePool (outputBuffer);
  576. return status;
  577. }
  578. NTSTATUS
  579. CmBattGetBstData(
  580. IN PCM_BATT CmBatt,
  581. OUT PCM_BST_BAT_INFO BstBuf
  582. )
  583. /*++
  584. Routine Description:
  585. Called to read the BST package from ACPI
  586. Arguments:
  587. CmBatt - The extension for this device.
  588. BstBuf - Output buffer for the BST data
  589. Return Value:
  590. NT Status of the operation
  591. --*/
  592. {
  593. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  594. NTSTATUS status;
  595. PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  596. PACPI_METHOD_ARGUMENT argument;
  597. CmBattPrint(
  598. CMBATT_CM_EXE,
  599. ("CmBattGetBstData: Buffer (0x%x) Device %x Tid %x\n",
  600. BstBuf, CmBatt->DeviceNumber, GetTid() )
  601. );
  602. //
  603. // Allocate a buffer for this
  604. //
  605. outputBuffer = ExAllocatePoolWithTag(
  606. PagedPool,
  607. EXPECTED_DATA_SIZE,
  608. 'MtaB'
  609. );
  610. if (!outputBuffer) {
  611. CmBattPrint(
  612. (CMBATT_ERROR | CMBATT_CM_EXE),
  613. ("CmBattGetBstData: Failed to allocate Buffer\n")
  614. );
  615. return STATUS_INSUFFICIENT_RESOURCES;
  616. }
  617. //
  618. // Clear the buffers
  619. //
  620. RtlZeroMemory(outputBuffer, EXPECTED_DATA_SIZE);
  621. RtlZeroMemory(BstBuf, sizeof(CM_BST_BAT_INFO));
  622. //
  623. // Set the request data
  624. //
  625. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  626. inputBuffer.MethodNameAsUlong = CM_BST_METHOD;
  627. //
  628. // Send the request along
  629. //
  630. status = CmBattSendDownStreamIrp(
  631. CmBatt->LowerDeviceObject,
  632. IOCTL_ACPI_EVAL_METHOD,
  633. &inputBuffer,
  634. sizeof(ACPI_EVAL_INPUT_BUFFER),
  635. outputBuffer,
  636. EXPECTED_DATA_SIZE
  637. );
  638. if (!NT_SUCCESS(status)) {
  639. CmBattPrint(
  640. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  641. ("CmBattGetBstData: Failed _BST method on device %x - Status (0x%x)\n",
  642. CmBatt->DeviceNumber, status)
  643. );
  644. goto CmBattGetBstDataExit;
  645. }
  646. //
  647. // Sanity check the return value
  648. //
  649. if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
  650. outputBuffer->Count != NUMBER_OF_BST_ELEMENTS) {
  651. //
  652. // Package did not contain the correct number of elements to be a BIF
  653. //
  654. CmBattPrint(
  655. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  656. ("CmBattGetBstData: _BST returned %d elements. BIF requires %d\n",
  657. outputBuffer->Count,
  658. NUMBER_OF_BST_ELEMENTS)
  659. );
  660. status = STATUS_ACPI_INVALID_DATA;
  661. goto CmBattGetBstDataExit;
  662. }
  663. //
  664. // Look at the return arguments
  665. //
  666. argument = outputBuffer->Argument;
  667. //
  668. // Parse the package data that is returned. This should look like:
  669. //
  670. status = GetDwordElement (argument, &BstBuf->BatteryState);
  671. if (!NT_SUCCESS (status)) {
  672. CmBattPrint(
  673. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  674. ("CmBattGetBstData: Failed to get BatteryState\n")
  675. );
  676. goto CmBattGetBstDataExit;
  677. }
  678. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  679. status = GetDwordElement (argument, &BstBuf->PresentRate);
  680. if (!NT_SUCCESS (status)) {
  681. CmBattPrint(
  682. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  683. ("CmBattGetBstData: Failed to get PresentRate\n")
  684. );
  685. goto CmBattGetBstDataExit;
  686. }
  687. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  688. status = GetDwordElement (argument, &BstBuf->RemainingCapacity);
  689. if (!NT_SUCCESS (status)) {
  690. CmBattPrint(
  691. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  692. ("CmBattGetBstData: Failed to get RemainingCapacity\n")
  693. );
  694. goto CmBattGetBstDataExit;
  695. }
  696. argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
  697. status = GetDwordElement (argument, &BstBuf->PresentVoltage);
  698. if (!NT_SUCCESS (status)) {
  699. CmBattPrint(
  700. (CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
  701. ("CmBattGetBstData: Failed to get PresentVoltage\n")
  702. );
  703. goto CmBattGetBstDataExit;
  704. }
  705. CmBattPrint ((CMBATT_TRACE | CMBATT_DATA | CMBATT_BIOS),
  706. ("CmBattGetBstData: (BST) State=%x Rate=%x Capacity=%x Volts=%x\n",
  707. BstBuf->BatteryState, BstBuf->PresentRate,
  708. BstBuf->RemainingCapacity, BstBuf->PresentVoltage));
  709. //
  710. // Done --- cleanup
  711. //
  712. CmBattGetBstDataExit:
  713. ExFreePool( outputBuffer );
  714. return status;
  715. }
  716. NTSTATUS
  717. GetDwordElement (
  718. IN PACPI_METHOD_ARGUMENT Argument,
  719. OUT PULONG PDword
  720. )
  721. /*++
  722. Routine Description:
  723. This routine cracks the integer value from the argument and stores it
  724. in the supplied pointer to a ULONG
  725. Arguments:
  726. Argument - Points to the argument to parse
  727. PDword - Where to store the argument
  728. Return Value:
  729. NT Status of the operation
  730. --*/
  731. {
  732. //
  733. // Check to see if we have the right type of data
  734. //
  735. if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
  736. CmBattPrint(
  737. (CMBATT_ERROR | CMBATT_CM_EXE),
  738. ("GetDwordElement: Object contained wrong data type - %d\n",
  739. Argument->Type)
  740. );
  741. return STATUS_ACPI_INVALID_DATA;
  742. }
  743. //
  744. // Copy the DWORD
  745. //
  746. *PDword = Argument->Argument;
  747. //
  748. // Success!
  749. //
  750. return STATUS_SUCCESS;
  751. }
  752. NTSTATUS
  753. GetStringElement (
  754. IN PACPI_METHOD_ARGUMENT Argument,
  755. OUT PUCHAR PBuffer
  756. )
  757. /*++
  758. Routine Description:
  759. This routine cracks the string from the argument and stroes it in the
  760. supplied pointer to a PUCHAR
  761. Note: A buffer is allowed as well.
  762. Arguments:
  763. Argument - Points to the argument to parse
  764. PBuffer - Pointer to storage for the string
  765. Return Value:
  766. NT Status of the operation
  767. --*/
  768. {
  769. //
  770. // Check to see if we have the right type of data
  771. //
  772. if (Argument->Type != ACPI_METHOD_ARGUMENT_STRING &&
  773. Argument->Type != ACPI_METHOD_ARGUMENT_BUFFER) {
  774. CmBattPrint(
  775. (CMBATT_ERROR | CMBATT_CM_EXE),
  776. ("GetStringElement: Object contained wrong data type - %d\n",
  777. Argument->Type)
  778. );
  779. return STATUS_ACPI_INVALID_DATA;
  780. }
  781. //
  782. // Check to see if the return buffer is long enough
  783. //
  784. if (Argument->DataLength >= CM_MAX_STRING_LENGTH) {
  785. CmBattPrint(
  786. (CMBATT_ERROR | CMBATT_CM_EXE),
  787. ("GetStringElement: return buffer not big enough - %d\n",
  788. Argument->DataLength)
  789. );
  790. return STATUS_BUFFER_TOO_SMALL;
  791. }
  792. //
  793. // Copy the string
  794. //
  795. RtlCopyMemory (PBuffer, Argument->Data, Argument->DataLength);
  796. //
  797. // Success
  798. //
  799. return STATUS_SUCCESS;
  800. }