2 * The serial port interface routines implement a simple polled i/o
3 * interface to a standard serial port. Due to the space restrictions
4 * for the boot blocks, no BIOS support is used (since BIOS requires
5 * expensive real/protected mode switches), instead the rudimentary
6 * BIOS support is duplicated here.
8 * The base address and speed for the i/o port are passed from the
9 * Makefile in the COMCONSOLE and CONSPEED preprocessor macros. The
10 * line control parameters are currently hard-coded to 8 bits, no
11 * parity, 1 stop bit (8N1). This can be changed in init_serial().
18 /* Set default values if none specified */
21 #define COMCONSOLE 0x3f8
41 #define UART_BASE ( COMCONSOLE )
44 #define UART_BAUD ( COMSPEED )
46 #if ((115200%UART_BAUD) != 0)
47 #error Bad ttys0 baud rate
50 #define COMBRD (115200/UART_BAUD)
52 /* Line Control Settings */
53 #define UART_LCS ( ( ( (COMDATA) - 5 ) << 0 ) | \
54 ( ( (COMPARITY) ) << 3 ) | \
55 ( ( (COMSTOP) - 1 ) << 2 ) )
72 #define UART_LSR_TEMPT 0x40 /* Transmitter empty */
73 #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
74 #define UART_LSR_BI 0x10 /* Break interrupt indicator */
75 #define UART_LSR_FE 0x08 /* Frame error indicator */
76 #define UART_LSR_PE 0x04 /* Parity error indicator */
77 #define UART_LSR_OE 0x02 /* Overrun error indicator */
78 #define UART_LSR_DR 0x01 /* Receiver data ready */
83 #define uart_readb(addr) inb(addr)
84 #define uart_writeb(val,addr) outb((val),(addr))
87 * void serial_putc(int ch);
88 * Write character `ch' to port UART_BASE.
90 void serial_putc(int ch
)
94 status
= uart_readb(UART_BASE
+ UART_LSR
);
95 if (status
& UART_LSR_THRE
) {
97 uart_writeb(ch
, UART_BASE
+ UART_TBR
);
104 * int serial_getc(void);
105 * Read a character from port UART_BASE.
107 int serial_getc(void)
112 status
= uart_readb(UART_BASE
+ UART_LSR
);
113 } while ((status
& 1) == 0);
114 ch
= uart_readb(UART_BASE
+ UART_RBR
); /* fetch (first) character */
115 ch
&= 0x7f; /* remove any parity bits we get */
116 if (ch
== 0x7f) { /* Make DEL... look like BS */
123 * int serial_init(void);
124 * Initialize port UART_BASE to speed COMSPEED, line settings 8N1.
126 void serial_init(void)
135 lcs
= uart_readb(UART_BASE
+ UART_LCR
) & 0x7f;
136 uart_writeb(0x80 | lcs
, UART_BASE
+ UART_LCR
);
138 (uart_readb(UART_BASE
+ UART_DLM
) << 8) | uart_readb(UART_BASE
+
140 uart_writeb(lcs
, UART_BASE
+ UART_LCR
);
143 /* Set Baud Rate Divisor to COMSPEED, and test to see if the
144 * serial port appears to be present.
146 uart_writeb(0x80 | lcs
, UART_BASE
+ UART_LCR
);
147 uart_writeb(0xaa, UART_BASE
+ UART_DLL
);
148 if (uart_readb(UART_BASE
+ UART_DLL
) != 0xaa) {
151 uart_writeb(0x55, UART_BASE
+ UART_DLL
);
152 if (uart_readb(UART_BASE
+ UART_DLL
) != 0x55) {
155 uart_writeb(divisor
& 0xff, UART_BASE
+ UART_DLL
);
156 if (uart_readb(UART_BASE
+ UART_DLL
) != (divisor
& 0xff)) {
159 uart_writeb(0xaa, UART_BASE
+ UART_DLM
);
160 if (uart_readb(UART_BASE
+ UART_DLM
) != 0xaa) {
163 uart_writeb(0x55, UART_BASE
+ UART_DLM
);
164 if (uart_readb(UART_BASE
+ UART_DLM
) != 0x55) {
167 uart_writeb((divisor
>> 8) & 0xff, UART_BASE
+ UART_DLM
);
168 if (uart_readb(UART_BASE
+ UART_DLM
) != ((divisor
>> 8) & 0xff)) {
171 uart_writeb(lcs
, UART_BASE
+ UART_LCR
);
173 /* disable interrupts */
174 uart_writeb(0x0, UART_BASE
+ UART_IER
);
177 uart_writeb(0x00, UART_BASE
+ UART_FCR
);
179 /* Set clear to send, so flow control works... */
180 uart_writeb((1 << 1), UART_BASE
+ UART_MCR
);
182 /* Flush the input buffer. */
185 * throw away (unconditionally the first time)
187 (void)uart_readb(UART_BASE
+ UART_RBR
);
188 /* line status reg */
189 status
= uart_readb(UART_BASE
+ UART_LSR
);
190 } while (status
& UART_LSR_DR
);