#include <pexpert/protos.h>
#include <pexpert/pexpert.h>
enum {
COM1_PORT_ADDR = 0x3f8,
COM2_PORT_ADDR = 0x2f8
};
enum {
UART_RBR = 0,
UART_THR = 0,
UART_DLL = 0,
UART_IER = 1,
UART_DLM = 1,
UART_IIR = 2,
UART_FCR = 2,
UART_LCR = 3,
UART_MCR = 4,
UART_LSR = 5,
UART_MSR = 6
};
enum {
UART_LCR_8BITS = 0x03,
UART_LCR_DLAB = 0x80
};
enum {
UART_MCR_DTR = 0x01,
UART_MCR_RTS = 0x02,
UART_MCR_OUT1 = 0x04,
UART_MCR_OUT2 = 0x08,
UART_MCR_LOOP = 0x10
};
enum {
UART_LSR_THRE = 0x20
};
#define UART_BAUD_RATE 115200
#define UART_PORT_ADDR COM1_PORT_ADDR
#define WRITE(r, v) outb(UART_PORT_ADDR + UART_##r, v)
#define READ(r) inb(UART_PORT_ADDR + UART_##r)
#define DELAY(x) { volatile int _d_; for (_d_ = 0; _d_ < (10000*x); _d_++) ; }
static int uart_initted = 0;
static int
uart_probe( void )
{
WRITE( LCR, UART_LCR_DLAB );
WRITE( DLL, 0x5a );
if (READ(DLL) != 0x5a) return 0;
WRITE( DLL, 0xa5 );
if (READ(DLL) != 0xa5) return 0;
WRITE( LCR, 0x00 );
return 1;
}
static void
uart_set_baud_rate( unsigned long baud_rate )
{
#define UART_CLOCK 1843200
const unsigned char lcr = READ( LCR );
unsigned long div;
if (baud_rate == 0) baud_rate = 9600;
div = UART_CLOCK / 16 / baud_rate;
WRITE( LCR, lcr | UART_LCR_DLAB );
WRITE( DLM, (unsigned char)(div >> 8) );
WRITE( DLL, (unsigned char) div );
WRITE( LCR, lcr & ~UART_LCR_DLAB);
}
static void
uart_putc( char c )
{
if (!uart_initted) return;
while ( !(READ(LSR) & UART_LSR_THRE) ) DELAY(1);
WRITE( THR, c );
}
int serial_init( void )
{
if ( uart_initted || uart_probe() == 0 ) return 0;
WRITE( MCR, 0 );
WRITE( IER, 0 );
WRITE( FCR, 0 );
WRITE( LCR, UART_LCR_8BITS );
uart_set_baud_rate( UART_BAUD_RATE );
WRITE( MCR, UART_MCR_DTR | UART_MCR_RTS );
READ( RBR );
uart_initted = 1;
return 1;
}
void serial_putc( char c )
{
uart_putc(c);
if (c == '\n') uart_putc('\r');
}
int serial_getc( void )
{
return 0;
}