ps2 init complete, can receive keyboard presses
This commit is contained in:
@@ -18,9 +18,9 @@ stack_top:
|
|||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
|
||||||
_start:
|
_start:
|
||||||
|
cli
|
||||||
mov $stack_top, %esp
|
mov $stack_top, %esp
|
||||||
call kmain
|
call kmain
|
||||||
1:
|
loop:
|
||||||
jmp 1b
|
jmp loop
|
||||||
|
|||||||
@@ -3,4 +3,9 @@
|
|||||||
.global enable_interrupts
|
.global enable_interrupts
|
||||||
enable_interrupts:
|
enable_interrupts:
|
||||||
sti
|
sti
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global io_wait
|
||||||
|
io_wait:
|
||||||
|
outb %al, $0x80
|
||||||
ret
|
ret
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "drivers/pic/pic.h"
|
#include "drivers/pic/pic.h"
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
|
.extern io_wait
|
||||||
|
|
||||||
.global init_pic
|
.global init_pic
|
||||||
init_pic:
|
init_pic:
|
||||||
# init command
|
# init command
|
||||||
@@ -17,7 +19,7 @@ init_pic:
|
|||||||
# cascade
|
# cascade
|
||||||
mov $0x04, %al
|
mov $0x04, %al
|
||||||
outb %al, $PIC1_DATA
|
outb %al, $PIC1_DATA
|
||||||
mov $0x02, %al
|
mov $0x02, %al
|
||||||
outb %al, $PIC2_DATA
|
outb %al, $PIC2_DATA
|
||||||
|
|
||||||
# env
|
# env
|
||||||
@@ -25,7 +27,7 @@ init_pic:
|
|||||||
outb %al, $PIC1_DATA
|
outb %al, $PIC1_DATA
|
||||||
outb %al, $PIC2_DATA
|
outb %al, $PIC2_DATA
|
||||||
|
|
||||||
# mask all
|
# mask
|
||||||
mov $0xFC, %al
|
mov $0xFC, %al
|
||||||
outb %al, $PIC1_DATA
|
outb %al, $PIC1_DATA
|
||||||
mov $0xFF, %al
|
mov $0xFF, %al
|
||||||
@@ -33,10 +35,6 @@ init_pic:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.global io_wait
|
|
||||||
io_wait:
|
|
||||||
ret
|
|
||||||
|
|
||||||
.global send_eoi_master
|
.global send_eoi_master
|
||||||
send_eoi_master:
|
send_eoi_master:
|
||||||
mov $0x20, %al
|
mov $0x20, %al
|
||||||
@@ -49,3 +47,19 @@ send_eoi_slave:
|
|||||||
outb %al, $PIC2_COMMAND
|
outb %al, $PIC2_COMMAND
|
||||||
call send_eoi_master
|
call send_eoi_master
|
||||||
ret
|
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
70
kernel/drivers/ps2/ps2.c
Normal 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
19
kernel/drivers/ps2/ps2.h
Normal 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
|
||||||
87
kernel/drivers/ps2/ps2_stubs.S
Normal file
87
kernel/drivers/ps2/ps2_stubs.S
Normal 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
|
||||||
@@ -27,12 +27,6 @@ isr_common_stub:
|
|||||||
addl $8, %esp
|
addl $8, %esp
|
||||||
iret
|
iret
|
||||||
|
|
||||||
.global master_eoi
|
|
||||||
master_eoi:
|
|
||||||
movb $0x20, %al
|
|
||||||
outb %al, $0x20
|
|
||||||
ret
|
|
||||||
|
|
||||||
.extern idtr
|
.extern idtr
|
||||||
.global load_idt
|
.global load_idt
|
||||||
load_idt:
|
load_idt:
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
extern void send_eoi_master(void);
|
extern void send_eoi_master(void);
|
||||||
extern void send_eoi_slave(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 {
|
struct registers {
|
||||||
uint32_t edi, esi, ebp, esp_dummy, ebx, edx, ecx, eax;
|
uint32_t edi, esi, ebp, esp_dummy, ebx, edx, ecx, eax;
|
||||||
@@ -17,29 +21,42 @@ const char* err_messages[32] = {
|
|||||||
[0] = "Divide by 0",
|
[0] = "Divide by 0",
|
||||||
[1] = "",
|
[1] = "",
|
||||||
[8] = "",
|
[8] = "",
|
||||||
[13] = "General Protection Fault",
|
[13] = "General Protection Fault",a->i
|
||||||
[14] = "Page Fault",
|
[14] = "Page Fault",
|
||||||
};
|
};
|
||||||
|
|
||||||
void common_interrupt_handler(struct registers *regs) {
|
void common_interrupt_handler(struct registers *args) {
|
||||||
switch (regs->int_no) {
|
switch (args->int_no) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
case 12:
|
||||||
case 13:
|
case 13:
|
||||||
case 14:
|
case 14:
|
||||||
|
case 15:
|
||||||
|
case 16:
|
||||||
kprint("CPU Error: ");
|
kprint("CPU Error: ");
|
||||||
kprint(err_messages[regs->int_no]);
|
kprint(err_messages[args->int_no]);
|
||||||
kprint("\n");
|
kprint("\n");
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
// wake the PIT timer driver
|
// wake the PIT timer driver
|
||||||
send_eoi_master();
|
send_eoi_master();
|
||||||
break;
|
break;
|
||||||
case 33:
|
case 33: {
|
||||||
kprint("keypress detected\n");
|
uint8_t data = ps2_read_data();
|
||||||
send_eoi_master();
|
send_eoi_master();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
kprint("Received unhandled interrupt\n");
|
kprint("Received unhandled interrupt\n");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ extern void init_idt();
|
|||||||
extern void init_gdt();
|
extern void init_gdt();
|
||||||
extern void init_pic();
|
extern void init_pic();
|
||||||
extern void init_pit();
|
extern void init_pit();
|
||||||
|
extern int init_ps2();
|
||||||
extern void enable_interrupts();
|
extern void enable_interrupts();
|
||||||
|
|
||||||
void kmain(void)
|
void kmain(void)
|
||||||
@@ -32,6 +33,13 @@ void kmain(void)
|
|||||||
init_pit();
|
init_pit();
|
||||||
kprint("PIT initialized\n");
|
kprint("PIT initialized\n");
|
||||||
|
|
||||||
|
int result = init_ps2();
|
||||||
|
if (result == -1) {
|
||||||
|
kprint("PS2 init failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
kprint("PS2 initialized\n");
|
||||||
|
|
||||||
enable_interrupts();
|
enable_interrupts();
|
||||||
kprint("Interrupts enabled\n");
|
kprint("Interrupts enabled\n");
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,8 @@ void kprint(const char *str) {
|
|||||||
kout->putchar(*str);
|
kout->putchar(*str);
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kputc(const char c) {
|
||||||
|
kout->putchar(c);
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,6 @@
|
|||||||
#define KLIBPRINT_H
|
#define KLIBPRINT_H
|
||||||
|
|
||||||
void kprint(const char* str);
|
void kprint(const char* str);
|
||||||
|
void kputc(const char c);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user