Okay wow i forgot to commit a bunch of stuff

I added some work on a keyboard driver here
also changed the emulation system, since bochs was giving me headaches when it came to keyboard input
added some todo stuff.. probably some cleanup, idk
This commit is contained in:
2025-06-03 19:08:45 -04:00
parent ca77157344
commit af92026a74
11 changed files with 160 additions and 156 deletions

View File

@ -44,7 +44,8 @@ os.iso: kernel.elf
grub-mkrescue -o $@ iso
run: os.iso
bochs -f util/bochsrc.txt -q
kitty --hold sh -c "gdb kernel.elf -x util/gdbcmds" &
qemu-system-i386 -s -cdrom os.iso
#TODO: when i inevitably do add libc, this is going to fail because they have the same name as the libk objects
#TODO: so we'll need to do a batch rename on one of the two object files,

7
TODO.md Normal file
View File

@ -0,0 +1,7 @@
## What do I need to do?
Exception handling is a must for next part, we need to be able to dianogse issues better
- Want the address of the fault
- Proper handling of the issue
- Maybe dump registers?

View File

@ -70,6 +70,8 @@ void gdt_init(void)
reloadSegments();
#ifdef __TESTING__
kinfo("Initialized the GDT");
#endif
#ifdef __TESTING__
dump_gdt();
#endif
}

View File

@ -27,18 +27,10 @@ void exception_handler(unsigned int i)
}
if (i == PIC_KEYB) {
#ifdef __TESTING__
//kinfo("Sending EOI instruction to KEYB");
#endif
unsigned char in = inb(0x60);
char to_print = decode_key_enum(decode_scancode(in));
if (to_print != '\0')
printf("%c", to_print);
/**
* TODO: this is a cute temporary fix but lets do a real keyboard driver please?
*/
#ifdef __TESTING__
printf("scancode: %x\n", in);
#endif
PIC_sendEOI(1);
}

View File

@ -1,126 +1,95 @@
#include <stdbool.h>
#include <stdint.h>
#include <queue.h>
#ifdef __TESTING__
#include <kernel/_kernel.h>
#include <stdio.h>
#endif
#include <kernel/x86/keyb.h>
#include <kernel/x86/io.h>
bool is_shift_down = false;
queue kb_cmd_queue;
// current plan is to create a a multi d array
//
//
// 16 entries each for each scan code... so
// 0x01..0x0F (15)/ this is the top row, so esc - 1..0, etc
// 0x10..0x1F (16) ...
// 0x20..0x2F ...
// these arrays will keep a 0/1 flag to see if these keys are pressed
// as a stort of state machine
// this will also let us tell multiple keys pressed
//
// another more simple version, which i could start with
//
// is do a Single character as currently pressed
// and a bitflag we can mask for leftshift, leftctrl, right shift, right ctrl, alt, etc being pressed down
//
//
//
struct keyboard_state keyb_state;
void init_kb(void)
{
#ifdef __TESTING__
puts("Initializing keyboard driver!");
#endif
init_queue(&kb_cmd_queue);
keyb_state.leds = 0;
queue_kb_command(KEYB_CMD_ENABLE_SCANNING);
queue_kb_command(KEYB_CMD_SET_DEFAULT_PARAMS);
//queue_kb_command(KEYB_CMD_SET_TYPEMATIC);
//queue_kb_command(0x1F);
send_kb_commands();
#ifdef __TESTING__
puts("Initialized keyboard driver!");
#endif
}
void queue_kb_command(uint8_t command)
{enqueue(&kb_cmd_queue, command);}
void send_kb_commands(void)
{
int i;
uint8_t resp, cmd;
while (!queue_is_empty(&kb_cmd_queue)) {
cmd = queue_peek(&kb_cmd_queue);
for (i = 0; i < KEYB_CMD_RETRIES; i++) {
outb(KEYB_PORT, cmd);
io_wait();
resp = inb(KEYB_PORT);
io_wait();
switch(resp) {
case KEYB_RESP_ACK:
break;
case KEYB_RESP_RESEND:
continue;
default:
break;
}
}
dequeue(&kb_cmd_queue);
}
}
kb_key_press_t decode_scancode(uint8_t scancode)
{return (kb_key_press_t) scancode;}
// TODO: check the shift scan code as a boolean, if yes ... blah blah
char decode_key_enum(kb_key_press_t keycode)
{
switch(keycode) {
case KEY_Q:
return (is_shift_down) ? 'Q' : 'q';
case KEY_W:
return (is_shift_down) ? 'W' : 'w';
case KEY_E:
return (is_shift_down) ? 'E' : 'e';
case KEY_R:
return (is_shift_down) ? 'R' : 'r';
case KEY_T:
return (is_shift_down) ? 'T' : 't';
case KEY_Y:
return (is_shift_down) ? 'Y' : 'y';
case KEY_U:
return (is_shift_down) ? 'U' : 'u';
case KEY_I:
return (is_shift_down) ? 'I' : 'i';
case KEY_O:
return (is_shift_down) ? 'O' : 'o';
case KEY_P:
return (is_shift_down) ? 'P' : 'p';
case KEY_A:
return (is_shift_down) ? 'A' : 'a';
case KEY_S:
return (is_shift_down) ? 'S' : 's';
case KEY_D:
return (is_shift_down) ? 'D' : 'd';
case KEY_F:
return (is_shift_down) ? 'F' : 'f';
case KEY_G:
return (is_shift_down) ? 'G' : 'g';
case KEY_H:
return (is_shift_down) ? 'H' : 'h';
case KEY_J:
return (is_shift_down) ? 'J' : 'j';
case KEY_K:
return (is_shift_down) ? 'K' : 'k';
case KEY_L:
return (is_shift_down) ? 'L' : 'l';
case KEY_Z:
return (is_shift_down) ? 'Z' : 'z';
case KEY_X:
return (is_shift_down) ? 'X' : 'x';
case KEY_C:
return (is_shift_down) ? 'C' : 'c';
case KEY_V:
return (is_shift_down) ? 'V' : 'v';
case KEY_B:
return (is_shift_down) ? 'B' : 'b';
case KEY_N:
return (is_shift_down) ? 'N' : 'n';
case KEY_M:
return (is_shift_down) ? 'M' : 'm';
case KEY_1:
return (is_shift_down) ? '!' : '1';
case KEY_2:
return (is_shift_down) ? '@' : '2';
case KEY_3:
return (is_shift_down) ? '#' : '3';
case KEY_4:
return (is_shift_down) ? '$' : '4';
case KEY_5:
return (is_shift_down) ? '%' : '5';
case KEY_6:
return (is_shift_down) ? '^' : '6';
case KEY_7:
return (is_shift_down) ? '&' : '7';
case KEY_8:
return (is_shift_down) ? '*' : '8';
case KEY_9:
return (is_shift_down) ? '(' : '9';
case KEY_0:
return (is_shift_down) ? ')' : '0';
case KEY_MINUS:
return (is_shift_down) ? '_' : '-';
case KEY_EQUALS:
return (is_shift_down) ? '=' : '+';
case KEY_LEFT_BRACKET:
return (is_shift_down) ? '{' : '[';
case KEY_RIGHT_BRACKET:
return (is_shift_down) ? '}' : ']';
case KEY_BACKSLASH:
return (is_shift_down) ? '|' : '\\';
case KEY_SEMICOLON:
return (is_shift_down) ? ':' : ';';
case KEY_SINGLE_QUOTE:
return (is_shift_down) ? '\"' : '\'';
case KEY_COMMA:
return (is_shift_down) ? '<' : ',';
case KEY_PERIOD:
return (is_shift_down) ? '>' : '.';
case KEY_FORWARDSLASH:
return (is_shift_down) ? '?' : '/';
case KEY_BACK_TICK:
return (is_shift_down) ? '~' : '`';
case KEY_ENTER:
return '\n';
case KEY_SPACE:
return ' ';
case KEY_LEFT_SHIFT:
case KEY_RIGHT_SHIFT:
is_shift_down = true;
return '\0';
case KEY_LEFT_SHIFT_R:
case KEY_RIGHT_SHIFT_R:
is_shift_down = false;
return '\0'; // TODO: should i send a character on a no op key?
default:
return '\0';
}
}

View File

@ -3,9 +3,37 @@
#ifndef ARCH_KEYB_H
#define ARCH_KEYB_H
#define KEYB_DATA_PORT (0x60)
#define KEYB_STATUS_PORT (0x64)
#define KEYB_COMMAND_PORT (0x64)
#define KEYB_PORT (0x60)
#define KEYB_CMD_RETRIES 3
#define KEYB_CMD_SET_LEDS (0xED)
#define KEYB_CMD_ECHO (0xEE)
#define KEYB_CMD_DO_SCAN_CODE (0xF0)
#define KEYB_CMD_IDENTIFY_KEYB (0xF2)
#define KEYB_CMD_SET_TYPEMATIC (0xF3)
#define KEYB_CMD_ENABLE_SCANNING (0xF4)
#define KEYB_CMD_DISABLE_SCANNING (0xF5)
#define KEYB_CMD_SET_DEFAULT_PARAMS (0xF6)
#define KEYB_CMD_TYPEMATIC_AUTOREPEAT_3 (0xF7)
#define KEYB_CMD_ALL_MAKE_RELEASE_3 (0xF8)
#define KEYB_CMD_MAKE_ONLY_3 (0xF9)
#define KEYB_CMD_TYPE_AUTOREPEAT_MAKE_RELEASE_3 (0xFA)
#define KEYB_CMD_KEY_TYPEMATIC_AUTOREPEAT_3 (0xFB)
#define KEYB_CMD_KEY_MAKE_RELEASE_3 (0xFC)
#define KEYB_CMD_KEY_MAKE_3 (0xFD)
#define KEYB_RESEND_LAST_BYTE (0xFE)
#define KEYB_RESET_SELF_TEST (0xFF)
#define KEYB_LED_SCRL_LCK (1 << 0)
#define KEYB_LED_NUM_LCK (1 << 1)
#define KEYB_LED_CAP_LCK (1 << 2)
#define KEYB_GET_SCAN_SET (0x00)
#define KEYB_SET_SCAN_1 (0x01)
#define KEYB_SET_SCAN_2 (0x02)
#define KEYB_SET_SCAN_3 (0x03)
#define KEYB_RESP_ERR (0x00)
@ -72,7 +100,20 @@ typedef enum {
KEY_F12_R,
} kb_key_press_t;
struct keypress {
kb_key_press_t key_code;
uint8_t
};
struct keyboard_state {
uint8_t leds;
};
void init_kb(void);
void send_kb_commands(void);
void queue_kb_command(uint8_t command);
kb_key_press_t decode_scancode(uint8_t scancode);

View File

@ -7,6 +7,9 @@
#include <kernel/x86/gdt.h>
#include <kernel/x86/idt.h>
#include <kernel/x86/io.h>
#include <kernel/x86/keyb.h>
void kmain(void)
{
@ -22,17 +25,7 @@ void kmain(void)
serial_initialize();
#endif
/**
* The computer is now hanging on INTERRUPT 32,
* this is good because that means the PIC is working, its the timer interrupt, except... the PIT is masked off...
* we need to now implement the ISR routines in exception_handler,
* first i want to implement all of the code for the basic exceptions..
* then i want to setup the PIC triggers
*
* now for keyboard stuff, i believe i need to start looking into setting up a ps/2 driver before the interrupts will even start arriving..
*
*/
init_kb();
printf("Entering loop...\n");
while (1) {

View File

@ -14,7 +14,12 @@ void init_queue(queue *q)
}
bool queue_is_empty(queue *q)
{return (q->front == q->rear - 1);} ; // TODO: if this returns true, shouldn't we just be re-init-ing because we have the space to take up that used array
{
bool empty = q->front == q->rear - 1;
if (empty)
init_queue(q);
return empty;
}
bool queue_is_full(queue *q)
{return (q->rear == MAX_QUEUE_SIZE);} // TODO: this is an error for SURE
@ -40,7 +45,7 @@ void dequeue(queue* q)
q->front++;
}
uint8_t peek(queue* q)
uint8_t queue_peek(queue* q)
{
if (queue_is_empty(q)) {
#ifdef __TESTING__

View File

@ -1,11 +0,0 @@
megs: 32
display_library: sdl
romimage: file=/usr/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
ata0-master: type=cdrom, path=os.iso, status=inserted
boot: cdrom
log: bochslog.txt
clock: sync=realtime, time0=local
cpu: count=1, ips=1000000
com1: enabled=1, mode=file, dev=com1.out
keyboard: type=mf, serial_delay=150

2
util/gdbcmds Normal file
View File

@ -0,0 +1,2 @@
target remote :1234
c

3
util/run-qemu.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
qemu-system-i386 -s -cdrom os.iso & gdb kernel.elf -x=util/gdbcmds