diff options
Diffstat (limited to 'memdump/serial.c')
-rw-r--r-- | memdump/serial.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/memdump/serial.c b/memdump/serial.c new file mode 100644 index 00000000..902dcc3d --- /dev/null +++ b/memdump/serial.c @@ -0,0 +1,80 @@ +#include "mystuff.h" +#include "ymsend.h" +#include "io.h" + +enum { + THR = 0, + RBR = 0, + DLL = 0, + DLM = 1, + IER = 1, + IIR = 2, + FCR = 2, + LCR = 3, + MCR = 4, + LSR = 5, + MSR = 6, + SCR = 7, +}; + +int serial_init(struct serial_if *sif) +{ + uint16_t port = sif->port; + uint8_t dll, dlm, lcr; + + /* Set 115200n81 */ + outb(0x83, port+LCR); + outb(0x01, port+DLL); + outb(0x00, port+DLM); + (void)inb(port+IER); /* Synchronize */ + dll = inb(port+DLL); + dlm = inb(port+DLM); + lcr = inb(port+LCR); + outb(0x03, port+LCR); + (void)inb(port+IER); /* Synchronize */ + + if (dll != 0x01 || dlm != 0x00 || lcr != 0x83) + return -1; /* This doesn't look like a serial port */ + + /* Disable interrupts */ + outb(port+IER, 0); + + /* Enable 16550A FIFOs if available */ + outb(port+FCR, 0x01); /* Enable FIFO */ + (void)inb(port+IER); /* Synchronize */ + if (inb(port+IIR) < 0xc0) + outb(port+FCR, 0x00); /* Disable FIFOs if non-functional */ + (void)inb(port+IER); /* Synchronize */ + + return 0; +} + +void serial_write(struct serial_if *sif, const void *data, size_t n) +{ + uint16_t port = sif->port; + const char *p = data; + uint8_t lsr; + + while (n--) { + do { + lsr = inb(port+LSR); + } while (!(lsr & 0x20)); + + outb(*p++, port+THR); + } +} + +void serial_read(struct serial_if *sif, void *data, size_t n) +{ + uint16_t port = sif->port; + char *p = data; + uint8_t lsr; + + while (n--) { + do { + lsr = inb(port+LSR); + } while (!(lsr & 0x01)); + + *p++ = inb(port+RBR); + } +} |