diff options
author | Yinghai Lu <yinghai@kernel.org> | 2010-08-02 05:17:31 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-08-02 18:51:56 -0400 |
commit | f4ed2877b16e8146427306aea8819adac5c88374 (patch) | |
tree | 9451d9e5bb300634b00c25bd0ab155a1854e4223 /arch/x86/boot/tty.c | |
parent | 22a57f5896df218356bae6203dfaf04bcfd6c88c (diff) |
x86, setup: reorganize the early console setup
Separate early_serial_console from tty.c
This allows for reuse of
early_serial_console.c/string.c/printf.c/cmdline.c in boot/compressed/.
-v2: according to hpa, don't include string.c etc
-v3: compressed/misc.c must have early_serial_base as static, so move it back to tty.c
for setup code
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <4C568D2B.205@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/boot/tty.c')
-rw-r--r-- | arch/x86/boot/tty.c | 136 |
1 files changed, 1 insertions, 135 deletions
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c index ff4b27a0fc5e..def2451f46ae 100644 --- a/arch/x86/boot/tty.c +++ b/arch/x86/boot/tty.c | |||
@@ -15,27 +15,12 @@ | |||
15 | 15 | ||
16 | #include "boot.h" | 16 | #include "boot.h" |
17 | 17 | ||
18 | #define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */ | 18 | int early_serial_base; |
19 | |||
20 | static int early_serial_base; | ||
21 | 19 | ||
22 | #define XMTRDY 0x20 | 20 | #define XMTRDY 0x20 |
23 | 21 | ||
24 | #define DLAB 0x80 | ||
25 | |||
26 | #define TXR 0 /* Transmit register (WRITE) */ | 22 | #define TXR 0 /* Transmit register (WRITE) */ |
27 | #define RXR 0 /* Receive register (READ) */ | ||
28 | #define IER 1 /* Interrupt Enable */ | ||
29 | #define IIR 2 /* Interrupt ID */ | ||
30 | #define FCR 2 /* FIFO control */ | ||
31 | #define LCR 3 /* Line control */ | ||
32 | #define MCR 4 /* Modem control */ | ||
33 | #define LSR 5 /* Line Status */ | 23 | #define LSR 5 /* Line Status */ |
34 | #define MSR 6 /* Modem Status */ | ||
35 | #define DLL 0 /* Divisor Latch Low */ | ||
36 | #define DLH 1 /* Divisor latch High */ | ||
37 | |||
38 | #define DEFAULT_BAUD 9600 | ||
39 | 24 | ||
40 | /* | 25 | /* |
41 | * These functions are in .inittext so they can be used to signal | 26 | * These functions are in .inittext so they can be used to signal |
@@ -152,122 +137,3 @@ int getchar_timeout(void) | |||
152 | return 0; /* Timeout! */ | 137 | return 0; /* Timeout! */ |
153 | } | 138 | } |
154 | 139 | ||
155 | static void early_serial_init(int port, int baud) | ||
156 | { | ||
157 | unsigned char c; | ||
158 | unsigned divisor; | ||
159 | |||
160 | outb(0x3, port + LCR); /* 8n1 */ | ||
161 | outb(0, port + IER); /* no interrupt */ | ||
162 | outb(0, port + FCR); /* no fifo */ | ||
163 | outb(0x3, port + MCR); /* DTR + RTS */ | ||
164 | |||
165 | divisor = 115200 / baud; | ||
166 | c = inb(port + LCR); | ||
167 | outb(c | DLAB, port + LCR); | ||
168 | outb(divisor & 0xff, port + DLL); | ||
169 | outb((divisor >> 8) & 0xff, port + DLH); | ||
170 | outb(c & ~DLAB, port + LCR); | ||
171 | |||
172 | early_serial_base = port; | ||
173 | |||
174 | printf("Early serial console at I/O port 0x%x baud: %d\n", port, baud); | ||
175 | } | ||
176 | |||
177 | static void parse_earlyprintk(void) | ||
178 | { | ||
179 | int baud = DEFAULT_BAUD; | ||
180 | char arg[32]; | ||
181 | int pos = 0; | ||
182 | int port = 0; | ||
183 | |||
184 | if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) { | ||
185 | char *e; | ||
186 | |||
187 | if (!strncmp(arg, "serial", 6)) { | ||
188 | port = DEFAULT_SERIAL_PORT; | ||
189 | pos += 6; | ||
190 | } | ||
191 | |||
192 | if (arg[pos] == ',') | ||
193 | pos++; | ||
194 | |||
195 | if (!strncmp(arg, "ttyS", 4)) { | ||
196 | static const int bases[] = { 0x3f8, 0x2f8 }; | ||
197 | int idx = 0; | ||
198 | |||
199 | if (!strncmp(arg + pos, "ttyS", 4)) | ||
200 | pos += 4; | ||
201 | |||
202 | if (arg[pos++] == '1') | ||
203 | idx = 1; | ||
204 | |||
205 | port = bases[idx]; | ||
206 | } | ||
207 | |||
208 | if (arg[pos] == ',') | ||
209 | pos++; | ||
210 | |||
211 | baud = simple_strtoull(arg + pos, &e, 0); | ||
212 | if (baud == 0 || arg + pos == e) | ||
213 | baud = DEFAULT_BAUD; | ||
214 | } | ||
215 | |||
216 | if (port) | ||
217 | early_serial_init(port, baud); | ||
218 | } | ||
219 | |||
220 | #define BASE_BAUD (1843200/16) | ||
221 | static unsigned int probe_baud(int port) | ||
222 | { | ||
223 | unsigned char lcr, dll, dlh; | ||
224 | unsigned int quot; | ||
225 | |||
226 | lcr = inb(port + LCR); | ||
227 | outb(lcr | DLAB, port + LCR); | ||
228 | dll = inb(port + DLL); | ||
229 | dlh = inb(port + DLH); | ||
230 | outb(lcr, port + LCR); | ||
231 | quot = (dlh << 8) | dll; | ||
232 | |||
233 | return BASE_BAUD / quot; | ||
234 | } | ||
235 | |||
236 | static void parse_console_uart8250(void) | ||
237 | { | ||
238 | char optstr[64], *options; | ||
239 | int baud = DEFAULT_BAUD; | ||
240 | int port = 0; | ||
241 | |||
242 | /* | ||
243 | * console=uart8250,io,0x3f8,115200n8 | ||
244 | * need to make sure it is last one console ! | ||
245 | */ | ||
246 | if (cmdline_find_option("console", optstr, sizeof optstr) <= 0) | ||
247 | return; | ||
248 | |||
249 | options = optstr; | ||
250 | |||
251 | if (!strncmp(options, "uart8250,io,", 12)) | ||
252 | port = simple_strtoull(options + 12, &options, 0); | ||
253 | else if (!strncmp(options, "uart,io,", 8)) | ||
254 | port = simple_strtoull(options + 8, &options, 0); | ||
255 | else | ||
256 | return; | ||
257 | |||
258 | if (options && (options[0] == ',')) | ||
259 | baud = simple_strtoull(options + 1, &options, 0); | ||
260 | else | ||
261 | baud = probe_baud(port); | ||
262 | |||
263 | if (port) | ||
264 | early_serial_init(port, baud); | ||
265 | } | ||
266 | |||
267 | void console_init(void) | ||
268 | { | ||
269 | parse_earlyprintk(); | ||
270 | |||
271 | if (!early_serial_base) | ||
272 | parse_console_uart8250(); | ||
273 | } | ||