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