#include #include #include "serial.h" #include "util.h" enum { CP_DATA = 0x0, CP_INT = 0x1, CP_FIFO = 0x2, CP_LINE = 0x3, CP_MODEM = 0x4, CP_LINE_S = 0x5, CP_MODEM_S = 0x6, CP_DIVLOW = 0x0, CP_DIVHIGH = 0x1, CP_1 = 0x03f8, CP_2 = 0x02f8, CP_3 = 0x03e8, CP_4 = 0x02e8 }; enum { CL_BAUD = 0x80, CL_PODD = 0x08, CL_PEVEN = 0x0c, CL_PON = 0x18, CL_POFF = 0x1c, CL_LSTOP = 0x4, CL_5BIT = 0x0, CL_6BIT = 0x1, CL_7BIT = 0x2, CL_8BIT = 0x3 }; enum { CLS_B_ERR = 0x80, CLS_IDLE = 0x40, CLS_WRITE = 0x20, CLS_BREAK = 0x10, CLS_FRAME = 0x08, CLS_PAR = 0x04, CLS_OVER = 0x02, CLS_READ = 0x01 }; static const uint16_t ports[] = { CP_1, CP_2, CP_3, CP_4 }; static bool error[4]; void reset_error(enum serial_port n) { error[n] = false; } void init_serial() { for (enum serial_port i = COM1; i <= COM4; ++i) { error[i] = false; outb(ports[i] | CP_INT, 0); outb(ports[i] | CP_LINE, CL_BAUD); outb(ports[i] | CP_DIVLOW, 0x03);//38400 outb(ports[i] | CP_DIVHIGH, 0x00);//baud outb(ports[i] | CP_LINE, CL_8BIT); outb(ports[i] | CP_FIFO, 0xc7);//? } } typedef uint16_t serial_spin_t; void sout(enum serial_port n, uint8_t b) { if (error[n]) return; serial_spin_t spinner = -1; while (!(inb(ports[n] | CP_LINE_S) & CLS_WRITE)) if (--spinner) { error[n] = true; return; } outb(ports[n] | CP_DATA, b); } uint8_t sin(enum serial_port n) { if (error[n]) return 0; while (!(inb(ports[n] | CP_LINE_S) & CLS_READ)) ;//spin return inb(ports[n] | CP_DATA); }