1 #include <lwk/driver.h>
2 #include <lwk/console.h>
3 #include <lwk/interrupt.h>
6 // Serial port registers
7 #define TXB 0 // Transmitter Holding Buffer W
8 #define RXB 0 // Receiver Buffer R
9 #define DLL 0 // Divisor Latch Low Byte R/W
10 #define IER 1 // Interrupt Enable Register R/W
11 #define DLH 1 // Divisor Latch High Byte R/W
12 #define IIR 2 // Interrupt Identification Register R
13 #define FCR 2 // FIFO Control Register W
14 #define LCR 3 // Line Control Register R/W
15 #define MCR 4 // Modem Control Register R/W
16 #define LSR 5 // Line Status Register R
17 #define MSR 6 // Modem Status Register R
18 #define SCR 7 // Scratch Register R/W
21 #define IER_RLSI 0x08 // RX interrupt
22 #define IER_THRI 0x02 // TX interrupt
23 #define IER_RDI 0x01 // Reciver data interrupt
26 #define MCR_DTR 0x01 // Enable DTR
27 #define MCR_RTS 0x02 // Enable RTS
28 #define MCR_OUT2 0x08 // Enable Out2 (?)
31 #define LSR_TXEMPT 0x20 // Empty TX holding register
32 #define LSR_RXRDY 0x01 // Ready to receive
35 #define LCR_DLAB 0x80 // Divisor latch access bit
37 /** IO port address of the serial port. */
38 static unsigned int port = 0x3F8; // COM1
40 /** Serial port baud rate. */
41 static unsigned int baud = 9600;
42 #define SERIAL_MAX_BAUD 115200
44 /** Set when serial console has been initialized. */
45 static int initialized = 0;
48 * Prints a single character to the serial port.
50 static void serial_putc(unsigned char c)
52 // Wait until the TX buffer is empty
53 while ((inb_p(port + LSR) & LSR_TXEMPT) == 0)
55 // Slam the 8 bits down the 1 bit pipe... meeeooowwwy!
60 * Writes a string to the serial port.
62 static void serial_write(struct console *con, const char *str)
65 while ((c = *str++) != '\0') {
67 if (c == '\n') // new line
68 serial_putc('\r'); // tack on carriage return
73 * Serial port console device.
75 static struct console serial_console = {
76 .name = "Serial Console",
81 * Initializes and registers the serial console driver.
83 void serial_console_init(void)
85 // Setup the divisor latch registers for the specified baud rate
86 unsigned int div = SERIAL_MAX_BAUD / baud;
89 printk(KERN_ERR "Serial console already initialized.\n");
93 outb( inb(port+LCR) | LCR_DLAB , port+LCR ); // set DLAB
94 outb( (div>>0) & 0xFF , port+DLL ); // set divisor low byte
95 outb( (div>>8) & 0xFF , port+DLH ); // set divisor high byte
96 outb( inb(port+LCR) & ~LCR_DLAB , port+LCR ); // unset DLAB
98 outb( 0x0 , port+IER ); // Disable serial port interrupts
99 outb( 0x0 , port+FCR ); // Don't use the FIFOs
100 outb( 0x3 , port+LCR ); // 8n1
102 // Setup modem control register
103 outb( MCR_RTS | MCR_DTR | MCR_OUT2 , port+MCR);
105 console_register(&serial_console);
109 driver_init(serial_console_init);
112 * Configurable parameters for controlling the serial port
113 * I/O port address and baud.
115 driver_param(port, uint);
116 driver_param(baud, uint);