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

2829 lines
90 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. kbddep.c
  5. Abstract:
  6. The initialization and hardware-dependent portions of
  7. the Intel i8042 port driver which are specific to the
  8. keyboard.
  9. Environment:
  10. Kernel mode only.
  11. Notes:
  12. NOTES: (Future/outstanding issues)
  13. - Powerfail not implemented.
  14. - Consolidate duplicate code, where possible and appropriate.
  15. Revision History:
  16. --*/
  17. #include "stdarg.h"
  18. #include "stdio.h"
  19. #include "string.h"
  20. #include <ntddk.h>
  21. #include <windef.h>
  22. #include <imm.h>
  23. #include "i8042prt.h"
  24. #include "i8042log.h"
  25. //
  26. // Use the alloc_text pragma to specify the driver initialization routines
  27. // (they can be paged out).
  28. //
  29. #ifdef ALLOC_PRAGMA
  30. #pragma alloc_text(PAGE, I8xKeyboardConfiguration)
  31. #pragma alloc_text(PAGE, I8xInitializeKeyboard)
  32. #pragma alloc_text(PAGE, I8xKeyboardServiceParameters)
  33. #pragma alloc_text(PAGE, I8xServiceCrashDump)
  34. #endif
  35. #define BUFFER_FULL (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)
  36. #define GET_MAKE_CODE(_sc_) (_sc_ & 0x7F)
  37. //
  38. // Tests for the top bit
  39. //
  40. #define IS_BREAK_CODE(_sc_) (_sc_ > (UCHAR) 0x7F)
  41. #define IS_MAKE_CODE(_sc_) (_sc_ <= (UCHAR) 0x7F)
  42. BOOLEAN
  43. I8042KeyboardInterruptService(
  44. IN PKINTERRUPT Interrupt,
  45. IN PDEVICE_OBJECT DeviceObject
  46. )
  47. /*++
  48. Routine Description:
  49. This routine performs the actual work. It either processes a keystroke or
  50. the results from a write to the device.
  51. Arguments:
  52. CallIsrContext - Contains the interrupt object and device object.
  53. Return Value:
  54. TRUE if the interrupt was truly ours
  55. --*/
  56. {
  57. UCHAR scanCode, statusByte;
  58. PPORT_KEYBOARD_EXTENSION deviceExtension;
  59. KEYBOARD_SCAN_STATE *scanState;
  60. PKEYBOARD_INPUT_DATA input;
  61. ULONG i;
  62. #ifdef FE_SB
  63. PKEYBOARD_ID KeyboardId;
  64. #endif
  65. IsrPrint(DBG_KBISR_TRACE, ("enter\n"));
  66. //
  67. // Get the device extension.
  68. //
  69. deviceExtension = (PPORT_KEYBOARD_EXTENSION) DeviceObject->DeviceExtension;
  70. //
  71. // The interrupt will fire when we try to toggle the interrupts on the
  72. // controller itself. Don't touch any of the ports in this state and the
  73. // toggle will succeed.
  74. //
  75. if (deviceExtension->PowerState != PowerDeviceD0) {
  76. return FALSE;
  77. }
  78. #ifdef FE_SB
  79. //
  80. // Get a pointer to keyboard id.
  81. //
  82. KeyboardId = &deviceExtension->KeyboardAttributes.KeyboardIdentifier;
  83. #endif
  84. //
  85. // Verify that this device really interrupted. Check the status
  86. // register. The Output Buffer Full bit should be set, and the
  87. // Auxiliary Device Output Buffer Full bit should be clear.
  88. //
  89. statusByte =
  90. I8X_GET_STATUS_BYTE(Globals.ControllerData->DeviceRegisters[CommandPort]);
  91. if ((statusByte & BUFFER_FULL) != OUTPUT_BUFFER_FULL) {
  92. //
  93. // Stall and then try again. The Olivetti MIPS machine
  94. // sometimes gets an interrupt before the status
  95. // register is set. They do this for DOS compatibility (some
  96. // DOS apps do things in polled mode, until they see a character
  97. // in the keyboard buffer at which point they expect to get
  98. // an interrupt???).
  99. //
  100. for (i = 0; i < (ULONG)Globals.ControllerData->Configuration.PollStatusIterations; i++) {
  101. KeStallExecutionProcessor(1);
  102. statusByte = I8X_GET_STATUS_BYTE(Globals.ControllerData->DeviceRegisters[CommandPort]);
  103. if ((statusByte & BUFFER_FULL) == (OUTPUT_BUFFER_FULL)) {
  104. break;
  105. }
  106. }
  107. statusByte = I8X_GET_STATUS_BYTE(Globals.ControllerData->DeviceRegisters[CommandPort]);
  108. if ((statusByte & BUFFER_FULL) != (OUTPUT_BUFFER_FULL)) {
  109. //
  110. // Not our interrupt.
  111. //
  112. // NOTE: If the keyboard has not yet been "enabled", go ahead
  113. // and read a byte from the data port anyway.
  114. // This fixes weirdness on some Gateway machines, where
  115. // we get an interrupt sometime during driver initialization
  116. // after the interrupt is connected, but the output buffer
  117. // full bit never gets set.
  118. //
  119. IsrPrint(DBG_KBISR_ERROR|DBG_KBISR_INFO, ("not our interrupt!\n"));
  120. if (deviceExtension->EnableCount == 0) {
  121. scanCode =
  122. I8X_GET_DATA_BYTE(Globals.ControllerData->DeviceRegisters[DataPort]);
  123. }
  124. return FALSE;
  125. }
  126. }
  127. //
  128. // The interrupt is valid. Read the byte from the i8042 data port.
  129. //
  130. I8xGetByteAsynchronous(
  131. (CCHAR) KeyboardDeviceType,
  132. &scanCode
  133. );
  134. deviceExtension->LastScanCode = deviceExtension->CurrentScanCode;
  135. deviceExtension->CurrentScanCode = scanCode;
  136. IsrPrint(DBG_KBISR_SCODE, ("scanCode 0x%x\n", scanCode));
  137. if (deviceExtension->IsrHookCallback) {
  138. BOOLEAN cont = FALSE, ret;
  139. ret = (*deviceExtension->IsrHookCallback)(
  140. deviceExtension->HookContext,
  141. &deviceExtension->CurrentInput,
  142. &deviceExtension->CurrentOutput,
  143. statusByte,
  144. &scanCode,
  145. &cont,
  146. &deviceExtension->CurrentScanState
  147. );
  148. if (!cont) {
  149. return ret;
  150. }
  151. }
  152. //
  153. // Take the appropriate action, depending on whether the byte read
  154. // is a keyboard command response or a real scan code.
  155. //
  156. switch(scanCode) {
  157. //
  158. // The keyboard controller requests a resend. If the resend count
  159. // has not been exceeded, re-initiate the I/O operation.
  160. //
  161. case RESEND:
  162. IsrPrint(DBG_KBISR_INFO,
  163. (" RESEND, retries = %d\n",
  164. deviceExtension->ResendCount + 1
  165. ));
  166. //
  167. // If the timer count is zero, don't process the interrupt
  168. // further. The timeout routine will complete this request.
  169. //
  170. if (Globals.ControllerData->TimerCount == 0) {
  171. break;
  172. }
  173. //
  174. // Reset the timeout value to indicate no timeout.
  175. //
  176. Globals.ControllerData->TimerCount = I8042_ASYNC_NO_TIMEOUT;
  177. //
  178. // If the maximum number of retries has not been exceeded,
  179. //
  180. if ((deviceExtension->CurrentOutput.State == Idle)
  181. || (DeviceObject->CurrentIrp == NULL)) {
  182. //
  183. // We weren't sending a command or parameter to the hardware.
  184. // This must be a scan code. I hear the Brazilian keyboard
  185. // actually uses this.
  186. //
  187. goto ScanCodeCase;
  188. } else if (deviceExtension->ResendCount
  189. < Globals.ControllerData->Configuration.ResendIterations) {
  190. //
  191. // retard the byte count to resend the last byte
  192. //
  193. deviceExtension->CurrentOutput.CurrentByte -= 1;
  194. deviceExtension->ResendCount += 1;
  195. I8xInitiateIo(DeviceObject);
  196. } else {
  197. deviceExtension->CurrentOutput.State = Idle;
  198. KeInsertQueueDpc(
  199. &deviceExtension->RetriesExceededDpc,
  200. DeviceObject->CurrentIrp,
  201. NULL
  202. );
  203. }
  204. break;
  205. //
  206. // The keyboard controller has acknowledged a previous send.
  207. // If there are more bytes to send for the current packet, initiate
  208. // the next send operation. Otherwise, queue the completion DPC.
  209. //
  210. case ACKNOWLEDGE:
  211. IsrPrint(DBG_KBISR_STATE, (": ACK, "));
  212. //
  213. // If the timer count is zero, don't process the interrupt
  214. // further. The timeout routine will complete this request.
  215. //
  216. if (Globals.ControllerData->TimerCount == 0) {
  217. break;
  218. }
  219. //
  220. // We cannot clear the E0 or E1 bits b/c then the subsequent scan
  221. // code will be misinterpreted. ie, the OS should have seen 0x2d
  222. // with an extended bit, but instead it saw a plain 0x2d
  223. //
  224. // If the keyboard is using 0xE0 0x7A / 0xE0 0xFA as a make / break
  225. // code, then tough luck...bad choice, we do not support it.
  226. //
  227. #if 0
  228. //
  229. // If the E0 or E1 is set, that means that this keyboard's
  230. // manufacturer made a poor choice for a scan code, 0x7A, whose
  231. // break code is 0xFA. Thankfully, they used the E0 or E1 prefix
  232. // so we can tell the difference.
  233. //
  234. if (deviceExtension->CurrentInput.Flags & (KEY_E0 | KEY_E1)) {
  235. //
  236. // The following sequence can occur which requires the driver to
  237. // ignore the spurious keystroke
  238. //
  239. // 1 write set typematic to the device (0xF3)
  240. // 2 device responds with an ACK, ISR sees 0xFA
  241. // 3 write typematic value to the device (0x??)
  242. // 4 user hits an extended key (left arrow for instance), ISR sees 0xE0
  243. // 5 device response with an ACK to the typematic value, ISR sees 0xFA
  244. // before the actual scancode for the left arrow is sent to the ISR
  245. //
  246. //
  247. // Make sure we are trully not writing out data to the device
  248. //
  249. if (Globals.ControllerData->TimerCount == I8042_ASYNC_NO_TIMEOUT &&
  250. deviceExtension->CurrentOutput.State == Idle) {
  251. IsrPrint(DBG_KBISR_INFO,
  252. ("BAD KEYBOARD: 0xFA used as a real scancode!\n"));
  253. goto ScanCodeCase;
  254. }
  255. else {
  256. //
  257. // Spurious keystroke case.
  258. //
  259. // Clear the E0 / E1 flag. the 2nd byte of the scan code will
  260. // never come through b/c it was preempted by the ACK for the
  261. // write to the device
  262. //
  263. deviceExtension->CurrentInput.Flags &= ~(KEY_E0 | KEY_E1);
  264. }
  265. }
  266. #endif
  267. //
  268. // Reset the timeout value to indicate no timeout.
  269. //
  270. Globals.ControllerData->TimerCount = I8042_ASYNC_NO_TIMEOUT;
  271. //
  272. // Reset resend count.
  273. //
  274. deviceExtension->ResendCount = 0;
  275. //
  276. // Make sure we are writing to the device if we are going to write
  277. // another byte or queue a DPC
  278. //
  279. if (deviceExtension->CurrentOutput.State == SendingBytes) {
  280. if (deviceExtension->CurrentOutput.CurrentByte <
  281. deviceExtension->CurrentOutput.ByteCount) {
  282. //
  283. // We've successfully sent the first byte of a 2-byte (or more)
  284. // command sequence. Initiate a send of the second byte.
  285. //
  286. IsrPrint(DBG_KBISR_STATE,
  287. ("now initiate send of byte #%d\n",
  288. deviceExtension->CurrentOutput.CurrentByte
  289. ));
  290. I8xInitiateIo(DeviceObject);
  291. }
  292. else {
  293. //
  294. // We've successfully sent all bytes in the command sequence.
  295. // Reset the current state and queue the completion DPC.
  296. //
  297. IsrPrint(DBG_KBISR_STATE,
  298. ("all bytes have been sent\n"
  299. ));
  300. deviceExtension->CurrentOutput.State = Idle;
  301. ASSERT(DeviceObject->CurrentIrp != NULL);
  302. IoRequestDpc(
  303. DeviceObject,
  304. DeviceObject->CurrentIrp,
  305. IntToPtr(IsrDpcCauseKeyboardWriteComplete)
  306. );
  307. }
  308. }
  309. break;
  310. //
  311. // Assume we've got a real, live scan code (or perhaps a keyboard
  312. // overrun code, which we treat like a scan code). I.e., a key
  313. // has been pressed or released. Queue the ISR DPC to process
  314. // a complete scan code sequence.
  315. //
  316. ScanCodeCase:
  317. default:
  318. IsrPrint(DBG_KBISR_SCODE, ("real scan code\n"));
  319. //
  320. // Differentiate between an extended key sequence (first
  321. // byte is E0, followed by a normal make or break byte), or
  322. // a normal make code (one byte, the high bit is NOT set),
  323. // or a normal break code (one byte, same as the make code
  324. // but the high bit is set), or the key #126 byte sequence
  325. // (requires special handling -- sequence is E11D459DC5).
  326. //
  327. // If there is a key detection error/overrun, the keyboard
  328. // sends an overrun indicator (0xFF in scan code set 1).
  329. // Map it to the overrun indicator expected by the Windows
  330. // USER Raw Input Thread.
  331. //
  332. input = &deviceExtension->CurrentInput;
  333. scanState = &deviceExtension->CurrentScanState;
  334. if (scanCode == (UCHAR) 0xFF) {
  335. IsrPrint(DBG_KBISR_ERROR, ("OVERRUN\n"));
  336. input->MakeCode = KEYBOARD_OVERRUN_MAKE_CODE;
  337. input->Flags = 0;
  338. *scanState = Normal;
  339. } else {
  340. switch (*scanState) {
  341. case Normal:
  342. if (scanCode == (UCHAR) 0xE0) {
  343. input->Flags |= KEY_E0;
  344. *scanState = GotE0;
  345. IsrPrint(DBG_KBISR_STATE, ("change state to GotE0\n"));
  346. break;
  347. } else if (scanCode == (UCHAR) 0xE1) {
  348. input->Flags |= KEY_E1;
  349. *scanState = GotE1;
  350. IsrPrint(DBG_KBISR_STATE, ("change state to GotE1\n"));
  351. break;
  352. }
  353. //
  354. // Fall through to the GotE0/GotE1 case for the rest of the
  355. // Normal case.
  356. //
  357. case GotE0:
  358. case GotE1:
  359. if (deviceExtension->CrashFlags != 0x0) {
  360. I8xProcessCrashDump(deviceExtension,
  361. scanCode,
  362. *scanState);
  363. }
  364. if (IS_BREAK_CODE(scanCode)) {
  365. SYS_BUTTON_ACTION action;
  366. //
  367. // Got a break code. Strip the high bit off
  368. // to get the associated make code and set flags
  369. // to indicate a break code.
  370. //
  371. IsrPrint(DBG_KBISR_SCODE, ("BREAK code\n"));
  372. input->MakeCode = GET_MAKE_CODE(scanCode);
  373. input->Flags |= KEY_BREAK;
  374. if (input->Flags & KEY_E0) {
  375. switch (input->MakeCode) {
  376. case KEYBOARD_POWER_CODE:
  377. if (deviceExtension->PowerCaps &
  378. I8042_POWER_SYS_BUTTON) {
  379. IsrPrint(DBG_KBISR_POWER, ("Send Power Button\n"));
  380. action = SendAction;
  381. }
  382. else {
  383. IsrPrint(DBG_KBISR_POWER, ("Update Power Button\n"));
  384. action = UpdateAction;
  385. }
  386. break;
  387. case KEYBOARD_SLEEP_CODE:
  388. if (deviceExtension->PowerCaps &
  389. I8042_SLEEP_SYS_BUTTON) {
  390. IsrPrint(DBG_KBISR_POWER, ("Send Sleep Button\n"));
  391. action = SendAction;
  392. }
  393. else {
  394. IsrPrint(DBG_KBISR_POWER, ("Update Sleep Button\n"));
  395. action = UpdateAction;
  396. }
  397. break;
  398. case KEYBOARD_WAKE_CODE:
  399. if (deviceExtension->PowerCaps &
  400. I8042_WAKE_SYS_BUTTON) {
  401. IsrPrint(DBG_KBISR_POWER, ("Send Wake Button\n"));
  402. action = SendAction;
  403. }
  404. else {
  405. IsrPrint(DBG_KBISR_POWER, ("Update Wake Button\n"));
  406. action = UpdateAction;
  407. }
  408. break;
  409. default:
  410. action = NoAction;
  411. break;
  412. }
  413. if (action != NoAction) {
  414. //
  415. // Queue a DPC so that we can do the appropriate
  416. // action
  417. //
  418. KeInsertQueueDpc(
  419. &deviceExtension->SysButtonEventDpc,
  420. (PVOID) action,
  421. (PVOID) input->MakeCode
  422. );
  423. }
  424. }
  425. } else {
  426. //
  427. // Got a make code.
  428. //
  429. IsrPrint(DBG_KBISR_SCODE, ("MAKE code\n"));
  430. input->MakeCode = scanCode;
  431. //
  432. // If the input scan code is debug stop, then drop
  433. // into the kernel debugger if it is active.
  434. //
  435. if ((KD_DEBUGGER_NOT_PRESENT == FALSE) && !(input->Flags & KEY_BREAK)) {
  436. if (ENHANCED_KEYBOARD(
  437. deviceExtension->KeyboardAttributes.KeyboardIdentifier
  438. )) {
  439. //
  440. // Enhanced 101 keyboard, SysReq key is 0xE0 0x37.
  441. //
  442. if ((input->MakeCode == KEYBOARD_DEBUG_HOTKEY_ENH) &&
  443. (input->Flags & KEY_E0)) {
  444. try {
  445. if ((KD_DEBUGGER_ENABLED != FALSE) &&
  446. Globals.BreakOnSysRq) {
  447. DbgBreakPointWithStatus(DBG_STATUS_SYSRQ);
  448. }
  449. } except(EXCEPTION_EXECUTE_HANDLER) {
  450. }
  451. }
  452. //
  453. // 84-key AT keyboard, SysReq key is 0xE0 0x54.
  454. //
  455. } else if ((input->MakeCode == KEYBOARD_DEBUG_HOTKEY_AT)) {
  456. try {
  457. if ((KD_DEBUGGER_ENABLED != FALSE)
  458. && Globals.BreakOnSysRq) {
  459. DbgBreakPointWithStatus(DBG_STATUS_SYSRQ);
  460. }
  461. } except(EXCEPTION_EXECUTE_HANDLER) {
  462. }
  463. }
  464. }
  465. }
  466. //
  467. // Reset the state to Normal.
  468. //
  469. *scanState = Normal;
  470. break;
  471. default:
  472. //
  473. // Queue a DPC to log an internal driver error.
  474. //
  475. KeInsertQueueDpc(
  476. &deviceExtension->ErrorLogDpc,
  477. (PIRP) NULL,
  478. LongToPtr(I8042_INVALID_ISR_STATE_KBD)
  479. );
  480. ASSERT(FALSE);
  481. break;
  482. }
  483. }
  484. //
  485. // In the Normal state, if the keyboard device is enabled,
  486. // add the data to the InputData queue and queue the ISR DPC.
  487. //
  488. if (*scanState == Normal) {
  489. I8xQueueCurrentKeyboardInput(DeviceObject);
  490. }
  491. break;
  492. }
  493. IsrPrint(DBG_KBISR_TRACE, ("exit\n"));
  494. return TRUE;
  495. }
  496. VOID
  497. I8xProcessCrashDump(
  498. PPORT_KEYBOARD_EXTENSION DeviceExtension,
  499. UCHAR ScanCode,
  500. KEYBOARD_SCAN_STATE ScanState
  501. )
  502. {
  503. LONG crashFlags;
  504. BOOLEAN processFlags;
  505. UCHAR crashScanCode, crashScanCode2;
  506. crashFlags = DeviceExtension->CrashFlags;
  507. crashScanCode = DeviceExtension->CrashScanCode;
  508. crashScanCode2 = DeviceExtension->CrashScanCode2;
  509. if (IS_MAKE_CODE(ScanCode)) {
  510. //
  511. // make code
  512. //
  513. // If it is one of the crash flag keys record it.
  514. // If it is a crash dump key record it
  515. // If it is neither, reset the current tracking state (CurrentCrashFlags)
  516. //
  517. switch (ScanCode) {
  518. case CTRL_SCANCODE:
  519. if (ScanState == Normal) { // Left
  520. DeviceExtension->CurrentCrashFlags |= CRASH_L_CTRL;
  521. }
  522. else if (ScanState == GotE0) { // Right
  523. DeviceExtension->CurrentCrashFlags |= CRASH_R_CTRL;
  524. }
  525. break;
  526. case ALT_SCANCODE:
  527. if (ScanState == Normal) { // Left
  528. DeviceExtension->CurrentCrashFlags |= CRASH_L_ALT;
  529. }
  530. else if (ScanState == GotE0) { // Right
  531. DeviceExtension->CurrentCrashFlags |= CRASH_R_ALT;
  532. }
  533. break;
  534. case LEFT_SHIFT_SCANCODE:
  535. if (ScanState == Normal) {
  536. DeviceExtension->CurrentCrashFlags |= CRASH_L_SHIFT;
  537. }
  538. break;
  539. case RIGHT_SHIFT_SCANCODE:
  540. if (ScanState == Normal) {
  541. DeviceExtension->CurrentCrashFlags |= CRASH_R_SHIFT;
  542. }
  543. break;
  544. default:
  545. if (IS_MAKE_CODE(crashScanCode)) {
  546. if (ScanState == Normal && crashScanCode == ScanCode) {
  547. break;
  548. }
  549. }
  550. else {
  551. if (ScanState == GotE0 && GET_MAKE_CODE(crashScanCode) == ScanCode) {
  552. break;
  553. }
  554. }
  555. if (IS_MAKE_CODE(crashScanCode2)) {
  556. if (ScanState == Normal &&
  557. crashScanCode2 == ScanCode) {
  558. break;
  559. }
  560. }
  561. else {
  562. if (ScanState == GotE0 &&
  563. GET_MAKE_CODE(crashScanCode2) == ScanCode) {
  564. break;
  565. }
  566. }
  567. //
  568. // Not a key we are interested in, reset our current state
  569. //
  570. DeviceExtension->CurrentCrashFlags = 0x0;
  571. break;
  572. }
  573. }
  574. else {
  575. //
  576. // break code
  577. //
  578. // If one of the modifer keys is released, our state is reset and all
  579. // keys have to be pressed again.
  580. // If it is a non modifier key, proceed with the processing if it is the
  581. // crash dump key, otherwise reset our tracking state
  582. //
  583. switch (GET_MAKE_CODE(ScanCode)) {
  584. case CTRL_SCANCODE:
  585. if (ScanState == Normal) { // Left
  586. DeviceExtension->CurrentCrashFlags &=
  587. ~(CRASH_BOTH_TIMES | CRASH_L_CTRL);
  588. }
  589. else if (ScanState == GotE0) { // Right
  590. DeviceExtension->CurrentCrashFlags &=
  591. ~(CRASH_BOTH_TIMES | CRASH_R_CTRL);
  592. }
  593. break;
  594. case ALT_SCANCODE:
  595. if (ScanState == Normal) { // Left
  596. DeviceExtension->CurrentCrashFlags &=
  597. ~(CRASH_BOTH_TIMES | CRASH_L_ALT);
  598. }
  599. else if (ScanState == GotE0) { // Right
  600. DeviceExtension->CurrentCrashFlags &=
  601. ~(CRASH_BOTH_TIMES | CRASH_R_ALT);
  602. }
  603. break;
  604. case RIGHT_SHIFT_SCANCODE:
  605. if (ScanState == Normal) {
  606. DeviceExtension->CurrentCrashFlags &=
  607. ~(CRASH_BOTH_TIMES | CRASH_R_SHIFT);
  608. }
  609. break;
  610. case LEFT_SHIFT_SCANCODE:
  611. if (ScanState == Normal) {
  612. DeviceExtension->CurrentCrashFlags &=
  613. ~(CRASH_BOTH_TIMES | CRASH_L_SHIFT);
  614. }
  615. break;
  616. default:
  617. processFlags = FALSE;
  618. if (IS_MAKE_CODE(crashScanCode)) {
  619. if (ScanState == Normal && crashScanCode == GET_MAKE_CODE(ScanCode))
  620. processFlags = TRUE;
  621. }
  622. else {
  623. if (ScanState == GotE0 && crashScanCode == ScanCode) {
  624. processFlags = TRUE;
  625. }
  626. }
  627. if (IS_MAKE_CODE(crashScanCode2)) {
  628. if (ScanState == Normal && crashScanCode2 == GET_MAKE_CODE(ScanCode)) {
  629. processFlags = TRUE;
  630. }
  631. }
  632. else {
  633. if (ScanState == GotE0 && crashScanCode2 == ScanCode)
  634. processFlags = TRUE;
  635. }
  636. //
  637. // If this is the key we are interested in, continue, otherwise
  638. // our tracking state is reset
  639. //
  640. if (processFlags) {
  641. //
  642. // test to see if all the needed modifier
  643. // keys are down
  644. //
  645. if (crashFlags != (DeviceExtension->CurrentCrashFlags & crashFlags)) {
  646. break;
  647. }
  648. //
  649. // record how many times we have seen
  650. // this key
  651. //
  652. if (DeviceExtension->CurrentCrashFlags & CRASH_FIRST_TIME) {
  653. DeviceExtension->CurrentCrashFlags |= CRASH_SECOND_TIME;
  654. }
  655. else {
  656. DeviceExtension->CurrentCrashFlags |= CRASH_FIRST_TIME;
  657. }
  658. break;
  659. }
  660. DeviceExtension->CurrentCrashFlags = 0x0;
  661. break;
  662. }
  663. }
  664. crashFlags |= CRASH_BOTH_TIMES;
  665. if (DeviceExtension->CurrentCrashFlags == crashFlags) {
  666. DeviceExtension->CurrentCrashFlags = 0x0;
  667. //
  668. // Bring down the system in a somewhat controlled manner
  669. //
  670. KeBugCheckEx(MANUALLY_INITIATED_CRASH, 0, 0, 0, 0);
  671. }
  672. }
  673. //
  674. // The following table is used to convert typematic rate (keys per
  675. // second) into the value expected by the keyboard. The index into the
  676. // array is the number of keys per second. The resulting value is
  677. // the bit equate to send to the keyboard.
  678. //
  679. UCHAR
  680. I8xConvertTypematicParameters(
  681. IN USHORT Rate,
  682. IN USHORT Delay
  683. )
  684. /*++
  685. Routine Description:
  686. This routine converts the typematic rate and delay to the form the
  687. keyboard expects.
  688. The byte passed to the keyboard looks like this:
  689. - bit 7 is zero
  690. - bits 5 and 6 indicate the delay
  691. - bits 0-4 indicate the rate
  692. The delay is equal to 1 plus the binary value of bits 6 and 5,
  693. multiplied by 250 milliseconds.
  694. The period (interval from one typematic output to the next) is
  695. determined by the following equation:
  696. Period = (8 + A) x (2^B) x 0.00417 seconds
  697. where
  698. A = binary value of bits 0-2
  699. B = binary value of bits 3 and 4
  700. Arguments:
  701. Rate - Number of keys per second.
  702. Delay - Number of milliseconds to delay before the key repeat starts.
  703. Return Value:
  704. The byte to pass to the keyboard.
  705. --*/
  706. {
  707. UCHAR value;
  708. UCHAR TypematicPeriod[] = {
  709. 31, // 0 keys per second
  710. 31, // 1 keys per second
  711. 28, // 2 keys per second, This is really 2.5, needed for NEXUS.
  712. 26, // 3 keys per second
  713. 23, // 4 keys per second
  714. 20, // 5 keys per second
  715. 18, // 6 keys per second
  716. 17, // 7 keys per second
  717. 15, // 8 keys per second
  718. 13, // 9 keys per second
  719. 12, // 10 keys per second
  720. 11, // 11 keys per second
  721. 10, // 12 keys per second
  722. 9, // 13 keys per second
  723. 9, // 14 keys per second
  724. 8, // 15 keys per second
  725. 7, // 16 keys per second
  726. 6, // 17 keys per second
  727. 5, // 18 keys per second
  728. 4, // 19 keys per second
  729. 4, // 20 keys per second
  730. 3, // 21 keys per second
  731. 3, // 22 keys per second
  732. 2, // 23 keys per second
  733. 2, // 24 keys per second
  734. 1, // 25 keys per second
  735. 1, // 26 keys per second
  736. 1 // 27 keys per second
  737. // > 27 keys per second, use 0
  738. };
  739. Print(DBG_CALL_TRACE, ("I8xConvertTypematicParameters: enter\n"));
  740. //
  741. // Calculate the delay bits.
  742. //
  743. value = (UCHAR) ((Delay / 250) - 1);
  744. //
  745. // Put delay bits in the right place.
  746. //
  747. value <<= 5;
  748. //
  749. // Get the typematic period from the table. If keys per second
  750. // is > 27, the typematic period value is zero.
  751. //
  752. if (Rate <= 27) {
  753. value |= TypematicPeriod[Rate];
  754. }
  755. Print(DBG_CALL_TRACE, ("I8xConvertTypematicParameters: exit\n"));
  756. return(value);
  757. }
  758. #define KB_INIT_FAILED_RESET 0x00000001
  759. #define KB_INIT_FAILED_XLATE_OFF 0x00000010
  760. #define KB_INIT_FAILED_XLATE_ON 0x00000020
  761. #define KB_INIT_FAILED_SET_TYPEMATIC 0x00000100
  762. #define KB_INIT_FAILED_SET_TYPEMATIC_PARAM 0x00000200
  763. #define KB_INIT_FAILED_SET_LEDS 0x00001000
  764. #define KB_INIT_FAILED_SET_LEDS_PARAM 0x00002000
  765. #define KB_INIT_FAILED_SELECT_SS 0x00010000
  766. #define KB_INIT_FAILED_SELECT_SS_PARAM 0x00020000
  767. #if KEYBOARD_RECORD_INIT
  768. ULONG KeyboardInitStatus;
  769. #define SET_KB_INIT_FAILURE(flag) KeyboardInitStatus |= flag
  770. #define KB_INIT_START() KeyboardInitStatus = 0x0;
  771. #else
  772. #define SET_KB_INIT_FAILURE(flag)
  773. #define KB_INIT_START()
  774. #endif // KEYBOARD_RECORD_INIT
  775. NTSTATUS
  776. I8xInitializeKeyboard(
  777. IN PPORT_KEYBOARD_EXTENSION KeyboardExtension
  778. )
  779. /*++
  780. Routine Description:
  781. This routine initializes the i8042 keyboard hardware. It is called
  782. only at initialization, and does not synchronize access to the hardware.
  783. Arguments:
  784. DeviceObject - Pointer to the device object.
  785. Return Value:
  786. Returns status.
  787. --*/
  788. {
  789. NTSTATUS status;
  790. PKEYBOARD_ID id;
  791. PPORT_KEYBOARD_EXTENSION deviceExtension;
  792. PDEVICE_OBJECT deviceObject;
  793. UCHAR byte,
  794. failedResetResponseByte,
  795. failedResetResponseByte2;
  796. I8042_TRANSMIT_CCB_CONTEXT transmitCCBContext;
  797. ULONG i;
  798. ULONG limit;
  799. NTSTATUS failedLedsStatus,
  800. failedTypematicStatus,
  801. failedResetStatus,
  802. failedResetResponseStatus,
  803. failedResetResponseStatus2;
  804. PI8042_CONFIGURATION_INFORMATION configuration;
  805. PKEYBOARD_ID keyboardId;
  806. LARGE_INTEGER startOfSpin,
  807. nextQuery,
  808. difference,
  809. resetRespTimeout,
  810. li;
  811. BOOLEAN waitForAckOnReset = WAIT_FOR_ACKNOWLEDGE,
  812. translationOn = TRUE,
  813. failedReset = FALSE,
  814. failedResetResponse = FALSE,
  815. failedResetResponse2 = FALSE,
  816. failedTypematic = FALSE,
  817. failedLeds = FALSE;
  818. #define DUMP_COUNT 4
  819. ULONG dumpData[DUMP_COUNT];
  820. PAGED_CODE();
  821. KB_INIT_START();
  822. Print(DBG_SS_TRACE, ("I8xInitializeKeyboard, enter\n"));
  823. for (i = 0; i < DUMP_COUNT; i++)
  824. dumpData[i] = 0;
  825. //
  826. // Get the device extension.
  827. //
  828. deviceExtension = KeyboardExtension;
  829. deviceObject = deviceExtension->Self;
  830. //
  831. // Reset the keyboard.
  832. //
  833. StartOfReset:
  834. status = I8xPutBytePolled(
  835. (CCHAR) DataPort,
  836. waitForAckOnReset,
  837. (CCHAR) KeyboardDeviceType,
  838. (UCHAR) KEYBOARD_RESET
  839. );
  840. if (!NT_SUCCESS(status)) {
  841. SET_KB_INIT_FAILURE(KB_INIT_FAILED_RESET);
  842. failedReset = TRUE;
  843. failedResetStatus = status;
  844. if (KeyboardExtension->FailedReset == FAILED_RESET_STOP) {
  845. //
  846. // If the device was reported, but not responding, it is phantom
  847. //
  848. status = STATUS_DEVICE_NOT_CONNECTED;
  849. SET_HW_FLAGS(PHANTOM_KEYBOARD_HARDWARE_REPORTED);
  850. Print(DBG_SS_INFO,
  851. ("kb failed reset Reset failed, stopping immediately\n"));
  852. goto I8xInitializeKeyboardExit;
  853. }
  854. else {
  855. //
  856. // NOTE: The Gateway 4DX2/66V has a problem when an old Compaq 286
  857. // keyboard is attached. In this case, the keyboard reset
  858. // is not acknowledged (at least, the system never
  859. // receives the ack). Instead, the KEYBOARD_COMPLETE_SUCCESS
  860. // byte is sitting in the i8042 output buffer. The fix
  861. // is to ignore the keyboard reset failure and continue.
  862. //
  863. /* do nothing */;
  864. Print(DBG_SS_INFO, ("kb failed reset, proceeding\n"));
  865. }
  866. }
  867. //
  868. // Get the keyboard reset self-test response. A response byte of
  869. // KEYBOARD_COMPLETE_SUCCESS indicates success; KEYBOARD_COMPLETE_FAILURE
  870. // indicates failure.
  871. //
  872. // Note that it is usually necessary to stall a long time to get the
  873. // keyboard reset/self-test to work.
  874. //
  875. li.QuadPart = -100;
  876. resetRespTimeout.QuadPart = 50*10*1000*1000;
  877. KeQueryTickCount(&startOfSpin);
  878. while (TRUE) {
  879. status = I8xGetBytePolled(
  880. (CCHAR) KeyboardDeviceType,
  881. &byte
  882. );
  883. if (NT_SUCCESS(status)) {
  884. if (byte == (UCHAR) KEYBOARD_COMPLETE_SUCCESS) {
  885. //
  886. // The reset completed successfully.
  887. //
  888. break;
  889. }
  890. else {
  891. //
  892. // There was some sort of failure during the reset
  893. // self-test. Continue anyway.
  894. //
  895. failedResetResponse = TRUE;
  896. failedResetResponseStatus = status;
  897. failedResetResponseByte = byte;
  898. break;
  899. }
  900. }
  901. else {
  902. if (status == STATUS_IO_TIMEOUT) {
  903. //
  904. // Stall, and then try again to get a response from
  905. // the reset.
  906. //
  907. KeDelayExecutionThread(KernelMode,
  908. FALSE,
  909. &li);
  910. KeQueryTickCount(&nextQuery);
  911. difference.QuadPart = nextQuery.QuadPart - startOfSpin.QuadPart;
  912. ASSERT(KeQueryTimeIncrement() <= MAXLONG);
  913. if (difference.QuadPart*KeQueryTimeIncrement() >=
  914. resetRespTimeout.QuadPart) {
  915. Print(DBG_SS_ERROR, ("no reset response, quitting\n"));
  916. break;
  917. }
  918. }
  919. else {
  920. break;
  921. }
  922. }
  923. }
  924. if (!NT_SUCCESS(status)) {
  925. if (waitForAckOnReset == WAIT_FOR_ACKNOWLEDGE) {
  926. waitForAckOnReset = NO_WAIT_FOR_ACKNOWLEDGE;
  927. goto StartOfReset;
  928. }
  929. failedResetResponse2 = TRUE;
  930. failedResetResponseStatus2 = status;
  931. failedResetResponseByte2 = byte;
  932. goto I8xInitializeKeyboardExit;
  933. }
  934. //
  935. // Turn off Keyboard Translate Mode. Call I8xTransmitControllerCommand
  936. // to read the Controller Command Byte, modify the appropriate bits, and
  937. // rewrite the Controller Command Byte.
  938. //
  939. transmitCCBContext.HardwareDisableEnableMask = 0;
  940. transmitCCBContext.AndOperation = AND_OPERATION;
  941. transmitCCBContext.ByteMask = (UCHAR) ~((UCHAR)CCB_KEYBOARD_TRANSLATE_MODE);
  942. I8xTransmitControllerCommand(
  943. (PVOID) &transmitCCBContext
  944. );
  945. if (!NT_SUCCESS(transmitCCBContext.Status)) {
  946. //
  947. // If failure then retry once. This is for Toshiba T3400CT.
  948. //
  949. I8xTransmitControllerCommand(
  950. (PVOID) &transmitCCBContext
  951. );
  952. }
  953. if (!NT_SUCCESS(transmitCCBContext.Status)) {
  954. Print(DBG_SS_ERROR,
  955. ("I8xInitializeKeyboard: could not turn off translate\n"
  956. ));
  957. status = transmitCCBContext.Status;
  958. SET_KB_INIT_FAILURE(KB_INIT_FAILED_XLATE_OFF);
  959. goto I8xInitializeKeyboardExit;
  960. }
  961. //
  962. // Get a pointer to the keyboard identifier field.
  963. //
  964. id = &deviceExtension->KeyboardAttributes.KeyboardIdentifier;
  965. //
  966. // Set the typematic rate and delay. Send the Set Typematic Rate command
  967. // to the keyboard, followed by the typematic rate/delay parameter byte.
  968. // Note that it is often necessary to stall a long time to get this
  969. // to work. The stall value was determined by experimentation. Some
  970. // broken hardware does not accept this command, so ignore errors in the
  971. // hope that the keyboard will work okay anyway.
  972. //
  973. //
  974. if ((status = I8xPutBytePolled(
  975. (CCHAR) DataPort,
  976. WAIT_FOR_ACKNOWLEDGE,
  977. (CCHAR) KeyboardDeviceType,
  978. (UCHAR) SET_KEYBOARD_TYPEMATIC
  979. )) != STATUS_SUCCESS) {
  980. Print(DBG_SS_INFO, ("kb set typematic failed\n"));
  981. SET_KB_INIT_FAILURE(KB_INIT_FAILED_SET_TYPEMATIC);
  982. failedTypematic = TRUE;
  983. failedTypematicStatus = status;
  984. } else if ((status = I8xPutBytePolled(
  985. (CCHAR) DataPort,
  986. WAIT_FOR_ACKNOWLEDGE,
  987. (CCHAR) KeyboardDeviceType,
  988. I8xConvertTypematicParameters(
  989. deviceExtension->KeyRepeatCurrent.Rate,
  990. deviceExtension->KeyRepeatCurrent.Delay
  991. ))) != STATUS_SUCCESS) {
  992. SET_KB_INIT_FAILURE(KB_INIT_FAILED_SET_TYPEMATIC_PARAM);
  993. Print(DBG_SS_ERROR,
  994. ("I8xInitializeKeyboard: could not send typematic param\n"
  995. ));
  996. //
  997. // Log an error.
  998. //
  999. dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
  1000. dumpData[1] = DataPort;
  1001. dumpData[2] = SET_KEYBOARD_TYPEMATIC;
  1002. dumpData[3] =
  1003. I8xConvertTypematicParameters(
  1004. deviceExtension->KeyRepeatCurrent.Rate,
  1005. deviceExtension->KeyRepeatCurrent.Delay
  1006. );
  1007. I8xLogError(
  1008. deviceObject,
  1009. I8042_SET_TYPEMATIC_FAILED,
  1010. I8042_ERROR_VALUE_BASE + 540,
  1011. status,
  1012. dumpData,
  1013. 4
  1014. );
  1015. }
  1016. status = STATUS_SUCCESS;
  1017. //
  1018. // Set the keyboard indicator lights. Ignore errors.
  1019. //
  1020. if ((status = I8xPutBytePolled(
  1021. (CCHAR) DataPort,
  1022. WAIT_FOR_ACKNOWLEDGE,
  1023. (CCHAR) KeyboardDeviceType,
  1024. (UCHAR) SET_KEYBOARD_INDICATORS
  1025. )) != STATUS_SUCCESS) {
  1026. Print(DBG_SS_INFO, ("kb set LEDs failed\n"));
  1027. SET_KB_INIT_FAILURE(KB_INIT_FAILED_SET_LEDS);
  1028. failedLeds = TRUE;
  1029. failedLedsStatus = status;
  1030. } else if ((status = I8xPutBytePolled(
  1031. (CCHAR) DataPort,
  1032. WAIT_FOR_ACKNOWLEDGE,
  1033. (CCHAR) KeyboardDeviceType,
  1034. (UCHAR) deviceExtension->KeyboardIndicators.LedFlags
  1035. )) != STATUS_SUCCESS) {
  1036. SET_KB_INIT_FAILURE(KB_INIT_FAILED_SET_LEDS_PARAM);
  1037. Print(DBG_SS_ERROR,
  1038. ("I8xInitializeKeyboard: could not send SET LEDS param\n"
  1039. ));
  1040. //
  1041. // Log an error.
  1042. //
  1043. dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
  1044. dumpData[1] = DataPort;
  1045. dumpData[2] = SET_KEYBOARD_INDICATORS;
  1046. dumpData[3] =
  1047. deviceExtension->KeyboardIndicators.LedFlags;
  1048. I8xLogError(
  1049. deviceObject,
  1050. I8042_SET_LED_FAILED,
  1051. I8042_ERROR_VALUE_BASE + 550,
  1052. status,
  1053. dumpData,
  1054. 4
  1055. );
  1056. }
  1057. status = STATUS_SUCCESS;
  1058. #if !(defined(_X86_) || defined(_IA64_) || defined(_PPC_)) // IBMCPK: MIPS specific initialization
  1059. //
  1060. // NOTE: This code is necessary until the MIPS firmware stops
  1061. // selecting scan code set 3. Select scan code set 2 here.
  1062. // Since the translate bit is set, the net effect is that
  1063. // we will receive scan code set 1 bytes.
  1064. //
  1065. if (ENHANCED_KEYBOARD(*id)) {
  1066. status = I8xPutBytePolled(
  1067. (CCHAR) DataPort,
  1068. WAIT_FOR_ACKNOWLEDGE,
  1069. (CCHAR) KeyboardDeviceType,
  1070. (UCHAR) SELECT_SCAN_CODE_SET
  1071. );
  1072. if (NT_SUCCESS(status)) {
  1073. //
  1074. // Send the associated parameter byte.
  1075. //
  1076. status = I8xPutBytePolled(
  1077. (CCHAR) DataPort,
  1078. WAIT_FOR_ACKNOWLEDGE,
  1079. (CCHAR) KeyboardDeviceType,
  1080. (UCHAR) 2
  1081. );
  1082. }
  1083. if (!NT_SUCCESS(status)) {
  1084. Print(DBG_SS_ERROR,
  1085. ("I8xInitializeKeyboard: could not send Select Scan command\n"
  1086. ));
  1087. //
  1088. // This failed so probably what we have here isn't an enhanced
  1089. // keyboard at all. Make this an old style keyboard.
  1090. //
  1091. configuration = &Globals.ControllerData->Configuration;
  1092. keyboardId = &deviceExtension->KeyboardAttributes.KeyboardIdentifier;
  1093. keyboardId->Type = 3;
  1094. deviceExtension->KeyboardAttributes.NumberOfFunctionKeys =
  1095. KeyboardTypeInformation[keyboardId->Type - 1].NumberOfFunctionKeys;
  1096. deviceExtension->KeyboardAttributes.NumberOfIndicators =
  1097. KeyboardTypeInformation[keyboardId->Type - 1].NumberOfIndicators;
  1098. deviceExtension->KeyboardAttributes.NumberOfKeysTotal =
  1099. KeyboardTypeInformation[keyboardId->Type - 1].NumberOfKeysTotal;
  1100. status = STATUS_SUCCESS;
  1101. }
  1102. }
  1103. #endif
  1104. #if defined(FE_SB)
  1105. if (IBM02_KEYBOARD(*id)) {
  1106. //
  1107. // IBM-J 5576-002 Keyboard should set local scan code set for
  1108. // supplied NLS key.
  1109. //
  1110. status = I8xPutBytePolled(
  1111. (CCHAR) DataPort,
  1112. WAIT_FOR_ACKNOWLEDGE,
  1113. (CCHAR) KeyboardDeviceType,
  1114. (UCHAR) SELECT_SCAN_CODE_SET
  1115. );
  1116. if (status != STATUS_SUCCESS) {
  1117. Print(DBG_SS_ERROR,
  1118. ("I8xInitializeKeyboard: could not send Select Scan command\n"
  1119. ));
  1120. Print(DBG_SS_ERROR,
  1121. ("I8xInitializeKeyboard: WARNING - using scan set 82h\n"
  1122. ));
  1123. deviceExtension->KeyboardAttributes.KeyboardMode = 3;
  1124. } else {
  1125. //
  1126. // Send the associated parameter byte.
  1127. //
  1128. status = I8xPutBytePolled(
  1129. (CCHAR) DataPort,
  1130. WAIT_FOR_ACKNOWLEDGE,
  1131. (CCHAR) KeyboardDeviceType,
  1132. (UCHAR) 0x82
  1133. );
  1134. if (status != STATUS_SUCCESS) {
  1135. Print(DBG_SS_ERROR,
  1136. ("I8xInitializeKeyboard: could not send Select Scan param\n"
  1137. ));
  1138. Print(DBG_SS_ERROR,
  1139. ("I8xInitializeKeyboard: WARNING - using scan set 82h\n"
  1140. ));
  1141. deviceExtension->KeyboardAttributes.KeyboardMode = 3;
  1142. }
  1143. }
  1144. }
  1145. #endif // FE_SB
  1146. if (deviceExtension->InitializationHookCallback) {
  1147. (*deviceExtension->InitializationHookCallback) (
  1148. deviceExtension->HookContext,
  1149. (PVOID) deviceObject,
  1150. (PI8042_SYNCH_READ_PORT) I8xKeyboardSynchReadPort,
  1151. (PI8042_SYNCH_WRITE_PORT) I8xKeyboardSynchWritePort,
  1152. &translationOn
  1153. );
  1154. }
  1155. if (deviceExtension->KeyboardAttributes.KeyboardMode == 1 &&
  1156. translationOn) {
  1157. //
  1158. // Turn translate back on. The keyboard should, by default, send
  1159. // scan code set 2. When the translate bit in the 8042 command byte
  1160. // is on, the 8042 translates the scan code set 2 bytes to scan code
  1161. // set 1 before sending them to the CPU. Scan code set 1 is
  1162. // the industry standard scan code set.
  1163. //
  1164. // N.B. It does not appear to be possible to change the translate
  1165. // bit on some models of PS/2.
  1166. //
  1167. transmitCCBContext.HardwareDisableEnableMask = 0;
  1168. transmitCCBContext.AndOperation = OR_OPERATION;
  1169. transmitCCBContext.ByteMask = (UCHAR) CCB_KEYBOARD_TRANSLATE_MODE;
  1170. I8xTransmitControllerCommand(
  1171. (PVOID) &transmitCCBContext
  1172. );
  1173. if (!NT_SUCCESS(transmitCCBContext.Status)) {
  1174. SET_KB_INIT_FAILURE(KB_INIT_FAILED_XLATE_ON);
  1175. Print(DBG_SS_ERROR,
  1176. ("I8xInitializeKeyboard: couldn't turn on translate\n"
  1177. ));
  1178. if (transmitCCBContext.Status == STATUS_DEVICE_DATA_ERROR) {
  1179. //
  1180. // Could not turn translate back on. This happens on some
  1181. // PS/2 machines. In this case, select scan code set 1
  1182. // for the keyboard, since the 8042 will not do the
  1183. // translation from the scan code set 2, which is what the
  1184. // KEYBOARD_RESET caused the keyboard to default to.
  1185. //
  1186. if (ENHANCED_KEYBOARD(*id)) {
  1187. status = I8xPutBytePolled(
  1188. (CCHAR) DataPort,
  1189. WAIT_FOR_ACKNOWLEDGE,
  1190. (CCHAR) KeyboardDeviceType,
  1191. (UCHAR) SELECT_SCAN_CODE_SET
  1192. );
  1193. if (!NT_SUCCESS(status)) {
  1194. SET_KB_INIT_FAILURE(KB_INIT_FAILED_SELECT_SS);
  1195. Print(DBG_SS_ERROR,
  1196. ("I8xInitializeKeyboard: could not send Select Scan command\n"
  1197. ));
  1198. Print(DBG_SS_ERROR,
  1199. ("I8xInitializeKeyboard: WARNING - using scan set 2\n"
  1200. ));
  1201. deviceExtension->KeyboardAttributes.KeyboardMode = 2;
  1202. //
  1203. // Log an error.
  1204. //
  1205. dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
  1206. dumpData[1] = DataPort;
  1207. dumpData[2] = SELECT_SCAN_CODE_SET;
  1208. I8xLogError(
  1209. deviceObject,
  1210. I8042_SELECT_SCANSET_FAILED,
  1211. I8042_ERROR_VALUE_BASE + 555,
  1212. status,
  1213. dumpData,
  1214. 3
  1215. );
  1216. } else {
  1217. //
  1218. // Send the associated parameter byte.
  1219. //
  1220. status = I8xPutBytePolled(
  1221. (CCHAR) DataPort,
  1222. WAIT_FOR_ACKNOWLEDGE,
  1223. (CCHAR) KeyboardDeviceType,
  1224. #ifdef FE_SB // I8xInitializeKeyboard()
  1225. (UCHAR) (IBM02_KEYBOARD(*id) ? 0x81 : 1 )
  1226. #else
  1227. (UCHAR) 1
  1228. #endif // FE_SB
  1229. );
  1230. if (!NT_SUCCESS(status)) {
  1231. SET_KB_INIT_FAILURE(KB_INIT_FAILED_SELECT_SS_PARAM);
  1232. Print(DBG_SS_ERROR,
  1233. ("I8xInitializeKeyboard: could not send Select Scan param\n"
  1234. ));
  1235. Print(DBG_SS_ERROR,
  1236. ("I8xInitializeKeyboard: WARNING - using scan set 2\n"
  1237. ));
  1238. deviceExtension->KeyboardAttributes.KeyboardMode = 2;
  1239. //
  1240. // Log an error.
  1241. //
  1242. dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
  1243. dumpData[1] = DataPort;
  1244. dumpData[2] = SELECT_SCAN_CODE_SET;
  1245. dumpData[3] = 1;
  1246. I8xLogError(
  1247. deviceObject,
  1248. I8042_SELECT_SCANSET_FAILED,
  1249. I8042_ERROR_VALUE_BASE + 560,
  1250. status,
  1251. dumpData,
  1252. 4
  1253. );
  1254. }
  1255. }
  1256. }
  1257. } else {
  1258. status = transmitCCBContext.Status;
  1259. goto I8xInitializeKeyboardExit;
  1260. }
  1261. }
  1262. }
  1263. I8xInitializeKeyboardExit:
  1264. //
  1265. // If all 3 of these have failed, then we have a device that was reported
  1266. // present but is not plugged in. This usually happens on either an ACPI
  1267. // enabled machine (where it always reports the PS/2 kbd and mouse present)
  1268. // or on a machine which has legacy HID support (where the reported PS/2
  1269. // device(s) are really USB HID).
  1270. //
  1271. // If this is the case, then we will succeed the start and hide the device
  1272. // in the UI
  1273. //
  1274. if (failedReset && failedTypematic && failedLeds) {
  1275. if (KeyboardExtension->FailedReset == FAILED_RESET_PROCEED) {
  1276. OBJECT_ATTRIBUTES oa;
  1277. UNICODE_STRING string;
  1278. HANDLE hService, hParameters;
  1279. InitializeObjectAttributes(&oa,
  1280. &Globals.RegistryPath,
  1281. OBJ_CASE_INSENSITIVE,
  1282. NULL,
  1283. (PSECURITY_DESCRIPTOR) NULL);
  1284. if (NT_SUCCESS(ZwOpenKey(&hService, KEY_ALL_ACCESS, &oa))) {
  1285. RtlInitUnicodeString(&string, L"Parameters");
  1286. InitializeObjectAttributes(&oa,
  1287. &string,
  1288. OBJ_CASE_INSENSITIVE,
  1289. hService,
  1290. (PSECURITY_DESCRIPTOR) NULL);
  1291. if (NT_SUCCESS(ZwOpenKey(&hParameters, KEY_ALL_ACCESS, &oa))) {
  1292. ULONG tmp;
  1293. RtlInitUnicodeString (&string, STR_FAILED_RESET);
  1294. tmp = FAILED_RESET_STOP;
  1295. Print(DBG_SS_INFO | DBG_SS_ERROR,
  1296. ("Future failed kbd resets will stop init\n"));
  1297. ZwSetValueKey(hParameters,
  1298. &string,
  1299. 0,
  1300. REG_DWORD,
  1301. &tmp,
  1302. sizeof(tmp));
  1303. ZwClose(hParameters);
  1304. }
  1305. ZwClose(hService);
  1306. }
  1307. }
  1308. Print(DBG_SS_INFO,
  1309. ("kb, all 3 sets failed, assuming a phantom keyboard\n"));
  1310. status = STATUS_DEVICE_NOT_CONNECTED;
  1311. // errorCode = I8042_NO_KBD_DEVICE;
  1312. SET_HW_FLAGS(PHANTOM_KEYBOARD_HARDWARE_REPORTED);
  1313. if (Globals.ReportResetErrors) {
  1314. I8xLogError(deviceObject,
  1315. I8042_NO_KBD_DEVICE,
  1316. 0,
  1317. status,
  1318. NULL,
  1319. 0
  1320. );
  1321. }
  1322. }
  1323. else {
  1324. if (failedReset) {
  1325. Print(DBG_SS_ERROR,
  1326. ("I8xInitializeKeyboard: failed keyboard reset, status 0x%x\n",
  1327. status
  1328. ));
  1329. if (Globals.ReportResetErrors) {
  1330. dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
  1331. dumpData[1] = DataPort;
  1332. dumpData[2] = KEYBOARD_RESET;
  1333. I8xLogError(deviceObject,
  1334. I8042_KBD_RESET_COMMAND_FAILED,
  1335. I8042_ERROR_VALUE_BASE + 510,
  1336. failedResetStatus,
  1337. dumpData,
  1338. 3
  1339. );
  1340. }
  1341. }
  1342. if (failedResetResponse2) {
  1343. Print(DBG_SS_ERROR,
  1344. ("I8xInitializeKeyboard, failed reset response, status 0x%x, byte 0x%x\n",
  1345. status,
  1346. byte
  1347. ));
  1348. //
  1349. // Log a warning.
  1350. //
  1351. dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
  1352. dumpData[1] = KeyboardDeviceType;
  1353. dumpData[2] = KEYBOARD_COMPLETE_SUCCESS;
  1354. dumpData[3] = failedResetResponse2;
  1355. I8xLogError(
  1356. deviceObject,
  1357. I8042_KBD_RESET_RESPONSE_FAILED,
  1358. I8042_ERROR_VALUE_BASE + 520,
  1359. failedResetResponseStatus2,
  1360. dumpData,
  1361. 4
  1362. );
  1363. }
  1364. else if (failedResetResponse) {
  1365. Print(DBG_SS_ERROR,
  1366. ("kb failed reset response\n")
  1367. );
  1368. //
  1369. // Log a warning.
  1370. //
  1371. dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
  1372. dumpData[1] = KeyboardDeviceType;
  1373. dumpData[2] = KEYBOARD_COMPLETE_SUCCESS;
  1374. dumpData[3] = failedResetResponseByte;
  1375. I8xLogError(
  1376. deviceObject,
  1377. I8042_KBD_RESET_RESPONSE_FAILED,
  1378. I8042_ERROR_VALUE_BASE + 515,
  1379. failedResetResponseStatus,
  1380. dumpData,
  1381. 4
  1382. );
  1383. }
  1384. if (failedTypematic) {
  1385. Print(DBG_SS_ERROR,
  1386. ("I8xInitializeKeyboard: could not send SET TYPEMATIC cmd\n"
  1387. ));
  1388. //
  1389. // Log an error.
  1390. //
  1391. dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
  1392. dumpData[1] = DataPort;
  1393. dumpData[2] = SET_KEYBOARD_TYPEMATIC;
  1394. I8xLogError(
  1395. deviceObject,
  1396. I8042_SET_TYPEMATIC_FAILED,
  1397. I8042_ERROR_VALUE_BASE + 535,
  1398. failedTypematicStatus,
  1399. dumpData,
  1400. 3
  1401. );
  1402. }
  1403. if (failedLeds) {
  1404. Print(DBG_SS_ERROR,
  1405. ("I8xInitializeKeyboard: could not send SET LEDS cmd\n"
  1406. ));
  1407. //
  1408. // Log an error.
  1409. //
  1410. dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
  1411. dumpData[1] = DataPort;
  1412. dumpData[2] = SET_KEYBOARD_INDICATORS;
  1413. I8xLogError(
  1414. deviceObject,
  1415. I8042_SET_LED_FAILED,
  1416. I8042_ERROR_VALUE_BASE + 545,
  1417. failedLedsStatus,
  1418. dumpData,
  1419. 3
  1420. );
  1421. }
  1422. }
  1423. if (DEVICE_START_SUCCESS(status)) {
  1424. SET_HW_FLAGS(KEYBOARD_HARDWARE_PRESENT |
  1425. KEYBOARD_HARDWARE_INITIALIZED);
  1426. }
  1427. else {
  1428. CLEAR_KEYBOARD_PRESENT();
  1429. }
  1430. //
  1431. // Initialize current keyboard set packet state.
  1432. //
  1433. deviceExtension->CurrentOutput.State = Idle;
  1434. deviceExtension->CurrentOutput.Bytes = NULL;
  1435. deviceExtension->CurrentOutput.ByteCount = 0;
  1436. Print(DBG_SS_TRACE, ("I8xInitializeKeyboard (0x%x)\n", status));
  1437. return status;
  1438. }
  1439. NTSTATUS
  1440. I8xKeyboardConfiguration(
  1441. IN PPORT_KEYBOARD_EXTENSION KeyboardExtension,
  1442. IN PCM_RESOURCE_LIST ResourceList
  1443. )
  1444. /*++
  1445. Routine Description:
  1446. This routine retrieves the configuration information for the keyboard.
  1447. Arguments:
  1448. KeyboardExtension - Keyboard extension
  1449. ResourceList - Translated resource list give to us via the start IRP
  1450. Return Value:
  1451. STATUS_SUCCESS if all the resources required are presented
  1452. --*/
  1453. {
  1454. NTSTATUS status = STATUS_SUCCESS;
  1455. PCM_PARTIAL_RESOURCE_LIST partialResList = NULL;
  1456. PCM_PARTIAL_RESOURCE_DESCRIPTOR firstResDesc = NULL,
  1457. currentResDesc = NULL;
  1458. PCM_FULL_RESOURCE_DESCRIPTOR fullResDesc = NULL;
  1459. PI8042_CONFIGURATION_INFORMATION configuration;
  1460. PKEYBOARD_ID keyboardId;
  1461. ULONG count,
  1462. i;
  1463. KINTERRUPT_MODE defaultInterruptMode;
  1464. BOOLEAN defaultInterruptShare;
  1465. PAGED_CODE();
  1466. if (!ResourceList) {
  1467. Print(DBG_SS_INFO | DBG_SS_ERROR, ("keyboard with null resources\n"));
  1468. return STATUS_INSUFFICIENT_RESOURCES;
  1469. }
  1470. fullResDesc = ResourceList->List;
  1471. if (!fullResDesc) {
  1472. //
  1473. // this should never happen
  1474. //
  1475. ASSERT(fullResDesc != NULL);
  1476. return STATUS_INSUFFICIENT_RESOURCES;
  1477. }
  1478. configuration = &Globals.ControllerData->Configuration;
  1479. partialResList = &fullResDesc->PartialResourceList;
  1480. currentResDesc = firstResDesc = partialResList->PartialDescriptors;
  1481. count = partialResList->Count;
  1482. configuration->FloatingSave = I8042_FLOATING_SAVE;
  1483. configuration->BusNumber = fullResDesc->BusNumber;
  1484. configuration->InterfaceType = fullResDesc->InterfaceType;
  1485. if (configuration->InterfaceType == MicroChannel) {
  1486. defaultInterruptShare = TRUE;
  1487. defaultInterruptMode = LevelSensitive;
  1488. }
  1489. else {
  1490. defaultInterruptShare = I8042_INTERRUPT_SHARE;
  1491. defaultInterruptMode = I8042_INTERRUPT_MODE;
  1492. }
  1493. for (i = 0; i < count; i++, currentResDesc++) {
  1494. switch (currentResDesc->Type) {
  1495. case CmResourceTypeMemory:
  1496. Globals.RegistersMapped = TRUE;
  1497. case CmResourceTypePort:
  1498. //
  1499. // Copy the port information. We will sort the port list
  1500. // into ascending order based on the starting port address
  1501. // later (note that we *know* there are a max of two port
  1502. // ranges for the i8042).
  1503. //
  1504. #if 0
  1505. if (currentResDesc->Flags == CM_RESOURCE_PORT_MEMORY) {
  1506. Globals.RegistersMapped = TRUE;
  1507. }
  1508. #endif
  1509. Print(DBG_SS_NOISE,
  1510. ("port is %s.\n",
  1511. Globals.RegistersMapped ? "memory" : "io"));
  1512. if (configuration->PortListCount < MaximumPortCount) {
  1513. configuration->PortList[configuration->PortListCount] =
  1514. *currentResDesc;
  1515. configuration->PortList[configuration->PortListCount].ShareDisposition =
  1516. I8042_REGISTER_SHARE ? CmResourceShareShared:
  1517. CmResourceShareDriverExclusive;
  1518. configuration->PortListCount += 1;
  1519. }
  1520. else {
  1521. Print(DBG_SS_INFO | DBG_SS_ERROR,
  1522. ("KB::PortListCount already at max (%d)\n",
  1523. configuration->PortListCount
  1524. )
  1525. );
  1526. }
  1527. break;
  1528. case CmResourceTypeInterrupt:
  1529. //
  1530. // Copy the interrupt information.
  1531. //
  1532. KeyboardExtension->InterruptDescriptor = *currentResDesc;
  1533. KeyboardExtension->InterruptDescriptor.ShareDisposition =
  1534. defaultInterruptShare ? CmResourceShareShared :
  1535. CmResourceShareDeviceExclusive;
  1536. break;
  1537. default:
  1538. Print(DBG_ALWAYS,
  1539. ("resource type 0x%x unhandled...\n",
  1540. (LONG) currentResDesc->Type
  1541. ));
  1542. break;
  1543. }
  1544. }
  1545. if (KeyboardExtension->InterruptDescriptor.Type & CmResourceTypeInterrupt) {
  1546. Print(DBG_SS_INFO,
  1547. ("Keyboard interrupt config --\n"
  1548. " %s, %s, Irq = 0x%x\n",
  1549. KeyboardExtension->InterruptDescriptor.ShareDisposition ==
  1550. CmResourceShareShared ? "Sharable" : "NonSharable",
  1551. KeyboardExtension->InterruptDescriptor.Flags ==
  1552. CM_RESOURCE_INTERRUPT_LATCHED ? "Latched" : "Level Sensitive",
  1553. KeyboardExtension->InterruptDescriptor.u.Interrupt.Vector
  1554. ));
  1555. }
  1556. //
  1557. // If no keyboard-specific information (i.e., keyboard type, subtype,
  1558. // and initial LED settings) was found, use the keyboard driver
  1559. // defaults.
  1560. //
  1561. if (KeyboardExtension->KeyboardAttributes.KeyboardIdentifier.Type == 0) {
  1562. Print(DBG_SS_INFO, ("Using default keyboard type\n"));
  1563. KeyboardExtension->KeyboardAttributes.KeyboardIdentifier.Type =
  1564. KEYBOARD_TYPE_DEFAULT;
  1565. KeyboardExtension->KeyboardIndicators.LedFlags =
  1566. KEYBOARD_INDICATORS_DEFAULT;
  1567. KeyboardExtension->KeyboardIdentifierEx.Type = KEYBOARD_TYPE_DEFAULT;
  1568. }
  1569. Print(DBG_SS_INFO,
  1570. ("Keyboard device specific data --\n"
  1571. " Type = %d, Subtype = %d, Initial LEDs = 0x%x\n",
  1572. KeyboardExtension->KeyboardAttributes.KeyboardIdentifier.Type,
  1573. KeyboardExtension->KeyboardAttributes.KeyboardIdentifier.Subtype,
  1574. KeyboardExtension->KeyboardIndicators.LedFlags
  1575. ));
  1576. keyboardId = &KeyboardExtension->KeyboardAttributes.KeyboardIdentifier;
  1577. if (!ENHANCED_KEYBOARD(*keyboardId)) {
  1578. Print(DBG_SS_INFO, ("Old AT-style keyboard\n"));
  1579. configuration->PollingIterations =
  1580. configuration->PollingIterationsMaximum;
  1581. }
  1582. //
  1583. // Initialize keyboard-specific configuration parameters.
  1584. //
  1585. if (FAREAST_KEYBOARD(*keyboardId)) {
  1586. ULONG iIndex = 0;
  1587. PKEYBOARD_TYPE_INFORMATION pKeyboardTypeInformation = NULL;
  1588. while (KeyboardFarEastOemInformation[iIndex].KeyboardId.Type) {
  1589. if ((KeyboardFarEastOemInformation[iIndex].KeyboardId.Type
  1590. == keyboardId->Type) &&
  1591. (KeyboardFarEastOemInformation[iIndex].KeyboardId.Subtype
  1592. == keyboardId->Subtype)) {
  1593. pKeyboardTypeInformation = (PKEYBOARD_TYPE_INFORMATION)
  1594. &(KeyboardFarEastOemInformation[iIndex].KeyboardTypeInformation);
  1595. break;
  1596. }
  1597. iIndex++;
  1598. }
  1599. if (pKeyboardTypeInformation == NULL) {
  1600. //
  1601. // Set default...
  1602. //
  1603. pKeyboardTypeInformation = (PKEYBOARD_TYPE_INFORMATION)
  1604. &(KeyboardTypeInformation[KEYBOARD_TYPE_DEFAULT-1]);
  1605. }
  1606. KeyboardExtension->KeyboardAttributes.NumberOfFunctionKeys =
  1607. pKeyboardTypeInformation->NumberOfFunctionKeys;
  1608. KeyboardExtension->KeyboardAttributes.NumberOfIndicators =
  1609. pKeyboardTypeInformation->NumberOfIndicators;
  1610. KeyboardExtension->KeyboardAttributes.NumberOfKeysTotal =
  1611. pKeyboardTypeInformation->NumberOfKeysTotal;
  1612. }
  1613. else {
  1614. KeyboardExtension->KeyboardAttributes.NumberOfFunctionKeys =
  1615. KeyboardTypeInformation[keyboardId->Type - 1].NumberOfFunctionKeys;
  1616. KeyboardExtension->KeyboardAttributes.NumberOfIndicators =
  1617. KeyboardTypeInformation[keyboardId->Type - 1].NumberOfIndicators;
  1618. KeyboardExtension->KeyboardAttributes.NumberOfKeysTotal =
  1619. KeyboardTypeInformation[keyboardId->Type - 1].NumberOfKeysTotal;
  1620. }
  1621. KeyboardExtension->KeyboardAttributes.KeyboardMode =
  1622. KEYBOARD_SCAN_CODE_SET;
  1623. KeyboardExtension->KeyboardAttributes.KeyRepeatMinimum.Rate =
  1624. KEYBOARD_TYPEMATIC_RATE_MINIMUM;
  1625. KeyboardExtension->KeyboardAttributes.KeyRepeatMinimum.Delay =
  1626. KEYBOARD_TYPEMATIC_DELAY_MINIMUM;
  1627. KeyboardExtension->KeyboardAttributes.KeyRepeatMaximum.Rate =
  1628. KEYBOARD_TYPEMATIC_RATE_MAXIMUM;
  1629. KeyboardExtension->KeyboardAttributes.KeyRepeatMaximum.Delay =
  1630. KEYBOARD_TYPEMATIC_DELAY_MAXIMUM;
  1631. KeyboardExtension->KeyRepeatCurrent.Rate =
  1632. KEYBOARD_TYPEMATIC_RATE_DEFAULT;
  1633. KeyboardExtension->KeyRepeatCurrent.Delay =
  1634. KEYBOARD_TYPEMATIC_DELAY_DEFAULT;
  1635. return status;
  1636. }
  1637. #if defined(_X86_)
  1638. ULONG
  1639. I8042ConversionStatusForOasys(
  1640. IN ULONG fOpen,
  1641. IN ULONG ConvStatus)
  1642. /*++
  1643. Routine Description:
  1644. This routine convert ime open/close status and ime converion mode to
  1645. FMV oyayubi-shift keyboard device internal input mode.
  1646. Arguments:
  1647. Return Value:
  1648. FMV oyayubi-shift keyboard's internal input mode.
  1649. --*/
  1650. {
  1651. ULONG ImeMode = 0;
  1652. if (fOpen) {
  1653. if (ConvStatus & IME_CMODE_ROMAN) {
  1654. if (ConvStatus & IME_CMODE_ALPHANUMERIC) {
  1655. //
  1656. // Alphanumeric, roman mode.
  1657. //
  1658. ImeMode = THUMB_ROMAN_ALPHA_CAPSON;
  1659. } else if (ConvStatus & IME_CMODE_KATAKANA) {
  1660. //
  1661. // Katakana, roman mode.
  1662. //
  1663. ImeMode = THUMB_ROMAN_KATAKANA;
  1664. } else if (ConvStatus & IME_CMODE_NATIVE) {
  1665. //
  1666. // Hiragana, roman mode.
  1667. //
  1668. ImeMode = THUMB_ROMAN_HIRAGANA;
  1669. } else {
  1670. ImeMode = THUMB_ROMAN_ALPHA_CAPSON;
  1671. }
  1672. } else {
  1673. if (ConvStatus & IME_CMODE_ALPHANUMERIC) {
  1674. //
  1675. // Alphanumeric, no-roman mode.
  1676. //
  1677. ImeMode = THUMB_NOROMAN_ALPHA_CAPSON;
  1678. } else if (ConvStatus & IME_CMODE_KATAKANA) {
  1679. //
  1680. // Katakana, no-roman mode.
  1681. //
  1682. ImeMode = THUMB_NOROMAN_KATAKANA;
  1683. } else if (ConvStatus & IME_CMODE_NATIVE) {
  1684. //
  1685. // Hiragana, no-roman mode.
  1686. //
  1687. ImeMode = THUMB_NOROMAN_HIRAGANA;
  1688. } else {
  1689. ImeMode = THUMB_NOROMAN_ALPHA_CAPSON;
  1690. }
  1691. }
  1692. } else {
  1693. //
  1694. // Ime close. In this case, internal mode is always this value.
  1695. // (the both LED off roman and kana)
  1696. //
  1697. ImeMode = THUMB_NOROMAN_ALPHA_CAPSON;
  1698. }
  1699. return ImeMode;
  1700. }
  1701. ULONG
  1702. I8042QueryIMEStatusForOasys(
  1703. IN PKEYBOARD_IME_STATUS KeyboardIMEStatus
  1704. )
  1705. {
  1706. ULONG InternalMode;
  1707. //
  1708. // Map to IME mode to hardware mode.
  1709. //
  1710. InternalMode = I8042ConversionStatusForOasys(
  1711. KeyboardIMEStatus->ImeOpen,
  1712. KeyboardIMEStatus->ImeConvMode
  1713. );
  1714. return InternalMode;
  1715. }
  1716. NTSTATUS
  1717. I8042SetIMEStatusForOasys(
  1718. IN PDEVICE_OBJECT DeviceObject,
  1719. IN PIRP Irp,
  1720. IN OUT PINITIATE_OUTPUT_CONTEXT InitiateContext
  1721. )
  1722. {
  1723. PKEYBOARD_IME_STATUS KeyboardIMEStatus;
  1724. PPORT_KEYBOARD_EXTENSION kbExtension;
  1725. ULONG InternalMode;
  1726. LARGE_INTEGER deltaTime;
  1727. kbExtension = DeviceObject->DeviceExtension;
  1728. //
  1729. // Get pointer to KEYBOARD_IME_STATUS buffer.
  1730. //
  1731. KeyboardIMEStatus = (PKEYBOARD_IME_STATUS)(Irp->AssociatedIrp.SystemBuffer);
  1732. //
  1733. // Map IME mode to keyboard hardware mode.
  1734. //
  1735. InternalMode = I8042QueryIMEStatusForOasys(KeyboardIMEStatus);
  1736. //
  1737. // Set up the context structure for the InitiateIo wrapper.
  1738. //
  1739. InitiateContext->Bytes = Globals.ControllerData->DefaultBuffer;
  1740. InitiateContext->DeviceObject = DeviceObject;
  1741. InitiateContext->ByteCount = 3;
  1742. InitiateContext->Bytes[0] = 0xF0;
  1743. InitiateContext->Bytes[1] = 0x8C;
  1744. InitiateContext->Bytes[2] = (UCHAR)InternalMode;
  1745. return (STATUS_SUCCESS);
  1746. }
  1747. #endif // defined(_X86_)
  1748. VOID
  1749. I8xQueueCurrentKeyboardInput(
  1750. IN PDEVICE_OBJECT DeviceObject
  1751. )
  1752. /*++
  1753. Routine Description:
  1754. This routine queues the current input data to be processed by a
  1755. DPC outside the ISR
  1756. Arguments:
  1757. DeviceObject - Pointer to the device object
  1758. Return Value:
  1759. None
  1760. --*/
  1761. {
  1762. PPORT_KEYBOARD_EXTENSION deviceExtension;
  1763. deviceExtension = DeviceObject->DeviceExtension;
  1764. if (deviceExtension->EnableCount) {
  1765. if (!I8xWriteDataToKeyboardQueue(
  1766. deviceExtension,
  1767. &deviceExtension->CurrentInput
  1768. )) {
  1769. //
  1770. // The InputData queue overflowed. There is
  1771. // not much that can be done about it, so just
  1772. // continue (but don't queue the ISR DPC, since
  1773. // no new packets were added to the queue).
  1774. //
  1775. // Queue a DPC to log an overrun error.
  1776. //
  1777. IsrPrint(DBG_KBISR_ERROR, ("queue overflow\n"));
  1778. if (deviceExtension->OkayToLogOverflow) {
  1779. KeInsertQueueDpc(
  1780. &deviceExtension->ErrorLogDpc,
  1781. (PIRP) NULL,
  1782. LongToPtr(I8042_KBD_BUFFER_OVERFLOW)
  1783. );
  1784. deviceExtension->OkayToLogOverflow = FALSE;
  1785. }
  1786. } else if (deviceExtension->DpcInterlockKeyboard >= 0) {
  1787. //
  1788. // The ISR DPC is already executing. Tell the ISR DPC
  1789. // it has more work to do by incrementing
  1790. // DpcInterlockKeyboard.
  1791. //
  1792. deviceExtension->DpcInterlockKeyboard += 1;
  1793. } else {
  1794. //
  1795. // Queue the ISR DPC.
  1796. //
  1797. KeInsertQueueDpc(
  1798. &deviceExtension->KeyboardIsrDpc,
  1799. DeviceObject->CurrentIrp,
  1800. NULL
  1801. );
  1802. }
  1803. }
  1804. //
  1805. // Reset the input state.
  1806. //
  1807. deviceExtension->CurrentInput.Flags = 0;
  1808. }
  1809. VOID
  1810. I8xServiceCrashDump(
  1811. IN PPORT_KEYBOARD_EXTENSION DeviceExtension,
  1812. IN PUNICODE_STRING RegistryPath
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. This routine retrieves this driver's service parameters information
  1817. from the registry.
  1818. Arguments:
  1819. DeviceExtension - Pointer to the device extension.
  1820. RegistryPath - Pointer to the null-terminated Unicode name of the
  1821. registry path for this driver.
  1822. Return Value:
  1823. None. As a side-effect, sets fields in DeviceExtension->Dump1Keys
  1824. & DeviceExtension->Dump2Key.
  1825. --*/
  1826. {
  1827. PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
  1828. UNICODE_STRING parametersPath;
  1829. LONG defaultCrashFlags = 0;
  1830. LONG crashFlags;
  1831. LONG defaultKeyNumber = 0;
  1832. LONG keyNumber;
  1833. NTSTATUS status = STATUS_SUCCESS;
  1834. PWSTR path = NULL;
  1835. USHORT queriesPlusOne = 3;
  1836. const UCHAR keyToScanTbl[134] = {
  1837. 0x00,0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
  1838. 0x0A,0x0B,0x0C,0x0D,0x7D,0x0E,0x0F,0x10,0x11,0x12,
  1839. 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x00,
  1840. 0x3A,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,
  1841. 0x27,0x28,0x2B,0x1C,0x2A,0x00,0x2C,0x2D,0x2E,0x2F,
  1842. 0x30,0x31,0x32,0x33,0x34,0x35,0x73,0x36,0x1D,0x00,
  1843. 0x38,0x39,0xB8,0x00,0x9D,0x00,0x00,0x00,0x00,0x00,
  1844. 0x00,0x00,0x00,0x00,0x00,0xD2,0xD3,0x00,0x00,0xCB,
  1845. 0xC7,0xCF,0x00,0xC8,0xD0,0xC9,0xD1,0x00,0x00,0xCD,
  1846. 0x45,0x47,0x4B,0x4F,0x00,0xB5,0x48,0x4C,0x50,0x52,
  1847. 0x37,0x49,0x4D,0x51,0x53,0x4A,0x4E,0x00,0x9C,0x00,
  1848. 0x01,0x00,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,
  1849. 0x43,0x44,0x57,0x58,0x00,0x46,0x00,0x00,0x00,0x00,
  1850. 0x00,0x7B,0x79,0x70 };
  1851. PAGED_CODE();
  1852. parametersPath.Buffer = NULL;
  1853. //
  1854. // Registry path is already null-terminated, so just use it.
  1855. //
  1856. path = RegistryPath->Buffer;
  1857. if (NT_SUCCESS(status)) {
  1858. //
  1859. // Allocate the Rtl query table.
  1860. //
  1861. parameters = ExAllocatePool(
  1862. PagedPool,
  1863. sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
  1864. );
  1865. if (!parameters) {
  1866. Print(DBG_SS_ERROR,
  1867. ("I8xServiceCrashDump: Couldn't allocate table for Rtl query to parameters for %ws\n",
  1868. path
  1869. ));
  1870. status = STATUS_UNSUCCESSFUL;
  1871. } else {
  1872. RtlZeroMemory(
  1873. parameters,
  1874. sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
  1875. );
  1876. //
  1877. // Form a path to this driver's Parameters subkey.
  1878. //
  1879. RtlInitUnicodeString(
  1880. &parametersPath,
  1881. NULL
  1882. );
  1883. parametersPath.MaximumLength = RegistryPath->Length +
  1884. sizeof(L"\\Crashdump");
  1885. parametersPath.Buffer = ExAllocatePool(
  1886. PagedPool,
  1887. parametersPath.MaximumLength
  1888. );
  1889. if (!parametersPath.Buffer) {
  1890. Print(DBG_SS_ERROR,
  1891. ("I8xServiceCrashDump: Couldn't allocate string for path to parameters for %ws\n",
  1892. path
  1893. ));
  1894. status = STATUS_UNSUCCESSFUL;
  1895. }
  1896. }
  1897. }
  1898. if (NT_SUCCESS(status)) {
  1899. //
  1900. // Form the parameters path.
  1901. //
  1902. RtlZeroMemory(
  1903. parametersPath.Buffer,
  1904. parametersPath.MaximumLength
  1905. );
  1906. RtlAppendUnicodeToString(
  1907. &parametersPath,
  1908. path
  1909. );
  1910. RtlAppendUnicodeToString(
  1911. &parametersPath,
  1912. L"\\Crashdump"
  1913. );
  1914. Print(DBG_SS_INFO,
  1915. ("I8xServiceCrashDump: crashdump path is %ws\n",
  1916. parametersPath.Buffer
  1917. ));
  1918. //
  1919. // Gather all of the "user specified" information from
  1920. // the registry.
  1921. //
  1922. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1923. parameters[0].Name = L"Dump1Keys";
  1924. parameters[0].EntryContext = &crashFlags;
  1925. parameters[0].DefaultType = REG_DWORD;
  1926. parameters[0].DefaultData = &defaultCrashFlags;
  1927. parameters[0].DefaultLength = sizeof(LONG);
  1928. parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1929. parameters[1].Name = L"Dump2Key";
  1930. parameters[1].EntryContext = &keyNumber;
  1931. parameters[1].DefaultType = REG_DWORD;
  1932. parameters[1].DefaultData = &defaultKeyNumber;
  1933. parameters[1].DefaultLength = sizeof(LONG);
  1934. status = RtlQueryRegistryValues(
  1935. RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  1936. parametersPath.Buffer,
  1937. parameters,
  1938. NULL,
  1939. NULL
  1940. );
  1941. }
  1942. if (!NT_SUCCESS(status)) {
  1943. //
  1944. // Go ahead and assign driver defaults.
  1945. //
  1946. DeviceExtension->CrashFlags = defaultCrashFlags;
  1947. }
  1948. else {
  1949. DeviceExtension->CrashFlags = crashFlags;
  1950. }
  1951. if (DeviceExtension->CrashFlags) {
  1952. if (keyNumber == 124) {
  1953. DeviceExtension->CrashScanCode = KEYBOARD_DEBUG_HOTKEY_ENH | 0x80;
  1954. DeviceExtension->CrashScanCode2 = KEYBOARD_DEBUG_HOTKEY_AT;
  1955. }
  1956. else {
  1957. if(keyNumber <= 133) {
  1958. DeviceExtension->CrashScanCode = keyToScanTbl[keyNumber];
  1959. }
  1960. else {
  1961. DeviceExtension->CrashScanCode = 0;
  1962. }
  1963. DeviceExtension->CrashScanCode2 = 0;
  1964. }
  1965. }
  1966. Print(DBG_SS_NOISE,
  1967. ("I8xServiceCrashDump: CrashFlags = 0x%x\n",
  1968. DeviceExtension->CrashFlags
  1969. ));
  1970. Print(DBG_SS_NOISE,
  1971. ("I8xServiceCrashDump: CrashScanCode = 0x%x, CrashScanCode2 = 0x%x\n",
  1972. (ULONG) DeviceExtension->CrashScanCode,
  1973. (ULONG) DeviceExtension->CrashScanCode2
  1974. ));
  1975. //
  1976. // Free the allocated memory before returning.
  1977. //
  1978. if (parametersPath.Buffer)
  1979. ExFreePool(parametersPath.Buffer);
  1980. if (parameters)
  1981. ExFreePool(parameters);
  1982. }
  1983. VOID
  1984. I8xKeyboardServiceParameters(
  1985. IN PUNICODE_STRING RegistryPath,
  1986. IN PPORT_KEYBOARD_EXTENSION KeyboardExtension
  1987. )
  1988. /*++
  1989. Routine Description:
  1990. This routine retrieves this driver's service parameters information
  1991. from the registry. Overrides these values if they are present in the
  1992. devnode.
  1993. Arguments:
  1994. RegistryPath - Pointer to the null-terminated Unicode name of the
  1995. registry path for this driver.
  1996. KeyboardExtension - Keyboard extension
  1997. Return Value:
  1998. None.
  1999. --*/
  2000. {
  2001. NTSTATUS status = STATUS_SUCCESS;
  2002. PI8042_CONFIGURATION_INFORMATION configuration;
  2003. PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
  2004. PWSTR path = NULL;
  2005. ULONG defaultDataQueueSize = DATA_QUEUE_SIZE;
  2006. ULONG invalidKeyboardSubtype = (ULONG) -1;
  2007. ULONG invalidKeyboardType = 0;
  2008. ULONG overrideKeyboardSubtype = (ULONG) -1;
  2009. ULONG overrideKeyboardType = 0;
  2010. ULONG pollStatusIterations = 0;
  2011. ULONG defaultPowerCaps = 0x0, powerCaps = 0x0;
  2012. ULONG failedReset = FAILED_RESET_DEFAULT,
  2013. defaultFailedReset = FAILED_RESET_DEFAULT;
  2014. ULONG i = 0;
  2015. UNICODE_STRING parametersPath;
  2016. HANDLE keyHandle;
  2017. ULONG defaultPollStatusIterations = I8042_POLLING_DEFAULT;
  2018. ULONG crashOnCtrlScroll = 0,
  2019. defaultCrashOnCtrlScroll = 0;
  2020. USHORT queries = 8;
  2021. PAGED_CODE();
  2022. #if I8042_VERBOSE
  2023. queries += 2;
  2024. #endif
  2025. configuration = &(Globals.ControllerData->Configuration);
  2026. parametersPath.Buffer = NULL;
  2027. //
  2028. // Registry path is already null-terminated, so just use it.
  2029. //
  2030. path = RegistryPath->Buffer;
  2031. if (NT_SUCCESS(status)) {
  2032. //
  2033. // Allocate the Rtl query table.
  2034. //
  2035. parameters = ExAllocatePool(
  2036. PagedPool,
  2037. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  2038. );
  2039. if (!parameters) {
  2040. Print(DBG_SS_ERROR,
  2041. ("%s: couldn't allocate table for Rtl query to %ws for %ws\n",
  2042. pFncServiceParameters,
  2043. pwParameters,
  2044. path
  2045. ));
  2046. status = STATUS_UNSUCCESSFUL;
  2047. } else {
  2048. RtlZeroMemory(
  2049. parameters,
  2050. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  2051. );
  2052. //
  2053. // Form a path to this driver's Parameters subkey.
  2054. //
  2055. RtlInitUnicodeString( &parametersPath, NULL );
  2056. parametersPath.MaximumLength = RegistryPath->Length +
  2057. (wcslen(pwParameters) * sizeof(WCHAR) ) + sizeof(UNICODE_NULL);
  2058. parametersPath.Buffer = ExAllocatePool(
  2059. PagedPool,
  2060. parametersPath.MaximumLength
  2061. );
  2062. if (!parametersPath.Buffer) {
  2063. Print(DBG_SS_ERROR,
  2064. ("%s: Couldn't allocate string for path to %ws for %ws\n",
  2065. pFncServiceParameters,
  2066. pwParameters,
  2067. path
  2068. ));
  2069. status = STATUS_UNSUCCESSFUL;
  2070. }
  2071. }
  2072. }
  2073. if (NT_SUCCESS(status)) {
  2074. //
  2075. // Form the parameters path.
  2076. //
  2077. RtlZeroMemory(
  2078. parametersPath.Buffer,
  2079. parametersPath.MaximumLength
  2080. );
  2081. RtlAppendUnicodeToString(
  2082. &parametersPath,
  2083. path
  2084. );
  2085. RtlAppendUnicodeToString(
  2086. &parametersPath,
  2087. pwParameters
  2088. );
  2089. //
  2090. // Gather all of the "user specified" information from
  2091. // the registry.
  2092. //
  2093. parameters[i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2094. parameters[i].Name = pwKeyboardDataQueueSize;
  2095. parameters[i].EntryContext =
  2096. &KeyboardExtension->KeyboardAttributes.InputDataQueueLength;
  2097. parameters[i].DefaultType = REG_DWORD;
  2098. parameters[i].DefaultData = &defaultDataQueueSize;
  2099. parameters[i].DefaultLength = sizeof(ULONG);
  2100. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2101. parameters[i].Name = pwOverrideKeyboardType;
  2102. parameters[i].EntryContext = &overrideKeyboardType;
  2103. parameters[i].DefaultType = REG_DWORD;
  2104. parameters[i].DefaultData = &invalidKeyboardType;
  2105. parameters[i].DefaultLength = sizeof(ULONG);
  2106. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2107. parameters[i].Name = pwOverrideKeyboardSubtype;
  2108. parameters[i].EntryContext = &overrideKeyboardSubtype;
  2109. parameters[i].DefaultType = REG_DWORD;
  2110. parameters[i].DefaultData = &invalidKeyboardSubtype;
  2111. parameters[i].DefaultLength = sizeof(ULONG);
  2112. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2113. parameters[i].Name = pwPollStatusIterations;
  2114. parameters[i].EntryContext = &pollStatusIterations;
  2115. parameters[i].DefaultType = REG_DWORD;
  2116. parameters[i].DefaultData = &defaultPollStatusIterations;
  2117. parameters[i].DefaultLength = sizeof(ULONG);
  2118. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2119. parameters[i].Name = pwPowerCaps;
  2120. parameters[i].EntryContext = &powerCaps;
  2121. parameters[i].DefaultType = REG_DWORD;
  2122. parameters[i].DefaultData = &defaultPowerCaps;
  2123. parameters[i].DefaultLength = sizeof(ULONG);
  2124. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2125. parameters[i].Name = L"CrashOnCtrlScroll";
  2126. parameters[i].EntryContext = &crashOnCtrlScroll;
  2127. parameters[i].DefaultType = REG_DWORD;
  2128. parameters[i].DefaultData = &defaultCrashOnCtrlScroll;
  2129. parameters[i].DefaultLength = sizeof(ULONG);
  2130. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2131. parameters[i].Name = STR_FAILED_RESET;
  2132. parameters[i].EntryContext = &failedReset;
  2133. parameters[i].DefaultType = REG_DWORD;
  2134. parameters[i].DefaultData = &defaultFailedReset;
  2135. parameters[i].DefaultLength = sizeof(ULONG);
  2136. status = RtlQueryRegistryValues(
  2137. RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  2138. parametersPath.Buffer,
  2139. parameters,
  2140. NULL,
  2141. NULL
  2142. );
  2143. if (!NT_SUCCESS(status)) {
  2144. Print(DBG_SS_INFO,
  2145. ("kb RtlQueryRegistryValues failed (0x%x)\n",
  2146. status
  2147. ));
  2148. }
  2149. }
  2150. if (!NT_SUCCESS(status)) {
  2151. //
  2152. // Go ahead and assign driver defaults.
  2153. //
  2154. configuration->PollStatusIterations = (USHORT)
  2155. defaultPollStatusIterations;
  2156. KeyboardExtension->KeyboardAttributes.InputDataQueueLength =
  2157. defaultDataQueueSize;
  2158. }
  2159. else {
  2160. configuration->PollStatusIterations = (USHORT) pollStatusIterations;
  2161. }
  2162. switch (failedReset) {
  2163. case FAILED_RESET_STOP:
  2164. case FAILED_RESET_PROCEED:
  2165. case FAILED_RESET_PROCEED_ALWAYS:
  2166. KeyboardExtension->FailedReset = (UCHAR) failedReset;
  2167. break;
  2168. default:
  2169. KeyboardExtension->FailedReset = FAILED_RESET_DEFAULT;
  2170. break;
  2171. }
  2172. Print(DBG_SS_NOISE, ("Failed reset is set to %d\n",
  2173. KeyboardExtension->FailedReset));
  2174. status = IoOpenDeviceRegistryKey(KeyboardExtension->PDO,
  2175. PLUGPLAY_REGKEY_DEVICE,
  2176. STANDARD_RIGHTS_READ,
  2177. &keyHandle
  2178. );
  2179. if (NT_SUCCESS(status)) {
  2180. //
  2181. // If the value is not present in devnode, then the default is the value
  2182. // read in from the Services\i8042prt\Parameters key
  2183. //
  2184. ULONG prevInputDataQueueLength,
  2185. prevPowerCaps,
  2186. prevOverrideKeyboardType,
  2187. prevOverrideKeyboardSubtype,
  2188. prevPollStatusIterations;
  2189. prevInputDataQueueLength =
  2190. KeyboardExtension->KeyboardAttributes.InputDataQueueLength;
  2191. prevPowerCaps = powerCaps;
  2192. prevOverrideKeyboardType = overrideKeyboardType;
  2193. prevOverrideKeyboardSubtype = overrideKeyboardSubtype;
  2194. prevPollStatusIterations = pollStatusIterations;
  2195. RtlZeroMemory(
  2196. parameters,
  2197. sizeof(RTL_QUERY_REGISTRY_TABLE) * (queries + 1)
  2198. );
  2199. i = 0;
  2200. //
  2201. // Gather all of the "user specified" information from
  2202. // the registry (this time from the devnode)
  2203. //
  2204. parameters[i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2205. parameters[i].Name = pwKeyboardDataQueueSize;
  2206. parameters[i].EntryContext =
  2207. &KeyboardExtension->KeyboardAttributes.InputDataQueueLength;
  2208. parameters[i].DefaultType = REG_DWORD;
  2209. parameters[i].DefaultData = &prevInputDataQueueLength;
  2210. parameters[i].DefaultLength = sizeof(ULONG);
  2211. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2212. parameters[i].Name = pwOverrideKeyboardType;
  2213. parameters[i].EntryContext = &overrideKeyboardType;
  2214. parameters[i].DefaultType = REG_DWORD;
  2215. parameters[i].DefaultData = &prevOverrideKeyboardType;
  2216. parameters[i].DefaultLength = sizeof(ULONG);
  2217. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2218. parameters[i].Name = pwOverrideKeyboardSubtype;
  2219. parameters[i].EntryContext = &overrideKeyboardSubtype;
  2220. parameters[i].DefaultType = REG_DWORD;
  2221. parameters[i].DefaultData = &prevOverrideKeyboardSubtype;
  2222. parameters[i].DefaultLength = sizeof(ULONG);
  2223. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2224. parameters[i].Name = pwPollStatusIterations;
  2225. parameters[i].EntryContext = &pollStatusIterations;
  2226. parameters[i].DefaultType = REG_DWORD;
  2227. parameters[i].DefaultData = &prevPollStatusIterations;
  2228. parameters[i].DefaultLength = sizeof(ULONG);
  2229. parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT;
  2230. parameters[i].Name = pwPowerCaps,
  2231. parameters[i].EntryContext = &powerCaps;
  2232. parameters[i].DefaultType = REG_DWORD;
  2233. parameters[i].DefaultData = &prevPowerCaps;
  2234. parameters[i].DefaultLength = sizeof(ULONG);
  2235. status = RtlQueryRegistryValues(
  2236. RTL_REGISTRY_HANDLE,
  2237. (PWSTR) keyHandle,
  2238. parameters,
  2239. NULL,
  2240. NULL
  2241. );
  2242. if (!NT_SUCCESS(status)) {
  2243. Print(DBG_SS_INFO,
  2244. ("kb RtlQueryRegistryValues (via handle) failed (0x%x)\n",
  2245. status
  2246. ));
  2247. }
  2248. ZwClose(keyHandle);
  2249. }
  2250. else {
  2251. Print(DBG_SS_INFO | DBG_SS_ERROR,
  2252. ("kb, opening devnode handle failed (0x%x)\n",
  2253. status
  2254. ));
  2255. }
  2256. Print(DBG_SS_NOISE, ("I8xKeyboardServiceParameters results..\n"));
  2257. Print(DBG_SS_NOISE,
  2258. (pDumpDecimal,
  2259. pwPollStatusIterations,
  2260. configuration->PollStatusIterations
  2261. ));
  2262. if (KeyboardExtension->KeyboardAttributes.InputDataQueueLength == 0) {
  2263. Print(DBG_SS_INFO | DBG_SS_ERROR,
  2264. ("\toverriding %ws = 0x%x\n",
  2265. pwKeyboardDataQueueSize,
  2266. KeyboardExtension->KeyboardAttributes.InputDataQueueLength
  2267. ));
  2268. KeyboardExtension->KeyboardAttributes.InputDataQueueLength =
  2269. defaultDataQueueSize;
  2270. }
  2271. KeyboardExtension->KeyboardAttributes.InputDataQueueLength *=
  2272. sizeof(KEYBOARD_INPUT_DATA);
  2273. KeyboardExtension->PowerCaps = (UCHAR) (powerCaps & I8042_SYS_BUTTONS);
  2274. Print(DBG_SS_NOISE, (pDumpHex, pwPowerCaps, KeyboardExtension->PowerCaps));
  2275. if (overrideKeyboardType != invalidKeyboardType) {
  2276. if (overrideKeyboardType <= NUM_KNOWN_KEYBOARD_TYPES) {
  2277. Print(DBG_SS_NOISE,
  2278. (pDumpDecimal,
  2279. pwOverrideKeyboardType,
  2280. overrideKeyboardType
  2281. ));
  2282. KeyboardExtension->KeyboardAttributes.KeyboardIdentifier.Type =
  2283. (UCHAR) overrideKeyboardType;
  2284. } else {
  2285. Print(DBG_SS_NOISE,
  2286. (pDumpDecimal,
  2287. pwOverrideKeyboardType,
  2288. overrideKeyboardType
  2289. ));
  2290. }
  2291. KeyboardExtension->KeyboardIdentifierEx.Type = overrideKeyboardType;
  2292. }
  2293. if (overrideKeyboardSubtype != invalidKeyboardSubtype) {
  2294. Print(DBG_SS_NOISE,
  2295. (pDumpDecimal,
  2296. pwOverrideKeyboardSubtype,
  2297. overrideKeyboardSubtype
  2298. ));
  2299. KeyboardExtension->KeyboardAttributes.KeyboardIdentifier.Subtype =
  2300. (UCHAR) overrideKeyboardSubtype;
  2301. KeyboardExtension->KeyboardIdentifierEx.Subtype =
  2302. overrideKeyboardSubtype;
  2303. }
  2304. if (crashOnCtrlScroll) {
  2305. Print(DBG_SS_INFO, ("Crashing on Ctrl + Scroll Lock\n"));
  2306. KeyboardExtension->CrashFlags = CRASH_R_CTRL;
  2307. KeyboardExtension->CrashScanCode = SCROLL_LOCK_SCANCODE;
  2308. KeyboardExtension->CrashScanCode2 = 0x0;
  2309. }
  2310. //
  2311. // Free the allocated memory before returning.
  2312. //
  2313. if (parametersPath.Buffer)
  2314. ExFreePool(parametersPath.Buffer);
  2315. if (parameters)
  2316. ExFreePool(parameters);
  2317. }