aboutsummaryrefslogtreecommitdiffstats
path: root/com32/sysdump/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'com32/sysdump/serial.c')
-rw-r--r--com32/sysdump/serial.c63
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 */
+}
+
+