diff options
author | rsc <rsc> | 2009-05-31 00:24:11 +0000 |
---|---|---|
committer | rsc <rsc> | 2009-05-31 00:24:11 +0000 |
commit | 74afa70d3051553df46d1ea0d76149a7a86c0a47 (patch) | |
tree | 593b7b00869b161597d2d8b5af76ee09d4cc7c12 /uart.c | |
parent | 0ca9ca0c55922f72dbf324c4ac1aecf8069d1dbe (diff) | |
download | xv6-labs-74afa70d3051553df46d1ea0d76149a7a86c0a47.tar.gz xv6-labs-74afa70d3051553df46d1ea0d76149a7a86c0a47.tar.bz2 xv6-labs-74afa70d3051553df46d1ea0d76149a7a86c0a47.zip |
Add serial port input/output.
Delete parallel port output.
Works well with qemu -nographic mode.
Diffstat (limited to 'uart.c')
-rw-r--r-- | uart.c | 76 |
1 files changed, 76 insertions, 0 deletions
@@ -0,0 +1,76 @@ +// Intel 8250 serial port (UART). + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "traps.h" +#include "spinlock.h" +#include "dev.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" + +#define COM1 0x3f8 + +static int uart; // is there a uart? + +void +uartinit(void) +{ + char *p; + + // Turn off the FIFO + outb(COM1+2, 0); + + // 9600 baud, 8 data bits, 1 stop bit, parity off. + outb(COM1+3, 0x80); // Unlock divisor + outb(COM1+0, 115200/9600); + outb(COM1+1, 0); + outb(COM1+3, 0x03); // Lock divisor, 8 data bits. + outb(COM1+4, 0); + outb(COM1+1, 0x01); // Enable receive interrupts. + + // If status is 0xFF, no serial port. + if(inb(COM1+5) == 0xFF) + return; + uart = 1; + + // Acknowledge pre-existing interrupt conditions; + // enable interrupts. + inb(COM1+2); + inb(COM1+0); + picenable(IRQ_COM1); + ioapicenable(IRQ_COM1, 0); + + // Announce that we're here. + for(p="xv6...\n"; *p; p++) + uartputc(*p); +} + +void +uartputc(int c) +{ + int i; + + if(!uart) + return; + for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) + microdelay(10); + outb(COM1+0, c); +} + +static int +uartgetc(void) +{ + if(!uart) + return -1; + if(!(inb(COM1+5) & 0x01)) + return -1; + return inb(COM1+0); +} + +void +uartintr(void) +{ + consoleintr(uartgetc); +} |