Basic serial driver
This commit is contained in:
parent
e9fd2e98bf
commit
c33a57fa33
4 changed files with 91 additions and 12 deletions
6
Makefile
6
Makefile
|
@ -8,9 +8,11 @@ kernel.o: kernel.c
|
||||||
tcc -m32 -c kernel.c
|
tcc -m32 -c kernel.c
|
||||||
vga.o: vga.c
|
vga.o: vga.c
|
||||||
tcc -m32 -c 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
|
kernel-i386.elf: kernel.o start32.o vga.o serial.o
|
||||||
tcc -m32 -nostdlib -Wl,-Ttext,0x100000 start32.o kernel.o vga.o -o kernel-i386.elf
|
tcc -m32 -nostdlib -Wl,-Ttext,0x100000 start32.o kernel.o vga.o serial.o -o kernel-i386.elf
|
||||||
|
|
||||||
qemu-multiboot: kernel-i386.elf
|
qemu-multiboot: kernel-i386.elf
|
||||||
qemu-system-i386 -kernel kernel-i386.elf -serial stdio
|
qemu-system-i386 -kernel kernel-i386.elf -serial stdio
|
||||||
|
|
39
kernel.c
39
kernel.c
|
@ -1,9 +1,15 @@
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
static inline void outb(unsigned short port, unsigned char val) {
|
static inline void outb(unsigned short port, unsigned char val) {
|
||||||
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
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* itoa(int value, int base) {
|
||||||
char* result;
|
char* result;
|
||||||
|
@ -41,6 +47,14 @@ void kmain (unsigned int mbootmagick, multiboot_info_t* mbootinfo) {
|
||||||
vga_init(VGA_COLOR_BLACK, VGA_COLOR_GRAY);
|
vga_init(VGA_COLOR_BLACK, VGA_COLOR_GRAY);
|
||||||
|
|
||||||
vga_write_line("=== KoalemOS ===");
|
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: ");
|
vga_write("Checking multiboot loader: ");
|
||||||
|
|
||||||
// Check multiboot header
|
// Check multiboot header
|
||||||
|
@ -56,23 +70,30 @@ void kmain (unsigned int mbootmagick, multiboot_info_t* mbootinfo) {
|
||||||
vga_write("\nMultiboot flags: ");
|
vga_write("\nMultiboot flags: ");
|
||||||
vga_write(itoa(mbootinfo->flags, 2));
|
vga_write(itoa(mbootinfo->flags, 2));
|
||||||
|
|
||||||
// Check videomode
|
serial_write_string("\nMultiboot flags: ");
|
||||||
vga_write("\nVideomode: ");
|
serial_write_string(itoa(mbootinfo->flags, 2));
|
||||||
|
|
||||||
|
// Check videomode
|
||||||
if (mbootinfo->flags & MULTIBOOT_INFO_VBE_INFO) {
|
if (mbootinfo->flags & MULTIBOOT_INFO_VBE_INFO) {
|
||||||
vga_write("VBE 0x");
|
vga_write("\nVBE Mode: 0x");
|
||||||
vga_write(itoa(mbootinfo->vbe_mode, 16));
|
vga_write(itoa(mbootinfo->vbe_mode, 16));
|
||||||
} else if (mbootinfo->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) {
|
serial_write_string("\nVBE Mode: 0x");
|
||||||
vga_write("Framebuffer");
|
serial_write_string(itoa(mbootinfo->vbe_mode, 16));
|
||||||
vga_write("\nVideo address: 0x");
|
}
|
||||||
|
if (mbootinfo->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) {
|
||||||
|
vga_write("\nFramebuffer: ");
|
||||||
|
vga_write("address: 0x");
|
||||||
vga_write(itoa(mbootinfo->framebuffer_addr, 16));
|
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;
|
*vmem = 0xff00ff;
|
||||||
|
|
||||||
} else {
|
} 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vga_write_line("\nExecution finished, halting...");
|
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