From daa6d35045ca1d82080b734726f05a9ce397ced1 Mon Sep 17 00:00:00 2001 From: Tom-on64 Date: Wed, 8 May 2024 16:54:25 +0200 Subject: [PATCH] Added Real Time Clock. Time is now being shown at the top --- Makefile | 14 ++-- include/interrupt/rtc.h | 148 ++++++++++++++++++++++++++++++++++++++++ src/filetable.asm | 10 +-- src/kernel.c | 5 +- src/stage1.asm | 2 +- 5 files changed, 167 insertions(+), 12 deletions(-) create mode 100644 include/interrupt/rtc.h diff --git a/Makefile b/Makefile index 1b06e2d..c6191e8 100644 --- a/Makefile +++ b/Makefile @@ -25,10 +25,10 @@ filesystem: bootloader kernel $(C_FILES) $(FONTS) @dd if=$(BUILD)/boot.bin of=kern.iso bs=512 seek=0 conv=notrunc status=none @dd if=$(BUILD)/filetable.bin of=kern.iso bs=512 seek=5 conv=notrunc status=none @dd if=$(BUILD)/kernel.bin of=kern.iso bs=512 seek=6 conv=notrunc status=none - @dd if=$(BUILD)/term16n.bin of=kern.iso bs=512 seek=36 conv=notrunc status=none - @dd if=$(BUILD)/testfont.bin of=kern.iso bs=512 seek=40 conv=notrunc status=none - @dd if=$(SRC)/fs/test.txt of=kern.iso bs=512 seek=44 conv=notrunc status=none - @dd if=$(BUILD)/calc.bin of=kern.iso bs=512 seek=45 conv=notrunc status=none + @dd if=$(BUILD)/term16n.bin of=kern.iso bs=512 seek=46 conv=notrunc status=none + @dd if=$(BUILD)/testfont.bin of=kern.iso bs=512 seek=50 conv=notrunc status=none + @dd if=$(SRC)/fs/test.txt of=kern.iso bs=512 seek=54 conv=notrunc status=none + @dd if=$(BUILD)/calc.bin of=kern.iso bs=512 seek=55 conv=notrunc status=none $(BUILD): @[ -d $(BUILD) ] || mkdir $(BUILD) @@ -63,7 +63,11 @@ $(FONTS): # Run QEMU run: - qemu-system-x86_64 -drive format=raw,file="./kern.iso",index=0,media=disk -m 256M -accel tcg + qemu-system-x86_64\ + -drive format=raw,file="./kern.iso",index=0,media=disk\ + -m 256M\ + -accel tcg\ + -rtc base=localtime,clock=host,driftfix=slew # Clean all build files clean: diff --git a/include/interrupt/rtc.h b/include/interrupt/rtc.h new file mode 100644 index 0000000..354d85c --- /dev/null +++ b/include/interrupt/rtc.h @@ -0,0 +1,148 @@ +#ifndef RTC_H +#define RTC_H + +#include +#include +#include +#include +#include + +#define CMOS_ADDRESS 0x70 +#define CMOS_DATA 0x71 + +typedef struct { + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day; + uint8_t month; + uint16_t year; +} __attribute__ ((packed)) datetime_t; + +static datetime_t* datetime = (datetime_t*)0x2000; // TODO: Put this at a constant address in memory + +bool cmosUpdateProgress() { + outb(CMOS_ADDRESS, 0x8a); // Read status reg A, disable NMI + return inb(CMOS_DATA) & 0x80; +} + +uint8_t getRtcRegister(uint8_t reg) { + outb(CMOS_ADDRESS, reg | 0x80); // Disable NMI when sending + return inb(CMOS_DATA); +} + +void enableRtc() { + uint8_t regB = getRtcRegister(0x0b); + outb(CMOS_ADDRESS, 0x8b); + outb(CMOS_DATA, regB | 0x40); // Set bit 6 - periodic int at 1024Hz + + getRtcRegister(0x0c); // Clear pending interrupts +} + +void disableRtc() { + __asm__ volatile ("cli"); + uint8_t regB = getRtcRegister(0x0b); + outb(CMOS_ADDRESS, 0x8b); + outb(CMOS_DATA, regB & 0xbf); // Clear bit 6 + __asm__ volatile ("sti"); +} + +__attribute__ ((interrupt)) void rtcHandler(intFrame_t* iframe) { + datetime_t newDatetime, oldDatetime; + static uint16_t rtcTicks = 0; + + __asm__ volatile ("cli"); + rtcTicks++; + if (rtcTicks % 1024 == 0) { // 1 Second has passed + while (cmosUpdateProgress()); // Wait + + newDatetime.second = getRtcRegister(0); + newDatetime.minute = getRtcRegister(2); + newDatetime.hour = getRtcRegister(4); + newDatetime.day = getRtcRegister(7); + newDatetime.month = getRtcRegister(8); + newDatetime.year = getRtcRegister(9); + + do { + oldDatetime = newDatetime; + + while (cmosUpdateProgress()); // Wait + newDatetime.second = getRtcRegister(0); + newDatetime.minute = getRtcRegister(2); + newDatetime.hour = getRtcRegister(4); + newDatetime.day = getRtcRegister(7); + newDatetime.month = getRtcRegister(8); + newDatetime.year = getRtcRegister(9); + + } while ( + newDatetime.second != oldDatetime.second || + newDatetime.minute != oldDatetime.minute || + newDatetime.hour != oldDatetime.hour || + newDatetime.day != oldDatetime.day || + newDatetime.month != oldDatetime.month || + newDatetime.year != oldDatetime.year + ); + + uint8_t regB = getRtcRegister(0x0b); + if (!(regB & 0x04)) { + newDatetime.second = (newDatetime.second & 0x0f) + ((newDatetime.second >> 4) * 10); + newDatetime.minute = (newDatetime.minute & 0x0f) + ((newDatetime.minute >> 4) * 10); + newDatetime.hour = ((newDatetime.hour & 0x0f) + (((newDatetime.hour & 0x70) >> 4) * 10)) | (newDatetime.hour * 0x80); // 12/24 Hour format bs + newDatetime.day = (newDatetime.day & 0x0f) + ((newDatetime.day >> 4) * 10); + newDatetime.month = (newDatetime.month & 0x0f) + ((newDatetime.month >> 4) * 10); + newDatetime.year = (newDatetime.year & 0x0f) + ((newDatetime.year >> 4) * 10); + } + + // Convert 12 to 14 hour format + if (!(regB & 0x02) && (newDatetime.hour & 0x80)) { + newDatetime.hour = ((newDatetime.hour & 0x7f) + 12) % 24; + } + + newDatetime.year += 2000; // Add current century + + //*datetime = newDatetime; + + datetime->second = newDatetime.second; + datetime->minute = newDatetime.minute; + datetime->hour = newDatetime.hour; + datetime->day = newDatetime.day; + datetime->month = newDatetime.month; + datetime->year = newDatetime.year; + + if (true) { // TODO: Probably get rid of this idk + char buf[20] = { 0 }; // "12/12 2012 12:12:12" - Max string 20 chars with null byte + + strcat(buf, itoa(datetime->day, 10)); + strcat(buf, "/"); + strcat(buf, itoa(datetime->month, 10)); + strcat(buf, " "); + strcat(buf, itoa(datetime->year, 10)); + strcat(buf, " "); + strcat(buf, itoa(datetime->hour, 10)); + strcat(buf, ":"); + strcat(buf, itoa(datetime->minute, 10)); + strcat(buf, ":"); + strcat(buf, itoa(datetime->second, 10)); + + printAt(" ", 30, 0); + bgColor = 0x0027323f; + fgColor = 0x00ededed; + printAt(buf, 30, 0); + bgColor = BG_COLOR; + fgColor = FG_COLOR; + } + } + + getRtcRegister(0x0c); + sendPicEOI(8); + + __asm__ volatile ("sti"); +} + +void setupRtc() { // IRQ 8 - Real Time Clock + idtSetGate(0x28, rtcHandler, INT_GATE_FLAGS); + unsetIrqMask(8); + enableRtc(); +} + +#endif diff --git a/src/filetable.asm b/src/filetable.asm index 85812da..f1f991d 100644 --- a/src/filetable.asm +++ b/src/filetable.asm @@ -12,11 +12,11 @@ filetable: db "boot",0,0,0,0,0,0, "bin",0,0,5 db "filetable",0, "tab",0,5,1 - db "kernel",0,0,0,0, "bin",0,6,30 - db "term16n",0,0,0, "fnt",0,36,4 - db "testfont",0,0, "fnt",0,40,4 - db "test",0,0,0,0,0,0, "txt",0,44,1 - db "calc",0,0,0,0,0,0, "bin",0,45,2 + db "kernel",0,0,0,0, "bin",0,6,40 + db "term16n",0,0,0, "fnt",0,46,4 + db "testfont",0,0, "fnt",0,50,4 + db "test",0,0,0,0,0,0, "txt",0,54,1 + db "calc",0,0,0,0,0,0, "bin",0,55,2 times 512-($-$$) db 0 diff --git a/src/kernel.c b/src/kernel.c index 5e68cb1..520d30f 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #define PROMPT "#> " @@ -39,7 +40,7 @@ void main() { deinitMemoryRegion(memmapAddr, maxBlocks / BLOCKS_PER_BYTE); // TODO: Find font in filetable - diskRead(36, 4, font); // Read font from disk + diskRead(46, 4, font); // Read font from disk clear(); print("kern.\n\n"); @@ -52,9 +53,11 @@ void main() { idtSetGate(0x80, syscallHandler, USR_INT_GAME_FLAGS); // Setup Syscall handler in IDT for int 0x80 disableIrqs(); remapPic(); + unsetIrqMask(2); // Enable PIC 2 line __asm__ volatile ("sti"); setupTimer(); + setupRtc(); setupKeyboard(); // Run Interactive Shell Program diff --git a/src/stage1.asm b/src/stage1.asm index 75865af..9d881a0 100644 --- a/src/stage1.asm +++ b/src/stage1.asm @@ -4,7 +4,7 @@ %define VIDMEM 0xb800 %define FILETAB_LOC 0x7000 ; TODO: Read kernel size and location from ft -%define KERNEL_SIZE 30 ; 15kB +%define KERNEL_SIZE 40 ; 20kB start: mov [driveNum], dl ; Store the drive number