libpayload-x86: keyboard: Use i8042 driver

Make use of i8042 driver in keyboard.c.

Required to add PS/2 mouse support.

Tested on Lenovo T500.

Change-Id: If60b5ed922b8fc4b552d0bfd9fe20c0fd6c776bf
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/18596
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Patrick Rudolph 2017-02-04 17:44:17 +01:00 committed by Patrick Georgi
parent 717ba74836
commit 52165966f3
2 changed files with 39 additions and 32 deletions

View File

@ -331,6 +331,7 @@ config FONT_SCALE_FACTOR
config PC_I8042 config PC_I8042
bool "A common PC i8042 driver" bool "A common PC i8042 driver"
default y if PC_KEYBOARD
default n default n
help help
To be used by PC_KEYBOARD and PC_MOUSE. To be used by PC_KEYBOARD and PC_MOUSE.

View File

@ -2,6 +2,7 @@
* This file is part of the libpayload project. * This file is part of the libpayload project.
* *
* Copyright (C) 2008 Advanced Micro Devices, Inc. * Copyright (C) 2008 Advanced Micro Devices, Inc.
* Copyright (C) 2017 Patrick Rudolph <siro@das-labor.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -162,31 +163,21 @@ static struct layout_maps keyboard_layouts[] = {
#define MOD_CAPSLOCK (1 << 2) #define MOD_CAPSLOCK (1 << 2)
#define MOD_ALT (1 << 3) #define MOD_ALT (1 << 3)
static void keyboard_cmd(unsigned char cmd, unsigned char val) static unsigned char keyboard_cmd(unsigned char cmd)
{ {
while (inb(0x64) & 2); i8042_write_data(cmd);
outb(cmd, 0x60);
mdelay(20);
while (inb(0x64) & 2); return i8042_wait_read_ps2() == 0xfa;
outb(val, 0x60);
mdelay(20);
} }
int keyboard_havechar(void) int keyboard_havechar(void)
{ {
unsigned char c = inb(0x64); return i8042_data_ready_ps2();
return (c == 0xFF) ? 0 : c & 1;
} }
unsigned char keyboard_get_scancode(void) unsigned char keyboard_get_scancode(void)
{ {
unsigned char ch = 0; return i8042_read_data_ps2();
if (keyboard_havechar())
ch = inb(0x60);
return ch;
} }
int keyboard_getchar(void) int keyboard_getchar(void)
@ -224,10 +215,12 @@ int keyboard_getchar(void)
case 0x3a: case 0x3a:
if (modifier & MOD_CAPSLOCK) { if (modifier & MOD_CAPSLOCK) {
modifier &= ~MOD_CAPSLOCK; modifier &= ~MOD_CAPSLOCK;
keyboard_cmd(0xed, (0 << 2)); if (keyboard_cmd(0xed))
keyboard_cmd(0 << 2);
} else { } else {
modifier |= MOD_CAPSLOCK; modifier |= MOD_CAPSLOCK;
keyboard_cmd(0xed, (1 << 2)); if (keyboard_cmd(0xed))
keyboard_cmd(1 << 2);
} }
break; break;
} }
@ -262,16 +255,6 @@ int keyboard_getchar(void)
return ret; return ret;
} }
static int keyboard_wait_write(void)
{
int retries = 10000;
while(retries-- && (inb(0x64) & 0x02))
udelay(50);
return (retries <= 0) ? -1 : 0;
}
/** /**
* Set keyboard layout * Set keyboard layout
* @param country string describing the keyboard layout language. * @param country string describing the keyboard layout language.
@ -303,11 +286,32 @@ static struct console_input_driver cons = {
void keyboard_init(void) void keyboard_init(void)
{ {
unsigned int ret;
map = &keyboard_layouts[0]; map = &keyboard_layouts[0];
/* If 0x64 returns 0xff, then we have no keyboard /* Initialized keyboard controller. */
* controller */ if (!i8042_probe() || !i8042_has_ps2())
if (inb(0x64) == 0xFF) return;
/* Empty keyboard buffer */
while (keyboard_havechar())
keyboard_getchar();
/* Enable first PS/2 port */
i8042_cmd(0xae);
/* Set scancode set 1 */
ret = keyboard_cmd(0xf0);
if (!ret)
return;
ret = keyboard_cmd(0x01);
if (!ret)
return;
/* Enable scanning */
ret = keyboard_cmd(0xf4);
if (!ret)
return; return;
console_add_input_driver(&cons); console_add_input_driver(&cons);
@ -325,10 +329,12 @@ void keyboard_disconnect(void)
keyboard_getchar(); keyboard_getchar();
/* Send keyboard disconnect command */ /* Send keyboard disconnect command */
outb(I8042_CMD_DIS_KB, 0x64); i8042_cmd(I8042_CMD_DIS_KB);
keyboard_wait_write();
/* Hand off with empty buffer */ /* Hand off with empty buffer */
while (keyboard_havechar()) while (keyboard_havechar())
keyboard_getchar(); keyboard_getchar();
/* Release keyboard controller driver */
i8042_close();
} }