mouse interrupts working

This commit is contained in:
2026-01-29 13:06:49 +11:00
parent 7ee5ff5bd4
commit dc825fb6d3
14 changed files with 224 additions and 37 deletions

View File

@@ -3,22 +3,22 @@
#include "../IO.h"
#include "../userinput/keyboard.h"
__attribute__((interrupt)) void PageFault_Handler(struct interrupt_frame* frame) {
__attribute__((interrupt)) void PageFault_Handler(interrupt_frame* frame) {
Panic("Page Fault");
while (true);
}
__attribute__((interrupt)) void DoubleFault_Handler(struct interrupt_frame* frame) {
__attribute__((interrupt)) void DoubleFault_Handler(interrupt_frame* frame) {
Panic("Double Fault");
while (true);
}
__attribute__((interrupt)) void GPFault_Handler(struct interrupt_frame* frame) {
__attribute__((interrupt)) void GPFault_Handler(interrupt_frame* frame) {
Panic("General Protection Fault");
while (true);
}
__attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame* frame) {
__attribute__((interrupt)) void KeyboardInterrupt_Handler(interrupt_frame* frame) {
uint8_t scancode = inb(0x60);
HandleKeyboard(scancode);
@@ -26,6 +26,14 @@ __attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame
PIC_EndMaster();
}
__attribute__((interrupt)) void MouseInterrupt_Handler(interrupt_frame* frame) {
uint8_t mouseData = inb(0x60);
HandlePS2Mouse(mouseData);
PIC_EndSlave();
}
void PIC_EndMaster() {
outb(PIC1_COMMAND, PIC_EOI);
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "../BasicRenderer.h"
#include "../userinput/mouse.h"
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
@@ -12,11 +13,12 @@
#define ICW4_8086 0x01
struct interrupt_frame;
__attribute__((interrupt)) void PageFault_Handler(struct interrupt_frame* frame);
__attribute__((interrupt)) void DoubleFault_Handler(struct interrupt_frame* frame);
__attribute__((interrupt)) void GPFault_Handler(struct interrupt_frame* frame);
__attribute__((interrupt)) void PageFault_Handler(interrupt_frame* frame);
__attribute__((interrupt)) void DoubleFault_Handler(interrupt_frame* frame);
__attribute__((interrupt)) void GPFault_Handler(interrupt_frame* frame);
__attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame* frame);
__attribute__((interrupt)) void KeyboardInterrupt_Handler(interrupt_frame* frame);
__attribute__((interrupt)) void MouseInterrupt_Handler(interrupt_frame* frame);
void RemapPIC();
void PIC_EndMaster();

View File

@@ -3,12 +3,11 @@
extern "C" void _start(BootInfo* bootInfo) {
KernelInfo kernelInfo = InitializeKernel(bootInfo);
PageTableManager* pageTableManager = kernelInfo.pageTableManager;
GlobalRenderer->ClearColour = 0xFF191919;
GlobalRenderer->Clear();
GlobalRenderer->Print("Kernel initialized successfully!");
GlobalRenderer->Next();
while (true) {
ProcessMousePacket();
}
// make sure we never return from our OS
while (true);
}

View File

@@ -45,40 +45,31 @@ void PrepareMemory(BootInfo* bootInfo){
}
IDTR idtr;
void SetIDTGate(void* handler, uint8_t entryOffset, uint8_t type_attr, uint8_t selector) {
IDTDescEntry* interrupt = (IDTDescEntry*)(idtr.Offset + entryOffset * sizeof(IDTDescEntry));
interrupt->SetOffset((uint64_t)handler);
interrupt->type_attr = type_attr;
interrupt->selector = selector;
}
void PrepareInterrupts() {
idtr.Limit = 0x0FFF;
idtr.Offset = (uint64_t)GlobalAllocator.RequestPage();
memset((void*)idtr.Offset, 0, 0x1000);
IDTDescEntry* int_PageFault = (IDTDescEntry*)(idtr.Offset + 0xE * sizeof(IDTDescEntry));
int_PageFault->SetOffset((uint64_t)PageFault_Handler);
int_PageFault->type_attr = IDT_TA_InterruptGate;
int_PageFault->selector = 0x08; // kernel code segment
IDTDescEntry* int_DoubleFault = (IDTDescEntry*)(idtr.Offset + 0x8 * sizeof(IDTDescEntry));
int_DoubleFault->SetOffset((uint64_t)DoubleFault_Handler);
int_DoubleFault->type_attr = IDT_TA_InterruptGate;
int_DoubleFault->selector = 0x08; // kernel code segment
IDTDescEntry* int_GPFault = (IDTDescEntry*)(idtr.Offset + 0xD * sizeof(IDTDescEntry));
int_GPFault->SetOffset((uint64_t)GPFault_Handler);
int_GPFault->type_attr = IDT_TA_InterruptGate;
int_GPFault->selector = 0x08; // kernel code segment
IDTDescEntry* int_Keyboard = (IDTDescEntry*)(idtr.Offset + 0x21 * sizeof(IDTDescEntry));
int_Keyboard->SetOffset((uint64_t)KeyboardInterrupt_Handler);
int_Keyboard->type_attr = IDT_TA_InterruptGate;
int_Keyboard->selector = 0x08; // kernel code segment
SetIDTGate((void*)PageFault_Handler, 0xE, IDT_TA_InterruptGate, 0x08);
SetIDTGate((void*)DoubleFault_Handler, 0x8, IDT_TA_InterruptGate, 0x08);
SetIDTGate((void*)GPFault_Handler, 0xD, IDT_TA_InterruptGate, 0x08);
SetIDTGate((void*)KeyboardInterrupt_Handler, 0x21, IDT_TA_InterruptGate, 0x08);
SetIDTGate((void*)MouseInterrupt_Handler, 0x2C, IDT_TA_InterruptGate, 0x08);
// load idt
asm("lidt %0" : : "m" (idtr));
// remap pic so we can get hardware interrupts
RemapPIC();
outb(PIC1_DATA, 0b11111101); // unmask 2nd interrupt
outb(PIC2_DATA, 0b11111111);
asm ("sti");
}
BasicRenderer r = BasicRenderer(NULL, NULL);
@@ -86,16 +77,42 @@ KernelInfo InitializeKernel(BootInfo* bootInfo){
r = BasicRenderer(bootInfo->framebuffer, bootInfo->psf1_Font);
GlobalRenderer = &r;
GlobalRenderer->ClearColour = 0xFF191919;
GlobalRenderer->Clear();
GlobalRenderer->Print("Setting up GDT...");
GlobalRenderer->Next();
GDTDescriptor gdtDescriptor;
gdtDescriptor.Size = sizeof(GDT) - 1;
gdtDescriptor.Offset = (uint64_t)&DefaultGDT;
LoadGDT(&gdtDescriptor);
GlobalRenderer->Print("Preparing memory... (this doesn't always work, you may need to restart. sorry.)");
GlobalRenderer->Next();
PrepareMemory(bootInfo);
memset(bootInfo->framebuffer->BaseAddress, 0, bootInfo->framebuffer->BufferSize);
//memset(bootInfo->framebuffer->BaseAddress, 0, bootInfo->framebuffer->BufferSize);
GlobalRenderer->Print("Setting up interrupts...");
GlobalRenderer->Next();
PrepareInterrupts();
GlobalRenderer->Print("Setting up mouse...");
GlobalRenderer->Next();
InitPS2Mouse();
outb(PIC1_DATA, 0b11111001); // unmask 2nd interrupt
outb(PIC2_DATA, 0b11101111);
asm ("sti"); // enable interrupts
GlobalRenderer->Print("Init complete!");
GlobalRenderer->Next();
return kernelInfo;
}

View File

@@ -11,6 +11,7 @@
#include "paging/PageMapIndexer.h"
#include "paging/paging.h"
#include "paging/PageTableManager.h"
#include "userinput/mouse.h"
struct BootInfo {
Framebuffer* framebuffer;

View File

@@ -0,0 +1,141 @@
#include "mouse.h"
#include "../IO.h"
void MouseWait() {
uint64_t timeout = 100000;
while (timeout--) {
if (inb(0x64) & 0b10 == 0)
return;
}
}
void MouseWaitInput() {
uint64_t timeout = 100000;
while (timeout--) {
if (inb(0x64) & 0b1)
return;
}
}
void MouseWrite(uint8_t value) {
MouseWait();
outb(0x64, 0xD4);
MouseWait();
outb(0x60, value);
}
uint8_t MouseRead() {
MouseWaitInput();
return inb(0x60);
}
uint8_t mouseCycle = 0;
uint8_t mousePacket[4];
bool mousePacketReady = false;
Point mousePosition;
void HandlePS2Mouse(uint8_t data) {
switch (mouseCycle) {
case 0:
if (mousePacketReady) break;
if (data & 0b00001000 == 0) break;
mousePacket[0] = data;
mouseCycle++;
break;
case 1:
if (mousePacketReady) break;
mousePacket[1] = data;
mouseCycle++;
break;
case 2:
if (mousePacketReady) break;
mousePacket[2] = data;
mousePacketReady = true;
mouseCycle = 0;
break;
}
}
void ProcessMousePacket() {
if (!mousePacketReady) return;
mousePacketReady = false;
bool xNegative, yNegative, xOverflow, yOverflow;
if (mousePacket[0] & PS2XSign) {
xNegative = true;
} else xNegative = false;
if (mousePacket[0] & PS2YSign) {
yNegative = true;
} else yNegative = false;
if (mousePacket[0] & PS2XOverflow) {
xOverflow = true;
} else xOverflow = false;
if (mousePacket[0] & PS2YOverflow) {
yOverflow = true;
} else yOverflow = false;
if (!xNegative) {
mousePosition.x += mousePacket[1];
if (xOverflow) {
mousePosition.x += 255;
}
} else {
mousePacket[1] = 256 - mousePacket[1];
mousePosition.x -= mousePacket[1];
if (xOverflow) {
mousePosition.x -= 255;
}
}
if (!yNegative) {
mousePosition.y -= mousePacket[2];
if (yOverflow) {
mousePosition.y -= 255;
}
} else {
mousePacket[2] = 256 - mousePacket[2];
mousePosition.y += mousePacket[2];
if (yOverflow) {
mousePosition.y += 255;
}
}
if (mousePosition.x < 0) mousePosition.x = 0;
if (mousePosition.x > GlobalRenderer->targetFramebuffer->Width-1) mousePosition.x = GlobalRenderer->targetFramebuffer->Width;
if (mousePosition.y < 0) mousePosition.y = 0;
if (mousePosition.y > GlobalRenderer->targetFramebuffer->Height-1) mousePosition.y = GlobalRenderer->targetFramebuffer->Height;
}
void InitPS2Mouse() {
// enable aux device mouse
outb(0x64, 0xA8);
MouseWait();
outb(0x64, 0x20); // tells the keyboard controller we want to send a command to the mouse
MouseWaitInput();
uint8_t status = inb(0x60);
status |= 0b10;
MouseWait();
outb(0x64, 0x60);
MouseWait();
outb(0x60, status); // setting the correct bit in the "compaq" status byte
MouseWrite(0xF6); // default settings
MouseRead();
MouseWrite(0xF4);
MouseRead();
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#include "../math.h"
#include "../BasicRenderer.h"
#define PS2LeftButton 0b00000001
#define PS2MiddleButton 0b00000010
#define PS2RightButton 0b00000100
#define PS2XSign 0b00010000
#define PS2YSign 0b00100000
#define PS2XOverflow 0b01000000
#define PS2YOverflow 0b10000000
extern Point mousePosition;
void InitPS2Mouse();
void HandlePS2Mouse(uint8_t data);
void ProcessMousePacket();