3 Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
19 PS2 Mouse Communication Interface
27 // Include common header file for this module.
29 #include "CommonHeader.h"
34 UINT8 SampleRateTbl
[MAX_SR
] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 };
36 UINT8 ResolutionTbl
[MAX_CMR
] = { 0, 1, 2, 3 };
40 IN EFI_ISA_IO_PROTOCOL
*IsaIo
46 GC_TODO: Add function description
50 IsaIo - GC_TODO: add argument description
54 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
55 EFI_SUCCESS - GC_TODO: Add description for return value
63 // Keyboard controller self test
65 Status
= Out8042Command (IsaIo
, SELF_TEST
);
66 if (EFI_ERROR (Status
)) {
72 Status
= In8042Data (IsaIo
, &Data
);
73 if (EFI_ERROR (Status
)) {
78 return EFI_DEVICE_ERROR
;
83 Status
= Out8042Command (IsaIo
, READ_CMD_BYTE
);
84 if (EFI_ERROR (Status
)) {
88 Status
= In8042Data (IsaIo
, &Data
);
89 if (EFI_ERROR (Status
)) {
93 Status
= Out8042Command (IsaIo
, WRITE_CMD_BYTE
);
94 if (EFI_ERROR (Status
)) {
99 Status
= Out8042Data (IsaIo
, Data
);
100 if (EFI_ERROR (Status
)) {
109 IN EFI_ISA_IO_PROTOCOL
*IsaIo
115 GC_TODO: Add function description
119 IsaIo - GC_TODO: add argument description
123 GC_TODO: add return values
128 // Send 8042 enable mouse command
130 return Out8042Command (IsaIo
, ENABLE_AUX
);
135 IN EFI_ISA_IO_PROTOCOL
*IsaIo
141 GC_TODO: Add function description
145 IsaIo - GC_TODO: add argument description
149 GC_TODO: add return values
154 // Send 8042 disable mouse command
156 return Out8042Command (IsaIo
, DISABLE_AUX
);
161 IN EFI_ISA_IO_PROTOCOL
*IsaIo
167 GC_TODO: Add function description
171 IsaIo - GC_TODO: add argument description
175 GC_TODO: add return values
180 // Send 8042 enable keyboard command
182 return Out8042Command (IsaIo
, ENABLE_KB
);
187 IN EFI_ISA_IO_PROTOCOL
*IsaIo
193 GC_TODO: Add function description
197 IsaIo - GC_TODO: add argument description
201 GC_TODO: add return values
206 // Send 8042 disable keyboard command
208 return Out8042Command (IsaIo
, DISABLE_KB
);
213 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
214 OUT BOOLEAN
*KeyboardEnable
220 GC_TODO: Add function description
224 IsaIo - GC_TODO: add argument description
225 KeyboardEnable - GC_TODO: add argument description
229 EFI_SUCCESS - GC_TODO: Add description for return value
237 // Send command to read KBC command byte
239 Status
= Out8042Command (IsaIo
, READ_CMD_BYTE
);
240 if (EFI_ERROR (Status
)) {
244 Status
= In8042Data (IsaIo
, &Data
);
245 if (EFI_ERROR (Status
)) {
249 // Check keyboard enable or not
251 if ((Data
& CMD_KB_STS
) == CMD_KB_DIS
) {
252 *KeyboardEnable
= FALSE
;
254 *KeyboardEnable
= TRUE
;
262 IN EFI_ISA_IO_PROTOCOL
*IsaIo
268 GC_TODO: Add function description
272 IsaIo - GC_TODO: add argument description
276 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
277 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
278 EFI_SUCCESS - GC_TODO: Add description for return value
285 Status
= Out8042AuxCommand (IsaIo
, RESET_CMD
, FALSE
);
286 if (EFI_ERROR (Status
)) {
290 Status
= In8042AuxData (IsaIo
, &Data
);
291 if (EFI_ERROR (Status
)) {
295 // Check BAT Complete Code
297 if (Data
!= PS2MOUSE_BAT1
) {
298 return EFI_DEVICE_ERROR
;
301 Status
= In8042AuxData (IsaIo
, &Data
);
302 if (EFI_ERROR (Status
)) {
306 // Check BAT Complete Code
308 if (Data
!= PS2MOUSE_BAT2
) {
309 return EFI_DEVICE_ERROR
;
316 PS2MouseSetSampleRate (
317 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
318 IN MOUSE_SR SampleRate
324 GC_TODO: Add function description
328 IsaIo - GC_TODO: add argument description
329 SampleRate - GC_TODO: add argument description
333 GC_TODO: add return values
340 // Send auxiliary command to set mouse sample rate
342 Status
= Out8042AuxCommand (IsaIo
, SETSR_CMD
, FALSE
);
343 if (EFI_ERROR (Status
)) {
347 Status
= Out8042AuxData (IsaIo
, SampleRateTbl
[SampleRate
]);
353 PS2MouseSetResolution (
354 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
355 IN MOUSE_RE Resolution
361 GC_TODO: Add function description
365 IsaIo - GC_TODO: add argument description
366 Resolution - GC_TODO: add argument description
370 GC_TODO: add return values
377 // Send auxiliary command to set mouse resolution
379 Status
= Out8042AuxCommand (IsaIo
, SETRE_CMD
, FALSE
);
380 if (EFI_ERROR (Status
)) {
384 Status
= Out8042AuxData (IsaIo
, ResolutionTbl
[Resolution
]);
391 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
398 GC_TODO: Add function description
402 IsaIo - GC_TODO: add argument description
403 Scaling - GC_TODO: add argument description
407 GC_TODO: add return values
413 Command
= (UINT8
) (Scaling
== SF1
? SETSF1_CMD
: SETSF2_CMD
);
416 // Send auxiliary command to set mouse scaling data
418 return Out8042AuxCommand (IsaIo
, Command
, FALSE
);
423 IN EFI_ISA_IO_PROTOCOL
*IsaIo
429 GC_TODO: Add function description
433 IsaIo - GC_TODO: add argument description
437 GC_TODO: add return values
442 // Send auxiliary command to enable mouse
444 return Out8042AuxCommand (IsaIo
, ENABLE_CMD
, FALSE
);
449 PS2_MOUSE_DEV
*MouseDev
455 Get mouse packet . Only care first 3 bytes
459 MouseDev - Pointer of PS2 Mouse Private Data Structure
463 EFI_NOT_READY - Mouse Device not ready to input data packet, or some error happened during getting the packet
464 EFI_SUCCESS - The data packet is gotten successfully.
469 BOOLEAN KeyboardEnable
;
470 UINT8 Packet
[PS2_PACKET_LENGTH
];
474 INT16 RelativeMovementX
;
475 INT16 RelativeMovementY
;
479 KeyboardEnable
= FALSE
;
481 State
= PS2_READ_BYTE_ONE
;
484 // State machine to get mouse packet
489 case PS2_READ_BYTE_ONE
:
491 // Read mouse first byte data, if failed, immediately return
493 KbcDisableAux (MouseDev
->IsaIo
);
494 Status
= PS2MouseRead (MouseDev
->IsaIo
, &Data
, &Count
, State
);
495 if (EFI_ERROR (Status
)) {
496 KbcEnableAux (MouseDev
->IsaIo
);
497 return EFI_NOT_READY
;
501 KbcEnableAux (MouseDev
->IsaIo
);
502 return EFI_NOT_READY
;
505 if (IS_PS2_SYNC_BYTE (Data
)) {
507 State
= PS2_READ_DATA_BYTE
;
509 CheckKbStatus (MouseDev
->IsaIo
, &KeyboardEnable
);
510 KbcDisableKb (MouseDev
->IsaIo
);
511 KbcEnableAux (MouseDev
->IsaIo
);
515 case PS2_READ_DATA_BYTE
:
517 Status
= PS2MouseRead (MouseDev
->IsaIo
, (Packet
+ 1), &Count
, State
);
518 if (EFI_ERROR (Status
)) {
519 if (KeyboardEnable
) {
520 KbcEnableKb (MouseDev
->IsaIo
);
523 return EFI_NOT_READY
;
527 if (KeyboardEnable
) {
528 KbcEnableKb (MouseDev
->IsaIo
);
531 return EFI_NOT_READY
;
534 State
= PS2_PROCESS_PACKET
;
537 case PS2_PROCESS_PACKET
:
538 if (KeyboardEnable
) {
539 KbcEnableKb (MouseDev
->IsaIo
);
544 RelativeMovementX
= Packet
[1];
545 RelativeMovementY
= Packet
[2];
547 // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0
548 // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn
549 // Byte 1 | 8 bit X Movement
550 // Byte 2 | 8 bit Y Movement
552 // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission.
553 // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement.
556 // First, Clear X and Y high 8 bits
558 RelativeMovementX
= (INT16
) (RelativeMovementX
& 0xFF);
559 RelativeMovementY
= (INT16
) (RelativeMovementY
& 0xFF);
561 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff
563 if ((Packet
[0] & 0x10) != 0) {
564 RelativeMovementX
= (INT16
) (RelativeMovementX
| 0xFF00);
566 if ((Packet
[0] & 0x20) != 0) {
567 RelativeMovementY
= (INT16
) (RelativeMovementY
| 0xFF00);
571 RButton
= (UINT8
) (Packet
[0] & 0x2);
572 LButton
= (UINT8
) (Packet
[0] & 0x1);
575 // Update mouse state
577 MouseDev
->State
.RelativeMovementX
+= RelativeMovementX
;
578 MouseDev
->State
.RelativeMovementY
-= RelativeMovementY
;
579 MouseDev
->State
.RightButton
= (UINT8
) (RButton
? TRUE
: FALSE
);
580 MouseDev
->State
.LeftButton
= (UINT8
) (LButton
? TRUE
: FALSE
);
581 MouseDev
->StateChanged
= TRUE
;
590 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
592 IN OUT UINTN
*BufSize
,
599 GC_TODO: Add function description
603 IsaIo - GC_TODO: add argument description
604 Buffer - GC_TODO: add argument description
605 BufSize - GC_TODO: add argument description
606 State - GC_TODO: add argument description
610 GC_TODO: add return values
617 Status
= EFI_SUCCESS
;
620 if (State
== PS2_READ_BYTE_ONE
) {
622 // Check input for mouse
624 Status
= CheckForInput (IsaIo
);
626 if (EFI_ERROR (Status
)) {
631 while (BytesRead
< *BufSize
) {
633 Status
= WaitOutputFull (IsaIo
, TIMEOUT
);
634 if (EFI_ERROR (Status
)) {
638 IsaIo
->Io
.Read (IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1, Buffer
);
641 Buffer
= (UINT8
*) Buffer
+ 1;
644 // Verify the correct number of bytes read
646 if (BytesRead
== 0 || BytesRead
!= *BufSize
) {
647 Status
= EFI_NOT_FOUND
;
650 *BufSize
= BytesRead
;
658 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
665 GC_TODO: Add function description
669 IsaIo - GC_TODO: add argument description
670 Command - GC_TODO: add argument description
674 EFI_SUCCESS - GC_TODO: Add description for return value
682 // Wait keyboard controller input buffer empty
684 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
685 if (EFI_ERROR (Status
)) {
692 IsaIo
->Io
.Write (IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1, &Data
);
694 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
695 if (EFI_ERROR (Status
)) {
704 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
711 GC_TODO: Add function description
715 IsaIo - GC_TODO: add argument description
716 Data - GC_TODO: add argument description
720 EFI_SUCCESS - GC_TODO: Add description for return value
727 // Wait keyboard controller input buffer empty
729 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
730 if (EFI_ERROR (Status
)) {
735 IsaIo
->Io
.Write (IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1, &temp
);
737 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
738 if (EFI_ERROR (Status
)) {
747 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
754 GC_TODO: Add function description
758 IsaIo - GC_TODO: add argument description
759 Data - GC_TODO: add argument description
763 EFI_TIMEOUT - GC_TODO: Add description for return value
764 EFI_SUCCESS - GC_TODO: Add description for return value
771 Delay
= TIMEOUT
/ 50;
774 IsaIo
->Io
.Read (IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1, &temp
);
777 // Check keyboard controller status bit 0(output buffer status)
779 if ((temp
& KBC_OUTB
) == KBC_OUTB
) {
791 IsaIo
->Io
.Read (IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1, Data
);
798 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
806 GC_TODO: Add function description
810 IsaIo - GC_TODO: add argument description
811 Command - GC_TODO: add argument description
812 Resend - GC_TODO: add argument description
816 EFI_SUCCESS - GC_TODO: Add description for return value
817 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
818 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
819 EFI_SUCCESS - GC_TODO: Add description for return value
827 // Wait keyboard controller input buffer empty
829 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
830 if (EFI_ERROR (Status
)) {
834 // Send write to auxiliary device command
836 Data
= WRITE_AUX_DEV
;
837 IsaIo
->Io
.Write (IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1, &Data
);
839 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
840 if (EFI_ERROR (Status
)) {
844 // Send auxiliary device command
846 IsaIo
->Io
.Write (IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1, &Command
);
851 Status
= In8042AuxData (IsaIo
, &Data
);
852 if (EFI_ERROR (Status
)) {
856 if (Data
== PS2_ACK
) {
858 // Receive mouse acknowledge, command send success
866 return EFI_DEVICE_ERROR
;
868 } else if (Data
== PS2_RESEND
) {
872 Status
= Out8042AuxCommand (IsaIo
, Command
, TRUE
);
873 if (EFI_ERROR (Status
)) {
879 // Invalid return code
881 return EFI_DEVICE_ERROR
;
890 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
897 GC_TODO: Add function description
901 IsaIo - GC_TODO: add argument description
902 Data - GC_TODO: add argument description
906 EFI_SUCCESS - GC_TODO: Add description for return value
913 // Wait keyboard controller input buffer empty
915 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
916 if (EFI_ERROR (Status
)) {
920 // Send write to auxiliary device command
922 Temp
= WRITE_AUX_DEV
;
923 IsaIo
->Io
.Write (IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1, &Temp
);
925 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
926 if (EFI_ERROR (Status
)) {
931 IsaIo
->Io
.Write (IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1, &Temp
);
933 Status
= WaitInputEmpty (IsaIo
, TIMEOUT
);
934 if (EFI_ERROR (Status
)) {
943 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
950 GC_TODO: Add function description
954 IsaIo - GC_TODO: add argument description
955 Data - GC_TODO: add argument description
959 EFI_SUCCESS - GC_TODO: Add description for return value
966 // wait for output data
968 Status
= WaitOutputFull (IsaIo
, BAT_TIMEOUT
);
969 if (EFI_ERROR (Status
)) {
973 IsaIo
->Io
.Read (IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1, Data
);
980 IN EFI_ISA_IO_PROTOCOL
*IsaIo
986 GC_TODO: Add function description
990 IsaIo - GC_TODO: add argument description
994 EFI_NOT_READY - GC_TODO: Add description for return value
995 EFI_SUCCESS - GC_TODO: Add description for return value
1001 IsaIo
->Io
.Read (IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1, &Data
);
1004 // Check keyboard controller status, if it is output buffer full and for auxiliary device
1006 if ((Data
& (KBC_OUTB
| KBC_AUXB
)) != (KBC_OUTB
| KBC_AUXB
)) {
1007 return EFI_NOT_READY
;
1015 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1020 Routine Description:
1022 GC_TODO: Add function description
1026 IsaIo - GC_TODO: add argument description
1027 Timeout - GC_TODO: add argument description
1031 EFI_TIMEOUT - GC_TODO: Add description for return value
1032 EFI_SUCCESS - GC_TODO: Add description for return value
1039 Delay
= Timeout
/ 50;
1042 IsaIo
->Io
.Read (IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1, &Data
);
1045 // Check keyboard controller status bit 1(input buffer status)
1047 if ((Data
& KBC_INPB
) == 0) {
1064 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1069 Routine Description:
1071 GC_TODO: Add function description
1075 IsaIo - GC_TODO: add argument description
1076 Timeout - GC_TODO: add argument description
1080 EFI_TIMEOUT - GC_TODO: Add description for return value
1081 EFI_SUCCESS - GC_TODO: Add description for return value
1088 Delay
= Timeout
/ 50;
1091 IsaIo
->Io
.Read (IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1, &Data
);
1094 // Check keyboard controller status bit 0(output buffer status)
1095 // & bit5(output buffer for auxiliary device)
1097 if ((Data
& (KBC_OUTB
| KBC_AUXB
)) == (KBC_OUTB
| KBC_AUXB
)) {