93 lines
1.6 KiB
C
93 lines
1.6 KiB
C
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#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);
|
|
}
|