forked from PoliEcho-holding-org/kern
Major libk restructuring, also rewrote drivers/serial.h
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user