diff options
author | H. Peter Anvin <hpa@zytor.com> | 2010-02-06 21:55:03 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-02-06 21:55:03 -0800 |
commit | 22c6d03bba83a3c68971e1927628ede12a3b618c (patch) | |
tree | 99e73a5c2d9ffd5a5f91674d1fb7542aafc9a81b /com32/sysdump/serial.c | |
parent | f6fb77dbc062f0fbc1672f37dc1560cdbc08083d (diff) | |
download | syslinux-22c6d03bba83a3c68971e1927628ede12a3b618c.tar.gz syslinux-22c6d03bba83a3c68971e1927628ede12a3b618c.tar.xz syslinux-22c6d03bba83a3c68971e1927628ede12a3b618c.zip |
sysdump: add back ymodem support; clean up memory dump structure
Now we just need more front ends (information providers)...
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'com32/sysdump/serial.c')
-rw-r--r-- | com32/sysdump/serial.c | 63 |
1 files changed, 53 insertions, 10 deletions
diff --git a/com32/sysdump/serial.c b/com32/sysdump/serial.c index 75bbd481..803b05fb 100644 --- a/com32/sysdump/serial.c +++ b/com32/sysdump/serial.c @@ -2,7 +2,7 @@ #include <stdio.h> #include <sys/io.h> -#include "file.h" +#include "serial.h" enum { THR = 0, @@ -19,33 +19,57 @@ enum { SCR = 7, }; -int serial_init(struct serial_if *sif) + +int serial_init(struct serial_if *sif, const char *argv[]) { - uint16_t port = sif->port; + uint16_t port; + unsigned int speed, divisor; uint8_t dll, dlm, lcr; + port = strtoul(argv[0], NULL, 0); + if (port <= 3) + port = *(uint16_t *)(0x400 + port*2); + + if (argv[1]) + speed = strtoul(argv[1], NULL, 0); + else + speed = 115200; + + divisor = 115200/speed; + + /* Save old register settings */ + sif->old.lcr = inb(port + LCR); + sif->old.mcr = inb(port + MCR); + sif->old.iir = inb(port + IIR); + /* Set 115200n81 */ - outb(0x83, port + LCR); - outb(0x01, port + DLL); - outb(0x00, port + DLM); + outb(0x83, port + LCR); /* Enable divisor access */ + sif->old.dll = inb(port + DLL); + sif->old.dlm = inb(port + DLM); + outb(divisor, port + DLL); + outb(divisor >> 8, 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 */ + sif->old.ier = inb(port + IER); - if (dll != 0x01 || dlm != 0x00 || lcr != 0x83) + if (dll != (uint8_t)divisor || + dlm != (uint8_t)(divisor >> 8) || + lcr != 0x83) return -1; /* This doesn't look like a serial port */ /* Disable interrupts */ - outb(port + IER, 0); + outb(0, port + IER); /* Enable 16550A FIFOs if available */ - outb(port + FCR, 0x01); /* Enable FIFO */ + outb(0x41, port + FCR); /* Enable FIFO */ (void)inb(port + IER); /* Synchronize */ if (inb(port + IIR) < 0xc0) - outb(port + FCR, 0x00); /* Disable FIFOs if non-functional */ + outb(0x00, port + FCR); /* Disable FIFOs if non-functional */ (void)inb(port + IER); /* Synchronize */ return 0; @@ -80,3 +104,22 @@ void serial_read(struct serial_if *sif, void *data, size_t n) *p++ = inb(port + RBR); } } + +void serial_cleanup(struct serial_if *sif) +{ + uint16_t port = sif->port; + + outb(0x83, port + LCR); + (void)inb(port + IER); + outb(sif->old.dll, port + DLL); + outb(sif->old.dlm, port + DLM); + (void)inb(port + IER); + outb(sif->old.lcr & 0x7f, port + LCR); + (void)inb(port + IER); + outb(sif->old.mcr, port + MCR); + outb(sif->old.ier, port + IER); + if ((sif->old.iir & 0xc0) != 0xc0) + outb(0x00, port + FCR); /* Disable FIFOs */ +} + + |