172 lines
4.2 KiB
C
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
|
|
}
|