aboutsummaryrefslogtreecommitdiff
path: root/devices
diff options
context:
space:
mode:
authoraqua <aqua@iserlohn-fortress.net>2022-12-10 20:56:57 +0200
committeraqua <aqua@iserlohn-fortress.net>2022-12-11 11:32:51 +0200
commit9b2a78fa52249ab481493550490aa5f37872dcf6 (patch)
tree127031268b9b42b0fbdae3d87684d9c045983677 /devices
parentRename CCFLAGS to CFLAGS (diff)
downloadkernel-9b2a78fa52249ab481493550490aa5f37872dcf6.tar.xz
Rewrite drivers/uart and drivers/vga in cpp
Diffstat (limited to 'devices')
-rw-r--r--devices/Makefile2
-rw-r--r--devices/pckbd.c3
-rw-r--r--devices/uart.h17
-rw-r--r--devices/uart.hpp7
-rw-r--r--devices/uart_16550.c117
-rw-r--r--devices/uart_16550.cpp110
-rw-r--r--devices/vga.cpp (renamed from devices/vga.c)56
-rw-r--r--devices/vga.h33
-rw-r--r--devices/vga.hpp51
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;
+};