]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
IntelFrameworkModulePkg: Fix typos in comments
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2MouseDxe / CommPs2.c
CommitLineData
172870ef 1/** @file\r
2 PS2 Mouse Communication Interface.\r
f8cd287b 3 \r
180a5a35
HT
4Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
92a428e1 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
05fbd06d 9\r
92a428e1 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
05fbd06d 12\r
f8cd287b 13**/\r
05fbd06d 14\r
05fbd06d 15#include "Ps2Mouse.h"\r
16#include "CommPs2.h"\r
17\r
3ae99102 18UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 };\r
05fbd06d 19\r
3ae99102 20UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 };\r
05fbd06d 21\r
ff1fcef8 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
05fbd06d 30EFI_STATUS\r
31KbcSelfTest (\r
32 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
33 )\r
05fbd06d 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
ff1fcef8 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
05fbd06d 90EFI_STATUS\r
91KbcEnableAux (\r
92 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
93 )\r
05fbd06d 94{\r
95 //\r
96 // Send 8042 enable mouse command\r
97 //\r
98 return Out8042Command (IsaIo, ENABLE_AUX);\r
99}\r
100\r
ff1fcef8 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
05fbd06d 108EFI_STATUS\r
109KbcDisableAux (\r
110 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
111 )\r
05fbd06d 112{\r
113 //\r
114 // Send 8042 disable mouse command\r
115 //\r
116 return Out8042Command (IsaIo, DISABLE_AUX);\r
117}\r
118\r
ff1fcef8 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
05fbd06d 126EFI_STATUS\r
127KbcEnableKb (\r
128 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
129 )\r
05fbd06d 130{\r
131 //\r
132 // Send 8042 enable keyboard command\r
133 //\r
134 return Out8042Command (IsaIo, ENABLE_KB);\r
135}\r
136\r
ff1fcef8 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
05fbd06d 144EFI_STATUS\r
145KbcDisableKb (\r
146 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
147 )\r
05fbd06d 148{\r
149 //\r
150 // Send 8042 disable keyboard command\r
151 //\r
152 return Out8042Command (IsaIo, DISABLE_KB);\r
153}\r
154\r
ff1fcef8 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
05fbd06d 163EFI_STATUS\r
164CheckKbStatus (\r
165 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
166 OUT BOOLEAN *KeyboardEnable\r
167 )\r
05fbd06d 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
ff1fcef8 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
05fbd06d 203EFI_STATUS\r
204PS2MouseReset (\r
205 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
206 )\r
05fbd06d 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
ff1fcef8 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
05fbd06d 249EFI_STATUS\r
250PS2MouseSetSampleRate (\r
251 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
252 IN MOUSE_SR SampleRate\r
253 )\r
05fbd06d 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
ff1fcef8 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
05fbd06d 278EFI_STATUS\r
279PS2MouseSetResolution (\r
280 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
281 IN MOUSE_RE Resolution\r
282 )\r
05fbd06d 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
ff1fcef8 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
05fbd06d 307EFI_STATUS\r
308PS2MouseSetScaling (\r
309 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
310 IN MOUSE_SF Scaling\r
311 )\r
05fbd06d 312{\r
313 UINT8 Command;\r
314\r
f66d00ca 315 Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD);\r
05fbd06d 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
ff1fcef8 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
05fbd06d 330EFI_STATUS\r
331PS2MouseEnable (\r
332 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
333 )\r
05fbd06d 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
05fbd06d 342 Get mouse packet . Only care first 3 bytes\r
343\r
ff1fcef8 344 @param MouseDev Pointer of PS2 Mouse Private Data Structure \r
05fbd06d 345\r
ff1fcef8 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
05fbd06d 348\r
bcd70414 349**/\r
ff1fcef8 350EFI_STATUS\r
351PS2MouseGetPacket (\r
352 PS2_MOUSE_DEV *MouseDev\r
353 )\r
354\r
05fbd06d 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 (MouseDev->IsaIo);\r
382 Status = PS2MouseRead (MouseDev->IsaIo, &Data, &Count, State);\r
383 if (EFI_ERROR (Status)) {\r
384 KbcEnableAux (MouseDev->IsaIo);\r
385 return EFI_NOT_READY;\r
386 }\r
387\r
388 if (Count != 1) {\r
389 KbcEnableAux (MouseDev->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 (MouseDev->IsaIo, &KeyboardEnable);\r
398 KbcDisableKb (MouseDev->IsaIo);\r
399 KbcEnableAux (MouseDev->IsaIo);\r
400 }\r
401 break;\r
402\r
403 case PS2_READ_DATA_BYTE:\r
404 Count = 2;\r
405 Status = PS2MouseRead (MouseDev->IsaIo, (Packet + 1), &Count, State);\r
406 if (EFI_ERROR (Status)) {\r
407 if (KeyboardEnable) {\r
408 KbcEnableKb (MouseDev->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 (MouseDev->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 (MouseDev->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 MouseDev->State.RelativeMovementX += RelativeMovementX;\r
466 MouseDev->State.RelativeMovementY -= RelativeMovementY;\r
467 MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE);\r
468 MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE);\r
469 MouseDev->StateChanged = TRUE;\r
470\r
471 return EFI_SUCCESS;\r
472 }\r
473 }\r
474}\r
475\r
ff1fcef8 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
05fbd06d 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
05fbd06d 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
533//\r
534// 8042 I/O function\r
535//\r
ff1fcef8 536/**\r
537 I/O work flow of outing 8042 command.\r
538 \r
539 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
540 @param Command I/O command.\r
541 \r
70d3fe9d 542 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 543 @retval EFI_TIMEOUT Keyboard controller time out.\r
544**/\r
05fbd06d 545EFI_STATUS\r
546Out8042Command (\r
547 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
548 IN UINT8 Command\r
549 )\r
05fbd06d 550{\r
551 EFI_STATUS Status;\r
552 UINT8 Data;\r
553\r
554 //\r
555 // Wait keyboard controller input buffer empty\r
556 //\r
557 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
558 if (EFI_ERROR (Status)) {\r
559 return Status;\r
560 }\r
561 //\r
562 // Send command\r
563 //\r
564 Data = Command;\r
565 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
566\r
567 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
568 if (EFI_ERROR (Status)) {\r
569 return Status;\r
570 }\r
571\r
572 return EFI_SUCCESS;\r
573}\r
574\r
ff1fcef8 575/**\r
576 I/O work flow of outing 8042 data.\r
577 \r
578 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
579 @param Data Data value\r
580 \r
70d3fe9d 581 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 582 @retval EFI_TIMEOUT Keyboard controller time out.\r
583**/\r
05fbd06d 584EFI_STATUS\r
585Out8042Data (\r
586 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
587 IN UINT8 Data\r
588 )\r
05fbd06d 589{\r
590 EFI_STATUS Status;\r
172870ef 591 UINT8 Temp;\r
05fbd06d 592 //\r
593 // Wait keyboard controller input buffer empty\r
594 //\r
595 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
596 if (EFI_ERROR (Status)) {\r
597 return Status;\r
598 }\r
599\r
172870ef 600 Temp = Data;\r
601 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);\r
05fbd06d 602\r
603 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
604 if (EFI_ERROR (Status)) {\r
605 return Status;\r
606 }\r
607\r
608 return EFI_SUCCESS;\r
609}\r
610\r
ff1fcef8 611/**\r
612 I/O work flow of in 8042 data.\r
613 \r
614 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
615 @param Data Data value\r
616 \r
70d3fe9d 617 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 618 @retval EFI_TIMEOUT Keyboard controller time out.\r
619**/\r
05fbd06d 620EFI_STATUS\r
621In8042Data (\r
622 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
623 IN OUT UINT8 *Data\r
624 )\r
05fbd06d 625{\r
626 UINTN Delay;\r
172870ef 627 UINT8 Temp;\r
05fbd06d 628\r
629 Delay = TIMEOUT / 50;\r
630\r
631 do {\r
172870ef 632 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);\r
05fbd06d 633\r
634 //\r
635 // Check keyboard controller status bit 0(output buffer status)\r
636 //\r
172870ef 637 if ((Temp & KBC_OUTB) == KBC_OUTB) {\r
05fbd06d 638 break;\r
639 }\r
640\r
641 gBS->Stall (50);\r
642 Delay--;\r
172870ef 643 } while (Delay != 0);\r
05fbd06d 644\r
645 if (Delay == 0) {\r
646 return EFI_TIMEOUT;\r
647 }\r
648\r
649 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);\r
650\r
651 return EFI_SUCCESS;\r
652}\r
653\r
ff1fcef8 654/**\r
655 I/O work flow of outing 8042 Aux command.\r
656 \r
657 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
658 @param Command Aux I/O command\r
659 @param Resend Whether need resend the Aux command.\r
660 \r
70d3fe9d 661 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 662 @retval EFI_TIMEOUT Keyboard controller time out.\r
663**/\r
05fbd06d 664EFI_STATUS\r
665Out8042AuxCommand (\r
666 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
667 IN UINT8 Command,\r
668 IN BOOLEAN Resend\r
669 )\r
05fbd06d 670{\r
671 EFI_STATUS Status;\r
672 UINT8 Data;\r
673\r
674 //\r
675 // Wait keyboard controller input buffer empty\r
676 //\r
677 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
678 if (EFI_ERROR (Status)) {\r
679 return Status;\r
680 }\r
681 //\r
682 // Send write to auxiliary device command\r
683 //\r
684 Data = WRITE_AUX_DEV;\r
685 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
686\r
687 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
688 if (EFI_ERROR (Status)) {\r
689 return Status;\r
690 }\r
691 //\r
692 // Send auxiliary device command\r
693 //\r
694 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command);\r
695\r
696 //\r
697 // Read return code\r
698 //\r
699 Status = In8042AuxData (IsaIo, &Data);\r
700 if (EFI_ERROR (Status)) {\r
701 return Status;\r
702 }\r
703\r
704 if (Data == PS2_ACK) {\r
705 //\r
706 // Receive mouse acknowledge, command send success\r
707 //\r
708 return EFI_SUCCESS;\r
709\r
710 } else if (Resend) {\r
711 //\r
712 // Resend fail\r
713 //\r
714 return EFI_DEVICE_ERROR;\r
715\r
716 } else if (Data == PS2_RESEND) {\r
717 //\r
718 // Resend command\r
719 //\r
720 Status = Out8042AuxCommand (IsaIo, Command, TRUE);\r
721 if (EFI_ERROR (Status)) {\r
722 return Status;\r
723 }\r
724\r
725 } else {\r
726 //\r
727 // Invalid return code\r
728 //\r
729 return EFI_DEVICE_ERROR;\r
730\r
731 }\r
732\r
733 return EFI_SUCCESS;\r
734}\r
735\r
ff1fcef8 736/**\r
737 I/O work flow of outing 8042 Aux data.\r
738 \r
739 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
172870ef 740 @param Data Buffer holding return value\r
ff1fcef8 741 \r
70d3fe9d 742 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 743 @retval EFI_TIMEOUT Keyboard controller time out.\r
744**/\r
05fbd06d 745EFI_STATUS\r
746Out8042AuxData (\r
747 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
748 IN UINT8 Data\r
749 )\r
05fbd06d 750{\r
751 EFI_STATUS Status;\r
752 UINT8 Temp;\r
753 //\r
754 // Wait keyboard controller input buffer empty\r
755 //\r
756 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
757 if (EFI_ERROR (Status)) {\r
758 return Status;\r
759 }\r
760 //\r
761 // Send write to auxiliary device command\r
762 //\r
763 Temp = WRITE_AUX_DEV;\r
764 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);\r
765\r
766 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
767 if (EFI_ERROR (Status)) {\r
768 return Status;\r
769 }\r
770\r
771 Temp = Data;\r
772 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);\r
773\r
774 Status = WaitInputEmpty (IsaIo, TIMEOUT);\r
775 if (EFI_ERROR (Status)) {\r
776 return Status;\r
777 }\r
778\r
779 return EFI_SUCCESS;\r
780}\r
781\r
ff1fcef8 782/**\r
783 I/O work flow of in 8042 Aux data.\r
784 \r
785 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
786 @param Data Buffer holding return value.\r
787 \r
70d3fe9d 788 @retval EFI_SUCCESS Success to execute I/O work flow\r
ff1fcef8 789 @retval EFI_TIMEOUT Keyboard controller time out.\r
790**/\r
05fbd06d 791EFI_STATUS\r
792In8042AuxData (\r
793 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
794 IN OUT UINT8 *Data\r
795 )\r
05fbd06d 796{\r
797 EFI_STATUS Status;\r
798\r
799 //\r
800 // wait for output data\r
801 //\r
802 Status = WaitOutputFull (IsaIo, BAT_TIMEOUT);\r
803 if (EFI_ERROR (Status)) {\r
804 return Status;\r
805 }\r
806\r
807 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);\r
808\r
809 return EFI_SUCCESS;\r
810}\r
811\r
ff1fcef8 812\r
813/**\r
172870ef 814 Check keyboard controller status, if it is output buffer full and for auxiliary device.\r
ff1fcef8 815 \r
816 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
817 \r
818 @retval EFI_SUCCESS Keyboard controller is ready\r
819 @retval EFI_NOT_READY Keyboard controller is not ready\r
820**/\r
05fbd06d 821EFI_STATUS\r
822CheckForInput (\r
823 IN EFI_ISA_IO_PROTOCOL *IsaIo\r
824 )\r
05fbd06d 825{\r
826 UINT8 Data;\r
827\r
828 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
829\r
830 //\r
831 // Check keyboard controller status, if it is output buffer full and for auxiliary device\r
832 //\r
833 if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) {\r
834 return EFI_NOT_READY;\r
835 }\r
836\r
837 return EFI_SUCCESS;\r
838}\r
839\r
ff1fcef8 840/**\r
841 I/O work flow to wait input buffer empty in given time.\r
842 \r
843 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
844 @param Timeout Wating time.\r
845 \r
846 @retval EFI_TIMEOUT if input is still not empty in given time.\r
847 @retval EFI_SUCCESS input is empty.\r
848**/\r
05fbd06d 849EFI_STATUS\r
850WaitInputEmpty (\r
851 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
852 IN UINTN Timeout\r
853 )\r
05fbd06d 854{\r
855 UINTN Delay;\r
856 UINT8 Data;\r
857\r
858 Delay = Timeout / 50;\r
859\r
860 do {\r
861 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
862\r
863 //\r
864 // Check keyboard controller status bit 1(input buffer status)\r
865 //\r
866 if ((Data & KBC_INPB) == 0) {\r
867 break;\r
868 }\r
869\r
870 gBS->Stall (50);\r
871 Delay--;\r
172870ef 872 } while (Delay != 0);\r
05fbd06d 873\r
874 if (Delay == 0) {\r
875 return EFI_TIMEOUT;\r
876 }\r
877\r
878 return EFI_SUCCESS;\r
879}\r
880\r
ff1fcef8 881/**\r
882 I/O work flow to wait output buffer full in given time.\r
883 \r
884 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r
885 @param Timeout given time\r
886 \r
887 @retval EFI_TIMEOUT output is not full in given time\r
888 @retval EFI_SUCCESS output is full in given time.\r
889**/\r
05fbd06d 890EFI_STATUS\r
891WaitOutputFull (\r
892 IN EFI_ISA_IO_PROTOCOL *IsaIo,\r
893 IN UINTN Timeout\r
894 )\r
05fbd06d 895{\r
896 UINTN Delay;\r
897 UINT8 Data;\r
898\r
899 Delay = Timeout / 50;\r
900\r
901 do {\r
902 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r
903\r
904 //\r
905 // Check keyboard controller status bit 0(output buffer status)\r
906 // & bit5(output buffer for auxiliary device)\r
907 //\r
908 if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) {\r
909 break;\r
910 }\r
911\r
912 gBS->Stall (50);\r
913 Delay--;\r
172870ef 914 } while (Delay != 0);\r
05fbd06d 915\r
916 if (Delay == 0) {\r
917 return EFI_TIMEOUT;\r
918 }\r
919\r
920 return EFI_SUCCESS;\r
921}\r