]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseAbsolutePointerDxe/CommPs2.c
Update the copyright notice format
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2MouseAbsolutePointerDxe / CommPs2.c
CommitLineData
18a73eb7 1/** @file\r
2 PS2 Mouse Communication Interface.\r
afd0fe22 3 \r
180a5a35
HT
4Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>\r
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
24 \r
25 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
26 \r
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
85 \r
86 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
87 \r
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
103 \r
104 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
105 \r
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
121 \r
122 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
123 \r
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
139 \r
140 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
141 \r
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
157 \r
158 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
159 @param KeyboardEnable return whether keyboard is enable.\r
160 \r
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
198 \r
199 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
200 \r
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
243 \r
244 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
245 @param SampleRate value of sample rate \r
246 \r
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
272 \r
273 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
274 @param Resolution value of resolution\r
275 \r
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
301 \r
302 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
303 @param Scaling value of scaling\r
304 \r
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
325 \r
326 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
327 \r
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
18a73eb7 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
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
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
446 RelativeMovementX = (INT16) (RelativeMovementX & 0xFF); \r
447 RelativeMovementY = (INT16) (RelativeMovementY & 0xFF); \r
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
458 \r
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
478 \r
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
483 \r
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
539 \r
540 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
541 @param Command I/O command.\r
542 \r
543 @retval EFI_SUCCESS Success to excute I/O work flow\r
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
578 \r
579 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
580 @param Data Data value\r
581 \r
582 @retval EFI_SUCCESS Success to excute I/O work flow\r
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
614 \r
615 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
616 @param Data Data value\r
617 \r
618 @retval EFI_SUCCESS Success to excute I/O work flow\r
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
657 \r
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
661 \r
662 @retval EFI_SUCCESS Success to excute I/O work flow\r
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
739 \r
740 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
18a73eb7 741 @param Data Buffer holding return value \r
bcd70414 742 \r
18a73eb7 743 @retval EFI_SUCCESS Success to excute 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
785 \r
786 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
787 @param Data Buffer holding return value.\r
788 \r
789 @retval EFI_SUCCESS Success to excute I/O work flow\r
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
bcd70414 816 \r
817 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
818 \r
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
843 \r
844 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
845 @param Timeout Wating time.\r
846 \r
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
884 \r
885 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
886 @param Timeout given time\r
887 \r
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