xref: /onnv-gate/usr/src/uts/i86pc/boot/boot_console.c (revision 3446:5903aece022d)
1*3446Smrj /*
2*3446Smrj  * CDDL HEADER START
3*3446Smrj  *
4*3446Smrj  * The contents of this file are subject to the terms of the
5*3446Smrj  * Common Development and Distribution License (the "License").
6*3446Smrj  * You may not use this file except in compliance with the License.
7*3446Smrj  *
8*3446Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3446Smrj  * or http://www.opensolaris.org/os/licensing.
10*3446Smrj  * See the License for the specific language governing permissions
11*3446Smrj  * and limitations under the License.
12*3446Smrj  *
13*3446Smrj  * When distributing Covered Code, include this CDDL HEADER in each
14*3446Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3446Smrj  * If applicable, add the following below this CDDL HEADER, with the
16*3446Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
17*3446Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3446Smrj  *
19*3446Smrj  * CDDL HEADER END
20*3446Smrj  */
21*3446Smrj /*
22*3446Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*3446Smrj  * Use is subject to license terms.
24*3446Smrj  */
25*3446Smrj 
26*3446Smrj #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*3446Smrj 
28*3446Smrj #include <sys/types.h>
29*3446Smrj #include <sys/systm.h>
30*3446Smrj #include <sys/archsystm.h>
31*3446Smrj #include <sys/boot_console.h>
32*3446Smrj 
33*3446Smrj #include "boot_serial.h"
34*3446Smrj #include "boot_vga.h"
35*3446Smrj 
36*3446Smrj #if defined(_BOOT)
37*3446Smrj #include "../dboot/dboot_xboot.h"
38*3446Smrj #include <util/string.h>
39*3446Smrj #else
40*3446Smrj #include <sys/bootconf.h>
41*3446Smrj static char *usbser_buf;
42*3446Smrj static char *usbser_cur;
43*3446Smrj #endif
44*3446Smrj 
45*3446Smrj static int cons_color = CONS_COLOR;
46*3446Smrj int console = CONS_SCREEN_TEXT;
47*3446Smrj /* or CONS_TTYA, CONS_TTYB */
48*3446Smrj static int serial_ischar(void);
49*3446Smrj static int serial_getchar(void);
50*3446Smrj static void serial_putchar(int);
51*3446Smrj static void serial_adjust_prop(void);
52*3446Smrj 
53*3446Smrj static char *boot_line = NULL;
54*3446Smrj 
55*3446Smrj /* Clear the screen and initialize VIDEO, XPOS and YPOS. */
56*3446Smrj static void
57*3446Smrj clear_screen(void)
58*3446Smrj {
59*3446Smrj 	/*
60*3446Smrj 	 * XXX should set vga mode so we don't depend on the
61*3446Smrj 	 * state left by the boot loader
62*3446Smrj 	 */
63*3446Smrj 	vga_clear(cons_color);
64*3446Smrj 	vga_setpos(0, 0);
65*3446Smrj }
66*3446Smrj 
67*3446Smrj /* Put the character C on the screen. */
68*3446Smrj static void
69*3446Smrj screen_putchar(int c)
70*3446Smrj {
71*3446Smrj 	int row, col;
72*3446Smrj 
73*3446Smrj 	vga_getpos(&row, &col);
74*3446Smrj 	switch (c) {
75*3446Smrj 	case '\t':
76*3446Smrj 		col += 8 - (col % 8);
77*3446Smrj 		if (col == VGA_TEXT_COLS)
78*3446Smrj 			col = 79;
79*3446Smrj 		vga_setpos(row, col);
80*3446Smrj 		break;
81*3446Smrj 
82*3446Smrj 	case '\r':
83*3446Smrj 		vga_setpos(row, 0);
84*3446Smrj 		break;
85*3446Smrj 
86*3446Smrj 	case '\b':
87*3446Smrj 		if (col > 0)
88*3446Smrj 			vga_setpos(row, col - 1);
89*3446Smrj 		break;
90*3446Smrj 
91*3446Smrj 	case '\n':
92*3446Smrj 		if (row < VGA_TEXT_ROWS - 1)
93*3446Smrj 			vga_setpos(row + 1, col);
94*3446Smrj 		else
95*3446Smrj 			vga_scroll(cons_color);
96*3446Smrj 		break;
97*3446Smrj 
98*3446Smrj 	default:
99*3446Smrj 		vga_drawc(c, cons_color);
100*3446Smrj 		if (col < VGA_TEXT_COLS -1)
101*3446Smrj 			vga_setpos(row, col + 1);
102*3446Smrj 		else if (row < VGA_TEXT_ROWS - 1)
103*3446Smrj 			vga_setpos(row + 1, 0);
104*3446Smrj 		else {
105*3446Smrj 			vga_setpos(row, 0);
106*3446Smrj 			vga_scroll(cons_color);
107*3446Smrj 		}
108*3446Smrj 		break;
109*3446Smrj 	}
110*3446Smrj }
111*3446Smrj 
112*3446Smrj /* serial port stuff */
113*3446Smrj static int port;
114*3446Smrj 
115*3446Smrj static void
116*3446Smrj serial_init(void)
117*3446Smrj {
118*3446Smrj 	switch (console) {
119*3446Smrj 	case CONS_TTYA:
120*3446Smrj 		port = 0x3f8;
121*3446Smrj 		break;
122*3446Smrj 	case CONS_TTYB:
123*3446Smrj 		port = 0x2f8;
124*3446Smrj 		break;
125*3446Smrj 	}
126*3446Smrj 
127*3446Smrj 	outb(port + ISR, 0x20);
128*3446Smrj 	if (inb(port + ISR) & 0x20) {
129*3446Smrj 		/*
130*3446Smrj 		 * 82510 chip is present
131*3446Smrj 		 */
132*3446Smrj 		outb(port + DAT+7, 0x04);	/* clear status */
133*3446Smrj 		outb(port + ISR, 0x40);  /* set to bank 2 */
134*3446Smrj 		outb(port + MCR, 0x08);  /* IMD */
135*3446Smrj 		outb(port + DAT, 0x21);  /* FMD */
136*3446Smrj 		outb(port + ISR, 0x00);  /* set to bank 0 */
137*3446Smrj 	} else {
138*3446Smrj 		/*
139*3446Smrj 		 * set the UART in FIFO mode if it has FIFO buffers.
140*3446Smrj 		 * use 16550 fifo reset sequence specified in NS
141*3446Smrj 		 * application note. disable fifos until chip is
142*3446Smrj 		 * initialized.
143*3446Smrj 		 */
144*3446Smrj 		outb(port + FIFOR, 0x00);		/* clear */
145*3446Smrj 		outb(port + FIFOR, FIFO_ON);		/* enable */
146*3446Smrj 		outb(port + FIFOR, FIFO_ON|FIFORXFLSH);  /* reset */
147*3446Smrj 		outb(port + FIFOR,
148*3446Smrj 		    FIFO_ON|FIFODMA|FIFOTXFLSH|FIFORXFLSH|0x80);
149*3446Smrj 		if ((inb(port + ISR) & 0xc0) != 0xc0) {
150*3446Smrj 			/*
151*3446Smrj 			 * no fifo buffers so disable fifos.
152*3446Smrj 			 * this is true for 8250's
153*3446Smrj 			 */
154*3446Smrj 			outb(port + FIFOR, 0x00);
155*3446Smrj 		}
156*3446Smrj 	}
157*3446Smrj 
158*3446Smrj 	/* disable interrupts */
159*3446Smrj 	outb(port + ICR, 0);
160*3446Smrj 
161*3446Smrj 	/* adjust setting based on tty properties */
162*3446Smrj 	serial_adjust_prop();
163*3446Smrj 
164*3446Smrj #if defined(_BOOT)
165*3446Smrj 	/*
166*3446Smrj 	 * Do a full reset to match console behavior.
167*3446Smrj 	 * 0x1B + c - reset everything
168*3446Smrj 	 */
169*3446Smrj 	serial_putchar(0x1B);
170*3446Smrj 	serial_putchar('c');
171*3446Smrj #endif
172*3446Smrj }
173*3446Smrj 
174*3446Smrj 
175*3446Smrj #define	MATCHES(p, pat)	\
176*3446Smrj 	(strncmp(p, pat, strlen(pat)) == 0 ? (p += strlen(pat), 1) : 0)
177*3446Smrj 
178*3446Smrj #define	SKIP(p, c)				\
179*3446Smrj 	while (*(p) != 0 && *p != (c))		\
180*3446Smrj 		++(p);				\
181*3446Smrj 	if (*(p) == (c))			\
182*3446Smrj 		++(p);
183*3446Smrj 
184*3446Smrj /*
185*3446Smrj  * find a tty mode property either from cmdline or from boot properties
186*3446Smrj  */
187*3446Smrj static char *
188*3446Smrj get_mode_value(char *name)
189*3446Smrj {
190*3446Smrj 	char *p;
191*3446Smrj 
192*3446Smrj 	/*
193*3446Smrj 	 * when specified on boot line it looks like "name" "="....
194*3446Smrj 	 */
195*3446Smrj 	if (boot_line != NULL) {
196*3446Smrj 		p = strstr(boot_line, name);
197*3446Smrj 		if (p == NULL)
198*3446Smrj 			return (NULL);
199*3446Smrj 		SKIP(p, '=');
200*3446Smrj 		return (p);
201*3446Smrj 	}
202*3446Smrj 
203*3446Smrj #if defined(_BOOT)
204*3446Smrj 	return (NULL);
205*3446Smrj #else
206*3446Smrj 	/*
207*3446Smrj 	 * if we're running in the full kernel we check the bootenv.rc settings
208*3446Smrj 	 */
209*3446Smrj 	{
210*3446Smrj 		static char propval[20];
211*3446Smrj 
212*3446Smrj 		propval[0] = 0;
213*3446Smrj 		if (bootops == NULL || BOP_GETPROPLEN(bootops, name) == 0)
214*3446Smrj 			return (NULL);
215*3446Smrj 		(void) BOP_GETPROP(bootops, name, propval);
216*3446Smrj 		return (propval);
217*3446Smrj 	}
218*3446Smrj #endif
219*3446Smrj }
220*3446Smrj 
221*3446Smrj /*
222*3446Smrj  * adjust serial port based on properties
223*3446Smrj  * These come either from the cmdline or from boot properties.
224*3446Smrj  */
225*3446Smrj static void
226*3446Smrj serial_adjust_prop(void)
227*3446Smrj {
228*3446Smrj 	char propname[20];
229*3446Smrj 	char *propval;
230*3446Smrj 	char *p;
231*3446Smrj 	ulong_t baud;
232*3446Smrj 	uchar_t lcr = 0;
233*3446Smrj 	uchar_t mcr = DTR | RTS;
234*3446Smrj 
235*3446Smrj 	(void) strcpy(propname, "ttyX-mode");
236*3446Smrj 	propname[3] = 'a' + console - CONS_TTYA;
237*3446Smrj 	propval = get_mode_value(propname);
238*3446Smrj 	if (propval == NULL)
239*3446Smrj 		propval = "9600,8,n,1,-";
240*3446Smrj 
241*3446Smrj 	/* property is of the form: "9600,8,n,1,-" */
242*3446Smrj 	p = propval;
243*3446Smrj 	if (MATCHES(p, "110,"))
244*3446Smrj 		baud = ASY110;
245*3446Smrj 	else if (MATCHES(p, "150,"))
246*3446Smrj 		baud = ASY150;
247*3446Smrj 	else if (MATCHES(p, "300,"))
248*3446Smrj 		baud = ASY300;
249*3446Smrj 	else if (MATCHES(p, "600,"))
250*3446Smrj 		baud = ASY600;
251*3446Smrj 	else if (MATCHES(p, "1200,"))
252*3446Smrj 		baud = ASY1200;
253*3446Smrj 	else if (MATCHES(p, "2400,"))
254*3446Smrj 		baud = ASY2400;
255*3446Smrj 	else if (MATCHES(p, "4800,"))
256*3446Smrj 		baud = ASY4800;
257*3446Smrj 	else if (MATCHES(p, "19200,"))
258*3446Smrj 		baud = ASY19200;
259*3446Smrj 	else if (MATCHES(p, "38400,"))
260*3446Smrj 		baud = ASY38400;
261*3446Smrj 	else if (MATCHES(p, "57600,"))
262*3446Smrj 		baud = ASY57600;
263*3446Smrj 	else if (MATCHES(p, "115200,"))
264*3446Smrj 		baud = ASY115200;
265*3446Smrj 	else {
266*3446Smrj 		baud = ASY9600;
267*3446Smrj 		SKIP(p, ',');
268*3446Smrj 	}
269*3446Smrj 	outb(port + LCR, DLAB);
270*3446Smrj 	outb(port + DAT + DLL, baud & 0xff);
271*3446Smrj 	outb(port + DAT + DLH, (baud >> 8) & 0xff);
272*3446Smrj 
273*3446Smrj 	switch (*p) {
274*3446Smrj 	case '5':
275*3446Smrj 		lcr |= BITS5;
276*3446Smrj 		++p;
277*3446Smrj 		break;
278*3446Smrj 	case '6':
279*3446Smrj 		lcr |= BITS6;
280*3446Smrj 		++p;
281*3446Smrj 		break;
282*3446Smrj 	case '7':
283*3446Smrj 		lcr |= BITS7;
284*3446Smrj 		++p;
285*3446Smrj 		break;
286*3446Smrj 	case '8':
287*3446Smrj 		++p;
288*3446Smrj 	default:
289*3446Smrj 		lcr |= BITS8;
290*3446Smrj 		break;
291*3446Smrj 	}
292*3446Smrj 
293*3446Smrj 	SKIP(p, ',');
294*3446Smrj 
295*3446Smrj 	switch (*p) {
296*3446Smrj 	case 'n':
297*3446Smrj 		lcr |= PARITY_NONE;
298*3446Smrj 		++p;
299*3446Smrj 		break;
300*3446Smrj 	case 'o':
301*3446Smrj 		lcr |= PARITY_ODD;
302*3446Smrj 		++p;
303*3446Smrj 		break;
304*3446Smrj 	case 'e':
305*3446Smrj 		++p;
306*3446Smrj 	default:
307*3446Smrj 		lcr |= PARITY_EVEN;
308*3446Smrj 		break;
309*3446Smrj 	}
310*3446Smrj 
311*3446Smrj 
312*3446Smrj 	SKIP(p, ',');
313*3446Smrj 
314*3446Smrj 	switch (*p) {
315*3446Smrj 	case '1':
316*3446Smrj 		/* STOP1 is 0 */
317*3446Smrj 		++p;
318*3446Smrj 		break;
319*3446Smrj 	default:
320*3446Smrj 		lcr |= STOP2;
321*3446Smrj 		break;
322*3446Smrj 	}
323*3446Smrj 	/* set parity bits */
324*3446Smrj 	outb(port + LCR, lcr);
325*3446Smrj 
326*3446Smrj 	(void) strcpy(propname, "ttyX-rts-dtr-off");
327*3446Smrj 	propname[3] = 'a' + console - CONS_TTYA;
328*3446Smrj 	propval = get_mode_value(propname);
329*3446Smrj 	if (propval == NULL)
330*3446Smrj 		propval = "false";
331*3446Smrj 	if (propval[0] != 'f' && propval[0] != 'F')
332*3446Smrj 		mcr = 0;
333*3446Smrj 	/* set modem control bits */
334*3446Smrj 	outb(port + MCR, mcr | OUT2);
335*3446Smrj }
336*3446Smrj 
337*3446Smrj void
338*3446Smrj bcons_init(char *bootstr)
339*3446Smrj {
340*3446Smrj 	boot_line = bootstr;
341*3446Smrj 	console = CONS_INVALID;
342*3446Smrj 
343*3446Smrj 	if (strstr(bootstr, "console=ttya") != 0)
344*3446Smrj 		console = CONS_TTYA;
345*3446Smrj 	else if (strstr(bootstr, "console=ttyb") != 0)
346*3446Smrj 		console = CONS_TTYB;
347*3446Smrj 	else if (strstr(bootstr, "console=text") != 0)
348*3446Smrj 		console = CONS_SCREEN_TEXT;
349*3446Smrj 
350*3446Smrj 	/*
351*3446Smrj 	 * If no console device specified, default to text.
352*3446Smrj 	 * Remember what was specified for second phase.
353*3446Smrj 	 */
354*3446Smrj 	if (console == CONS_INVALID)
355*3446Smrj 		console = CONS_SCREEN_TEXT;
356*3446Smrj 
357*3446Smrj 	switch (console) {
358*3446Smrj 	case CONS_TTYA:
359*3446Smrj 	case CONS_TTYB:
360*3446Smrj 		serial_init();
361*3446Smrj 		break;
362*3446Smrj 
363*3446Smrj 	case CONS_SCREEN_TEXT:
364*3446Smrj 	default:
365*3446Smrj #if defined(_BOOT)
366*3446Smrj 		clear_screen();	/* clears the grub screen */
367*3446Smrj #endif
368*3446Smrj 		kb_init();
369*3446Smrj 		break;
370*3446Smrj 	}
371*3446Smrj 	boot_line = NULL;
372*3446Smrj }
373*3446Smrj 
374*3446Smrj /*
375*3446Smrj  * 2nd part of console initialization.
376*3446Smrj  * In the kernel (ie. fakebop), this can be used only to switch to
377*3446Smrj  * using a serial port instead of screen based on the contents
378*3446Smrj  * of the bootenv.rc file.
379*3446Smrj  */
380*3446Smrj /*ARGSUSED*/
381*3446Smrj void
382*3446Smrj bcons_init2(char *inputdev, char *outputdev, char *consoledev)
383*3446Smrj {
384*3446Smrj #if !defined(_BOOT)
385*3446Smrj 	int cons = CONS_INVALID;
386*3446Smrj 
387*3446Smrj 	if (consoledev) {
388*3446Smrj 		if (strstr(consoledev, "ttya") != 0)
389*3446Smrj 			cons = CONS_TTYA;
390*3446Smrj 		else if (strstr(consoledev, "ttyb") != 0)
391*3446Smrj 			cons = CONS_TTYB;
392*3446Smrj 		else if (strstr(consoledev, "usb-serial") != 0)
393*3446Smrj 			cons = CONS_USBSER;
394*3446Smrj 	}
395*3446Smrj 
396*3446Smrj 	if (cons == CONS_INVALID && inputdev) {
397*3446Smrj 		if (strstr(inputdev, "ttya") != 0)
398*3446Smrj 			cons = CONS_TTYA;
399*3446Smrj 		else if (strstr(inputdev, "ttyb") != 0)
400*3446Smrj 			cons = CONS_TTYB;
401*3446Smrj 		else if (strstr(inputdev, "usb-serial") != 0)
402*3446Smrj 			cons = CONS_USBSER;
403*3446Smrj 	}
404*3446Smrj 
405*3446Smrj 	if (cons == CONS_INVALID && outputdev) {
406*3446Smrj 		if (strstr(outputdev, "ttya") != 0)
407*3446Smrj 			cons = CONS_TTYA;
408*3446Smrj 		else if (strstr(outputdev, "ttyb") != 0)
409*3446Smrj 			cons = CONS_TTYB;
410*3446Smrj 		else if (strstr(outputdev, "usb-serial") != 0)
411*3446Smrj 			cons = CONS_USBSER;
412*3446Smrj 	}
413*3446Smrj 
414*3446Smrj 	if (cons == CONS_INVALID)
415*3446Smrj 		return;
416*3446Smrj 	if (cons == console)
417*3446Smrj 		return;
418*3446Smrj 
419*3446Smrj 	console = cons;
420*3446Smrj 	if (cons == CONS_TTYA || cons == CONS_TTYB) {
421*3446Smrj 		serial_init();
422*3446Smrj 		return;
423*3446Smrj 	}
424*3446Smrj 
425*3446Smrj 	/*
426*3446Smrj 	 * USB serial -- we just collect data into a buffer
427*3446Smrj 	 */
428*3446Smrj 	if (cons == CONS_USBSER) {
429*3446Smrj 		extern void *usbser_init(size_t);
430*3446Smrj 		usbser_buf = usbser_cur = usbser_init(MMU_PAGESIZE);
431*3446Smrj 	}
432*3446Smrj #endif	/* _BOOT */
433*3446Smrj }
434*3446Smrj 
435*3446Smrj #if !defined(_BOOT)
436*3446Smrj static void
437*3446Smrj usbser_putchar(int c)
438*3446Smrj {
439*3446Smrj 	if (usbser_cur - usbser_buf < MMU_PAGESIZE)
440*3446Smrj 		*usbser_cur++ = c;
441*3446Smrj }
442*3446Smrj #endif	/* _BOOT */
443*3446Smrj 
444*3446Smrj static void
445*3446Smrj serial_putchar(int c)
446*3446Smrj {
447*3446Smrj 	int checks = 10000;
448*3446Smrj 
449*3446Smrj 	while (((inb(port + LSR) & XHRE) == 0) && checks--)
450*3446Smrj 		;
451*3446Smrj 	outb(port + DAT, (char)c);
452*3446Smrj }
453*3446Smrj 
454*3446Smrj static int
455*3446Smrj serial_getchar(void)
456*3446Smrj {
457*3446Smrj 	uchar_t lsr;
458*3446Smrj 
459*3446Smrj 	while (serial_ischar() == 0)
460*3446Smrj 		;
461*3446Smrj 
462*3446Smrj 	lsr = inb(port + LSR);
463*3446Smrj 	if (lsr & (SERIAL_BREAK | SERIAL_FRAME |
464*3446Smrj 	    SERIAL_PARITY | SERIAL_OVERRUN)) {
465*3446Smrj 		if (lsr & SERIAL_OVERRUN) {
466*3446Smrj 			return (inb(port + DAT));
467*3446Smrj 		} else {
468*3446Smrj 			/* Toss the garbage */
469*3446Smrj 			(void) inb(port + DAT);
470*3446Smrj 			return (0);
471*3446Smrj 		}
472*3446Smrj 	}
473*3446Smrj 	return (inb(port + DAT));
474*3446Smrj }
475*3446Smrj 
476*3446Smrj static int
477*3446Smrj serial_ischar(void)
478*3446Smrj {
479*3446Smrj 	return (inb(port + LSR) & RCA);
480*3446Smrj }
481*3446Smrj 
482*3446Smrj static void
483*3446Smrj _doputchar(int c)
484*3446Smrj {
485*3446Smrj 	switch (console) {
486*3446Smrj 	case CONS_TTYA:
487*3446Smrj 	case CONS_TTYB:
488*3446Smrj 		serial_putchar(c);
489*3446Smrj 		return;
490*3446Smrj 	case CONS_SCREEN_TEXT:
491*3446Smrj 		screen_putchar(c);
492*3446Smrj 		return;
493*3446Smrj #if !defined(_BOOT)
494*3446Smrj 	case CONS_USBSER:
495*3446Smrj 		usbser_putchar(c);
496*3446Smrj 		return;
497*3446Smrj #endif /* _BOOT */
498*3446Smrj 	}
499*3446Smrj }
500*3446Smrj 
501*3446Smrj void
502*3446Smrj bcons_putchar(int c)
503*3446Smrj {
504*3446Smrj 	static int bhcharpos = 0;
505*3446Smrj 
506*3446Smrj 	if (c == '\t') {
507*3446Smrj 		do {
508*3446Smrj 			_doputchar(' ');
509*3446Smrj 		} while (++bhcharpos % 8);
510*3446Smrj 		return;
511*3446Smrj 	} else  if (c == '\n' || c == '\r') {
512*3446Smrj 		bhcharpos = 0;
513*3446Smrj 		_doputchar('\r');
514*3446Smrj 		_doputchar(c);
515*3446Smrj 		return;
516*3446Smrj 	} else if (c == '\b') {
517*3446Smrj 		if (bhcharpos)
518*3446Smrj 			bhcharpos--;
519*3446Smrj 		_doputchar(c);
520*3446Smrj 		return;
521*3446Smrj 	}
522*3446Smrj 
523*3446Smrj 	bhcharpos++;
524*3446Smrj 	_doputchar(c);
525*3446Smrj }
526*3446Smrj 
527*3446Smrj /*
528*3446Smrj  * kernel character input functions
529*3446Smrj  */
530*3446Smrj int
531*3446Smrj bcons_getchar(void)
532*3446Smrj {
533*3446Smrj 	switch (console) {
534*3446Smrj 	case CONS_TTYA:
535*3446Smrj 	case CONS_TTYB:
536*3446Smrj 		return (serial_getchar());
537*3446Smrj 	default:
538*3446Smrj 		return (kb_getchar());
539*3446Smrj 	}
540*3446Smrj }
541*3446Smrj 
542*3446Smrj #if !defined(_BOOT)
543*3446Smrj 
544*3446Smrj int
545*3446Smrj bcons_ischar(void)
546*3446Smrj {
547*3446Smrj 	switch (console) {
548*3446Smrj 	case CONS_TTYA:
549*3446Smrj 	case CONS_TTYB:
550*3446Smrj 		return (serial_ischar());
551*3446Smrj 	default:
552*3446Smrj 		return (kb_ischar());
553*3446Smrj 	}
554*3446Smrj }
555*3446Smrj 
556*3446Smrj #endif /* _BOOT */
557