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