Major libk restructuring, also rewrote drivers/serial.h

This commit is contained in:
2024-10-27 10:23:56 +01:00
parent 4079049242
commit e8a55d72a5
62 changed files with 334 additions and 380 deletions
+53
View File
@@ -0,0 +1,53 @@
#include <drivers/disk.h>
#include <cpu/system.h>
#include <stdint.h>
void diskRead(uint32_t lbaAddress, uint8_t sectorCount, char* dst) {
outb(PIO_PORT + 6, ((lbaAddress >> 24) & 0x0f) | 0xe0); // 6 - Use LBA; 4 - Drive number; 3-0 - Highest lba address nibble
outb(PIO_PORT + 2, sectorCount); // Sector count register
outb(PIO_PORT + 3, (uint8_t)(lbaAddress)); // Lowest lba address byte
outb(PIO_PORT + 4, (uint8_t)(lbaAddress >> 8)); // Middle lba address byte
outb(PIO_PORT + 5, (uint8_t)(lbaAddress >> 16)); // High lba address byte
outb(PIO_PORT + 7, READ_COMMAND); // Command register
uint16_t* address = (uint16_t*)dst;
for (uint8_t i = sectorCount; i > 0; i--) {
while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear
for (size_t j = 0; j < 256; j++) {
*address++ = inw(PIO_PORT); // Read 256 words (512 Bytes = 1 Sector)
}
for (uint8_t delay = 0; delay < 4; delay++) { // 400ns delay
inb(0x3f6); // Alternate status register
}
}
}
void diskWrite(uint32_t lbaAddress, uint8_t sectorCount, char* src) {
outb(PIO_PORT + 6, ((lbaAddress >> 24) & 0x0f) | 0xe0); // 6 - Use LBA; 4 - Drive number; 3-0 - Highest lba address nibble
outb(PIO_PORT + 2, sectorCount); // Sector count register
outb(PIO_PORT + 3, (uint8_t)(lbaAddress)); // Lowest lba address byte
outb(PIO_PORT + 4, (uint8_t)(lbaAddress >> 8)); // Middle lba address byte
outb(PIO_PORT + 5, (uint8_t)(lbaAddress >> 16)); // High lba address byte
outb(PIO_PORT + 7, WRITE_COMMAND); // Command register
uint16_t* address = (uint16_t*)src;
for (uint8_t i = sectorCount; i > 0; i--) {
while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear
for (size_t j = 0; j < 256; j++) {
outw(PIO_PORT, *address++); // Write 256 words (512 Bytes = 1 Sector)
}
for (uint8_t delay = 0; delay < 4; delay++) { // 400ns delay
inb(0x3f6); // Alternate status register
}
}
outb(PIO_PORT + 7, CACHE_FLUSH); // Cache flush
while (inb(PIO_PORT + 7) & (1 << 7)); // Poll status register untill BSY bit is clear
}
+23
View File
@@ -0,0 +1,23 @@
#include <drivers/keyboard.h>
#include <memory/addresses.h>
#include <cpu/system.h>
#include <cpu/isr.h>
static const uint8_t US_Keyboard[2][128] = US_KEYBOARD;
keyboardState_t* keyboard = (keyboardState_t*)KEYBOARD_STATE_LOC;
// TODO: Make this better and be able to read multi-byte scancode
void keyboardHandler(intFrame_t*) {
uint8_t scancode = inb(0x60);
char c = US_Keyboard[keyboard->shift][scancode];
if (scancode == LEFT_SHIFT_PRESS || scancode == RIGHT_SHIFT_PRESS) {
keyboard->shift = 1;
} else if (scancode == LEFT_SHIFT_RELEASE || scancode == RIGHT_SHIFT_RELEASE) {
keyboard->shift = 0;
}
if (scancode & 0x80) { // Keyup
} else if (c != '\0') { keyboard->character = c; }
}
+27
View File
@@ -0,0 +1,27 @@
#include <drivers/pcspk.h>
#include <drivers/timer.h>
#include <cpu/system.h>
#include <sys/notes.h>
#include <stdint.h>
#include <time.h>
void enableSpeaker() {
uint8_t temp = inb(PC_SPEAKER);
outb(PC_SPEAKER, temp | 0x03); // Set first 2 bits
}
void disableSpeaker() {
uint8_t temp = inb(PC_SPEAKER);
outb(PC_SPEAKER, temp & 0xfc); // Set first 2 bits
}
void playNote(note_t note, uint32_t ms) {
setPitPhase(2, 3, note);
sleep(ms);
}
void rest(uint32_t ms) {
setPitPhase(2, 3, 30000); // Unhearable noise
sleep(ms);
}
+131
View File
@@ -0,0 +1,131 @@
#include <drivers/rtc.h>
#include <screen/gfxmode.h>
#include <screen/text.h>
#include <screen/tty.h>
#include <cpu/system.h>
#include <cpu/isr.h>
#include <string.h>
static datetime_t* datetime = (datetime_t*)DATETIME_LOC;
int 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");
}
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) / 16) * 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 (1) { // 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, " ");
if (datetime->hour < 10) strcat(buf, "0");
strcat(buf, itoa(datetime->hour, 10));
strcat(buf, ":");
if (datetime->minute < 10) strcat(buf, "0");
strcat(buf, itoa(datetime->minute, 10));
strcat(buf, ":");
if (datetime->second < 10) strcat(buf, "0");
strcat(buf, itoa(datetime->second, 10));
// The clock is a little offset down (about 0.4 of a character) It does look nice though!
uint8_t len = strlen(buf);
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, console->fg, console->bg);
}
}
}
getRtcRegister(0x0c);
__asm__ volatile ("sti");
}
+50
View File
@@ -0,0 +1,50 @@
#include <drivers/serial.h>
#include <cpu/system.h>
#include <stdio.h>
#include <stdarg.h>
int serialEnable(int port) {
outb(port + 1, 0x00); // Disable all interrupts
outb(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(port + 0, 0x03); // Set divisor to 3 (low byte) 38400 baud
outb(port + 1, 0x00); // (high byte)
outb(port + 3, 0x03); // 8 bits, no parity, one stop bit
outb(port + 2, 0xC7); // Enable FIFO, clear them, with 14 byte threshold
outb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(port + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if it returns)
if (inb(port + 0) != 0xAE) return 1;
outb(port + 4, 0x0F); // non-loopback, IRQs enabled, OUT#1 and OUT#2 bits enabled
return 0;
}
int setupSerial() {
if (serialEnable(PORT_COM1) != 0) { return 1; }
outb(PORT_COM1 + 1, 0x01);
return 0;
}
static int serialTransimitEmpty(int port) { return inb(port + 5) & 0x20; }
static int serialRecieved(int port) { return inb(port + 5) & 0x01; }
void serialWrite(int port, char c) { while (!serialTransimitEmpty(port)); outb(port, c); }
char serialRead(int port) { while (!serialRecieved(port)); return inb(port); }
char serialReadAsync(int port) { return inb(port); }
void _dbgPutc(char c, void* arg) {
(void)arg;
serialWrite(PORT_COM1, c);
if (c == '\n') serialWrite(PORT_COM1, '\r');
}
int vdebugf(const char* fmt, va_list va) { return vpprintf(_dbgPutc, NULL, fmt, va); }
int debugf(const char* fmt, ...) {
va_list va;
va_start(va, fmt);
int ret = vdebugf(fmt, va);
va_end(va);
return ret;
}
+33
View File
@@ -0,0 +1,33 @@
#include <drivers/timer.h>
#include <memory/addresses.h>
#include <screen/tty.h>
#include <cpu/system.h>
#include <cpu/isr.h>
#include <stdint.h>
void timerHandler(intFrame_t*) {
static uint32_t cursorTicks = 0;
cursorTicks++;
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); }
}
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
if (channel > 2 || opMode > 7) { return; }
__asm__ volatile ("cli");
// Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86
outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1)));
// Send frequency
uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out
outb(CHANNEL_0 + channel, (uint8_t)freq);
outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8));
__asm__ volatile ("sti");
}