From 496c8a5ee5042fb608a4fee3f8088873cc0daf71 Mon Sep 17 00:00:00 2001 From: garritfra Date: Sun, 17 Mar 2019 16:00:42 +0100 Subject: [PATCH] Add serial port controll --- Makefile | 2 +- bochsrc.txt | 3 ++- fb.c | 2 +- fb.h | 4 +++- io.h | 2 +- io.s | 12 ++++++++++- kmain.c | 2 +- serial.c | 32 +++++++++++++++++++++++++++ serial.h | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 serial.c create mode 100644 serial.h diff --git a/Makefile b/Makefile index 6b1d29b..77d371a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -OBJECTS = io.o loader.o kmain.o fb.o +OBJECTS = io.o loader.o kmain.o fb.o serial.o CC = gcc CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \ -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c diff --git a/bochsrc.txt b/bochsrc.txt index ad72300..c0f28c0 100644 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -6,4 +6,5 @@ ata0-master: type=cdrom, path=os.iso, status=inserted boot: cdrom log: bochslog.txt clock: sync=realtime, time0=local -cpu: count=1, ips=1000000 \ No newline at end of file +cpu: count=1, ips=1000000 +com1: enabled=1, mode=file, dev=com1.out \ No newline at end of file diff --git a/fb.c b/fb.c index cb6437d..aa3635d 100644 --- a/fb.c +++ b/fb.c @@ -15,7 +15,7 @@ void fb_move_cursor(unsigned short pos) outb(FB_DATA_PORT, pos & 0x00FF); } -int write(char *buf, unsigned int len) { +int fb_write(char *buf, unsigned int len) { for(int i = 0; i <= (int)len; i++) { fb_write_cell((int)(i * 2), buf[i], 0, 15); fb_move_cursor(i); diff --git a/fb.h b/fb.h index bcde8b8..0e34978 100644 --- a/fb.h +++ b/fb.h @@ -9,7 +9,9 @@ #define FB_HIGH_BYTE_COMMAND 14 #define FB_LOW_BYTE_COMMAND 15 -int write(char *buf, unsigned int len); +#include "io.h" + +int fb_write(char *buf, unsigned int len); diff --git a/io.h b/io.h index 9f20745..8d211b4 100644 --- a/io.h +++ b/io.h @@ -15,6 +15,6 @@ extern void outb(unsigned short port, unsigned char data); * @param port The address of the I/O port * @return The read byte */ -unsigned char inb(unsigned short port); +extern unsigned char inb(unsigned short port); #endif \ No newline at end of file diff --git a/io.s b/io.s index 30f6c0d..0f967a7 100644 --- a/io.s +++ b/io.s @@ -1,4 +1,5 @@ global outb ; make the label outb visible outside this file +global inb ; outb - send a byte to an I/O port ; stack: [esp + 8] the data byte @@ -8,4 +9,13 @@ outb: mov al, [esp + 8] ; move the data to be sent into the al register mov dx, [esp + 4] ; move the address of the I/O port into the dx register out dx, al ; send the data to the I/O port - ret ; return to the calling function \ No newline at end of file + ret ; return to the calling function + + +; inb - returns a byte from the given I/O port +; stack: [esp + 4] The address of the I/O port +; [esp ] The return address +inb: + mov dx, [esp + 4] ; move the address of the I/O port to the dx register + in al, dx ; read a byte from the I/O port and store it in the al register + ret ; return the read byte \ No newline at end of file diff --git a/kmain.c b/kmain.c index 2418a47..5638d6e 100644 --- a/kmain.c +++ b/kmain.c @@ -3,6 +3,6 @@ int main() { - write("Hello", 4); + fb_write("Hello", 4); return 0; } \ No newline at end of file diff --git a/serial.c b/serial.c new file mode 100644 index 0000000..8c4b774 --- /dev/null +++ b/serial.c @@ -0,0 +1,32 @@ +#include "serial.h" +/** serial_configure_line: + * Configures the line of the given serial port. The port is set to have a + * data length of 8 bits, no parity bits, one stop bit and break control + * disabled. + * + * @param com The serial port to configure + */ +void serial_configure_line(unsigned short com) +{ + /* Bit: | 7 | 6 | 5 4 3 | 2 | 1 0 | + * Content: | d | b | prty | s | dl | + * Value: | 0 | 0 | 0 0 0 | 0 | 1 1 | = 0x03 + */ + outb(SERIAL_LINE_COMMAND_PORT(com), 0x03); +} + +void serial_configure_baud_rate(unsigned short com, unsigned short divisor) +{ + outb(SERIAL_LINE_COMMAND_PORT(com), + SERIAL_LINE_ENABLE_DLAB); + outb(SERIAL_DATA_PORT(com), + (divisor >> 8) & 0x00FF); + outb(SERIAL_DATA_PORT(com), + divisor & 0x00FF); +} + +int serial_is_transmit_fifo_empty(unsigned int com) +{ + /* 0x20 = 0010 0000 */ + return inb(SERIAL_LINE_STATUS_PORT(com)) & 0x20; +} \ No newline at end of file diff --git a/serial.h b/serial.h new file mode 100644 index 0000000..87c137a --- /dev/null +++ b/serial.h @@ -0,0 +1,62 @@ +#ifndef INCLUDE_SERIAL +#define INCLUDE_SERIAL + +#include "io.h" + +/* The I/O ports */ + +/* All the I/O ports are calculated relative to the data port. This is because + * all serial ports (COM1, COM2, COM3, COM4) have their ports in the same + * order, but they start at different values. + */ + +#define SERIAL_COM1_BASE 0x3F8 /* COM1 base port */ + +#define SERIAL_DATA_PORT(base) (base) +#define SERIAL_FIFO_COMMAND_PORT(base) (base + 2) +#define SERIAL_LINE_COMMAND_PORT(base) (base + 3) +#define SERIAL_MODEM_COMMAND_PORT(base) (base + 4) +#define SERIAL_LINE_STATUS_PORT(base) (base + 5) + +/* The I/O port commands */ + +/* SERIAL_LINE_ENABLE_DLAB: + * Tells the serial port to expect first the highest 8 bits on the data port, + * then the lowest 8 bits will follow + */ +#define SERIAL_LINE_ENABLE_DLAB 0x80 + +/** serial_configure_baud_rate: + * Sets the speed of the data being sent. The default speed of a serial + * port is 115200 bits/s. The argument is a divisor of that number, hence + * the resulting speed becomes (115200 / divisor) bits/s. + * + * @param com The COM port to configure + * @param divisor The divisor + */ +void serial_configure_baud_rate(unsigned short com, unsigned short divisor); + + +/** serial_configure_line: + * Configures the line of the given serial port. The port is set to have a + * data length of 8 bits, no parity bits, one stop bit and break control + * disabled. + * + * @param com The serial port to configure + */ +void serial_configure_line(unsigned short com); + + +/** serial_is_transmit_fifo_empty: + * Checks whether the transmit FIFO queue is empty or not for the given COM + * port. + * + * @param com The COM port + * @return 0 if the transmit FIFO queue is not empty + * 1 if the transmit FIFO queue is empty + */ +int serial_is_transmit_fifo_empty(unsigned int com); + + + +#endif \ No newline at end of file