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