diff options
Diffstat (limited to 'contrib/syslinux-4.02/memdump/serial.c')
-rw-r--r-- | contrib/syslinux-4.02/memdump/serial.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/memdump/serial.c b/contrib/syslinux-4.02/memdump/serial.c new file mode 100644 index 0000000..1c613d1 --- /dev/null +++ b/contrib/syslinux-4.02/memdump/serial.c @@ -0,0 +1,83 @@ +#include <stdbool.h> +#include <stdio.h> + +#include "mystuff.h" +#include "file.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); + } +} |