Skip to content

Commit

Permalink
keyboard: 8042 initialization
Browse files Browse the repository at this point in the history
Initialize the 8042 controller of the keyboard

Signed-off-by: Daniele Ahmed <ahmeddan amazon c;om >
  • Loading branch information
82marbag authored and wipawel committed Nov 10, 2020
1 parent 6e57181 commit 30a0584
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 10 deletions.
2 changes: 1 addition & 1 deletion arch/x86/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <console.h>
#include <drivers/keyboard.h>
#include <drivers/pit.h>
#include <drivers/serial.h>
#include <drivers/keyboard.h>
#include <ktf.h>
#include <lib.h>
#include <percpu.h>
Expand Down
2 changes: 1 addition & 1 deletion common/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ void kernel_main(void) {
printk("All tasks done.\n");

while (1)
cpu_relax();
echo_loop();
}
2 changes: 1 addition & 1 deletion common/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
#include <cmdline.h>
#include <console.h>
#include <cpuid.h>
#include <ioapic.h>
#include <drivers/keyboard.h>
#include <ioapic.h>
#include <ktf.h>
#include <lib.h>
#include <multiboot.h>
Expand Down
92 changes: 90 additions & 2 deletions drivers/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,96 @@ static struct {
unsigned init;
} keyboard_state;

void init_keyboard(void) {
outb(PIC1_PORT_DATA, KEYBOARD_IRQ_UNMASK); /* unmask keyboard irq */
void init_keyboard() {
printk("Initializing keyboard driver\n");

/* Disable devices */
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_0);
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_1);

/* Flush output buffer */
while (inb(KEYBOARD_PORT_DATA) & KEYBOARD_STATUS_OUT_FULL)
; /* discard leftover bytes */

/* Controller configuration */
char current_status;
int dual_channel;

/* Read controller config */
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_READ_CONFIGURATION);
current_status = inb(KEYBOARD_PORT_DATA);

dual_channel = !!(current_status & (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1));
printk("Current PS/2 status before: %x\n", current_status);
/* Disable IRQs and translation */
current_status = current_status &
~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT) &
~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT) &
~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION);
/* Write controller config */
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION);
outb(KEYBOARD_PORT_DATA, current_status);

printk("Current PS/2 status after mods: %x\n", current_status);
printk("PS/2 dual channel? %d\n", dual_channel);

/* Controller self test */
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_SELF_TEST);
if (inb(KEYBOARD_PORT_DATA) != KEYBOARD_RES_SELF_TEST) {
printk("Self test did not succed\n");
return;
}

/* Determine whether second channel exists */
if (dual_channel) {
printk("Enabling second PS/2 port\n");
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_1);
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_READ_CONFIGURATION);
current_status = inb(KEYBOARD_PORT_DATA);
dual_channel =
(current_status & (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1)) == 0;
}
if (dual_channel)
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_1);

/* Interface tests */
int port1, port2 = 0;
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_0);
port1 = inb(KEYBOARD_PORT_DATA) == 0;
if (dual_channel) {
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_1);
port2 = inb(KEYBOARD_PORT_DATA) == 0;
}

printk("Port1 available? %d - port2 available? %d\n", port1, port2);
if (!port1 && !port2) {
printk("No available PS/2 working ports\n");
return;
}

/* Enable devices */
if (port1) {
printk("Keyboard: enabling first channel\n");
current_status = current_status |
(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT) |
(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1) |
(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION);
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION);
outb(KEYBOARD_PORT_DATA, current_status);

pic_enable_irq(PIC1_DEVICE_SEL, KEYBOARD_IRQ);
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_0);
}
else {
printk("Keyboard: enabling second channel\n");
current_status =
current_status | (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT);
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION);
outb(KEYBOARD_PORT_DATA, current_status);

pic_enable_irq(PIC1_DEVICE_SEL, KEYBOARD_IRQ_2);
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_1);
}

memset(&keyboard_state, 0, sizeof(keyboard_state));
}
Expand Down
42 changes: 37 additions & 5 deletions include/drivers/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,48 @@
#define KEYBOARD_PORT_CMD 0x64 /* keyboard command port */
#define KEYBOARD_PORT_DATA 0x60 /* keyboard data port */

#define KEYBOARD_IRQ0_OFFSET (PIC_IRQ0_OFFSET + 1) /* keyboard irq offset */
#define KEYBOARD_IRQ_UNMASK (~2) /* mask with keyboard irq enabled, others disabled */
#define KEYBOARD_IRQ 0x01
#define KEYBOARD_IRQ_2 0x04 /* Second port */
#define KEYBOARD_IRQ0_OFFSET \
(PIC_IRQ0_OFFSET + KEYBOARD_IRQ) /* keyboard first channel irq offset */
#define KEYBOARD_2_IRQ0_OFFSET (PIC_IRQ0_OFFSET + KEYBOARD_IRQ_2)

#define KEYBOARD_STATUS_OUT_FULL 1 /* bit set when the keyboard buffer is full */
#define KEYBOARD_STATUS_OUT_FULL 0x01 /* bit set when the keyboard buffer is full */

enum {
KEYBOARD_CMD_WRITE_CONFIGURATION = 0x60, /* Write configuration byte */
KEYBOARD_CMD_READ_CONFIGURATION = 0x20, /* Read configuration byte */
KEYBOARD_CMD_SELF_TEST = 0xAA,
KEYBOARD_CMD_TEST_PORT_0 = 0xAB,
KEYBOARD_CMD_TEST_PORT_1 = 0xA9,
KEYBOARD_CMD_DISABLE_PORT_0 = 0xAD,
KEYBOARD_CMD_DISABLE_PORT_1 = 0xA7,
KEYBOARD_CMD_ENABLE_PORT_0 = 0xAE,
KEYBOARD_CMD_ENABLE_PORT_1 = 0xA8,
} keyboard_cmd;
typedef enum keyboard_cmd keyboard_cmd_t;

enum {
KEYBOARD_RES_SELF_TEST = 0x55,
} keyboard_res;

enum {
KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT,
KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT,
KEYBOARD_CONTROLLER_CONFIG_BIT_SYS_FLAG,
KEYBOARD_CONTROLLER_CONFIG_BIT_ZERO,
KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_0,
KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1,
KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION,
KEYBOARD_CONTROLLER_CONFIG_BIT_ZERO_,
} keyboard_controller_config_byte;
typedef enum keyboard_controller_config_byte keyboard_controller_config_byte_t;

#define KEY_BUF 80 /* size of internal input buffer */

#define SCAN_RELEASE_MASK 0x80 /* bit set on key release */

#define KEY_NULL 0x0 /* no key */
#define KEY_NULL 0x00 /* no key */

/* scan codes */
#define SCAN_NULL 0x0
Expand Down Expand Up @@ -76,7 +108,7 @@
#define SCAN_INS 0x52
#define SCAN_DEL 0x53

void init_keyboard(void);
void init_keyboard();
void keyboard_interrupt_handler(void);
unsigned int keyboard_process_keys(void);

Expand Down

0 comments on commit 30a0584

Please sign in to comment.