ps2 init complete, can receive keyboard presses

This commit is contained in:
2026-06-13 19:53:57 -04:00
parent 3ecbcdf369
commit 2ab98fe582
11 changed files with 240 additions and 21 deletions

View File

@@ -18,9 +18,9 @@ stack_top:
.section .text
.global _start
.type _start, @function
_start:
cli
mov $stack_top, %esp
call kmain
1:
jmp 1b
loop:
jmp loop

View File

@@ -4,3 +4,8 @@
enable_interrupts:
sti
ret
.global io_wait
io_wait:
outb %al, $0x80
ret

View File

@@ -1,6 +1,8 @@
#include "drivers/pic/pic.h"
.code32
.extern io_wait
.global init_pic
init_pic:
# init command
@@ -25,7 +27,7 @@ init_pic:
outb %al, $PIC1_DATA
outb %al, $PIC2_DATA
# mask all
# mask
mov $0xFC, %al
outb %al, $PIC1_DATA
mov $0xFF, %al
@@ -33,10 +35,6 @@ init_pic:
ret
.global io_wait
io_wait:
ret
.global send_eoi_master
send_eoi_master:
mov $0x20, %al
@@ -49,3 +47,19 @@ send_eoi_slave:
outb %al, $PIC2_COMMAND
call send_eoi_master
ret
.global read_isr_master
read_isr_master:
xorl %eax, %eax
mov $0x0B, %al
outb %al, $PIC1_COMMAND
in $PIC1_COMMAND, %al
ret
.global read_isr_slave
read_isr_slave:
xorl %eax, %eax
mov $0x0B, %al
outb %al, $PIC2_COMMAND
in $PIC2_COMMAND, %al
ret

70
kernel/drivers/ps2/ps2.c Normal file
View File

@@ -0,0 +1,70 @@
#include <stdint.h>
#include <drivers/ps2/ps2.h>
extern void ps2_wait_input_empty(void);
extern void ps2_wait_output_full(void);
extern void ps2_write_command(uint8_t);
extern uint8_t ps2_read_data(void);
extern void ps2_write_data(uint8_t);
extern void ps2_flush_output_buffer(void);
extern void io_wait(void);
static uint8_t read_ccb() {
ps2_write_command(CMD_READ_CCB);
io_wait();
return ps2_read_data();
}
static void write_ccb(uint8_t ccb) {
ps2_write_command(CMD_WRITE_CCB);
io_wait();
ps2_write_data(ccb);
io_wait();
}
static int perform_self_test() {
ps2_write_command(CMD_SELF_TEST);
io_wait();
return ps2_read_data();
}
static int test_port_1() {
ps2_write_command(CMD_TEST_P1);
io_wait();
return ps2_read_data();
}
static void enable_port_1() {
ps2_write_command(CMD_ENABLE_P1);
io_wait();
}
int init_ps2() {
ps2_write_command(CMD_DISABLE_P1);
ps2_write_command(CMD_DISABLE_P2);
ps2_flush_output_buffer();
uint8_t ccb = read_ccb();
ccb = ccb & 0xEC;
write_ccb(ccb);
int result = perform_self_test();
if (result != SELF_TEST_SUCCESS) {
return -1;
}
result = test_port_1();
if (result != PORT_TEST_SUCCESS) {
return -1;
}
enable_port_1();
ccb = read_ccb();
ccb |= 0x01; // this enables interrupts for port 1, which we want
write_ccb(ccb);
return 0;
}

19
kernel/drivers/ps2/ps2.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef KPS2_H
#define KPS2_H
#define PS2_DATA 0x60
#define PS2_STATUS 0x64
#define PS2_COMMAND 0x64
#define CMD_DISABLE_P1 0xAD
#define CMD_DISABLE_P2 0xAE
#define CMD_READ_CCB 0x20
#define CMD_WRITE_CCB 0x60
#define CMD_SELF_TEST 0xAA
#define CMD_TEST_P1 0xAB
#define CMD_ENABLE_P1 0xAE
#define SELF_TEST_SUCCESS 0x55
#define PORT_TEST_SUCCESS 0x00
#endif

View File

@@ -0,0 +1,87 @@
#include "drivers/ps2/ps2.h"
.code32
.global ps2_wait_input_empty
.global ps2_wait_output_full
.global ps2_write_command
.global ps2_read_data
.global ps2_write_data
.global ps2_flush_output_buffer
.extern io_wait
# helpers
ps2_wait_input_empty: #(void) -> void
push %ebp
mov %esp, %ebp
1:
inb $PS2_STATUS, %al
andb $0x02, %al
jnz 1b
leave
ret
ps2_wait_output_full: #(void) -> void
push %ebp
mov %esp, %ebp
1:
inb $PS2_STATUS, %al
andb $0x01, %al
jz 1b
leave
ret
ps2_write_command: #(uint8_t command) -> void
push %ebp
mov %esp, %ebp
call ps2_wait_input_empty
xor %eax, %eax
movb 8(%ebp), %al
outb %al, $PS2_COMMAND
leave
ret
ps2_read_data: #(void) -> uint8_t
push %ebp
mov %esp, %ebp
call ps2_wait_output_full
xor %eax, %eax
inb $PS2_DATA, %al
leave
ret
ps2_write_data: #(uint8_t) -> void
push %ebp
mov %esp, %ebp
call ps2_wait_input_empty
xor %eax, %eax
movb 8(%ebp), %al
outb %al, $PS2_DATA
leave
ret
ps2_flush_output_buffer: #(void) -> void
push %ebp
mov %esp, %ebp
1:
inb $PS2_STATUS, %al
andb $0x01, %al
jz 2f
inb $PS2_DATA, %al
jmp 1b
2:
leave
ret

View File

@@ -27,12 +27,6 @@ isr_common_stub:
addl $8, %esp
iret
.global master_eoi
master_eoi:
movb $0x20, %al
outb %al, $0x20
ret
.extern idtr
.global load_idt
load_idt:

View File

@@ -3,6 +3,10 @@
extern void send_eoi_master(void);
extern void send_eoi_slave(void);
extern uint8_t read_isr_master(void);
extern uint8_t read_isr_slave(void);
extern uint8_t ps2_read_data();
struct registers {
uint32_t edi, esi, ebp, esp_dummy, ebx, edx, ecx, eax;
@@ -17,29 +21,42 @@ const char* err_messages[32] = {
[0] = "Divide by 0",
[1] = "",
[8] = "",
[13] = "General Protection Fault",
[13] = "General Protection Fault",a->i
[14] = "Page Fault",
};
void common_interrupt_handler(struct registers *regs) {
switch (regs->int_no) {
void common_interrupt_handler(struct registers *args) {
switch (args->int_no) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
kprint("CPU Error: ");
kprint(err_messages[regs->int_no]);
kprint(err_messages[args->int_no]);
kprint("\n");
break;
case 32:
// wake the PIT timer driver
send_eoi_master();
break;
case 33:
kprint("keypress detected\n");
case 33: {
uint8_t data = ps2_read_data();
send_eoi_master();
break;
}
default:
kprint("Received unhandled interrupt\n");
return;

View File

@@ -9,6 +9,7 @@ extern void init_idt();
extern void init_gdt();
extern void init_pic();
extern void init_pit();
extern int init_ps2();
extern void enable_interrupts();
void kmain(void)
@@ -32,6 +33,13 @@ void kmain(void)
init_pit();
kprint("PIT initialized\n");
int result = init_ps2();
if (result == -1) {
kprint("PS2 init failed\n");
return;
}
kprint("PS2 initialized\n");
enable_interrupts();
kprint("Interrupts enabled\n");

View File

@@ -9,3 +9,7 @@ void kprint(const char *str) {
str++;
}
}
void kputc(const char c) {
kout->putchar(c);
}

View File

@@ -2,5 +2,6 @@
#define KLIBPRINT_H
void kprint(const char* str);
void kputc(const char c);
#endif