mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 00:36:31 +00:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5111 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			2056 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2056 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**@file
 | 
						|
  PS/2 Keyboard driver
 | 
						|
  Routines that access 8042 keyboard controller
 | 
						|
 | 
						|
Copyright (c) 2006 - 2007, Intel Corporation
 | 
						|
All rights reserved. This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
//
 | 
						|
// Include common header file for this module.
 | 
						|
//
 | 
						|
#include "Ps2Keyboard.h"
 | 
						|
 | 
						|
//
 | 
						|
// Function declarations
 | 
						|
//
 | 
						|
STATIC
 | 
						|
UINT8
 | 
						|
KeyReadDataRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
KeyWriteDataRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
KeyWriteCommandRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
KeyboardError (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV*ConsoleIn,
 | 
						|
  IN CHAR16                 *ErrMsg // should be a unicode string
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
GetScancodeBufHead (
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
 | 
						|
  IN UINT32                Count,
 | 
						|
  OUT UINT8                *Buf
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
PopScancodeBufHead (
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
 | 
						|
  IN UINT32                Count,
 | 
						|
  OUT UINT8                *Buf
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
KeyboardWrite (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
KeyboardCommand (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  );
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
KeyboardWaitForValue (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Value
 | 
						|
  );
 | 
						|
 | 
						|
STATIC struct {
 | 
						|
  UINT8  ScanCode;
 | 
						|
  UINT16  EfiScanCode;
 | 
						|
  CHAR16  UnicodeChar;
 | 
						|
  CHAR16  ShiftUnicodeChar;
 | 
						|
}
 | 
						|
ConvertKeyboardScanCodeToEfiKey[] = {
 | 
						|
 | 
						|
  {
 | 
						|
    0x01,  //   Escape
 | 
						|
    SCAN_ESC,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x02,
 | 
						|
    SCAN_NULL,
 | 
						|
    '1',
 | 
						|
    '!'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x03,
 | 
						|
    SCAN_NULL,
 | 
						|
    '2',
 | 
						|
    '@'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x04,
 | 
						|
    SCAN_NULL,
 | 
						|
    '3',
 | 
						|
    '#'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x05,
 | 
						|
    SCAN_NULL,
 | 
						|
    '4',
 | 
						|
    '$'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x06,
 | 
						|
    SCAN_NULL,
 | 
						|
    '5',
 | 
						|
    '%'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x07,
 | 
						|
    SCAN_NULL,
 | 
						|
    '6',
 | 
						|
    '^'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x08,
 | 
						|
    SCAN_NULL,
 | 
						|
    '7',
 | 
						|
    '&'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x09,
 | 
						|
    SCAN_NULL,
 | 
						|
    '8',
 | 
						|
    '*'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0A,
 | 
						|
    SCAN_NULL,
 | 
						|
    '9',
 | 
						|
    '('
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0B,
 | 
						|
    SCAN_NULL,
 | 
						|
    '0',
 | 
						|
    ')'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0C,
 | 
						|
    SCAN_NULL,
 | 
						|
    '-',
 | 
						|
    '_'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0D,
 | 
						|
    SCAN_NULL,
 | 
						|
    '=',
 | 
						|
    '+'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0E, //  BackSpace
 | 
						|
    SCAN_NULL,
 | 
						|
    0x08,
 | 
						|
    0x08
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x0F, //  Tab
 | 
						|
    SCAN_NULL,
 | 
						|
    0x09,
 | 
						|
    0x09
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x10,
 | 
						|
    SCAN_NULL,
 | 
						|
    'q',
 | 
						|
    'Q'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x11,
 | 
						|
    SCAN_NULL,
 | 
						|
    'w',
 | 
						|
    'W'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x12,
 | 
						|
    SCAN_NULL,
 | 
						|
    'e',
 | 
						|
    'E'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x13,
 | 
						|
    SCAN_NULL,
 | 
						|
    'r',
 | 
						|
    'R'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x14,
 | 
						|
    SCAN_NULL,
 | 
						|
    't',
 | 
						|
    'T'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x15,
 | 
						|
    SCAN_NULL,
 | 
						|
    'y',
 | 
						|
    'Y'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x16,
 | 
						|
    SCAN_NULL,
 | 
						|
    'u',
 | 
						|
    'U'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x17,
 | 
						|
    SCAN_NULL,
 | 
						|
    'i',
 | 
						|
    'I'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x18,
 | 
						|
    SCAN_NULL,
 | 
						|
    'o',
 | 
						|
    'O'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x19,
 | 
						|
    SCAN_NULL,
 | 
						|
    'p',
 | 
						|
    'P'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1a,
 | 
						|
    SCAN_NULL,
 | 
						|
    '[',
 | 
						|
    '{'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1b,
 | 
						|
    SCAN_NULL,
 | 
						|
    ']',
 | 
						|
    '}'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1c, //   Enter
 | 
						|
    SCAN_NULL,
 | 
						|
    0x0d,
 | 
						|
    0x0d
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1d,
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1e,
 | 
						|
    SCAN_NULL,
 | 
						|
    'a',
 | 
						|
    'A'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x1f,
 | 
						|
    SCAN_NULL,
 | 
						|
    's',
 | 
						|
    'S'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x20,
 | 
						|
    SCAN_NULL,
 | 
						|
    'd',
 | 
						|
    'D'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x21,
 | 
						|
    SCAN_NULL,
 | 
						|
    'f',
 | 
						|
    'F'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x22,
 | 
						|
    SCAN_NULL,
 | 
						|
    'g',
 | 
						|
    'G'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x23,
 | 
						|
    SCAN_NULL,
 | 
						|
    'h',
 | 
						|
    'H'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x24,
 | 
						|
    SCAN_NULL,
 | 
						|
    'j',
 | 
						|
    'J'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x25,
 | 
						|
    SCAN_NULL,
 | 
						|
    'k',
 | 
						|
    'K'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x26,
 | 
						|
    SCAN_NULL,
 | 
						|
    'l',
 | 
						|
    'L'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x27,
 | 
						|
    SCAN_NULL,
 | 
						|
    ';',
 | 
						|
    ':'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x28,
 | 
						|
    SCAN_NULL,
 | 
						|
    '\'',
 | 
						|
    '"'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x29,
 | 
						|
    SCAN_NULL,
 | 
						|
    '`',
 | 
						|
    '~'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2a, //   Left Shift
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2b,
 | 
						|
    SCAN_NULL,
 | 
						|
    '\\',
 | 
						|
    '|'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2c,
 | 
						|
    SCAN_NULL,
 | 
						|
    'z',
 | 
						|
    'Z'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2d,
 | 
						|
    SCAN_NULL,
 | 
						|
    'x',
 | 
						|
    'X'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2e,
 | 
						|
    SCAN_NULL,
 | 
						|
    'c',
 | 
						|
    'C'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x2f,
 | 
						|
    SCAN_NULL,
 | 
						|
    'v',
 | 
						|
    'V'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x30,
 | 
						|
    SCAN_NULL,
 | 
						|
    'b',
 | 
						|
    'B'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x31,
 | 
						|
    SCAN_NULL,
 | 
						|
    'n',
 | 
						|
    'N'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x32,
 | 
						|
    SCAN_NULL,
 | 
						|
    'm',
 | 
						|
    'M'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x33,
 | 
						|
    SCAN_NULL,
 | 
						|
    ',',
 | 
						|
    '<'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x34,
 | 
						|
    SCAN_NULL,
 | 
						|
    '.',
 | 
						|
    '>'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x35,
 | 
						|
    SCAN_NULL,
 | 
						|
    '/',
 | 
						|
    '?'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x36, //Right Shift
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x37, // Numeric Keypad *
 | 
						|
    SCAN_NULL,
 | 
						|
    '*',
 | 
						|
    '*'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x38,  //Left Alt/Extended Right Alt
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x39,
 | 
						|
    SCAN_NULL,
 | 
						|
    ' ',
 | 
						|
    ' '
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3A, //CapsLock
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3B,
 | 
						|
    SCAN_F1,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3C,
 | 
						|
    SCAN_F2,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3D,
 | 
						|
    SCAN_F3,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3E,
 | 
						|
    SCAN_F4,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x3F,
 | 
						|
    SCAN_F5,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x40,
 | 
						|
    SCAN_F6,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x41,
 | 
						|
    SCAN_F7,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x42,
 | 
						|
    SCAN_F8,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x43,
 | 
						|
    SCAN_F9,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x44,
 | 
						|
    SCAN_F10,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x45, // NumLock
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x46, //  ScrollLock
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x47,
 | 
						|
    SCAN_HOME,
 | 
						|
    '7',
 | 
						|
    '7'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x48,
 | 
						|
    SCAN_UP,
 | 
						|
    '8',
 | 
						|
    '8'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x49,
 | 
						|
    SCAN_PAGE_UP,
 | 
						|
    '9',
 | 
						|
    '9'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4a,
 | 
						|
    SCAN_NULL,
 | 
						|
    '-',
 | 
						|
    '-'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4b,
 | 
						|
    SCAN_LEFT,
 | 
						|
    '4',
 | 
						|
    '4'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4c, //  Numeric Keypad 5
 | 
						|
    SCAN_NULL,
 | 
						|
    '5',
 | 
						|
    '5'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4d,
 | 
						|
    SCAN_RIGHT,
 | 
						|
    '6',
 | 
						|
    '6'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4e,
 | 
						|
    SCAN_NULL,
 | 
						|
    '+',
 | 
						|
    '+'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x4f,
 | 
						|
    SCAN_END,
 | 
						|
    '1',
 | 
						|
    '1'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x50,
 | 
						|
    SCAN_DOWN,
 | 
						|
    '2',
 | 
						|
    '2'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x51,
 | 
						|
    SCAN_PAGE_DOWN,
 | 
						|
    '3',
 | 
						|
    '3'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x52,
 | 
						|
    SCAN_INSERT,
 | 
						|
    '0',
 | 
						|
    '0'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x53,
 | 
						|
    SCAN_DELETE,
 | 
						|
    '.',
 | 
						|
    '.'
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x57,
 | 
						|
    SCAN_F11,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x58,
 | 
						|
    SCAN_F12,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },
 | 
						|
  {
 | 
						|
    0x5B,  //Left LOGO
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },  
 | 
						|
  {
 | 
						|
    0x5C,  //Right LOGO
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },  
 | 
						|
  {
 | 
						|
    0x5D,  //Menu key
 | 
						|
    SCAN_NULL,
 | 
						|
    0x00,
 | 
						|
    0x00
 | 
						|
  },    
 | 
						|
  {
 | 
						|
    TABLE_END,
 | 
						|
    TABLE_END,
 | 
						|
    SCAN_NULL,
 | 
						|
    SCAN_NULL
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// The WaitForValue time out
 | 
						|
//
 | 
						|
STATIC UINTN  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
 | 
						|
 | 
						|
/**
 | 
						|
  Read data register 
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
 | 
						|
  @return return the value 
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINT8
 | 
						|
KeyReadDataRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | 
						|
  UINT8                               Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use IsaIo protocol to perform IO operations
 | 
						|
  //
 | 
						|
  IsaIo = ConsoleIn->IsaIo;
 | 
						|
 | 
						|
  IsaIo->Io.Read (
 | 
						|
              IsaIo,
 | 
						|
              EfiIsaIoWidthUint8,
 | 
						|
              ConsoleIn->DataRegisterAddress,
 | 
						|
              1,
 | 
						|
              &Data
 | 
						|
              );
 | 
						|
 | 
						|
  return Data;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write data register
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      value wanted to be written
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
KeyWriteDataRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use IsaIo protocol to perform IO operations
 | 
						|
  //
 | 
						|
  IsaIo = ConsoleIn->IsaIo;
 | 
						|
 | 
						|
  IsaIo->Io.Write (
 | 
						|
              IsaIo,
 | 
						|
              EfiIsaIoWidthUint8,
 | 
						|
              ConsoleIn->DataRegisterAddress,
 | 
						|
              1,
 | 
						|
              &Data
 | 
						|
              );
 | 
						|
 | 
						|
  //
 | 
						|
  // outp(ConsoleIn->DataRegisterAddress, Data);
 | 
						|
  //
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read status register
 | 
						|
 | 
						|
  @param ConsoleIn  Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
 | 
						|
  @return value in status register
 | 
						|
 | 
						|
**/
 | 
						|
UINT8
 | 
						|
KeyReadStatusRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | 
						|
  UINT8                               Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use IsaIo protocol to perform IO operations
 | 
						|
  //
 | 
						|
  IsaIo = ConsoleIn->IsaIo;
 | 
						|
 | 
						|
  IsaIo->Io.Read (
 | 
						|
              IsaIo,
 | 
						|
              EfiIsaIoWidthUint8,
 | 
						|
              ConsoleIn->StatusRegisterAddress,
 | 
						|
              1,
 | 
						|
              &Data
 | 
						|
              );
 | 
						|
 | 
						|
  return Data;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Write command register 
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      The value wanted to be written
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
KeyWriteCommandRegister (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use IsaIo protocol to perform IO operations
 | 
						|
  //
 | 
						|
  IsaIo = ConsoleIn->IsaIo;
 | 
						|
 | 
						|
  IsaIo->Io.Write (
 | 
						|
              IsaIo,
 | 
						|
              EfiIsaIoWidthUint8,
 | 
						|
              ConsoleIn->CommandRegisterAddress,
 | 
						|
              1,
 | 
						|
              &Data
 | 
						|
              );
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Display error message
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param ErrMsg    Unicode string of error message
 | 
						|
  
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
KeyboardError (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN CHAR16                  *ErrMsg
 | 
						|
  )
 | 
						|
{
 | 
						|
  ConsoleIn->KeyboardErr = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // gST -> ConOut -> OutputString (gST -> ConOut, L"Keyboard Driver: ");
 | 
						|
  // gST -> ConOut -> OutputString (gST -> ConOut, ErrMsg);
 | 
						|
  //
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Timer event handler: read a series of scancodes from 8042
 | 
						|
  and put them into memory scancode buffer.
 | 
						|
  it read as much scancodes to either fill
 | 
						|
  the memory buffer or empty the keyboard buffer.
 | 
						|
  It is registered as running under TPL_NOTIFY
 | 
						|
 | 
						|
  @param Event - The timer event
 | 
						|
  @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
KeyboardTimerHandler (
 | 
						|
  IN EFI_EVENT    Event,
 | 
						|
  IN VOID         *Context
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  UINT8                   Data;
 | 
						|
  EFI_TPL                 OldTpl;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
 | 
						|
 | 
						|
  ConsoleIn = Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
 | 
						|
    //
 | 
						|
    // Leave critical section and return
 | 
						|
    //
 | 
						|
    gBS->RestoreTPL (OldTpl);
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that
 | 
						|
  // KB is not connected to system. If KB is not connected to system, driver will find there's  something
 | 
						|
  // error in the following code and wait for the input buffer empty, this waiting time shoulb be  short enough since
 | 
						|
  // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
 | 
						|
  // Just skip the 'resend' process simply.
 | 
						|
  //
 | 
						|
 | 
						|
  Data = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // if there is no key present, just return
 | 
						|
  //
 | 
						|
  if ((KeyReadStatusRegister (Context) & 0x21) != 0x1) {
 | 
						|
    //
 | 
						|
    // Leave critical section and return
 | 
						|
    //
 | 
						|
    gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read one byte of the scan code and store it into the memory buffer
 | 
						|
  //
 | 
						|
  if (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT) {
 | 
						|
 | 
						|
    Data = KeyReadDataRegister (Context);
 | 
						|
    //
 | 
						|
    // put the scancode into the memory scancode buffer
 | 
						|
    //
 | 
						|
    ConsoleIn->ScancodeBufCount++;
 | 
						|
    ConsoleIn->ScancodeBufEndPos++;
 | 
						|
    if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {
 | 
						|
      ConsoleIn->ScancodeBufEndPos = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Data;
 | 
						|
 | 
						|
    //
 | 
						|
    // Handle Alt+Ctrl+Del Key combination
 | 
						|
    //
 | 
						|
    switch (Data) {
 | 
						|
    case SCANCODE_CTRL_MAKE:
 | 
						|
      ConsoleIn->Ctrled = TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_CTRL_BREAK:
 | 
						|
      ConsoleIn->Ctrled = FALSE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_ALT_MAKE:
 | 
						|
      ConsoleIn->Alted = TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_ALT_BREAK:
 | 
						|
      ConsoleIn->Alted = FALSE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // if Alt+Ctrl+Del, Reboot the System
 | 
						|
    //
 | 
						|
    if (ConsoleIn->Ctrled && ConsoleIn->Alted && Data == 0x53) {
 | 
						|
      gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Leave critical section and return
 | 
						|
  //
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read several bytes from the scancode buffer without removing them.
 | 
						|
  This function is called to see if there are enough bytes of scancode
 | 
						|
  representing a single key.
 | 
						|
 | 
						|
  @param Count - Number of bytes to be read
 | 
						|
  @param Buf - Store the results
 | 
						|
 | 
						|
  @retval EFI_SUCCESS success to scan the keyboard code
 | 
						|
  @retval EFI_NOT_READY invalid parameter
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
GetScancodeBufHead (
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV    *ConsoleIn,
 | 
						|
  IN UINT32                  Count,
 | 
						|
  OUT UINT8                  *Buf
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  Index;
 | 
						|
  UINT32  Pos;
 | 
						|
 | 
						|
  Index = 0;
 | 
						|
  Pos   = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // check the valid range of parameter 'Count'
 | 
						|
  //
 | 
						|
  if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // retrieve the values
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Count; Index++) {
 | 
						|
 | 
						|
    if (Index == 0) {
 | 
						|
 | 
						|
      Pos = ConsoleIn->ScancodeBufStartPos;
 | 
						|
    } else {
 | 
						|
 | 
						|
      Pos = Pos + 1;
 | 
						|
      if (Pos >= KEYBOARD_BUFFER_MAX_COUNT) {
 | 
						|
        Pos = 0;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Buf[Index] = ConsoleIn->ScancodeBuf[Pos];
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Read & remove several bytes from the scancode buffer.
 | 
						|
  This function is usually called after GetScancodeBufHead()
 | 
						|
 | 
						|
  @param Count - Number of bytes to be read
 | 
						|
  @param Buf - Store the results
 | 
						|
 | 
						|
  @retval EFI_SUCCESS success to scan the keyboard code
 | 
						|
  @retval EFI_NOT_READY invalid parameter
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
PopScancodeBufHead (
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV   *ConsoleIn,
 | 
						|
  IN UINT32                 Count,
 | 
						|
  OUT UINT8                 *Buf
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  Index;
 | 
						|
 | 
						|
  Index = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the valid range of parameter 'Count'
 | 
						|
  //
 | 
						|
  if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Retrieve and remove the values
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Count; Index++) {
 | 
						|
 | 
						|
    if (Index != 0) {
 | 
						|
 | 
						|
      ConsoleIn->ScancodeBufStartPos++;
 | 
						|
      if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {
 | 
						|
        ConsoleIn->ScancodeBufStartPos = 0;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Buf[Index] = ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufStartPos];
 | 
						|
    ConsoleIn->ScancodeBufCount--;
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleIn->ScancodeBufStartPos++;
 | 
						|
  if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {
 | 
						|
    ConsoleIn->ScancodeBufStartPos = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read key value 
 | 
						|
 | 
						|
  @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      - Pointer to outof buffer for keeping key value
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT Status resigter time out
 | 
						|
  @retval EFI_SUCCESS Success to read keyboard
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KeyboardRead (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
 | 
						|
  OUT UINT8                   *Data
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  RegFilled;
 | 
						|
 | 
						|
  TimeOut   = 0;
 | 
						|
  RegFilled = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // wait till output buffer full then perform the read
 | 
						|
  //
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
 | 
						|
      RegFilled = 1;
 | 
						|
      *Data     = KeyReadDataRegister (ConsoleIn);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->Stall (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!RegFilled) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  write key to keyboard
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      value wanted to be written
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT - GC_TODO: Add description for return value
 | 
						|
  @retval EFI_SUCCESS - GC_TODO: Add description for return value
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
KeyboardWrite (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  RegEmptied;
 | 
						|
 | 
						|
  TimeOut     = 0;
 | 
						|
  RegEmptied  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // wait for input buffer empty
 | 
						|
  //
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
 | 
						|
      RegEmptied = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->Stall (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!RegEmptied) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Write it
 | 
						|
  //
 | 
						|
  KeyWriteDataRegister (ConsoleIn, Data);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Issue keyboard command
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Data      The buff holding the command 
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT Keyboard is not ready to issuing 
 | 
						|
  @retval EFI_SUCCESS Success to issue keyboard command
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
KeyboardCommand (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  RegEmptied;
 | 
						|
 | 
						|
  TimeOut     = 0;
 | 
						|
  RegEmptied  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Wait For Input Buffer Empty
 | 
						|
  //
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
 | 
						|
      RegEmptied = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->Stall (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!RegEmptied) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // issue the command
 | 
						|
  //
 | 
						|
  KeyWriteCommandRegister (ConsoleIn, Data);
 | 
						|
 | 
						|
  //
 | 
						|
  // Wait For Input Buffer Empty again
 | 
						|
  //
 | 
						|
  RegEmptied = 0;
 | 
						|
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
    if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
 | 
						|
      RegEmptied = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->Stall (30);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!RegEmptied) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  wait for a specific value to be presented on
 | 
						|
  8042 Data register by keyboard and then read it,
 | 
						|
  used in keyboard commands ack
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  @param Value     the value wanted to be waited.
 | 
						|
 | 
						|
  @retval EFI_TIMEOUT Fail to get specific value in given time
 | 
						|
  @retval EFI_SUCCESS Success to get specific value in given time.
 | 
						|
  
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
KeyboardWaitForValue (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN UINT8                   Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8   Data;
 | 
						|
  UINT32  TimeOut;
 | 
						|
  UINT32  SumTimeOut;
 | 
						|
  UINT32  GotIt;
 | 
						|
 | 
						|
  GotIt       = 0;
 | 
						|
  TimeOut     = 0;
 | 
						|
  SumTimeOut  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure the initial value of 'Data' is different from 'Value'
 | 
						|
  //
 | 
						|
  Data = 0;
 | 
						|
  if (Data == Value) {
 | 
						|
    Data = 1;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Read from 8042 (multiple times if needed)
 | 
						|
  // until the expected value appears
 | 
						|
  // use SumTimeOut to control the iteration
 | 
						|
  //
 | 
						|
  while (1) {
 | 
						|
    //
 | 
						|
    // Perform a read
 | 
						|
    //
 | 
						|
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
 | 
						|
      if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
 | 
						|
        Data = KeyReadDataRegister (ConsoleIn);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      gBS->Stall (30);
 | 
						|
    }
 | 
						|
 | 
						|
    SumTimeOut += TimeOut;
 | 
						|
 | 
						|
    if (Data == Value) {
 | 
						|
      GotIt = 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SumTimeOut >= mWaitForValueTimeOut) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check results
 | 
						|
  //
 | 
						|
  if (GotIt) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Show keyboard status lights according to
 | 
						|
  indicators in ConsoleIn.
 | 
						|
 | 
						|
  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
 | 
						|
  
 | 
						|
  @return status
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UpdateStatusLights (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT8       Command;
 | 
						|
 | 
						|
  //
 | 
						|
  // Send keyboard command
 | 
						|
  //
 | 
						|
  Status = KeyboardWrite (ConsoleIn, 0xed);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
 | 
						|
  //
 | 
						|
  // Light configuration
 | 
						|
  //
 | 
						|
  Command = 0;
 | 
						|
  if (ConsoleIn->CapsLock) {
 | 
						|
    Command |= 4;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConsoleIn->NumLock) {
 | 
						|
    Command |= 2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConsoleIn->ScrollLock) {
 | 
						|
    Command |= 1;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = KeyboardWrite (ConsoleIn, Command);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get scancode from scancode buffer
 | 
						|
  and translate into EFI-scancode and unicode defined by EFI spec
 | 
						|
  The function is always called in TPL_NOTIFY
 | 
						|
 | 
						|
  @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer
 | 
						|
 | 
						|
  @retval EFI_NOT_READY - Input from console not ready yet.
 | 
						|
  @retval EFI_SUCCESS   - Function executed successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KeyGetchar (
 | 
						|
  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT8       ScanCode;
 | 
						|
  UINT8       Readed;
 | 
						|
  BOOLEAN     Extended;
 | 
						|
  UINT8       ScancodeArr[4];
 | 
						|
  UINTN       Index;
 | 
						|
  //
 | 
						|
  // 4 bytes most
 | 
						|
  //
 | 
						|
  UINT32      ScancodeArrPos;
 | 
						|
  //
 | 
						|
  // point to the current position in ScancodeArr
 | 
						|
  //
 | 
						|
 | 
						|
  Readed          = 0;
 | 
						|
  Extended        = FALSE;
 | 
						|
  ScancodeArrPos  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Read one byte of the scan code and store it into the memory buffer
 | 
						|
  // This block of code is added to insert an action that is equivalent to
 | 
						|
  // the timer event handling function, so as to increase the frequency of
 | 
						|
  // detecting the availability of keys. Timer event has a max frequency of
 | 
						|
  // 18Hz which is insufficient
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that
 | 
						|
  // KB is not connected to system. If KB is not connected to system, driver will find there's  something
 | 
						|
  // error in the following code and wait for the input buffer empty, this waiting time shoulb be  short enough since
 | 
						|
  // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
 | 
						|
  // Just skip the 'resend' process simply.
 | 
						|
  //
 | 
						|
 | 
						|
 | 
						|
  if (((KeyReadStatusRegister (ConsoleIn) & 0x21) == 0x1) && (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT)) {
 | 
						|
 | 
						|
    Readed = KeyReadDataRegister (ConsoleIn);
 | 
						|
    //
 | 
						|
    // put the scancode into the memory scancode buffer
 | 
						|
    //
 | 
						|
    ConsoleIn->ScancodeBufCount++;
 | 
						|
    ConsoleIn->ScancodeBufEndPos++;
 | 
						|
    if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {
 | 
						|
      ConsoleIn->ScancodeBufEndPos = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Readed;
 | 
						|
 | 
						|
    //
 | 
						|
    // Handle Alt+Ctrl+Del Key combination
 | 
						|
    //
 | 
						|
    switch (Readed) {
 | 
						|
 | 
						|
    case SCANCODE_CTRL_MAKE:
 | 
						|
      ConsoleIn->Ctrled = TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_CTRL_BREAK:
 | 
						|
      ConsoleIn->Ctrled = FALSE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_ALT_MAKE:
 | 
						|
      ConsoleIn->Alted = TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_ALT_BREAK:
 | 
						|
      ConsoleIn->Alted = FALSE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // if Alt+Ctrl+Del, Reboot the System
 | 
						|
    //
 | 
						|
    if (ConsoleIn->Ctrled && ConsoleIn->Alted && Readed == 0x53) {
 | 
						|
      gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check if there are enough bytes of scancode representing a single key
 | 
						|
  // available in the buffer
 | 
						|
  //
 | 
						|
  while (1) {
 | 
						|
 | 
						|
    Status          = GetScancodeBufHead (ConsoleIn, 1, ScancodeArr);
 | 
						|
    ScancodeArrPos  = 0;
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_NOT_READY;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {
 | 
						|
      Extended        = TRUE;
 | 
						|
      Status          = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);
 | 
						|
      ScancodeArrPos  = 1;
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return EFI_NOT_READY;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5
 | 
						|
    // if present, ignore them
 | 
						|
    //
 | 
						|
    if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
 | 
						|
 | 
						|
      Status          = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);
 | 
						|
      ScancodeArrPos  = 1;
 | 
						|
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return EFI_NOT_READY;
 | 
						|
      }
 | 
						|
 | 
						|
      Status          = GetScancodeBufHead (ConsoleIn, 3, ScancodeArr);
 | 
						|
      ScancodeArrPos  = 2;
 | 
						|
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return EFI_NOT_READY;
 | 
						|
      }
 | 
						|
 | 
						|
      PopScancodeBufHead (ConsoleIn, 3, ScancodeArr);
 | 
						|
      return EFI_NOT_READY;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // if we reach this position, scancodes for a key is in buffer now,pop them
 | 
						|
    //
 | 
						|
    Status = PopScancodeBufHead (ConsoleIn, ScancodeArrPos + 1, ScancodeArr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_NOT_READY;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // store the last available byte, this byte of scancode will be checked
 | 
						|
    //
 | 
						|
    ScanCode = ScancodeArr[ScancodeArrPos];
 | 
						|
 | 
						|
    //
 | 
						|
    // Check for special keys and update the driver state.
 | 
						|
    //
 | 
						|
    switch (ScanCode) {
 | 
						|
 | 
						|
    case SCANCODE_CTRL_MAKE:
 | 
						|
      ConsoleIn->Ctrl = TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_CTRL_BREAK:
 | 
						|
      ConsoleIn->Ctrl = FALSE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_ALT_MAKE:
 | 
						|
      ConsoleIn->Alt = TRUE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_ALT_BREAK:
 | 
						|
      ConsoleIn->Alt = FALSE;
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_LEFT_SHIFT_MAKE:
 | 
						|
      if (!Extended) {
 | 
						|
        ConsoleIn->Shift     = TRUE;
 | 
						|
        ConsoleIn->LeftShift = TRUE;
 | 
						|
      }      
 | 
						|
      break;
 | 
						|
    case SCANCODE_RIGHT_SHIFT_MAKE:
 | 
						|
      if (!Extended) {
 | 
						|
        ConsoleIn->Shift = TRUE;
 | 
						|
        ConsoleIn->RightShift = TRUE;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_LEFT_SHIFT_BREAK:
 | 
						|
      if (!Extended) {
 | 
						|
        ConsoleIn->Shift     = FALSE;
 | 
						|
        ConsoleIn->LeftShift = FALSE;
 | 
						|
      } else {
 | 
						|
        ConsoleIn->SysReq    = FALSE;
 | 
						|
      }      
 | 
						|
      break;
 | 
						|
    case SCANCODE_RIGHT_SHIFT_BREAK:
 | 
						|
      if (!Extended) {
 | 
						|
        ConsoleIn->Shift = FALSE;
 | 
						|
        ConsoleIn->RightShift = FALSE;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_LEFT_LOGO_MAKE:
 | 
						|
      ConsoleIn->LeftLogo = TRUE;
 | 
						|
      break;    
 | 
						|
    case SCANCODE_LEFT_LOGO_BREAK:
 | 
						|
      ConsoleIn->LeftLogo = FALSE;
 | 
						|
      break;          
 | 
						|
    case SCANCODE_RIGHT_LOGO_MAKE:
 | 
						|
      ConsoleIn->RightLogo = TRUE;
 | 
						|
      break;
 | 
						|
    case SCANCODE_RIGHT_LOGO_BREAK:
 | 
						|
      ConsoleIn->RightLogo = FALSE;
 | 
						|
      break;      
 | 
						|
    case SCANCODE_MENU_MAKE:
 | 
						|
      ConsoleIn->Menu = TRUE;
 | 
						|
      break;
 | 
						|
    case SCANCODE_MENU_BREAK:
 | 
						|
      ConsoleIn->Menu = FALSE;
 | 
						|
      break;      
 | 
						|
    case SCANCODE_SYS_REQ_MAKE:
 | 
						|
      if (Extended) {
 | 
						|
        ConsoleIn->SysReq = TRUE;
 | 
						|
      }
 | 
						|
    case SCANCODE_CAPS_LOCK_MAKE:
 | 
						|
      ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
 | 
						|
      UpdateStatusLights (ConsoleIn);
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_NUM_LOCK_MAKE:
 | 
						|
      ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
 | 
						|
      UpdateStatusLights (ConsoleIn);
 | 
						|
      break;
 | 
						|
 | 
						|
    case SCANCODE_SCROLL_LOCK_MAKE:
 | 
						|
      ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
 | 
						|
      UpdateStatusLights (ConsoleIn);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If this is a BREAK Key or above the valid range, ignore it
 | 
						|
    //
 | 
						|
    if (ScanCode >= SCANCODE_MAX_MAKE) {
 | 
						|
      continue;
 | 
						|
    } else {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Treat Numeric Key Pad "/" specially
 | 
						|
  //
 | 
						|
  if (Extended && ScanCode == 0x35) {
 | 
						|
    ConsoleIn->Key.ScanCode     = SCAN_NULL;
 | 
						|
    ConsoleIn->Key.UnicodeChar  = '/';
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Convert Keyboard ScanCode into an EFI Key
 | 
						|
  //
 | 
						|
  for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {
 | 
						|
    if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
 | 
						|
      ConsoleIn->Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
 | 
						|
      if (ConsoleIn->Shift) {
 | 
						|
        ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
 | 
						|
        //
 | 
						|
        // Need not return associated shift state if a class of printable characters that
 | 
						|
        // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
 | 
						|
        //
 | 
						|
        if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {
 | 
						|
          ConsoleIn->LeftShift  = FALSE;
 | 
						|
          ConsoleIn->RightShift = FALSE;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // alphabetic key is affected by CapsLock State
 | 
						|
      //
 | 
						|
      if (ConsoleIn->CapsLock) {
 | 
						|
        if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {
 | 
						|
          ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
 | 
						|
        } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {
 | 
						|
          ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
 | 
						|
      //
 | 
						|
      if (ConsoleIn->Ctrled) {
 | 
						|
        if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {
 | 
						|
          ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'a' + 1);
 | 
						|
        } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {
 | 
						|
          ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'A' + 1);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
 | 
						|
  //
 | 
						|
  if (ScanCode >= 0x47 && ScanCode <= 0x53) {
 | 
						|
 | 
						|
    if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {
 | 
						|
      ConsoleIn->Key.ScanCode = SCAN_NULL;
 | 
						|
    } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
 | 
						|
      ConsoleIn->Key.UnicodeChar = 0x00;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If the key can not be converted then just return.
 | 
						|
  //
 | 
						|
  if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Save the Shift/Toggle state
 | 
						|
  //
 | 
						|
  if (ConsoleIn->Ctrl) {
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= (Extended == TRUE) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;
 | 
						|
  }                                    
 | 
						|
  if (ConsoleIn->Alt) {                
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= (Extended == TRUE) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;
 | 
						|
  }                                    
 | 
						|
  if (ConsoleIn->LeftShift) {          
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= EFI_LEFT_SHIFT_PRESSED;
 | 
						|
  }                                    
 | 
						|
  if (ConsoleIn->RightShift) {         
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= EFI_RIGHT_SHIFT_PRESSED;
 | 
						|
  }                                    
 | 
						|
  if (ConsoleIn->LeftLogo) {           
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= EFI_LEFT_LOGO_PRESSED;
 | 
						|
  }                                    
 | 
						|
  if (ConsoleIn->RightLogo) {          
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= EFI_RIGHT_LOGO_PRESSED;
 | 
						|
  }                                    
 | 
						|
  if (ConsoleIn->Menu) {               
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= EFI_MENU_KEY_PRESSED;
 | 
						|
  }                                    
 | 
						|
  if (ConsoleIn->SysReq) {             
 | 
						|
    ConsoleIn->KeyState.KeyShiftState  |= EFI_SYS_REQ_PRESSED;
 | 
						|
  }  
 | 
						|
  if (ConsoleIn->CapsLock) {
 | 
						|
    ConsoleIn->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
 | 
						|
  }
 | 
						|
  if (ConsoleIn->NumLock) {
 | 
						|
    ConsoleIn->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
 | 
						|
  }
 | 
						|
  if (ConsoleIn->ScrollLock) {
 | 
						|
    ConsoleIn->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Perform 8042 controller and keyboard Initialization
 | 
						|
  If ExtendedVerification is TRUE, do additional test for
 | 
						|
  the keyboard interface
 | 
						|
 | 
						|
  @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
 | 
						|
  @param ExtendedVerification - indicates a thorough initialization
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR Fail to init keyboard
 | 
						|
  @retval EFI_SUCCESS      Success to init keyboard
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
InitKeyboard (
 | 
						|
  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
 | 
						|
  IN BOOLEAN                     ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_STATUS              Status1;
 | 
						|
  UINT8                   CommandByte;
 | 
						|
  STATIC BOOLEAN          EnableMouseInterface;
 | 
						|
  EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
 | 
						|
 | 
						|
  Status                = EFI_SUCCESS;
 | 
						|
  EnableMouseInterface  = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get Ps2 policy to set this
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiPs2PolicyProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) &Ps2Policy
 | 
						|
                  );
 | 
						|
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
 | 
						|
    ConsoleIn->DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Perform a read to cleanup the Status Register's
 | 
						|
  // output buffer full bits
 | 
						|
  //
 | 
						|
  while (!EFI_ERROR (Status)) {
 | 
						|
    Status = KeyboardRead (ConsoleIn, &CommandByte);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // We should disable mouse interface during the initialization process
 | 
						|
  // since mouse device output could block keyboard device output in the
 | 
						|
  // 60H port of 8042 controller.
 | 
						|
  //
 | 
						|
  // So if we are not initializing 8042 controller for the
 | 
						|
  // first time, we have to remember the previous mouse interface
 | 
						|
  // enabling state
 | 
						|
  //
 | 
						|
  // Test the system flag in to determine whether this is the first
 | 
						|
  // time initialization
 | 
						|
  //
 | 
						|
  if ((KeyReadStatusRegister (ConsoleIn) & 0x04)) {
 | 
						|
    //
 | 
						|
    // 8042 controller is already setup (by myself or by mouse driver):
 | 
						|
    //   See whether mouse interface is already enabled
 | 
						|
    //   which determines whether we should enable it later
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Read the command byte of 8042 controller
 | 
						|
    //
 | 
						|
    Status = KeyboardCommand (ConsoleIn, 0x20);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardRead (ConsoleIn, &CommandByte);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Test the mouse enabling bit
 | 
						|
    //
 | 
						|
    if (CommandByte & 0x20) {
 | 
						|
      EnableMouseInterface = FALSE;
 | 
						|
    } else {
 | 
						|
      EnableMouseInterface = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // 8042 controller is not setup yet:
 | 
						|
    //   8042 controller selftest;
 | 
						|
    //   Don't enable mouse interface later.
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Disable keyboard and mouse interfaces
 | 
						|
    //
 | 
						|
    Status = KeyboardCommand (ConsoleIn, 0xad);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardCommand (ConsoleIn, 0xa7);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_PROGRESS_CODE,
 | 
						|
      EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
 | 
						|
      ConsoleIn->DevicePath
 | 
						|
      );
 | 
						|
    //
 | 
						|
    // 8042 Controller Self Test
 | 
						|
    //
 | 
						|
    Status = KeyboardCommand (ConsoleIn, 0xaa);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, 0x55);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Don't enable mouse interface later
 | 
						|
    //
 | 
						|
    EnableMouseInterface = FALSE;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  if (Ps2Policy != NULL) {
 | 
						|
    Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Write 8042 Command Byte, set System Flag
 | 
						|
  // While at the same time:
 | 
						|
  //  1. disable mouse interface,
 | 
						|
  //  2. enable kbd interface,
 | 
						|
  //  3. enable PC/XT kbd translation mode
 | 
						|
  //  4. enable mouse and kbd interrupts
 | 
						|
  //
 | 
						|
  //  ( Command Byte bits:
 | 
						|
  //  7: Reserved
 | 
						|
  //  6: PC/XT translation mode
 | 
						|
  //  5: Disable Auxiliary device interface
 | 
						|
  //  4: Disable keyboard interface
 | 
						|
  //  3: Reserved
 | 
						|
  //  2: System Flag
 | 
						|
  //  1: Enable Auxiliary device interrupt
 | 
						|
  //  0: Enable Keyboard interrupt )
 | 
						|
  //
 | 
						|
  Status = KeyboardCommand (ConsoleIn, 0x60);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = KeyboardWrite (ConsoleIn, 0x67);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear Memory Scancode Buffer
 | 
						|
  //
 | 
						|
  ConsoleIn->ScancodeBufStartPos  = 0;
 | 
						|
  ConsoleIn->ScancodeBufEndPos    = KEYBOARD_BUFFER_MAX_COUNT - 1;
 | 
						|
  ConsoleIn->ScancodeBufCount     = 0;
 | 
						|
  ConsoleIn->Ctrled               = FALSE;
 | 
						|
  ConsoleIn->Alted                = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Reset the status indicators
 | 
						|
  //
 | 
						|
  ConsoleIn->Ctrl       = FALSE;
 | 
						|
  ConsoleIn->Alt        = FALSE;
 | 
						|
  ConsoleIn->Shift      = FALSE;
 | 
						|
  ConsoleIn->CapsLock   = FALSE;
 | 
						|
  ConsoleIn->NumLock    = FALSE;
 | 
						|
  ConsoleIn->ScrollLock = FALSE;
 | 
						|
  ConsoleIn->LeftShift  = FALSE;
 | 
						|
  ConsoleIn->RightShift = FALSE;
 | 
						|
  ConsoleIn->LeftLogo   = FALSE;
 | 
						|
  ConsoleIn->RightLogo  = FALSE;
 | 
						|
  ConsoleIn->Menu       = FALSE;
 | 
						|
  ConsoleIn->SysReq     = FALSE;  
 | 
						|
 | 
						|
  //
 | 
						|
  // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
 | 
						|
  // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
 | 
						|
  // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
 | 
						|
  // and normally during booting an OS, it's skipped.
 | 
						|
  //
 | 
						|
  if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
 | 
						|
    //
 | 
						|
    // Additional verifications for keyboard interface
 | 
						|
    //
 | 
						|
    //
 | 
						|
    // Keyboard Interface Test
 | 
						|
    //
 | 
						|
    Status = KeyboardCommand (ConsoleIn, 0xab);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, 0x00);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (
 | 
						|
        ConsoleIn,
 | 
						|
        L"Some specific value not aquired from 8042 controller!\n\r"
 | 
						|
        );
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Keyboard reset with a BAT(Basic Assurance Test)
 | 
						|
    //
 | 
						|
    Status = KeyboardWrite (ConsoleIn, 0xff);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // wait for BAT completion code
 | 
						|
    //
 | 
						|
    mWaitForValueTimeOut  = KEYBOARD_BAT_TIMEOUT;
 | 
						|
 | 
						|
    Status                = KeyboardWaitForValue (ConsoleIn, 0xaa);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
 | 
						|
 | 
						|
    //
 | 
						|
    // Set Keyboard to use Scan Code Set 2
 | 
						|
    //
 | 
						|
    Status = KeyboardWrite (ConsoleIn, 0xf0);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWrite (ConsoleIn, 0x02);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear Keyboard Scancode Buffer
 | 
						|
  //
 | 
						|
  Status = KeyboardWrite (ConsoleIn, 0xf4);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = KeyboardWaitForValue (ConsoleIn, 0xfa);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  if (Ps2Policy != NULL) {
 | 
						|
    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
 | 
						|
      ConsoleIn->CapsLock = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
 | 
						|
      ConsoleIn->NumLock = TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
 | 
						|
      ConsoleIn->ScrollLock = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Update Keyboard Lights
 | 
						|
  //
 | 
						|
  Status = UpdateStatusLights (ConsoleIn);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
 | 
						|
    goto Done;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // At last, we can now enable the mouse interface if appropriate
 | 
						|
  //
 | 
						|
Done:
 | 
						|
 | 
						|
  if (EnableMouseInterface) {
 | 
						|
    //
 | 
						|
    // Enable mouse interface
 | 
						|
    //
 | 
						|
    Status1 = KeyboardCommand (ConsoleIn, 0xa8);
 | 
						|
    if (EFI_ERROR (Status1)) {
 | 
						|
      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Disable the keyboard interface of the 8042 controller
 | 
						|
 | 
						|
  @param ConsoleIn   - the device instance
 | 
						|
 | 
						|
  @return status of issuing disable command
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
DisableKeyboard (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Disable keyboard interface
 | 
						|
  //
 | 
						|
  Status = KeyboardCommand (ConsoleIn, 0xad);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    KeyboardError (ConsoleIn, L"\n\r");
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
 | 
						|
  If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
 | 
						|
  should not be in system.
 | 
						|
 | 
						|
  @param[in]  ConsoleIn             Keyboard Private Data Structure
 | 
						|
 | 
						|
  @retval     TRUE                  Keyboard in System.
 | 
						|
  @retval     FALSE                 Keyboard not in System.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
CheckKeyboardConnect (
 | 
						|
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS     Status;
 | 
						|
  UINTN          WaitForValueTimeOutBcakup;
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  //
 | 
						|
  // enable keyboard itself and wait for its ack
 | 
						|
  // If can't receive ack, Keyboard should not be connected.
 | 
						|
  //
 | 
						|
  Status = KeyboardWrite (
 | 
						|
             ConsoleIn,
 | 
						|
             KEYBOARD_KBEN
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // wait for 1s
 | 
						|
  //
 | 
						|
  WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
 | 
						|
  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
 | 
						|
  Status = KeyboardWaitForValue (
 | 
						|
             ConsoleIn,
 | 
						|
             KEYBOARD_CMDECHO_ACK
 | 
						|
             );
 | 
						|
  mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 |