]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2MouseDxe / CommPs2.c
CommitLineData
172870ef 1/** @file\r
2 PS2 Mouse Communication Interface.\r
0a6f4824
LG
3\r
4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
c0a00b14 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
05fbd06d 6\r
f8cd287b 7**/\r
05fbd06d 8\r
05fbd06d 9#include "Ps2Mouse.h"\r
10#include "CommPs2.h"\r
11\r
3ae99102 12UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 };\r
05fbd06d 13\r
3ae99102 14UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 };\r
05fbd06d 15\r
ff1fcef8 16/**\r
17 Issue self test command via IsaIo interface.\r
0a6f4824 18\r
ff1fcef8 19 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 20\r
ff1fcef8 21 @return EFI_SUCCESS Success to do keyboard self testing.\r
22 @return others Fail to do keyboard self testing.\r
23**/\r
05fbd06d 24EFI_STATUS\r
25KbcSelfTest (\r
26 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
27 )\r
05fbd06d 28{\r
29 EFI_STATUS Status;\r
30 UINT8 Data;\r
31\r
32 //\r
33 // Keyboard controller self test\r
34 //\r
35 Status = Out8042Command (IsaIo, SELF_TEST);\r
36 if (EFI_ERROR (Status)) {\r
37 return Status;\r
38 }\r
39 //\r
40 // Read return code\r
41 //\r
42 Status = In8042Data (IsaIo, &Data);\r
43 if (EFI_ERROR (Status)) {\r
44 return Status;\r
45 }\r
46\r
47 if (Data != 0x55) {\r
48 return EFI_DEVICE_ERROR;\r
49 }\r
50 //\r
51 // Set system flag\r
52 //\r
53 Status = Out8042Command (IsaIo, READ_CMD_BYTE);\r
54 if (EFI_ERROR (Status)) {\r
55 return Status;\r
56 }\r
57\r
58 Status = In8042Data (IsaIo, &Data);\r
59 if (EFI_ERROR (Status)) {\r
60 return Status;\r
61 }\r
62\r
63 Status = Out8042Command (IsaIo, WRITE_CMD_BYTE);\r
64 if (EFI_ERROR (Status)) {\r
65 return Status;\r
66 }\r
67\r
68 Data |= CMD_SYS_FLAG;\r
69 Status = Out8042Data (IsaIo, Data);\r
70 if (EFI_ERROR (Status)) {\r
71 return Status;\r
72 }\r
73\r
74 return EFI_SUCCESS;\r
75}\r
76\r
ff1fcef8 77/**\r
78 Issue command to enable keyboard AUX functionality.\r
0a6f4824 79\r
ff1fcef8 80 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 81\r
ff1fcef8 82 @return Status of command issuing.\r
83**/\r
05fbd06d 84EFI_STATUS\r
85KbcEnableAux (\r
86 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
87 )\r
05fbd06d 88{\r
89 //\r
90 // Send 8042 enable mouse command\r
91 //\r
92 return Out8042Command (IsaIo, ENABLE_AUX);\r
93}\r
94\r
ff1fcef8 95/**\r
96 Issue command to disable keyboard AUX functionality.\r
0a6f4824 97\r
ff1fcef8 98 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 99\r
ff1fcef8 100 @return Status of command issuing.\r
101**/\r
05fbd06d 102EFI_STATUS\r
103KbcDisableAux (\r
104 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
105 )\r
05fbd06d 106{\r
107 //\r
108 // Send 8042 disable mouse command\r
109 //\r
110 return Out8042Command (IsaIo, DISABLE_AUX);\r
111}\r
112\r
ff1fcef8 113/**\r
114 Issue command to enable keyboard.\r
0a6f4824 115\r
ff1fcef8 116 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 117\r
ff1fcef8 118 @return Status of command issuing.\r
119**/\r
05fbd06d 120EFI_STATUS\r
121KbcEnableKb (\r
122 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
123 )\r
05fbd06d 124{\r
125 //\r
126 // Send 8042 enable keyboard command\r
127 //\r
128 return Out8042Command (IsaIo, ENABLE_KB);\r
129}\r
130\r
ff1fcef8 131/**\r
132 Issue command to disable keyboard.\r
0a6f4824 133\r
ff1fcef8 134 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 135\r
ff1fcef8 136 @return Status of command issuing.\r
137**/\r
05fbd06d 138EFI_STATUS\r
139KbcDisableKb (\r
140 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
141 )\r
05fbd06d 142{\r
143 //\r
144 // Send 8042 disable keyboard command\r
145 //\r
146 return Out8042Command (IsaIo, DISABLE_KB);\r
147}\r
148\r
ff1fcef8 149/**\r
150 Issue command to check keyboard status.\r
0a6f4824 151\r
ff1fcef8 152 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
153 @param KeyboardEnable return whether keyboard is enable.\r
0a6f4824 154\r
ff1fcef8 155 @return Status of command issuing.\r
156**/\r
05fbd06d 157EFI_STATUS\r
158CheckKbStatus (\r
159 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
160 OUT BOOLEAN *KeyboardEnable\r
161 )\r
05fbd06d 162{\r
163 EFI_STATUS Status;\r
164 UINT8 Data;\r
165\r
166 //\r
167 // Send command to read KBC command byte\r
168 //\r
169 Status = Out8042Command (IsaIo, READ_CMD_BYTE);\r
170 if (EFI_ERROR (Status)) {\r
171 return Status;\r
172 }\r
173\r
174 Status = In8042Data (IsaIo, &Data);\r
175 if (EFI_ERROR (Status)) {\r
176 return Status;\r
177 }\r
178 //\r
179 // Check keyboard enable or not\r
180 //\r
181 if ((Data & CMD_KB_STS) == CMD_KB_DIS) {\r
182 *KeyboardEnable = FALSE;\r
183 } else {\r
184 *KeyboardEnable = TRUE;\r
185 }\r
186\r
187 return EFI_SUCCESS;\r
188}\r
189\r
ff1fcef8 190/**\r
191 Issue command to reset keyboard.\r
0a6f4824 192\r
ff1fcef8 193 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 194\r
ff1fcef8 195 @return Status of command issuing.\r
196**/\r
05fbd06d 197EFI_STATUS\r
198PS2MouseReset (\r
199 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
200 )\r
05fbd06d 201{\r
202 EFI_STATUS Status;\r
203 UINT8 Data;\r
204\r
205 Status = Out8042AuxCommand (IsaIo, RESET_CMD, FALSE);\r
206 if (EFI_ERROR (Status)) {\r
207 return Status;\r
208 }\r
209\r
210 Status = In8042AuxData (IsaIo, &Data);\r
211 if (EFI_ERROR (Status)) {\r
212 return Status;\r
213 }\r
214 //\r
215 // Check BAT Complete Code\r
216 //\r
217 if (Data != PS2MOUSE_BAT1) {\r
218 return EFI_DEVICE_ERROR;\r
219 }\r
220\r
221 Status = In8042AuxData (IsaIo, &Data);\r
222 if (EFI_ERROR (Status)) {\r
223 return Status;\r
224 }\r
225 //\r
226 // Check BAT Complete Code\r
227 //\r
228 if (Data != PS2MOUSE_BAT2) {\r
229 return EFI_DEVICE_ERROR;\r
230 }\r
231\r
232 return EFI_SUCCESS;\r
233}\r
234\r
ff1fcef8 235/**\r
236 Issue command to set mouse's sample rate\r
0a6f4824 237\r
ff1fcef8 238 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824
LG
239 @param SampleRate value of sample rate\r
240\r
ff1fcef8 241 @return Status of command issuing.\r
242**/\r
05fbd06d 243EFI_STATUS\r
244PS2MouseSetSampleRate (\r
245 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
246 IN MOUSE_SR SampleRate\r
247 )\r
05fbd06d 248{\r
249 EFI_STATUS Status;\r
250\r
251 //\r
252 // Send auxiliary command to set mouse sample rate\r
253 //\r
254 Status = Out8042AuxCommand (IsaIo, SETSR_CMD, FALSE);\r
255 if (EFI_ERROR (Status)) {\r
256 return Status;\r
257 }\r
258\r
259 Status = Out8042AuxData (IsaIo, SampleRateTbl[SampleRate]);\r
260\r
261 return Status;\r
262}\r
263\r
ff1fcef8 264/**\r
265 Issue command to set mouse's resolution.\r
0a6f4824 266\r
ff1fcef8 267 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
268 @param Resolution value of resolution\r
0a6f4824 269\r
ff1fcef8 270 @return Status of command issuing.\r
271**/\r
05fbd06d 272EFI_STATUS\r
273PS2MouseSetResolution (\r
274 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
275 IN MOUSE_RE Resolution\r
276 )\r
05fbd06d 277{\r
278 EFI_STATUS Status;\r
279\r
280 //\r
281 // Send auxiliary command to set mouse resolution\r
282 //\r
283 Status = Out8042AuxCommand (IsaIo, SETRE_CMD, FALSE);\r
284 if (EFI_ERROR (Status)) {\r
285 return Status;\r
286 }\r
287\r
288 Status = Out8042AuxData (IsaIo, ResolutionTbl[Resolution]);\r
289\r
290 return Status;\r
291}\r
292\r
ff1fcef8 293/**\r
294 Issue command to set mouse's scaling.\r
0a6f4824 295\r
ff1fcef8 296 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
297 @param Scaling value of scaling\r
0a6f4824 298\r
ff1fcef8 299 @return Status of command issuing.\r
300**/\r
05fbd06d 301EFI_STATUS\r
302PS2MouseSetScaling (\r
303 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
304 IN MOUSE_SF Scaling\r
305 )\r
05fbd06d 306{\r
307 UINT8 Command;\r
308\r
f66d00ca 309 Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD);\r
05fbd06d 310\r
311 //\r
312 // Send auxiliary command to set mouse scaling data\r
313 //\r
314 return Out8042AuxCommand (IsaIo, Command, FALSE);\r
315}\r
316\r
ff1fcef8 317/**\r
318 Issue command to enable Ps2 mouse.\r
0a6f4824 319\r
ff1fcef8 320 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 321\r
ff1fcef8 322 @return Status of command issuing.\r
323**/\r
05fbd06d 324EFI_STATUS\r
325PS2MouseEnable (\r
326 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
327 )\r
05fbd06d 328{\r
329 //\r
330 // Send auxiliary command to enable mouse\r
331 //\r
332 return Out8042AuxCommand (IsaIo, ENABLE_CMD, FALSE);\r
333}\r
334\r
bcd70414 335/**\r
05fbd06d 336 Get mouse packet . Only care first 3 bytes\r
337\r
0a6f4824 338 @param MouseDev Pointer of PS2 Mouse Private Data Structure\r
05fbd06d 339\r
ff1fcef8 340 @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet\r
341 @retval EFI_SUCCESS The data packet is gotten successfully.\r
05fbd06d 342\r
bcd70414 343**/\r
ff1fcef8 344EFI_STATUS\r
345PS2MouseGetPacket (\r
346 PS2_MOUSE_DEV *MouseDev\r
347 )\r
348\r
05fbd06d 349{\r
350 EFI_STATUS Status;\r
351 BOOLEAN KeyboardEnable;\r
352 UINT8 Packet[PS2_PACKET_LENGTH];\r
353 UINT8 Data;\r
354 UINTN Count;\r
355 UINTN State;\r
356 INT16 RelativeMovementX;\r
357 INT16 RelativeMovementY;\r
358 BOOLEAN LButton;\r
359 BOOLEAN RButton;\r
360\r
361 KeyboardEnable = FALSE;\r
362 Count = 1;\r
363 State = PS2_READ_BYTE_ONE;\r
364\r
365 //\r
366 // State machine to get mouse packet\r
367 //\r
368 while (1) {\r
369\r
370 switch (State) {\r
371 case PS2_READ_BYTE_ONE:\r
372 //\r
373 // Read mouse first byte data, if failed, immediately return\r
374 //\r
375 KbcDisableAux (MouseDev->IsaIo);\r
376 Status = PS2MouseRead (MouseDev->IsaIo, &Data, &Count, State);\r
377 if (EFI_ERROR (Status)) {\r
378 KbcEnableAux (MouseDev->IsaIo);\r
379 return EFI_NOT_READY;\r
380 }\r
381\r
382 if (Count != 1) {\r
383 KbcEnableAux (MouseDev->IsaIo);\r
384 return EFI_NOT_READY;\r
385 }\r
386\r
387 if (IS_PS2_SYNC_BYTE (Data)) {\r
388 Packet[0] = Data;\r
389 State = PS2_READ_DATA_BYTE;\r
390\r
391 CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable);\r
392 KbcDisableKb (MouseDev->IsaIo);\r
393 KbcEnableAux (MouseDev->IsaIo);\r
394 }\r
395 break;\r
396\r
397 case PS2_READ_DATA_BYTE:\r
398 Count = 2;\r
399 Status = PS2MouseRead (MouseDev->IsaIo, (Packet + 1), &Count, State);\r
400 if (EFI_ERROR (Status)) {\r
401 if (KeyboardEnable) {\r
402 KbcEnableKb (MouseDev->IsaIo);\r
403 }\r
404\r
405 return EFI_NOT_READY;\r
406 }\r
407\r
408 if (Count != 2) {\r
409 if (KeyboardEnable) {\r
410 KbcEnableKb (MouseDev->IsaIo);\r
411 }\r
412\r
413 return EFI_NOT_READY;\r
414 }\r
415\r
416 State = PS2_PROCESS_PACKET;\r
417 break;\r
418\r
419 case PS2_PROCESS_PACKET:\r
420 if (KeyboardEnable) {\r
421 KbcEnableKb (MouseDev->IsaIo);\r
422 }\r
423 //\r
424 // Decode the packet\r
425 //\r
426 RelativeMovementX = Packet[1];\r
427 RelativeMovementY = Packet[2];\r
428 //\r
0a6f4824
LG
429 // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0\r
430 // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn\r
431 // Byte 1 | 8 bit X Movement\r
432 // Byte 2 | 8 bit Y Movement\r
433 //\r
05fbd06d 434 // 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.\r
435 // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement.\r
436 //\r
437 //\r
438 // First, Clear X and Y high 8 bits\r
439 //\r
0a6f4824
LG
440 RelativeMovementX = (INT16) (RelativeMovementX & 0xFF);\r
441 RelativeMovementY = (INT16) (RelativeMovementY & 0xFF);\r
05fbd06d 442 //\r
443 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff\r
444 //\r
445 if ((Packet[0] & 0x10) != 0) {\r
446 RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00);\r
447 }\r
448 if ((Packet[0] & 0x20) != 0) {\r
449 RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00);\r
450 }\r
451\r
0a6f4824 452\r
05fbd06d 453 RButton = (UINT8) (Packet[0] & 0x2);\r
454 LButton = (UINT8) (Packet[0] & 0x1);\r
455\r
456 //\r
457 // Update mouse state\r
458 //\r
459 MouseDev->State.RelativeMovementX += RelativeMovementX;\r
460 MouseDev->State.RelativeMovementY -= RelativeMovementY;\r
461 MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE);\r
462 MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE);\r
463 MouseDev->StateChanged = TRUE;\r
464\r
465 return EFI_SUCCESS;\r
466 }\r
467 }\r
468}\r
469\r
ff1fcef8 470/**\r
471 Read data via IsaIo protocol with given number.\r
0a6f4824 472\r
ff1fcef8 473 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
474 @param Buffer Buffer receive data of mouse\r
475 @param BufSize The size of buffer\r
476 @param State Check input or read data\r
0a6f4824 477\r
ff1fcef8 478 @return status of reading mouse data.\r
479**/\r
05fbd06d 480EFI_STATUS\r
481PS2MouseRead (\r
482 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
483 OUT VOID *Buffer,\r
484 IN OUT UINTN *BufSize,\r
485 IN UINTN State\r
486 )\r
05fbd06d 487{\r
488 EFI_STATUS Status;\r
489 UINTN BytesRead;\r
490\r
491 Status = EFI_SUCCESS;\r
492 BytesRead = 0;\r
493\r
494 if (State == PS2_READ_BYTE_ONE) {\r
495 //\r
496 // Check input for mouse\r
497 //\r
498 Status = CheckForInput (IsaIo);\r
499\r
500 if (EFI_ERROR (Status)) {\r
501 return Status;\r
502 }\r
503 }\r
504\r
505 while (BytesRead < *BufSize) {\r
506\r
507 Status = WaitOutputFull (IsaIo, TIMEOUT);\r
508 if (EFI_ERROR (Status)) {\r
509 break;\r
510 }\r
511\r
512 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Buffer);\r
513\r
514 BytesRead++;\r
515 Buffer = (UINT8 *) Buffer + 1;\r
516 }\r
517 //\r
518 // Verify the correct number of bytes read\r
519 //\r
520 if (BytesRead == 0 || BytesRead != *BufSize) {\r
521 Status = EFI_NOT_FOUND;\r
522 }\r
523\r
524 *BufSize = BytesRead;\r
525 return Status;\r
526}\r
527//\r
528// 8042 I/O function\r
529//\r
ff1fcef8 530/**\r
531 I/O work flow of outing 8042 command.\r
0a6f4824 532\r
ff1fcef8 533 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
534 @param Command I/O command.\r
0a6f4824 535\r
70d3fe9d 536 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 537 @retval EFI_TIMEOUT Keyboard controller time out.\r
538**/\r
05fbd06d 539EFI_STATUS\r
540Out8042Command (\r
541 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
542 IN UINT8 Command\r
543 )\r
05fbd06d 544{\r
545 EFI_STATUS Status;\r
546 UINT8 Data;\r
547\r
548 //\r
549 // Wait keyboard controller input buffer empty\r
550 //\r
551 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
552 if (EFI_ERROR (Status)) {\r
553 return Status;\r
554 }\r
555 //\r
556 // Send command\r
557 //\r
558 Data = Command;\r
559 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
560\r
561 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
562 if (EFI_ERROR (Status)) {\r
563 return Status;\r
564 }\r
565\r
566 return EFI_SUCCESS;\r
567}\r
568\r
ff1fcef8 569/**\r
570 I/O work flow of outing 8042 data.\r
0a6f4824 571\r
ff1fcef8 572 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
573 @param Data Data value\r
0a6f4824 574\r
70d3fe9d 575 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 576 @retval EFI_TIMEOUT Keyboard controller time out.\r
577**/\r
05fbd06d 578EFI_STATUS\r
579Out8042Data (\r
580 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
581 IN UINT8 Data\r
582 )\r
05fbd06d 583{\r
584 EFI_STATUS Status;\r
172870ef 585 UINT8 Temp;\r
05fbd06d 586 //\r
587 // Wait keyboard controller input buffer empty\r
588 //\r
589 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
590 if (EFI_ERROR (Status)) {\r
591 return Status;\r
592 }\r
593\r
172870ef 594 Temp = Data;\r
595 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);\r
05fbd06d 596\r
597 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
598 if (EFI_ERROR (Status)) {\r
599 return Status;\r
600 }\r
601\r
602 return EFI_SUCCESS;\r
603}\r
604\r
ff1fcef8 605/**\r
606 I/O work flow of in 8042 data.\r
0a6f4824 607\r
ff1fcef8 608 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
609 @param Data Data value\r
0a6f4824 610\r
70d3fe9d 611 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 612 @retval EFI_TIMEOUT Keyboard controller time out.\r
613**/\r
05fbd06d 614EFI_STATUS\r
615In8042Data (\r
616 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
617 IN OUT UINT8 *Data\r
618 )\r
05fbd06d 619{\r
620 UINTN Delay;\r
172870ef 621 UINT8 Temp;\r
05fbd06d 622\r
623 Delay = TIMEOUT / 50;\r
624\r
625 do {\r
172870ef 626 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);\r
05fbd06d 627\r
628 //\r
629 // Check keyboard controller status bit 0(output buffer status)\r
630 //\r
172870ef 631 if ((Temp & KBC_OUTB) == KBC_OUTB) {\r
05fbd06d 632 break;\r
633 }\r
634\r
635 gBS->Stall (50);\r
636 Delay--;\r
172870ef 637 } while (Delay != 0);\r
05fbd06d 638\r
639 if (Delay == 0) {\r
640 return EFI_TIMEOUT;\r
641 }\r
642\r
643 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);\r
644\r
645 return EFI_SUCCESS;\r
646}\r
647\r
ff1fcef8 648/**\r
649 I/O work flow of outing 8042 Aux command.\r
0a6f4824 650\r
ff1fcef8 651 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
652 @param Command Aux I/O command\r
653 @param Resend Whether need resend the Aux command.\r
0a6f4824 654\r
70d3fe9d 655 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 656 @retval EFI_TIMEOUT Keyboard controller time out.\r
657**/\r
05fbd06d 658EFI_STATUS\r
659Out8042AuxCommand (\r
660 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
661 IN UINT8 Command,\r
662 IN BOOLEAN Resend\r
663 )\r
05fbd06d 664{\r
665 EFI_STATUS Status;\r
666 UINT8 Data;\r
667\r
668 //\r
669 // Wait keyboard controller input buffer empty\r
670 //\r
671 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
672 if (EFI_ERROR (Status)) {\r
673 return Status;\r
674 }\r
675 //\r
676 // Send write to auxiliary device command\r
677 //\r
678 Data = WRITE_AUX_DEV;\r
679 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
680\r
681 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
682 if (EFI_ERROR (Status)) {\r
683 return Status;\r
684 }\r
685 //\r
686 // Send auxiliary device command\r
687 //\r
688 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command);\r
689\r
690 //\r
691 // Read return code\r
692 //\r
693 Status = In8042AuxData (IsaIo, &Data);\r
694 if (EFI_ERROR (Status)) {\r
695 return Status;\r
696 }\r
697\r
698 if (Data == PS2_ACK) {\r
699 //\r
700 // Receive mouse acknowledge, command send success\r
701 //\r
702 return EFI_SUCCESS;\r
703\r
704 } else if (Resend) {\r
705 //\r
706 // Resend fail\r
707 //\r
708 return EFI_DEVICE_ERROR;\r
709\r
710 } else if (Data == PS2_RESEND) {\r
711 //\r
712 // Resend command\r
713 //\r
714 Status = Out8042AuxCommand (IsaIo, Command, TRUE);\r
715 if (EFI_ERROR (Status)) {\r
716 return Status;\r
717 }\r
718\r
719 } else {\r
720 //\r
721 // Invalid return code\r
722 //\r
723 return EFI_DEVICE_ERROR;\r
724\r
725 }\r
726\r
727 return EFI_SUCCESS;\r
728}\r
729\r
ff1fcef8 730/**\r
731 I/O work flow of outing 8042 Aux data.\r
0a6f4824 732\r
ff1fcef8 733 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
172870ef 734 @param Data Buffer holding return value\r
0a6f4824 735\r
70d3fe9d 736 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 737 @retval EFI_TIMEOUT Keyboard controller time out.\r
738**/\r
05fbd06d 739EFI_STATUS\r
740Out8042AuxData (\r
741 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
742 IN UINT8 Data\r
743 )\r
05fbd06d 744{\r
745 EFI_STATUS Status;\r
746 UINT8 Temp;\r
747 //\r
748 // Wait keyboard controller input buffer empty\r
749 //\r
750 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
751 if (EFI_ERROR (Status)) {\r
752 return Status;\r
753 }\r
754 //\r
755 // Send write to auxiliary device command\r
756 //\r
757 Temp = WRITE_AUX_DEV;\r
758 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);\r
759\r
760 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
761 if (EFI_ERROR (Status)) {\r
762 return Status;\r
763 }\r
764\r
765 Temp = Data;\r
766 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);\r
767\r
768 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
769 if (EFI_ERROR (Status)) {\r
770 return Status;\r
771 }\r
772\r
773 return EFI_SUCCESS;\r
774}\r
775\r
ff1fcef8 776/**\r
777 I/O work flow of in 8042 Aux data.\r
0a6f4824 778\r
ff1fcef8 779 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
780 @param Data Buffer holding return value.\r
0a6f4824 781\r
70d3fe9d 782 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 783 @retval EFI_TIMEOUT Keyboard controller time out.\r
784**/\r
05fbd06d 785EFI_STATUS\r
786In8042AuxData (\r
787 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
788 IN OUT UINT8 *Data\r
789 )\r
05fbd06d 790{\r
791 EFI_STATUS Status;\r
792\r
793 //\r
794 // wait for output data\r
795 //\r
796 Status = WaitOutputFull (IsaIo, BAT_TIMEOUT);\r
797 if (EFI_ERROR (Status)) {\r
798 return Status;\r
799 }\r
800\r
801 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);\r
802\r
803 return EFI_SUCCESS;\r
804}\r
805\r
ff1fcef8 806\r
807/**\r
172870ef 808 Check keyboard controller status, if it is output buffer full and for auxiliary device.\r
0a6f4824 809\r
ff1fcef8 810 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
0a6f4824 811\r
ff1fcef8 812 @retval EFI_SUCCESS Keyboard controller is ready\r
813 @retval EFI_NOT_READY Keyboard controller is not ready\r
814**/\r
05fbd06d 815EFI_STATUS\r
816CheckForInput (\r
817 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
818 )\r
05fbd06d 819{\r
820 UINT8 Data;\r
821\r
822 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
823\r
824 //\r
825 // Check keyboard controller status, if it is output buffer full and for auxiliary device\r
826 //\r
827 if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) {\r
828 return EFI_NOT_READY;\r
829 }\r
830\r
831 return EFI_SUCCESS;\r
832}\r
833\r
ff1fcef8 834/**\r
835 I/O work flow to wait input buffer empty in given time.\r
0a6f4824 836\r
ff1fcef8 837 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
838 @param Timeout Wating time.\r
0a6f4824 839\r
ff1fcef8 840 @retval EFI_TIMEOUT if input is still not empty in given time.\r
841 @retval EFI_SUCCESS input is empty.\r
842**/\r
05fbd06d 843EFI_STATUS\r
844WaitInputEmpty (\r
845 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
846 IN UINTN Timeout\r
847 )\r
05fbd06d 848{\r
849 UINTN Delay;\r
850 UINT8 Data;\r
851\r
852 Delay = Timeout / 50;\r
853\r
854 do {\r
855 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
856\r
857 //\r
858 // Check keyboard controller status bit 1(input buffer status)\r
859 //\r
860 if ((Data & KBC_INPB) == 0) {\r
861 break;\r
862 }\r
863\r
864 gBS->Stall (50);\r
865 Delay--;\r
172870ef 866 } while (Delay != 0);\r
05fbd06d 867\r
868 if (Delay == 0) {\r
869 return EFI_TIMEOUT;\r
870 }\r
871\r
872 return EFI_SUCCESS;\r
873}\r
874\r
ff1fcef8 875/**\r
876 I/O work flow to wait output buffer full in given time.\r
0a6f4824 877\r
ff1fcef8 878 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
879 @param Timeout given time\r
0a6f4824 880\r
ff1fcef8 881 @retval EFI_TIMEOUT output is not full in given time\r
882 @retval EFI_SUCCESS output is full in given time.\r
883**/\r
05fbd06d 884EFI_STATUS\r
885WaitOutputFull (\r
886 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
887 IN UINTN Timeout\r
888 )\r
05fbd06d 889{\r
890 UINTN Delay;\r
891 UINT8 Data;\r
892\r
893 Delay = Timeout / 50;\r
894\r
895 do {\r
896 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
897\r
898 //\r
899 // Check keyboard controller status bit 0(output buffer status)\r
900 // & bit5(output buffer for auxiliary device)\r
901 //\r
902 if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) {\r
903 break;\r
904 }\r
905\r
906 gBS->Stall (50);\r
907 Delay--;\r
172870ef 908 } while (Delay != 0);\r
05fbd06d 909\r
910 if (Delay == 0) {\r
911 return EFI_TIMEOUT;\r
912 }\r
913\r
914 return EFI_SUCCESS;\r
915}\r