ref: e1bd16a9979b02d8e58d8d8d79654d7bacbcdb27
parent: bf6d794b8e8eb4bebd0bc8e692d5dec6265d285c
author: mkf <mkf@cloud9p.org>
date: Thu Nov 9 12:27:14 EST 2023
import³: oops
--- /dev/null
+++ b/pc/com.c
@@ -1,0 +1,74 @@
+#include <u.h>
+#include <libc.h>
+#include <x86.h>
+
+/* see https://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming
+ --- UART Registers
+Address DLAB I/O Access Register Name
++0 0 W Transmitter Holding Buffer
++0 0 R Receiver Buffer
++0 1 R/W Divisor Latch Low Byte
++1 0 R/W Interrupt Enable Register
++1 1 R/W Divisor Latch High Byte
++2 x R Interrupt Identification Register
++2 x W FIFO Control Register
++3 x R/W Line Control Register
++4 x R/W Modem Control Register
++5 x R Line Status Register
++6 x R Modem Status Register
++7 x R/W Scratch Register
+*/
+
+void
+com_init(uint16 port, uint32 baud_rate)
+{
+ uint16 divisor = 115200 / baud_rate;
+ outb(port + 2, 0); /* Turn off the FIFO */
+ outb(port + 3, 0x80); /* set the divisor latch access bit (7th bit)*/
+ outb(port + 0, divisor & 0xff);
+ outb(port + 1, divisor >> 8);
+ outb(port + 3, 0x3); /* lock the divisor and select 8 data bits */
+ outb(port + 4, 0x0);
+
+ /* testing */
+ outb(port + 4, 0x1e); /* set in loopback mode*/
+ outb(port + 0, 0xee); /* write some random data in it */
+ if (inb(port + 0) != 0xee) {
+ /* the serial is faulty */
+ /* TODO panic */
+ return;
+ }
+ /* the serial is working correctly, set in normal operation mode */
+ outb(port + 4, 0x0F);
+}
+
+void
+com_putchar(uint16 port, uint8 c)
+{
+ while(!(inb(port + 5) & 0x20))
+ {
+ ; /* wait for uart to be ready */
+ }
+ outb(port, c);
+}
+
+uint8
+com_getchar(uint16 port)
+{
+ while(!(inb(port + 5) & 1))
+ ; /* wait til data is ready */
+ return inb(port);
+}
+
+void
+com1_putchar(char c)
+{
+ com_putchar(COM1, c);
+}
+
+void
+com1_puts(char* s)
+{
+ for(int i = 0 ; i < strlen(s) ; i++)
+ com1_putchar(s[i]);
+}
\ No newline at end of file
--- /dev/null
+++ b/pc/kern.c
@@ -1,0 +1,17 @@
+#include <vga.h>
+#include <com.h>
+#include <ps2.h>
+
+/* abandon hope, all ye who enter here */
+void panic(void)
+{
+ vga_puts("panic: give up. it's over.\n");
+ com1_puts("panic: give up. it's over.\n");
+}
+
+void kernel_main(void)
+{
+ vga_init(WHITE, BLUE);
+ vga_puts("check out serial console");
+ com1_puts("check out VGA console");
+}
--- /dev/null
+++ b/pc/vga.c
@@ -1,0 +1,82 @@
+#include <u.h>
+#include <libc.h>
+#include <vga.h>
+
+static inline uint8
+vga_gencolor(int fg, int bg)
+{
+ return fg | bg << 4;
+}
+
+static inline uint16
+vga_char(unsigned char c, uint8 color)
+{
+ return (uint16) c | (uint16) color << 8;
+}
+
+void
+vga_clear(char c)
+{
+ for (size_t y = 0; y < VGA_HEIGHT; y++)
+ {
+ for (size_t x = 0; x < VGA_WIDTH; x++)
+ {
+ const size_t index = y * VGA_WIDTH + x;
+ vga_buf[index] = vga_char(c, vga_color);
+ }
+ }
+}
+
+void
+vga_init(int fg, int bg)
+{
+ vga_row = 0;
+ vga_col = 0;
+ vga_color = vga_gencolor(fg, bg);
+ vga_buf = (uint16*) 0xB8000;
+ vga_clear(' ');
+}
+
+void
+vga_writeto(char c, uint8 color, int x, int y)
+{
+ int index = y * VGA_WIDTH + x;
+ vga_buf[index] = vga_char(c, color);
+}
+
+
+void
+vga_nl(void)
+{
+ vga_col = 0; /* cr */
+ if(++vga_row == VGA_HEIGHT) /* lf */
+ vga_row = 0;
+
+}
+
+void
+vga_putc(char c)
+{
+ switch(c)
+ {
+ case '\n':
+ vga_nl();
+ return;
+ case '\t':
+ for(int i = 0 ; i < 4 ; i++)
+ vga_putc(' ');
+ return;
+ default:
+ vga_writeto(c, vga_color, vga_col, vga_row);
+ if(++vga_col == VGA_WIDTH)
+ vga_nl();
+ }
+}
+
+void
+vga_puts(char *s)
+{
+ int len = strlen(s);
+ for(int i = 0 ; i < len ; i++)
+ vga_putc(s[i]);
+}
--- /dev/null
+++ b/pc/x86.c
@@ -1,0 +1,28 @@
+#include <u.h>
+
+inline void
+instr(uint16 port, uint8* address, uint32 size)
+{
+ asm volatile("cld; rep insl" :
+ "=D" (address), "=c" (size) :
+ "d" (port), "0" (address), "1" (size) :
+ "memory", "cc");
+}
+
+inline void
+sti(void)
+{
+ asm volatile("sti");
+}
+
+inline void
+cli(void)
+{
+ asm volatile("cli");
+}
+
+inline void
+nop(void)
+{
+ asm volatile("nop");
+}
\ No newline at end of file