From 1f71b9576db536af84155363e14fc49e92de2eef Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Sun, 29 Aug 2021 02:52:48 -0500 Subject: backup 8.29.21 --- src/kernel/klog.c | 180 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 136 insertions(+), 44 deletions(-) (limited to 'src/kernel/klog.c') diff --git a/src/kernel/klog.c b/src/kernel/klog.c index 52444b1..c62c4d3 100644 --- a/src/kernel/klog.c +++ b/src/kernel/klog.c @@ -1,57 +1,104 @@ #include -#include #include #include -#include +#include #include #include +#include -//README -//this file has some temporary workarounds until I get further into development -//this isn't going to be the serial driver I end up keeping +//right now, this program is simply for debuging. +//Later in development, we will hook it up to a TTY, impliment FCS, etc #define VIDEO_BUFFER PHYS_TO_VIRT(0xb8000) #define MAX_LOOPBACK_ATTEMPTS 20 -//later we'll set it up for interrupting instead of polling -bool init_serial(uint16_t port) { - outb_wait(port + 1, 0x00); - outb_wait(port + 2, 0x00); - outb_wait(port + 3, 0x80); - outb_wait(port + 0, 0x01); //here - outb_wait(port + 1, 0x00); - outb_wait(port + 3, 0x03); - outb_wait(port + 2, 0xc7); - outb_wait(port + 4, 0x0b); - outb_wait(port + 4, 0x1e); - - - //we shouldn't accept this as a loopback success. - //I'm making an exception because my dell desktop has a faulty serial port - //that requires some extra effort. - - uint8_t loopback_byte; - for(int attempts = 0; attempts < MAX_LOOPBACK_ATTEMPTS; attempts++) { - outb_wait(port + 0, 0xae); // test char - loopback_byte = inb(port); - if(loopback_byte == 0xae) break; - } +#define KLOG_COM1 0 +#define KLOG_COM2 1 +#define KLOG_COM3 2 +#define KLOG_COM4 3 +#define KLOG_SCREEN 4 + +static int debug_output = KLOG_SCREEN; + +#define SERIAL_THR 0 //transmitter holding buffer +#define SERIAL_RBR 1 //receiving holding buffer +#define SERIAL_DLL 0 //divisor latch low byte +#define SERIAL_DLH 1 //divisor latch high byte +#define SERIAL_FCR 2 +#define SERIAL_IIR 2 +#define SERIAL_LCR 3 +#define SERIAL_MCR 4 +#define SERIAL_LSR 5 +#define SERIAL_MSR 6 +#define SERIAL_SR 7 + +#define COM1 0x3f8 +#define COM2 0x2f8 +#define COM3 0x3e8 +#define COM4 0x2e8 + +uint16_t serial_ports[4] = {COM1, COM2, COM3, COM4}; + +/** +enum com_ports { + COM1 = 0x3f8, + COM2 = 0x2f8, + COM3 = 0x3e8, + COM4 = 0x2e8 +}; +**/ + + +static bool detect_serial(uint16_t port) { + outb(port + SERIAL_FCR, 0xe7); + outb(port + SERIAL_SR, 0xba); + if((inb(port + SERIAL_IIR) & (1 << 6)) && (inb(port + SERIAL_SR) == 0xba)) { + outb_wait(port + 1, 0x00); + outb_wait(port + 2, 0x00); + outb_wait(port + 3, 0x80); + outb_wait(port + 0, 0x01); + outb_wait(port + 1, 0x00); + outb_wait(port + 3, 0x03); + outb_wait(port + 2, 0xc7); + outb_wait(port + 4, 0x0b); + outb_wait(port + 4, 0x1e); - if(loopback_byte != 0xae) { - //I'm sorry if these next few lines give you a stroke. They gave me one. + + uint8_t loopback_byte; + for(int attempts = 0; attempts < MAX_LOOPBACK_ATTEMPTS; attempts++) { + outb_wait(port + 0, 0xae); + loopback_byte = inb(port); + if(loopback_byte == 0xae) break; + } + + if(loopback_byte != 0xae) { + //you better delete this once you get tty drivers working... + int a = 0 / 0; + } - //My old Dell test desktop has disfunctional serial hardware that only works after a reboot. - //Seeing we don't have ACPI set up yet, we can't reboot without crashing. - //IM GOING TO REMOVE THIS ONCE I DEVELOP THE "REAL" SERIAL DRIVER!!!! - asm("mov rax, 0\n" - "div rax\n"); - return false; + outb_wait(port + 4, 0x0f); + return true; } - - outb_wait(port + 4, 0x0f); - return true; + return false; } + +//this function is going to be teleted after ttys work. +//but, for now, if a serial port is detected, it'll set debug_output to 0-3 (com port #). +//debug_output == 4 is for screen output. +void init_klog() { + for(unsigned int p = 0; p < (sizeof(serial_ports) / sizeof(uint16_t)); p++) { + if(detect_serial(serial_ports[p])) { + debug_output = p; + return; + } + } + debug_output = KLOG_SCREEN; + _putchar('\n'); +} + + + void _putchar_serial(uint16_t port, char msg) { while(!(inb(port + 5) & 0x20)); //wait for transmit to be done outb_wait(port, msg); @@ -80,13 +127,10 @@ void next_line() { } void move_cursor(unsigned int x, unsigned int y) { - //yeah yeah yeah, it doens't test for overflows... I'm gonna delete this once i get serial working - //on my second desktop on_char = x; on_line = y; } -//until we get serial working on hp void _putchar_screen(char msg) { if(on_char >= 80) { next_line(); @@ -94,7 +138,55 @@ void _putchar_screen(char msg) { next_line(); return; } - char *screen_buffer = (void *)((uint64_t)VIDEO_BUFFER + ((on_line * 160) + (on_char * 2))); - *screen_buffer = msg; + *(char *)((uint64_t)VIDEO_BUFFER + ((on_line * 160) + (on_char * 2))) = msg; on_char++; } + + + +void _putchar(char character) { + if(debug_output < (sizeof(serial_ports) / sizeof(uint16_t))) { + _putchar_serial(serial_ports[debug_output], character); + } + else { + _putchar_screen(character); + } +} + + + + +/** + * Set the value "0xE7" to the FCR to test the status of the FIFO flags. +Read the value of the IIR to test for what flags actually got set. +If Bit 6 is set Then + If Bit 7 is set Then + If Bit 5 is set Then + UART is 16750 (64 bit fifo) + Else + UART is 16550A (idk why this matters, 16 bit fifo) + End If + Else + UART is 16550 (16 bit fifo) + End If +Else you know the chip doesn't use FIFO, so we need to check the scratch register + Set some arbitrary value like 0x2A to the Scratch Register. + If the arbitrary value comes back identical + UART is 16450 (idk why this matters, 1 byte at a time) + Else + UART is 8250 (one byte at a time) + End If +End If + +#define UART_16750 0 +#define UART_16550A 1 +#define UART_16550 2 +#define UART_16450 3 +#define UART_8250 4 + +#define KLOG_COM1 0 +#define KLOG_COM2 1 +#define KLOG_COM3 2 +#define KLOG_COM4 3 +#define KLOG_SCREEN 4 * 5 // 5 leaves enough space for com ports +**/ -- cgit v1.2.3