Basic serial driver
This commit is contained in:
parent
e9fd2e98bf
commit
c33a57fa33
4 changed files with 91 additions and 12 deletions
8
Makefile
8
Makefile
|
@ -8,16 +8,18 @@ kernel.o: kernel.c
|
|||
tcc -m32 -c kernel.c
|
||||
vga.o: vga.c
|
||||
tcc -m32 -c vga.c
|
||||
serial.o: serial.c
|
||||
tcc -m32 -c serial.c
|
||||
|
||||
kernel-i386.elf: kernel.o start32.o vga.o
|
||||
tcc -m32 -nostdlib -Wl,-Ttext,0x100000 start32.o kernel.o vga.o -o kernel-i386.elf
|
||||
kernel-i386.elf: kernel.o start32.o vga.o serial.o
|
||||
tcc -m32 -nostdlib -Wl,-Ttext,0x100000 start32.o kernel.o vga.o serial.o -o kernel-i386.elf
|
||||
|
||||
qemu-multiboot: kernel-i386.elf
|
||||
qemu-system-i386 -kernel kernel-i386.elf -serial stdio
|
||||
qemu-image: kernel-i386.elf mount
|
||||
cp kernel-i386.elf mnt/
|
||||
sync
|
||||
qemu-system-i386 koalemos.img -serial stdio
|
||||
qemu-system-i386 koalemos.img -serial stdio
|
||||
|
||||
mount: koalemos.img mnt/
|
||||
@if ! mountpoint -q "mnt/"; then \
|
||||
|
|
39
kernel.c
39
kernel.c
|
@ -1,9 +1,15 @@
|
|||
#include "multiboot.h"
|
||||
#include "vga.h"
|
||||
#include "serial.h"
|
||||
|
||||
static inline void outb(unsigned short port, unsigned char val) {
|
||||
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
||||
}
|
||||
static inline unsigned char inb(unsigned short port) {
|
||||
unsigned char ret;
|
||||
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* itoa(int value, int base) {
|
||||
char* result;
|
||||
|
@ -41,6 +47,14 @@ void kmain (unsigned int mbootmagick, multiboot_info_t* mbootinfo) {
|
|||
vga_init(VGA_COLOR_BLACK, VGA_COLOR_GRAY);
|
||||
|
||||
vga_write_line("=== KoalemOS ===");
|
||||
|
||||
if (serial_init() > 0) {
|
||||
vga_write_line_color("Serial initialization failed", VGA_COLOR_BLACK,
|
||||
VGA_COLOR_ORANGE);
|
||||
} else {
|
||||
vga_write_line("\nInitialized serial.");
|
||||
serial_write_string("\n=== KoalemOS ===\n");
|
||||
}
|
||||
vga_write("Checking multiboot loader: ");
|
||||
|
||||
// Check multiboot header
|
||||
|
@ -56,23 +70,30 @@ void kmain (unsigned int mbootmagick, multiboot_info_t* mbootinfo) {
|
|||
vga_write("\nMultiboot flags: ");
|
||||
vga_write(itoa(mbootinfo->flags, 2));
|
||||
|
||||
// Check videomode
|
||||
vga_write("\nVideomode: ");
|
||||
serial_write_string("\nMultiboot flags: ");
|
||||
serial_write_string(itoa(mbootinfo->flags, 2));
|
||||
|
||||
// Check videomode
|
||||
if (mbootinfo->flags & MULTIBOOT_INFO_VBE_INFO) {
|
||||
vga_write("VBE 0x");
|
||||
vga_write("\nVBE Mode: 0x");
|
||||
vga_write(itoa(mbootinfo->vbe_mode, 16));
|
||||
} else if (mbootinfo->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) {
|
||||
vga_write("Framebuffer");
|
||||
vga_write("\nVideo address: 0x");
|
||||
serial_write_string("\nVBE Mode: 0x");
|
||||
serial_write_string(itoa(mbootinfo->vbe_mode, 16));
|
||||
}
|
||||
if (mbootinfo->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) {
|
||||
vga_write("\nFramebuffer: ");
|
||||
vga_write("address: 0x");
|
||||
vga_write(itoa(mbootinfo->framebuffer_addr, 16));
|
||||
unsigned long long *vmem = &mbootinfo->framebuffer_addr;
|
||||
serial_write_string("\nFramebuffer: ");
|
||||
serial_write_string("address: 0x");
|
||||
serial_write_string(itoa(mbootinfo->framebuffer_addr, 16));
|
||||
unsigned long *vmem = &mbootinfo->framebuffer_addr;
|
||||
*vmem = 0xff00ff;
|
||||
|
||||
} else {
|
||||
vga_write_color("Not available", VGA_COLOR_BLACK, VGA_COLOR_RED);
|
||||
vga_write_color("Info not available", VGA_COLOR_BLACK, VGA_COLOR_RED);
|
||||
serial_write_string("Info not available");
|
||||
return;
|
||||
}
|
||||
|
||||
vga_write_line("\nExecution finished, halting...");
|
||||
}
|
||||
|
|
49
serial.c
Normal file
49
serial.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "serial.h"
|
||||
#define PORT 0x3f8 // COM1
|
||||
|
||||
static inline void outb(unsigned short port, unsigned char val) {
|
||||
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
||||
}
|
||||
static inline unsigned char inb(unsigned short port) {
|
||||
unsigned char ret;
|
||||
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int serial_init() {
|
||||
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 (lo byte) 38400 baud
|
||||
outb(PORT + 1, 0x00); // (hi 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 serial
|
||||
// returns same byte)
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if (inb(PORT + 0) != 0xAE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 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(PORT + 4, 0x0F);
|
||||
return 0;
|
||||
}
|
||||
static int serial_is_transmit_empty() { return inb(PORT + 5) & 0x20; }
|
||||
|
||||
static void serial_write_char(char chr) {
|
||||
while (serial_is_transmit_empty() == 0);
|
||||
outb(PORT, chr);
|
||||
}
|
||||
|
||||
void serial_write_string(const char* text) {
|
||||
int i = 0;
|
||||
while(text[i]) {
|
||||
serial_write_char(text[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
7
serial.h
Normal file
7
serial.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef HEADER_SERIAL
|
||||
#define HEADER_SERIAL
|
||||
|
||||
int serial_init(void);
|
||||
void serial_write_string(const char* text);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue