diff options
Diffstat (limited to 'devices')
-rw-r--r-- | devices/Makefile | 2 | ||||
-rw-r--r-- | devices/pckbd.c | 3 | ||||
-rw-r--r-- | devices/uart.h | 17 | ||||
-rw-r--r-- | devices/uart.hpp | 7 | ||||
-rw-r--r-- | devices/uart_16550.c | 117 | ||||
-rw-r--r-- | devices/uart_16550.cpp | 110 | ||||
-rw-r--r-- | devices/vga.cpp (renamed from devices/vga.c) | 56 | ||||
-rw-r--r-- | devices/vga.h | 33 | ||||
-rw-r--r-- | devices/vga.hpp | 51 |
9 files changed, 191 insertions, 205 deletions
diff --git a/devices/Makefile b/devices/Makefile index 0c3a0b1..3acf31c 100644 --- a/devices/Makefile +++ b/devices/Makefile @@ -1,6 +1,6 @@ include ../Makefile.config -devs.SRCS = pic_8259.c uart_16550.c vga.c i8042.c pckbd.c mouse.c +devs.SRCS = pic_8259.c uart_16550.cpp vga.cpp i8042.c pckbd.c mouse.c include ../rules.mk diff --git a/devices/pckbd.c b/devices/pckbd.c index c4fce5b..d550f91 100644 --- a/devices/pckbd.c +++ b/devices/pckbd.c @@ -1,6 +1,5 @@ #include "keyboard.h" #include "ps2_controller.h" -#include "vga.h" #include <stdint.h> #include <stdio.h> #include <sys/io.h> @@ -42,7 +41,7 @@ ps2_keyboard_irq_handler() return; case 0x58: // F12 - vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); + // vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); return; } diff --git a/devices/uart.h b/devices/uart.h deleted file mode 100644 index ee74e98..0000000 --- a/devices/uart.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -// TODO #include <arch/platform.h> -#include <stdio.h> - -enum UART { - COM1 = 0x3f8, - COM2 = 0x2f8, - COM3 = 0x3E8, - COM4 = 0x2E8, - COM5 = 0x5F8, - COM6 = 0x4F8, - COM7 = 0x5E8, - COM8 = 0x4E8, -}; - -FILE *uart_init(enum UART port); diff --git a/devices/uart.hpp b/devices/uart.hpp new file mode 100644 index 0000000..c86557c --- /dev/null +++ b/devices/uart.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include <stdio.h> +#include <sys/io.h> + +template <UART port> FILE *uart_init(); +template <> FILE *uart_init<COM1>(); diff --git a/devices/uart_16550.c b/devices/uart_16550.c deleted file mode 100644 index 1adcf38..0000000 --- a/devices/uart_16550.c +++ /dev/null @@ -1,117 +0,0 @@ -#include "uart.h" -#include <stddef.h> -#include <sys/io.h> - -enum uart_16550_offset { - Data = 0, // read from receive buffer / write to transmit buffer | BaudDiv_l - InterruptControl = 1, // interrupt enable | BaudDiv_h - FifoControl = 2, // interrupt ID and FIFO control - LineControl = 3, // most significant bit is the DLAB - ModemControl = 4, - LineStatus = 5, - ModemStatus = 6, - Scratch = 7, -}; -// Line Control -// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | -// |dla| | parity | s | data | - -enum LineControl { - d5bit = 0x00, // 0000 0000 data bits - d6bit = 0x01, // 0000 0001 - d7bit = 0x02, // 0000 0010 - d8bit = 0x03, // 0000 0011 - // none = 0b00000000, // parity bits - odd = 0x08, // 0000 1000 - even = 0x18, // 0001 1000 - mark = 0x28, // 0010 1000 - space = 0x38, // 0011 1000 - // s1bit = 0b00000000, // stop bits - s2bit = 0x04, // 0000 0100 1.5 for 5bit data; 2 otherwise - dlab = 0x80 // 1000 0000 divisor latch access bit -}; - -// Line Status Register -enum LineStatus { - DR = (1 << 0), // data ready: see if there is data to read - OE = (1 << 1), // overrun error: see if there has been data lost - PE = (1 << 2), // parity error: see if there was error in transmission - FE = (1 << 3), // framing error: see if a stop bit was missing - BI = (1 << 4), // break indicator: see if there is a break in data input - THRE = (1 << 5), // transmitter holding register empty: see if transmission buffer is empty - TEMT = (1 << 6), // transmitter empty: see if transmitter is not doing anything - ERRO = (1 << 7), // impending error: see if there is an error with a word in the input buffer -}; - -int -uart_thre(enum UART port) -{ - return inb(port + LineStatus) & THRE; -} - -void -uart_write(const FILE *self, char a) -{ - while (uart_thre(self->id) == 0) {} - outb(a, self->id); - - if (a == '\n') { - while (uart_thre(self->id) == 0) {} - outb('\r', self->id); - } -} - -int -uart_puts(const FILE *self, const char *string, int length) -{ - int written = 0; - - if (length == -1) - while (*string != '\0') { - uart_write(self, *string); - ++string; - ++written; - } - - else - for (int i = 0; i < length; ++i) { - uart_write(self, string[i]); - ++written; - } - - return written; -} - -void -uart_flush(__attribute__((unused)) const FILE *self) -{ -} - -FILE uart_stream; - -FILE * -uart_init(enum UART port) -{ - outb(0x00, port + 1); // Disable all interrupts - outb(0x80, port + 3); // Enable DLAB (set baud rate divisor) - outb(0x03, port + 0); // Set divisor to 3 (lo byte) 38400 baud - outb(0x00, port + 1); // (hi byte) - outb(0x03, port + 3); // 8 bits, no parity, one stop bit - outb(0xc7, port + 2); // Enable FIFO, clear them, with 14-byte threshold - outb(0x0b, port + 4); // IRQs enabled, RTS/DSR set - outb(0x1e, port + 4); // Set in loopback mode, test the serial chip - outb(0xae, port + 0); // Test serial chip (send byte 0xAE and check if serial - // returns same byte) - - // Check if serial is faulty (i.e: not same byte as sent) - if (inb(port + 0) != 0xae) { return NULL; } - - // If serial is not faulty set it in normal operation mode - // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) - outb(0x0f, port + 4); - uart_stream.id = port; - uart_stream.putc = &uart_write; - uart_stream.puts = &uart_puts; - uart_stream.flush = &uart_flush; - return &uart_stream; -} diff --git a/devices/uart_16550.cpp b/devices/uart_16550.cpp new file mode 100644 index 0000000..9620981 --- /dev/null +++ b/devices/uart_16550.cpp @@ -0,0 +1,110 @@ +#include "uart.hpp" +#include <sys/io.hpp> + +template <UART port> struct Uart16550 : public kIoDevice, private Port<unsigned short, port> { + using Base = Port<unsigned short, port>; + using Ports = UART; + using PortOffset = UARTPortOffset; + + // Line Control + // | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + // |dla| | parity | s | data | + enum LineControl : unsigned char { + d5bit = 0x00, // 0000 0000 data bits + d6bit = 0x01, // 0000 0001 + d7bit = 0x02, // 0000 0010 + d8bit = 0x03, // 0000 0011 + none = 0x00, // 0000 0000 parity bits + odd = 0x08, // 0000 1000 + even = 0x18, // 0001 1000 + mark = 0x28, // 0010 1000 + space = 0x38, // 0011 1000 + s1bit = 0x00, // 0000 0000 stop bits + s2bit = 0x04, // 0000 0100 1.5 for 5bit data; 2 otherwise + dlab = 0x80 // 1000 0000 divisor latch access bit + }; + + // Line Status Register + enum LineStatus : unsigned char { + DR = (1 << 0), // data ready: see if there is data to read + OE = (1 << 1), // overrun error: see if there has been data lost + PE = (1 << 2), // parity error: see if there was error in transmission + FE = (1 << 3), // framing error: see if a stop bit was missing + BI = (1 << 4), // break indicator: see if there is a break in data input + THRE = (1 << 5), // transmitter holding register empty: see if transmission buffer is empty + TEMT = (1 << 6), // transmitter empty: see if transmitter is not doing anything + ERRO = (1 << 7), // impending error: see if there is an error with a word in the input buffer + }; + + [[nodiscard]] static bool + test() + { + Base::out(0x00, 1); // Disable all interrupts + Base::out(0x80, 3); // Enable DLAB (set baud rate divisor) + Base::out(0x03, 0); // Set divisor to 3 (lo byte) 38400 baud + Base::out(0x00, 1); // (hi byte) + Base::out(0x03, 3); // 8 bits, no parity, one stop bit + Base::out(0xc7, 2); // Enable FIFO, clear them, with 14-byte threshold + Base::out(0x0b, 4); // IRQs enabled, RTS/DSR set + Base::out(0x1e, 4); // Set in loopback mode, test the serial chip + Base::out(0xae, 0); // Test serial chip (send byte 0xAE and check if serial + // returns same byte) + + // Check if serial is faulty (i.e: not same byte as sent) + if (Base::in() != 0xae) { return false; } + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + Base::out(0x0f, 4); + return true; + } + + [[nodiscard]] static bool + thre() + { + return Base::in(PortOffset::LineStatus)&THRE; + } + + void + putc(char a) override + { + while (!thre()) {} + Base::out(a); + if (a == '\n') putc('\r'); + } + + int + puts(const char *string, int length) override + { + int written = 0; + + if (length == -1) + while (*string != '\0') { + putc(*string); + ++string; + ++written; + } + + else { + for (int i = 0; i < length; ++i) putc(string[i]); + written += length; + } + + return written; + } + + void + flush() override + { + } +}; + +static_assert(sizeof(Uart16550<COM1>) == sizeof(void *)); + +template <> +FILE * +uart_init<COM1>() +{ + static Uart16550<COM1> device; + return &device; +} diff --git a/devices/vga.c b/devices/vga.cpp index 6d64c0a..3f83a5f 100644 --- a/devices/vga.c +++ b/devices/vga.cpp @@ -1,31 +1,26 @@ -#include "vga.h" +#include "vga.hpp" #include <stdint.h> #include <sys/io.h> +// FIXME user a Port #define cga_idx_port 0x3d4 #define cga_dat_port 0x3d5 +// FIXME make constexpr #define cursor_start 0x0a #define cursor_end 0x0b #define cursor_addr_h 0x0e #define cursor_addr_l 0x0f #define cursor_hide 0x20 -struct __attribute__((packed)) VGAEntry { - unsigned char text; - uint8_t foreground : 4; - uint8_t background : 4; -}; -_Static_assert(sizeof(struct VGAEntry) == 2, "sizeof VGAEntry"); +static_assert(sizeof(struct VGA::VGAEntry) == 2, "sizeof VGAEntry"); +// FIXME make constexpr const int width = 80; const int height = 25; -struct VGAEntry *buffer; -int col = 0; -int row = 0; - // *** Cursor *** +// FIXME make VGA members void vga_enable_cursor(unsigned char start, unsigned char end) { @@ -44,7 +39,7 @@ vga_disable_cursor() } void -vga_update_cursor() +VGA::update_cursor() { const uint16_t pos = row * width + col; @@ -57,7 +52,7 @@ vga_update_cursor() // *** Text Mode Output *** void -vga_putc(__attribute__((unused)) const FILE *self, char a) +VGA::putc(char a) { switch (a) { case '\n': @@ -96,49 +91,40 @@ vga_putc(__attribute__((unused)) const FILE *self, char a) } int -vga_puts(const FILE *self, const char *string, int len) +VGA::puts(const char *string, int len) { int written = 0; if (len == -1) while (*string != '\0') { - vga_putc(self, *string); + putc(*string); ++string; ++written; } else for (int i = 0; i < len; ++i) { - vga_putc(self, string[i]); + putc(string[i]); ++written; } return written; } -void -vga_flush(__attribute__((unused)) const FILE *self) +// *** Text Mode *** +VGA::VGA(void *addr) { - vga_update_cursor(); + buffer = (struct VGAEntry *)addr; + vga_enable_cursor(14, 15); + clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); } - -// *** Text Mode *** -FILE vga_stream; - FILE * -vga_init() +vga_init(void *buffer) { - buffer = (struct VGAEntry *)0xc03ff000; - vga_enable_cursor(14, 15); - vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); - - vga_stream.id = 0; - vga_stream.putc = &vga_putc; - vga_stream.puts = &vga_puts; - vga_stream.flush = &vga_flush; - return &vga_stream; + static VGA device(buffer); + return &device; } void -vga_clear(enum vga_color foreground, enum vga_color background) +VGA::clear(enum vga_color foreground, enum vga_color background) { for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) { @@ -148,5 +134,5 @@ vga_clear(enum vga_color foreground, enum vga_color background) buffer[index].background = background; } col = row = 0; - vga_update_cursor(); + update_cursor(); } diff --git a/devices/vga.h b/devices/vga.h deleted file mode 100644 index d9dfd44..0000000 --- a/devices/vga.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include <stdio.h> - -/** Hardware text mode color constants. */ -enum vga_color { - VGA_COLOR_BLACK = 0, - VGA_COLOR_BLUE = 1, - VGA_COLOR_GREEN = 2, - VGA_COLOR_CYAN = 3, - VGA_COLOR_RED = 4, - VGA_COLOR_MAGENTA = 5, - VGA_COLOR_BROWN = 6, - VGA_COLOR_LIGHT_GREY = 7, - VGA_COLOR_DARK_GREY = 8, - VGA_COLOR_LIGHT_BLUE = 9, - VGA_COLOR_LIGHT_GREEN = 10, - VGA_COLOR_LIGHT_CYAN = 11, - VGA_COLOR_LIGHT_RED = 12, - VGA_COLOR_LIGHT_MAGENTA = 13, - VGA_COLOR_LIGHT_BROWN = 14, - VGA_COLOR_WHITE = 15, -}; - -FILE *vga_init(); -void vga_clear(enum vga_color foreground, enum vga_color background); - -// void vga_putc(char a); -// void vga_puts(const char *string, int len); - -// void vga_enable_cursor(unsigned char start, unsigned char end); -// void vga_disable_cursor(); -void vga_update_cursor(); diff --git a/devices/vga.hpp b/devices/vga.hpp new file mode 100644 index 0000000..5287d73 --- /dev/null +++ b/devices/vga.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include <stdio.h> + +/** Hardware text mode color constants. */ +enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; + +FILE *vga_init(void *buffer); + +struct VGA : public kIoDevice { + VGA(void *addr); + + void putc(char a) override; + int puts(const char *string, int length) override; + void + flush() override + { + update_cursor(); + } + + struct __attribute__((packed)) VGAEntry { + unsigned char text; + unsigned char foreground : 4; + unsigned char background : 4; + }; + +private: + void clear(enum vga_color foreground, enum vga_color background); + void update_cursor(); + + struct VGAEntry *buffer; + int col = 0; + int row = 0; +}; |