mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2025-12-18 02:05:19 -08:00
Create ps2.c
add initial ps/2 driver code. This will need wired up to be used
This commit is contained in:
117
kernel/ps2.c
Normal file
117
kernel/ps2.c
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "ps2.h"
|
||||
|
||||
/* --- Low Level I/O Helpers --- */
|
||||
static inline void outb(uint16_t port, uint8_t val) {
|
||||
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t port) {
|
||||
uint8_t ret;
|
||||
asm volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --- Controller Synchronization --- */
|
||||
|
||||
// Wait until the controller is ready to receive a byte
|
||||
static void ps2_wait_write() {
|
||||
while (inb(PS2_STATUS_REG) & PS2_STATUS_INPUT);
|
||||
}
|
||||
|
||||
// Wait until the controller has a byte for us to read
|
||||
static void ps2_wait_read() {
|
||||
while (!(inb(PS2_STATUS_REG) & PS2_STATUS_OUTPUT));
|
||||
}
|
||||
|
||||
/* --- Initialization --- */
|
||||
|
||||
void ps2_write_device(uint8_t command) {
|
||||
ps2_wait_write();
|
||||
outb(PS2_DATA_PORT, command);
|
||||
}
|
||||
|
||||
void ps2_write_mouse(uint8_t data) {
|
||||
ps2_wait_write();
|
||||
outb(PS2_COMMAND_REG, PS2_CMD_WRITE_MOUSE); // "Next byte goes to mouse"
|
||||
ps2_wait_write();
|
||||
outb(PS2_DATA_PORT, data);
|
||||
}
|
||||
|
||||
void ps2_init(void) {
|
||||
// 1. Disable Devices
|
||||
ps2_wait_write();
|
||||
outb(PS2_COMMAND_REG, PS2_CMD_DISABLE_KB);
|
||||
ps2_wait_write();
|
||||
outb(PS2_COMMAND_REG, PS2_CMD_DISABLE_MS);
|
||||
|
||||
// 2. Flush Output Buffer
|
||||
while (inb(PS2_STATUS_REG) & PS2_STATUS_OUTPUT) {
|
||||
inb(PS2_DATA_PORT);
|
||||
}
|
||||
|
||||
// 3. Set Controller Configuration Byte
|
||||
// Bit 0: KB Interrupt, Bit 1: Mouse Interrupt, Bit 6: Translation
|
||||
ps2_wait_write();
|
||||
outb(PS2_COMMAND_REG, PS2_CMD_READ_CONFIG);
|
||||
ps2_wait_read();
|
||||
uint8_t status = inb(PS2_DATA_PORT);
|
||||
status |= (1 << 0) | (1 << 1); // Enable IRQ 1 and IRQ 12
|
||||
|
||||
ps2_wait_write();
|
||||
outb(PS2_COMMAND_REG, PS2_CMD_WRITE_CONFIG);
|
||||
ps2_wait_write();
|
||||
outb(PS2_DATA_PORT, status);
|
||||
|
||||
// 4. Enable Devices
|
||||
ps2_wait_write();
|
||||
outb(PS2_COMMAND_REG, PS2_CMD_ENABLE_KB);
|
||||
ps2_wait_write();
|
||||
outb(PS2_COMMAND_REG, PS2_CMD_ENABLE_MS);
|
||||
|
||||
// 5. Initialize Mouse (The mouse won't send IRQs until you tell it to)
|
||||
ps2_write_mouse(MOUSE_CMD_SET_DEFAULTS);
|
||||
ps2_wait_read(); inb(PS2_DATA_PORT); // Read ACK (0xFA)
|
||||
|
||||
ps2_write_mouse(MOUSE_CMD_ENABLE_SCAN);
|
||||
ps2_wait_read(); inb(PS2_DATA_PORT); // Read ACK (0xFA)
|
||||
}
|
||||
|
||||
/* --- IRQ Handlers --- */
|
||||
|
||||
// Called from IRQ 1 (Keyboard)
|
||||
void ps2_keyboard_handler(void) {
|
||||
uint8_t scancode = inb(PS2_DATA_PORT);
|
||||
// Process scancode (e.g., put it into a circular buffer)
|
||||
}
|
||||
|
||||
// Called from IRQ 12 (Mouse)
|
||||
static uint8_t mouse_cycle = 0;
|
||||
static uint8_t mouse_bytes[3];
|
||||
|
||||
void ps2_mouse_handler(void) {
|
||||
uint8_t status = inb(PS2_STATUS_REG);
|
||||
|
||||
// Ensure this is actually mouse data
|
||||
if (!(status & PS2_STATUS_MOUSE)) return;
|
||||
|
||||
mouse_bytes[mouse_cycle++] = inb(PS2_DATA_PORT);
|
||||
|
||||
if (mouse_cycle == 3) {
|
||||
mouse_cycle = 0;
|
||||
|
||||
// Byte 0: Flags (Buttons, Signs)
|
||||
// Byte 1: X Delta
|
||||
// Byte 2: Y Delta
|
||||
|
||||
mouse_state_t state;
|
||||
state.left_button = (mouse_bytes[0] & 0x01);
|
||||
state.right_button = (mouse_bytes[0] & 0x02);
|
||||
state.middle_button = (mouse_bytes[0] & 0x04);
|
||||
|
||||
// Handle negative deltas (signed 9-bit logic)
|
||||
state.x_delta = (int8_t)mouse_bytes[1];
|
||||
state.y_delta = (int8_t)mouse_bytes[2];
|
||||
|
||||
// Update your kernel's internal mouse position here
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user