More supports for A20 enable/disable

Add i8042 output port commands (0xf0-0xff), I8042_ENABLE_A20 and
I8042_DISABLE_A20.

BUG=chrome-os-partner:13119,
BRANCH=None
TEST=Tested on W7 installer. No KB error shown on EC console.

Change-Id: I9ad1fd7baa10683ef18ccf13faf09dc0cefcca0a
Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/34994
Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
This commit is contained in:
Louis Yung-Chieh Lo
2012-10-09 17:30:16 +08:00
committed by Gerrit
parent 4f410f5468
commit 25bbb6b5de
4 changed files with 45 additions and 2 deletions

View File

@@ -214,6 +214,13 @@ int lpc_keyboard_has_char(void)
return (LM4_LPC_ST(LPC_CH_KEYBOARD) & LM4_LPC_ST_TOH) ? 1 : 0;
}
/* Return true if the FRMH is set */
int lpc_keyboard_input_pending(void)
{
return (LM4_LPC_ST(LPC_CH_KEYBOARD) & LM4_LPC_ST_FRMH) ? 1 : 0;
}
/* Put a char to host buffer and send IRQ if specified. */
void lpc_keyboard_put_char(uint8_t chr, int send_irq)
{
LPC_POOL_KEYBOARD[1] = chr;

View File

@@ -62,6 +62,7 @@ static uint8_t controller_ram[0x20] = {
I8042_XLATE | I8042_AUX_DIS | I8042_KBD_DIS,
/* 0x01 - 0x1f are controller RAM */
};
static uint8_t A20_status;
static int power_button_pressed = 0;
static void keyboard_special(uint16_t k);
@@ -355,6 +356,7 @@ static enum {
STATE_EX_SETLEDS_1, /* expect 2-byte parameter coming */
STATE_EX_SETLEDS_2,
STATE_WRITE_CMD_BYTE,
STATE_WRITE_OUTPUT_PORT,
STATE_ECHO_MOUSE,
STATE_SETREP,
STATE_SEND_TO_MOUSE,
@@ -409,6 +411,13 @@ int handle_keyboard_data(uint8_t data, uint8_t *output)
data_port_state = STATE_NORMAL;
break;
case STATE_WRITE_OUTPUT_PORT:
CPRINTF5("[%T KB eaten by STATE_WRITE_OUTPUT_PORT: 0x%02x]\n",
data);
A20_status = (data & (1 << 1)) ? 1 : 0;
data_port_state = STATE_NORMAL;
break;
case STATE_ECHO_MOUSE:
CPRINTF5("[%T KB eaten by STATE_ECHO_MOUSE: 0x%02x]\n", data);
output[out_len++] = data;
@@ -559,6 +568,18 @@ int handle_keyboard_command(uint8_t command, uint8_t *output)
update_ctl_ram(0, read_ctl_ram(0) & ~I8042_KBD_DIS);
break;
case I8042_READ_OUTPUT_PORT:
output[out_len++] =
(lpc_keyboard_input_pending() ? (1 << 5) : 0) |
(lpc_keyboard_has_char() ? (1 << 4) : 0) |
(A20_status ? (1 << 1) : 0) |
1; /* Main processor in normal mode */
break;
case I8042_WRITE_OUTPUT_PORT:
data_port_state = STATE_WRITE_OUTPUT_PORT;
break;
case I8042_RESET_SELF_TEST:
output[out_len++] = 0x55; /* Self test success */
break;
@@ -599,9 +620,17 @@ int handle_keyboard_command(uint8_t command, uint8_t *output)
command <= I8042_WRITE_CTL_RAM_END) {
data_port_state = STATE_WRITE_CMD_BYTE;
controller_ram_address = command - 0x60;
} else if (command == I8042_DISABLE_A20) {
A20_status = 0;
} else if (command == I8042_ENABLE_A20) {
A20_status = 1;
} else if (command >= I8042_PULSE_START &&
command <= I8042_PULSE_END) {
/* Pulse Output Bit. Not implemented. Ignore it. */
/* Pulse Output Bits,
* b0=0 to reset CPU, see I8042_SYSTEM_RESET above
* b1=0 to disable A20 line
*/
A20_status = command & (1 << 1) ? 1 : 0;
} else {
CPRINTF("[%T KB unsupported cmd: 0x%02x]\n", command);
reset_rate_and_delay();

View File

@@ -55,11 +55,15 @@
#define I8042_TEST_KB_PORT 0xab
#define I8042_DIS_KB 0xad
#define I8042_ENA_KB 0xae
#define I8042_READ_OUTPUT_PORT 0xd0
#define I8042_WRITE_OUTPUT_PORT 0xd1
#define I8042_ECHO_MOUSE 0xd3 /* expect a byte on port 0x60 */
#define I8042_SEND_TO_MOUSE 0xd4 /* expect a byte on port 0x60 */
#define I8042_DISABLE_A20 0xdd
#define I8042_ENABLE_A20 0xdf
#define I8042_PULSE_START 0xf0
#define I8042_PULSE_END 0xfd
#define I8042_SYSTEM_RESET 0xfe
#define I8042_PULSE_END 0xff
/* port 0x60 return value */
#define I8042_RET_BAT 0xaa

View File

@@ -23,6 +23,9 @@ uint8_t *lpc_get_memmap_range(void);
*/
int lpc_keyboard_has_char(void);
/* Return true if the FRMH is still set */
int lpc_keyboard_input_pending(void);
/**
* Send a byte to host via keyboard port 0x60.
*