mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Major interrupt change
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
#include <error/debug.h>
|
||||
#include <ports/serial.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int debugf(const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
serialPrint(PORT_COM1, fmt); // TODO: use a printf
|
||||
int res = 0;
|
||||
va_end(va);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <error/panic.h>
|
||||
|
||||
void panic() {
|
||||
// TODO: print a message
|
||||
while (1) { __asm__ volatile ("cli; hlt"); }
|
||||
}
|
||||
|
||||
+3
-3
@@ -47,15 +47,15 @@ void initOpenFileTable() {
|
||||
|
||||
// offset and ptr are unused in these
|
||||
stdin = fsInfo->openFileTable + 0;
|
||||
stdin->_file = 0;
|
||||
stdin->_file = STDIN_FILENO;
|
||||
stdin->_flag = O_RDONLY;
|
||||
|
||||
stdout = fsInfo->openFileTable + 1;
|
||||
stdout->_file = 1;
|
||||
stdout->_file = STDOUT_FILENO;
|
||||
stdout->_flag = O_WRONLY | O_APPEND;
|
||||
|
||||
stderr = fsInfo->openFileTable + 2;
|
||||
stderr->_file = 2;
|
||||
stderr->_file = STDERR_FILENO;
|
||||
stderr->_flag = O_WRONLY | O_APPEND;
|
||||
|
||||
fsInfo->openFiles = 3;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef ERROR_DEBUG_H
|
||||
#define ERROR_DEBUG_H
|
||||
|
||||
int debugf(const char* fmt, ...);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef ERROR_PANIC_H
|
||||
#define ERROR_PANIC_H
|
||||
|
||||
void panic();
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#define TRAP_GATE_FLAGS 0x8f // P = 1, DPL = 00, S = 0, Type = 1111 (32-bit Trap gate)
|
||||
#define INT_GATE_FLAGS 0x8e // P = 1, DPL = 00, S = 0, Type = 1110 (32-bit Int gate)
|
||||
#define USR_INT_GAME_FLAGS 0xee // P = 1, DPL = 11, S = 0, Type = 1110 (32-bit Int gate)
|
||||
#define USR_INT_GATE_FLAGS 0xee // P = 1, DPL = 11, S = 0, Type = 1110 (32-bit Int gate)
|
||||
|
||||
typedef struct {
|
||||
uint16_t offsetLow;
|
||||
@@ -20,14 +20,6 @@ typedef struct {
|
||||
uint32_t base;
|
||||
} __attribute__ ((packed)) idtp_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t eip;
|
||||
uint32_t cs;
|
||||
uint32_t eflags;
|
||||
uint32_t esp;
|
||||
uint32_t ss;
|
||||
} __attribute__ ((packed)) intFrame_t;
|
||||
|
||||
void idtSetGate(uint8_t i, void* handler, uint8_t flags);
|
||||
void setupIdt();
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef INTERRUPT_ISR_H
|
||||
#define INTERRUPT_ISR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
// Pushed by OS
|
||||
uint32_t esp, ebx, ecx, edx, esi, edi, ebp;
|
||||
uint32_t ds, es, fs, gs, eax;
|
||||
uint32_t interrupt, error;
|
||||
|
||||
// Pushed by CPU
|
||||
uint32_t eip, cs, eflags, user_esp, user_ss;
|
||||
} intFrame_t;
|
||||
typedef void (*HandlerPtr)(intFrame_t* iframe);
|
||||
|
||||
void setupIsrs();
|
||||
int handleInterrupt(intFrame_t iframe);
|
||||
void registerIrq(uint8_t id, HandlerPtr handler);
|
||||
|
||||
// ISR Table
|
||||
extern void* asm_isrRedirectTable[48];
|
||||
|
||||
// Int 0x80 - Syscall
|
||||
extern void isr128();
|
||||
|
||||
#endif
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef INTERRUPT_PIC_H
|
||||
#define INTERRUPT_PIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// PIC I/O Ports
|
||||
#define PIC_1_CMD 0x20
|
||||
#define PIC_1_DATA 0x21
|
||||
#define PIC_2_CMD 0xA0
|
||||
#define PIC_2_DATA 0xA1
|
||||
|
||||
// IRQs
|
||||
#define NEW_IRQ_0 0x20 // IRQ 0 : int 32
|
||||
#define NEW_IRQ_8 0x28 // IRQ 8 : int 40
|
||||
|
||||
// Commands
|
||||
#define PIC_EOI 0x20 // End Of Interrupt
|
||||
#define PIC_DISABLE 0xff
|
||||
|
||||
void sendPicEOI(uint8_t irq);
|
||||
void disableIrqs();
|
||||
void setIrqMask(uint8_t irq);
|
||||
void unsetIrqMask(uint8_t irq);
|
||||
void remapPic();
|
||||
|
||||
#endif
|
||||
@@ -1,13 +1,14 @@
|
||||
#ifndef INTERRUPT_PIT_H
|
||||
#define INTERRUPT_PIT_H
|
||||
|
||||
#include <interrupt/isr.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2
|
||||
#define COMMAND 0x43
|
||||
#define INPUT_CLK 1193182
|
||||
|
||||
void timerHandler(intFrame_t*);
|
||||
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz);
|
||||
void setupTimer();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef INTERRUPT_RTC_H
|
||||
#define INTERRUPT_RTC_H
|
||||
|
||||
#include <interrupt/isr.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -16,10 +17,10 @@ typedef struct {
|
||||
uint16_t year;
|
||||
} __attribute__ ((packed)) datetime_t;
|
||||
|
||||
void rtcHandler(intFrame_t*);
|
||||
bool cmosUpdateProgress();
|
||||
uint8_t getRtcRegister(uint8_t reg);
|
||||
void enableRtc();
|
||||
void disableRtc();
|
||||
void setupRtc();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#ifndef INTERRUPT_SYSCALLS_H
|
||||
#define INTERRUPT_SYSCALLS_H
|
||||
|
||||
#include <interrupt/idt.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t esp;
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
uint32_t esi;
|
||||
uint32_t edi;
|
||||
uint32_t ebp;
|
||||
uint32_t ds;
|
||||
uint32_t es;
|
||||
uint32_t fs;
|
||||
uint32_t gs;
|
||||
uint32_t eax;
|
||||
} __attribute__ ((packed)) sys_regs_t;
|
||||
|
||||
__attribute__ ((naked)) void syscallHandler(intFrame_t* iframe);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef KEYBOARD_KEYBOARD_H
|
||||
#define KEYBOARD_KEYBOARD_H
|
||||
|
||||
#include <interrupt/isr.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
@@ -8,6 +9,6 @@ typedef struct {
|
||||
bool shift;
|
||||
} keyboardState_t;
|
||||
|
||||
void setupKeyboard();
|
||||
void keyboardHandler(intFrame_t*);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@ int serialTransmitEmpty(uint32_t port);
|
||||
int serialRecieved(uint32_t port);
|
||||
|
||||
void serialWrite(uint32_t port, char c);
|
||||
void serialPrint(uint32_t port, char* s);
|
||||
void serialPrint(uint32_t port, const char* s);
|
||||
char serialRead(uint32_t port);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef INTERRUPT_SYSCALLS_H
|
||||
#define INTERRUPT_SYSCALLS_H
|
||||
|
||||
#include <interrupt/isr.h>
|
||||
|
||||
int sys_exit (intFrame_t* iframe);
|
||||
int sys_read (intFrame_t* iframe);
|
||||
int sys_write (intFrame_t* iframe);
|
||||
int sys_open (intFrame_t* iframe);
|
||||
int sys_close (intFrame_t* iframe);
|
||||
int sys_seek (intFrame_t* iframe);
|
||||
int sys_malloc (intFrame_t* iframe);
|
||||
int sys_free (intFrame_t* iframe);
|
||||
int sys_sleep (intFrame_t* iframe);
|
||||
|
||||
// Main syscall handler/dispatcher
|
||||
int syscallHandler(intFrame_t* iframe);
|
||||
|
||||
#endif
|
||||
@@ -13,11 +13,11 @@ typedef struct {
|
||||
uint32_t height; // Height in characters
|
||||
char cursorChar; // Character to use as a cursor
|
||||
bool hideCursor; // Should we display the cursor
|
||||
} terminal_t;
|
||||
} console_t;
|
||||
|
||||
extern terminal_t* terminal;
|
||||
extern console_t* console;
|
||||
|
||||
int32_t terminalWrite(const void* buf, uint32_t len);
|
||||
int32_t consoleWrite(const void* buf, uint32_t len);
|
||||
void toggleCursor();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#include <interrupt/exceptions.h>
|
||||
#include <interrupt/idt.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Exception handlers
|
||||
__attribute__ ((interrupt))
|
||||
void excp_divideErr(intFrame_t* iframe) { // ISR 0
|
||||
printf("\x1b[1M[ Division Error ]\n\x1b[8M");
|
||||
iframe->eip++;
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_doubleFault(intFrame_t* iframe, uint32_t errCode) { // ISR 8
|
||||
printf("\x1b[1M[ Double Fault ]\n\x1b[8M"); // Error code should be 0 (TODO: Maybe check if it's != 0?)
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_pageFault(intFrame_t* iframe, uint32_t errCode) { // ISR 14
|
||||
uint32_t badAddress = 0;
|
||||
|
||||
// cr2 should contain invalid address
|
||||
__asm__ volatile("movl %%cr2, %0" : "=r"(badAddress));
|
||||
|
||||
printf("\x1b[1M[ Page Fault : 0x%x ] - Tried to access 0x%x.\n\x1b[8M", errCode, badAddress);
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void excp_reserved(intFrame_t* iframe) { // ISR 15
|
||||
print("\x1b[1M[ Unknown Exception ]\n\x1b[8M");
|
||||
__asm__ volatile ("cli; hlt");
|
||||
}
|
||||
|
||||
// TODO: Add more (because there's always more)
|
||||
|
||||
// Repetative isr definitions
|
||||
void setupExceptions() {
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
idtSetGate(i, excp_reserved, TRAP_GATE_FLAGS); // Doesn't account for err codes, will just halt anyways
|
||||
}
|
||||
|
||||
idtSetGate(0, excp_divideErr, TRAP_GATE_FLAGS);
|
||||
idtSetGate(8, excp_doubleFault, TRAP_GATE_FLAGS);
|
||||
idtSetGate(14, excp_pageFault, TRAP_GATE_FLAGS);
|
||||
idtSetGate(15, excp_reserved, TRAP_GATE_FLAGS);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include <interrupt/idt.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define IDT_ENTRIES 256
|
||||
|
||||
__attribute__ ((aligned(0x10))) // For performance
|
||||
idtEntry_t idt[256] = { 0 };
|
||||
idtEntry_t idt[IDT_ENTRIES] = { 0 };
|
||||
idtp_t idtp;
|
||||
|
||||
void idtSetGate(uint8_t i, void* handler, uint8_t flags) {
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <interrupt/isr.h>
|
||||
#include <interrupt/idt.h>
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <error/panic.h>
|
||||
#include <error/debug.h>
|
||||
#include <ports/io.h>
|
||||
|
||||
const char* format = "\x1b[31mPanic: %s!\n";
|
||||
const char* exceptions[] = {
|
||||
"Division By Zero",
|
||||
"Debug",
|
||||
"Non Maskable Interrupt",
|
||||
"Breakpoint",
|
||||
"Into Detected Overflow",
|
||||
"Out of Bounds",
|
||||
"Invalid Opcode",
|
||||
"No Coprocessor",
|
||||
"Double Fault",
|
||||
"Coprocessor Segment Overrun",
|
||||
"Bad TSS",
|
||||
"Segment Not Present",
|
||||
"Stack Fault",
|
||||
"General Protection Fault",
|
||||
"Page Fault",
|
||||
"Unknown Interrupt",
|
||||
"Coprocessor Fault",
|
||||
"Alignment Check",
|
||||
"Machine Check",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved"
|
||||
};
|
||||
|
||||
void remapPic() {
|
||||
outb(0x20, 0x11);
|
||||
outb(0xa0, 0x11);
|
||||
outb(0x21, 0x20);
|
||||
outb(0xa1, 0x28);
|
||||
outb(0x21, 0x04);
|
||||
outb(0xa1, 0x02);
|
||||
outb(0x21, 0x01);
|
||||
outb(0xa1, 0x01);
|
||||
outb(0x21, 0x00);
|
||||
outb(0xa1, 0x00);
|
||||
}
|
||||
|
||||
HandlerPtr irqHandlers[16] = { 0 }; // IRQ 0-15
|
||||
|
||||
void setupIsrs() {
|
||||
setupIdt();
|
||||
remapPic(); // Remap IRQs 0-15 -> 32-48
|
||||
|
||||
for (int i = 0; i < 48; i++) {
|
||||
idtSetGate(i, asm_isrRedirectTable[i], TRAP_GATE_FLAGS);
|
||||
}
|
||||
|
||||
// System call
|
||||
idtSetGate(0x80, isr128, USR_INT_GATE_FLAGS);
|
||||
|
||||
__asm__ volatile ("sti");
|
||||
}
|
||||
|
||||
void registerIrq(uint8_t id, HandlerPtr handler) {
|
||||
irqHandlers[id] = handler;
|
||||
}
|
||||
|
||||
void sendPicEOI(uint8_t irq) {
|
||||
if (irq >= 8) {
|
||||
outb(0xA0, 0x20); // PIC2 Command
|
||||
}
|
||||
outb(0x20, 0x20); // PIC1 Command
|
||||
}
|
||||
|
||||
int handleInterrupt(intFrame_t iframe) {
|
||||
if (iframe.interrupt < 32) {
|
||||
// ISRs 0-31 - Exceptions
|
||||
debugf(format, exceptions[iframe.interrupt]);
|
||||
panic();
|
||||
} else if (iframe.interrupt >= 32 && iframe.interrupt < 48) {
|
||||
// ISRs 32-47 - Hardware interrupts
|
||||
uint8_t irq = iframe.interrupt - 32;
|
||||
if (irqHandlers[irq]) {
|
||||
irqHandlers[irq](&iframe);
|
||||
sendPicEOI(irq);
|
||||
}
|
||||
} else if (iframe.interrupt == 128) {
|
||||
// ISR 128 - System call
|
||||
return syscallHandler(&iframe);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
; ISR Assembly
|
||||
[bits 32]
|
||||
|
||||
isrCommon:
|
||||
;; Push registers to the intFrame_t struct
|
||||
|
||||
push eax
|
||||
push gs
|
||||
push fs
|
||||
push es
|
||||
push ds
|
||||
push ebp
|
||||
push edi
|
||||
push esi
|
||||
push edx
|
||||
push ecx
|
||||
push ebx
|
||||
push esp
|
||||
|
||||
[extern handleInterrupt]
|
||||
call handleInterrupt
|
||||
isrReturn:
|
||||
add esp, 4 ; Keep ESP
|
||||
pop ebx
|
||||
pop ecx
|
||||
pop edx
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebp
|
||||
pop ds
|
||||
pop es
|
||||
pop fs
|
||||
pop gs
|
||||
add esp, 4 ; Keep EAX
|
||||
add esp, 8 ; Pop interupt number and error code
|
||||
|
||||
iretd ; Pop CS, EIP & EFLAGS (Also SS & ESP if it's from userspace)
|
||||
|
||||
%macro ISR_WITH_ERRNO 1
|
||||
isr%1:
|
||||
push dword %1
|
||||
jmp isrCommon
|
||||
%endmacro
|
||||
|
||||
%macro ISR_WITHOUT_ERRNO 1
|
||||
isr%1:
|
||||
push dword 0 ; Instead of error code
|
||||
push dword %1
|
||||
jmp isrCommon
|
||||
%endmacro
|
||||
|
||||
;; Exceptions
|
||||
ISR_WITHOUT_ERRNO 0
|
||||
ISR_WITHOUT_ERRNO 1
|
||||
ISR_WITHOUT_ERRNO 2
|
||||
ISR_WITHOUT_ERRNO 3
|
||||
ISR_WITHOUT_ERRNO 4
|
||||
ISR_WITHOUT_ERRNO 5
|
||||
ISR_WITHOUT_ERRNO 6
|
||||
ISR_WITHOUT_ERRNO 7
|
||||
ISR_WITH_ERRNO 8
|
||||
ISR_WITHOUT_ERRNO 9
|
||||
ISR_WITH_ERRNO 10
|
||||
ISR_WITH_ERRNO 11
|
||||
ISR_WITH_ERRNO 12
|
||||
ISR_WITH_ERRNO 13
|
||||
ISR_WITH_ERRNO 14
|
||||
ISR_WITHOUT_ERRNO 15
|
||||
ISR_WITHOUT_ERRNO 16
|
||||
ISR_WITHOUT_ERRNO 17
|
||||
ISR_WITHOUT_ERRNO 18
|
||||
ISR_WITHOUT_ERRNO 19
|
||||
ISR_WITHOUT_ERRNO 20
|
||||
ISR_WITHOUT_ERRNO 21
|
||||
ISR_WITHOUT_ERRNO 22
|
||||
ISR_WITHOUT_ERRNO 23
|
||||
ISR_WITHOUT_ERRNO 24
|
||||
ISR_WITHOUT_ERRNO 25
|
||||
ISR_WITHOUT_ERRNO 26
|
||||
ISR_WITHOUT_ERRNO 27
|
||||
ISR_WITHOUT_ERRNO 28
|
||||
ISR_WITHOUT_ERRNO 29
|
||||
ISR_WITHOUT_ERRNO 30
|
||||
ISR_WITHOUT_ERRNO 31
|
||||
|
||||
;; IRQs 0-15 (mapped 32-47)
|
||||
ISR_WITHOUT_ERRNO 32
|
||||
ISR_WITHOUT_ERRNO 33
|
||||
ISR_WITHOUT_ERRNO 34
|
||||
ISR_WITHOUT_ERRNO 35
|
||||
ISR_WITHOUT_ERRNO 36
|
||||
ISR_WITHOUT_ERRNO 37
|
||||
ISR_WITHOUT_ERRNO 38
|
||||
ISR_WITHOUT_ERRNO 39
|
||||
ISR_WITHOUT_ERRNO 40
|
||||
ISR_WITHOUT_ERRNO 41
|
||||
ISR_WITHOUT_ERRNO 42
|
||||
ISR_WITHOUT_ERRNO 43
|
||||
ISR_WITHOUT_ERRNO 44
|
||||
ISR_WITHOUT_ERRNO 45
|
||||
ISR_WITHOUT_ERRNO 46
|
||||
ISR_WITHOUT_ERRNO 47
|
||||
|
||||
;; Syscall ISR128
|
||||
[global isr128]
|
||||
ISR_WITHOUT_ERRNO 128
|
||||
|
||||
;; Create table of ISRs
|
||||
[global asm_isrRedirectTable]
|
||||
asm_isrRedirectTable:
|
||||
%assign i 0
|
||||
%rep 48
|
||||
dd isr%+i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#include <interrupt/pic.h>
|
||||
#include <ports/io.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void sendPicEOI(uint8_t irq) {
|
||||
if (irq >= 8) {
|
||||
outb(PIC_2_CMD, PIC_EOI);
|
||||
}
|
||||
outb(PIC_1_CMD, PIC_EOI);
|
||||
}
|
||||
|
||||
void disableIrqs() {
|
||||
outb(PIC_2_DATA, PIC_DISABLE);
|
||||
outb(PIC_1_DATA, PIC_DISABLE);
|
||||
}
|
||||
|
||||
void setIrqMask(uint8_t irq) {
|
||||
uint16_t port;
|
||||
uint8_t value;
|
||||
|
||||
if (irq < 8) {
|
||||
port = PIC_1_DATA;
|
||||
} else {
|
||||
irq -= 8;
|
||||
port = PIC_2_DATA;
|
||||
}
|
||||
|
||||
value = inb(port) | (1 << irq);
|
||||
outb(port, value);
|
||||
}
|
||||
|
||||
void unsetIrqMask(uint8_t irq) {
|
||||
uint16_t port;
|
||||
uint8_t value;
|
||||
|
||||
if (irq < 8) {
|
||||
port = PIC_1_DATA;
|
||||
} else {
|
||||
irq -= 8;
|
||||
port = PIC_2_DATA;
|
||||
}
|
||||
|
||||
value = inb(port) & ~(1 << irq);
|
||||
outb(port, value);
|
||||
}
|
||||
|
||||
void remapPic() {
|
||||
uint8_t pic1Mask = inb(PIC_1_DATA);
|
||||
uint8_t pic2Mask = inb(PIC_2_DATA);
|
||||
|
||||
// Send Init Control Word 1-4 to both PICs
|
||||
// ICW 1: bit 0 - send up to 4 ICWs, bit 4 - Init PIC
|
||||
outb(PIC_1_CMD, 0x11);
|
||||
ioWait(); // For slower machines
|
||||
outb(PIC_2_CMD, 0x11);
|
||||
ioWait();
|
||||
|
||||
// ICW 2: Where to map IRW bases in IDT
|
||||
outb(PIC_1_DATA, NEW_IRQ_0);
|
||||
ioWait();
|
||||
outb(PIC_2_DATA, NEW_IRQ_8);
|
||||
ioWait();
|
||||
|
||||
// ICW 3: Which IRQ in PIC1 is PIC2; Mapping PIC2 to IRQ 2
|
||||
outb(PIC_1_DATA, 0x04);
|
||||
ioWait();
|
||||
outb(PIC_2_DATA, 0x02);
|
||||
ioWait();
|
||||
|
||||
// ICW 4 - Set x86 mode
|
||||
outb(PIC_1_DATA, 0x01);
|
||||
ioWait();
|
||||
outb(PIC_2_DATA, 0x01);
|
||||
ioWait();
|
||||
|
||||
outb(PIC_1_DATA, pic1Mask);
|
||||
outb(PIC_2_DATA, pic2Mask);
|
||||
}
|
||||
|
||||
+3
-13
@@ -1,23 +1,19 @@
|
||||
#include <interrupt/pit.h>
|
||||
#include <interrupt/idt.h>
|
||||
#include <interrupt/pic.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <tty/tty.h>
|
||||
#include <memory/addresses.h>
|
||||
#include <ports/io.h>
|
||||
#include <stdint.h>
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void timerHandler(intFrame_t* iframe) {
|
||||
void timerHandler(intFrame_t*) {
|
||||
static uint32_t cursorTicks = 0;
|
||||
cursorTicks++;
|
||||
|
||||
if (!terminal->hideCursor) { // TODO: Make a better cursor drawing thing
|
||||
if (!console->hideCursor) { // TODO: Make a better cursor drawing thing
|
||||
if (cursorTicks % 500 == 0) toggleCursor();
|
||||
}
|
||||
|
||||
if (*(uint32_t*)SLEEP_TIMER > 0) { --(*(uint32_t*)SLEEP_TIMER); }
|
||||
|
||||
sendPicEOI(0);
|
||||
}
|
||||
|
||||
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
|
||||
@@ -35,9 +31,3 @@ void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
|
||||
__asm__ volatile ("sti");
|
||||
}
|
||||
|
||||
void setupTimer() { // Sets up IRQ 0 - PIT
|
||||
idtSetGate(0x20, timerHandler, INT_GATE_FLAGS);
|
||||
unsetIrqMask(0);
|
||||
setPitPhase(0, 2, 1000); // Default setup: 1000Hz - 1 tick per 1ms
|
||||
}
|
||||
|
||||
|
||||
+3
-11
@@ -1,6 +1,5 @@
|
||||
#include <interrupt/rtc.h>
|
||||
#include <interrupt/pic.h>
|
||||
#include <interrupt/idt.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <screen/text.h>
|
||||
#include <screen/gfxmode.h>
|
||||
#include <tty/tty.h>
|
||||
@@ -36,7 +35,7 @@ void disableRtc() {
|
||||
__asm__ volatile ("sti");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt)) void rtcHandler(intFrame_t* iframe) {
|
||||
void rtcHandler(intFrame_t* iframe) {
|
||||
datetime_t newDatetime, oldDatetime;
|
||||
static uint16_t rtcTicks = 0;
|
||||
|
||||
@@ -121,20 +120,13 @@ __attribute__ ((interrupt)) void rtcHandler(intFrame_t* iframe) {
|
||||
uint32_t x = gfxMode->xRes - len - 1;
|
||||
char* str = &buf[0];
|
||||
for (uint8_t i = 0; i != len; i++, x++) {
|
||||
drawChar(str[i], x, 0, terminal->fg, terminal->bg);
|
||||
drawChar(str[i], x, 0, console->fg, console->bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getRtcRegister(0x0c);
|
||||
sendPicEOI(8);
|
||||
|
||||
__asm__ volatile ("sti");
|
||||
}
|
||||
|
||||
void setupRtc() { // IRQ 8 - Real Time Clock
|
||||
idtSetGate(0x28, rtcHandler, INT_GATE_FLAGS);
|
||||
unsetIrqMask(8);
|
||||
enableRtc();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
#include <interrupt/syscalls.h>
|
||||
#include <interrupt/idt.h>
|
||||
#include <tty/tty.h>
|
||||
#include <keyboard/keyboard.h>
|
||||
#include <memory/malloc.h>
|
||||
#include <memory/addresses.h>
|
||||
#include <memory/physical.h>
|
||||
#include <fs/fs.h>
|
||||
#include <fs/impl.h>
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* XXX WARNING - Update MAX_SYSCALLS in the handler XXX
|
||||
*/
|
||||
|
||||
int sys_reserved(sys_regs_t) {
|
||||
printf("\e[1N\e[6M Illegal use of Reserved() system call! \e[8M\e[8N\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Args: ebx - number of miliseconds
|
||||
int sys_sleep(sys_regs_t regs) {
|
||||
uint32_t* sleepTimerTicks = (uint32_t*)SLEEP_TIMER;
|
||||
*sleepTimerTicks = regs.ebx;
|
||||
|
||||
while (*sleepTimerTicks > 0) { // Wait...
|
||||
__asm__ volatile ("sti;hlt;cli;");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Args: ebx - int fd
|
||||
// ecx - void* buf
|
||||
// edx - uint32_t len
|
||||
// Rets: Number of bytes written
|
||||
int sys_write(sys_regs_t regs) {
|
||||
int32_t fd = regs.ebx;
|
||||
void* buf = (void*)regs.ecx;
|
||||
uint32_t len = regs.edx;
|
||||
|
||||
// TODO: Open fd table?
|
||||
if (fd == 1) {
|
||||
return terminalWrite(buf, len); // Call a terminal print function
|
||||
} else { return -1; }
|
||||
}
|
||||
|
||||
// TODO: Use a Read() sycall and read from stdin
|
||||
// Args: ebx - char* buffer
|
||||
int sys_read(sys_regs_t regs) {
|
||||
char* s = (char*)regs.ebx;
|
||||
reads(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Args: ebx - size_t count
|
||||
// Rets: Pointer to malloc-ed memory
|
||||
int sys_malloc(sys_regs_t regs) {
|
||||
uint32_t count = regs.ebx;
|
||||
|
||||
// First Malloc()
|
||||
if (!mallocListHead) {
|
||||
mallocInit(count); // Setup malloc linked list
|
||||
}
|
||||
|
||||
void* ptr = mallocNextNode(count);
|
||||
mallocMergeFree();
|
||||
|
||||
return (uint32_t)ptr;
|
||||
}
|
||||
|
||||
// Args: ebx - void* ptr
|
||||
int sys_free(sys_regs_t regs) {
|
||||
void* ptr = (void*)regs.ebx;
|
||||
mallocFree(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Args: ebx - path,
|
||||
// ecx - oflag
|
||||
// Rets: Opened file descriptor
|
||||
int sys_open(sys_regs_t regs) {
|
||||
int fd = 0;
|
||||
char* path = (char*)regs.ebx;
|
||||
uint32_t oflag = regs.ecx;
|
||||
|
||||
// TODO: better file finding
|
||||
inode_t* root = (inode_t*)impl_superblock->rootInodePtr;
|
||||
loadFile(root, (void*)SCRATCH_BLOCK_LOC);
|
||||
|
||||
inode_t* inode = getInode(path, (dirEntry_t*)SCRATCH_BLOCK_LOC);
|
||||
if (inode == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: check if max open files have'nt been reached
|
||||
fd = fsInfo->openFiles++;
|
||||
FILE* fp = fsInfo->openFileTable + fd;
|
||||
fp->_ptr = (void*)0xd000;
|
||||
fp->_offset = 0;
|
||||
fp->_size = inode->sizeBytes;
|
||||
fp->_flag = oflag;
|
||||
fp->_file = fd;
|
||||
|
||||
loadFile(inode, fp->_ptr);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Args: ebx - int fd
|
||||
// Rets: status
|
||||
int sys_close(sys_regs_t regs) {
|
||||
int fd = regs.ebx;
|
||||
|
||||
FILE* fp = fsInfo->openFileTable + fd;
|
||||
free(fp->_ptr);
|
||||
fsInfo->openFiles--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO
|
||||
int sys_seek(sys_regs_t regs) { return -1; }
|
||||
|
||||
// System call table
|
||||
int (*syscalls[MAX_SYSCALLS])(sys_regs_t) = {
|
||||
[SYS_RESERVED] = sys_reserved,
|
||||
[SYS_SLEEP] = sys_sleep,
|
||||
[SYS_WRITE] = sys_write,
|
||||
[SYS_READ] = sys_read,
|
||||
[SYS_MALLOC] = sys_malloc,
|
||||
[SYS_FREE] = sys_free,
|
||||
[SYS_OPEN] = sys_open,
|
||||
[SYS_CLOSE] = sys_close,
|
||||
[SYS_SEEK] = sys_seek,
|
||||
};
|
||||
|
||||
// int 0x80 - Syscall interrupt, handled by this function
|
||||
// eax : Syscall number
|
||||
__attribute__ ((naked)) // No prologue or epilogue, just assembly
|
||||
void syscallHandler(intFrame_t* iframe) {
|
||||
// Interrupt - Stack should contain: ss, esp, eflags, cs, eip
|
||||
// We should also push these regs: ax, gs, fs, es, ds, bp, di, si, dx, cx, bx
|
||||
__asm__ volatile (
|
||||
".intel_syntax noprefix\n" // We use intel syntax
|
||||
".equ MAX_SYSCALLS, 9\n" // Define MAX_SYSCALLS again TODO: I don't want to have to do this
|
||||
|
||||
// Check if syscall exists
|
||||
"cmp eax, MAX_SYSCALLS - 1\n"
|
||||
"ja invalidSyscall\n"
|
||||
|
||||
// Call the syscall
|
||||
"push eax\n"
|
||||
"push gs\n"
|
||||
"push fs\n"
|
||||
"push es\n"
|
||||
"push ds\n"
|
||||
"push ebp\n"
|
||||
"push edi\n"
|
||||
"push esi\n"
|
||||
"push edx\n"
|
||||
"push ecx\n"
|
||||
"push ebx\n"
|
||||
"push esp\n" // Push stack pointer again (for variables and such idk)
|
||||
|
||||
"call [syscalls + eax * 4]\n" // Call syscall from table. Syscall number should be in eax
|
||||
"add esp, 4\n" // Do not override ESP
|
||||
"pop ebx\n"
|
||||
"pop ecx\n"
|
||||
"add esp, 4\n" // Do not override EDX, some syscalls use it
|
||||
|
||||
"pop esi\n"
|
||||
"pop edi\n"
|
||||
"pop ebp\n"
|
||||
"pop ds\n"
|
||||
"pop es\n"
|
||||
"pop fs\n"
|
||||
"pop gs\n"
|
||||
"add esp, 4\n" // Save eax value
|
||||
"iretd\n" // Return from interrupt (32 bit)
|
||||
|
||||
// TODO: Send an error or something here
|
||||
"invalidSyscall:\n"
|
||||
"mov eax, -1\n" // Current error thing
|
||||
"iretd\n"
|
||||
|
||||
".att_syntax" // Switch back to AT&T Syntax (Just in case)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <keyboard/keyboard.h>
|
||||
#include <interrupt/idt.h>
|
||||
#include <interrupt/pic.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <keyboard/keys.h>
|
||||
#include <memory/addresses.h>
|
||||
#include <ports/io.h>
|
||||
@@ -10,8 +9,7 @@
|
||||
static const uint8_t US_Keyboard[2][128] = US_KEYBOARD;
|
||||
keyboardState_t* keyboard = (keyboardState_t*)KEYBOARD_STATE_LOC;
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void keyboardHandler(intFrame_t* iframe) { // TODO: Make this better and be able to read multi-byte scancode
|
||||
void keyboardHandler(intFrame_t*) { // TODO: Make this better and be able to read multi-byte scancode
|
||||
uint8_t scancode = inb(0x60);
|
||||
char c = US_Keyboard[keyboard->shift][scancode];
|
||||
|
||||
@@ -25,12 +23,5 @@ void keyboardHandler(intFrame_t* iframe) { // TODO: Make this better and be able
|
||||
} else if (c != '\0') {
|
||||
keyboard->character = c;
|
||||
}
|
||||
|
||||
sendPicEOI(1);
|
||||
}
|
||||
|
||||
void setupKeyboard() {
|
||||
idtSetGate(0x21, keyboardHandler, INT_GATE_FLAGS);
|
||||
unsetIrqMask(1);
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -4,8 +4,11 @@
|
||||
|
||||
include make.defaults
|
||||
|
||||
$(LIBK): $(LIBK_SRC)
|
||||
LIBK_ASM=$(LIBK_DIR)/interrupt/isr.s
|
||||
|
||||
$(LIBK): $(LIBK_SRC) $(LIBK_ASM)
|
||||
@echo "Building $(LIBK)..."
|
||||
nasm -felf32 -o $(BIN)/libk/isr_asm.o $(LIBK_ASM)
|
||||
for f in $(LIBK_SRC); do\
|
||||
filename=$$(basename $$f .c);\
|
||||
$(CC) $(CFLAGS) -I$(LIBC_INC) -I$(LIBK_INC) -o $(BIN)/libk/$$filename.o -c $$f;\
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ void serialWrite(uint32_t port, char c) {
|
||||
outb(port, c);
|
||||
}
|
||||
|
||||
void serialPrint(uint32_t port, char* s) {
|
||||
void serialPrint(uint32_t port, const char* s) {
|
||||
while (*s != '\0') {
|
||||
if (*s == '\n') serialWrite(port, '\r');
|
||||
serialWrite(port, *s++);
|
||||
|
||||
+7
-7
@@ -39,10 +39,10 @@ void drawChar(char c, uint32_t x, uint32_t y, uint32_t fgColor, uint32_t bgColor
|
||||
|
||||
void scroll() { // TODO: Make this faster (still kinda slow, but memcpy32() helped alot)
|
||||
uint8_t charHeight = ((font_t*)FONT_LOC)->height;
|
||||
if (terminal->y+1 < terminal->height) { return; } // Check if we should scroll
|
||||
if (console->y+1 < console->height) { return; } // Check if we should scroll
|
||||
|
||||
uint32_t bytesPerLine = charHeight * gfxMode->bytesPerScanline;
|
||||
uint32_t lines = terminal->height;
|
||||
uint32_t lines = console->height;
|
||||
uint32_t vidmem = gfxMode->physicalBasePtr;
|
||||
|
||||
for (uint32_t i = 1; i < lines; i++) {
|
||||
@@ -50,7 +50,7 @@ void scroll() { // TODO: Make this faster (still kinda slow, but memcpy32() help
|
||||
memcpy32((char*)address, (char*)(address - bytesPerLine), bytesPerLine);
|
||||
}
|
||||
|
||||
uint32_t color = convertColor(terminal->bg);
|
||||
uint32_t color = convertColor(console->bg);
|
||||
uint8_t* lastLine = (uint8_t*)(vidmem + (lines-1) * bytesPerLine);
|
||||
uint8_t bytesPerPx = (gfxMode->bpp+1) / 8;
|
||||
|
||||
@@ -61,16 +61,16 @@ void scroll() { // TODO: Make this faster (still kinda slow, but memcpy32() help
|
||||
lastLine += bytesPerPx;
|
||||
}
|
||||
|
||||
terminal->y--;
|
||||
console->y--;
|
||||
}
|
||||
|
||||
// TODO: Make this comply with the new terminal.h thing!
|
||||
// TODO: Make this comply with the new console.h thing!
|
||||
void clearScreen(uint32_t bgColor) {
|
||||
uint8_t* vidmem = (uint8_t*)gfxMode->physicalBasePtr;
|
||||
uint8_t bytesPerPx = (gfxMode->bpp+1) / 8;
|
||||
|
||||
terminal->x = 0;
|
||||
terminal->y = 0;
|
||||
console->x = 0;
|
||||
console->y = 0;
|
||||
|
||||
uint32_t color = convertColor(bgColor);
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int sys_close(intFrame_t* iframe) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <error/debug.h>
|
||||
|
||||
int sys_exit(intFrame_t* iframe) {
|
||||
debugf("Tried to exit with %d", iframe->eax);
|
||||
return iframe->eax;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <memory/malloc.h>
|
||||
|
||||
int sys_free(intFrame_t* iframe) {
|
||||
void* ptr = (void*)iframe->ebx;
|
||||
mallocFree(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <memory/malloc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int sys_malloc(intFrame_t* iframe) {
|
||||
size_t count = iframe->ebx;
|
||||
|
||||
// First Malloc()
|
||||
if (!mallocListHead) {
|
||||
mallocInit(count); // Setup malloc linked list
|
||||
}
|
||||
|
||||
void* ptr = mallocNextNode(count);
|
||||
mallocMergeFree();
|
||||
|
||||
return (size_t)ptr;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int sys_open(intFrame_t* iframe) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int sys_read(intFrame_t* iframe) {
|
||||
char* s = (char*)iframe->ebx;
|
||||
reads(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
|
||||
int sys_seek(intFrame_t* iframe) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <memory/addresses.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int sys_sleep(intFrame_t* iframe) {
|
||||
uint32_t* sleepTimerTicks = (uint32_t*)SLEEP_TIMER;
|
||||
*sleepTimerTicks = iframe->ebx;
|
||||
|
||||
while (*sleepTimerTicks > 0) { __asm__ volatile ("sti; hlt"); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <tty/tty.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int sys_write(intFrame_t* iframe) {
|
||||
int fd = iframe->ebx;
|
||||
void* buf = (void*)iframe->ecx;
|
||||
size_t len = iframe->edx;
|
||||
|
||||
if (fd == 1) {
|
||||
return consoleWrite(buf, len);
|
||||
} else { return -1; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <syscalls/syscalls.h>
|
||||
#include <interrupt/isr.h>
|
||||
#include <error/debug.h>
|
||||
#include <syscall.h>
|
||||
|
||||
// System call table
|
||||
int (*syscalls[MAX_SYSCALLS])(intFrame_t*) = {
|
||||
[SYS_EXIT] = sys_exit,
|
||||
[SYS_READ] = sys_read,
|
||||
[SYS_WRITE] = sys_write,
|
||||
[SYS_OPEN] = sys_open,
|
||||
[SYS_CLOSE] = sys_close,
|
||||
[SYS_SEEK] = sys_seek,
|
||||
[SYS_MALLOC] = sys_malloc,
|
||||
[SYS_FREE] = sys_free,
|
||||
[SYS_SLEEP] = sys_sleep,
|
||||
};
|
||||
|
||||
// Syscall handler
|
||||
int syscallHandler(intFrame_t* iframe) {
|
||||
if (iframe->eax > MAX_SYSCALLS-1) { // Syscall doesn't exist
|
||||
debugf("Error: Syscall(%d) does not exist!\n", iframe->eax);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return syscalls[iframe->eax](iframe);
|
||||
}
|
||||
|
||||
+33
-33
@@ -7,11 +7,11 @@
|
||||
#include <stdbool.h>
|
||||
#include <sys/gfx.h>
|
||||
|
||||
terminal_t* terminal = (terminal_t*)TERMINAL_INFO_LOC;
|
||||
console_t* console = (console_t*)TERMINAL_INFO_LOC;
|
||||
|
||||
int32_t terminalWrite(const void* buf, uint32_t len) { // TODO fix font size
|
||||
terminal->width = gfxMode->xRes / 8;//*(uint8_t*)(FONT_LOC);
|
||||
terminal->height = gfxMode->yRes / 16;//*(uint8_t*)(FONT_LOC+1);
|
||||
int32_t consoleWrite(const void* buf, uint32_t len) { // TODO fix font size
|
||||
console->width = gfxMode->xRes / 8;//*(uint8_t*)(FONT_LOC);
|
||||
console->height = gfxMode->yRes / 16;//*(uint8_t*)(FONT_LOC+1);
|
||||
|
||||
char* str = (char*)buf;
|
||||
uint32_t i;
|
||||
@@ -19,18 +19,18 @@ int32_t terminalWrite(const void* buf, uint32_t len) { // TODO fix font size
|
||||
// Do we need to check for NULL? Can we just skip it/ignore it?
|
||||
for (i = 0; i < len && str[i] != '\0'; i++) {
|
||||
if (str[i] == '\n') {
|
||||
drawChar(' ', terminal->x, terminal->y, terminal->fg, terminal->bg);
|
||||
terminal->y++;
|
||||
terminal->x = 0;
|
||||
drawChar(' ', console->x, console->y, console->fg, console->bg);
|
||||
console->y++;
|
||||
console->x = 0;
|
||||
} else if (str[i] == '\b') {
|
||||
drawChar(' ', terminal->x, terminal->y, terminal->fg, terminal->bg);
|
||||
if (terminal->x == 0) {
|
||||
terminal->x = terminal->width - 1;
|
||||
terminal->y--; // Y could be 0?
|
||||
drawChar(' ', console->x, console->y, console->fg, console->bg);
|
||||
if (console->x == 0) {
|
||||
console->x = console->width - 1;
|
||||
console->y--; // Y could be 0?
|
||||
} else {
|
||||
terminal->x--;
|
||||
console->x--;
|
||||
}
|
||||
drawChar(' ', terminal->x, terminal->y, terminal->fg, terminal->bg);
|
||||
drawChar(' ', console->x, console->y, console->fg, console->bg);
|
||||
} else if (str[i] == '\x1b') { // Escape sequence
|
||||
if (str[++i] != '[') { // TODO: Support more types of escape sequences
|
||||
i--;
|
||||
@@ -57,33 +57,33 @@ int32_t terminalWrite(const void* buf, uint32_t len) { // TODO fix font size
|
||||
|
||||
switch (str[i]) { // TODO: Add default values (see docs/escape.txt)
|
||||
case 'A': // Cursor up
|
||||
terminal->y -= args[0];
|
||||
console->y -= args[0];
|
||||
break;
|
||||
case 'B': // Cursor down
|
||||
terminal->y += args[0];
|
||||
console->y += args[0];
|
||||
break;
|
||||
case 'C': // Cursor left
|
||||
terminal->x -= args[0];
|
||||
console->x -= args[0];
|
||||
break;
|
||||
case 'D': // Cursor right
|
||||
terminal->x += args[0];
|
||||
console->x += args[0];
|
||||
break;
|
||||
case 'E': // nth row
|
||||
terminal->x = args[0];
|
||||
console->x = args[0];
|
||||
break;
|
||||
case 'F': // nth col
|
||||
terminal->y = args[0];
|
||||
console->y = args[0];
|
||||
break;
|
||||
case 'G': // show/hide cursor
|
||||
terminal->hideCursor = args[0] ? false : true;
|
||||
console->hideCursor = args[0] ? false : true;
|
||||
break;
|
||||
case 'H': // move cursor to (x,y)
|
||||
terminal->x = args[0];
|
||||
terminal->y = args[1];
|
||||
console->x = args[0];
|
||||
console->y = args[1];
|
||||
break;
|
||||
case 'I': // RESERVED
|
||||
case 'J': // Erase screen
|
||||
clearScreen(terminal->bg);
|
||||
clearScreen(console->bg);
|
||||
break;
|
||||
case 'K': // Erase line
|
||||
break; // TODO
|
||||
@@ -91,27 +91,27 @@ int32_t terminalWrite(const void* buf, uint32_t len) { // TODO fix font size
|
||||
break; // TODO
|
||||
case 'M': // Set FG
|
||||
if (args[0] < 8) {
|
||||
terminal->fg = codeToColor(args[0]);
|
||||
console->fg = codeToColor(args[0]);
|
||||
} else if (args[0] == 8) {
|
||||
terminal->fg = FG_COLOR;
|
||||
console->fg = FG_COLOR;
|
||||
}
|
||||
break;
|
||||
case 'N': // Set BG
|
||||
if (args[0] < 8) {
|
||||
terminal->bg = codeToColor(args[0]);
|
||||
console->bg = codeToColor(args[0]);
|
||||
} else if (args[0] == 8) {
|
||||
terminal->bg = BG_COLOR;
|
||||
console->bg = BG_COLOR;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
drawChar(str[i], terminal->x, terminal->y, terminal->fg, terminal->bg);
|
||||
terminal->x++;
|
||||
drawChar(str[i], console->x, console->y, console->fg, console->bg);
|
||||
console->x++;
|
||||
|
||||
if (terminal->x >= terminal->width) { // Go to next line
|
||||
terminal->y++;
|
||||
terminal->x = 0;
|
||||
if (console->x >= console->width) { // Go to next line
|
||||
console->y++;
|
||||
console->x = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,6 +124,6 @@ void toggleCursor() {
|
||||
static bool visible = false;
|
||||
visible = !visible;
|
||||
|
||||
drawChar(visible ? 127 : ' ', terminal->x, terminal->y, terminal->fg, terminal->bg);
|
||||
drawChar(visible ? 127 : ' ', console->x, console->y, console->fg, console->bg);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user