summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-10-22 14:46:50 -0700
committerGerrit <chrome-bot@google.com>2012-10-23 17:32:01 -0700
commit090e4f5f8e7c8de473b26a8c0c437085d7c3db79 (patch)
tree39d92f114df54f1a44d34cdc25ad12cd50ff2fa4
parente72788ef96e83ef9d6ac0b2593c7edd8139c9376 (diff)
downloadchrome-ec-090e4f5f8e7c8de473b26a8c0c437085d7c3db79.tar.gz
Clean up i8042 module
Remove unused code paths. Simplify interfaces. Clarify comments. Split the protocol constants into their own header file (since they're used only by keyboard.c, not i8042.c, which is really keyboard buffering... and will be renamed so in a followup CL.) This cleanup reduces binary size by about 200 bytes. BUG=chrome-os-partner:15579 BRANCH=none TEST=type on the keyboard; it should still work. Change-Id: I6acbab5fe5604b4b0c516ba3622e6f41820985d1 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/36271
-rw-r--r--chip/lm4/lpc.c8
-rw-r--r--common/i8042.c126
-rw-r--r--common/keyboard.c14
-rw-r--r--common/mock_i8042.c23
-rw-r--r--include/i8042.h136
-rw-r--r--include/i8042_protocol.h86
6 files changed, 162 insertions, 231 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index d34793cc80..cc77984638 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -564,12 +564,8 @@ static void lpc_interrupt(void)
#ifdef CONFIG_TASK_I8042CMD
/* Handle keyboard interface writes */
st = LM4_LPC_ST(LPC_CH_KEYBOARD);
- if (st & LM4_LPC_ST_FRMH) {
- if (st & LM4_LPC_ST_CMD)
- i8042_receives_command(LPC_POOL_KEYBOARD[0]);
- else
- i8042_receives_data(LPC_POOL_KEYBOARD[0]);
- }
+ if (st & LM4_LPC_ST_FRMH)
+ i8042_receive(LPC_POOL_KEYBOARD[0], st & LM4_LPC_ST_CMD);
if (mis & LM4_LPC_INT_MASK(LPC_CH_KEYBOARD, 1)) {
/* Host read data; wake up task to send remaining bytes */
diff --git a/common/i8042.c b/common/i8042.c
index 0174e84f0b..5c3b1bbf06 100644
--- a/common/i8042.c
+++ b/common/i8042.c
@@ -2,11 +2,13 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * Chrome OS EC i8042 interface code.
+ * i8042 interface to host
+ *
+ * i8042 commands are processed by keyboard.c.
*/
-#include "board.h"
#include "common.h"
+#include "config.h"
#include "console.h"
#include "i8042.h"
#include "keyboard.h"
@@ -16,29 +18,20 @@
#include "timer.h"
#include "util.h"
-
-#define I8042_DEBUG 1
-
/* Console output macros */
-#if I8042_DEBUG >= 4
-#define CPRINTF4(format, args...) cprintf(CC_I8042, format, ## args)
-#else
-#define CPRINTF4(format, args...)
-#endif
-#if I8042_DEBUG >= 5
-#define CPRINTF5(format, args...) cprintf(CC_I8042, format, ## args)
-#else
-#define CPRINTF5(format, args...)
-#endif
-
+#define CPRINTF(format, args...) cprintf(CC_I8042, format, ## args)
static int i8042_irq_enabled;
-
+/*
+ * Mutex to control write access to the to-host buffer head. Don't need to
+ * mutex the tail because reads are only done in one place.
+ */
static struct mutex to_host_mutex;
+
static uint8_t to_host_buffer[16];
static struct queue to_host = {
- .buf_bytes = ARRAY_SIZE(to_host_buffer),
+ .buf_bytes = sizeof(to_host_buffer),
.unit_bytes = sizeof(uint8_t),
.buf = to_host_buffer,
};
@@ -52,70 +45,45 @@ struct host_byte {
uint8_t type;
uint8_t byte;
};
+
/* 4 is big enough for all i8042 commands */
static uint8_t from_host_buffer[4 * sizeof(struct host_byte)];
static struct queue from_host = {
- .buf_bytes = ARRAY_SIZE(from_host_buffer),
+ .buf_bytes = sizeof(from_host_buffer),
.unit_bytes = sizeof(struct host_byte),
.buf = from_host_buffer,
};
-
-/* Reset all i8042 buffer */
void i8042_flush_buffer()
{
+ mutex_lock(&to_host_mutex);
queue_reset(&to_host);
+ mutex_unlock(&to_host_mutex);
lpc_keyboard_clear_buffer();
}
-
-/* Called by the chip-specific code when host sends a byte to port 0x60.
- * Note that this is in the interrupt context.
- */
-void i8042_receives_data(int data)
+void i8042_receive(int data, int is_cmd)
{
struct host_byte h;
- h.type = HOST_DATA;
+ h.type = is_cmd ? HOST_COMMAND : HOST_DATA;
h.byte = data;
queue_add_units(&from_host, &h, 1);
task_wake(TASK_ID_I8042CMD);
}
-
-/* Called by the chip-specific code when host sends a byte to port 0x64.
- * Note that this is in the interrupt context.
- */
-void i8042_receives_command(int cmd)
+void i8042_enable_keyboard_irq(int enable)
{
- struct host_byte h;
-
- h.type = HOST_COMMAND;
- h.byte = cmd;
- queue_add_units(&from_host, &h, 1);
- task_wake(TASK_ID_I8042CMD);
-}
-
-
-/* Called by common/keyboard.c when the host wants to receive keyboard IRQ
- * (or not).
- */
-void i8042_enable_keyboard_irq(void) {
- i8042_irq_enabled = 1;
- lpc_keyboard_resume_irq();
-}
-
-void i8042_disable_keyboard_irq(void) {
- i8042_irq_enabled = 0;
+ i8042_irq_enabled = enable;
+ if (enable)
+ lpc_keyboard_resume_irq();
}
-
static void i8042_handle_from_host(void)
{
struct host_byte h;
int ret_len;
uint8_t output[MAX_SCAN_CODE_LEN];
- enum ec_error_list ret;
while (queue_remove_unit(&from_host, &h)) {
if (h.type == HOST_COMMAND)
@@ -123,35 +91,29 @@ static void i8042_handle_from_host(void)
else
ret_len = handle_keyboard_data(h.byte, output);
- ret = i8042_send_to_host(ret_len, output);
- ASSERT(ret == EC_SUCCESS);
+ i8042_send_to_host(ret_len, output);
}
}
void i8042_command_task(void)
{
while (1) {
- /* Either a new byte to host or host picking up can un-block. */
+ /* Wait for next host read/write */
task_wait_event(-1);
while (1) {
uint8_t chr;
- /* first handle command/data from host. */
+ /* Handle command/data write from host */
i8042_handle_from_host();
- /* Check if we have data in buffer to host. */
+ /* Check if we have data to send to host */
if (queue_is_empty(&to_host))
- break; /* nothing to host */
-
- /* if the host still didn't read that away,
- try next time. */
- if (lpc_keyboard_has_char()) {
- CPRINTF5("[%T i8042_command_task() "
- "cannot send to host due to host "
- "haven't taken away.\n");
break;
- }
+
+ /* Host interface must have space */
+ if (lpc_keyboard_has_char())
+ break;
/* Get a char from buffer. */
kblog_put('k', to_host.head);
@@ -160,41 +122,25 @@ void i8042_command_task(void)
/* Write to host. */
lpc_keyboard_put_char(chr, i8042_irq_enabled);
- CPRINTF4("[%T i8042_command_task() "
- "sends to host: 0x%02x\n", chr);
}
}
}
-
-static void enq_to_host(int len, const uint8_t *bytes)
+void i8042_send_to_host(int len, const uint8_t *bytes)
{
int i;
+ for (i = 0; i < len; i++)
+ kblog_put('s', bytes[i]);
+
+ /* Enqueue output data if there's space */
mutex_lock(&to_host_mutex);
- /* Check if the buffer has enough space, then copy them to buffer. */
if (queue_has_space(&to_host, len)) {
- for (i = 0; i < len; ++i) {
- kblog_put('t', to_host.tail);
- kblog_put('T', bytes[i]);
- }
+ kblog_put('t', to_host.tail);
queue_add_units(&to_host, bytes, len);
}
mutex_unlock(&to_host_mutex);
-}
-
-enum ec_error_list i8042_send_to_host(int len, const uint8_t *bytes)
-{
- int i;
- for (i = 0; i < len; i++)
- kblog_put('s', bytes[i]);
-
- /* Put to queue in memory */
- enq_to_host(len, bytes);
-
- /* Wake up the task to move from queue to the buffer to host. */
+ /* Wake up the task to move from queue to host */
task_wake(TASK_ID_I8042CMD);
-
- return EC_SUCCESS;
}
diff --git a/common/keyboard.c b/common/keyboard.c
index 38535df1bd..93d4d96a13 100644
--- a/common/keyboard.c
+++ b/common/keyboard.c
@@ -8,11 +8,11 @@
#include "chipset.h"
#include "common.h"
#include "console.h"
-#include "ec_commands.h"
-#include "keyboard.h"
-#include "i8042.h"
#include "hooks.h"
#include "host_command.h"
+#include "i8042.h"
+#include "i8042_protocol.h"
+#include "keyboard.h"
#include "lightbar.h"
#include "lpc.h"
#include "registers.h"
@@ -345,7 +345,7 @@ static void update_ctl_ram(uint8_t addr, uint8_t data)
if (addr == 0x00) { /* the controller RAM */
/* Enable IRQ before enable keyboard (queue chars to host) */
if (!(orig & I8042_ENIRQ1) && (data & I8042_ENIRQ1))
- i8042_enable_keyboard_irq();
+ i8042_enable_keyboard_irq(1);
/* Handle the I8042_KBD_DIS bit */
keyboard_enable(!(data & I8042_KBD_DIS));
@@ -353,7 +353,7 @@ static void update_ctl_ram(uint8_t addr, uint8_t data)
/* Disable IRQ after disable keyboard so that every char
* must have informed the host. */
if ((orig & I8042_ENIRQ1) && !(data & I8042_ENIRQ1))
- i8042_disable_keyboard_irq();
+ i8042_enable_keyboard_irq(0);
}
}
@@ -677,7 +677,6 @@ static void keyboard_special(uint16_t k)
void keyboard_set_power_button(int pressed)
{
enum scancode_set_list code_set;
- enum ec_error_list ret;
uint8_t code[2][2][3] = {
{ /* set 1 */
{0xe0, 0xde}, /* break */
@@ -696,10 +695,9 @@ void keyboard_set_power_button(int pressed)
code_set = acting_code_set(scancode_set);
if (keyboard_enabled) {
- ret = i8042_send_to_host(
+ i8042_send_to_host(
(code_set == SCANCODE_SET_2 && !pressed) ? 3 : 2,
code[code_set - SCANCODE_SET_1][pressed]);
- ASSERT(ret == EC_SUCCESS);
}
}
diff --git a/common/mock_i8042.c b/common/mock_i8042.c
index 2677d7ee7f..a8c1a01447 100644
--- a/common/mock_i8042.c
+++ b/common/mock_i8042.c
@@ -9,21 +9,12 @@
#include "timer.h"
#include "uart.h"
-
-void i8042_receives_data(int data)
+void i8042_receive(int data, int is_cmd)
{
/* Not implemented */
return;
}
-
-void i8042_receives_command(int cmd)
-{
- /* Not implemented */
- return;
-}
-
-
void i8042_command_task(void)
{
/* Do nothing */
@@ -31,7 +22,6 @@ void i8042_command_task(void)
usleep(5000000);
}
-
enum ec_error_list i8042_send_to_host(int len, const uint8_t *bytes)
{
int i;
@@ -42,19 +32,12 @@ enum ec_error_list i8042_send_to_host(int len, const uint8_t *bytes)
return EC_SUCCESS;
}
-
-void i8042_enable_keyboard_irq(void) {
- /* Not implemented */
- return;
-}
-
-
-void i8042_disable_keyboard_irq(void) {
+void i8042_enable_keyboard_irq(int enable)
+{
/* Not implemented */
return;
}
-
void i8042_flush_buffer()
{
/* Not implemented */
diff --git a/include/i8042.h b/include/i8042.h
index 6635e75aae..6bca016b94 100644
--- a/include/i8042.h
+++ b/include/i8042.h
@@ -1,125 +1,47 @@
-/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * i8042.h -- defines the interface between EC core and the EC lib, which
- * talks to the LPC driver (on the EC side) peering to the keyboard driver
- * (on the host side).
- *
- * The EC lib implements this interface.
+ * i8042 keyboard protocol
*/
-#ifndef __INTERFACE_I8042_H
-#define __INTERFACE_I8042_H
+#ifndef __CROS_EC_I8042_H
+#define __CROS_EC_I8042_H
#include "common.h"
-
-/* Keyboard command definition. Modified from Linux kernel atkbd.c file. */
-/* port 0x60 */
-#define I8042_CMD_MOUSE_1_1 0xe6
-#define I8042_CMD_MOUSE_2_1 0xe7
-#define I8042_CMD_MOUSE_RES 0xe8 /* dup to I8042_CMD_OK_GETID */
-#define I8042_CMD_GET_MOUSE 0xe9
-#define I8042_CMD_SETLEDS 0xed
-#define I8042_CMD_DIAG_ECHO 0xee
-#define I8042_CMD_GSCANSET 0xf0
-#define I8042_CMD_SSCANSET 0xf0
-#define I8042_CMD_GETID 0xf2
-#define I8042_CMD_SETREP 0xf3
-#define I8042_CMD_ENABLE 0xf4
-#define I8042_CMD_RESET_DIS 0xf5
-#define I8042_CMD_RESET_DEF 0xf6
-#define I8042_CMD_ALL_TYPEM 0xf7
-#define I8042_CMD_SETALL_MB 0xf8
-#define I8042_CMD_SETALL_MBR 0xfa
-#define I8042_CMD_SET_A_KEY_T 0xfb
-#define I8042_CMD_SET_A_KEY_MR 0xfc
-#define I8042_CMD_SET_A_KEY_M 0xfd
-#define I8042_CMD_RESET_BAT 0xff
-#define I8042_CMD_RESEND 0xfe
-#define I8042_CMD_EX_ENABLE 0xea
-#define I8042_CMD_EX_SETLEDS 0xeb
-#define I8042_CMD_OK_GETID 0xe8
-
-/* port 0x64 */
-#define I8042_READ_CMD_BYTE 0x20
-#define I8042_READ_CTL_RAM 0x21
-#define I8042_READ_CTL_RAM_END 0x3f
-#define I8042_WRITE_CMD_BYTE 0x60 /* expect a byte on port 0x60 */
-#define I8042_WRITE_CTL_RAM 0x61
-#define I8042_WRITE_CTL_RAM_END 0x7f
-#define I8042_ROUTE_AUX0 0x90
-#define I8042_ROUTE_AUX1 0x91
-#define I8042_ROUTE_AUX2 0x92
-#define I8042_ROUTE_AUX3 0x93
-#define I8042_ENA_PASSWORD 0xa6
-#define I8042_DIS_MOUSE 0xa7
-#define I8042_ENA_MOUSE 0xa8
-#define I8042_TEST_MOUSE 0xa9
-#define I8042_RESET_SELF_TEST 0xaa
-#define I8042_TEST_KB_PORT 0xab
-#define I8042_DIS_KB 0xad
-#define I8042_ENA_KB 0xae
-#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_PULSE_START 0xf0
-#define I8042_PULSE_END 0xfd
-#define I8042_SYSTEM_RESET 0xfe
-
-/* port 0x60 return value */
-#define I8042_RET_BAT 0xaa
-#define I8042_RET_EMUL0 0xe0
-#define I8042_RET_EMUL1 0xe1
-#define I8042_RET_ECHO 0xee
-#define I8042_RET_RELEASE 0xf0
-#define I8042_RET_HANJA 0xf1
-#define I8042_RET_HANGEUL 0xf2
-#define I8042_RET_ACK 0xfa
-#define I8042_RET_TEST_FAIL 0xfc
-#define I8042_RET_INTERNAL_FAIL 0xfd
-#define I8042_RET_NAK 0xfe
-#define I8042_RET_ERR 0xff
-
-/* port 64 - command byte bits */
-#define I8042_XLATE (1 << 6)
-#define I8042_AUX_DIS (1 << 5)
-#define I8042_KBD_DIS (1 << 4)
-#define I8042_SYS_FLAG (1 << 2)
-#define I8042_ENIRQ12 (1 << 1)
-#define I8042_ENIRQ1 (1 << 0)
-
-
+/**
+ * Flush and reset all i8042 keyboard buffers.
+ */
void i8042_flush_buffer(void);
-
-/* common/i8042.c implements this function, which is called by lpc.c
- * when an i8042 command/data from host side appears.
+/**
+ * Notify the i8042 module when a byte is written by the host.
+ *
+ * Note: This is called in interrupt context by the LPC interrupt handler.
*
- * Actually the a pair of data/command write would trigger 2 LPc interrupts.
- * So, we will queue the data byte first, then call keyboard routine after
- * receiving the command byte.
+ * @param data Byte written by host
+ * @param is_cmd Is byte command (!=0) or data (0)
*/
-void i8042_receives_data(int data);
-void i8042_receives_command(int cmd);
+void i8042_receive(int data, int is_cmd);
-
-/* Called by common/keyboard.c when the host doesn't want to receive
- * keyboard IRQ.
+/**
+ * Enable keyboard IRQ generation.
+ *
+ * @param enable Enable (!=0) or disable (0) IRQ generation.
*/
-void i8042_enable_keyboard_irq(void);
-void i8042_disable_keyboard_irq(void);
+void i8042_enable_keyboard_irq(int enable);
-
-/* Send the scan code to the host. The EC lib will push the scan code bytes
- * to host via port 0x60 and assert the IBF flag to trigger an interrupt.
- * The EC lib must queue them if the host cannot read the previous byte away
- * in time.
+/**
+ * Send a scan code to the host.
+ *
+ * The EC lib will push the scan code bytes to host via port 0x60 and assert
+ * the IBF flag to trigger an interrupt. The EC lib must queue them if the
+ * host cannot read the previous byte away in time.
*
- * Return:
- * EC_ERROR_BUFFER_FULL -- the queue to host is full. Try again?
+ * @param len Number of bytes to send to the host
+ * @param to_host Data to send
*/
-enum ec_error_list i8042_send_to_host(int len, const uint8_t *to_host);
-
+void i8042_send_to_host(int len, const uint8_t *to_host);
-#endif /* __INTERFACE_I8042_H */
+#endif /* __CROS_EC_I8042_H */
diff --git a/include/i8042_protocol.h b/include/i8042_protocol.h
new file mode 100644
index 0000000000..961d3e337c
--- /dev/null
+++ b/include/i8042_protocol.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * i8042 keyboard protocol constants
+ */
+
+#ifndef __CROS_EC_I8042_PROTOCOL_H
+#define __CROS_EC_I8042_PROTOCOL_H
+
+/* Some commands appear more than once. Why? */
+
+/* port 0x60 */
+#define I8042_CMD_MOUSE_1_1 0xe6
+#define I8042_CMD_MOUSE_2_1 0xe7
+#define I8042_CMD_MOUSE_RES 0xe8
+#define I8042_CMD_OK_GETID 0xe8
+#define I8042_CMD_GET_MOUSE 0xe9
+#define I8042_CMD_EX_ENABLE 0xea
+#define I8042_CMD_EX_SETLEDS 0xeb
+#define I8042_CMD_SETLEDS 0xed
+#define I8042_CMD_DIAG_ECHO 0xee
+#define I8042_CMD_GSCANSET 0xf0
+#define I8042_CMD_SSCANSET 0xf0
+#define I8042_CMD_GETID 0xf2
+#define I8042_CMD_SETREP 0xf3
+#define I8042_CMD_ENABLE 0xf4
+#define I8042_CMD_RESET_DIS 0xf5
+#define I8042_CMD_RESET_DEF 0xf6
+#define I8042_CMD_ALL_TYPEM 0xf7
+#define I8042_CMD_SETALL_MB 0xf8
+#define I8042_CMD_SETALL_MBR 0xfa
+#define I8042_CMD_SET_A_KEY_T 0xfb
+#define I8042_CMD_SET_A_KEY_MR 0xfc
+#define I8042_CMD_SET_A_KEY_M 0xfd
+#define I8042_CMD_RESET_BAT 0xff
+#define I8042_CMD_RESEND 0xfe
+
+/* port 0x64 */
+#define I8042_READ_CMD_BYTE 0x20
+#define I8042_READ_CTL_RAM 0x21
+#define I8042_READ_CTL_RAM_END 0x3f
+#define I8042_WRITE_CMD_BYTE 0x60 /* expect a byte on port 0x60 */
+#define I8042_WRITE_CTL_RAM 0x61
+#define I8042_WRITE_CTL_RAM_END 0x7f
+#define I8042_ROUTE_AUX0 0x90
+#define I8042_ROUTE_AUX1 0x91
+#define I8042_ROUTE_AUX2 0x92
+#define I8042_ROUTE_AUX3 0x93
+#define I8042_ENA_PASSWORD 0xa6
+#define I8042_DIS_MOUSE 0xa7
+#define I8042_ENA_MOUSE 0xa8
+#define I8042_TEST_MOUSE 0xa9
+#define I8042_RESET_SELF_TEST 0xaa
+#define I8042_TEST_KB_PORT 0xab
+#define I8042_DIS_KB 0xad
+#define I8042_ENA_KB 0xae
+#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_PULSE_START 0xf0
+#define I8042_PULSE_END 0xfd
+#define I8042_SYSTEM_RESET 0xfe
+
+/* port 0x60 return value */
+#define I8042_RET_BAT 0xaa
+#define I8042_RET_EMUL0 0xe0
+#define I8042_RET_EMUL1 0xe1
+#define I8042_RET_ECHO 0xee
+#define I8042_RET_RELEASE 0xf0
+#define I8042_RET_HANJA 0xf1
+#define I8042_RET_HANGEUL 0xf2
+#define I8042_RET_ACK 0xfa
+#define I8042_RET_TEST_FAIL 0xfc
+#define I8042_RET_INTERNAL_FAIL 0xfd
+#define I8042_RET_NAK 0xfe
+#define I8042_RET_ERR 0xff
+
+/* port 64 - command byte bits */
+#define I8042_XLATE (1 << 6)
+#define I8042_AUX_DIS (1 << 5)
+#define I8042_KBD_DIS (1 << 4)
+#define I8042_SYS_FLAG (1 << 2)
+#define I8042_ENIRQ12 (1 << 1)
+#define I8042_ENIRQ1 (1 << 0)
+
+#endif /* __CROS_EC_I8042_PROTOCOL_H */