// Intel 8250 serial port (UART). #include "core/types.h" #include "core/defs.h" #include "core/irq.h" #include "core/param.h" #include "arch/traps.h" #include "core/spinlock.h" #include "core/sleeplock.h" #include "fs/fs.h" #include "fs/file.h" #include "arch/mmu.h" #include "core/proc.h" #include "arch/x86.h" #define COM1 0x3f8 static int uart; // is there a uart? void uartearlyinit(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; // Announce that we're here -- only when asked for. This is the first thing a serial line ever sees from // SchOS and it says nothing except that the port works -- which is worth a // line on a boot you are watching and not on every boot for ever. It cannot // go through kinfo(): it runs before there is a console to route it to. if (!boot_verbose) return; for(p="SchOS UART...\n"; *p; p++) uartputc(*p); } // irq.c hands every handler an opaque argument, because a driver with two // controllers needs to know which one interrupted. There is only one COM1. static void uart_irq(void *arg) { (void)arg; uartintr(); } void uartinit(void) { if(!uart) return; // Acknowledge pre-existing interrupt conditions; // enable interrupts. inb(COM1+2); inb(COM1+0); irq_register(IRQ_COM1, uart_irq, 0, "serial", 0); } 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); }