summaryrefslogtreecommitdiff
path: root/kernel/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers')
-rw-r--r--kernel/drivers/ata.c18
-rw-r--r--kernel/drivers/gpu.c2
-rw-r--r--kernel/drivers/gpu/bochs.c4
-rw-r--r--kernel/drivers/gpu/gop.c4
-rw-r--r--kernel/drivers/pit.c9
-rw-r--r--kernel/drivers/ps2.c268
6 files changed, 287 insertions, 18 deletions
diff --git a/kernel/drivers/ata.c b/kernel/drivers/ata.c
index 63c4559..6c8de86 100644
--- a/kernel/drivers/ata.c
+++ b/kernel/drivers/ata.c
@@ -506,7 +506,7 @@ static uint8_t get_ata_cmd_for_access(enum lba_mode lba_mode,
static enum ide_error ide_device_ata_access(struct ide_device *dev,
enum access_mode mode, uint32_t lba,
- uint8_t numsects,
+ uint16_t numsects,
uint16_t buf[numsects * 256])
{
struct ide_channel *chan = channel(dev->channel_idx);
@@ -521,7 +521,7 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
chan->no_interrupt = (ide_irq_invoked = 0x0) + 0x02);
// select one from LBA28, LBA48 or CHS
- if (lba >= 0x10000000) {
+ if (lba >= 0x10000000 || numsects > UINT8_MAX) {
// drive should support LBA in this case, or you are giving a bad LBA
lba_mode = LBA48;
lba_io[0] = (lba & 0x000000FF) >> 0;
@@ -565,19 +565,21 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
if (lba_mode == CHS) {
ide_channel_write(chan, ATA_REG_HDDEVSEL,
0xA0 | (dev->drive_idx << 4) | head);
- } else {
+ } else if (lba_mode == LBA28) {
ide_channel_write(chan, ATA_REG_HDDEVSEL,
0xE0 | (dev->drive_idx << 4) | head);
+ } else {
+ ide_channel_write(chan, ATA_REG_HDDEVSEL, 0x40 | (dev->drive_idx << 4));
}
// write Parameters
- if (lba_mode == 2) {
- ide_channel_write(chan, ATA_REG_SECCOUNT1, 0);
+ if (lba_mode == LBA48) {
+ ide_channel_write(chan, ATA_REG_SECCOUNT1, (numsects >> 8) & 0xff);
ide_channel_write(chan, ATA_REG_LBA3, lba_io[3]);
ide_channel_write(chan, ATA_REG_LBA4, lba_io[4]);
ide_channel_write(chan, ATA_REG_LBA5, lba_io[5]);
}
- ide_channel_write(chan, ATA_REG_SECCOUNT0, numsects);
+ ide_channel_write(chan, ATA_REG_SECCOUNT0, numsects & 0xff);
ide_channel_write(chan, ATA_REG_LBA0, lba_io[0]);
ide_channel_write(chan, ATA_REG_LBA1, lba_io[1]);
ide_channel_write(chan, ATA_REG_LBA2, lba_io[2]);
@@ -624,7 +626,7 @@ static enum ide_error ide_device_ata_access(struct ide_device *dev,
}
enum ide_error ide_device_read_sectors(ide_device_t dev_identifier,
- uint8_t numsects, uint32_t lba,
+ uint16_t numsects, uint32_t lba,
uint16_t buf[numsects * 256])
{
struct ide_device *dev = device(dev_identifier);
@@ -656,7 +658,7 @@ enum ide_error ide_device_read_sectors(ide_device_t dev_identifier,
}
enum ide_error ide_device_write_sectors(ide_device_t device_identifier,
- uint8_t numsects, uint32_t lba,
+ uint16_t numsects, uint32_t lba,
uint16_t buf[numsects * 256])
{
struct ide_device *dev = device(device_identifier);
diff --git a/kernel/drivers/gpu.c b/kernel/drivers/gpu.c
index 3d79b99..fc6ec8e 100644
--- a/kernel/drivers/gpu.c
+++ b/kernel/drivers/gpu.c
@@ -7,7 +7,7 @@
#include <comus/term.h>
#include <comus/asm.h>
-struct gpu *gpu_dev = NULL;
+struct gpu_dev *gpu_dev = NULL;
int gpu_init(void)
{
diff --git a/kernel/drivers/gpu/bochs.c b/kernel/drivers/gpu/bochs.c
index f8e5820..2dfe62e 100644
--- a/kernel/drivers/gpu/bochs.c
+++ b/kernel/drivers/gpu/bochs.c
@@ -31,7 +31,7 @@
#define BOCHS_HEIGHT 768
#define BOCHS_BIT_DEPTH 32
-struct gpu bochs_dev = { 0 };
+struct gpu_dev bochs_dev = { 0 };
static void write(uint16_t index, uint16_t data)
{
@@ -45,7 +45,7 @@ static uint16_t read(uint16_t value)
return inw(DATA);
}
-int bochs_init(struct gpu **gpu_dev)
+int bochs_init(struct gpu_dev **gpu_dev)
{
struct pci_device bochs = { 0 };
bool found =
diff --git a/kernel/drivers/gpu/gop.c b/kernel/drivers/gpu/gop.c
index 47da952..a57766d 100644
--- a/kernel/drivers/gpu/gop.c
+++ b/kernel/drivers/gpu/gop.c
@@ -5,11 +5,11 @@
#include <comus/efi.h>
#include <efi.h>
-struct gpu gop_dev = { 0 };
+struct gpu_dev gop_dev = { 0 };
static EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
-int gop_init(struct gpu **gpu_dev)
+int gop_init(struct gpu_dev **gpu_dev)
{
gop = efi_get_gop();
if (gop == NULL || gop->Mode == NULL)
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c
index d77df08..53a9263 100644
--- a/kernel/drivers/pit.c
+++ b/kernel/drivers/pit.c
@@ -22,9 +22,8 @@ uint16_t pit_read_divider(void)
void pit_set_divider(uint16_t count)
{
(void)count;
- // FIXME: broken on -O0
- // cli();
- // outb(CHAN_0, count & 0xFF); // low byte
- // outb(CHAN_0, (count & 0xFF00) >> 8); // high byte
- // sti();
+ cli();
+ outb(CHAN_0, count & 0xFF); // low byte
+ outb(CHAN_0, (count & 0xFF00) >> 8); // high byte
+ sti();
}
diff --git a/kernel/drivers/ps2.c b/kernel/drivers/ps2.c
new file mode 100644
index 0000000..e260f6b
--- /dev/null
+++ b/kernel/drivers/ps2.c
@@ -0,0 +1,268 @@
+#include <comus/drivers/ps2.h>
+#include <comus/keycodes.h>
+#include <comus/input.h>
+#include <comus/asm.h>
+#include <lib.h>
+
+#define STATUS_OUT_BUF ((uint8_t)0x01)
+#define STATUS_IN_BUF ((uint8_t)0x02)
+
+#define CONFIG_INT_0 ((uint8_t)0x01)
+#define CONFIG_INT_1 ((uint8_t)0x02)
+#define CONFIG_SYS ((uint8_t)0x04)
+#define CONFIG_CLOCK_0 ((uint8_t)0x10)
+#define CONFIG_CLOCK_1 ((uint8_t)0x20)
+#define CONFIG_TRANS ((uint8_t)0x40)
+
+static uint8_t scancodes[] = {
+ KEY_NONE, KEY_F9, KEY_NONE, KEY_F5, KEY_F3,
+ KEY_F1, KEY_F2, KEY_F12, KEY_NONE, KEY_F10,
+ KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_BACKTICK,
+ KEY_NONE, KEY_NONE, KEY_L_ALT, KEY_L_SHIFT, KEY_NONE,
+ KEY_L_CTRL, KEY_Q, KEY_1, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_Z, KEY_S, KEY_A, KEY_W,
+ KEY_2, KEY_NONE, KEY_NONE, KEY_C, KEY_X,
+ KEY_D, KEY_E, KEY_4, KEY_3, KEY_NONE,
+ KEY_NONE, KEY_SPACE, KEY_V, KEY_F, KEY_T,
+ KEY_R, KEY_5, KEY_NONE, KEY_NONE, KEY_N,
+ KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_M, KEY_J,
+ KEY_U, KEY_7, KEY_8, KEY_NONE, KEY_NONE,
+ KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0,
+ KEY_9, KEY_NONE, KEY_NONE, KEY_PERIOD, KEY_SLASH,
+ KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_QUOTE, KEY_NONE, KEY_L_BRACE,
+ KEY_EQUAL, KEY_NONE, KEY_NONE, KEY_CAPS_LOCK, KEY_R_SHIFT,
+ KEY_ENTER, KEY_R_BRACE, KEY_NONE, KEY_BACKSLASH, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_BACKSPACE, KEY_NONE, KEY_NONE,
+ KEY_NP_1, KEY_NONE, KEY_NP_4, KEY_NP_7, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_NP_0, KEY_NP_PERIOD, KEY_NP_2,
+ KEY_NP_5, KEY_NP_6, KEY_NP_8, KEY_ESCAPE, KEY_NUM_LOCK,
+ KEY_F11, KEY_NP_PLUS, KEY_NP_3, KEY_NP_MINUS, KEY_NP_ASTERISK,
+ KEY_NP_9, KEY_SCROLL_LOCK, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_F7,
+};
+static uint8_t scancodes_ext[] = {
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_UNKNOWN, KEY_R_ALT, KEY_PRINT_SCREEN, KEY_NONE,
+ KEY_R_CTRL, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_L_META, KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE,
+ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_R_META,
+ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_MENU, KEY_UNKNOWN, KEY_NONE,
+ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE,
+ KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_UNKNOWN,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_UNKNOWN,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NP_SLASH,
+ KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE,
+ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NP_ENTER, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_END, KEY_NONE, KEY_LEFT, KEY_HOME, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_INSERT, KEY_DELETE, KEY_DOWN,
+ KEY_NONE, KEY_RIGHT, KEY_UP, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_PAGE_DOWN, KEY_NONE, KEY_NONE,
+ KEY_PAGE_UP, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
+ KEY_NONE,
+};
+
+// ctrl
+static bool has_kbd = false;
+static bool has_mouse = false;
+
+// kbd
+static bool state_keyup = false;
+static bool state_ext = false;
+
+// mouse
+static uint8_t first_b, second_b, third_b;
+
+static uint8_t ps2ctrl_in_status(void)
+{
+ return inb(0x64);
+}
+
+static uint8_t ps2ctrl_in(void)
+{
+ while ((ps2ctrl_in_status() & STATUS_OUT_BUF) == 0) {
+ io_wait();
+ }
+ return inb(0x60);
+}
+
+static void ps2ctrl_out_cmd(uint8_t cmd)
+{
+ while ((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) {
+ io_wait();
+ }
+ outb(0x64, cmd);
+}
+
+static void ps2ctrl_out_data(uint8_t data)
+{
+ while ((ps2ctrl_in_status() & STATUS_IN_BUF) != 0) {
+ io_wait();
+ }
+ outb(0x60, data);
+}
+
+static void ps2ctrl_set_port2(void)
+{
+ outb(0x64, 0xD4);
+}
+
+static int ps2kb_init(void)
+{
+ uint8_t result;
+
+ ps2ctrl_out_data(0xFF);
+ if ((result = ps2ctrl_in()) != 0xFA)
+ return 1;
+
+ if ((result = ps2ctrl_in()) != 0xAA)
+ return 1;
+
+ ps2ctrl_out_data(0xF4);
+ if ((result = ps2ctrl_in()) != 0xFA)
+ return 1;
+
+ has_kbd = true;
+ return 0;
+}
+
+static int ps2mouse_init(void)
+{
+ uint8_t result;
+
+ ps2ctrl_set_port2();
+ ps2ctrl_out_data(0xFF);
+ if ((result = ps2ctrl_in()) != 0xFA)
+ return 1;
+
+ if ((result = ps2ctrl_in()) != 0xAA)
+ return 1;
+
+ ps2ctrl_set_port2();
+ ps2ctrl_out_data(0xF4);
+
+ has_mouse = true;
+ return 0;
+}
+
+void ps2kb_recv(void)
+{
+ static struct keycode keycode;
+ uint8_t code;
+
+ if (!has_kbd)
+ return;
+
+ code = ps2ctrl_in();
+ if (code == 0x00 || code == 0x0F) {
+ keycode.key = KEY_NONE;
+ keycode.flags = KC_FLAG_ERROR;
+ } else if (code == 0xF0) {
+ state_keyup = true;
+ } else if (code == 0xE0) {
+ state_ext = true;
+ } else if (code <= 0x84) {
+ uint8_t *scancode_table = state_ext ? scancodes_ext : scancodes;
+ uint8_t kcode = scancode_table[code];
+ if (kcode != KEY_NONE) {
+ keycode.key = kcode;
+ keycode.flags = state_keyup ? KC_FLAG_KEY_UP : KC_FLAG_KEY_DOWN;
+ keycode_push(&keycode);
+ }
+ state_keyup = false;
+ state_ext = false;
+ }
+}
+
+void ps2mouse_recv(void)
+{
+ static struct mouse_event mouse_ev;
+ static uint8_t packet_num = 0;
+ uint8_t code;
+
+ if (!has_mouse)
+ return;
+
+ code = ps2ctrl_in();
+ switch (packet_num) {
+ case 0:
+ first_b = code;
+ break;
+ case 1:
+ second_b = code;
+ break;
+ case 2: {
+ int state, d;
+
+ third_b = code;
+ state = first_b;
+ d = second_b;
+ mouse_ev.relx = d - ((state << 4) & 0x100);
+ d = third_b;
+ mouse_ev.rely = d - ((state << 3) & 0x100);
+
+ mouse_ev.lmb = first_b & 0x01;
+ mouse_ev.rmb = first_b & 0x02;
+ mouse_ev.mmb = first_b & 0x04;
+ mouse_ev.updated = true;
+ mouse_event_push(&mouse_ev);
+ break;
+ }
+ }
+
+ packet_num += 1;
+ packet_num %= 3;
+}
+
+int ps2_init(void)
+{
+ uint8_t result;
+
+ cli();
+
+ inb(0x60);
+
+ // self-test
+ ps2ctrl_out_cmd(0xAA);
+ if ((result = ps2ctrl_in()) != 0x55) {
+ WARN("PS/2 Controller failed to initalize.");
+ return 1;
+ }
+
+ // set config
+ ps2ctrl_out_cmd(0x20);
+ uint8_t config = ps2ctrl_in();
+ config = (config | CONFIG_INT_0 | CONFIG_INT_1) & ~CONFIG_TRANS;
+ // config = 0xFF;
+ ps2ctrl_out_cmd(0x60);
+ ps2ctrl_out_data(config);
+
+ // enable port 0
+ ps2ctrl_out_cmd(0xAE);
+
+ // enable port 2
+ ps2ctrl_out_cmd(0xA9);
+ if ((result != ps2ctrl_in()) != 0x01) {
+ WARN("PS/2 port 2 not supported");
+ return 1;
+ }
+
+ ps2ctrl_out_cmd(0xA8);
+
+ ps2kb_init();
+ ps2mouse_init();
+ sti();
+ return 0;
+}