diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-09-25 16:38:31 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-09-25 16:38:31 -0700 |
commit | 223f5298620a3b3be9fbd206e2a3fbb388487da0 (patch) | |
tree | 286635488927e801c646d80e21d6a194261ed75b /memdump/serial.c | |
parent | 57556d8f612128679464667ce124ddc611795db2 (diff) | |
parent | a81fb89a445ae0dca286c861d8d51f705533df0d (diff) | |
download | syslinux-3.60-pre2.tar.gz |
Merge commit 'syslinux-3.52' into gpxe-supportsyslinux-3.60-pre2
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); + } +} |