#include "headers/common.h" #include "headers/screen.h" // for conversion functions(maybye put in seperate header) #include #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 }