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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

@@ -4,10 +4,9 @@ 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();