2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/input/i8042prt/keyboard.c
5 * PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver
7 * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
8 * Jason Filby (jasonfilby@yahoo.com)
12 /* INCLUDES ****************************************************************/
21 /* GLOBALS *******************************************************************/
23 static UCHAR TypematicTable
[] = {
24 0x00, 0x00, 0x00, 0x05, 0x08, 0x0B, 0x0D, 0x0F, 0x10, 0x12, /* 0-9 */
25 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1A, /* 10-19 */
26 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E };
28 typedef struct _LOCAL_KEYBOARD_INDICATOR_TRANSLATION
{
29 USHORT NumberOfIndicatorKeys
;
30 INDICATOR_LIST IndicatorList
[3];
31 } LOCAL_KEYBOARD_INDICATOR_TRANSLATION
, *PLOCAL_KEYBOARD_INDICATOR_TRANSLATION
;
33 static LOCAL_KEYBOARD_INDICATOR_TRANSLATION IndicatorTranslation
= { 3, {
34 {0x3A, KEYBOARD_CAPS_LOCK_ON
},
35 {0x45, KEYBOARD_NUM_LOCK_ON
},
36 {0x46, KEYBOARD_SCROLL_LOCK_ON
}}};
38 static VOID STDCALL
I8042DebugWorkItem(PDEVICE_OBJECT DeviceObject
,
41 /* FUNCTIONS *****************************************************************/
44 * These functions are callbacks for filter driver custom interrupt
47 VOID STDCALL
I8042IsrWritePortKbd(PVOID Context
,
50 I8042IsrWritePort(Context
, Value
, 0);
53 static VOID STDCALL
I8042QueueKeyboardPacket(PVOID Context
)
55 PDEVICE_OBJECT DeviceObject
= Context
;
56 PFDO_DEVICE_EXTENSION FdoDevExt
= DeviceObject
->DeviceExtension
;
57 PDEVICE_EXTENSION DevExt
= FdoDevExt
->PortDevExt
;
59 DevExt
->KeyComplete
= TRUE
;
60 DevExt
->KeysInBuffer
++;
61 if (DevExt
->KeysInBuffer
>
62 DevExt
->KeyboardAttributes
.InputDataQueueLength
) {
63 DPRINT1("Keyboard buffer overflow\n");
64 DevExt
->KeysInBuffer
--;
67 DPRINT("Irq completes key\n");
68 KeInsertQueueDpc(&DevExt
->DpcKbd
, DevExt
, NULL
);
72 * These functions are callbacks for filter driver custom
73 * initialization routines.
75 NTSTATUS STDCALL
I8042SynchWritePortKbd(PVOID Context
,
79 return I8042SynchWritePort((PDEVICE_EXTENSION
)Context
,
85 BOOLEAN STDCALL
I8042InterruptServiceKbd(struct _KINTERRUPT
*Interrupt
,
91 PDEVICE_EXTENSION DevExt
= (PDEVICE_EXTENSION
) Context
;
92 BOOLEAN HookContinue
= FALSE
, HookReturn
;
95 KEYBOARD_INPUT_DATA
*InputData
=
96 DevExt
->KeyboardBuffer
+ DevExt
->KeysInBuffer
;
99 Status
= I8042ReadStatus(&PortStatus
);
100 DPRINT("PortStatus: %x\n", PortStatus
);
101 Status
= I8042ReadData(&Output
);
103 if (STATUS_SUCCESS
== Status
)
105 KeStallExecutionProcessor(1);
106 } while (Iterations
< DevExt
->Settings
.PollStatusIterations
);
108 if (STATUS_SUCCESS
!= Status
) {
109 DPRINT("Spurious I8042 interrupt\n");
113 DPRINT("Got: %x\n", Output
);
115 if (DevExt
->KeyboardHook
.IsrRoutine
) {
116 HookReturn
= DevExt
->KeyboardHook
.IsrRoutine(
117 DevExt
->KeyboardHook
.Context
,
123 &DevExt
->KeyboardScanState
);
129 if (I8042PacketIsr(DevExt
, Output
)) {
130 if (DevExt
->PacketComplete
) {
131 DPRINT("Packet complete\n");
132 KeInsertQueueDpc(&DevExt
->DpcKbd
, DevExt
, NULL
);
134 DPRINT("Irq eaten by packet\n");
138 DPRINT("Irq is keyboard input\n");
140 if (Normal
== DevExt
->KeyboardScanState
) {
143 DevExt
->KeyboardScanState
= GotE0
;
146 DevExt
->KeyboardScanState
= GotE1
;
153 InputData
->Flags
= 0;
155 switch (DevExt
->KeyboardScanState
) {
157 InputData
->Flags
|= KEY_E0
;
160 InputData
->Flags
|= KEY_E1
;
165 DevExt
->KeyboardScanState
= Normal
;
168 InputData
->Flags
|= KEY_BREAK
;
170 InputData
->Flags
|= KEY_MAKE
;
172 InputData
->MakeCode
= Output
& 0x7f;
174 I8042QueueKeyboardPacket(DevExt
->KeyboardObject
);
179 VOID STDCALL
I8042DpcRoutineKbd(PKDPC Dpc
,
180 PVOID DeferredContext
,
181 PVOID SystemArgument1
,
182 PVOID SystemArgument2
)
184 PDEVICE_EXTENSION DevExt
= (PDEVICE_EXTENSION
)SystemArgument1
;
185 ULONG KeysTransferred
= 0;
186 ULONG KeysInBufferCopy
;
189 I8042PacketDpc(DevExt
);
191 if (!DevExt
->KeyComplete
)
194 /* We got the interrupt as it was being enabled, too bad */
195 if (!DevExt
->HighestDIRQLInterrupt
)
198 Irql
= KeAcquireInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
);
200 DevExt
->KeyComplete
= FALSE
;
201 KeysInBufferCopy
= DevExt
->KeysInBuffer
;
203 KeReleaseInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
, Irql
);
205 /* Test for TAB (debugging) */
206 if (DevExt
->Settings
.CrashSysRq
) {
207 PKEYBOARD_INPUT_DATA InputData
= DevExt
->KeyboardBuffer
+
208 KeysInBufferCopy
- 1;
209 if (InputData
->MakeCode
== 0x0F) {
211 DevExt
->TabPressed
= !(InputData
->Flags
& KEY_BREAK
);
212 } else if (DevExt
->TabPressed
) {
213 DPRINT ("Queueing work item %x\n", DevExt
->DebugWorkItem
);
214 DevExt
->DebugKey
= InputData
->MakeCode
;
215 DevExt
->TabPressed
= FALSE
;
217 IoQueueWorkItem(DevExt
->DebugWorkItem
,
218 &(I8042DebugWorkItem
),
224 DPRINT ("Send a key\n");
226 if (!DevExt
->KeyboardData
.ClassService
)
229 ((PSERVICE_CALLBACK_ROUTINE
) DevExt
->KeyboardData
.ClassService
)(
230 DevExt
->KeyboardData
.ClassDeviceObject
,
231 DevExt
->KeyboardBuffer
,
232 DevExt
->KeyboardBuffer
+ KeysInBufferCopy
,
235 Irql
= KeAcquireInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
);
236 DevExt
->KeysInBuffer
-= KeysTransferred
;
237 KeReleaseInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
, Irql
);
240 /* You have to send the rate/delay in a somewhat awkward format */
241 static UCHAR
I8042GetTypematicByte(USHORT Rate
, USHORT Delay
)
247 } else if (Rate
> 26) {
250 ret
= TypematicTable
[Rate
];
255 } else if (Delay
< 625) {
257 } else if (Delay
< 875) {
265 * Process the keyboard internal device requests
266 * returns FALSE if it doesn't understand the
267 * call so someone else can handle it.
269 BOOLEAN STDCALL
I8042StartIoKbd(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
271 PIO_STACK_LOCATION Stk
;
272 PFDO_DEVICE_EXTENSION FdoDevExt
= DeviceObject
->DeviceExtension
;
273 PDEVICE_EXTENSION DevExt
= FdoDevExt
->PortDevExt
;
275 Stk
= IoGetCurrentIrpStackLocation(Irp
);
277 switch (Stk
->Parameters
.DeviceIoControl
.IoControlCode
) {
278 case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER
:
282 Stk
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
283 Stk
->Parameters
.DeviceIoControl
.InputBufferLength
,
287 case IOCTL_KEYBOARD_SET_INDICATORS
:
288 DevExt
->PacketBuffer
[0] = 0xED;
289 DevExt
->PacketBuffer
[1] = 0;
290 if (DevExt
->KeyboardIndicators
.LedFlags
& KEYBOARD_CAPS_LOCK_ON
)
291 DevExt
->PacketBuffer
[1] |= 0x04;
293 if (DevExt
->KeyboardIndicators
.LedFlags
& KEYBOARD_NUM_LOCK_ON
)
294 DevExt
->PacketBuffer
[1] |= 0x02;
296 if (DevExt
->KeyboardIndicators
.LedFlags
& KEYBOARD_SCROLL_LOCK_ON
)
297 DevExt
->PacketBuffer
[1] |= 0x01;
299 I8042StartPacket(DevExt
,
301 DevExt
->PacketBuffer
,
305 case IOCTL_KEYBOARD_SET_TYPEMATIC
:
306 DevExt
->PacketBuffer
[0] = 0xF3;
307 DevExt
->PacketBuffer
[1] = I8042GetTypematicByte(
308 DevExt
->KeyboardTypematic
.Rate
,
309 DevExt
->KeyboardTypematic
.Delay
);
311 I8042StartPacket(DevExt
,
313 DevExt
->PacketBuffer
,
325 * Runs the keyboard IOCTL_INTERNAL dispatch.
326 * Returns NTSTATUS_INVALID_DEVICE_REQUEST if it doesn't handle this request
327 * so someone else can have a try at it.
329 NTSTATUS STDCALL
I8042InternalDeviceControlKbd(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
331 PIO_STACK_LOCATION Stk
;
332 PFDO_DEVICE_EXTENSION FdoDevExt
= DeviceObject
->DeviceExtension
;
333 PDEVICE_EXTENSION DevExt
= FdoDevExt
->PortDevExt
;
335 DPRINT("InternalDeviceControl\n");
337 Irp
->IoStatus
.Information
= 0;
338 Stk
= IoGetCurrentIrpStackLocation(Irp
);
340 switch (Stk
->Parameters
.DeviceIoControl
.IoControlCode
) {
342 case IOCTL_INTERNAL_KEYBOARD_CONNECT
:
343 DPRINT("IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
344 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
<
345 sizeof(CONNECT_DATA
)) {
346 DPRINT1("Keyboard IOCTL_INTERNAL_KEYBOARD_CONNECT "
347 "invalid buffer size\n");
348 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
352 if (!DevExt
->KeyboardExists
) {
353 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_CONNECTED
;
357 if (DevExt
->KeyboardClaimed
) {
358 DPRINT1("IOCTL_INTERNAL_KEYBOARD_CONNECT: "
359 "Keyboard is already claimed\n");
360 Irp
->IoStatus
.Status
= STATUS_SHARING_VIOLATION
;
364 memcpy(&DevExt
->KeyboardData
,
365 Stk
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
366 sizeof(CONNECT_DATA
));
367 DevExt
->KeyboardHook
.IsrWritePort
= I8042IsrWritePortKbd
;
368 DevExt
->KeyboardHook
.QueueKeyboardPacket
=
369 I8042QueueKeyboardPacket
;
370 DevExt
->KeyboardHook
.CallContext
= DevExt
;
373 PIO_WORKITEM WorkItem
;
374 PI8042_HOOK_WORKITEM WorkItemData
;
376 WorkItem
= IoAllocateWorkItem(DeviceObject
);
378 DPRINT ("IOCTL_INTERNAL_KEYBOARD_CONNECT: "
379 "Can't allocate work item\n");
380 Irp
->IoStatus
.Status
=
381 STATUS_INSUFFICIENT_RESOURCES
;
385 WorkItemData
= ExAllocatePoolWithTag(
387 sizeof(I8042_HOOK_WORKITEM
),
390 DPRINT ("IOCTL_INTERNAL_KEYBOARD_CONNECT: "
391 "Can't allocate work item data\n");
392 Irp
->IoStatus
.Status
=
393 STATUS_INSUFFICIENT_RESOURCES
;
394 IoFreeWorkItem(WorkItem
);
397 WorkItemData
->WorkItem
= WorkItem
;
398 WorkItemData
->Target
=
399 DevExt
->KeyboardData
.ClassDeviceObject
;
400 WorkItemData
->Irp
= Irp
;
402 IoMarkIrpPending(Irp
);
403 IoQueueWorkItem(WorkItem
,
404 I8042SendHookWorkItem
,
408 Irp
->IoStatus
.Status
= STATUS_PENDING
;
412 case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER
:
413 DPRINT("IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER\n");
414 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
< 1) {
415 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
418 if (!DevExt
->KeyboardInterruptObject
) {
419 Irp
->IoStatus
.Status
= STATUS_DEVICE_NOT_READY
;
423 IoMarkIrpPending(Irp
);
424 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
425 Irp
->IoStatus
.Status
= STATUS_PENDING
;
428 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES
:
429 DPRINT("IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n");
430 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
431 sizeof(KEYBOARD_ATTRIBUTES
)) {
432 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_ATTRIBUTES "
433 "invalid buffer size\n");
434 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
437 memcpy(Irp
->AssociatedIrp
.SystemBuffer
,
438 &DevExt
->KeyboardAttributes
,
439 sizeof(KEYBOARD_ATTRIBUTES
));
441 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
443 case IOCTL_KEYBOARD_QUERY_INDICATORS
:
444 DPRINT("IOCTL_KEYBOARD_QUERY_INDICATORS\n");
445 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
446 sizeof(KEYBOARD_INDICATOR_PARAMETERS
)) {
447 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_INDICATORS "
448 "invalid buffer size\n");
449 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
452 memcpy(Irp
->AssociatedIrp
.SystemBuffer
,
453 &DevExt
->KeyboardIndicators
,
454 sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
456 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
458 case IOCTL_KEYBOARD_QUERY_TYPEMATIC
:
459 DPRINT("IOCTL_KEYBOARD_QUERY_TYPEMATIC\n");
460 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
461 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
)) {
462 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_TYPEMATIC "
463 "invalid buffer size\n");
464 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
467 memcpy(Irp
->AssociatedIrp
.SystemBuffer
,
468 &DevExt
->KeyboardTypematic
,
469 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
471 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
473 case IOCTL_KEYBOARD_SET_INDICATORS
:
474 DPRINT("IOCTL_KEYBOARD_SET_INDICATORS\n");
475 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
<
476 sizeof(KEYBOARD_INDICATOR_PARAMETERS
)) {
477 DPRINT("Keyboard IOCTL_KEYBOARD_SET_INDICTATORS "
478 "invalid buffer size\n");
479 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
483 memcpy(&DevExt
->KeyboardIndicators
,
484 Irp
->AssociatedIrp
.SystemBuffer
,
485 sizeof(KEYBOARD_INDICATOR_PARAMETERS
));
487 DPRINT("%x\n", DevExt
->KeyboardIndicators
.LedFlags
);
489 IoMarkIrpPending(Irp
);
490 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
491 Irp
->IoStatus
.Status
= STATUS_PENDING
;
494 case IOCTL_KEYBOARD_SET_TYPEMATIC
:
495 DPRINT("IOCTL_KEYBOARD_SET_TYPEMATIC\n");
496 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
<
497 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
)) {
498 DPRINT("Keyboard IOCTL_KEYBOARD_SET_TYPEMATIC "
499 "invalid buffer size\n");
500 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
504 memcpy(&DevExt
->KeyboardTypematic
,
505 Irp
->AssociatedIrp
.SystemBuffer
,
506 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS
));
508 IoMarkIrpPending(Irp
);
509 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
510 Irp
->IoStatus
.Status
= STATUS_PENDING
;
513 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
:
514 /* We should check the UnitID, but it's kind of pointless as
515 * all keyboards are supposed to have the same one
517 if (Stk
->Parameters
.DeviceIoControl
.OutputBufferLength
<
518 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
)) {
519 DPRINT("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: "
520 "invalid buffer size (expected)\n");
521 /* It's to query the buffer size */
522 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
525 Irp
->IoStatus
.Information
=
526 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
);
528 memcpy(Irp
->AssociatedIrp
.SystemBuffer
,
529 &IndicatorTranslation
,
530 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION
));
532 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
534 case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD
:
535 /* Nothing to do here */
536 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
539 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
544 return Irp
->IoStatus
.Status
;
547 /* This is all pretty confusing. There's more than one way to
548 * disable/enable the keyboard. You can send KBD_ENABLE to the
549 * keyboard, and it will start scanning keys. Sending KBD_DISABLE
550 * will disable the key scanning but also reset the parameters to
553 * You can also send 0xAE to the controller for enabling the
554 * keyboard clock line and 0xAD for disabling it. Then it'll
555 * automatically get turned on at the next command. The last
556 * way is by modifying the bit that drives the clock line in the
557 * 'command byte' of the controller. This is almost, but not quite,
558 * the same as the AE/AD thing. The difference can be used to detect
559 * some really old broken keyboard controllers which I hope won't be
562 * Anyway, disabling the keyboard helps the detection and it also
563 * clears the keyboard buffer and sets defaults which is what we
567 BOOLEAN STDCALL
I8042KeyboardEnable(PDEVICE_EXTENSION DevExt
)
569 DPRINT("Enabling keyboard\n");
570 if (STATUS_SUCCESS
!= I8042SynchWritePort(DevExt
,
574 DPRINT("Can't enable keyboard\n");
580 BOOLEAN STDCALL
I8042KeyboardDefaultsAndDisable(PDEVICE_EXTENSION DevExt
)
582 DPRINT("Disabling keyboard\n");
583 if (STATUS_SUCCESS
!= I8042SynchWritePort(DevExt
,
587 DPRINT("Can't disable keyboard\n");
593 BOOLEAN STDCALL
I8042KeyboardEnableInterrupt(PDEVICE_EXTENSION DevExt
)
598 DPRINT("Enabling keyboard interrupt\n");
600 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, KBD_READ_MODE
)) {
601 DPRINT1("Can't read i8042 mode\n");
605 Status
= I8042ReadDataWait(DevExt
, &Value
);
606 if (!NT_SUCCESS(Status
)) {
607 DPRINT1("No response after read i8042 mode\n");
611 Value
&= ~(0x10); // don't disable keyboard
612 Value
|= 0x01; // enable keyboard interrupts
614 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, KBD_WRITE_MODE
)) {
615 DPRINT1("Can't set i8042 mode\n");
619 if (!I8042Write(DevExt
, I8042_DATA_PORT
, Value
)) {
620 DPRINT1("Can't send i8042 mode\n");
627 BOOLEAN STDCALL
I8042DetectKeyboard(PDEVICE_EXTENSION DevExt
)
631 ULONG RetryCount
= 10;
633 DPRINT("Detecting keyboard\n");
635 I8042KeyboardDefaultsAndDisable(DevExt
);
638 Status
= I8042SynchWritePort(DevExt
, 0, KBD_GET_ID
, TRUE
);
639 } while (STATUS_TIMEOUT
== Status
&& RetryCount
--);
641 if (!NT_SUCCESS(Status
)) {
642 DPRINT1("Can't write GET_ID (%x)\n", Status
);
646 Status
= I8042ReadDataWait(DevExt
, &Value
);
647 if (!NT_SUCCESS(Status
)) {
648 DPRINT1("No response after GET_ID\n");
649 /* Could be an AT keyboard */
650 DevExt
->KeyboardIsAT
= TRUE
;
653 DevExt
->KeyboardIsAT
= FALSE
;
655 if (Value
!= 0xAB && Value
!= 0xAC) {
656 DPRINT("Bad ID: %x\n", Value
);
657 /* This is certainly not a keyboard */
661 DPRINT("Keyboard ID: %x", Value
);
663 Status
= I8042ReadDataWait(DevExt
, &Value
);
664 if (!NT_SUCCESS(Status
)) {
665 DPRINT("Partial ID\n");
669 DPRINT ("%x\n", Value
);
672 Status
= I8042SynchWritePort(DevExt
, 0, KBD_SET_LEDS
, TRUE
);
673 if (!NT_SUCCESS(Status
)) {
674 DPRINT("Can't write SET_LEDS (%x)\n", Status
);
677 Status
= I8042SynchWritePort(DevExt
, 0, 0, TRUE
);
678 if (!NT_SUCCESS(Status
)) {
679 DPRINT("Can't finish SET_LEDS (%x)\n", Status
);
683 // Turn on translation
685 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, KBD_READ_MODE
)) {
686 DPRINT1("Can't read i8042 mode\n");
690 Status
= I8042ReadDataWait(DevExt
, &Value
);
691 if (!NT_SUCCESS(Status
)) {
692 DPRINT1("No response after read i8042 mode\n");
696 Value
|= 0x40; // enable keyboard translation
698 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, KBD_WRITE_MODE
)) {
699 DPRINT1("Can't set i8042 mode\n");
703 if (!I8042Write(DevExt
, I8042_DATA_PORT
, Value
)) {
704 DPRINT1("Can't send i8042 mode\n");
713 KdpServiceDispatcher(ULONG Code
, PVOID Context1
, PVOID Context2
);
714 #define EnterDebugger ((PVOID)0x25)
716 static VOID STDCALL
I8042DebugWorkItem(PDEVICE_OBJECT DeviceObject
,
720 PFDO_DEVICE_EXTENSION FdoDevExt
= DeviceObject
->DeviceExtension
;
721 PDEVICE_EXTENSION DevExt
= FdoDevExt
->PortDevExt
;
723 Key
= InterlockedExchange((PLONG
)&DevExt
->DebugKey
, 0);
724 DPRINT("Debug key: %x\n", Key
);
730 /* We hope kernel would understand this. If
731 * that's not the case, nothing would happen.
733 KdpServiceDispatcher(TAG('R', 'o', 's', ' '), (PVOID
)Key
, NULL
);
734 #endif /* __REACTOS__ */