Browse Source

[serial] Use new UART abstraction in serial console driver

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
2a696ab963

+ 10
- 13
src/arch/i386/interface/syslinux/comboot_call.c View File

@@ -41,8 +41,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
41 41
 #include <ipxe/image.h>
42 42
 #include <ipxe/version.h>
43 43
 #include <usr/imgmgmt.h>
44
-#include "config/console.h"
45
-#include "config/serial.h"
46 44
 
47 45
 /** The "SYSLINUX" version string */
48 46
 static char __bss16_array ( syslinux_version, [32] );
@@ -261,8 +259,10 @@ static __asmcall void int21 ( struct i386_all_regs *ix86 ) {
261 259
 		break;
262 260
 
263 261
 	case 0x04: /* Write Character to Serial Port */
264
-		serial_putc ( ix86->regs.dl );
265
-		ix86->flags &= ~CF;
262
+		if ( serial_console.base ) {
263
+			uart_transmit ( &serial_console, ix86->regs.dl );
264
+			ix86->flags &= ~CF;
265
+		}
266 266
 		break;
267 267
 
268 268
 	case 0x09: /* Write DOS String to Console */
@@ -455,15 +455,12 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
455 455
 		break;
456 456
 
457 457
 	case 0x000B: /* Get Serial Console Configuration */
458
-#if defined(CONSOLE_SERIAL) && !defined(COMPRESERVE)
459
-		ix86->regs.dx = COMCONSOLE;
460
-		ix86->regs.cx = 115200 / COMSPEED;
461
-		ix86->regs.bx = 0;
462
-#else
463
-		ix86->regs.dx = 0;
464
-#endif
465
-
466
-		ix86->flags &= ~CF;
458
+		if ( serial_console.base ) {
459
+			ix86->regs.dx = ( ( intptr_t ) serial_console.base );
460
+			ix86->regs.cx = serial_console.divisor;
461
+			ix86->regs.bx = 0;
462
+			ix86->flags &= ~CF;
463
+		}
467 464
 		break;
468 465
 
469 466
 	case 0x000E: /* Get configuration file name */

+ 1
- 1
src/config/config.c View File

@@ -55,7 +55,7 @@ PROVIDE_REQUIRING_SYMBOL();
55 55
 REQUIRE_OBJECT ( bios_console );
56 56
 #endif
57 57
 #ifdef CONSOLE_SERIAL
58
-REQUIRE_OBJECT ( serial_console );
58
+REQUIRE_OBJECT ( serial );
59 59
 #endif
60 60
 #ifdef CONSOLE_DIRECT_VGA
61 61
 REQUIRE_OBJECT ( video_subr );

+ 0
- 5
src/config/serial.h View File

@@ -13,11 +13,6 @@
13 13
 
14 14
 FILE_LICENCE ( GPL2_OR_LATER );
15 15
 
16
-#define	COM1		0x3f8
17
-#define	COM2		0x2f8
18
-#define	COM3		0x3e8
19
-#define	COM4		0x2e8
20
-
21 16
 #define	COMCONSOLE	COM1		/* I/O port address */
22 17
 
23 18
 /* Keep settings from a previous user of the serial port (e.g. lilo or

+ 137
- 212
src/core/serial.c View File

@@ -1,259 +1,184 @@
1 1
 /*
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.
2
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
7 3
  *
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().
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
12 22
  */
13 23
 
14
-FILE_LICENCE ( GPL2_OR_LATER );
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+/** @file
27
+ *
28
+ * Serial console
29
+ *
30
+ */
15 31
 
16
-#include "stddef.h"
32
+#include <stddef.h>
17 33
 #include <ipxe/init.h>
18
-#include <ipxe/io.h>
19
-#include <unistd.h>
34
+#include <ipxe/uart.h>
35
+#include <ipxe/console.h>
20 36
 #include <ipxe/serial.h>
21
-#include "config/serial.h"
22
-
23
-/* Set default values if none specified */
37
+#include <config/console.h>
38
+#include <config/serial.h>
24 39
 
25
-#ifndef COMCONSOLE
26
-#define COMCONSOLE	0x3f8
40
+/* Set default console usage if applicable */
41
+#if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) )
42
+#undef CONSOLE_SERIAL
43
+#define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
27 44
 #endif
28 45
 
29
-#ifndef COMSPEED
30
-#define COMSPEED	9600
31
-#endif
32
-
33
-#ifndef COMDATA
34
-#define COMDATA		8
46
+/* UART port number */
47
+#ifdef COMCONSOLE
48
+#define CONSOLE_PORT COMCONSOLE
49
+#else
50
+#define CONSOLE_PORT 0
35 51
 #endif
36 52
 
37
-#ifndef COMPARITY
38
-#define COMPARITY	0
53
+/* UART baud rate */
54
+#ifdef COMPRESERVE
55
+#define CONSOLE_BAUD 0
56
+#else
57
+#define CONSOLE_BAUD COMSPEED
39 58
 #endif
40 59
 
41
-#ifndef COMSTOP
42
-#define COMSTOP		1
60
+/* UART line control register value */
61
+#ifdef COMPRESERVE
62
+#define CONSOLE_LCR 0
63
+#else
64
+#define CONSOLE_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP )
43 65
 #endif
44 66
 
45
-#undef UART_BASE
46
-#define UART_BASE ( COMCONSOLE )
47
-
48
-#undef UART_BAUD
49
-#define UART_BAUD ( COMSPEED )
67
+/** Serial console UART */
68
+struct uart serial_console;
50 69
 
51
-#if ((115200%UART_BAUD) != 0)
52
-#error Bad ttys0 baud rate
53
-#endif
54
-
55
-#define COMBRD (115200/UART_BAUD)
70
+/**
71
+ * Print a character to serial console
72
+ *
73
+ * @v character		Character to be printed
74
+ */
75
+static void serial_putchar ( int character ) {
56 76
 
57
-/* Line Control Settings */
58
-#define UART_LCS ( ( ( (COMDATA) - 5 )	<< 0 ) | \
59
-		   ( ( (COMPARITY) )	<< 3 ) | \
60
-		   ( ( (COMSTOP) - 1 )	<< 2 ) )
77
+	/* Do nothing if we have no UART */
78
+	if ( ! serial_console.base )
79
+		return;
61 80
 
62
-/* Data */
63
-#define UART_RBR 0x00
64
-#define UART_TBR 0x00
81
+	/* Transmit character */
82
+	uart_transmit ( &serial_console, character );
83
+}
65 84
 
66
-/* Control */
67
-#define UART_IER 0x01
68
-#define UART_IIR 0x02
69
-#define UART_FCR 0x02
70
-#define UART_LCR 0x03
71
-#define UART_MCR 0x04
72
-#define UART_DLL 0x00
73
-#define UART_DLM 0x01
85
+/**
86
+ * Get character from serial console
87
+ *
88
+ * @ret character	Character read from console
89
+ */
90
+static int serial_getchar ( void ) {
91
+	uint8_t data;
74 92
 
75
-/* Status */
76
-#define UART_LSR 0x05
77
-#define  UART_LSR_TEMPT 0x40	/* Transmitter empty */
78
-#define  UART_LSR_THRE  0x20	/* Transmit-hold-register empty */
79
-#define  UART_LSR_BI	0x10	/* Break interrupt indicator */
80
-#define  UART_LSR_FE	0x08	/* Frame error indicator */
81
-#define  UART_LSR_PE	0x04	/* Parity error indicator */
82
-#define  UART_LSR_OE	0x02	/* Overrun error indicator */
83
-#define  UART_LSR_DR	0x01	/* Receiver data ready */
93
+	/* Do nothing if we have no UART */
94
+	if ( ! serial_console.base )
95
+		return 0;
84 96
 
85
-#define UART_MSR 0x06
86
-#define UART_SCR 0x07
97
+	/* Wait for data to be ready */
98
+	while ( ! uart_data_ready ( &serial_console ) ) {}
87 99
 
88
-#if defined(UART_MEM)
89
-#define uart_readb(addr) readb((addr))
90
-#define uart_writeb(val,addr) writeb((val),(addr))
91
-#else
92
-#define uart_readb(addr) inb((addr))
93
-#define uart_writeb(val,addr) outb((val),(addr))
94
-#endif
100
+	/* Receive data */
101
+	data = uart_receive ( &serial_console );
95 102
 
96
-/* Boolean for the state of serial driver initialization */
97
-int serial_initialized = 0;
103
+	/* Strip any high bit and convert DEL to backspace */
104
+	data &= 0x7f;
105
+	if ( data == 0x7f )
106
+		data = 0x08;
98 107
 
99
-/*
100
- * void serial_putc(int ch);
101
- *	Write character `ch' to port UART_BASE.
102
- */
103
-void serial_putc ( int ch ) {
104
-	int i;
105
-	int status;
106
-	i = 1000; /* timeout */
107
-	while(--i > 0) {
108
-		status = uart_readb(UART_BASE + UART_LSR);
109
-		if (status & UART_LSR_THRE) { 
110
-			/* TX buffer emtpy */
111
-			uart_writeb(ch, UART_BASE + UART_TBR);
112
-			break;
113
-		}
114
-		mdelay(2);
115
-	}
108
+	return data;
116 109
 }
117 110
 
118
-/*
119
- * int serial_getc(void);
120
- *	Read a character from port UART_BASE.
121
- */
122
-int serial_getc ( void ) {
123
-	int status;
124
-	int ch;
125
-	do {
126
-		status = uart_readb(UART_BASE + UART_LSR);
127
-	} while((status & 1) == 0);
128
-	ch = uart_readb(UART_BASE + UART_RBR);	/* fetch (first) character */
129
-	ch &= 0x7f;				/* remove any parity bits we get */
130
-	if (ch == 0x7f) {			/* Make DEL... look like BS */
131
-		ch = 0x08;
132
-	}
133
-	return ch;
134
-}
135
-
136
-/*
137
- * int serial_ischar(void);
138
- *       If there is a character in the input buffer of port UART_BASE,
139
- *       return nonzero; otherwise return 0.
111
+/**
112
+ * Check for character ready to read from serial console
113
+ *
114
+ * @ret True		Character available to read
115
+ * @ret False		No character available to read
140 116
  */
141
-int serial_ischar ( void ) {
142
-	int status;
143
-	status = uart_readb(UART_BASE + UART_LSR);	/* line status reg; */
144
-	return status & 1;		/* rx char available */
145
-}
117
+static int serial_iskey ( void ) {
146 118
 
147
-/*
148
- * int serial_init(void);
149
- *	Initialize port UART_BASE to speed COMSPEED, line settings 8N1.
150
- */
151
-static void serial_init ( void ) {
152
-	int status;
153
-	int divisor, lcs;
119
+	/* Do nothing if we have no UART */
120
+	if ( ! serial_console.base )
121
+		return 0;
154 122
 
155
-	DBG ( "Serial port %#x initialising\n", UART_BASE );
123
+	/* Check UART */
124
+	return uart_data_ready ( &serial_console );
125
+}
156 126
 
157
-	divisor = COMBRD;
158
-	lcs = UART_LCS;
127
+/** Serial console */
128
+struct console_driver serial_console_driver __console_driver = {
129
+	.putchar = serial_putchar,
130
+	.getchar = serial_getchar,
131
+	.iskey = serial_iskey,
132
+	.usage = CONSOLE_SERIAL,
133
+};
159 134
 
135
+/** Initialise serial console */
136
+static void serial_init ( void ) {
137
+	int rc;
160 138
 
161
-#ifdef COMPRESERVE
162
-	lcs = uart_readb(UART_BASE + UART_LCR) & 0x7f;
163
-	uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
164
-	divisor = (uart_readb(UART_BASE + UART_DLM) << 8) | uart_readb(UART_BASE + UART_DLL);
165
-	uart_writeb(lcs, UART_BASE + UART_LCR);
166
-#endif
139
+	/* Do nothing if we have no default port */
140
+	if ( ! CONSOLE_PORT )
141
+		return;
167 142
 
168
-	/* Set Baud Rate Divisor to COMSPEED, and test to see if the
169
-	 * serial port appears to be present.
170
-	 */
171
-	uart_writeb(0x80 | lcs, UART_BASE + UART_LCR);
172
-	uart_writeb(0xaa, UART_BASE + UART_DLL);
173
-	if (uart_readb(UART_BASE + UART_DLL) != 0xaa) {
174
-		DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
175
-		goto out;
176
-	}
177
-	uart_writeb(0x55, UART_BASE + UART_DLL);
178
-	if (uart_readb(UART_BASE + UART_DLL) != 0x55) {
179
-		DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
180
-		goto out;
143
+	/* Select UART */
144
+	if ( ( rc = uart_select ( &serial_console, CONSOLE_PORT ) ) != 0 ) {
145
+		DBG ( "Could not select UART %d: %s\n",
146
+		      CONSOLE_PORT, strerror ( rc ) );
147
+		return;
181 148
 	}
182
-	uart_writeb(divisor & 0xff, UART_BASE + UART_DLL);
183
-	if (uart_readb(UART_BASE + UART_DLL) != (divisor & 0xff)) {
184
-		DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE );
185
-		goto out;
186
-	}
187
-	uart_writeb(0xaa, UART_BASE + UART_DLM);
188
-	if (uart_readb(UART_BASE + UART_DLM) != 0xaa) {
189
-		DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
190
-		goto out;
191
-	}
192
-	uart_writeb(0x55, UART_BASE + UART_DLM);
193
-	if (uart_readb(UART_BASE + UART_DLM) != 0x55) {
194
-		DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
195
-		goto out;
196
-	}
197
-	uart_writeb((divisor >> 8) & 0xff, UART_BASE + UART_DLM);
198
-	if (uart_readb(UART_BASE + UART_DLM) != ((divisor >> 8) & 0xff)) {
199
-		DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE );
200
-		goto out;
201
-	}
202
-	uart_writeb(lcs, UART_BASE + UART_LCR);
203
-	
204
-	/* disable interrupts */
205
-	uart_writeb(0x0, UART_BASE + UART_IER);
206 149
 
207
-	/* enable fifos */
208
-	uart_writeb(0x01, UART_BASE + UART_FCR);
150
+	/* Initialise UART */
151
+	if ( ( rc = uart_init ( &serial_console, CONSOLE_BAUD,
152
+				CONSOLE_LCR ) ) != 0 ) {
153
+		DBG ( "Could not initialise UART %d baud %d LCR %#02x: %s\n",
154
+		      CONSOLE_PORT, CONSOLE_BAUD, CONSOLE_LCR, strerror ( rc ));
155
+		return;
156
+	}
157
+}
209 158
 
210
-	/* Set clear to send, so flow control works... */
211
-	uart_writeb((1<<1), UART_BASE + UART_MCR);
159
+/**
160
+ * Shut down serial console
161
+ *
162
+ * @v flags		Shutdown flags
163
+ */
164
+static void serial_shutdown ( int flags __unused ) {
212 165
 
213
-	/* Flush the input buffer. */
214
-	do {
215
-		/* rx buffer reg
216
-		 * throw away (unconditionally the first time)
217
-		 */
218
-	        (void) uart_readb(UART_BASE + UART_RBR);
219
-		/* line status reg */
220
-		status = uart_readb(UART_BASE + UART_LSR);
221
-	} while(status & UART_LSR_DR);
166
+	/* Do nothing if we have no UART */
167
+	if ( ! serial_console.base )
168
+		return;
222 169
 
223
-	/* Note that serial support has been initialized */
224
-	serial_initialized = 1;
225
- out:
226
-	return;
227
-}
170
+	/* Flush any pending output */
171
+	uart_flush ( &serial_console );
228 172
 
229
-/*
230
- * void serial_fini(void);
231
- *	Cleanup our use of the serial port, in particular flush the
232
- *	output buffer so we don't accidentially lose characters.
233
- */
234
-static void serial_fini ( int flags __unused ) {
235
-	int i, status;
236
-	/* Flush the output buffer to avoid dropping characters,
237
-	 * if we are reinitializing the serial port.
238
-	 */
239
-	i = 10000; /* timeout */
240
-	do {
241
-		status = uart_readb(UART_BASE + UART_LSR);
242
-	} while((--i > 0) && !(status & UART_LSR_TEMPT));
243
-	/* Don't mark it as disabled; it's still usable */
173
+	/* Leave console enabled; it's still usable */
244 174
 }
245 175
 
246
-/**
247
- * Serial driver initialisation function
248
- *
249
- * Initialise serial port early on so that it is available to capture
250
- * early debug messages.
251
- */
252
-struct init_fn serial_init_fn __init_fn ( INIT_SERIAL ) = {
176
+/** Serial console initialisation function */
177
+struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = {
253 178
 	.initialise = serial_init,
254 179
 };
255 180
 
256
-/** Serial driver startup function */
181
+/** Serial console startup function */
257 182
 struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
258
-	.shutdown = serial_fini,
183
+	.shutdown = serial_shutdown,
259 184
 };

+ 0
- 42
src/core/serial_console.c View File

@@ -1,42 +0,0 @@
1
-#include <ipxe/init.h>
2
-#include <ipxe/serial.h>
3
-#include <ipxe/console.h>
4
-#include <config/console.h>
5
-
6
-/** @file
7
- *
8
- * Serial console
9
- *
10
- */
11
-
12
-/* Set default console usage if applicable */
13
-#if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) )
14
-#undef CONSOLE_SERIAL
15
-#define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
16
-#endif
17
-
18
-struct console_driver serial_console __console_driver;
19
-
20
-static void serial_console_init ( void ) {
21
-	/*
22
-	 * Check if serial driver initialization is done.
23
-	 * If so, it's time to enable the serial console.
24
-	 */
25
-	if ( serial_initialized )
26
-		serial_console.disabled = 0;
27
-}
28
-
29
-struct console_driver serial_console __console_driver = {
30
-	.putchar = serial_putc,
31
-	.getchar = serial_getc,
32
-	.iskey = serial_ischar,
33
-	.disabled = CONSOLE_DISABLED,
34
-	.usage = CONSOLE_SERIAL,
35
-};
36
-
37
-/**
38
- * Serial console initialisation function
39
- */
40
-struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = {
41
-	.initialise = serial_console_init,
42
-};

+ 3
- 4
src/include/ipxe/init.h View File

@@ -26,10 +26,9 @@ struct init_fn {
26 26
  */
27 27
 
28 28
 #define INIT_EARLY	01	/**< Early initialisation */
29
-#define INIT_SERIAL	02	/**< Serial driver initialisation */
30
-#define	INIT_CONSOLE	03	/**< Console initialisation */
31
-#define INIT_NORMAL	04	/**< Normal initialisation */
32
-#define INIT_LATE	05	/**< Late initialisation */
29
+#define	INIT_CONSOLE	02	/**< Console initialisation */
30
+#define INIT_NORMAL	03	/**< Normal initialisation */
31
+#define INIT_LATE	04	/**< Late initialisation */
33 32
 
34 33
 /** @} */
35 34
 

+ 4
- 5
src/include/ipxe/serial.h View File

@@ -3,15 +3,14 @@
3 3
 
4 4
 /** @file
5 5
  *
6
- * Serial driver functions
6
+ * Serial console
7 7
  *
8 8
  */
9 9
 
10 10
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 11
 
12
-extern void serial_putc ( int ch );
13
-extern int serial_getc ( void );
14
-extern int serial_ischar ( void );
15
-extern int serial_initialized;
12
+#include <ipxe/uart.h>
13
+
14
+extern struct uart serial_console;
16 15
 
17 16
 #endif /* _IPXE_SERIAL_H */

Loading…
Cancel
Save