This repository has been archived on 2020-02-06. You can view files and clone it, but cannot push or open issues or pull requests.
Legacy-Sync/serial.c
Jenny Curle f6ba6aa117 Legacy OS files. Have an i686-elf-gcc & -ld in your PATH,
and the Makefile will take care of the rest.
2019-04-01 01:38:50 +01:00

172 lines
4.2 KiB
C

#include "headers/common.h"
#include "headers/screen.h" // for conversion functions(maybye put in seperate header)
#include <stdarg.h>
#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)
#define SERIAL_COM1_BASE 0x3F8 // com1 base port
// SERIAL_LINE_ENABLE_DLAB:
// tells the serial port to expect high byte first
// then the low order byte follows
#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)
{
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);
}
// configures line of a serial port
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);
}
// Bit: | 7 6 | 5 | 4 | 3 | 2 | 1 | 0 |
// Content: | lvl | bs | r | dma | clt | clr | e |
// 0xc7
/*
*Enables FIFO
*Clear both receiver and transmission FIFO queues
*Use 14 bytes as size of queue
*/
void serial_configure_buffers(unsigned short com)
{
outb(SERIAL_FIFO_COMMAND_PORT(com), 0xc7);
}
// configure the modem of our serial port
// Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
// Content: | r | r | af | lb | ao2 | ao1 | rts | dtr |
void serial_configure_modem(unsigned short com)
{
outb(SERIAL_MODEM_COMMAND_PORT(com), 0x3);
}
/** 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_trasmit_fifo_empty(unsigned short com)
{
return inb(SERIAL_LINE_STATUS_PORT(com)) & 0x20;
}
void serial_write(unsigned short com, char data)
{
while(serial_is_trasmit_fifo_empty(com) == 0); // wait till write finished
outb(com, data);
}
void serial_print(char *string)
{
int j = 0;
while(string[j] != 0)
{
serial_write(0x3f8, string[j]);
j++;
}
}
void serial_printf(const char *format, ...) // printf style func for serial port
{
int j = 0;
int num; // number to hold our stuff :)
char string2[10] = {0}; // string for printing ints :)
/* list stuff :) */
va_list ap;
va_start(ap, format);
while(format[j] != 0)
{
if(format[j] == '%') // if a format specifier
{
if(format[j+1] == 'd')
{
num = va_arg(ap, int);
itoa(num, string2);
serial_print(string2);
zerostring(string2);
j += 2;
}
else if(format[j+1] == 'x')
{
num = va_arg(ap, int);
tohex(num, string2);
serial_print(string2);
zerostring(string2);
j += 2;
}
else if(format[j+1] == 's')
{
serial_print(va_arg(ap, char* ));
j += 2;
}
else // unknown format string
{
serial_print("[ERROR]attempted to parse unknown format string\n");
return; // prevent undefined behaviour
}
}
else // is a regular character
{
serial_write(0x3f8,format[j]);
j++;
}
}
va_end(ap); // clean up variable length list
}
// init our serial com1 port for debuggin purpoes(rest are general use functions for other ports)
#define PORT 0x3f8 /* COM1 */
void init_serial()
{
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
}