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.

1058 lines
31 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. service.c
  5. Abstract:
  6. ACPI Embedded Controller Driver
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. Notes:
  11. Revision History:
  12. --*/
  13. #include "ecp.h"
  14. #define NTMS 10000L // 1 millisecond is ten thousand 100ns
  15. #define NTSEC (NTMS * 1000L)
  16. LARGE_INTEGER AcpiEcWatchdogTimeout = {(NTSEC * -5L), -1};
  17. LARGE_INTEGER AcpiEcLastActionTime = {0,0};
  18. PUCHAR AcpiEcActionDescription [EC_ACTION_MAX >> 4] = {
  19. "Invalid ",
  20. "Read Status",
  21. "Read Data ",
  22. "Write Cmd ",
  23. "Write Data ",
  24. "Interrupt ",
  25. "Disable GPE",
  26. "Enable GPE ",
  27. "Clear GPE ",
  28. "Queued IO ",
  29. "Repeated Last action this many times:"
  30. };
  31. VOID
  32. AcpiEcServiceDevice (
  33. IN PECDATA EcData
  34. )
  35. /*++
  36. Routine Description:
  37. This routine starts or continues servicing the device's work queue
  38. Arguments:
  39. EcData - Pointer to embedded controller to service.
  40. Return Value:
  41. None
  42. --*/
  43. {
  44. KIRQL OldIrql;
  45. //
  46. // Even though the device is unloaded, there might still be a
  47. // service call which occurs until the timer is canceled
  48. //
  49. EcPrint(EC_TRACE, ("AcpiEcServiceDevice.\n"));
  50. if (EcData->DeviceState > EC_DEVICE_UNLOAD_PENDING) {
  51. return;
  52. }
  53. //
  54. // Acquire device lock and signal function was entered
  55. //
  56. KeAcquireSpinLock (&EcData->Lock, &OldIrql);
  57. EcData->InServiceLoop = TRUE;
  58. //
  59. // If not already in service, enter InService
  60. //
  61. if (!EcData->InService) {
  62. EcData->InService = TRUE;
  63. //
  64. // Disable the device's interrupt
  65. //
  66. if (EcData->InterruptEnabled) {
  67. EcData->InterruptEnabled = FALSE;
  68. //
  69. // Call ACPI to disable the device's interrupt
  70. //
  71. AcpiEcLogAction (EcData, EC_ACTION_DISABLE_GPE, 0);
  72. AcpiInterfaces.GpeDisableEvent (AcpiInterfaces.Context,
  73. EcData->GpeVectorObject);
  74. }
  75. //
  76. // While service invocation pending, loop
  77. //
  78. while (EcData->InServiceLoop) {
  79. EcData->InServiceLoop = FALSE;
  80. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  81. //
  82. // Dispatch service handler
  83. //
  84. AcpiEcServiceIoLoop (EcData);
  85. //
  86. // Loop and re-service
  87. //
  88. KeAcquireSpinLock (&EcData->Lock, &OldIrql);
  89. }
  90. //
  91. // No longer in service loop
  92. //
  93. EcData->InService = FALSE;
  94. //
  95. // If unload is pending, check to see if the device can be unloaded now
  96. //
  97. if (EcData->DeviceState > EC_DEVICE_WORKING) {
  98. AcpiEcUnloadPending (EcData);
  99. }
  100. //
  101. // Enable the device's interrupt
  102. //
  103. if (!EcData->InterruptEnabled) {
  104. EcData->InterruptEnabled = TRUE;
  105. //
  106. // Call ACPI to enable the device's interrupt
  107. //
  108. AcpiEcLogAction (EcData, EC_ACTION_ENABLE_GPE, 0);
  109. AcpiInterfaces.GpeEnableEvent (AcpiInterfaces.Context,
  110. EcData->GpeVectorObject);
  111. }
  112. }
  113. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  114. }
  115. VOID
  116. AcpiEcServiceIoLoop (
  117. IN PECDATA EcData
  118. )
  119. /*++
  120. Routine Description:
  121. Main embedded controller device service loop. Services EC events,
  122. and processes IO queue. Terminate when the controller is busy (e.g.,
  123. wait for interrupt to continue) or when all servicing has been completed.
  124. N.B. Caller must be the owner of the device InService flag
  125. Arguments:
  126. EcData - Pointer to embedded controller to service.
  127. Return Value:
  128. none
  129. --*/
  130. {
  131. PIO_STACK_LOCATION IrpSp;
  132. PLIST_ENTRY Link;
  133. PIRP Irp;
  134. PUCHAR WritePort;
  135. UCHAR WriteData;
  136. UCHAR Status;
  137. UCHAR Data;
  138. BOOLEAN EcBusy;
  139. BOOLEAN BurstEnabled;
  140. BOOLEAN ProcessQuery;
  141. ULONG NoWorkStall;
  142. ULONG StallAccumulator;
  143. PULONG Timeout;
  144. KIRQL OldIrql;
  145. LIST_ENTRY CompleteQueue;
  146. ULONG i, j;
  147. //
  148. // EcBusy flags that there may be work to do. Initialized to TRUE every time
  149. // The service loop is entered, or when a timeout almost occured, but then some
  150. // work was found. It is set to FALSE when the IO queue is empty and there are
  151. // no query events pending.
  152. //
  153. EcBusy = TRUE;
  154. //
  155. // Timeout points to the counter to be incremented as the loop exits. It is
  156. // also used as a flag to indicate that the loop should exit. The loop won't
  157. // exit until Timeout != NULL. When exiting because of idleness, it is set
  158. // to the local vailable i, so that we don't keep a permanent count of those
  159. // timeout conditions. We keep track of how many time we timeout waiting for
  160. // the EC. If we do, we expect an interrupt when the EC is ready.
  161. //
  162. Timeout = NULL;
  163. //
  164. // This is set (along with WriteData) to have write a command or data to the
  165. // EC at the appropriate point in the loop.
  166. //
  167. WritePort = NULL;
  168. //
  169. // NoWorkStall is incremented every time through the loop. It is reset to 0
  170. // whenever any work is done. If it gets too big, Timeout is set. If it
  171. // then gets cleared before the loop actually exits, Timeout is Cleared.
  172. //
  173. NoWorkStall = 0;
  174. //
  175. // BurstEnable keeps trakc of whethe we think Burst Mode is enabled. If
  176. // Burst Mode gets disabled automatically by the EC, we know that and pretend
  177. // that burst mode is enabled so that the driver can make forward progress.
  178. //
  179. BurstEnabled = FALSE;
  180. //
  181. // ProcessQuery is set if we need to go run some _Qxx methods as the loop exits.
  182. //
  183. ProcessQuery = FALSE;
  184. //
  185. // StallAccumulator counts how many ticks we've stalled for using
  186. // KeStallExecutionProcessor during one complete run of the service loop.
  187. //
  188. StallAccumulator = 0;
  189. EcPrint(EC_TRACE, ("AcpiEcServiceIoLoop.\n"));
  190. InitializeListHead (&CompleteQueue);
  191. //
  192. // Loop while busy
  193. //
  194. for (; ;) {
  195. //
  196. // If there's outgoing data write it, issue the device required
  197. // stall and indicate work is being done (clear noworkstall)
  198. //
  199. if (WritePort) {
  200. EcPrint(EC_IO, ("AcpiEcServiceIO: Write = %x at %x\n", WriteData, WritePort));
  201. AcpiEcLogAction (EcData,
  202. (WritePort == EcData->CommandPort) ?
  203. EC_ACTION_WRITE_CMD : EC_ACTION_WRITE_DATA,
  204. WriteData);
  205. WRITE_PORT_UCHAR (WritePort, WriteData);
  206. KeStallExecutionProcessor (1);
  207. StallAccumulator += 1;
  208. WritePort = NULL;
  209. NoWorkStall = 0; // work was done
  210. }
  211. //
  212. // If work was done, clear pending timeout condition if it exists to
  213. // continue servicing the device
  214. //
  215. if (NoWorkStall == 0 && Timeout) {
  216. Timeout = NULL;
  217. EcBusy = TRUE;
  218. }
  219. //
  220. // If NoWorkStall is non-zero, then no work was performed. Determine
  221. // if the type of delay to issue while waiting (spinning) for the device
  222. //
  223. if (NoWorkStall) {
  224. //
  225. // No work was done the last time around.
  226. // If its time to timeout, exit the service loop.
  227. //
  228. if (Timeout) {
  229. break;
  230. }
  231. //
  232. // If device is idle, setup as if a timeout is occuring. This
  233. // will acquire the device lock, clear the gpe sts bit and terminate
  234. // the service loop (or if the device is now busy, continue)
  235. //
  236. if (!EcBusy) {
  237. if (Status & EC_BURST) {
  238. //
  239. // Before exiting, clear burst mode for embedded controller.
  240. // Has no response, no need to wait for EC to read it.
  241. //
  242. EcPrint (EC_IO, ("AcpiEcServiceIO: Clear Burst mode - Write = %x at %x\n", EC_CANCEL_BURST, EcData->CommandPort));
  243. AcpiEcLogAction (EcData, EC_ACTION_WRITE_CMD, EC_CANCEL_BURST);
  244. WRITE_PORT_UCHAR (EcData->CommandPort, EC_CANCEL_BURST);
  245. Timeout = &EcData->BurstComplete;
  246. } else {
  247. Timeout = &i;
  248. }
  249. } else {
  250. //
  251. // Interject stalls while spinning on device
  252. //
  253. StallAccumulator += NoWorkStall;
  254. KeStallExecutionProcessor (NoWorkStall);
  255. //
  256. // If wait is over the limit, prepare for a timeout.
  257. //
  258. if (!(Status & EC_BURST)) {
  259. if (NoWorkStall >= EcData->MaxNonBurstStall) {
  260. Timeout = &EcData->NonBurstTimeout;
  261. }
  262. } else {
  263. if (NoWorkStall >= EcData->MaxBurstStall) {
  264. Timeout = &EcData->BurstTimeout;
  265. }
  266. }
  267. }
  268. if (Timeout) {
  269. //
  270. // Over time limit, clear the GPE status bit
  271. //
  272. AcpiEcLogAction (EcData, EC_ACTION_CLEAR_GPE, 0);
  273. AcpiInterfaces.GpeClearStatus (AcpiInterfaces.Context,
  274. EcData->GpeVectorObject);
  275. }
  276. }
  277. //
  278. // Increase stall time and indicate no work was done
  279. //
  280. NoWorkStall += 1;
  281. //
  282. // Check Status
  283. //
  284. Status = READ_PORT_UCHAR (EcData->StatusPort);
  285. AcpiEcLogAction (EcData, EC_ACTION_READ_STATUS, Status);
  286. EcPrint(EC_IO, ("AcpiEcServiceIO: Status Read = %x at %x\n", Status, EcData->StatusPort));
  287. //
  288. // Keep bursts dropped by the EC stat
  289. //
  290. if (BurstEnabled && !(Status & EC_BURST)) {
  291. EcData->BurstAborted += 1;
  292. BurstEnabled = FALSE;
  293. Status |= EC_BURST; // move one char
  294. }
  295. //
  296. // If Embedded controller has data for us, process it
  297. //
  298. if (Status & EC_OUTPUT_FULL) {
  299. Data = READ_PORT_UCHAR (EcData->DataPort);
  300. AcpiEcLogAction (EcData, EC_ACTION_READ_DATA, Data);
  301. EcPrint(EC_IO, ("AcpiEcServiceIO: Data Read = %x at %x\n", Data, EcData->DataPort));
  302. switch (EcData->IoState) {
  303. case EC_IO_READ_QUERY:
  304. //
  305. // Response to a read query. Get the query value and set it
  306. //
  307. EcPrint(EC_NOTE, ("AcpiEcServiceIO: Query %x\n", Data));
  308. if (Data) {
  309. //
  310. // If not set, set pending bit
  311. //
  312. KeAcquireSpinLock (&EcData->Lock, &OldIrql);
  313. i = Data / BITS_PER_ULONG;
  314. j = 1 << (Data % BITS_PER_ULONG);
  315. if (!(EcData->QuerySet[i] & j)) {
  316. EcData->QuerySet[i] |= j;
  317. //
  318. // Queue the query or vector operation
  319. //
  320. if (EcData->QueryType[i] & j) {
  321. //
  322. // This is a vector, put it in the vector pending list
  323. //
  324. Data = EcData->QueryMap[Data];
  325. EcData->VectorTable[Data].Next = EcData->VectorHead;
  326. EcData->VectorHead = Data;
  327. } else {
  328. //
  329. // This is a query, put in in the query pending list
  330. //
  331. EcData->QueryMap[Data] = EcData->QueryHead;
  332. EcData->QueryHead = Data;
  333. }
  334. }
  335. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  336. ProcessQuery = TRUE;
  337. }
  338. EcData->IoState = EC_IO_NONE;
  339. break;
  340. case EC_IO_READ_BYTE:
  341. //
  342. // Read transfer. Read the data byte
  343. //
  344. *EcData->IoBuffer = Data;
  345. EcData->IoState = EC_IO_NEXT_BYTE;
  346. break;
  347. case EC_IO_BURST_ACK:
  348. //
  349. // Burst ACK byte
  350. //
  351. EcData->IoState = EcData->IoBurstState;
  352. EcData->IoBurstState = EC_IO_UNKNOWN;
  353. EcData->TotalBursts += 1;
  354. BurstEnabled = TRUE;
  355. break;
  356. default:
  357. EcPrint(EC_ERROR,
  358. ("AcpiEcService: Spurious data received State = %x, Data = %x\n",
  359. EcData->IoState, Data)
  360. );
  361. if( EcData->Errors < 5 ) {
  362. AcpiEcLogError (EcData, ACPIEC_ERR_SPURIOUS_DATA);
  363. }
  364. EcData->Errors += 1;
  365. break;
  366. }
  367. NoWorkStall = 0;
  368. continue;
  369. }
  370. if (Status & EC_INPUT_FULL) {
  371. //
  372. // The embedded controllers input buffer is full, wait
  373. //
  374. continue;
  375. }
  376. //
  377. // Embedded controller is ready to receive data, see if anything
  378. // is already being sent
  379. //
  380. switch (EcData->IoState) {
  381. case EC_IO_NEXT_BYTE:
  382. //
  383. // Data transfer.
  384. //
  385. if (EcData->IoRemain) {
  386. if (!(Status & EC_BURST)) {
  387. //
  388. // Not in burst mode. Write burst mode command
  389. //
  390. EcData->IoState = EC_IO_BURST_ACK;
  391. EcData->IoBurstState = EC_IO_NEXT_BYTE;
  392. WritePort = EcData->CommandPort;
  393. WriteData = EC_BURST_TRANSFER;
  394. } else {
  395. //
  396. // Send command to transfer next byte
  397. //
  398. EcData->IoBuffer += 1;
  399. EcData->IoAddress += 1;
  400. EcData->IoRemain -= 1;
  401. EcData->IoState = EC_IO_SEND_ADDRESS;
  402. WritePort = EcData->CommandPort;
  403. WriteData = EcData->IoTransferMode;
  404. }
  405. } else {
  406. //
  407. // Transfer complete
  408. //
  409. EcData->IoState = EC_IO_NONE;
  410. EcData->IoRemain = 0;
  411. Irp = EcData->DeviceObject->CurrentIrp;
  412. EcData->DeviceObject->CurrentIrp = NULL;
  413. Irp->IoStatus.Status = STATUS_SUCCESS;
  414. Irp->IoStatus.Information = EcData->IoLength;
  415. InsertTailList (&CompleteQueue, &Irp->Tail.Overlay.ListEntry);
  416. }
  417. break;
  418. case EC_IO_SEND_ADDRESS:
  419. //
  420. // Send address of transfer request
  421. //
  422. WritePort = EcData->DataPort;
  423. WriteData = EcData->IoAddress;
  424. //
  425. // Wait or send data byte next
  426. //
  427. if (EcData->IoTransferMode == EC_READ_BYTE) {
  428. EcData->IoState = EC_IO_READ_BYTE;
  429. } else {
  430. EcData->IoState = EC_IO_WRITE_BYTE;
  431. }
  432. break;
  433. case EC_IO_WRITE_BYTE:
  434. //
  435. // Write transfer - write the data byte
  436. //
  437. EcData->IoState = EC_IO_NEXT_BYTE;
  438. WritePort = EcData->DataPort;
  439. WriteData = *EcData->IoBuffer;
  440. break;
  441. }
  442. //
  443. // If something to write, loop and handle it
  444. //
  445. if (WritePort) {
  446. continue;
  447. }
  448. //
  449. // If state is NONE, then nothing is pending see what should be
  450. // initiated
  451. //
  452. if (EcData->IoState == EC_IO_NONE) {
  453. EcData->ConsecutiveFailures = 0;
  454. if (Status & EC_QEVT_PENDING) {
  455. //
  456. // Embedded Controller has some sort of event pending
  457. //
  458. EcPrint(EC_QUERY, ("AcpiEcServiceIO: Received Query Request.\n"));
  459. EcData->IoState = EC_IO_READ_QUERY;
  460. WritePort = EcData->CommandPort;
  461. WriteData = EC_QUERY_EVENT;
  462. //
  463. // Reset the watchdog timer
  464. //
  465. KeSetTimer (&EcData->WatchdogTimer,
  466. AcpiEcWatchdogTimeout,
  467. &EcData->WatchdogDpc);
  468. } else {
  469. //
  470. // Get next tranfer from IO queue
  471. //
  472. Link = ExInterlockedRemoveHeadList (&EcData->WorkQueue, &EcData->Lock);
  473. //
  474. // If there's a transfer initiate it
  475. //
  476. if (Link) {
  477. EcPrint(EC_HANDLER, ("AcpiEcServiceIO: Got next work item %x\n", Link));
  478. Irp = CONTAINING_RECORD (
  479. Link,
  480. IRP,
  481. Tail.Overlay.ListEntry
  482. );
  483. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  484. EcData->DeviceObject->CurrentIrp = Irp;
  485. EcData->IoBuffer = Irp->AssociatedIrp.SystemBuffer;
  486. EcData->IoAddress = (UCHAR) IrpSp->Parameters.Read.ByteOffset.LowPart;
  487. EcData->IoLength = (UCHAR) IrpSp->Parameters.Read.Length;
  488. EcData->IoTransferMode =
  489. IrpSp->MajorFunction == IRP_MJ_READ ? EC_READ_BYTE : EC_WRITE_BYTE;
  490. //
  491. // Set it up via EC_IO_NEXT_BYTE and back up one byte
  492. //
  493. EcData->IoBuffer -= 1;
  494. EcData->IoAddress -= 1;
  495. EcData->IoRemain = EcData->IoLength;
  496. EcData->IoState = EC_IO_NEXT_BYTE;
  497. NoWorkStall = 0;
  498. //
  499. // Reset the watchdog timer
  500. //
  501. KeSetTimer (&EcData->WatchdogTimer,
  502. AcpiEcWatchdogTimeout,
  503. &EcData->WatchdogDpc);
  504. } else {
  505. //
  506. // Nothing but nothing to do.
  507. //
  508. EcBusy = FALSE;
  509. //
  510. // Clear the Watchdog timer
  511. //
  512. KeCancelTimer (&EcData->WatchdogTimer);
  513. }
  514. }
  515. }
  516. }
  517. //
  518. // Keep stat as to why service loop terminated
  519. //
  520. *Timeout += 1;
  521. //
  522. // Track maximum service loop stall accumulator
  523. //
  524. if (StallAccumulator > EcData->MaxServiceLoop) {
  525. EcData->MaxServiceLoop = StallAccumulator;
  526. }
  527. //
  528. // Complete processed io requests
  529. //
  530. while (!IsListEmpty(&CompleteQueue)) {
  531. Link = RemoveHeadList(&CompleteQueue);
  532. Irp = CONTAINING_RECORD (
  533. Link,
  534. IRP,
  535. Tail.Overlay.ListEntry
  536. );
  537. EcPrint(EC_IO, ("AcpiEcServiceIO: IOComplete: Irp=%Lx\n", Irp));
  538. #if DEBUG
  539. if (ECDebug & EC_TRANSACTION) {
  540. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  541. if (IrpSp->MajorFunction == IRP_MJ_READ) {
  542. EcPrint (EC_TRANSACTION, ("AcpiEcServiceIO: Read ("));
  543. for (i=0; i < IrpSp->Parameters.Read.Length; i++) {
  544. EcPrint (EC_TRANSACTION, ("%02x ",
  545. ((PUCHAR)Irp->AssociatedIrp.SystemBuffer) [i]));
  546. }
  547. EcPrint (EC_TRANSACTION, (") from %02x length %02x\n",
  548. (UCHAR)IrpSp->Parameters.Read.ByteOffset.LowPart,
  549. (UCHAR)IrpSp->Parameters.Read.Length));
  550. }
  551. }
  552. #endif
  553. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  554. }
  555. //
  556. // If queries occured, dispatch them
  557. //
  558. if (ProcessQuery) {
  559. AcpiEcDispatchQueries (EcData);
  560. }
  561. }
  562. VOID
  563. AcpiEcWatchdogDpc(
  564. IN PKDPC Dpc,
  565. IN PECDATA EcData,
  566. IN PVOID SystemArgument1,
  567. IN PVOID SystemArgument2
  568. )
  569. /*++
  570. Routine Description:
  571. Gets called if EC doesn't respond within 5 seconds of request.
  572. Arguments:
  573. EcData - Pointer to embedded controller to service.
  574. Return Value:
  575. None.
  576. --*/
  577. {
  578. UCHAR ecStatus;
  579. PIRP Irp;
  580. KIRQL OldIrql;
  581. #if DEBUG
  582. UCHAR i;
  583. #endif
  584. ecStatus = READ_PORT_UCHAR (EcData->StatusPort);
  585. AcpiEcLogAction (EcData, EC_ACTION_READ_STATUS, ecStatus);
  586. if (EcData->ConsecutiveFailures < 255) {
  587. EcData->ConsecutiveFailures++;
  588. }
  589. if (EcData->ConsecutiveFailures <= 5) {
  590. //
  591. // Only log an error for the first 5 consecutive failures. After that just be quiet about it.
  592. //
  593. AcpiEcLogError(EcData, ACPIEC_ERR_WATCHDOG);
  594. }
  595. EcPrint (EC_ERROR, ("AcpiEcWatchdogDpc: EC error encountered. \nAction History:\n"
  596. " D time IoState Action Data\n"
  597. " *%3dns\n", (ULONG)(1000000000/EcData->PerformanceFrequency.QuadPart)));
  598. #if DEBUG
  599. i = EcData->LastAction;
  600. do {
  601. i++;
  602. i &= ACPIEC_ACTION_COUNT_MASK;
  603. if ((EcData->RecentActions[i].IoStateAction & EC_ACTION_MASK) == 0) {
  604. continue;
  605. }
  606. EcPrint (EC_ERROR, (" %04x %01x %s 0x%02x\n",
  607. EcData->RecentActions[i].Time,
  608. EcData->RecentActions[i].IoStateAction & ~EC_ACTION_MASK,
  609. (EcData->RecentActions[i].IoStateAction & EC_ACTION_MASK) < EC_ACTION_MAX ?
  610. AcpiEcActionDescription [(EcData->RecentActions[i].IoStateAction & EC_ACTION_MASK) >> 4] : "",
  611. EcData->RecentActions[i].Data));
  612. } while (i != EcData->LastAction);
  613. #endif
  614. KeAcquireSpinLock (&EcData->Lock, &OldIrql);
  615. if (EcData->InService) {
  616. //
  617. // This is not likely to happen.
  618. // If the service loop is running, this should exit.
  619. // Reset the Watchdog Timer. This may be set again or canceld by the service loop
  620. //
  621. KeSetTimer (&EcData->WatchdogTimer,
  622. AcpiEcWatchdogTimeout,
  623. &EcData->WatchdogDpc);
  624. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  625. return;
  626. }
  627. //
  628. // Hold Spinlock throughout so we can guatantee there won't be a conflict in the IO queue.
  629. //
  630. EcData->InService = TRUE;
  631. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  632. switch (EcData->IoState) {
  633. case EC_IO_NONE:
  634. //
  635. // This shouldn't happen. The watchdog should be shut off if the
  636. // driver isn't busy.
  637. //
  638. break;
  639. case EC_IO_READ_BYTE:
  640. case EC_IO_BURST_ACK:
  641. if (ecStatus & EC_OUTPUT_FULL) {
  642. //
  643. // EC appears to be ready. Log an error and continue.
  644. //
  645. } else {
  646. //
  647. // If the embedded controller is not ready yet, somthing went wrong.
  648. // Retry the transaction.
  649. //
  650. if (EcData->IoState == EC_IO_READ_BYTE) {
  651. EcData->IoBuffer -= 1;
  652. EcData->IoAddress -= 1;
  653. EcData->IoRemain += 1;
  654. }
  655. EcData->IoState = EC_IO_NEXT_BYTE;
  656. }
  657. break;
  658. case EC_IO_READ_QUERY:
  659. if (ecStatus & EC_OUTPUT_FULL) {
  660. //
  661. // EC appears to be ready. Log an error and continue.
  662. //
  663. } else {
  664. //
  665. // If the embedded controller is not ready yet, somthing went wrong.
  666. // This could mean that the query was lost. If the Query bit is still set,
  667. // the driver will retry automatically.
  668. //
  669. EcData->IoState = EC_IO_NONE;
  670. }
  671. break;
  672. case EC_IO_WRITE_BYTE:
  673. case EC_IO_SEND_ADDRESS:
  674. //
  675. // This is just waiting for IBF==0. If it took this long, chances are the
  676. // state was lost. Retry the transaction.
  677. //
  678. EcData->IoBuffer -= 1;
  679. EcData->IoAddress -= 1;
  680. EcData->IoRemain += 1;
  681. EcData->IoState = EC_IO_NEXT_BYTE;
  682. break;
  683. case EC_IO_NEXT_BYTE:
  684. //
  685. // This could happen if IBF is still set
  686. //
  687. if (ecStatus & EC_INPUT_FULL) {
  688. //
  689. // Try thwaking it to see if it will wake up.
  690. //
  691. EcPrint (EC_IO, ("AcpiEcWatchDog: Clear Burst mode - Write = %x at %x\n", EC_CANCEL_BURST, EcData->CommandPort));
  692. AcpiEcLogAction (EcData, EC_ACTION_WRITE_CMD, EC_CANCEL_BURST);
  693. WRITE_PORT_UCHAR (EcData->CommandPort, EC_CANCEL_BURST);
  694. }
  695. }
  696. KeAcquireSpinLock (&EcData->Lock, &OldIrql);
  697. EcData->InService = FALSE;
  698. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  699. //
  700. // Set the timer. The ServiceIoLoop won't reset the timer, until some forward progress is made.
  701. //
  702. KeSetTimer (&EcData->WatchdogTimer,
  703. AcpiEcWatchdogTimeout,
  704. &EcData->WatchdogDpc);
  705. AcpiEcServiceDevice(EcData);
  706. }
  707. VOID
  708. AcpiEcLogAction (
  709. PECDATA EcData,
  710. UCHAR Action,
  711. UCHAR Data
  712. )
  713. {
  714. UCHAR i, j;
  715. LARGE_INTEGER time, temp;
  716. i = EcData->LastAction;
  717. j = (i-1)&ACPIEC_ACTION_COUNT_MASK;
  718. if ( ((EcData->RecentActions [i].IoStateAction & EC_ACTION_MASK) == EC_ACTION_REPEATED) &&
  719. (EcData->RecentActions [j].IoStateAction == (EcData->IoState | Action)) &&
  720. (EcData->RecentActions [j].Data == Data)) {
  721. //
  722. // If we already have a repeated action, increment the count on the repeated action
  723. // then update the time on the latest one. We only care about the time of the first and last one.
  724. //
  725. EcData->RecentActions [i].Data++;
  726. if (EcData->RecentActions [i].Data == 0) {
  727. //
  728. // If we've logged 255 repeats, don't roll over to 0.
  729. //
  730. EcData->RecentActions [i].Data = 0xff;
  731. }
  732. time = KeQueryPerformanceCounter (NULL);
  733. temp.QuadPart = time.QuadPart - AcpiEcLastActionTime.QuadPart;
  734. temp.QuadPart = temp.QuadPart + EcData->RecentActions[i].Time;
  735. if (temp.QuadPart > ((USHORT) -1)) {
  736. temp.QuadPart = (USHORT) -1;
  737. }
  738. EcData->RecentActions[i].Time = (USHORT) temp.LowPart;
  739. } else if ((EcData->RecentActions [i].IoStateAction == (EcData->IoState | Action)) &&
  740. (EcData->RecentActions [i].Data == Data)) {
  741. //
  742. // This is the same action as the last one. list as a repeated action
  743. //
  744. EcData->LastAction++;
  745. EcData->LastAction &= ACPIEC_ACTION_COUNT_MASK;
  746. EcData->RecentActions[EcData->LastAction].Data = 1;
  747. time = KeQueryPerformanceCounter (NULL);
  748. temp.QuadPart = time.QuadPart - AcpiEcLastActionTime.QuadPart;
  749. if (temp.QuadPart > ((USHORT) -1)) {
  750. temp.QuadPart = (USHORT) -1;
  751. }
  752. EcData->RecentActions[EcData->LastAction].Time = (USHORT) temp.LowPart;
  753. AcpiEcLastActionTime = time;
  754. // Set this last since it is the key to saying that an entry is complete.
  755. EcData->RecentActions[EcData->LastAction].IoStateAction = EC_ACTION_REPEATED | EcData->IoState;
  756. } else {
  757. EcData->LastAction++;
  758. EcData->LastAction &= ACPIEC_ACTION_COUNT_MASK;
  759. EcData->RecentActions[EcData->LastAction].Data = Data;
  760. time = KeQueryPerformanceCounter (NULL);
  761. temp.QuadPart = time.QuadPart - AcpiEcLastActionTime.QuadPart;
  762. if (temp.QuadPart > ((USHORT) -1)) {
  763. temp.QuadPart = (USHORT) -1;
  764. }
  765. EcData->RecentActions[EcData->LastAction].Time = (USHORT) temp.LowPart;
  766. AcpiEcLastActionTime = time;
  767. // Set this last since it is the key to saying that an entry is complete.
  768. EcData->RecentActions[EcData->LastAction].IoStateAction = Action | EcData->IoState;
  769. }
  770. }
  771. VOID
  772. AcpiEcLogError (
  773. PECDATA EcData,
  774. NTSTATUS ErrCode
  775. )
  776. {
  777. PIO_ERROR_LOG_PACKET logEntry = NULL;
  778. PACPIEC_ACTION action;
  779. ULONG size;
  780. UCHAR i;
  781. logEntry = IoAllocateErrorLogEntry(EcData->DeviceObject,
  782. ERROR_LOG_MAXIMUM_SIZE);
  783. if (!logEntry) {
  784. EcPrint (EC_ERROR, ("AcpiEcLogError: Couldn't write error to errorlog\n"));
  785. return;
  786. }
  787. RtlZeroMemory(logEntry, ERROR_LOG_MAXIMUM_SIZE);
  788. //
  789. // Fill out the packet
  790. //
  791. logEntry->DumpDataSize = (USHORT) ERROR_LOG_MAXIMUM_SIZE - sizeof(IO_ERROR_LOG_PACKET);
  792. logEntry->NumberOfStrings = 0;
  793. logEntry->ErrorCode = ErrCode;
  794. //
  795. // Fill in data
  796. //
  797. logEntry->DumpData[0] = EcData->PerformanceFrequency.LowPart;
  798. action = (PACPIEC_ACTION) (&logEntry->DumpData[1]);
  799. size = sizeof(IO_ERROR_LOG_PACKET) + sizeof(logEntry->DumpData[0]) + sizeof(ACPIEC_ACTION);
  800. i = EcData->LastAction;
  801. while (size <= ERROR_LOG_MAXIMUM_SIZE) {
  802. RtlCopyMemory (action, &EcData->RecentActions[i], sizeof(ACPIEC_ACTION));
  803. i--;
  804. i &= ACPIEC_ACTION_COUNT_MASK;
  805. if (i == EcData->LastAction) {
  806. break;
  807. }
  808. action++;
  809. size += sizeof(ACPIEC_ACTION);
  810. }
  811. //
  812. // Submit error log packet
  813. //
  814. IoWriteErrorLogEntry(logEntry);
  815. }